[Spice-commits] 971 commits - .gitignore .gitmodules .mailmap Changelog HACKING LICENSE MAINTAINERS Makefile Makefile.objs Makefile.target QMP/qmp QMP/qmp-events.txt README VERSION acl.c arch_init.c arch_init.h arm-dis.c audio/audio.c audio/fmodaudio.c balloon.c balloon.h block-migration.c block.c block.h block/blkverify.c block/cloop.c block/cow.c block/curl.c block/nbd.c block/qcow.c block/qcow2-cluster.c block/qcow2-refcount.c block/qcow2-snapshot.c block/qcow2.c block/qcow2.h block/qed-table.c block/qed.c block/qed.h block/raw-posix.c block/raw-win32.c block/raw.c block/rbd.c block/sheepdog.c block/vdi.c block/vmdk.c block/vpc.c block/vvfat.c block_int.h blockdev.c blockdev.h bsd-user/bsdload.c bsd-user/elfload.c bsd-user/x86_64 check-qdict.c check-qfloat.c check-qint.c check-qjson.c check-qlist.c check-qstring.c cmd.c configure console.c console.h coroutine-gthread.c coroutine-ucontext.c cpu-all.h cpu-common.h cpu-defs.h cpus.c cpus.h cris-dis.c cutils.c darwin-user/machload.c darwin-user/main.c darwin-user/signal.c darwin-user/syscall.c default-configs/xtensa-softmmu.mak default-configs/xtensaeb-softmmu.mak dis-asm.h disas.c dma-helpers.c dma.h docs/libcacard.txt docs/memory.txt docs/migration.txt docs/qapi-code-gen.txt docs/specs docs/tracing.txt docs/writing-qmp-commands.txt dyngen-exec.h event_notifier.c event_notifier.h exec-all.h exec-memory.h exec-obsolete.h exec.c fsdev/file-op-9p.h fsdev/qemu-fsdev.c fsdev/qemu-fsdev.h fsdev/virtfs-proxy-helper.c fsdev/virtfs-proxy-helper.texi fsdev/virtio-9p-marshal.c fsdev/virtio-9p-marshal.h gdbstub.c hmp-commands.hx hmp.c hmp.h hppa-dis.c hw/9pfs hw/a9mpcore.c hw/ac97.c hw/acpi.c hw/adlib.c hw/alpha_dp264.c hw/alpha_sys.h hw/alpha_typhoon.c hw/an5206.c hw/apb_pci.c hw/apic.c hw/arm11mpcore.c hw/arm_gic.c hw/arm_l2x0.c hw/arm_mptimer.c hw/arm_sysctl.c hw/arm_timer.c hw/armv7m.c hw/audiodev.h hw/axis_dev88.c hw/bitbang_i2c.c hw/bonito.c hw/bt-hci-csr.c hw/ccid-card-emulated.c hw/ccid-card-passthru.c hw/ cirrus_vga.c hw/container.c hw/cs4231.c hw/cs4231a.c hw/dec_pci.c hw/device-hotplug.c hw/dma.c hw/dp8393x.c hw/ds1225y.c hw/dummy_m68k.c hw/e1000.c hw/e1000_hw.h hw/eccmemctl.c hw/eepro100.c hw/elf_ops.h hw/empty_slot.c hw/es1370.c hw/escc.c hw/esp.c hw/etraxfs_dma.c hw/etraxfs_dma.h hw/etraxfs_eth.c hw/etraxfs_pic.c hw/etraxfs_ser.c hw/etraxfs_timer.c hw/event_notifier.c hw/event_notifier.h hw/fdc.c hw/fdc.h hw/fmopl.c hw/fmopl.h hw/framebuffer.c hw/framebuffer.h hw/fw_cfg.c hw/g364fb.c hw/grackle_pci.c hw/grlib_apbuart.c hw/grlib_gptimer.c hw/grlib_irqmp.c hw/gus.c hw/gusemu.h hw/gusemu_hal.c hw/hpet.c hw/hw.h hw/i8254.c hw/i8259.c hw/ide hw/ide.h hw/integratorcp.c hw/intel-hda.c hw/ioapic.c hw/isa-bus.c hw/isa.h hw/ivshmem.c hw/jazz_led.c hw/lan9118.c hw/lance.c hw/leon3.c hw/lm32_boards.c hw/lm32_sys.c hw/lm32_timer.c hw/lm32_uart.c hw/lm4549.c hw/lm4549.h hw/loader.c hw/loader.h hw/lsi53c895a.c hw/m48t59.c hw/mainstone.c hw/marvell_88w8618_audio.c hw/mc146818rtc.c hw/mc 146818rtc.h hw/mcf.h hw/mcf5206.c hw/mcf5208.c hw/mcf_fec.c hw/mcf_intc.c hw/mcf_uart.c hw/milkymist-ac97.c hw/milkymist-hpdmc.c hw/milkymist-memcard.c hw/milkymist-minimac2.c hw/milkymist-pfpu.c hw/milkymist-softusb.c hw/milkymist-sysctl.c hw/milkymist-tmu2.c hw/milkymist-uart.c hw/milkymist-vgafb.c hw/milkymist.c hw/mips.h hw/mips_fulong2e.c hw/mips_jazz.c hw/mips_malta.c hw/mips_mipssim.c hw/mips_r4k.c hw/mipsnet.c hw/mpc8544_guts.c hw/mpcore.c hw/msix.c hw/mst_fpga.c hw/musicpal.c hw/nand.c hw/nseries.c hw/nvram.h hw/omap.h hw/omap1.c hw/omap2.c hw/omap_dma.c hw/omap_dss.c hw/omap_gpio.c hw/omap_gpmc.c hw/omap_gptimer.c hw/omap_i2c.c hw/omap_intc.c hw/omap_l4.c hw/omap_lcdc.c hw/omap_mmc.c hw/omap_sdrc.c hw/omap_spi.c hw/omap_sx1.c hw/omap_synctimer.c hw/omap_tap.c hw/omap_uart.c hw/onenand.c hw/opencores_eth.c hw/palm.c hw/parallel.c hw/pc.c hw/pc.h hw/pc_piix.c hw/pci-hotplug.c hw/pci-stub.c hw/pci.c hw/pci.h hw/pci_host.h hw/pcie_aer.c hw/pcnet-pci.c hw/pcnet.c hw/pcn et.h hw/pcspk.c hw/petalogix_ml605_mmu.c hw/petalogix_s3adsp1800_mmu.c hw/pflash_cfi01.c hw/pflash_cfi02.c hw/piix4.c hw/piix_pci.c hw/pl011.c hw/pl022.c hw/pl031.c hw/pl041.c hw/pl041.h hw/pl041.hx hw/pl050.c hw/pl061.c hw/pl080.c hw/pl110.c hw/pl181.c hw/pl190.c hw/ppc.c hw/ppc405_boards.c hw/ppc405_uc.c hw/ppc4xx_devs.c hw/ppc4xx_pci.c hw/ppc_newworld.c hw/ppc_oldworld.c hw/ppc_prep.c hw/ppce500_mpc8544ds.c hw/ppce500_pci.c hw/ppce500_spin.c hw/prep_pci.c hw/ps2.c hw/pxa.h hw/pxa2xx.c hw/pxa2xx_dma.c hw/pxa2xx_gpio.c hw/pxa2xx_keypad.c hw/pxa2xx_lcd.c hw/pxa2xx_mmci.c hw/pxa2xx_pcmcia.c hw/pxa2xx_pic.c hw/pxa2xx_timer.c hw/qdev-addr.c hw/qdev-properties.c hw/qdev.c hw/qdev.h hw/qxl-render.c hw/qxl.c hw/qxl.h hw/r2d.c hw/rc4030.c hw/realview.c hw/realview_gic.c hw/rtl8139.c hw/s390-virtio-bus.c hw/s390-virtio-bus.h hw/s390-virtio.c hw/sb16.c hw/sbi.c hw/scsi-bus.c hw/scsi-defs.h hw/scsi-disk.c hw/scsi-generic.c hw/scsi.h hw/sd.c hw/sh.h hw/sh7750.c hw/sh7750_regs.h hw/sh_i ntc.c hw/sh_intc.h hw/sh_pci.c hw/sh_serial.c hw/sh_timer.c hw/shix.c hw/slavio_intctl.c hw/slavio_misc.c hw/slavio_timer.c hw/sm501.c hw/smc91c111.c hw/spapr.c hw/spapr.h hw/spapr_llan.c hw/spapr_pci.c hw/spapr_pci.h hw/spapr_vio.c hw/spapr_vio.h hw/spapr_vty.c hw/sparc32_dma.c hw/spitz.c hw/ssd0303.c hw/stellaris.c hw/stellaris_enet.c hw/strongarm.c hw/sun4c_intctl.c hw/sun4m.c hw/sun4m_iommu.c hw/sun4u.c hw/syborg.c hw/syborg.h hw/syborg_fb.c hw/syborg_interrupt.c hw/syborg_keyboard.c hw/syborg_pointer.c hw/syborg_rtc.c hw/syborg_serial.c hw/syborg_timer.c hw/syborg_virtio.c hw/sysbus.c hw/sysbus.h hw/tc58128.c hw/tc6393xb.c hw/tc6393xb_template.h hw/tcx.c hw/tosa.c hw/tusb6010.c hw/unin_pci.c hw/usb-bt.c hw/usb-bus.c hw/usb-ehci.c hw/usb-hub.c hw/usb-msd.c hw/usb-net.c hw/usb-ohci.c hw/usb-uhci.c hw/versatile_pci.c hw/versatilepb.c hw/vexpress.c hw/vga-pci.c hw/vga.c hw/vhost.c hw/vhost.h hw/virtex_ml507.c hw/virtio-balloon.c hw/virtio-blk.c hw/virtio-console.c hw/virtio -pci.c hw/virtio-pci.h hw/virtio-serial-bus.c hw/virtio.c hw/virtio.h hw/vmport.c hw/vmware_vga.c hw/vmware_vga.h hw/vt82c686.c hw/vt82c686.h hw/wdt_ib700.c hw/wm8750.c hw/xen.h hw/xen_disk.c hw/xen_platform.c hw/xilinx_axidma.c hw/xilinx_axienet.c hw/xilinx_ethlite.c hw/xilinx_intc.c hw/xilinx_timer.c hw/xilinx_uartlite.c hw/xtensa_bootparam.h hw/xtensa_lx60.c hw/xtensa_sim.c hw/zaurus.c ia64-dis.c int128.h kvm-all.c kvm.h libcacard/card_7816.c libcacard/card_7816.h libcacard/vcard_emul_nss.c libcacard/vscard_common.h linux-aio.c linux-user/arm linux-user/cpu-uname.c linux-user/elfload.c linux-user/flatload.c linux-user/linuxload.c linux-user/main.c linux-user/signal.c linux-user/syscall.c linux-user/syscall_defs.h linux-user/x86_64 m68k-dis.c main-loop.c main-loop.h memory.c memory.h migration-exec.c migration-fd.c migration-tcp.c migration-unix.c migration.c migration.h monitor.c monitor.h nbd.c nbd.h net.c net.h net/dump.c net/slirp.c net/socket.c net/tap-linux.c net/tap -solaris.c net/tap.c os-posix.c os-win32.c osdep.c oslib-posix.c oslib-win32.c pc-bios/README pc-bios/keymaps pc-bios/ohw.diff pc-bios/optionrom pc-bios/sgabios.bin pc-bios/slof.bin posix-aio-compat.c ppc.ld ppc64.ld qapi-schema-guest.json qapi-schema-test.json qapi-schema.json qapi/qmp-core.h qapi/qmp-dispatch.c qapi/qmp-input-visitor.c qapi/qmp-output-visitor.c qapi/qmp-registry.c qemu-barrier.h qemu-char.c qemu-char.h qemu-common.h qemu-config.c qemu-coroutine-io.c qemu-coroutine-lock.c qemu-coroutine.h qemu-doc.texi qemu-error.c qemu-error.h qemu-ga.c qemu-img-cmds.hx qemu-img.c qemu-img.texi qemu-io.c qemu-nbd.c qemu-option.c qemu-options-wrapper.h qemu-options.h qemu-options.hx qemu-os-posix.h qemu-sockets.c qemu-tech.texi qemu-thread-posix.c qemu-thread-win32.c qemu-thread-win32.h qemu-thread.h qemu-timer.c qemu-tls.h qemu-tool.c qemu-xattr.h qemu_socket.h qerror.c qerror.h qga/guest-agent-commands.c qmp-commands.hx qmp.c readline.c roms/SLOF roms/sgabios savevm.c scr ipts/analyse-9p-simpletrace.py scripts/checkpatch.pl scripts/hxtool scripts/qapi-commands.py scripts/qapi-types.py scripts/qapi-visit.py scripts/qapi.py softmmu_template.h spice-qemu-char.c sysemu.h target-alpha/STATUS target-arm/cpu.h target-arm/helper.c target-arm/machine.c target-arm/translate.c target-cris/cpu.h target-cris/helper.c target-cris/translate_v10.c target-i386/TODO target-i386/cpu.h target-i386/cpuid.c target-i386/helper.c target-i386/helper.h target-i386/kvm.c target-i386/op_helper.c target-i386/ops_sse.h target-i386/translate.c target-microblaze/cpu.h target-microblaze/helper.h target-microblaze/op_helper.c target-microblaze/translate.c target-mips/cpu.h target-mips/helper.c target-mips/machine.c target-ppc/cpu.h target-ppc/helper.c target-ppc/kvm.c target-ppc/kvm_ppc.h target-ppc/mfrom_table_gen.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/helpers.h target-s390x/kvm.c targ et-s390x/op_helper.c target-s390x/translate.c target-sh4/helper.c target-sh4/translate.c target-sparc/TODO target-sparc/helper.c target-sparc/helper.h target-sparc/int32_helper.c target-sparc/mmu_helper.c target-sparc/translate.c target-xtensa/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/sparc tcg/tcg-op.h tcg/tcg.c tcg/tcg.h tcg/tci tci-dis.c tci.c test-qmp-input-visitor.c test-qmp-output-visitor.c test-visitor.c tests/Makefile tests/alpha tests/cris tests/hello-arm.c tests/hello-i386.c tests/hello-mips.c tests/linux-test.c tests/lm32 tests/pi_10.com tests/qruncom.c tests/runcom.c tests/sha1.c tests/tcg tests/test-arm-iwmmxt.s tests/test-i386-code16.S tests/test-i386-muldiv.h tests/test-i386-shift.h tests/test-i386-ssse3.c tests/test-i386-vm86.S tests/test-i386.c tests/test-i386.h tests/test-mmap.c tests/test_path.c tests/testthread.c tests/xtensa trace-events trace/simple.c trace/stderr.c ui/cocoa.m ui/keymaps.c ui/vnc-auth-sasl.c ui/vnc-enc-hextile.c ui/vnc-enc-zywrle-template.c ui/vnc-enc-zywrle.h ui/vnc-jobs-async.c ui/vnc-tls.c ui/vnc.c usb-linux.c usb-redir.c vl.c xen-all.c xen-mapcache.c xen-stub.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Tue Jan 17 07:35:46 PST 2012


 .gitignore                                  |    4 
 .gitmodules                                 |    3 
 .mailmap                                    |   16 
 Changelog                                   |    4 
 HACKING                                     |   10 
 LICENSE                                     |    4 
 MAINTAINERS                                 |   32 
 Makefile                                    |  112 -
 Makefile.objs                               |   20 
 Makefile.target                             |   25 
 QMP/qmp                                     |  126 +
 QMP/qmp-events.txt                          |    2 
 README                                      |    4 
 VERSION                                     |    2 
 acl.c                                       |    4 
 arch_init.c                                 |   87 
 arch_init.h                                 |    2 
 arm-dis.c                                   |    6 
 audio/audio.c                               |    2 
 audio/fmodaudio.c                           |    6 
 balloon.c                                   |   28 
 balloon.h                                   |    3 
 block-migration.c                           |   17 
 block.c                                     |  711 ++++++-
 block.h                                     |   30 
 block/blkverify.c                           |   24 
 block/cloop.c                               |  119 -
 block/cow.c                                 |  112 -
 block/curl.c                                |    4 
 block/nbd.c                                 |  323 ++-
 block/qcow.c                                |   40 
 block/qcow2-cluster.c                       |  115 -
 block/qcow2-refcount.c                      |    7 
 block/qcow2-snapshot.c                      |  362 ++-
 block/qcow2.c                               |   77 
 block/qcow2.h                               |    4 
 block/qed-table.c                           |   24 
 block/qed.c                                 |   85 
 block/qed.h                                 |    2 
 block/raw-posix.c                           |    4 
 block/raw-win32.c                           |   15 
 block/raw.c                                 |    8 
 block/rbd.c                                 |   16 
 block/sheepdog.c                            |  256 --
 block/vdi.c                                 |   91 
 block/vmdk.c                                |   28 
 block/vpc.c                                 |   32 
 block/vvfat.c                               |  125 -
 block_int.h                                 |   59 
 blockdev.c                                  |  212 +-
 blockdev.h                                  |    6 
 bsd-user/bsdload.c                          |    2 
 bsd-user/elfload.c                          |   16 
 bsd-user/x86_64/syscall.h                   |    2 
 check-qdict.c                               |  246 +-
 check-qfloat.c                              |   47 
 check-qint.c                                |   68 
 check-qjson.c                               |  333 +--
 check-qlist.c                               |   74 
 check-qstring.c                             |   77 
 cmd.c                                       |  168 -
 configure                                   |  371 ++-
 console.c                                   |   30 
 console.h                                   |    2 
 coroutine-gthread.c                         |    5 
 coroutine-ucontext.c                        |   30 
 cpu-all.h                                   |   71 
 cpu-common.h                                |   77 
 cpu-defs.h                                  |    9 
 cpus.c                                      |  132 +
 cpus.h                                      |    1 
 cris-dis.c                                  |   34 
 cutils.c                                    |  207 +-
 darwin-user/machload.c                      |    6 
 darwin-user/main.c                          |    4 
 darwin-user/signal.c                        |    3 
 darwin-user/syscall.c                       |    2 
 default-configs/xtensa-softmmu.mak          |    1 
 default-configs/xtensaeb-softmmu.mak        |    1 
 dev/null                                    |binary
 dis-asm.h                                   |    1 
 disas.c                                     |    4 
 dma-helpers.c                               |   19 
 dma.h                                       |   18 
 docs/libcacard.txt                          |   20 
 docs/memory.txt                             |    6 
 docs/migration.txt                          |   12 
 docs/qapi-code-gen.txt                      |    6 
 docs/specs/qcow2.txt                        |    8 
 docs/tracing.txt                            |    9 
 docs/writing-qmp-commands.txt               |  642 ++++++
 dyngen-exec.h                               |   14 
 event_notifier.c                            |   61 
 event_notifier.h                            |   16 
 exec-all.h                                  |   55 
 exec-memory.h                               |    2 
 exec-obsolete.h                             |   98 
 exec.c                                      | 1076 +++-------
 fsdev/file-op-9p.h                          |   23 
 fsdev/qemu-fsdev.c                          |   47 
 fsdev/qemu-fsdev.h                          |   11 
 fsdev/virtfs-proxy-helper.c                 | 1120 +++++++++++
 fsdev/virtfs-proxy-helper.texi              |   63 
 fsdev/virtio-9p-marshal.c                   |  323 +++
 fsdev/virtio-9p-marshal.h                   |   90 
 gdbstub.c                                   |   18 
 hmp-commands.hx                             |   58 
 hmp.c                                       |  158 +
 hmp.h                                       |   12 
 hppa-dis.c                                  |    2 
 hw/9pfs/codir.c                             |    6 
 hw/9pfs/cofile.c                            |    4 
 hw/9pfs/virtio-9p-coth.h                    |    2 
 hw/9pfs/virtio-9p-device.c                  |   38 
 hw/9pfs/virtio-9p-handle.c                  |   92 
 hw/9pfs/virtio-9p-local.c                   |   86 
 hw/9pfs/virtio-9p-posix-acl.c               |    2 
 hw/9pfs/virtio-9p-proxy.c                   | 1210 ++++++++++++
 hw/9pfs/virtio-9p-proxy.h                   |   95 
 hw/9pfs/virtio-9p-synth.c                   |    5 
 hw/9pfs/virtio-9p-xattr.h                   |    2 
 hw/9pfs/virtio-9p.c                         | 1086 ++++-------
 hw/9pfs/virtio-9p.h                         |   88 
 hw/a9mpcore.c                               |  219 ++
 hw/ac97.c                                   |   23 
 hw/acpi.c                                   |    2 
 hw/adlib.c                                  |    2 
 hw/alpha_dp264.c                            |   14 
 hw/alpha_sys.h                              |    3 
 hw/alpha_typhoon.c                          |   12 
 hw/an5206.c                                 |    8 
 hw/apb_pci.c                                |    6 
 hw/apic.c                                   |    2 
 hw/arm11mpcore.c                            |  132 +
 hw/arm_gic.c                                |  143 +
 hw/arm_l2x0.c                               |  181 +
 hw/arm_mptimer.c                            |  332 +++
 hw/arm_sysctl.c                             |   29 
 hw/arm_timer.c                              |   81 
 hw/armv7m.c                                 |   11 
 hw/audiodev.h                               |    8 
 hw/axis_dev88.c                             |   69 
 hw/bitbang_i2c.c                            |    4 
 hw/bonito.c                                 |  201 --
 hw/bt-hci-csr.c                             |    2 
 hw/ccid-card-emulated.c                     |   25 
 hw/ccid-card-passthru.c                     |    1 
 hw/cirrus_vga.c                             |   60 
 hw/container.c                              |   20 
 hw/cs4231.c                                 |   27 
 hw/cs4231a.c                                |    4 
 hw/dec_pci.c                                |    4 
 hw/device-hotplug.c                         |   47 
 hw/dma.c                                    |   10 
 hw/dp8393x.c                                |   32 
 hw/ds1225y.c                                |   64 
 hw/dummy_m68k.c                             |    3 
 hw/e1000.c                                  |   28 
 hw/e1000_hw.h                               |    2 
 hw/eccmemctl.c                              |   63 
 hw/eepro100.c                               |  132 -
 hw/elf_ops.h                                |   12 
 hw/empty_slot.c                             |   32 
 hw/es1370.c                                 |   19 
 hw/escc.c                                   |    2 
 hw/esp.c                                    |   37 
 hw/etraxfs_dma.c                            |   30 
 hw/etraxfs_dma.h                            |   13 
 hw/etraxfs_eth.c                            |    7 
 hw/etraxfs_pic.c                            |    4 
 hw/etraxfs_ser.c                            |    2 
 hw/etraxfs_timer.c                          |    2 
 hw/event_notifier.c                         |   62 
 hw/event_notifier.h                         |   16 
 hw/fdc.c                                    |   60 
 hw/fdc.h                                    |    4 
 hw/fmopl.c                                  |   40 
 hw/fmopl.h                                  |    4 
 hw/framebuffer.c                            |   32 
 hw/framebuffer.h                            |    3 
 hw/fw_cfg.c                                 |  212 +-
 hw/g364fb.c                                 |    7 
 hw/grackle_pci.c                            |    4 
 hw/grlib_apbuart.c                          |   30 
 hw/grlib_gptimer.c                          |   34 
 hw/grlib_irqmp.c                            |   34 
 hw/gus.c                                    |    4 
 hw/gusemu.h                                 |    4 
 hw/gusemu_hal.c                             |    4 
 hw/hpet.c                                   |   66 
 hw/hw.h                                     |   13 
 hw/i8254.c                                  |    2 
 hw/i8259.c                                  |   10 
 hw/ide.h                                    |    4 
 hw/ide/atapi.c                              |   39 
 hw/ide/core.c                               |   34 
 hw/ide/isa.c                                |    4 
 hw/ide/macio.c                              |   16 
 hw/ide/mmio.c                               |   57 
 hw/ide/pci.c                                |   21 
 hw/ide/piix.c                               |    2 
 hw/ide/via.c                                |    4 
 hw/integratorcp.c                           |  121 -
 hw/intel-hda.c                              |   16 
 hw/ioapic.c                                 |   34 
 hw/isa-bus.c                                |   33 
 hw/isa.h                                    |   17 
 hw/ivshmem.c                                |   21 
 hw/jazz_led.c                               |   27 
 hw/lan9118.c                                |    7 
 hw/lance.c                                  |    3 
 hw/leon3.c                                  |    6 
 hw/lm32_boards.c                            |    6 
 hw/lm32_sys.c                               |   28 
 hw/lm32_timer.c                             |   30 
 hw/lm32_uart.c                              |   31 
 hw/lm4549.c                                 |    2 
 hw/lm4549.h                                 |    2 
 hw/loader.c                                 |   18 
 hw/loader.h                                 |    4 
 hw/lsi53c895a.c                             |   33 
 hw/m48t59.c                                 |   28 
 hw/mainstone.c                              |    3 
 hw/marvell_88w8618_audio.c                  |   28 
 hw/mc146818rtc.c                            |   31 
 hw/mc146818rtc.h                            |    2 
 hw/mcf.h                                    |   23 
 hw/mcf5206.c                                |   62 
 hw/mcf5208.c                                |   17 
 hw/mcf_fec.c                                |   38 
 hw/mcf_intc.c                               |   33 
 hw/mcf_uart.c                               |   34 
 hw/milkymist-ac97.c                         |    2 
 hw/milkymist-hpdmc.c                        |    2 
 hw/milkymist-memcard.c                      |    2 
 hw/milkymist-minimac2.c                     |    5 
 hw/milkymist-pfpu.c                         |    2 
 hw/milkymist-softusb.c                      |    8 
 hw/milkymist-sysctl.c                       |    2 
 hw/milkymist-tmu2.c                         |    2 
 hw/milkymist-uart.c                         |    2 
 hw/milkymist-vgafb.c                        |    4 
 hw/milkymist.c                              |    3 
 hw/mips.h                                   |    8 
 hw/mips_fulong2e.c                          |   26 
 hw/mips_jazz.c                              |   32 
 hw/mips_malta.c                             |   72 
 hw/mips_mipssim.c                           |    8 
 hw/mips_r4k.c                               |   27 
 hw/mipsnet.c                                |    2 
 hw/mpc8544_guts.c                           |   35 
 hw/mpcore.c                                 |  283 --
 hw/msix.c                                   |   48 
 hw/mst_fpga.c                               |   29 
 hw/musicpal.c                               |   24 
 hw/nand.c                                   |   22 
 hw/nseries.c                                |    4 
 hw/nvram.h                                  |    3 
 hw/omap.h                                   |   73 
 hw/omap1.c                                  |  165 -
 hw/omap2.c                                  |  215 +-
 hw/omap_dma.c                               |   71 
 hw/omap_dss.c                               |  178 -
 hw/omap_gpio.c                              |   97 
 hw/omap_gpmc.c                              |   32 
 hw/omap_gptimer.c                           |   32 
 hw/omap_i2c.c                               |   45 
 hw/omap_intc.c                              |   10 
 hw/omap_l4.c                                |  182 -
 hw/omap_lcdc.c                              |   37 
 hw/omap_mmc.c                               |   44 
 hw/omap_sdrc.c                              |   39 
 hw/omap_spi.c                               |   37 
 hw/omap_sx1.c                               |  101 -
 hw/omap_synctimer.c                         |   30 
 hw/omap_tap.c                               |   32 
 hw/omap_uart.c                              |   41 
 hw/onenand.c                                |   10 
 hw/opencores_eth.c                          |   33 
 hw/palm.c                                   |    3 
 hw/parallel.c                               |   27 
 hw/pc.c                                     |   81 
 hw/pc.h                                     |   52 
 hw/pc_piix.c                                |  118 +
 hw/pci-hotplug.c                            |   27 
 hw/pci-stub.c                               |    2 
 hw/pci.c                                    |    4 
 hw/pci.h                                    |   69 
 hw/pci_host.h                               |    1 
 hw/pcie_aer.c                               |    4 
 hw/pcnet-pci.c                              |   59 
 hw/pcnet.c                                  |   25 
 hw/pcnet.h                                  |   20 
 hw/pcspk.c                                  |    2 
 hw/petalogix_ml605_mmu.c                    |    6 
 hw/petalogix_s3adsp1800_mmu.c               |    7 
 hw/pflash_cfi01.c                           |    4 
 hw/pflash_cfi02.c                           |    3 
 hw/piix4.c                                  |    3 
 hw/piix_pci.c                               |   33 
 hw/pl011.c                                  |   27 
 hw/pl022.c                                  |   29 
 hw/pl031.c                                  |   30 
 hw/pl041.c                                  |    4 
 hw/pl041.h                                  |    2 
 hw/pl041.hx                                 |    2 
 hw/pl050.c                                  |   27 
 hw/pl061.c                                  |   29 
 hw/pl080.c                                  |   27 
 hw/pl110.c                                  |   42 
 hw/pl181.c                                  |   79 
 hw/pl190.c                                  |   28 
 hw/ppc.c                                    |    8 
 hw/ppc405_boards.c                          |   18 
 hw/ppc405_uc.c                              |    3 
 hw/ppc4xx_devs.c                            |    3 
 hw/ppc4xx_pci.c                             |   68 
 hw/ppc_newworld.c                           |    6 
 hw/ppc_oldworld.c                           |    6 
 hw/ppc_prep.c                               |   26 
 hw/ppce500_mpc8544ds.c                      |    3 
 hw/ppce500_pci.c                            |  137 -
 hw/ppce500_spin.c                           |    3 
 hw/prep_pci.c                               |   23 
 hw/ps2.c                                    |   46 
 hw/pxa.h                                    |   15 
 hw/pxa2xx.c                                 |   41 
 hw/pxa2xx_dma.c                             |   54 
 hw/pxa2xx_gpio.c                            |   29 
 hw/pxa2xx_keypad.c                          |   34 
 hw/pxa2xx_lcd.c                             |   42 
 hw/pxa2xx_mmci.c                            |   31 
 hw/pxa2xx_pcmcia.c                          |   95 
 hw/pxa2xx_pic.c                             |   31 
 hw/pxa2xx_timer.c                           |   27 
 hw/qdev-addr.c                              |   41 
 hw/qdev-properties.c                        |  407 +++-
 hw/qdev.c                                   |  581 +++++
 hw/qdev.h                                   |  295 ++
 hw/qxl-render.c                             |   38 
 hw/qxl.c                                    |   60 
 hw/qxl.h                                    |    3 
 hw/r2d.c                                    |   21 
 hw/rc4030.c                                 |   51 
 hw/realview.c                               |   11 
 hw/realview_gic.c                           |   27 
 hw/rtl8139.c                                |  120 -
 hw/s390-virtio-bus.c                        |   29 
 hw/s390-virtio-bus.h                        |    5 
 hw/s390-virtio.c                            |   50 
 hw/sb16.c                                   |    4 
 hw/sbi.c                                    |   33 
 hw/scsi-bus.c                               |  137 +
 hw/scsi-defs.h                              |   10 
 hw/scsi-disk.c                              |   74 
 hw/scsi-generic.c                           |   17 
 hw/scsi.h                                   |    4 
 hw/sd.c                                     |  132 -
 hw/sh.h                                     |    9 
 hw/sh7750.c                                 |  155 -
 hw/sh7750_regs.h                            |    2 
 hw/sh_intc.c                                |   85 
 hw/sh_intc.h                                |    7 
 hw/sh_pci.c                                 |   31 
 hw/sh_serial.c                              |   55 
 hw/sh_timer.c                               |   43 
 hw/shix.c                                   |   19 
 hw/slavio_intctl.c                          |   67 
 hw/slavio_misc.c                            |  250 +-
 hw/slavio_timer.c                           |   41 
 hw/sm501.c                                  |    5 
 hw/smc91c111.c                              |    4 
 hw/spapr.c                                  |  240 ++
 hw/spapr.h                                  |    5 
 hw/spapr_llan.c                             |   17 
 hw/spapr_pci.c                              |  508 +++++
 hw/spapr_pci.h                              |   61 
 hw/spapr_vio.c                              |  175 +
 hw/spapr_vio.h                              |    5 
 hw/spapr_vty.c                              |   77 
 hw/sparc32_dma.c                            |   31 
 hw/spitz.c                                  |    5 
 hw/ssd0303.c                                |    2 
 hw/stellaris.c                              |  116 -
 hw/stellaris_enet.c                         |    2 
 hw/strongarm.c                              |   15 
 hw/sun4c_intctl.c                           |   36 
 hw/sun4m.c                                  |   20 
 hw/sun4m_iommu.c                            |   33 
 hw/sun4u.c                                  |   34 
 hw/syborg.c                                 |  113 -
 hw/syborg.h                                 |   18 
 hw/syborg_fb.c                              |  560 -----
 hw/syborg_interrupt.c                       |  238 --
 hw/syborg_keyboard.c                        |  221 --
 hw/syborg_pointer.c                         |  226 --
 hw/syborg_rtc.c                             |  140 -
 hw/syborg_serial.c                          |  335 ---
 hw/syborg_timer.c                           |  231 --
 hw/syborg_virtio.c                          |  315 ---
 hw/sysbus.c                                 |   62 
 hw/sysbus.h                                 |   12 
 hw/tc58128.c                                |    6 
 hw/tc6393xb.c                               |    3 
 hw/tc6393xb_template.h                      |    2 
 hw/tcx.c                                    |   17 
 hw/tosa.c                                   |    7 
 hw/tusb6010.c                               |    4 
 hw/unin_pci.c                               |   16 
 hw/usb-bt.c                                 |    3 
 hw/usb-bus.c                                |   37 
 hw/usb-ehci.c                               |  103 -
 hw/usb-hub.c                                |   27 
 hw/usb-msd.c                                |   87 
 hw/usb-net.c                                |    5 
 hw/usb-ohci.c                               |    8 
 hw/usb-uhci.c                               |   19 
 hw/versatile_pci.c                          |    6 
 hw/versatilepb.c                            |   36 
 hw/vexpress.c                               |   35 
 hw/vga-pci.c                                |    5 
 hw/vga.c                                    |   15 
 hw/vhost.c                                  |  178 +
 hw/vhost.h                                  |    5 
 hw/virtex_ml507.c                           |    8 
 hw/virtio-balloon.c                         |   13 
 hw/virtio-blk.c                             |   46 
 hw/virtio-console.c                         |   20 
 hw/virtio-pci.c                             |   18 
 hw/virtio-pci.h                             |    1 
 hw/virtio-serial-bus.c                      |   20 
 hw/virtio.c                                 |   24 
 hw/virtio.h                                 |    1 
 hw/vmport.c                                 |    2 
 hw/vmware_vga.c                             |    3 
 hw/vmware_vga.h                             |    6 
 hw/vt82c686.c                               |    4 
 hw/vt82c686.h                               |    2 
 hw/wdt_ib700.c                              |    2 
 hw/wm8750.c                                 |    2 
 hw/xen.h                                    |    7 
 hw/xen_disk.c                               |   86 
 hw/xen_platform.c                           |   20 
 hw/xilinx_axidma.c                          |   29 
 hw/xilinx_axienet.c                         |   29 
 hw/xilinx_ethlite.c                         |    2 
 hw/xilinx_intc.c                            |    2 
 hw/xilinx_timer.c                           |    2 
 hw/xilinx_uartlite.c                        |    2 
 hw/xtensa_bootparam.h                       |   25 
 hw/xtensa_lx60.c                            |  116 +
 hw/xtensa_sim.c                             |    6 
 hw/zaurus.c                                 |   26 
 ia64-dis.c                                  |    3 
 int128.h                                    |  116 +
 kvm-all.c                                   |  157 -
 kvm.h                                       |    4 
 libcacard/card_7816.c                       |    4 
 libcacard/card_7816.h                       |    2 
 libcacard/vcard_emul_nss.c                  |    2 
 libcacard/vscard_common.h                   |    2 
 linux-aio.c                                 |    2 
 linux-user/arm/nwfpe/fpopcode.h             |   34 
 linux-user/cpu-uname.c                      |    2 
 linux-user/elfload.c                        |   18 
 linux-user/flatload.c                       |    2 
 linux-user/linuxload.c                      |    2 
 linux-user/main.c                           |    4 
 linux-user/signal.c                         |    2 
 linux-user/syscall.c                        |   10 
 linux-user/syscall_defs.h                   |    6 
 linux-user/x86_64/syscall.h                 |    2 
 m68k-dis.c                                  |    2 
 main-loop.c                                 |    4 
 main-loop.h                                 |    8 
 memory.c                                    |  663 ++++--
 memory.h                                    |  251 ++
 migration-exec.c                            |    9 
 migration-fd.c                              |   23 
 migration-tcp.c                             |    7 
 migration-unix.c                            |    7 
 migration.c                                 |   67 
 migration.h                                 |   22 
 monitor.c                                   |  235 --
 monitor.h                                   |    7 
 nbd.c                                       |  450 +++-
 nbd.h                                       |   14 
 net.c                                       |   23 
 net.h                                       |    1 
 net/dump.c                                  |    9 
 net/slirp.c                                 |   11 
 net/socket.c                                |  170 +
 net/tap-linux.c                             |    6 
 net/tap-solaris.c                           |    2 
 net/tap.c                                   |    6 
 os-posix.c                                  |   45 
 os-win32.c                                  |   19 
 osdep.c                                     |   76 
 oslib-posix.c                               |   68 
 oslib-win32.c                               |    5 
 pc-bios/README                              |    8 
 pc-bios/keymaps/is                          |    2 
 pc-bios/ohw.diff                            |    2 
 pc-bios/optionrom/multiboot.S               |    2 
 pc-bios/sgabios.bin                         |binary
 pc-bios/slof.bin                            |binary
 posix-aio-compat.c                          |    9 
 ppc.ld                                      |   16 
 ppc64.ld                                    |   16 
 qapi-schema-guest.json                      |    8 
 qapi-schema-test.json                       |    6 
 qapi-schema.json                            |  390 +++
 qapi/qmp-core.h                             |    4 
 qapi/qmp-dispatch.c                         |    4 
 qapi/qmp-input-visitor.c                    |   10 
 qapi/qmp-output-visitor.c                   |    2 
 qapi/qmp-registry.c                         |   56 
 qemu-barrier.h                              |    2 
 qemu-char.c                                 |   45 
 qemu-char.h                                 |   10 
 qemu-common.h                               |   42 
 qemu-config.c                               |   41 
 qemu-coroutine-io.c                         |   96 
 qemu-coroutine-lock.c                       |   23 
 qemu-coroutine.h                            |   11 
 qemu-doc.texi                               |   83 
 qemu-error.c                                |    5 
 qemu-error.h                                |    1 
 qemu-ga.c                                   |   37 
 qemu-img-cmds.hx                            |    6 
 qemu-img.c                                  |   52 
 qemu-img.texi                               |   10 
 qemu-io.c                                   |   78 
 qemu-nbd.c                                  |  372 ++-
 qemu-option.c                               |    2 
 qemu-options-wrapper.h                      |   41 
 qemu-options.h                              |    9 
 qemu-options.hx                             |   80 
 qemu-os-posix.h                             |    3 
 qemu-sockets.c                              |    1 
 qemu-tech.texi                              |   12 
 qemu-thread-posix.c                         |   33 
 qemu-thread-win32.c                         |  122 -
 qemu-thread-win32.h                         |    8 
 qemu-thread.h                               |    8 
 qemu-timer.c                                |    4 
 qemu-tls.h                                  |   52 
 qemu-tool.c                                 |   51 
 qemu-xattr.h                                |   30 
 qemu_socket.h                               |    1 
 qerror.c                                    |   36 
 qerror.h                                    |   24 
 qga/guest-agent-commands.c                  |   24 
 qmp-commands.hx                             |  148 -
 qmp.c                                       |  130 +
 readline.c                                  |    2 
 roms/SLOF                                   |    2 
 roms/sgabios                                |    1 
 savevm.c                                    |  115 -
 scripts/analyse-9p-simpletrace.py           |   75 
 scripts/checkpatch.pl                       |   14 
 scripts/hxtool                              |    3 
 scripts/qapi-commands.py                    |   27 
 scripts/qapi-types.py                       |   26 
 scripts/qapi-visit.py                       |   25 
 scripts/qapi.py                             |    7 
 softmmu_template.h                          |   33 
 spice-qemu-char.c                           |   36 
 sysemu.h                                    |    8 
 target-alpha/STATUS                         |    2 
 target-arm/cpu.h                            |    6 
 target-arm/helper.c                         |  187 +
 target-arm/machine.c                        |    6 
 target-arm/translate.c                      |    8 
 target-cris/cpu.h                           |    2 
 target-cris/helper.c                        |    1 
 target-cris/translate_v10.c                 |   72 
 target-i386/TODO                            |    1 
 target-i386/cpu.h                           |    3 
 target-i386/cpuid.c                         |   32 
 target-i386/helper.c                        |    1 
 target-i386/helper.h                        |    1 
 target-i386/kvm.c                           |   43 
 target-i386/op_helper.c                     |   64 
 target-i386/ops_sse.h                       |   65 
 target-i386/translate.c                     |   13 
 target-microblaze/cpu.h                     |    5 
 target-microblaze/helper.h                  |    2 
 target-microblaze/op_helper.c               |   16 
 target-microblaze/translate.c               |   60 
 target-mips/cpu.h                           |    2 
 target-mips/helper.c                        |    2 
 target-mips/machine.c                       |    2 
 target-ppc/cpu.h                            |   53 
 target-ppc/helper.c                         |   39 
 target-ppc/kvm.c                            |  200 +-
 target-ppc/kvm_ppc.h                        |   50 
 target-ppc/mfrom_table_gen.c                |    2 
 target-ppc/op_helper.c                      |    4 
 target-ppc/translate.c                      |  504 ++---
 target-ppc/translate_init.c                 |  162 +
 target-s390x/cpu.h                          |   23 
 target-s390x/helper.c                       |   27 
 target-s390x/helpers.h                      |    1 
 target-s390x/kvm.c                          |   20 
 target-s390x/op_helper.c                    |   50 
 target-s390x/translate.c                    |    4 
 target-sh4/helper.c                         |    5 
 target-sh4/translate.c                      |   20 
 target-sparc/TODO                           |    2 
 target-sparc/helper.c                       |    7 
 target-sparc/helper.h                       |    1 
 target-sparc/int32_helper.c                 |   10 
 target-sparc/mmu_helper.c                   |    5 
 target-sparc/translate.c                    |    9 
 target-xtensa/helper.c                      |    2 
 target-xtensa/overlay_tool.h                |    8 
 target-xtensa/translate.c                   |    9 
 tcg/arm/tcg-target.c                        |   44 
 tcg/arm/tcg-target.h                        |    6 
 tcg/hppa/tcg-target.c                       |   12 
 tcg/hppa/tcg-target.h                       |    4 
 tcg/i386/tcg-target.c                       |   13 
 tcg/i386/tcg-target.h                       |    9 
 tcg/ia64/tcg-target.c                       |   12 
 tcg/ia64/tcg-target.h                       |    4 
 tcg/mips/tcg-target.c                       |   13 
 tcg/mips/tcg-target.h                       |    4 
 tcg/ppc/tcg-target.c                        |    8 
 tcg/ppc/tcg-target.h                        |    8 
 tcg/ppc64/tcg-target.c                      |   22 
 tcg/ppc64/tcg-target.h                      |    4 
 tcg/sparc/tcg-target.c                      |   17 
 tcg/sparc/tcg-target.h                      |    4 
 tcg/tcg-op.h                                |   16 
 tcg/tcg.c                                   |   11 
 tcg/tcg.h                                   |   18 
 tcg/tci/README                              |  130 +
 tcg/tci/tcg-target.c                        |  902 +++++++++
 tcg/tci/tcg-target.h                        |  164 +
 tci-dis.c                                   |   59 
 tci.c                                       | 1208 ++++++++++++
 test-qmp-input-visitor.c                    |  270 ++
 test-qmp-output-visitor.c                   |  423 ++++
 test-visitor.c                              |  338 ---
 tests/Makefile                              |  172 -
 tests/alpha/Makefile                        |   35 
 tests/alpha/crt.s                           |   26 
 tests/alpha/hello-alpha.c                   |    5 
 tests/alpha/test-cond.c                     |   87 
 tests/alpha/test-ovf.c                      |   29 
 tests/cris/.gdbinit                         |   11 
 tests/cris/Makefile                         |  155 -
 tests/cris/README                           |    1 
 tests/cris/check_abs.c                      |   40 
 tests/cris/check_addc.c                     |   58 
 tests/cris/check_addcm.c                    |   85 
 tests/cris/check_addi.s                     |   57 
 tests/cris/check_addiv32.s                  |   62 
 tests/cris/check_addm.s                     |   96 
 tests/cris/check_addo.c                     |  125 -
 tests/cris/check_addoq.c                    |   44 
 tests/cris/check_addq.s                     |   47 
 tests/cris/check_addr.s                     |   96 
 tests/cris/check_addxc.s                    |   91 
 tests/cris/check_addxm.s                    |  106 -
 tests/cris/check_addxr.s                    |   96 
 tests/cris/check_andc.s                     |   80 
 tests/cris/check_andm.s                     |   90 
 tests/cris/check_andq.s                     |   46 
 tests/cris/check_andr.s                     |   95 
 tests/cris/check_asr.s                      |  230 --
 tests/cris/check_ba.s                       |   93 
 tests/cris/check_bas.s                      |  102 -
 tests/cris/check_bcc.s                      |  197 -
 tests/cris/check_bound.c                    |  142 -
 tests/cris/check_boundc.s                   |  101 -
 tests/cris/check_boundr.s                   |  125 -
 tests/cris/check_btst.s                     |   96 
 tests/cris/check_clearfv32.s                |   19 
 tests/cris/check_clrjmp1.s                  |   36 
 tests/cris/check_cmp-2.s                    |   15 
 tests/cris/check_cmpc.s                     |   86 
 tests/cris/check_cmpm.s                     |   96 
 tests/cris/check_cmpq.s                     |   75 
 tests/cris/check_cmpr.s                     |  102 -
 tests/cris/check_cmpxc.s                    |   92 
 tests/cris/check_cmpxm.s                    |  106 -
 tests/cris/check_dstep.s                    |   42 
 tests/cris/check_ftag.c                     |   37 
 tests/cris/check_gcctorture_pr28634-1.c     |   15 
 tests/cris/check_gcctorture_pr28634.c       |   15 
 tests/cris/check_glibc_kernelversion.c      |  116 -
 tests/cris/check_hello.c                    |    7 
 tests/cris/check_int64.c                    |   47 
 tests/cris/check_jsr.s                      |   85 
 tests/cris/check_lapc.s                     |   78 
 tests/cris/check_lsl.s                      |  217 --
 tests/cris/check_lsr.s                      |  218 --
 tests/cris/check_lz.c                       |   49 
 tests/cris/check_mapbrk.c                   |   39 
 tests/cris/check_mcp.s                      |   49 
 tests/cris/check_mmap1.c                    |   48 
 tests/cris/check_mmap2.c                    |   48 
 tests/cris/check_mmap3.c                    |   33 
 tests/cris/check_movdelsr1.s                |   33 
 tests/cris/check_movecr.s                   |   37 
 tests/cris/check_movei.s                    |   50 
 tests/cris/check_movemr.s                   |   78 
 tests/cris/check_movemrv32.s                |   96 
 tests/cris/check_moveq.c                    |   51 
 tests/cris/check_mover.s                    |   28 
 tests/cris/check_moverm.s                   |   45 
 tests/cris/check_movmp.s                    |  131 -
 tests/cris/check_movpmv32.s                 |   35 
 tests/cris/check_movpr.s                    |   28 
 tests/cris/check_movprv32.s                 |   21 
 tests/cris/check_movscr.s                   |   29 
 tests/cris/check_movsm.s                    |   44 
 tests/cris/check_movsr.s                    |   46 
 tests/cris/check_movucr.s                   |   33 
 tests/cris/check_movum.s                    |   40 
 tests/cris/check_movur.s                    |   45 
 tests/cris/check_mulv32.s                   |   51 
 tests/cris/check_mulx.s                     |  246 --
 tests/cris/check_neg.s                      |  104 -
 tests/cris/check_not.s                      |   31 
 tests/cris/check_openpf1.c                  |   38 
 tests/cris/check_openpf2.c                  |   16 
 tests/cris/check_openpf3.c                  |   49 
 tests/cris/check_openpf4.c                  |    5 
 tests/cris/check_openpf5.c                  |   56 
 tests/cris/check_orc.s                      |   71 
 tests/cris/check_orm.s                      |   75 
 tests/cris/check_orq.s                      |   41 
 tests/cris/check_orr.s                      |   84 
 tests/cris/check_ret.s                      |   25 
 tests/cris/check_scc.s                      |   95 
 tests/cris/check_settls1.c                  |   45 
 tests/cris/check_sigalrm.c                  |   26 
 tests/cris/check_stat1.c                    |   16 
 tests/cris/check_stat2.c                    |   20 
 tests/cris/check_stat3.c                    |   25 
 tests/cris/check_stat4.c                    |   27 
 tests/cris/check_subc.s                     |   87 
 tests/cris/check_subm.s                     |   96 
 tests/cris/check_subq.s                     |   52 
 tests/cris/check_subr.s                     |  102 -
 tests/cris/check_swap.c                     |   76 
 tests/cris/check_time1.c                    |   46 
 tests/cris/check_time2.c                    |   18 
 tests/cris/check_xarith.s                   |   72 
 tests/cris/crisutils.h                      |   71 
 tests/cris/crt.s                            |   13 
 tests/cris/sys.c                            |   51 
 tests/cris/sys.h                            |   16 
 tests/cris/testutils.inc                    |  117 -
 tests/hello-arm.c                           |  113 -
 tests/hello-i386.c                          |   26 
 tests/hello-mips.c                          |   64 
 tests/linux-test.c                          |  537 -----
 tests/lm32/Makefile                         |  102 -
 tests/lm32/crt.S                            |   84 
 tests/lm32/linker.ld                        |   55 
 tests/lm32/macros.inc                       |   79 
 tests/lm32/test_add.S                       |   75 
 tests/lm32/test_addi.S                      |   56 
 tests/lm32/test_and.S                       |   45 
 tests/lm32/test_andhi.S                     |   35 
 tests/lm32/test_andi.S                      |   35 
 tests/lm32/test_b.S                         |   13 
 tests/lm32/test_be.S                        |   48 
 tests/lm32/test_bg.S                        |   78 
 tests/lm32/test_bge.S                       |   78 
 tests/lm32/test_bgeu.S                      |   78 
 tests/lm32/test_bgu.S                       |   78 
 tests/lm32/test_bi.S                        |   23 
 tests/lm32/test_bne.S                       |   48 
 tests/lm32/test_break.S                     |   20 
 tests/lm32/test_bret.S                      |   38 
 tests/lm32/test_call.S                      |   16 
 tests/lm32/test_calli.S                     |   15 
 tests/lm32/test_cmpe.S                      |   40 
 tests/lm32/test_cmpei.S                     |   35 
 tests/lm32/test_cmpg.S                      |   64 
 tests/lm32/test_cmpge.S                     |   64 
 tests/lm32/test_cmpgei.S                    |   55 
 tests/lm32/test_cmpgeu.S                    |   64 
 tests/lm32/test_cmpgeui.S                   |   55 
 tests/lm32/test_cmpgi.S                     |   55 
 tests/lm32/test_cmpgu.S                     |   64 
 tests/lm32/test_cmpgui.S                    |   55 
 tests/lm32/test_cmpne.S                     |   40 
 tests/lm32/test_cmpnei.S                    |   35 
 tests/lm32/test_divu.S                      |   29 
 tests/lm32/test_eret.S                      |   38 
 tests/lm32/test_lb.S                        |   45 
 tests/lm32/test_lbu.S                       |   45 
 tests/lm32/test_lh.S                        |   45 
 tests/lm32/test_lhu.S                       |   45 
 tests/lm32/test_lw.S                        |   30 
 tests/lm32/test_modu.S                      |   35 
 tests/lm32/test_mul.S                       |   70 
 tests/lm32/test_muli.S                      |   45 
 tests/lm32/test_nor.S                       |   51 
 tests/lm32/test_nori.S                      |   35 
 tests/lm32/test_or.S                        |   51 
 tests/lm32/test_orhi.S                      |   35 
 tests/lm32/test_ori.S                       |   35 
 tests/lm32/test_ret.S                       |   14 
 tests/lm32/test_sb.S                        |   30 
 tests/lm32/test_scall.S                     |   20 
 tests/lm32/test_sextb.S                     |   20 
 tests/lm32/test_sexth.S                     |   20 
 tests/lm32/test_sh.S                        |   30 
 tests/lm32/test_sl.S                        |   45 
 tests/lm32/test_sli.S                       |   30 
 tests/lm32/test_sr.S                        |   57 
 tests/lm32/test_sri.S                       |   40 
 tests/lm32/test_sru.S                       |   57 
 tests/lm32/test_srui.S                      |   40 
 tests/lm32/test_sub.S                       |   75 
 tests/lm32/test_sw.S                        |   35 
 tests/lm32/test_xnor.S                      |   51 
 tests/lm32/test_xnori.S                     |   35 
 tests/lm32/test_xor.S                       |   51 
 tests/lm32/test_xori.S                      |   35 
 tests/qruncom.c                             |  284 --
 tests/runcom.c                              |  192 -
 tests/sha1.c                                |  240 --
 tests/tcg/Makefile                          |  145 +
 tests/tcg/alpha/Makefile                    |   35 
 tests/tcg/alpha/crt.s                       |   26 
 tests/tcg/alpha/hello-alpha.c               |    5 
 tests/tcg/alpha/test-cond.c                 |   87 
 tests/tcg/alpha/test-ovf.c                  |   29 
 tests/tcg/cris/.gdbinit                     |   11 
 tests/tcg/cris/Makefile                     |  155 +
 tests/tcg/cris/README                       |    1 
 tests/tcg/cris/check_abs.c                  |   40 
 tests/tcg/cris/check_addc.c                 |   58 
 tests/tcg/cris/check_addcm.c                |   85 
 tests/tcg/cris/check_addi.s                 |   57 
 tests/tcg/cris/check_addiv32.s              |   62 
 tests/tcg/cris/check_addm.s                 |   96 
 tests/tcg/cris/check_addo.c                 |  125 +
 tests/tcg/cris/check_addoq.c                |   44 
 tests/tcg/cris/check_addq.s                 |   47 
 tests/tcg/cris/check_addr.s                 |   96 
 tests/tcg/cris/check_addxc.s                |   91 
 tests/tcg/cris/check_addxm.s                |  106 +
 tests/tcg/cris/check_addxr.s                |   96 
 tests/tcg/cris/check_andc.s                 |   80 
 tests/tcg/cris/check_andm.s                 |   90 
 tests/tcg/cris/check_andq.s                 |   46 
 tests/tcg/cris/check_andr.s                 |   95 
 tests/tcg/cris/check_asr.s                  |  230 ++
 tests/tcg/cris/check_ba.s                   |   93 
 tests/tcg/cris/check_bas.s                  |  102 +
 tests/tcg/cris/check_bcc.s                  |  197 +
 tests/tcg/cris/check_bound.c                |  142 +
 tests/tcg/cris/check_boundc.s               |  101 +
 tests/tcg/cris/check_boundr.s               |  125 +
 tests/tcg/cris/check_btst.s                 |   96 
 tests/tcg/cris/check_clearfv32.s            |   19 
 tests/tcg/cris/check_clrjmp1.s              |   36 
 tests/tcg/cris/check_cmp-2.s                |   15 
 tests/tcg/cris/check_cmpc.s                 |   86 
 tests/tcg/cris/check_cmpm.s                 |   96 
 tests/tcg/cris/check_cmpq.s                 |   75 
 tests/tcg/cris/check_cmpr.s                 |  102 +
 tests/tcg/cris/check_cmpxc.s                |   92 
 tests/tcg/cris/check_cmpxm.s                |  106 +
 tests/tcg/cris/check_dstep.s                |   42 
 tests/tcg/cris/check_ftag.c                 |   37 
 tests/tcg/cris/check_gcctorture_pr28634-1.c |   15 
 tests/tcg/cris/check_gcctorture_pr28634.c   |   15 
 tests/tcg/cris/check_glibc_kernelversion.c  |  116 +
 tests/tcg/cris/check_hello.c                |    7 
 tests/tcg/cris/check_int64.c                |   47 
 tests/tcg/cris/check_jsr.s                  |   85 
 tests/tcg/cris/check_lapc.s                 |   78 
 tests/tcg/cris/check_lsl.s                  |  217 ++
 tests/tcg/cris/check_lsr.s                  |  218 ++
 tests/tcg/cris/check_lz.c                   |   49 
 tests/tcg/cris/check_mapbrk.c               |   39 
 tests/tcg/cris/check_mcp.s                  |   49 
 tests/tcg/cris/check_mmap1.c                |   48 
 tests/tcg/cris/check_mmap2.c                |   48 
 tests/tcg/cris/check_mmap3.c                |   33 
 tests/tcg/cris/check_movdelsr1.s            |   33 
 tests/tcg/cris/check_movecr.s               |   37 
 tests/tcg/cris/check_movei.s                |   50 
 tests/tcg/cris/check_movemr.s               |   78 
 tests/tcg/cris/check_movemrv32.s            |   96 
 tests/tcg/cris/check_moveq.c                |   51 
 tests/tcg/cris/check_mover.s                |   28 
 tests/tcg/cris/check_moverm.s               |   45 
 tests/tcg/cris/check_movmp.s                |  131 +
 tests/tcg/cris/check_movpmv32.s             |   35 
 tests/tcg/cris/check_movpr.s                |   28 
 tests/tcg/cris/check_movprv32.s             |   21 
 tests/tcg/cris/check_movscr.s               |   29 
 tests/tcg/cris/check_movsm.s                |   44 
 tests/tcg/cris/check_movsr.s                |   46 
 tests/tcg/cris/check_movucr.s               |   33 
 tests/tcg/cris/check_movum.s                |   40 
 tests/tcg/cris/check_movur.s                |   45 
 tests/tcg/cris/check_mulv32.s               |   51 
 tests/tcg/cris/check_mulx.s                 |  246 ++
 tests/tcg/cris/check_neg.s                  |  104 +
 tests/tcg/cris/check_not.s                  |   31 
 tests/tcg/cris/check_openpf1.c              |   38 
 tests/tcg/cris/check_openpf2.c              |   16 
 tests/tcg/cris/check_openpf3.c              |   49 
 tests/tcg/cris/check_openpf4.c              |    5 
 tests/tcg/cris/check_openpf5.c              |   56 
 tests/tcg/cris/check_orc.s                  |   71 
 tests/tcg/cris/check_orm.s                  |   75 
 tests/tcg/cris/check_orq.s                  |   41 
 tests/tcg/cris/check_orr.s                  |   84 
 tests/tcg/cris/check_ret.s                  |   25 
 tests/tcg/cris/check_scc.s                  |   95 
 tests/tcg/cris/check_settls1.c              |   45 
 tests/tcg/cris/check_sigalrm.c              |   26 
 tests/tcg/cris/check_stat1.c                |   16 
 tests/tcg/cris/check_stat2.c                |   20 
 tests/tcg/cris/check_stat3.c                |   25 
 tests/tcg/cris/check_stat4.c                |   27 
 tests/tcg/cris/check_subc.s                 |   87 
 tests/tcg/cris/check_subm.s                 |   96 
 tests/tcg/cris/check_subq.s                 |   52 
 tests/tcg/cris/check_subr.s                 |  102 +
 tests/tcg/cris/check_swap.c                 |   76 
 tests/tcg/cris/check_time1.c                |   46 
 tests/tcg/cris/check_time2.c                |   18 
 tests/tcg/cris/check_xarith.s               |   72 
 tests/tcg/cris/crisutils.h                  |   71 
 tests/tcg/cris/crt.s                        |   13 
 tests/tcg/cris/sys.c                        |   51 
 tests/tcg/cris/sys.h                        |   16 
 tests/tcg/cris/testutils.inc                |  117 +
 tests/tcg/hello-arm.c                       |  113 +
 tests/tcg/hello-i386.c                      |   26 
 tests/tcg/hello-mips.c                      |   64 
 tests/tcg/linux-test.c                      |  537 +++++
 tests/tcg/lm32/Makefile                     |  102 +
 tests/tcg/lm32/crt.S                        |   84 
 tests/tcg/lm32/linker.ld                    |   55 
 tests/tcg/lm32/macros.inc                   |   79 
 tests/tcg/lm32/test_add.S                   |   75 
 tests/tcg/lm32/test_addi.S                  |   56 
 tests/tcg/lm32/test_and.S                   |   45 
 tests/tcg/lm32/test_andhi.S                 |   35 
 tests/tcg/lm32/test_andi.S                  |   35 
 tests/tcg/lm32/test_b.S                     |   13 
 tests/tcg/lm32/test_be.S                    |   48 
 tests/tcg/lm32/test_bg.S                    |   78 
 tests/tcg/lm32/test_bge.S                   |   78 
 tests/tcg/lm32/test_bgeu.S                  |   78 
 tests/tcg/lm32/test_bgu.S                   |   78 
 tests/tcg/lm32/test_bi.S                    |   23 
 tests/tcg/lm32/test_bne.S                   |   48 
 tests/tcg/lm32/test_break.S                 |   20 
 tests/tcg/lm32/test_bret.S                  |   38 
 tests/tcg/lm32/test_call.S                  |   16 
 tests/tcg/lm32/test_calli.S                 |   15 
 tests/tcg/lm32/test_cmpe.S                  |   40 
 tests/tcg/lm32/test_cmpei.S                 |   35 
 tests/tcg/lm32/test_cmpg.S                  |   64 
 tests/tcg/lm32/test_cmpge.S                 |   64 
 tests/tcg/lm32/test_cmpgei.S                |   55 
 tests/tcg/lm32/test_cmpgeu.S                |   64 
 tests/tcg/lm32/test_cmpgeui.S               |   55 
 tests/tcg/lm32/test_cmpgi.S                 |   55 
 tests/tcg/lm32/test_cmpgu.S                 |   64 
 tests/tcg/lm32/test_cmpgui.S                |   55 
 tests/tcg/lm32/test_cmpne.S                 |   40 
 tests/tcg/lm32/test_cmpnei.S                |   35 
 tests/tcg/lm32/test_divu.S                  |   29 
 tests/tcg/lm32/test_eret.S                  |   38 
 tests/tcg/lm32/test_lb.S                    |   45 
 tests/tcg/lm32/test_lbu.S                   |   45 
 tests/tcg/lm32/test_lh.S                    |   45 
 tests/tcg/lm32/test_lhu.S                   |   45 
 tests/tcg/lm32/test_lw.S                    |   30 
 tests/tcg/lm32/test_modu.S                  |   35 
 tests/tcg/lm32/test_mul.S                   |   70 
 tests/tcg/lm32/test_muli.S                  |   45 
 tests/tcg/lm32/test_nor.S                   |   51 
 tests/tcg/lm32/test_nori.S                  |   35 
 tests/tcg/lm32/test_or.S                    |   51 
 tests/tcg/lm32/test_orhi.S                  |   35 
 tests/tcg/lm32/test_ori.S                   |   35 
 tests/tcg/lm32/test_ret.S                   |   14 
 tests/tcg/lm32/test_sb.S                    |   30 
 tests/tcg/lm32/test_scall.S                 |   20 
 tests/tcg/lm32/test_sextb.S                 |   20 
 tests/tcg/lm32/test_sexth.S                 |   20 
 tests/tcg/lm32/test_sh.S                    |   30 
 tests/tcg/lm32/test_sl.S                    |   45 
 tests/tcg/lm32/test_sli.S                   |   30 
 tests/tcg/lm32/test_sr.S                    |   57 
 tests/tcg/lm32/test_sri.S                   |   40 
 tests/tcg/lm32/test_sru.S                   |   57 
 tests/tcg/lm32/test_srui.S                  |   40 
 tests/tcg/lm32/test_sub.S                   |   75 
 tests/tcg/lm32/test_sw.S                    |   35 
 tests/tcg/lm32/test_xnor.S                  |   51 
 tests/tcg/lm32/test_xnori.S                 |   35 
 tests/tcg/lm32/test_xor.S                   |   51 
 tests/tcg/lm32/test_xori.S                  |   35 
 tests/tcg/pi_10.com                         |binary
 tests/tcg/runcom.c                          |  192 +
 tests/tcg/sha1.c                            |  240 ++
 tests/tcg/test-arm-iwmmxt.s                 |   49 
 tests/tcg/test-i386-code16.S                |   79 
 tests/tcg/test-i386-muldiv.h                |   76 
 tests/tcg/test-i386-shift.h                 |  185 +
 tests/tcg/test-i386-ssse3.c                 |   57 
 tests/tcg/test-i386-vm86.S                  |  103 +
 tests/tcg/test-i386.c                       | 2764 ++++++++++++++++++++++++++++
 tests/tcg/test-i386.h                       |  152 +
 tests/tcg/test-mmap.c                       |  476 ++++
 tests/tcg/test_path.c                       |  160 +
 tests/tcg/testthread.c                      |   51 
 tests/tcg/xtensa/Makefile                   |   75 
 tests/tcg/xtensa/crt.S                      |   24 
 tests/tcg/xtensa/linker.ld                  |  112 +
 tests/tcg/xtensa/macros.inc                 |   68 
 tests/tcg/xtensa/test_b.S                   |  221 ++
 tests/tcg/xtensa/test_bi.S                  |  103 +
 tests/tcg/xtensa/test_boolean.S             |   23 
 tests/tcg/xtensa/test_bz.S                  |   57 
 tests/tcg/xtensa/test_clamps.S              |   42 
 tests/tcg/xtensa/test_fail.S                |    9 
 tests/tcg/xtensa/test_interrupt.S           |  194 +
 tests/tcg/xtensa/test_loop.S                |   77 
 tests/tcg/xtensa/test_mac16.S               |  243 ++
 tests/tcg/xtensa/test_max.S                 |   81 
 tests/tcg/xtensa/test_min.S                 |   81 
 tests/tcg/xtensa/test_mmu.S                 |  318 +++
 tests/tcg/xtensa/test_mul16.S               |   83 
 tests/tcg/xtensa/test_mul32.S               |   20 
 tests/tcg/xtensa/test_nsa.S                 |   59 
 tests/tcg/xtensa/test_pipeline.S            |  157 +
 tests/tcg/xtensa/test_quo.S                 |  147 +
 tests/tcg/xtensa/test_rem.S                 |  147 +
 tests/tcg/xtensa/test_rst0.S                |  148 +
 tests/tcg/xtensa/test_sar.S                 |  111 +
 tests/tcg/xtensa/test_sext.S                |   69 
 tests/tcg/xtensa/test_shift.S               |  206 ++
 tests/tcg/xtensa/test_timer.S               |  178 +
 tests/tcg/xtensa/test_windowed.S            |  302 +++
 tests/tcg/xtensa/vectors.S                  |   39 
 tests/test-arm-iwmmxt.s                     |   49 
 tests/test-i386-code16.S                    |   79 
 tests/test-i386-muldiv.h                    |   76 
 tests/test-i386-shift.h                     |  185 -
 tests/test-i386-ssse3.c                     |   57 
 tests/test-i386-vm86.S                      |  103 -
 tests/test-i386.c                           | 2764 ----------------------------
 tests/test-i386.h                           |  152 -
 tests/test-mmap.c                           |  476 ----
 tests/test_path.c                           |  160 -
 tests/testthread.c                          |   51 
 tests/xtensa/Makefile                       |   75 
 tests/xtensa/crt.S                          |   24 
 tests/xtensa/linker.ld                      |  112 -
 tests/xtensa/macros.inc                     |   68 
 tests/xtensa/test_b.S                       |  221 --
 tests/xtensa/test_bi.S                      |  103 -
 tests/xtensa/test_boolean.S                 |   23 
 tests/xtensa/test_bz.S                      |   57 
 tests/xtensa/test_clamps.S                  |   42 
 tests/xtensa/test_fail.S                    |    9 
 tests/xtensa/test_interrupt.S               |  194 -
 tests/xtensa/test_loop.S                    |   77 
 tests/xtensa/test_mac16.S                   |  243 --
 tests/xtensa/test_max.S                     |   81 
 tests/xtensa/test_min.S                     |   81 
 tests/xtensa/test_mmu.S                     |  318 ---
 tests/xtensa/test_mul16.S                   |   83 
 tests/xtensa/test_mul32.S                   |   20 
 tests/xtensa/test_nsa.S                     |   59 
 tests/xtensa/test_pipeline.S                |  157 -
 tests/xtensa/test_quo.S                     |  147 -
 tests/xtensa/test_rem.S                     |  147 -
 tests/xtensa/test_rst0.S                    |  148 -
 tests/xtensa/test_sar.S                     |  111 -
 tests/xtensa/test_sext.S                    |   69 
 tests/xtensa/test_shift.S                   |  206 --
 tests/xtensa/test_timer.S                   |  178 -
 tests/xtensa/test_windowed.S                |  302 ---
 tests/xtensa/vectors.S                      |   39 
 trace-events                                |   20 
 trace/simple.c                              |   24 
 trace/stderr.c                              |   17 
 ui/cocoa.m                                  |    2 
 ui/keymaps.c                                |   12 
 ui/vnc-auth-sasl.c                          |   27 
 ui/vnc-enc-hextile.c                        |    4 
 ui/vnc-enc-zywrle-template.c                |    2 
 ui/vnc-enc-zywrle.h                         |    2 
 ui/vnc-jobs-async.c                         |    2 
 ui/vnc-tls.c                                |    2 
 ui/vnc.c                                    |   14 
 usb-linux.c                                 |   85 
 usb-redir.c                                 |   37 
 vl.c                                        |   98 
 xen-all.c                                   |  211 +-
 xen-mapcache.c                              |    2 
 xen-stub.c                                  |    7 
 1113 files changed, 44698 insertions(+), 33038 deletions(-)

New commits:
commit 515aa3c57986b3e26558d72ecaeb7545ecd30510
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Jan 12 11:33:22 2012 -0600

    check-qstring: remove check.h include
    
    Reported-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/check-qstring.c b/check-qstring.c
index 681bb68..addad6c 100644
--- a/check-qstring.c
+++ b/check-qstring.c
@@ -9,7 +9,7 @@
  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
  * See the COPYING.LIB file in the top-level directory.
  */
-#include <check.h>
+#include <glib.h>
 
 #include "qstring.h"
 #include "qemu-common.h"
commit 92af0bfda00dc2585d34ec6d83ae091ec4e93e89
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Jan 11 10:02:43 2012 +0000

    MAINTAINERS: update tracing repo git URL
    
    I have moved git hosting services.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/MAINTAINERS b/MAINTAINERS
index 764c92d..de2a916 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -490,7 +490,7 @@ Tracing
 M: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
 S: Maintained
 F: trace/
-T: git://repo.or.cz/qemu/stefanha.git tracing
+T: git://github.com/stefanha/qemu.git tracing
 
 Checkpatch
 M: Blue Swirl <blauwirbel at gmail.com>
commit 0e0e7facc775e9bb020314f48751b3d09f316c8b
Author: Benjamin <mlspirat42 at gmail.com>
Date:   Wed Jan 11 09:20:54 2012 +0900

    Support for UDP unicast network backend
    
    Signed-off-by: Benjamin MARSILI <mlspirat42 at gmail.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/net.c b/net.c
index f7bebf8..2b0f766 100644
--- a/net.c
+++ b/net.c
@@ -1000,7 +1000,11 @@ static const struct {
             }, {
                 .name = "localaddr",
                 .type = QEMU_OPT_STRING,
-                .help = "source address for multicast packets",
+                .help = "source address and port for multicast and udp packets",
+            }, {
+                .name = "udp",
+                .type = QEMU_OPT_STRING,
+                .help = "UDP unicast address and port number",
             },
             { /* end of list */ }
         },
diff --git a/net/socket.c b/net/socket.c
index c9d70d3..d4c2002 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -534,6 +534,57 @@ static int net_socket_mcast_init(VLANState *vlan,
 
 }
 
+static int net_socket_udp_init(VLANState *vlan,
+                                 const char *model,
+                                 const char *name,
+                                 const char *rhost,
+                                 const char *lhost)
+{
+    NetSocketState *s;
+    int fd, val, ret;
+    struct sockaddr_in laddr, raddr;
+
+    if (parse_host_port(&laddr, lhost) < 0) {
+        return -1;
+    }
+
+    if (parse_host_port(&raddr, rhost) < 0) {
+        return -1;
+    }
+
+    fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
+    if (fd < 0) {
+        perror("socket(PF_INET, SOCK_DGRAM)");
+        return -1;
+    }
+    val = 1;
+    ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+                   (const char *)&val, sizeof(val));
+    if (ret < 0) {
+        perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
+        closesocket(fd);
+        return -1;
+    }
+    ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
+    if (ret < 0) {
+        perror("bind");
+        closesocket(fd);
+        return -1;
+    }
+
+    s = net_socket_fd_init(vlan, model, name, fd, 0);
+    if (!s) {
+        return -1;
+    }
+
+    s->dgram_dst = raddr;
+
+    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
+             "socket: udp=%s:%d",
+             inet_ntoa(raddr.sin_addr), ntohs(raddr.sin_port));
+    return 0;
+}
+
 int net_init_socket(QemuOpts *opts,
                     Monitor *mon,
                     const char *name,
@@ -606,10 +657,32 @@ int net_init_socket(QemuOpts *opts,
         if (net_socket_mcast_init(vlan, "socket", name, mcast, localaddr) == -1) {
             return -1;
         }
+    } else if (qemu_opt_get(opts, "udp")) {
+        const char *udp, *localaddr;
+
+        if (qemu_opt_get(opts, "fd") ||
+            qemu_opt_get(opts, "connect") ||
+            qemu_opt_get(opts, "listen") ||
+            qemu_opt_get(opts, "mcast")) {
+            error_report("fd=, connect=, listen=\
+                         and mcast= is invalid with udp=");
+            return -1;
+        }
+
+        udp = qemu_opt_get(opts, "udp");
+        localaddr = qemu_opt_get(opts, "localaddr");
+        if (localaddr == NULL) {
+                error_report("localaddr= is mandatory with udp=");
+                return -1;
+        }
+
+        if (net_socket_udp_init(vlan, "udp", name, udp, localaddr) == -1) {
+            return -1;
+        }
     } else {
-        error_report("-socket requires fd=, listen=, connect= or mcast=");
+        error_report("-socket requires fd=, listen=, \
+                     connect=, mcast= or udp=");
         return -1;
     }
-
     return 0;
 }
diff --git a/qemu-options.hx b/qemu-options.hx
index 7903e5c..6295cde 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1239,6 +1239,8 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
     "-net socket[,vlan=n][,name=str][,fd=h][,mcast=maddr:port[,localaddr=addr]]\n"
     "                connect the vlan 'n' to multicast maddr and port\n"
     "                use 'localaddr=addr' to specify the host address to send packets from\n"
+    "-net socket[,vlan=n][,name=str][,fd=h][,udp=host:port][,localaddr=host:port]\n"
+    "                connect the vlan 'n' to another VLAN using an UDP tunnel\n"
 #ifdef CONFIG_VDE
     "-net vde[,vlan=n][,name=str][,sock=socketpath][,port=n][,group=groupname][,mode=octalmode]\n"
     "                connect the vlan 'n' to port 'n' of a vde switch running\n"
commit 4aa7534d22aaa48663770a98f989450b0cb34ef0
Author: Lai Jiangshan <laijs at cn.fujitsu.com>
Date:   Thu Jan 12 17:05:35 2012 +0800

    cleanup, save a syscall
    
    Signed-off-by: Lai Jiangshan <laijs at cn.fujitsu.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/main-loop.c b/main-loop.c
index 60e9748..692381c 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -142,14 +142,12 @@ static int qemu_signal_init(void)
      */
     sigemptyset(&set);
     sigaddset(&set, SIG_IPI);
-    pthread_sigmask(SIG_BLOCK, &set, NULL);
-
-    sigemptyset(&set);
     sigaddset(&set, SIGIO);
     sigaddset(&set, SIGALRM);
     sigaddset(&set, SIGBUS);
     pthread_sigmask(SIG_BLOCK, &set, NULL);
 
+    sigdelset(&set, SIG_IPI);
     sigfd = qemu_signalfd(&set);
     if (sigfd == -1) {
         fprintf(stderr, "failed to create signalfd\n");
commit a7d64ddbcccecab7f212f5ef53897ed408727237
Author: Lai Jiangshan <laijs at cn.fujitsu.com>
Date:   Thu Jan 12 17:05:34 2012 +0800

    cleanup, Remove duplicated code
    
    These two blocks of code are exactly the same, remove one.
    
    Signed-off-by: Lai Jiangshan <laijs at cn.fujitsu.com>
    Signed-off-by: Lai Jiangshan <laijs at cn.fujitsu.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/cpus.c b/cpus.c
index b421a71..2dae549 100644
--- a/cpus.c
+++ b/cpus.c
@@ -565,14 +565,6 @@ static void qemu_kvm_init_cpu_signals(CPUState *env)
         fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r));
         exit(1);
     }
-
-    sigdelset(&set, SIG_IPI);
-    sigdelset(&set, SIGBUS);
-    r = kvm_set_signal_mask(env, &set);
-    if (r) {
-        fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r));
-        exit(1);
-    }
 }
 
 static void qemu_tcg_init_cpu_signals(void)
commit ad65aa882c4ed744fc5bae6ccd8630c57251c941
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jan 10 13:10:51 2012 -0600

    test: eliminate libcheck tests and have make check use gtester
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index c1dd42d..2bbc547 100644
--- a/Makefile
+++ b/Makefile
@@ -77,7 +77,7 @@ defconfig:
 
 -include config-all-devices.mak
 
-build-all: $(DOCS) $(TOOLS) $(CHECKS) recurse-all
+build-all: $(DOCS) $(TOOLS) recurse-all
 
 config-host.h: config-host.h-timestamp
 config-host.h-timestamp: config-host.mak
@@ -203,7 +203,7 @@ clean:
 # avoid old build problems by removing potentially incorrect old files
 	rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
 	rm -f qemu-options.def
-	rm -f *.o *.d *.a *.lo $(TOOLS) $(CHECKS) qemu-ga TAGS cscope.* *.pod *~ */*~
+	rm -f *.o *.d *.a *.lo $(TOOLS) qemu-ga TAGS cscope.* *.pod *~ */*~
 	rm -Rf .libs
 	rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d net/*.o net/*.d fsdev/*.o fsdev/*.d ui/*.o ui/*.d qapi/*.o qapi/*.d qga/*.o qga/*.d
 	rm -f qemu-img-cmds.h
diff --git a/configure b/configure
index b2e622c..eb9a01d 100755
--- a/configure
+++ b/configure
@@ -176,7 +176,6 @@ mixemu="no"
 aix="no"
 blobs="yes"
 pkgversion=""
-check_utests=""
 pie=""
 zero_malloc=""
 trace_backend="nop"
@@ -733,10 +732,6 @@ for opt do
   ;;
   --enable-fdt) fdt="yes"
   ;;
-  --disable-check-utests) check_utests="no"
-  ;;
-  --enable-check-utests) check_utests="yes"
-  ;;
   --disable-nptl) nptl="no"
   ;;
   --enable-nptl) nptl="yes"
@@ -1014,8 +1009,6 @@ echo "  --disable-curl           disable curl connectivity"
 echo "  --enable-curl            enable curl connectivity"
 echo "  --disable-fdt            disable fdt device tree"
 echo "  --enable-fdt             enable fdt device tree"
-echo "  --disable-check-utests   disable check unit-tests"
-echo "  --enable-check-utests    enable check unit-tests"
 echo "  --disable-bluez          disable bluez stack connectivity"
 echo "  --enable-bluez           enable bluez stack connectivity"
 echo "  --disable-slirp          disable SLIRP userspace network connectivity"
@@ -1923,26 +1916,6 @@ EOF
 fi # test "$curl"
 
 ##########################################
-# check framework probe
-
-if test "$check_utests" != "no" ; then
-  cat > $TMPC << EOF
-#include <check.h>
-int main(void) { suite_create("qemu test"); return 0; }
-EOF
-  check_libs=`$pkg_config --libs check 2>/dev/null`
-  if compile_prog "" $check_libs ; then
-    check_utests=yes
-    libs_tools="$check_libs $libs_tools"
-  else
-    if test "$check_utests" = "yes" ; then
-      feature_not_found "check"
-    fi
-    check_utests=no
-  fi
-fi # test "$check_utests"
-
-##########################################
 # bluez support probe
 if test "$bluez" != "no" ; then
   cat > $TMPC << EOF
@@ -2799,10 +2772,6 @@ if test "$softmmu" = yes ; then
     if [ "$guest_agent" = "yes" ]; then
       tools="qemu-ga\$(EXESUF) $tools"
     fi
-    if [ "$check_utests" = "yes" ]; then
-      checks="$checks"
-    fi
-    test_progs="$checks check-qdict check-qfloat check-qint check-qstring check-qlist check-qjson test-coroutine test-qmp-output-visitor test-qmp-input-visitor"
   fi
 fi
 
@@ -2856,7 +2825,6 @@ fi
 echo "SDL support       $sdl"
 echo "curses support    $curses"
 echo "curl support      $curl"
-echo "check support     $check_utests"
 echo "mingw32 support   $mingw32"
 echo "Audio drivers     $audio_drv_list"
 echo "Extra audio cards $audio_card_list"
@@ -3274,7 +3242,6 @@ if test "$trace_default" = "yes"; then
 fi
 
 echo "TOOLS=$tools" >> $config_host_mak
-echo "CHECKS=$test_progs" >> $config_host_mak
 echo "ROMS=$roms" >> $config_host_mak
 echo "MAKE=$make" >> $config_host_mak
 echo "INSTALL=$install" >> $config_host_mak
diff --git a/tests/Makefile b/tests/Makefile
index 54c95bc..efde63a 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,3 +1,7 @@
+CHECKS = check-qdict check-qfloat check-qint check-qstring check-qlist
+CHECKS += check-qjson test-qmp-output-visitor test-qmp-input-visitor
+CHECKS += test-coroutine
+
 check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o test-coroutine.o: $(GENERATED_HEADERS)
 
 check-qint: check-qint.o qint.o $(tools-obj-y)
@@ -31,8 +35,5 @@ test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types
 test-qmp-commands: test-qmp-commands.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
 
 .PHONY: check
-check: $(patsubst %,run-check-%,$(CHECKS))
-
-run-check-%: %
-	./$<
-
+check: $(CHECKS)
+	gtester $(CHECKS)
commit 38273e1dee8c7c8ce1f9e79619561f63957577b3
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jan 10 13:10:50 2012 -0600

    check-qjson: enable disabled tests
    
    gtest does the right thing here so there's no need to comment these tests out.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/check-qjson.c b/check-qjson.c
index 430f53b..526e25e 100644
--- a/check-qjson.c
+++ b/check-qjson.c
@@ -678,7 +678,6 @@ static void unterminated_dict_comma(void)
     g_assert(obj == NULL);
 }
 
-#if 0
 static void invalid_dict_comma(void)
 {
     QObject *obj = qobject_from_json("{'abc':32,}");
@@ -690,7 +689,6 @@ static void unterminated_literal(void)
     QObject *obj = qobject_from_json("nul");
     g_assert(obj == NULL);
 }
-#endif
 
 int main(int argc, char **argv)
 {
@@ -723,11 +721,8 @@ int main(int argc, char **argv)
     g_test_add_func("/errors/unterminated/dict", unterminated_dict);
     g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
     g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
-#if 0
-    /* FIXME: this print parse error messages on stderr.  */
     g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
     g_test_add_func("/errors/unterminated/literal", unterminated_literal);
-#endif
 
     return g_test_run();
 }
commit ef76dc59fa5203d146a2acf85a0ad5a5971a4824
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jan 10 13:10:49 2012 -0600

    check-qjson: convert to gtest
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/check-qjson.c b/check-qjson.c
index 36d4ac2..430f53b 100644
--- a/check-qjson.c
+++ b/check-qjson.c
@@ -8,7 +8,7 @@
  * See the COPYING.LIB file in the top-level directory.
  *
  */
-#include <check.h>
+#include <glib.h>
 
 #include "qstring.h"
 #include "qint.h"
@@ -20,7 +20,7 @@
 
 #include "qemu-common.h"
 
-START_TEST(escaped_string)
+static void escaped_string(void)
 {
     int i;
     struct {
@@ -52,28 +52,23 @@ START_TEST(escaped_string)
 
         obj = qobject_from_json(test_cases[i].encoded);
 
-        fail_unless(obj != NULL);
-        fail_unless(qobject_type(obj) == QTYPE_QSTRING);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QSTRING);
         
         str = qobject_to_qstring(obj);
-        fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0,
-                    "%s != %s\n", qstring_get_str(str), test_cases[i].decoded);
+        g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
 
         if (test_cases[i].skip == 0) {
             str = qobject_to_json(obj);
-            fail_unless(strcmp(qstring_get_str(str),test_cases[i].encoded) == 0,
-                        "%s != %s\n", qstring_get_str(str),
-                                      test_cases[i].encoded);
-
+            g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].encoded);
             qobject_decref(obj);
         }
 
         QDECREF(str);
     }
 }
-END_TEST
 
-START_TEST(simple_string)
+static void simple_string(void)
 {
     int i;
     struct {
@@ -92,23 +87,22 @@ START_TEST(simple_string)
 
         obj = qobject_from_json(test_cases[i].encoded);
 
-        fail_unless(obj != NULL);
-        fail_unless(qobject_type(obj) == QTYPE_QSTRING);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QSTRING);
         
         str = qobject_to_qstring(obj);
-        fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
+        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
 
         str = qobject_to_json(obj);
-        fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
+        g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
 
         qobject_decref(obj);
         
         QDECREF(str);
     }
 }
-END_TEST
 
-START_TEST(single_quote_string)
+static void single_quote_string(void)
 {
     int i;
     struct {
@@ -127,18 +121,17 @@ START_TEST(single_quote_string)
 
         obj = qobject_from_json(test_cases[i].encoded);
 
-        fail_unless(obj != NULL);
-        fail_unless(qobject_type(obj) == QTYPE_QSTRING);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QSTRING);
         
         str = qobject_to_qstring(obj);
-        fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
+        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
 
         QDECREF(str);
     }
 }
-END_TEST
 
-START_TEST(vararg_string)
+static void vararg_string(void)
 {
     int i;
     struct {
@@ -155,18 +148,17 @@ START_TEST(vararg_string)
 
         obj = qobject_from_jsonf("%s", test_cases[i].decoded);
 
-        fail_unless(obj != NULL);
-        fail_unless(qobject_type(obj) == QTYPE_QSTRING);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QSTRING);
         
         str = qobject_to_qstring(obj);
-        fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
+        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
 
         QDECREF(str);
     }
 }
-END_TEST
 
-START_TEST(simple_number)
+static void simple_number(void)
 {
     int i;
     struct {
@@ -187,25 +179,24 @@ START_TEST(simple_number)
         QInt *qint;
 
         obj = qobject_from_json(test_cases[i].encoded);
-        fail_unless(obj != NULL);
-        fail_unless(qobject_type(obj) == QTYPE_QINT);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QINT);
 
         qint = qobject_to_qint(obj);
-        fail_unless(qint_get_int(qint) == test_cases[i].decoded);
+        g_assert(qint_get_int(qint) == test_cases[i].decoded);
         if (test_cases[i].skip == 0) {
             QString *str;
 
             str = qobject_to_json(obj);
-            fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
+            g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
             QDECREF(str);
         }
 
         QDECREF(qint);
     }
 }
-END_TEST
 
-START_TEST(float_number)
+static void float_number(void)
 {
     int i;
     struct {
@@ -225,26 +216,25 @@ START_TEST(float_number)
         QFloat *qfloat;
 
         obj = qobject_from_json(test_cases[i].encoded);
-        fail_unless(obj != NULL);
-        fail_unless(qobject_type(obj) == QTYPE_QFLOAT);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QFLOAT);
 
         qfloat = qobject_to_qfloat(obj);
-        fail_unless(qfloat_get_double(qfloat) == test_cases[i].decoded);
+        g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
 
         if (test_cases[i].skip == 0) {
             QString *str;
 
             str = qobject_to_json(obj);
-            fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
+            g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
             QDECREF(str);
         }
 
         QDECREF(qfloat);
     }
 }
-END_TEST
 
-START_TEST(vararg_number)
+static void vararg_number(void)
 {
     QObject *obj;
     QInt *qint;
@@ -254,85 +244,83 @@ START_TEST(vararg_number)
     double valuef = 2.323423423;
 
     obj = qobject_from_jsonf("%d", value);
-    fail_unless(obj != NULL);
-    fail_unless(qobject_type(obj) == QTYPE_QINT);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QINT);
 
     qint = qobject_to_qint(obj);
-    fail_unless(qint_get_int(qint) == value);
+    g_assert(qint_get_int(qint) == value);
 
     QDECREF(qint);
 
     obj = qobject_from_jsonf("%" PRId64, value64);
-    fail_unless(obj != NULL);
-    fail_unless(qobject_type(obj) == QTYPE_QINT);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QINT);
 
     qint = qobject_to_qint(obj);
-    fail_unless(qint_get_int(qint) == value64);
+    g_assert(qint_get_int(qint) == value64);
 
     QDECREF(qint);
 
     obj = qobject_from_jsonf("%f", valuef);
-    fail_unless(obj != NULL);
-    fail_unless(qobject_type(obj) == QTYPE_QFLOAT);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QFLOAT);
 
     qfloat = qobject_to_qfloat(obj);
-    fail_unless(qfloat_get_double(qfloat) == valuef);
+    g_assert(qfloat_get_double(qfloat) == valuef);
 
     QDECREF(qfloat);
 }
-END_TEST
 
-START_TEST(keyword_literal)
+static void keyword_literal(void)
 {
     QObject *obj;
     QBool *qbool;
     QString *str;
 
     obj = qobject_from_json("true");
-    fail_unless(obj != NULL);
-    fail_unless(qobject_type(obj) == QTYPE_QBOOL);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QBOOL);
 
     qbool = qobject_to_qbool(obj);
-    fail_unless(qbool_get_int(qbool) != 0);
+    g_assert(qbool_get_int(qbool) != 0);
 
     str = qobject_to_json(obj);
-    fail_unless(strcmp(qstring_get_str(str), "true") == 0);
+    g_assert(strcmp(qstring_get_str(str), "true") == 0);
     QDECREF(str);
 
     QDECREF(qbool);
 
     obj = qobject_from_json("false");
-    fail_unless(obj != NULL);
-    fail_unless(qobject_type(obj) == QTYPE_QBOOL);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QBOOL);
 
     qbool = qobject_to_qbool(obj);
-    fail_unless(qbool_get_int(qbool) == 0);
+    g_assert(qbool_get_int(qbool) == 0);
 
     str = qobject_to_json(obj);
-    fail_unless(strcmp(qstring_get_str(str), "false") == 0);
+    g_assert(strcmp(qstring_get_str(str), "false") == 0);
     QDECREF(str);
 
     QDECREF(qbool);
 
     obj = qobject_from_jsonf("%i", false);
-    fail_unless(obj != NULL);
-    fail_unless(qobject_type(obj) == QTYPE_QBOOL);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QBOOL);
 
     qbool = qobject_to_qbool(obj);
-    fail_unless(qbool_get_int(qbool) == 0);
+    g_assert(qbool_get_int(qbool) == 0);
 
     QDECREF(qbool);
     
     obj = qobject_from_jsonf("%i", true);
-    fail_unless(obj != NULL);
-    fail_unless(qobject_type(obj) == QTYPE_QBOOL);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QBOOL);
 
     qbool = qobject_to_qbool(obj);
-    fail_unless(qbool_get_int(qbool) != 0);
+    g_assert(qbool_get_int(qbool) != 0);
 
     QDECREF(qbool);
 }
-END_TEST
 
 typedef struct LiteralQDictEntry LiteralQDictEntry;
 typedef struct LiteralQObject LiteralQObject;
@@ -426,7 +414,7 @@ static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
     return 0;
 }
 
-START_TEST(simple_dict)
+static void simple_dict(void)
 {
     int i;
     struct {
@@ -460,26 +448,25 @@ START_TEST(simple_dict)
         QString *str;
 
         obj = qobject_from_json(test_cases[i].encoded);
-        fail_unless(obj != NULL);
-        fail_unless(qobject_type(obj) == QTYPE_QDICT);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QDICT);
 
-        fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
 
         str = qobject_to_json(obj);
         qobject_decref(obj);
 
         obj = qobject_from_json(qstring_get_str(str));
-        fail_unless(obj != NULL);
-        fail_unless(qobject_type(obj) == QTYPE_QDICT);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QDICT);
 
-        fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
         qobject_decref(obj);
         QDECREF(str);
     }
 }
-END_TEST
 
-START_TEST(simple_list)
+static void simple_list(void)
 {
     int i;
     struct {
@@ -524,26 +511,25 @@ START_TEST(simple_list)
         QString *str;
 
         obj = qobject_from_json(test_cases[i].encoded);
-        fail_unless(obj != NULL);
-        fail_unless(qobject_type(obj) == QTYPE_QLIST);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QLIST);
 
-        fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
 
         str = qobject_to_json(obj);
         qobject_decref(obj);
 
         obj = qobject_from_json(qstring_get_str(str));
-        fail_unless(obj != NULL);
-        fail_unless(qobject_type(obj) == QTYPE_QLIST);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QLIST);
 
-        fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
         qobject_decref(obj);
         QDECREF(str);
     }
 }
-END_TEST
 
-START_TEST(simple_whitespace)
+static void simple_whitespace(void)
 {
     int i;
     struct {
@@ -593,27 +579,26 @@ START_TEST(simple_whitespace)
         QString *str;
 
         obj = qobject_from_json(test_cases[i].encoded);
-        fail_unless(obj != NULL);
-        fail_unless(qobject_type(obj) == QTYPE_QLIST);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QLIST);
 
-        fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
 
         str = qobject_to_json(obj);
         qobject_decref(obj);
 
         obj = qobject_from_json(qstring_get_str(str));
-        fail_unless(obj != NULL);
-        fail_unless(qobject_type(obj) == QTYPE_QLIST);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QLIST);
 
-        fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
 
         qobject_decref(obj);
         QDECREF(str);
     }
 }
-END_TEST
 
-START_TEST(simple_varargs)
+static void simple_varargs(void)
 {
     QObject *embedded_obj;
     QObject *obj;
@@ -627,169 +612,122 @@ START_TEST(simple_varargs)
             {}}));
 
     embedded_obj = qobject_from_json("[32, 42]");
-    fail_unless(embedded_obj != NULL);
+    g_assert(embedded_obj != NULL);
 
     obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
-    fail_unless(obj != NULL);
+    g_assert(obj != NULL);
 
-    fail_unless(compare_litqobj_to_qobj(&decoded, obj) == 1);
+    g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
 
     qobject_decref(obj);
 }
-END_TEST
 
-START_TEST(empty_input)
+static void empty_input(void)
 {
     const char *empty = "";
 
     QObject *obj = qobject_from_json(empty);
-    fail_unless(obj == NULL);
+    g_assert(obj == NULL);
 }
-END_TEST
 
-START_TEST(unterminated_string)
+static void unterminated_string(void)
 {
     QObject *obj = qobject_from_json("\"abc");
-    fail_unless(obj == NULL);
+    g_assert(obj == NULL);
 }
-END_TEST
 
-START_TEST(unterminated_sq_string)
+static void unterminated_sq_string(void)
 {
     QObject *obj = qobject_from_json("'abc");
-    fail_unless(obj == NULL);
+    g_assert(obj == NULL);
 }
-END_TEST
 
-START_TEST(unterminated_escape)
+static void unterminated_escape(void)
 {
     QObject *obj = qobject_from_json("\"abc\\\"");
-    fail_unless(obj == NULL);
+    g_assert(obj == NULL);
 }
-END_TEST
 
-START_TEST(unterminated_array)
+static void unterminated_array(void)
 {
     QObject *obj = qobject_from_json("[32");
-    fail_unless(obj == NULL);
+    g_assert(obj == NULL);
 }
-END_TEST
 
-START_TEST(unterminated_array_comma)
+static void unterminated_array_comma(void)
 {
     QObject *obj = qobject_from_json("[32,");
-    fail_unless(obj == NULL);
+    g_assert(obj == NULL);
 }
-END_TEST
 
-START_TEST(invalid_array_comma)
+static void invalid_array_comma(void)
 {
     QObject *obj = qobject_from_json("[32,}");
-    fail_unless(obj == NULL);
+    g_assert(obj == NULL);
 }
-END_TEST
 
-START_TEST(unterminated_dict)
+static void unterminated_dict(void)
 {
     QObject *obj = qobject_from_json("{'abc':32");
-    fail_unless(obj == NULL);
+    g_assert(obj == NULL);
 }
-END_TEST
 
-START_TEST(unterminated_dict_comma)
+static void unterminated_dict_comma(void)
 {
     QObject *obj = qobject_from_json("{'abc':32,");
-    fail_unless(obj == NULL);
+    g_assert(obj == NULL);
 }
-END_TEST
 
 #if 0
-START_TEST(invalid_dict_comma)
+static void invalid_dict_comma(void)
 {
     QObject *obj = qobject_from_json("{'abc':32,}");
-    fail_unless(obj == NULL);
+    g_assert(obj == NULL);
 }
-END_TEST
 
-START_TEST(unterminated_literal)
+static void unterminated_literal(void)
 {
     QObject *obj = qobject_from_json("nul");
-    fail_unless(obj == NULL);
+    g_assert(obj == NULL);
 }
-END_TEST
 #endif
 
-static Suite *qjson_suite(void)
+int main(int argc, char **argv)
 {
-    Suite *suite;
-    TCase *string_literals, *number_literals, *keyword_literals;
-    TCase *dicts, *lists, *whitespace, *varargs, *errors;
-
-    string_literals = tcase_create("String Literals");
-    tcase_add_test(string_literals, simple_string);
-    tcase_add_test(string_literals, escaped_string);
-    tcase_add_test(string_literals, single_quote_string);
-    tcase_add_test(string_literals, vararg_string);
-
-    number_literals = tcase_create("Number Literals");
-    tcase_add_test(number_literals, simple_number);
-    tcase_add_test(number_literals, float_number);
-    tcase_add_test(number_literals, vararg_number);
-
-    keyword_literals = tcase_create("Keywords");
-    tcase_add_test(keyword_literals, keyword_literal);
-    dicts = tcase_create("Objects");
-    tcase_add_test(dicts, simple_dict);
-    lists = tcase_create("Lists");
-    tcase_add_test(lists, simple_list);
-
-    whitespace = tcase_create("Whitespace");
-    tcase_add_test(whitespace, simple_whitespace);
-
-    varargs = tcase_create("Varargs");
-    tcase_add_test(varargs, simple_varargs);
-
-    errors = tcase_create("Invalid JSON");
-    tcase_add_test(errors, empty_input);
-    tcase_add_test(errors, unterminated_string);
-    tcase_add_test(errors, unterminated_escape);
-    tcase_add_test(errors, unterminated_sq_string);
-    tcase_add_test(errors, unterminated_array);
-    tcase_add_test(errors, unterminated_array_comma);
-    tcase_add_test(errors, invalid_array_comma);
-    tcase_add_test(errors, unterminated_dict);
-    tcase_add_test(errors, unterminated_dict_comma);
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/literals/string/simple", simple_string);
+    g_test_add_func("/literals/string/escaped", escaped_string);
+    g_test_add_func("/literals/string/single_quote", single_quote_string);
+    g_test_add_func("/literals/string/vararg", vararg_string);
+
+    g_test_add_func("/literals/number/simple", simple_number);
+    g_test_add_func("/literals/number/float", float_number);
+    g_test_add_func("/literals/number/vararg", vararg_number);
+
+    g_test_add_func("/literals/keyword", keyword_literal);
+
+    g_test_add_func("/dicts/simple_dict", simple_dict);
+    g_test_add_func("/lists/simple_list", simple_list);
+
+    g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
+
+    g_test_add_func("/varargs/simple_varargs", simple_varargs);
+
+    g_test_add_func("/errors/empty_input", empty_input);
+    g_test_add_func("/errors/unterminated/string", unterminated_string);
+    g_test_add_func("/errors/unterminated/escape", unterminated_escape);
+    g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
+    g_test_add_func("/errors/unterminated/array", unterminated_array);
+    g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
+    g_test_add_func("/errors/unterminated/dict", unterminated_dict);
+    g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
+    g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
 #if 0
     /* FIXME: this print parse error messages on stderr.  */
-    tcase_add_test(errors, invalid_dict_comma);
-    tcase_add_test(errors, unterminated_literal);
+    g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
+    g_test_add_func("/errors/unterminated/literal", unterminated_literal);
 #endif
 
-    suite = suite_create("QJSON test-suite");
-    suite_add_tcase(suite, string_literals);
-    suite_add_tcase(suite, number_literals);
-    suite_add_tcase(suite, keyword_literals);
-    suite_add_tcase(suite, dicts);
-    suite_add_tcase(suite, lists);
-    suite_add_tcase(suite, whitespace);
-    suite_add_tcase(suite, varargs);
-    suite_add_tcase(suite, errors);
-
-    return suite;
-}
-
-int main(void)
-{
-    int nf;
-    Suite *s;
-    SRunner *sr;
-
-    s = qjson_suite();
-    sr = srunner_create(s);
-        
-    srunner_run_all(sr, CK_NORMAL);
-    nf = srunner_ntests_failed(sr);
-    srunner_free(sr);
-    
-    return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+    return g_test_run();
 }
diff --git a/configure b/configure
index 2ab7d6f..b2e622c 100755
--- a/configure
+++ b/configure
@@ -2800,9 +2800,9 @@ if test "$softmmu" = yes ; then
       tools="qemu-ga\$(EXESUF) $tools"
     fi
     if [ "$check_utests" = "yes" ]; then
-      checks="check-qjson $checks"
+      checks="$checks"
     fi
-    test_progs="$checks check-qdict check-qfloat check-qint check-qstring check-qlist test-coroutine test-qmp-output-visitor test-qmp-input-visitor"
+    test_progs="$checks check-qdict check-qfloat check-qint check-qstring check-qlist check-qjson test-coroutine test-qmp-output-visitor test-qmp-input-visitor"
   fi
 fi
 
commit 91479dd0b5bd3b087b92ddd7bc3f2c54982cfe17
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jan 10 13:10:48 2012 -0600

    check-qlist: convert to gtest
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/check-qlist.c b/check-qlist.c
index ee2454a..501ba26 100644
--- a/check-qlist.c
+++ b/check-qlist.c
@@ -9,7 +9,7 @@
  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
  * See the COPYING.LIB file in the top-level directory.
  */
-#include <check.h>
+#include <glib.h>
 
 #include "qint.h"
 #include "qlist.h"
@@ -20,21 +20,20 @@
  * (with some violations to access 'private' data)
  */
 
-START_TEST(qlist_new_test)
+static void qlist_new_test(void)
 {
     QList *qlist;
 
     qlist = qlist_new();
-    fail_unless(qlist != NULL);
-    fail_unless(qlist->base.refcnt == 1);
-    fail_unless(qobject_type(QOBJECT(qlist)) == QTYPE_QLIST);
+    g_assert(qlist != NULL);
+    g_assert(qlist->base.refcnt == 1);
+    g_assert(qobject_type(QOBJECT(qlist)) == QTYPE_QLIST);
 
     // destroy doesn't exist yet
     g_free(qlist);
 }
-END_TEST
 
-START_TEST(qlist_append_test)
+static void qlist_append_test(void)
 {
     QInt *qi;
     QList *qlist;
@@ -46,30 +45,28 @@ START_TEST(qlist_append_test)
     qlist_append(qlist, qi);
 
     entry = QTAILQ_FIRST(&qlist->head);
-    fail_unless(entry != NULL);
-    fail_unless(entry->value == QOBJECT(qi));
+    g_assert(entry != NULL);
+    g_assert(entry->value == QOBJECT(qi));
 
     // destroy doesn't exist yet
     QDECREF(qi);
     g_free(entry);
     g_free(qlist);
 }
-END_TEST
 
-START_TEST(qobject_to_qlist_test)
+static void qobject_to_qlist_test(void)
 {
     QList *qlist;
 
     qlist = qlist_new();
 
-    fail_unless(qobject_to_qlist(QOBJECT(qlist)) == qlist);
+    g_assert(qobject_to_qlist(QOBJECT(qlist)) == qlist);
 
     // destroy doesn't exist yet
     g_free(qlist);
 }
-END_TEST
 
-START_TEST(qlist_destroy_test)
+static void qlist_destroy_test(void)
 {
     int i;
     QList *qlist;
@@ -81,7 +78,6 @@ START_TEST(qlist_destroy_test)
 
     QDECREF(qlist);
 }
-END_TEST
 
 static int iter_called;
 static const int iter_max = 42;
@@ -90,16 +86,16 @@ static void iter_func(QObject *obj, void *opaque)
 {
     QInt *qi;
 
-    fail_unless(opaque == NULL);
+    g_assert(opaque == NULL);
 
     qi = qobject_to_qint(obj);
-    fail_unless(qi != NULL);
-    fail_unless((qint_get_int(qi) >= 0) && (qint_get_int(qi) <= iter_max));
+    g_assert(qi != NULL);
+    g_assert((qint_get_int(qi) >= 0) && (qint_get_int(qi) <= iter_max));
 
     iter_called++;
 }
 
-START_TEST(qlist_iter_test)
+static void qlist_iter_test(void)
 {
     int i;
     QList *qlist;
@@ -112,42 +108,20 @@ START_TEST(qlist_iter_test)
     iter_called = 0;
     qlist_iter(qlist, iter_func, NULL);
 
-    fail_unless(iter_called == iter_max);
+    g_assert(iter_called == iter_max);
 
     QDECREF(qlist);
 }
-END_TEST
 
-static Suite *QList_suite(void)
+int main(int argc, char **argv)
 {
-    Suite *s;
-    TCase *qlist_public_tcase;
+    g_test_init(&argc, &argv, NULL);
 
-    s = suite_create("QList suite");
+    g_test_add_func("/public/new", qlist_new_test);
+    g_test_add_func("/public/append", qlist_append_test);
+    g_test_add_func("/public/to_qlist", qobject_to_qlist_test);
+    g_test_add_func("/public/destroy", qlist_destroy_test);
+    g_test_add_func("/public/iter", qlist_iter_test);
 
-    qlist_public_tcase = tcase_create("Public Interface");
-    suite_add_tcase(s, qlist_public_tcase);
-    tcase_add_test(qlist_public_tcase, qlist_new_test);
-    tcase_add_test(qlist_public_tcase, qlist_append_test);
-    tcase_add_test(qlist_public_tcase, qobject_to_qlist_test);
-    tcase_add_test(qlist_public_tcase, qlist_destroy_test);
-    tcase_add_test(qlist_public_tcase, qlist_iter_test);
-
-    return s;
-}
-
-int main(void)
-{
-	int nf;
-	Suite *s;
-	SRunner *sr;
-
-	s = QList_suite();
-	sr = srunner_create(s);
-
-	srunner_run_all(sr, CK_NORMAL);
-	nf = srunner_ntests_failed(sr);
-	srunner_free(sr);
-
-	return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+    return g_test_run();
 }
diff --git a/configure b/configure
index 18f06ba..2ab7d6f 100755
--- a/configure
+++ b/configure
@@ -2800,10 +2800,9 @@ if test "$softmmu" = yes ; then
       tools="qemu-ga\$(EXESUF) $tools"
     fi
     if [ "$check_utests" = "yes" ]; then
-      checks="check-qlist"
       checks="check-qjson $checks"
     fi
-    test_progs="$checks check-qdict check-qfloat check-qint check-qstring test-coroutine test-qmp-output-visitor test-qmp-input-visitor"
+    test_progs="$checks check-qdict check-qfloat check-qint check-qstring check-qlist test-coroutine test-qmp-output-visitor test-qmp-input-visitor"
   fi
 fi
 
commit 0ac7cc2af500b948510f2481c22e84a57b0a2447
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jan 10 13:10:47 2012 -0600

    check-qstring: convert to gtest
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/check-qstring.c b/check-qstring.c
index 93bd475..681bb68 100644
--- a/check-qstring.c
+++ b/check-qstring.c
@@ -20,31 +20,29 @@
  * (with some violations to access 'private' data)
  */
 
-START_TEST(qstring_from_str_test)
+static void qstring_from_str_test(void)
 {
     QString *qstring;
     const char *str = "QEMU";
 
     qstring = qstring_from_str(str);
-    fail_unless(qstring != NULL);
-    fail_unless(qstring->base.refcnt == 1);
-    fail_unless(strcmp(str, qstring->string) == 0);
-    fail_unless(qobject_type(QOBJECT(qstring)) == QTYPE_QSTRING);
+    g_assert(qstring != NULL);
+    g_assert(qstring->base.refcnt == 1);
+    g_assert(strcmp(str, qstring->string) == 0);
+    g_assert(qobject_type(QOBJECT(qstring)) == QTYPE_QSTRING);
 
     // destroy doesn't exit yet
     g_free(qstring->string);
     g_free(qstring);
 }
-END_TEST
 
-START_TEST(qstring_destroy_test)
+static void qstring_destroy_test(void)
 {
     QString *qstring = qstring_from_str("destroy test");
     QDECREF(qstring);
 }
-END_TEST
 
-START_TEST(qstring_get_str_test)
+static void qstring_get_str_test(void)
 {
     QString *qstring;
     const char *ret_str;
@@ -52,13 +50,12 @@ START_TEST(qstring_get_str_test)
 
     qstring = qstring_from_str(str);
     ret_str = qstring_get_str(qstring);
-    fail_unless(strcmp(ret_str, str) == 0);
+    g_assert(strcmp(ret_str, str) == 0);
 
     QDECREF(qstring);
 }
-END_TEST
 
-START_TEST(qstring_append_chr_test)
+static void qstring_append_chr_test(void)
 {
     int i;
     QString *qstring;
@@ -69,66 +66,42 @@ START_TEST(qstring_append_chr_test)
     for (i = 0; str[i]; i++)
         qstring_append_chr(qstring, str[i]);
 
-    fail_unless(strcmp(str, qstring_get_str(qstring)) == 0);
+    g_assert(strcmp(str, qstring_get_str(qstring)) == 0);
     QDECREF(qstring);
 }
-END_TEST
 
-START_TEST(qstring_from_substr_test)
+static void qstring_from_substr_test(void)
 {
     QString *qs;
 
     qs = qstring_from_substr("virtualization", 3, 9);
-    fail_unless(qs != NULL);
-    fail_unless(strcmp(qstring_get_str(qs), "tualiza") == 0);
+    g_assert(qs != NULL);
+    g_assert(strcmp(qstring_get_str(qs), "tualiza") == 0);
 
     QDECREF(qs);
 }
-END_TEST
 
 
-START_TEST(qobject_to_qstring_test)
+static void qobject_to_qstring_test(void)
 {
     QString *qstring;
 
     qstring = qstring_from_str("foo");
-    fail_unless(qobject_to_qstring(QOBJECT(qstring)) == qstring);
+    g_assert(qobject_to_qstring(QOBJECT(qstring)) == qstring);
 
     QDECREF(qstring);
 }
-END_TEST
 
-static Suite *qstring_suite(void)
+int main(int argc, char **argv)
 {
-    Suite *s;
-    TCase *qstring_public_tcase;
+    g_test_init(&argc, &argv, NULL);
 
-    s = suite_create("QString test-suite");
+    g_test_add_func("/public/from_str", qstring_from_str_test);
+    g_test_add_func("/public/destroy", qstring_destroy_test);
+    g_test_add_func("/public/get_str", qstring_get_str_test);
+    g_test_add_func("/public/append_chr", qstring_append_chr_test);
+    g_test_add_func("/public/from_substr", qstring_from_substr_test);
+    g_test_add_func("/public/to_qstring", qobject_to_qstring_test);
 
-    qstring_public_tcase = tcase_create("Public Interface");
-    suite_add_tcase(s, qstring_public_tcase);
-    tcase_add_test(qstring_public_tcase, qstring_from_str_test);
-    tcase_add_test(qstring_public_tcase, qstring_destroy_test);
-    tcase_add_test(qstring_public_tcase, qstring_get_str_test);
-    tcase_add_test(qstring_public_tcase, qstring_append_chr_test);
-    tcase_add_test(qstring_public_tcase, qstring_from_substr_test);
-    tcase_add_test(qstring_public_tcase, qobject_to_qstring_test);
-
-    return s;
-}
-
-int main(void)
-{
-	int nf;
-	Suite *s;
-	SRunner *sr;
-
-	s = qstring_suite();
-	sr = srunner_create(s);
-
-	srunner_run_all(sr, CK_NORMAL);
-	nf = srunner_ntests_failed(sr);
-	srunner_free(sr);
-
-	return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+    return g_test_run();
 }
diff --git a/configure b/configure
index cea9cb6..18f06ba 100755
--- a/configure
+++ b/configure
@@ -2800,10 +2800,10 @@ if test "$softmmu" = yes ; then
       tools="qemu-ga\$(EXESUF) $tools"
     fi
     if [ "$check_utests" = "yes" ]; then
-      checks="check-qstring check-qlist"
+      checks="check-qlist"
       checks="check-qjson $checks"
     fi
-    test_progs="$checks check-qdict check-qfloat check-qint test-coroutine test-qmp-output-visitor test-qmp-input-visitor"
+    test_progs="$checks check-qdict check-qfloat check-qint check-qstring test-coroutine test-qmp-output-visitor test-qmp-input-visitor"
   fi
 fi
 
commit 65cdadd2e2de76f7db3bf6b7d8dd8c67abff9659
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jan 10 13:10:46 2012 -0600

    check-qint: convert to gtest
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/check-qint.c b/check-qint.c
index 3af51f2..5a27119 100644
--- a/check-qint.c
+++ b/check-qint.c
@@ -9,7 +9,7 @@
  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
  * See the COPYING.LIB file in the top-level directory.
  */
-#include <check.h>
+#include <glib.h>
 
 #include "qint.h"
 #include "qemu-common.h"
@@ -20,94 +20,68 @@
  * (with some violations to access 'private' data)
  */
 
-START_TEST(qint_from_int_test)
+static void qint_from_int_test(void)
 {
     QInt *qi;
     const int value = -42;
 
     qi = qint_from_int(value);
-    fail_unless(qi != NULL);
-    fail_unless(qi->value == value);
-    fail_unless(qi->base.refcnt == 1);
-    fail_unless(qobject_type(QOBJECT(qi)) == QTYPE_QINT);
+    g_assert(qi != NULL);
+    g_assert(qi->value == value);
+    g_assert(qi->base.refcnt == 1);
+    g_assert(qobject_type(QOBJECT(qi)) == QTYPE_QINT);
 
     // destroy doesn't exit yet
     g_free(qi);
 }
-END_TEST
 
-START_TEST(qint_destroy_test)
+static void qint_destroy_test(void)
 {
     QInt *qi = qint_from_int(0);
     QDECREF(qi);
 }
-END_TEST
 
-START_TEST(qint_from_int64_test)
+static void qint_from_int64_test(void)
 {
     QInt *qi;
     const int64_t value = 0x1234567890abcdefLL;
 
     qi = qint_from_int(value);
-    fail_unless((int64_t) qi->value == value);
+    g_assert((int64_t) qi->value == value);
 
     QDECREF(qi);
 }
-END_TEST
 
-START_TEST(qint_get_int_test)
+static void qint_get_int_test(void)
 {
     QInt *qi;
     const int value = 123456;
 
     qi = qint_from_int(value);
-    fail_unless(qint_get_int(qi) == value);
+    g_assert(qint_get_int(qi) == value);
 
     QDECREF(qi);
 }
-END_TEST
 
-START_TEST(qobject_to_qint_test)
+static void qobject_to_qint_test(void)
 {
     QInt *qi;
 
     qi = qint_from_int(0);
-    fail_unless(qobject_to_qint(QOBJECT(qi)) == qi);
+    g_assert(qobject_to_qint(QOBJECT(qi)) == qi);
 
     QDECREF(qi);
 }
-END_TEST
 
-static Suite *qint_suite(void)
+int main(int argc, char **argv)
 {
-    Suite *s;
-    TCase *qint_public_tcase;
+    g_test_init(&argc, &argv, NULL);
 
-    s = suite_create("QInt test-suite");
+    g_test_add_func("/public/from_int", qint_from_int_test);
+    g_test_add_func("/public/destroy", qint_destroy_test);
+    g_test_add_func("/public/from_int64", qint_from_int64_test);
+    g_test_add_func("/public/get_int", qint_get_int_test);
+    g_test_add_func("/public/to_qint", qobject_to_qint_test);
 
-    qint_public_tcase = tcase_create("Public Interface");
-    suite_add_tcase(s, qint_public_tcase);
-    tcase_add_test(qint_public_tcase, qint_from_int_test);
-    tcase_add_test(qint_public_tcase, qint_destroy_test);
-    tcase_add_test(qint_public_tcase, qint_from_int64_test);
-    tcase_add_test(qint_public_tcase, qint_get_int_test);
-    tcase_add_test(qint_public_tcase, qobject_to_qint_test);
-
-    return s;
-}
-
-int main(void)
-{
-	int nf;
-	Suite *s;
-	SRunner *sr;
-
-	s = qint_suite();
-	sr = srunner_create(s);
-
-	srunner_run_all(sr, CK_NORMAL);
-	nf = srunner_ntests_failed(sr);
-	srunner_free(sr);
-
-	return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+    return g_test_run();
 }
diff --git a/configure b/configure
index a7a6758..cea9cb6 100755
--- a/configure
+++ b/configure
@@ -2800,10 +2800,10 @@ if test "$softmmu" = yes ; then
       tools="qemu-ga\$(EXESUF) $tools"
     fi
     if [ "$check_utests" = "yes" ]; then
-      checks="check-qint check-qstring check-qlist"
+      checks="check-qstring check-qlist"
       checks="check-qjson $checks"
     fi
-    test_progs="$checks check-qdict check-qfloat test-coroutine test-qmp-output-visitor test-qmp-input-visitor"
+    test_progs="$checks check-qdict check-qfloat check-qint test-coroutine test-qmp-output-visitor test-qmp-input-visitor"
   fi
 fi
 
commit a9e1c28ddaae5a48415fec1f336b5560eb85d3e1
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jan 10 13:10:45 2012 -0600

    check-qfloat: convert to gtest
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/check-qfloat.c b/check-qfloat.c
index 3344057..cdc66ea 100644
--- a/check-qfloat.c
+++ b/check-qfloat.c
@@ -10,7 +10,7 @@
  * See the COPYING.LIB file in the top-level directory.
  *
  */
-#include <check.h>
+#include <glib.h>
 
 #include "qfloat.h"
 #include "qemu-common.h"
@@ -21,56 +21,33 @@
  * (with some violations to access 'private' data)
  */
 
-START_TEST(qfloat_from_double_test)
+static void qfloat_from_double_test(void)
 {
     QFloat *qf;
     const double value = -42.23423;
 
     qf = qfloat_from_double(value);
-    fail_unless(qf != NULL);
-    fail_unless(qf->value == value);
-    fail_unless(qf->base.refcnt == 1);
-    fail_unless(qobject_type(QOBJECT(qf)) == QTYPE_QFLOAT);
+    g_assert(qf != NULL);
+    g_assert(qf->value == value);
+    g_assert(qf->base.refcnt == 1);
+    g_assert(qobject_type(QOBJECT(qf)) == QTYPE_QFLOAT);
 
     // destroy doesn't exit yet
     g_free(qf);
 }
-END_TEST
 
-START_TEST(qfloat_destroy_test)
+static void qfloat_destroy_test(void)
 {
     QFloat *qf = qfloat_from_double(0.0);
     QDECREF(qf);
 }
-END_TEST
 
-static Suite *qfloat_suite(void)
+int main(int argc, char **argv)
 {
-    Suite *s;
-    TCase *qfloat_public_tcase;
+    g_test_init(&argc, &argv, NULL);
 
-    s = suite_create("QFloat test-suite");
+    g_test_add_func("/public/from_double", qfloat_from_double_test);
+    g_test_add_func("/public/destroy", qfloat_destroy_test);
 
-    qfloat_public_tcase = tcase_create("Public Interface");
-    suite_add_tcase(s, qfloat_public_tcase);
-    tcase_add_test(qfloat_public_tcase, qfloat_from_double_test);
-    tcase_add_test(qfloat_public_tcase, qfloat_destroy_test);
-
-    return s;
-}
-
-int main(void)
-{
-    int nf;
-    Suite *s;
-    SRunner *sr;
-
-    s = qfloat_suite();
-    sr = srunner_create(s);
-
-    srunner_run_all(sr, CK_NORMAL);
-    nf = srunner_ntests_failed(sr);
-    srunner_free(sr);
-
-    return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+    return g_test_run();
 }
diff --git a/configure b/configure
index 7e3f28f..a7a6758 100755
--- a/configure
+++ b/configure
@@ -2801,9 +2801,9 @@ if test "$softmmu" = yes ; then
     fi
     if [ "$check_utests" = "yes" ]; then
       checks="check-qint check-qstring check-qlist"
-      checks="check-qfloat check-qjson $checks"
+      checks="check-qjson $checks"
     fi
-    test_progs="$checks check-qdict test-coroutine test-qmp-output-visitor test-qmp-input-visitor"
+    test_progs="$checks check-qdict check-qfloat test-coroutine test-qmp-output-visitor test-qmp-input-visitor"
   fi
 fi
 
commit ac531cb6e542b1e61d668604adf9dc5306a948c0
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jan 10 13:10:44 2012 -0600

    check-qdict: convert to gtest
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/check-qdict.c b/check-qdict.c
index 5515773..fc0d276 100644
--- a/check-qdict.c
+++ b/check-qdict.c
@@ -9,7 +9,7 @@
  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
  * See the COPYING.LIB file in the top-level directory.
  */
-#include <check.h>
+#include <glib.h>
 
 #include "qint.h"
 #include "qdict.h"
@@ -22,22 +22,21 @@
  * (with some violations to access 'private' data)
  */
 
-START_TEST(qdict_new_test)
+static void qdict_new_test(void)
 {
     QDict *qdict;
 
     qdict = qdict_new();
-    fail_unless(qdict != NULL);
-    fail_unless(qdict_size(qdict) == 0);
-    fail_unless(qdict->base.refcnt == 1);
-    fail_unless(qobject_type(QOBJECT(qdict)) == QTYPE_QDICT);
+    g_assert(qdict != NULL);
+    g_assert(qdict_size(qdict) == 0);
+    g_assert(qdict->base.refcnt == 1);
+    g_assert(qobject_type(QOBJECT(qdict)) == QTYPE_QDICT);
 
     // destroy doesn't exit yet
-    free(qdict);
+    g_free(qdict);
 }
-END_TEST
 
-START_TEST(qdict_put_obj_test)
+static void qdict_put_obj_test(void)
 {
     QInt *qi;
     QDict *qdict;
@@ -49,10 +48,10 @@ START_TEST(qdict_put_obj_test)
     // key "" will have tdb hash 12345
     qdict_put_obj(qdict, "", QOBJECT(qint_from_int(num)));
 
-    fail_unless(qdict_size(qdict) == 1);
+    g_assert(qdict_size(qdict) == 1);
     ent = QLIST_FIRST(&qdict->table[12345 % QDICT_BUCKET_MAX]);
     qi = qobject_to_qint(ent->value);
-    fail_unless(qint_get_int(qi) == num);
+    g_assert(qint_get_int(qi) == num);
 
     // destroy doesn't exit yet
     QDECREF(qi);
@@ -60,9 +59,8 @@ START_TEST(qdict_put_obj_test)
     g_free(ent);
     g_free(qdict);
 }
-END_TEST
 
-START_TEST(qdict_destroy_simple_test)
+static void qdict_destroy_simple_test(void)
 {
     QDict *qdict;
 
@@ -72,134 +70,138 @@ START_TEST(qdict_destroy_simple_test)
 
     QDECREF(qdict);
 }
-END_TEST
-
-static QDict *tests_dict = NULL;
-
-static void qdict_setup(void)
-{
-    tests_dict = qdict_new();
-    fail_unless(tests_dict != NULL);
-}
 
-static void qdict_teardown(void)
-{
-    QDECREF(tests_dict);
-    tests_dict = NULL;
-}
-
-START_TEST(qdict_get_test)
+static void qdict_get_test(void)
 {
     QInt *qi;
     QObject *obj;
     const int value = -42;
     const char *key = "test";
+    QDict *tests_dict = qdict_new();
 
     qdict_put(tests_dict, key, qint_from_int(value));
 
     obj = qdict_get(tests_dict, key);
-    fail_unless(obj != NULL);
+    g_assert(obj != NULL);
 
     qi = qobject_to_qint(obj);
-    fail_unless(qint_get_int(qi) == value);
+    g_assert(qint_get_int(qi) == value);
+
+    QDECREF(tests_dict);
 }
-END_TEST
 
-START_TEST(qdict_get_int_test)
+static void qdict_get_int_test(void)
 {
     int ret;
     const int value = 100;
     const char *key = "int";
+    QDict *tests_dict = qdict_new();
 
     qdict_put(tests_dict, key, qint_from_int(value));
 
     ret = qdict_get_int(tests_dict, key);
-    fail_unless(ret == value);
+    g_assert(ret == value);
+
+    QDECREF(tests_dict);
 }
-END_TEST
 
-START_TEST(qdict_get_try_int_test)
+static void qdict_get_try_int_test(void)
 {
     int ret;
     const int value = 100;
     const char *key = "int";
+    QDict *tests_dict = qdict_new();
 
     qdict_put(tests_dict, key, qint_from_int(value));
 
     ret = qdict_get_try_int(tests_dict, key, 0);
-    fail_unless(ret == value);
+    g_assert(ret == value);
+
+    QDECREF(tests_dict);
 }
-END_TEST
 
-START_TEST(qdict_get_str_test)
+static void qdict_get_str_test(void)
 {
     const char *p;
     const char *key = "key";
     const char *str = "string";
+    QDict *tests_dict = qdict_new();
 
     qdict_put(tests_dict, key, qstring_from_str(str));
 
     p = qdict_get_str(tests_dict, key);
-    fail_unless(p != NULL);
-    fail_unless(strcmp(p, str) == 0);
+    g_assert(p != NULL);
+    g_assert(strcmp(p, str) == 0);
+
+    QDECREF(tests_dict);
 }
-END_TEST
 
-START_TEST(qdict_get_try_str_test)
+static void qdict_get_try_str_test(void)
 {
     const char *p;
     const char *key = "key";
     const char *str = "string";
+    QDict *tests_dict = qdict_new();
 
     qdict_put(tests_dict, key, qstring_from_str(str));
 
     p = qdict_get_try_str(tests_dict, key);
-    fail_unless(p != NULL);
-    fail_unless(strcmp(p, str) == 0);
+    g_assert(p != NULL);
+    g_assert(strcmp(p, str) == 0);
+
+    QDECREF(tests_dict);
 }
-END_TEST
 
-START_TEST(qdict_haskey_not_test)
+static void qdict_haskey_not_test(void)
 {
-    fail_unless(qdict_haskey(tests_dict, "test") == 0);
+    QDict *tests_dict = qdict_new();
+    g_assert(qdict_haskey(tests_dict, "test") == 0);
+
+    QDECREF(tests_dict);
 }
-END_TEST
 
-START_TEST(qdict_haskey_test)
+static void qdict_haskey_test(void)
 {
     const char *key = "test";
+    QDict *tests_dict = qdict_new();
 
     qdict_put(tests_dict, key, qint_from_int(0));
-    fail_unless(qdict_haskey(tests_dict, key) == 1);
+    g_assert(qdict_haskey(tests_dict, key) == 1);
+
+    QDECREF(tests_dict);
 }
-END_TEST
 
-START_TEST(qdict_del_test)
+static void qdict_del_test(void)
 {
     const char *key = "key test";
+    QDict *tests_dict = qdict_new();
 
     qdict_put(tests_dict, key, qstring_from_str("foo"));
-    fail_unless(qdict_size(tests_dict) == 1);
+    g_assert(qdict_size(tests_dict) == 1);
 
     qdict_del(tests_dict, key);
 
-    fail_unless(qdict_size(tests_dict) == 0);
-    fail_unless(qdict_haskey(tests_dict, key) == 0);
+    g_assert(qdict_size(tests_dict) == 0);
+    g_assert(qdict_haskey(tests_dict, key) == 0);
+
+    QDECREF(tests_dict);
 }
-END_TEST
 
-START_TEST(qobject_to_qdict_test)
+static void qobject_to_qdict_test(void)
 {
-    fail_unless(qobject_to_qdict(QOBJECT(tests_dict)) == tests_dict);
+    QDict *tests_dict = qdict_new();
+    g_assert(qobject_to_qdict(QOBJECT(tests_dict)) == tests_dict);
+
+    QDECREF(tests_dict);
 }
-END_TEST
 
-START_TEST(qdict_iterapi_test)
+static void qdict_iterapi_test(void)
 {
     int count;
     const QDictEntry *ent;
+    QDict *tests_dict = qdict_new();
 
-    fail_unless(qdict_first(tests_dict) == NULL);
+    g_assert(qdict_first(tests_dict) == NULL);
 
     qdict_put(tests_dict, "key1", qint_from_int(1));
     qdict_put(tests_dict, "key2", qint_from_int(2));
@@ -207,47 +209,52 @@ START_TEST(qdict_iterapi_test)
 
     count = 0;
     for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
-        fail_unless(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
+        g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
         count++;
     }
 
-    fail_unless(count == qdict_size(tests_dict));
+    g_assert(count == qdict_size(tests_dict));
 
     /* Do it again to test restarting */
     count = 0;
     for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
-        fail_unless(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
+        g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
         count++;
     }
 
-    fail_unless(count == qdict_size(tests_dict));
+    g_assert(count == qdict_size(tests_dict));
+
+    QDECREF(tests_dict);
 }
-END_TEST
 
 /*
  * Errors test-cases
  */
 
-START_TEST(qdict_put_exists_test)
+static void qdict_put_exists_test(void)
 {
     int value;
     const char *key = "exists";
+    QDict *tests_dict = qdict_new();
 
     qdict_put(tests_dict, key, qint_from_int(1));
     qdict_put(tests_dict, key, qint_from_int(2));
 
     value = qdict_get_int(tests_dict, key);
-    fail_unless(value == 2);
+    g_assert(value == 2);
 
-    fail_unless(qdict_size(tests_dict) == 1);
+    g_assert(qdict_size(tests_dict) == 1);
+
+    QDECREF(tests_dict);
 }
-END_TEST
 
-START_TEST(qdict_get_not_exists_test)
+static void qdict_get_not_exists_test(void)
 {
-    fail_unless(qdict_get(tests_dict, "foo") == NULL);
+    QDict *tests_dict = qdict_new();
+    g_assert(qdict_get(tests_dict, "foo") == NULL);
+
+    QDECREF(tests_dict);
 }
-END_TEST
 
 /*
  * Stress test-case
@@ -276,7 +283,7 @@ static QString *read_line(FILE *file, char *key)
 
 #define reset_file(file)    fseek(file, 0L, SEEK_SET)
 
-START_TEST(qdict_stress_test)
+static void qdict_stress_test(void)
 {
     size_t lines;
     char key[128];
@@ -286,11 +293,11 @@ START_TEST(qdict_stress_test)
     const char *test_file_path = "qdict-test-data.txt";
 
     test_file = fopen(test_file_path, "r");
-    fail_unless(test_file != NULL);
+    g_assert(test_file != NULL);
 
     // Create the dict
     qdict = qdict_new();
-    fail_unless(qdict != NULL);
+    g_assert(qdict != NULL);
 
     // Add everything from the test file
     for (lines = 0;; lines++) {
@@ -300,7 +307,7 @@ START_TEST(qdict_stress_test)
 
         qdict_put(qdict, key, value);
     }
-    fail_unless(qdict_size(qdict) == lines);
+    g_assert(qdict_size(qdict) == lines);
 
     // Check if everything is really in there
     reset_file(test_file);
@@ -314,9 +321,9 @@ START_TEST(qdict_stress_test)
         str1 = qstring_get_str(value);
 
         str2 = qdict_get_str(qdict, key);
-        fail_unless(str2 != NULL);
+        g_assert(str2 != NULL);
 
-        fail_unless(strcmp(str1, str2) == 0);
+        g_assert(strcmp(str1, str2) == 0);
 
         QDECREF(value);
     }
@@ -331,72 +338,41 @@ START_TEST(qdict_stress_test)
         qdict_del(qdict, key);
         QDECREF(value);
 
-        fail_unless(qdict_haskey(qdict, key) == 0);
+        g_assert(qdict_haskey(qdict, key) == 0);
     }
     fclose(test_file);
 
-    fail_unless(qdict_size(qdict) == 0);
+    g_assert(qdict_size(qdict) == 0);
     QDECREF(qdict);
 }
-END_TEST
 
-static Suite *qdict_suite(void)
+int main(int argc, char **argv)
 {
-    Suite *s;
-    TCase *qdict_public_tcase;
-    TCase *qdict_public2_tcase;
-    TCase *qdict_stress_tcase;
-    TCase *qdict_errors_tcase;
-
-    s = suite_create("QDict test-suite");
+    g_test_init(&argc, &argv, NULL);
 
-    qdict_public_tcase = tcase_create("Public Interface");
-    suite_add_tcase(s, qdict_public_tcase);
-    tcase_add_test(qdict_public_tcase, qdict_new_test);
-    tcase_add_test(qdict_public_tcase, qdict_put_obj_test);
-    tcase_add_test(qdict_public_tcase, qdict_destroy_simple_test);
+    g_test_add_func("/public/new", qdict_new_test);
+    g_test_add_func("/public/put_obj", qdict_put_obj_test);
+    g_test_add_func("/public/destroy_simple", qdict_destroy_simple_test);
 
     /* Continue, but now with fixtures */
-    qdict_public2_tcase = tcase_create("Public Interface (2)");
-    suite_add_tcase(s, qdict_public2_tcase);
-    tcase_add_checked_fixture(qdict_public2_tcase, qdict_setup, qdict_teardown);
-    tcase_add_test(qdict_public2_tcase, qdict_get_test);
-    tcase_add_test(qdict_public2_tcase, qdict_get_int_test);
-    tcase_add_test(qdict_public2_tcase, qdict_get_try_int_test);
-    tcase_add_test(qdict_public2_tcase, qdict_get_str_test);
-    tcase_add_test(qdict_public2_tcase, qdict_get_try_str_test);
-    tcase_add_test(qdict_public2_tcase, qdict_haskey_not_test);
-    tcase_add_test(qdict_public2_tcase, qdict_haskey_test);
-    tcase_add_test(qdict_public2_tcase, qdict_del_test);
-    tcase_add_test(qdict_public2_tcase, qobject_to_qdict_test);
-    tcase_add_test(qdict_public2_tcase, qdict_iterapi_test);
-
-    qdict_errors_tcase = tcase_create("Errors");
-    suite_add_tcase(s, qdict_errors_tcase);
-    tcase_add_checked_fixture(qdict_errors_tcase, qdict_setup, qdict_teardown);
-    tcase_add_test(qdict_errors_tcase, qdict_put_exists_test);
-    tcase_add_test(qdict_errors_tcase, qdict_get_not_exists_test);
+    g_test_add_func("/public/get", qdict_get_test);
+    g_test_add_func("/public/get_int", qdict_get_int_test);
+    g_test_add_func("/public/get_try_int", qdict_get_try_int_test);
+    g_test_add_func("/public/get_str", qdict_get_str_test);
+    g_test_add_func("/public/get_try_str", qdict_get_try_str_test);
+    g_test_add_func("/public/haskey_not", qdict_haskey_not_test);
+    g_test_add_func("/public/haskey", qdict_haskey_test);
+    g_test_add_func("/public/del", qdict_del_test);
+    g_test_add_func("/public/to_qdict", qobject_to_qdict_test);
+    g_test_add_func("/public/iterapi", qdict_iterapi_test);
+
+    g_test_add_func("/errors/put_exists", qdict_put_exists_test);
+    g_test_add_func("/errors/get_not_exists", qdict_get_not_exists_test);
 
     /* The Big one */
-    qdict_stress_tcase = tcase_create("Stress Test");
-    suite_add_tcase(s, qdict_stress_tcase);
-    tcase_add_test(qdict_stress_tcase, qdict_stress_test);
-
-    return s;
-}
-
-int main(void)
-{
-	int nf;
-	Suite *s;
-	SRunner *sr;
-
-	s = qdict_suite();
-	sr = srunner_create(s);
-
-	srunner_run_all(sr, CK_NORMAL);
-	nf = srunner_ntests_failed(sr);
-	srunner_free(sr);
+    if (g_test_slow()) {
+        g_test_add_func("/stress/test", qdict_stress_test);
+    }
 
-	return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+    return g_test_run();
 }
diff --git a/configure b/configure
index 79790b3..7e3f28f 100755
--- a/configure
+++ b/configure
@@ -2800,10 +2800,10 @@ if test "$softmmu" = yes ; then
       tools="qemu-ga\$(EXESUF) $tools"
     fi
     if [ "$check_utests" = "yes" ]; then
-      checks="check-qint check-qstring check-qdict check-qlist"
+      checks="check-qint check-qstring check-qlist"
       checks="check-qfloat check-qjson $checks"
     fi
-    test_progs="$checks test-coroutine test-qmp-output-visitor test-qmp-input-visitor"
+    test_progs="$checks check-qdict test-coroutine test-qmp-output-visitor test-qmp-input-visitor"
   fi
 fi
 
commit dbfe06c62ccedc5b64e1c6466445133dd50f6de1
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jan 10 13:10:43 2012 -0600

    build: split unit test builds to a separate makefile fragment
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index 3b28582..c1dd42d 100644
--- a/Makefile
+++ b/Makefile
@@ -162,32 +162,13 @@ fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
 qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $@")
 
-check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o test-coroutine.o: $(GENERATED_HEADERS)
-
-check-qint: check-qint.o qint.o $(tools-obj-y)
-check-qstring: check-qstring.o qstring.o $(tools-obj-y)
-check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(tools-obj-y)
-check-qlist: check-qlist.o qlist.o qint.o $(tools-obj-y)
-check-qfloat: check-qfloat.o qfloat.o $(tools-obj-y)
-check-qjson: check-qjson.o $(qobject-obj-y) $(tools-obj-y)
-test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(tools-obj-y)
-
 $(qapi-obj-y): $(GENERATED_HEADERS)
 qapi-dir := $(BUILD_DIR)/qapi-generated
-test-qmp-input-visitor.o test-qmp-output-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
 
 gen-out-type = $(subst .,-,$(suffix $@))
 
-$(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
-$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
-$(qapi-dir)/test-qapi-visit.c $(qapi-dir)/test-qapi-visit.h :\
-$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
-$(qapi-dir)/test-qmp-commands.h $(qapi-dir)/test-qmp-marshal.c :\
-$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
-	    $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
+include $(SRC_PATH)/tests/Makefile
 
 $(qapi-dir)/qga-qapi-types.c $(qapi-dir)/qga-qapi-types.h :\
 $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-types.py
@@ -209,15 +190,6 @@ qmp-commands.h qmp-marshal.c :\
 $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, "  GEN   $@")
 
-test-qmp-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
-test-qmp-output-visitor: test-qmp-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
-
-test-qmp-input-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
-test-qmp-input-visitor: test-qmp-input-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
-
-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
-
 QGALIB_OBJ=$(addprefix $(qapi-dir)/, qga-qapi-types.o qga-qapi-visit.o qga-qmp-marshal.o)
 QGALIB_GEN=$(addprefix $(qapi-dir)/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
 $(QGALIB_OBJ): $(QGALIB_GEN) $(GENERATED_HEADERS)
@@ -321,12 +293,6 @@ endif
 test speed: all
 	$(MAKE) -C tests/tcg $@
 
-.PHONY: check
-check: $(patsubst %,run-check-%,$(CHECKS))
-
-run-check-%: %
-	./$<
-
 .PHONY: TAGS
 TAGS:
 	find "$(SRC_PATH)" -name '*.[hc]' -print0 | xargs -0 etags
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644
index 0000000..54c95bc
--- /dev/null
+++ b/tests/Makefile
@@ -0,0 +1,38 @@
+check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o test-coroutine.o: $(GENERATED_HEADERS)
+
+check-qint: check-qint.o qint.o $(tools-obj-y)
+check-qstring: check-qstring.o qstring.o $(tools-obj-y)
+check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(tools-obj-y)
+check-qlist: check-qlist.o qlist.o qint.o $(tools-obj-y)
+check-qfloat: check-qfloat.o qfloat.o $(tools-obj-y)
+check-qjson: check-qjson.o $(qobject-obj-y) $(tools-obj-y)
+test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(tools-obj-y)
+
+test-qmp-input-visitor.o test-qmp-output-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
+
+$(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
+$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
+$(qapi-dir)/test-qapi-visit.c $(qapi-dir)/test-qapi-visit.h :\
+$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
+$(qapi-dir)/test-qmp-commands.h $(qapi-dir)/test-qmp-marshal.c :\
+$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
+	    $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
+
+
+test-qmp-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
+test-qmp-output-visitor: test-qmp-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+
+test-qmp-input-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
+test-qmp-input-visitor: test-qmp-input-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+
+test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h test-qmp-marshal.c test-qmp-commands.h) $(qapi-obj-y)
+test-qmp-commands: test-qmp-commands.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
+
+.PHONY: check
+check: $(patsubst %,run-check-%,$(CHECKS))
+
+run-check-%: %
+	./$<
+
commit c09015dd04e14a9b99250ed06fb5a47e2efa387f
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jan 10 13:10:42 2012 -0600

    tests: mv tests/* -> tests/tcg
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index 21f8c76..3b28582 100644
--- a/Makefile
+++ b/Makefile
@@ -241,7 +241,7 @@ clean:
 	rm -f trace-dtrace.h trace-dtrace.h-timestamp
 	rm -f $(GENERATED_SOURCES)
 	rm -rf $(qapi-dir)
-	$(MAKE) -C tests clean
+	$(MAKE) -C tests/tcg clean
 	for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard; do \
 	if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
 	rm -f $$d/qemu-options.def; \
@@ -319,7 +319,7 @@ endif
 
 # various test targets
 test speed: all
-	$(MAKE) -C tests $@
+	$(MAKE) -C tests/tcg $@
 
 .PHONY: check
 check: $(patsubst %,run-check-%,$(CHECKS))
diff --git a/configure b/configure
index 0309dad..79790b3 100755
--- a/configure
+++ b/configure
@@ -3809,14 +3809,14 @@ echo "QEMU_INCLUDES+=$includes" >> $config_target_mak
 done # for target in $targets
 
 # build tree in object directory in case the source is not in the current directory
-DIRS="tests tests/cris slirp audio block net pc-bios/optionrom"
+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 qapi qapi-generated"
 DIRS="$DIRS qga trace"
-FILES="Makefile tests/Makefile qdict-test-data.txt"
-FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
+FILES="Makefile tests/tcg/Makefile qdict-test-data.txt"
+FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit"
 FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
 FILES="$FILES pc-bios/spapr-rtas/Makefile"
 FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
diff --git a/tests/Makefile b/tests/Makefile
deleted file mode 100644
index 15e36a2..0000000
--- a/tests/Makefile
+++ /dev/null
@@ -1,145 +0,0 @@
--include ../config-host.mak
--include $(SRC_PATH)/rules.mak
-
-$(call set-vpath, $(SRC_PATH)/tests)
-
-QEMU=../i386-linux-user/qemu-i386
-QEMU_X86_64=../x86_64-linux-user/qemu-x86_64
-CC_X86_64=$(CC_I386) -m64
-
-QEMU_INCLUDES += -I..
-CFLAGS=-Wall -O2 -g -fno-strict-aliasing
-#CFLAGS+=-msse2
-LDFLAGS=
-
-# TODO: automatically detect ARM and MIPS compilers, and run those too
-
-# runcom maps page 0, so it requires root privileges
-# also, pi_10.com runs indefinitely
-
-I386_TESTS=hello-i386 \
-	   linux-test \
-	   testthread \
-	   sha1-i386 \
-	   test-i386 \
-	   test-mmap \
-	   # runcom
-
-# native i386 compilers sometimes are not biarch.  assume cross-compilers are
-ifneq ($(ARCH),i386)
-I386_TESTS+=run-test-x86_64
-endif
-
-TESTS = test_path
-ifneq ($(call find-in-path, $(CC_I386)),)
-TESTS += $(I386_TESTS)
-endif
-
-all: $(patsubst %,run-%,$(TESTS))
-
-# rules to run tests
-
-.PHONY: $(patsubst %,run-%,$(TESTS))
-
-run-%: %
-	-$(QEMU) ./$*
-
-run-hello-i386: hello-i386
-run-linux-test: linux-test
-run-testthread: testthread
-run-sha1-i386: sha1-i386
-
-run-test-i386: test-i386
-	./test-i386 > test-i386.ref
-	-$(QEMU) test-i386 > test-i386.out
-	@if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK"; fi
-
-run-test-x86_64: test-x86_64
-	./test-x86_64 > test-x86_64.ref
-	-$(QEMU_X86_64) test-x86_64 > test-x86_64.out
-	@if diff -u test-x86_64.ref test-x86_64.out ; then echo "Auto Test OK"; fi
-
-run-test-mmap: test-mmap
-	-$(QEMU) ./test-mmap
-	-$(QEMU) -p 8192 ./test-mmap 8192
-	-$(QEMU) -p 16384 ./test-mmap 16384
-	-$(QEMU) -p 32768 ./test-mmap 32768
-
-run-runcom: runcom
-	-$(QEMU) ./runcom $(SRC_PATH)/tests/pi_10.com
-
-run-test_path: test_path
-	./test_path
-
-# rules to compile tests
-
-test_path: test_path.o
-test_path.o: test_path.c
-
-hello-i386: hello-i386.c
-	$(CC_I386) -nostdlib $(CFLAGS) -static $(LDFLAGS) -o $@ $<
-	strip $@
-
-testthread: testthread.c
-	$(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $< -lpthread
-
-# i386/x86_64 emulation test (test various opcodes) */
-test-i386: test-i386.c test-i386-code16.S test-i386-vm86.S \
-           test-i386.h test-i386-shift.h test-i386-muldiv.h
-	$(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ \
-              $(<D)/test-i386.c $(<D)/test-i386-code16.S $(<D)/test-i386-vm86.S -lm
-
-test-x86_64: test-i386.c \
-           test-i386.h test-i386-shift.h test-i386-muldiv.h
-	$(CC_X86_64) $(CFLAGS) $(LDFLAGS) -o $@ $(<D)/test-i386.c -lm
-
-# generic Linux and CPU test
-linux-test: linux-test.c
-	$(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $< -lm
-
-# vm86 test
-runcom: runcom.c
-	$(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $<
-
-test-mmap: test-mmap.c
-	$(CC_I386) -m32 $(CFLAGS) -Wall -O2 $(LDFLAGS) -o $@ $<
-
-# speed test
-sha1-i386: sha1.c
-	$(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $<
-
-sha1: sha1.c
-	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
-
-speed: sha1 sha1-i386
-	time ./sha1
-	time $(QEMU) ./sha1-i386
-
-# arm test
-hello-arm: hello-arm.o
-	arm-linux-ld -o $@ $<
-
-hello-arm.o: hello-arm.c
-	arm-linux-gcc -Wall -g -O2 -c -o $@ $<
-
-test-arm-iwmmxt: test-arm-iwmmxt.s
-	cpp < $< | arm-linux-gnu-gcc -Wall -static -march=iwmmxt -mabi=aapcs -x assembler - -o $@
-
-# MIPS test
-hello-mips: hello-mips.c
-	mips-linux-gnu-gcc -nostdlib -static -mno-abicalls -fno-PIC -mabi=32 -Wall -Wextra -g -O2 -o $@ $<
-
-hello-mipsel: hello-mips.c
-	mipsel-linux-gnu-gcc -nostdlib -static -mno-abicalls -fno-PIC -mabi=32 -Wall -Wextra -g -O2 -o $@ $<
-
-# testsuite for the CRIS port.
-test-cris:
-	$(MAKE) -C cris check
-
-# testsuite for the LM32 port.
-test-lm32:
-	$(MAKE) -C lm32 check
-
-clean:
-	rm -f *~ *.o test-i386.out test-i386.ref \
-           test-x86_64.log test-x86_64.ref qruncom $(TESTS)
diff --git a/tests/alpha/Makefile b/tests/alpha/Makefile
deleted file mode 100644
index 2b1f03d..0000000
--- a/tests/alpha/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-CROSS=alpha-linux-gnu-
-CC=$(CROSS)gcc
-AS=$(CROSS)as
-
-SIM=../../alpha-linux-user/qemu-alpha
-
-CFLAGS=-O
-LINK=$(CC) -o $@ crt.o $< -nostdlib
-
-TESTS=test-cond test-cmov
-
-all: hello-alpha $(TESTS)
-
-hello-alpha: hello-alpha.o crt.o
-	$(LINK)
-
-test-cond: test-cond.o crt.o
-	$(LINK)
-
-test-cmov.o: test-cond.c
-	$(CC) -c $(CFLAGS) -DTEST_CMOV -o $@ $<
-
-test-cmov: test-cmov.o crt.o
-	$(LINK)
-
-test-ovf: test-ovf.o crt.o
-	$(LINK)
-
-check: $(TESTS)
-	for f in $(TESTS); do $(SIM) $$f || exit 1; done
-
-clean:
-	$(RM) *.o *~ hello-alpha $(TESTS)
-
-.PHONY: clean all check
diff --git a/tests/alpha/crt.s b/tests/alpha/crt.s
deleted file mode 100644
index 31af882..0000000
--- a/tests/alpha/crt.s
+++ /dev/null
@@ -1,26 +0,0 @@
-	.text
-
-	.globl _start
-	.ent _start,0
-_start:
-	.frame $15,0,$15
-	br $29,1f
-1:	ldgp $29, 0($29)
-	.prologue 0
-	ldq $27,main($29) !literal!1
-	jsr $26,($27)
-	or $0,$0,$16
-	.end _start
-
-	.globl _exit
-_exit:
-	lda $0,1
-	callsys
-
-	call_pal 0
-
-	.globl write
-write:
-	lda $0,4
-	callsys
-	ret
diff --git a/tests/alpha/hello-alpha.c b/tests/alpha/hello-alpha.c
deleted file mode 100644
index 79892e6..0000000
--- a/tests/alpha/hello-alpha.c
+++ /dev/null
@@ -1,5 +0,0 @@
-int main (void)
-{
-  write (1, "hello\n", 6);
-  return 0;
-}
diff --git a/tests/alpha/test-cond.c b/tests/alpha/test-cond.c
deleted file mode 100644
index 74adffa..0000000
--- a/tests/alpha/test-cond.c
+++ /dev/null
@@ -1,87 +0,0 @@
-
-#ifdef TEST_CMOV
-
-#define TEST_COND(N) 				\
-int test_##N (long a)				\
-{						\
-  int res = 1;					\
-						\
-  asm ("cmov"#N" %1,$31,%0"			\
-       : "+r" (res) : "r" (a));			\
-  return !res;					\
-}
-
-#else
-
-#define TEST_COND(N) 				\
-int test_##N (long a)				\
-{						\
-  int res = 1;					\
-						\
-  asm ("b"#N" %1,1f\n\t"			\
-       "addq $31,$31,%0\n\t"			\
-       "1: unop\n"				\
-       : "+r" (res) : "r" (a));			\
-  return res;					\
-}
-
-#endif
-
-TEST_COND(eq)
-TEST_COND(ne)
-TEST_COND(ge)
-TEST_COND(gt)
-TEST_COND(lbc)
-TEST_COND(lbs)
-TEST_COND(le)
-TEST_COND(lt)
-
-static struct {
-  int (*func)(long);
-  long v;
-  int r;
-} vectors[] =
-  {
-    {test_eq, 0, 1},
-    {test_eq, 1, 0},
-
-    {test_ne, 0, 0},
-    {test_ne, 1, 1},
-
-    {test_ge, 0, 1},
-    {test_ge, 1, 1},
-    {test_ge, -1, 0},
-
-    {test_gt, 0, 0},
-    {test_gt, 1, 1},
-    {test_gt, -1, 0},
-
-    {test_lbc, 0, 1},
-    {test_lbc, 1, 0},
-    {test_lbc, -1, 0},
-
-    {test_lbs, 0, 0},
-    {test_lbs, 1, 1},
-    {test_lbs, -1, 1},
-
-    {test_le, 0, 1},
-    {test_le, 1, 0},
-    {test_le, -1, 1},
-
-    {test_lt, 0, 0},
-    {test_lt, 1, 0},
-    {test_lt, -1, 1},
-  };
-
-int main (void)
-{
-  int i;
-
-  for (i = 0; i < sizeof (vectors)/sizeof(vectors[0]); i++)
-    if ((*vectors[i].func)(vectors[i].v) != vectors[i].r) {
-      write(1, "Failed\n", 7);
-      return 1;
-    }
-  write(1, "OK\n", 3);
-  return 0;
-}
diff --git a/tests/alpha/test-ovf.c b/tests/alpha/test-ovf.c
deleted file mode 100644
index 01c80e7..0000000
--- a/tests/alpha/test-ovf.c
+++ /dev/null
@@ -1,29 +0,0 @@
-static long test_subqv (long a, long b)
-{
-  long res;
-
-  asm ("subq/v %1,%2,%0"
-       : "=r" (res) : "r" (a), "r" (b));
-  return res;
-}
-static struct {
-  long (*func)(long, long);
-  long a;
-  long b;
-  long r;
-} vectors[] =
-  {
-    {test_subqv, 0, 0x7d54000, 0xfffffffff82ac000L}
-  };
-
-int main (void)
-{
-  int i;
-
-  for (i = 0; i < sizeof (vectors)/sizeof(vectors[0]); i++)
-    if ((*vectors[i].func)(vectors[i].a, vectors[i].b) != vectors[i].r) {
-      write(1, "Failed\n", 7);
-    }
-  write(1, "OK\n", 3);
-  return 0;
-}
diff --git a/tests/cris/.gdbinit b/tests/cris/.gdbinit
deleted file mode 100644
index 5e8c1d3..0000000
--- a/tests/cris/.gdbinit
+++ /dev/null
@@ -1,11 +0,0 @@
-b main
-b _fail
-b exit
-display /i $pc
-display /x $srp
-display /x $r0
-display /x $r1
-display /x $r2
-display /x $r3
-display /x $r4
-display /t $ccs
diff --git a/tests/cris/Makefile b/tests/cris/Makefile
deleted file mode 100644
index b86bcad..0000000
--- a/tests/cris/Makefile
+++ /dev/null
@@ -1,155 +0,0 @@
--include ../../config-host.mak
-
-CROSS=crisv32-axis-linux-gnu-
-SIM=../../cris-linux-user/qemu-cris -L ./
-SIMG=cris-axis-linux-gnu-run --sysroot=./
-
-CC      = $(CROSS)gcc
-#AS      = $(CROSS)as
-AS	= $(CC) -x assembler-with-cpp
-SIZE    = $(CROSS)size
-LD      = $(CC)
-OBJCOPY = $(CROSS)objcopy
-
-# we rely on GCC inline:ing the stuff we tell it to in many places here.
-CFLAGS  = -Winline -Wall -g -O2 -static
-NOSTDFLAGS = -nostartfiles -nostdlib
-ASFLAGS += -g -Wa,-I,$(SRC_PATH)/tests/cris/
-LDLIBS  =
-NOSTDLIBS = -lgcc
-
-CRT        = crt.o
-SYS        = sys.o
-TESTCASES += check_abs.tst
-TESTCASES += check_addc.tst
-TESTCASES += check_addcm.tst
-TESTCASES += check_addo.tst
-TESTCASES += check_addoq.tst
-TESTCASES += check_addi.tst
-TESTCASES += check_addiv32.tst
-TESTCASES += check_addm.tst
-TESTCASES += check_addr.tst
-TESTCASES += check_addq.tst
-TESTCASES += check_addxc.tst
-TESTCASES += check_addxm.tst
-TESTCASES += check_addxr.tst
-TESTCASES += check_andc.tst
-TESTCASES += check_andm.tst
-TESTCASES += check_andr.tst
-TESTCASES += check_andq.tst
-TESTCASES += check_asr.tst
-TESTCASES += check_ba.tst
-TESTCASES += check_bas.tst
-TESTCASES += check_bcc.tst
-TESTCASES += check_bound.tst
-TESTCASES += check_boundc.tst
-TESTCASES += check_boundr.tst
-TESTCASES += check_btst.tst
-TESTCASES += check_clearfv32.tst
-TESTCASES += check_cmpc.tst
-TESTCASES += check_cmpr.tst
-TESTCASES += check_cmpq.tst
-TESTCASES += check_cmpm.tst
-TESTCASES += check_cmpxc.tst
-TESTCASES += check_cmpxm.tst
-TESTCASES += check_cmp-2.tst
-TESTCASES += check_clrjmp1.tst
-TESTCASES += check_dstep.tst
-TESTCASES += check_ftag.tst
-TESTCASES += check_int64.tst
-# check_jsr is broken.
-#TESTCASES += check_jsr.tst
-TESTCASES += check_mcp.tst
-TESTCASES += check_movei.tst
-TESTCASES += check_mover.tst
-TESTCASES += check_moverm.tst
-TESTCASES += check_moveq.tst
-TESTCASES += check_movemr.tst
-TESTCASES += check_movemrv32.tst
-TESTCASES += check_movecr.tst
-TESTCASES += check_movmp.tst
-TESTCASES += check_movpr.tst
-TESTCASES += check_movprv32.tst
-TESTCASES += check_movdelsr1.tst
-TESTCASES += check_movpmv32.tst
-TESTCASES += check_movsr.tst
-TESTCASES += check_movsm.tst
-TESTCASES += check_movscr.tst
-TESTCASES += check_movur.tst
-TESTCASES += check_movum.tst
-TESTCASES += check_movucr.tst
-TESTCASES += check_mulx.tst
-TESTCASES += check_mulv32.tst
-TESTCASES += check_neg.tst
-TESTCASES += check_not.tst
-TESTCASES += check_lz.tst
-TESTCASES += check_lapc.tst
-TESTCASES += check_lsl.tst
-TESTCASES += check_lsr.tst
-TESTCASES += check_orc.tst
-TESTCASES += check_orm.tst
-TESTCASES += check_orr.tst
-TESTCASES += check_orq.tst
-TESTCASES += check_ret.tst
-TESTCASES += check_swap.tst
-TESTCASES += check_scc.tst
-TESTCASES += check_subc.tst
-TESTCASES += check_subq.tst
-TESTCASES += check_subr.tst
-TESTCASES += check_subm.tst
-TESTCASES += check_glibc_kernelversion.tst
-TESTCASES += check_xarith.tst
-
-TESTCASES += check_hello.ctst
-TESTCASES += check_stat1.ctst
-TESTCASES += check_stat2.ctst
-TESTCASES += check_stat3.ctst
-TESTCASES += check_stat4.ctst
-TESTCASES += check_openpf1.ctst
-TESTCASES += check_openpf2.ctst
-TESTCASES += check_openpf3.ctst
-TESTCASES += check_openpf4.ctst
-TESTCASES += check_openpf5.ctst
-TESTCASES += check_mapbrk.ctst
-TESTCASES += check_mmap1.ctst
-TESTCASES += check_mmap2.ctst
-TESTCASES += check_mmap3.ctst
-TESTCASES += check_sigalrm.ctst
-TESTCASES += check_time1.ctst
-TESTCASES += check_time2.ctst
-TESTCASES += check_settls1.ctst
-
-TESTCASES += check_gcctorture_pr28634-1.ctst
-#TESTCASES += check_gcctorture_pr28634.ctst
-
-all: build
-
-%.o: $(SRC_PATH)/tests/cris/%.c
-	$(CC) $(CFLAGS) -c $< -o $@
-
-%.o: $(SRC_PATH)/tests/cris/%.s
-	$(AS) $(ASFLAGS) -c $< -o $@
-
-%.tst: %.o
-	$(CC) $(CFLAGS) $(NOSTDFLAGS) $(LDLIBS) $(NOSTDLIBS) $(CRT) $< $(SYS) -o $@
-
-%.ctst: %.o
-	$(CC) $(CFLAGS) $(LDLIBS) $< -o $@
-
-build: $(CRT) $(SYS) $(TESTCASES)
-
-check: $(CRT) $(SYS) $(TESTCASES)
-	@echo -e "\nQEMU simulator."
-	for case in $(TESTCASES); do \
-		echo -n "$$case "; \
-		$(SIM) ./$$case; \
-	done
-check-g: $(CRT) $(SYS) $(TESTCASES)
-	@echo -e "\nGDB simulator."
-	@for case in $(TESTCASES); do \
-		echo -n "$$case "; \
-		$(SIMG) $$case; \
-	done
-
-clean:
-	$(RM) -fr $(TESTCASES) $(CRT) $(SYS)
diff --git a/tests/cris/README b/tests/cris/README
deleted file mode 100644
index 2e65a76..0000000
--- a/tests/cris/README
+++ /dev/null
@@ -1 +0,0 @@
-Test-suite for the cris port. Heavily based on the test-suite for the CRIS port of sim by Hans-Peter Nilsson.
diff --git a/tests/cris/check_abs.c b/tests/cris/check_abs.c
deleted file mode 100644
index 9770a8d..0000000
--- a/tests/cris/check_abs.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include "sys.h"
-#include "crisutils.h"
-
-static inline int cris_abs(int n)
-{
-	int r;
-	asm ("abs\t%1, %0\n" : "=r" (r) : "r" (n));
-	return r;
-}
-
-static inline void
-verify_abs(int val, int res,
-	   const int n, const int z, const int v, const int c)
-{
-	int r;
-
-	cris_tst_cc_init();
-	r = cris_abs(val);
-	cris_tst_cc(n, z, v, c);
-	if (r != res)
-		err();
-}
-
-int main(void)
-{
-	verify_abs(-1, 1, 0, 0, 0, 0);
-	verify_abs(0x80000000, 0x80000000, 1, 0, 0, 0);
-	verify_abs(0x7fffffff, 0x7fffffff, 0, 0, 0, 0);
-	verify_abs(42, 42, 0, 0, 0, 0);
-	verify_abs(1, 1, 0, 0, 0, 0);
-	verify_abs(0xffff, 0xffff, 0, 0, 0, 0);
-	verify_abs(0xffff, 0xffff, 0, 0, 0, 0);
-	verify_abs(-31, 0x1f, 0, 0, 0, 0);
-	verify_abs(0, 0, 0, 1, 0, 0);
-	pass();
-	return 0;
-}
diff --git a/tests/cris/check_addc.c b/tests/cris/check_addc.c
deleted file mode 100644
index facd1be..0000000
--- a/tests/cris/check_addc.c
+++ /dev/null
@@ -1,58 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include "sys.h"
-#include "crisutils.h"
-
-static inline int cris_addc(int a, const int b)
-{
-	asm ("addc\t%1, %0\n" : "+r" (a) : "r" (b));
-	return a;
-}
-
-#define verify_addc(a, b, res, n, z, v, c)  \
-{                                           \
-	int r;                              \
-	r = cris_addc((a), (b));            \
-	cris_tst_cc((n), (z), (v), (c));    \
-	if (r != (res))                     \
-		err();                      \
-}
-
-int main(void)
-{
-	cris_tst_cc_init();
-	asm volatile ("clearf cz");
-	verify_addc(0, 0, 0, 0, 0, 0, 0);
-
-	cris_tst_cc_init();
-	asm volatile ("setf z");
-	verify_addc(0, 0, 0, 0, 1, 0, 0);
-
-	cris_tst_cc_init();
-	asm volatile ("setf cz");
-	verify_addc(0, 0, 1, 0, 0, 0, 0);
-	cris_tst_cc_init();
-	asm volatile ("clearf c");
-	verify_addc(-1, 2, 1, 0, 0, 0, 1);
-
-	cris_tst_cc_init();
-	asm volatile ("clearf nzv");
-	asm volatile ("setf c");
-	verify_addc(-1, 2, 2, 0, 0, 0, 1);
-
-	cris_tst_cc_init();
-	asm volatile ("setf c");
-	verify_addc(0xffff, 0xffff, 0x1ffff, 0, 0, 0, 0);
-
-	cris_tst_cc_init();
-	asm volatile ("clearf nzvc");
-	verify_addc(-1, -1, 0xfffffffe, 1, 0, 0, 1);
-
-	cris_tst_cc_init();
-	asm volatile ("setf c");
-	verify_addc(0x78134452, 0x5432f789, 0xcc463bdc, 1, 0, 1, 0);
-
-	pass();
-	return 0;
-}
diff --git a/tests/cris/check_addcm.c b/tests/cris/check_addcm.c
deleted file mode 100644
index 7928bc9..0000000
--- a/tests/cris/check_addcm.c
+++ /dev/null
@@ -1,85 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include "sys.h"
-#include "crisutils.h"
-
-/* need to avoid acr as source here.  */
-static inline int cris_addc_m(int a, const int *b)
-{
-	asm volatile ("addc [%1], %0\n" : "+r" (a) : "r" (b));
-	return a;
-}
-
-/* 'b' is a crisv32 constrain to avoid postinc with $acr.  */
-static inline int cris_addc_pi_m(int a, int **b)
-{
-	asm volatile ("addc [%1+], %0\n" : "+r" (a), "+b" (*b));
-	return a;
-}
-
-#define verify_addc_m(a, b, res, n, z, v, c)  \
-{                                           \
-	int r;                              \
-	r = cris_addc_m((a), (b));            \
-	cris_tst_cc((n), (z), (v), (c));    \
-	if (r != (res))                     \
-		err();                      \
-}
-
-#define verify_addc_pi_m(a, b, res, n, z, v, c)  \
-{                                           \
-	int r;                              \
-	r = cris_addc_pi_m((a), (b));            \
-	cris_tst_cc((n), (z), (v), (c));    \
-	if (r != (res))                     \
-		err();                      \
-}
-
-int x[] = { 0, 0, 2, -1, 0xffff, -1, 0x5432f789};
-
-int main(void)
-{
-	int *p = (void *)&x[0];
-#if 1
-	cris_tst_cc_init();
-	asm volatile ("clearf cz");
-	verify_addc_m(0, p, 0, 0, 0, 0, 0);
-
-	cris_tst_cc_init();
-	asm volatile ("setf z");
-	verify_addc_m(0, p, 0, 0, 1, 0, 0);
-
-	cris_tst_cc_init();
-	asm volatile ("setf c");
-	verify_addc_m(0, p, 1, 0, 0, 0, 0);
-
-	cris_tst_cc_init();
-	asm volatile ("clearf c");
-	verify_addc_pi_m(0, &p, 0, 0, 1, 0, 0);
-
-	p = &x[1];
-	cris_tst_cc_init();
-	asm volatile ("setf c");
-	verify_addc_pi_m(0, &p, 1, 0, 0, 0, 0);
-
-	if (p != &x[2])
-		err();
-
-	cris_tst_cc_init();
-	asm volatile ("clearf c");
-	verify_addc_pi_m(-1, &p, 1, 0, 0, 0, 1);
-
-	if (p != &x[3])
-		err();
-#endif
-	p = &x[3];
-	/* TODO: investigate why this one fails.  */
-	cris_tst_cc_init();
-	asm volatile ("setf c");
-	verify_addc_m(2, p, 2, 0, 0, 0, 1);
-	p += 4;
-
-	pass();
-	return 0;
-}
diff --git a/tests/cris/check_addi.s b/tests/cris/check_addi.s
deleted file mode 100644
index a00dec0..0000000
--- a/tests/cris/check_addi.s
+++ /dev/null
@@ -1,57 +0,0 @@
-# mach:  crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 0\n1\n2\n4\nbe02460f\n69d035a6\nc16c14d4\n
-
- .include "testutils.inc"
- start
- moveq 0,r3
- moveq 0,r4
- clearf zcvn
- addi r4.b,r3
- test_cc 0 0 0 0
- checkr3 0
-
- moveq 0,r3
- moveq 1,r4
- setf zcvn
- addi r4.b,r3
- test_cc 1 1 1 1
- checkr3 1
-
- moveq 0,r3
- moveq 1,r4
- setf cv
- clearf zn
- addi r4.w,r3
- test_cc 0 0 1 1
- checkr3 2
-
- moveq 0,r3
- moveq 1,r4
- clearf cv
- setf zn
- addi r4.d,r3
- test_cc 1 1 0 0
- checkr3 4
-
- move.d 0x12345678,r3
- move.d 0xabcdef97,r4
- clearf cn
- setf zv
- addi r4.b,r3
- test_cc 0 1 1 0
- checkr3 be02460f
-
- move.d 0x12345678,r3
- move.d 0xabcdef97,r4
- setf cn
- clearf zv
- addi r4.w,r3
- test_cc 1 0 0 1
- checkr3 69d035a6
-
- move.d 0x12345678,r3
- move.d 0xabcdef97,r4
- addi r4.d,r3
- checkr3 c16c14d4
-
- quit
diff --git a/tests/cris/check_addiv32.s b/tests/cris/check_addiv32.s
deleted file mode 100644
index 20ba25d..0000000
--- a/tests/cris/check_addiv32.s
+++ /dev/null
@@ -1,62 +0,0 @@
-# mach: crisv32
-# output: 4455aa77\n4455aa77\nee19ccff\nff22\n4455aa77\nff224455\n55aa77ff\n
-
- .include "testutils.inc"
- .data
-x:
- .dword 0x55aa77ff
- .dword 0xccff2244
- .dword 0x88ccee19
-
- start
- setf cv
- moveq -1,r0
- move.d x-32768,r5
- move.d 32769,r6
- addi r6.b,r5,acr
- test_cc 0 0 1 1
- move.d [acr],r3
- checkr3 4455aa77
-
- addu.w 32771,r5
- setf znvc
- moveq -1,r8
- addi r8.w,r5,acr
- test_cc 1 1 1 1
- move.d [acr],r3
- checkr3 4455aa77
-
- moveq 5,r10
- clearf znvc
- addi r10.b,acr,acr
- test_cc 0 0 0 0
- move.d [acr],r3
- checkr3 ee19ccff
-
- subq 1,r5
- move.d r5,r8
- subq 1,r8
- moveq 1,r9
- addi r9.d,r8,acr
- test_cc 0 0 0 0
- movu.w [acr],r3
- checkr3 ff22
-
- moveq -2,r11
- addi r11.w,acr,acr
- move.d [acr],r3
- checkr3 4455aa77
-
- moveq 5,r9
- addi r9.d,acr,acr
- subq 18,acr
- move.d [acr],r3
- checkr3 ff224455
-
- move.d -76789888/4,r12
- addi r12.d,r5,acr
- add.d 76789886,acr
- move.d [acr],r3
- checkr3 55aa77ff
-
- quit
diff --git a/tests/cris/check_addm.s b/tests/cris/check_addm.s
deleted file mode 100644
index efece9f..0000000
--- a/tests/cris/check_addm.s
+++ /dev/null
@@ -1,96 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n781344d0\n
-
- .include "testutils.inc"
- .data
-x:
- .dword 2,-1,0xffff,-1,0x5432f789
- .word 2,-1,0xffff,0xf789
- .byte 2,0xff,0x89
- .byte 0x7e
-
- start
- moveq -1,r3
- move.d x,r5
- add.d [r5+],r3
- test_cc 0 0 0 1
- checkr3 1
-
- moveq 2,r3
- add.d [r5],r3
- test_cc 0 0 0 1
- addq 4,r5
- checkr3 1
-
- move.d 0xffff,r3
- add.d [r5+],r3
- test_cc 0 0 0 0
- checkr3 1fffe
-
- moveq -1,r3
- add.d [r5+],r3
- test_cc 1 0 0 1
- checkr3 fffffffe
-
- move.d 0x78134452,r3
- add.d [r5+],r3
- test_cc 1 0 1 0
- checkr3 cc463bdb
-
- moveq -1,r3
- add.w [r5+],r3
- test_cc 0 0 0 1
- checkr3 ffff0001
-
- moveq 2,r3
- add.w [r5+],r3
- test_cc 0 0 0 1
- checkr3 1
-
- move.d 0xffff,r3
- add.w [r5],r3
- test_cc 1 0 0 1
- checkr3 fffe
-
- move.d 0xfedaffff,r3
- add.w [r5+],r3
- test_cc 1 0 0 1
- checkr3 fedafffe
-
- move.d 0x78134452,r3
- add.w [r5+],r3
- test_cc 0 0 0 1
- checkr3 78133bdb
-
- moveq -1,r3
- add.b [r5],r3
- test_cc 0 0 0 1
- addq 1,r5
- checkr3 ffffff01
-
- moveq 2,r3
- add.b [r5],r3
- test_cc 0 0 0 1
- checkr3 1
-
- move.d 0xff,r3
- add.b [r5],r3
- test_cc 1 0 0 1
- checkr3 fe
-
- move.d 0xfeda49ff,r3
- add.b [r5+],r3
- test_cc 1 0 0 1
- checkr3 feda49fe
-
- move.d 0x78134452,r3
- add.b [r5+],r3
- test_cc 1 0 0 0
- checkr3 781344db
-
- move.d 0x78134452,r3
- add.b [r5],r3
- test_cc 1 0 1 0
- checkr3 781344d0
-
- quit
diff --git a/tests/cris/check_addo.c b/tests/cris/check_addo.c
deleted file mode 100644
index 3d8e789..0000000
--- a/tests/cris/check_addo.c
+++ /dev/null
@@ -1,125 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include "sys.h"
-#include "crisutils.h"
-
-/* this would be better to do in asm, it's an orgy in GCC inline asm now.  */
-
-#define cris_addo_b(o, v) \
-	asm volatile ("addo.b\t[%0], %1, $acr\n" : : "r" (o), "r" (v) : "acr");
-#define cris_addo_w(o, v) \
-	asm volatile ("addo.w\t[%0], %1, $acr\n" : : "r" (o), "r" (v) : "acr");
-#define cris_addo_d(o, v) \
-	asm volatile ("addo.d\t[%0], %1, $acr\n" : : "r" (o), "r" (v) : "acr");
-#define cris_addo_pi_b(o, v) \
-	asm volatile ("addo.b\t[%0+], %1, $acr\n" \
-                         : "+b" (o): "r" (v) : "acr");
-#define cris_addo_pi_w(o, v) \
-	asm volatile ("addo.w\t[%0+], %1, $acr\n" \
-                         : "+b" (o): "r" (v) : "acr");
-#define cris_addo_pi_d(o, v) \
-	asm volatile ("addo.d\t[%0+], %1, $acr\n" \
-                         : "+b" (o): "r" (v) : "acr");
-
-struct {
-	uint32_t v1;
-	uint16_t v2;
-	uint32_t v3;
-	uint8_t v4;
-	uint8_t v5;
-	uint16_t v6;
-	uint32_t v7;
-} y = {
-	32769,
-	-1,
-	5,
-	3, -4,
-	2,
-	-76789887
-};
-
-static int x[3] = {0x55aa77ff, 0xccff2244, 0x88ccee19};
-
-int main(void)
-{
-	int *r;
-	unsigned char *t, *p;
-
-	/* Note, this test-case will trig an unaligned access, partly
-	   to x[0] and to [x1].  */
-	t = (unsigned char *)x;
-	t -= 32768;
-	p = (unsigned char *) &y.v1;
-	mb(); /* dont reorder anything beyond here.  */
-	cris_tst_cc_init();
-	asm volatile ("setf\tzvnc\n");
-	cris_addo_pi_d(p, t);
-	cris_tst_cc(1, 1, 1, 1);
-	asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
-	if (*r != 0x4455aa77)
-		err();
-
-
-	t += 32770;
-	mb(); /* dont reorder anything beyond here.  */
-	cris_tst_cc_init();
-	asm volatile ("setf\tzvnc\n");
-	cris_addo_pi_w(p, t);
-	cris_tst_cc(1, 1, 1, 1);
-	asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
-	if (*r != 0x4455aa77)
-		err();
-
-	mb(); /* dont reorder anything beyond here.  */
-	cris_tst_cc_init();
-	asm volatile ("setf\tzvnc\n");
-	cris_addo_d(p, r);
-	cris_tst_cc(1, 1, 1, 1);
-	p += 4;
-	asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
-	if (*r != 0xee19ccff)
-		err();
-
-	mb(); /* dont reorder anything beyond here.  */
-	cris_tst_cc_init();
-	asm volatile ("setf\tzvnc\n");
-	cris_addo_pi_b(p, t);
-	cris_tst_cc(0, 0, 0, 0);
-	asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
-	if (*(uint16_t*)r != 0xff22)
-		err();
-
-	mb(); /* dont reorder anything beyond here.  */
-	cris_tst_cc_init();
-	asm volatile ("setf\tzvnc\n");
-	cris_addo_b(p, r);
-	cris_tst_cc(1, 1, 1, 1);
-	p += 1;
-	asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
-	if (*r != 0x4455aa77)
-		err();
-
-	mb(); /* dont reorder anything beyond here.  */
-	cris_tst_cc_init();
-	asm volatile ("setf\tzvnc\n");
-	cris_addo_w(p, r);
-	cris_tst_cc(1, 1, 1, 1);
-	p += 2;
-	asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
-	if (*r != 0xff224455)
-		err();
-
-	mb(); /* dont reorder anything beyond here.  */
-	cris_tst_cc_init();
-	asm volatile ("setf\tzvnc\n");
-	cris_addo_pi_d(p, t);
-	cris_tst_cc(0, 0, 0, 0);
-	asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
-	r = (void*)(((char *)r) + 76789885);
-	if (*r != 0x55aa77ff)
-		err();
-
-	pass();
-	return 0;
-}
diff --git a/tests/cris/check_addoq.c b/tests/cris/check_addoq.c
deleted file mode 100644
index ed509e2..0000000
--- a/tests/cris/check_addoq.c
+++ /dev/null
@@ -1,44 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include "sys.h"
-#include "crisutils.h"
-
-/* this would be better to do in asm, it's an orgy in GCC inline asm now.  */
-
-/* ACR will be clobbered.  */
-#define cris_addoq(o, v) \
-	asm volatile ("addoq\t%1, %0, $acr\n" : : "r" (v), "i" (o) : "acr");
-
-
-int main(void)
-{
-	int x[3] = {0x55aa77ff, 0xccff2244, 0x88ccee19};
-	int *p, *t = x + 1;
-
-	cris_tst_cc_init();
-	asm volatile ("setf\tzvnc\n");
-	cris_addoq(0, t);
-	cris_tst_cc(1, 1, 1, 1);
-	asm volatile ("move.d\t$acr, %0\n" : "=r" (p));
-	if (*p != 0xccff2244)
-		err();
-
-	cris_tst_cc_init();
-	asm volatile ("setf\tzvnc\n");
-	cris_addoq(4, t);
-	cris_tst_cc(0, 0, 0, 0);
-	asm volatile ("move.d\t$acr, %0\n" : "=r" (p));
-	if (*p != 0x88ccee19)
-		err();
-
-	cris_tst_cc_init();
-	asm volatile ("clearf\tzvnc\n");
-	cris_addoq(-8, t + 1);
-	cris_tst_cc(0, 0, 0, 0);
-	asm volatile ("move.d\t$acr, %0\n" : "=r" (p));
-	if (*p != 0x55aa77ff)
-		err();
-	pass();
-	return 0;
-}
diff --git a/tests/cris/check_addq.s b/tests/cris/check_addq.s
deleted file mode 100644
index e6f874f..0000000
--- a/tests/cris/check_addq.s
+++ /dev/null
@@ -1,47 +0,0 @@
-# mach: crisv3 crisv8 crisv10 crisv32
-# output: ffffffff\n0\n1\n100\n10000\n47\n67\na6\n80000001\n
-
- .include "testutils.inc"
- start
- moveq -2,r3
- addq 1,r3
- test_cc 1 0 0 0
- checkr3 ffffffff
-
- addq 1,r3
- test_cc 0 1 0 1
- checkr3 0
-
- addq 1,r3
- test_cc 0 0 0 0
- checkr3 1
-
- move.d 0xff,r3
- addq 1,r3
- test_cc 0 0 0 0
- checkr3 100
-
- move.d 0xffff,r3
- addq 1,r3
- test_cc 0 0 0 0
- checkr3 10000
-
- move.d 0x42,r3
- addq 5,r3
- test_cc 0 0 0 0
- checkr3 47
-
- addq 32,r3
- test_cc 0 0 0 0
- checkr3 67
-
- addq 63,r3
- test_cc 0 0 0 0
- checkr3 a6
-
- move.d 0x7ffffffe,r3
- addq 3,r3
- test_cc 1 0 1 0
- checkr3 80000001
-
- quit
diff --git a/tests/cris/check_addr.s b/tests/cris/check_addr.s
deleted file mode 100644
index 7f55cdc..0000000
--- a/tests/cris/check_addr.s
+++ /dev/null
@@ -1,96 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n
-
- .include "testutils.inc"
- start
- moveq -1,r3
- moveq 2,r4
- add.d r4,r3
- test_cc 0 0 0 1
- checkr3 1
-
- moveq 2,r3
- moveq -1,r4
- add.d r4,r3
- test_cc 0 0 0 1
- checkr3 1
-
- move.d 0xffff,r4
- move.d r4,r3
- add.d r4,r3
- test_cc 0 0 0 0
- checkr3 1fffe
-
- moveq -1,r4
- move.d r4,r3
- add.d r4,r3
- test_cc 1 0 0 1
- checkr3 fffffffe
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- add.d r4,r3
- test_cc 1 0 1 0
- checkr3 cc463bdb
-
- moveq -1,r3
- moveq 2,r4
- add.w r4,r3
- test_cc 0 0 0 1
- checkr3 ffff0001
-
- moveq 2,r3
- moveq -1,r4
- add.w r4,r3
- test_cc 0 0 0 1
- checkr3 1
-
- move.d 0xffff,r4
- move.d r4,r3
- add.w r4,r3
- test_cc 1 0 0 1
- checkr3 fffe
-
- move.d 0xfedaffff,r4
- move.d r4,r3
- add.w r4,r3
- test_cc 1 0 0 1
- checkr3 fedafffe
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- add.w r4,r3
- test_cc 0 0 0 1
- checkr3 78133bdb
-
- moveq -1,r3
- moveq 2,r4
- add.b r4,r3
- test_cc 0 0 0 1
- checkr3 ffffff01
-
- moveq 2,r3
- moveq -1,r4
- add.b r4,r3
- test_cc 0 0 0 1
- checkr3 1
-
- move.d 0xff,r4
- move.d r4,r3
- add.b r4,r3
- test_cc 1 0 0 1
- checkr3 fe
-
- move.d 0xfeda49ff,r4
- move.d r4,r3
- add.b r4,r3
- test_cc 1 0 0 1
- checkr3 feda49fe
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- add.b r4,r3
- test_cc 1 0 0 0
- checkr3 781344db
-
- quit
diff --git a/tests/cris/check_addxc.s b/tests/cris/check_addxc.s
deleted file mode 100644
index 09c8355..0000000
--- a/tests/cris/check_addxc.s
+++ /dev/null
@@ -1,91 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 1\n1\n101\n10001\n100fe\n1fffe\nfffe\nfffe\nfffffffe\nfe\nfffffffe\n781344db\n781343db\n78143bdb\n78133bdb\n800000ed\n0\n
-
- .include "testutils.inc"
- start
- moveq 2,r3
- adds.b 0xff,r3
- test_cc 0 0 0 1
- checkr3 1
-
- moveq 2,r3
- adds.w 0xffff,r3
- test_cc 0 0 0 1
- checkr3 1
-
- moveq 2,r3
- addu.b 0xff,r3
- checkr3 101
-
- moveq 2,r3
- move.d 0xffffffff,r4
- addu.w -1,r3
- test_cc 0 0 0 0
- checkr3 10001
-
- move.d 0xffff,r3
- addu.b -1,r3
- test_cc 0 0 0 0
- checkr3 100fe
-
- move.d 0xffff,r3
- addu.w -1,r3
- test_cc 0 0 0 0
- checkr3 1fffe
-
- move.d 0xffff,r3
- adds.b 0xff,r3
- test_cc 0 0 0 1
- checkr3 fffe
-
- move.d 0xffff,r3
- adds.w 0xffff,r3
- test_cc 0 0 0 1
- checkr3 fffe
-
- moveq -1,r3
- adds.b 0xff,r3
- test_cc 1 0 0 1
- checkr3 fffffffe
-
- moveq -1,r3
- adds.w 0xff,r3
- test_cc 0 0 0 1
- checkr3 fe
-
- moveq -1,r3
- adds.w 0xffff,r3
- test_cc 1 0 0 1
- checkr3 fffffffe
-
- move.d 0x78134452,r3
- addu.b 0x89,r3
- test_cc 0 0 0 0
- checkr3 781344db
-
- move.d 0x78134452,r3
- adds.b 0x89,r3
- test_cc 0 0 0 1
- checkr3 781343db
-
- move.d 0x78134452,r3
- addu.w 0xf789,r3
- test_cc 0 0 0 0
- checkr3 78143bdb
-
- move.d 0x78134452,r3
- adds.w 0xf789,r3
- test_cc 0 0 0 1
- checkr3 78133bdb
-
- move.d 0x7fffffee,r3
- addu.b 0xff,r3
- test_cc 1 0 1 0
- checkr3 800000ed
-
- move.d 0x1,r3
- adds.w 0xffff,r3
- test_cc 0 1 0 1
- checkr3 0
-
- quit
diff --git a/tests/cris/check_addxm.s b/tests/cris/check_addxm.s
deleted file mode 100644
index 7563494..0000000
--- a/tests/cris/check_addxm.s
+++ /dev/null
@@ -1,106 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 1\n1\n101\n10001\n100fe\n1fffe\nfffe\nfffe\nfffffffe\nfe\nfffffffe\n781344db\n781343db\n78143bdb\n78133bdb\n800000ed\n0\n
-
- .include "testutils.inc"
- .data
-x:
- .byte 0xff
- .word 0xffff
- .word 0xff
- .word 0xffff
- .byte 0x89
- .word 0xf789
- .byte 0xff
- .word 0xffff
-
- start
- moveq 2,r3
- move.d x,r5
- adds.b [r5+],r3
- test_cc 0 0 0 1
- checkr3 1
-
- moveq 2,r3
- adds.w [r5+],r3
- test_cc 0 0 0 1
- checkr3 1
-
- moveq 2,r3
- subq 3,r5
- addu.b [r5+],r3
- test_cc 0 0 0 0
- checkr3 101
-
- moveq 2,r3
- addu.w [r5+],r3
- subq 3,r5
- test_cc 0 0 0 0
- checkr3 10001
-
- move.d 0xffff,r3
- addu.b [r5],r3
- test_cc 0 0 0 0
- checkr3 100fe
-
- move.d 0xffff,r3
- addu.w [r5],r3
- test_cc 0 0 0 0
- checkr3 1fffe
-
- move.d 0xffff,r3
- adds.b [r5],r3
- test_cc 0 0 0 1
- checkr3 fffe
-
- move.d 0xffff,r3
- adds.w [r5],r3
- test_cc 0 0 0 1
- checkr3 fffe
-
- moveq -1,r3
- adds.b [r5],r3
- test_cc 1 0 0 1
- addq 3,r5
- checkr3 fffffffe
-
- moveq -1,r3
- adds.w [r5+],r3
- test_cc 0 0 0 1
- checkr3 fe
-
- moveq -1,r3
- adds.w [r5+],r3
- test_cc 1 0 0 1
- checkr3 fffffffe
-
- move.d 0x78134452,r3
- addu.b [r5],r3
- test_cc 0 0 0 0
- checkr3 781344db
-
- move.d 0x78134452,r3
- adds.b [r5+],r3
- test_cc 0 0 0 1
- checkr3 781343db
-
- move.d 0x78134452,r3
- addu.w [r5],r3
- test_cc 0 0 0 0
- checkr3 78143bdb
-
- move.d 0x78134452,r3
- adds.w [r5+],r3
- test_cc 0 0 0 1
- checkr3 78133bdb
-
- move.d 0x7fffffee,r3
- addu.b [r5+],r3
- test_cc 1 0 1 0
- checkr3 800000ed
-
- move.d 0x1,r3
- adds.w [r5+],r3
- test_cc 0 1 0 1
- checkr3 0
-
- quit
diff --git a/tests/cris/check_addxr.s b/tests/cris/check_addxr.s
deleted file mode 100644
index 7f55cdc..0000000
--- a/tests/cris/check_addxr.s
+++ /dev/null
@@ -1,96 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n
-
- .include "testutils.inc"
- start
- moveq -1,r3
- moveq 2,r4
- add.d r4,r3
- test_cc 0 0 0 1
- checkr3 1
-
- moveq 2,r3
- moveq -1,r4
- add.d r4,r3
- test_cc 0 0 0 1
- checkr3 1
-
- move.d 0xffff,r4
- move.d r4,r3
- add.d r4,r3
- test_cc 0 0 0 0
- checkr3 1fffe
-
- moveq -1,r4
- move.d r4,r3
- add.d r4,r3
- test_cc 1 0 0 1
- checkr3 fffffffe
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- add.d r4,r3
- test_cc 1 0 1 0
- checkr3 cc463bdb
-
- moveq -1,r3
- moveq 2,r4
- add.w r4,r3
- test_cc 0 0 0 1
- checkr3 ffff0001
-
- moveq 2,r3
- moveq -1,r4
- add.w r4,r3
- test_cc 0 0 0 1
- checkr3 1
-
- move.d 0xffff,r4
- move.d r4,r3
- add.w r4,r3
- test_cc 1 0 0 1
- checkr3 fffe
-
- move.d 0xfedaffff,r4
- move.d r4,r3
- add.w r4,r3
- test_cc 1 0 0 1
- checkr3 fedafffe
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- add.w r4,r3
- test_cc 0 0 0 1
- checkr3 78133bdb
-
- moveq -1,r3
- moveq 2,r4
- add.b r4,r3
- test_cc 0 0 0 1
- checkr3 ffffff01
-
- moveq 2,r3
- moveq -1,r4
- add.b r4,r3
- test_cc 0 0 0 1
- checkr3 1
-
- move.d 0xff,r4
- move.d r4,r3
- add.b r4,r3
- test_cc 1 0 0 1
- checkr3 fe
-
- move.d 0xfeda49ff,r4
- move.d r4,r3
- add.b r4,r3
- test_cc 1 0 0 1
- checkr3 feda49fe
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- add.b r4,r3
- test_cc 1 0 0 0
- checkr3 781344db
-
- quit
diff --git a/tests/cris/check_andc.s b/tests/cris/check_andc.s
deleted file mode 100644
index a947b77..0000000
--- a/tests/cris/check_andc.s
+++ /dev/null
@@ -1,80 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 2\n2\nffff\nffffffff\n50124400\nffff0002\n2\nfffff\nfedaff0f\n78134400\nffffff02\n2\nf02\n78134401\n78134400\n
-
- .include "testutils.inc"
- start
- moveq -1,r3
- and.d 2,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- moveq 2,r3
- and.d -1,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- move.d 0xffff,r3
- and.d 0xffff,r3
- test_move_cc 0 0 0 0
- checkr3 ffff
-
- moveq -1,r3
- and.d -1,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- move.d 0x78134452,r3
- and.d 0x5432f789,r3
- test_move_cc 0 0 0 0
- checkr3 50124400
-
- moveq -1,r3
- and.w 2,r3
- test_move_cc 0 0 0 0
- checkr3 ffff0002
-
- moveq 2,r3
- and.w -1,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- move.d 0xfffff,r3
- and.w 0xffff,r3
- test_move_cc 1 0 0 0
- checkr3 fffff
-
- move.d 0xfedaffaf,r3
- and.w 0xff5f,r3
- test_move_cc 1 0 0 0
- checkr3 fedaff0f
-
- move.d 0x78134452,r3
- and.w 0xf789,r3
- test_move_cc 0 0 0 0
- checkr3 78134400
-
- moveq -1,r3
- and.b 2,r3
- test_move_cc 0 0 0 0
- checkr3 ffffff02
-
- moveq 2,r3
- and.b -1,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- move.d 0xfa7,r3
- and.b 0x5a,r3
- test_move_cc 0 0 0 0
- checkr3 f02
-
- move.d 0x78134453,r3
- and.b 0x89,r3
- test_move_cc 0 0 0 0
- checkr3 78134401
-
- and.b 0,r3
- test_move_cc 0 1 0 0
- checkr3 78134400
-
- quit
diff --git a/tests/cris/check_andm.s b/tests/cris/check_andm.s
deleted file mode 100644
index 9385886..0000000
--- a/tests/cris/check_andm.s
+++ /dev/null
@@ -1,90 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 2\n2\nffff\nffffffff\n50124400\nffff0002\n2\nfffff\nfedaff0f\n78134400\nffffff02\n2\nf02\n78134401\n78134400\n
-
- .include "testutils.inc"
- .data
-x:
- .dword 2,-1,0xffff,-1,0x5432f789
- .word 2,-1,0xffff,0xff5f,0xf789
- .byte 2,-1,0x5a,0x89,0
-
- start
- moveq -1,r3
- move.d x,r5
- and.d [r5+],r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- moveq 2,r3
- and.d [r5],r3
- test_move_cc 0 0 0 0
- addq 4,r5
- checkr3 2
-
- move.d 0xffff,r3
- and.d [r5+],r3
- test_move_cc 0 0 0 0
- checkr3 ffff
-
- moveq -1,r3
- and.d [r5+],r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- move.d 0x78134452,r3
- and.d [r5+],r3
- test_move_cc 0 0 0 0
- checkr3 50124400
-
- moveq -1,r3
- and.w [r5+],r3
- test_move_cc 0 0 0 0
- checkr3 ffff0002
-
- moveq 2,r3
- and.w [r5+],r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- move.d 0xfffff,r3
- and.w [r5],r3
- test_move_cc 1 0 0 0
- addq 2,r5
- checkr3 fffff
-
- move.d 0xfedaffaf,r3
- and.w [r5+],r3
- test_move_cc 1 0 0 0
- checkr3 fedaff0f
-
- move.d 0x78134452,r3
- and.w [r5+],r3
- test_move_cc 0 0 0 0
- checkr3 78134400
-
- moveq -1,r3
- and.b [r5],r3
- test_move_cc 0 0 0 0
- addq 1,r5
- checkr3 ffffff02
-
- moveq 2,r3
- and.b [r5+],r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- move.d 0xfa7,r3
- and.b [r5+],r3
- test_move_cc 0 0 0 0
- checkr3 f02
-
- move.d 0x78134453,r3
- and.b [r5+],r3
- test_move_cc 0 0 0 0
- checkr3 78134401
-
- and.b [r5],r3
- test_move_cc 0 1 0 0
- checkr3 78134400
-
- quit
diff --git a/tests/cris/check_andq.s b/tests/cris/check_andq.s
deleted file mode 100644
index 55aa7b0..0000000
--- a/tests/cris/check_andq.s
+++ /dev/null
@@ -1,46 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 2\n2\nffff\nffffffff\n1f\nffffffe0\n78134452\n0\n
-
- .include "testutils.inc"
- start
- moveq -1,r3
- andq 2,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- moveq 2,r3
- andq -1,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- move.d 0xffff,r3
- andq -1,r3
- test_move_cc 0 0 0 0
- checkr3 ffff
-
- moveq -1,r3
- andq -1,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq -1,r3
- andq 31,r3
- test_move_cc 0 0 0 0
- checkr3 1f
-
- moveq -1,r3
- andq -32,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffe0
-
- move.d 0x78134457,r3
- andq -14,r3
- test_move_cc 0 0 0 0
- checkr3 78134452
-
- moveq 0,r3
- andq -14,r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- quit
diff --git a/tests/cris/check_andr.s b/tests/cris/check_andr.s
deleted file mode 100644
index 61aa1dc..0000000
--- a/tests/cris/check_andr.s
+++ /dev/null
@@ -1,95 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 2\n2\nffff\nffffffff\n50124400\nffff0002\n2\nfffff\nfedaff0f\n78134400\nffffff02\n2\nf02\n78134401\n78134400\n
-
- .include "testutils.inc"
- start
- moveq -1,r3
- moveq 2,r4
- and.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- moveq 2,r3
- moveq -1,r4
- and.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- move.d 0xffff,r4
- move.d r4,r3
- and.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 ffff
-
- moveq -1,r4
- move.d r4,r3
- and.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- and.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 50124400
-
- moveq -1,r3
- moveq 2,r4
- and.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 ffff0002
-
- moveq 2,r3
- moveq -1,r4
- and.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- move.d 0xfffff,r3
- move.d 0xffff,r4
- and.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 fffff
-
- move.d 0xfedaffaf,r3
- move.d 0xff5f,r4
- and.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 fedaff0f
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- and.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 78134400
-
- moveq -1,r3
- moveq 2,r4
- and.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 ffffff02
-
- moveq 2,r3
- moveq -1,r4
- and.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- move.d 0x5a,r4
- move.d 0xfa7,r3
- and.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 f02
-
- move.d 0x5432f789,r4
- move.d 0x78134453,r3
- and.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 78134401
-
- moveq 0,r7
- and.b r7,r3
- test_move_cc 0 1 0 0
- checkr3 78134400
-
- quit
diff --git a/tests/cris/check_asr.s b/tests/cris/check_asr.s
deleted file mode 100644
index 0a02ae6..0000000
--- a/tests/cris/check_asr.s
+++ /dev/null
@@ -1,230 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: ffffffff\n1\nffffffff\nffffffff\n5a67f\nffffffff\nffffffff\nffffffff\nf699fc67\nffffffff\n1\nffffffff\nffffffff\n5a67f\nda67ffff\nda67ffff\nda67ffff\nda67fc67\nffffffff\nffffffff\n1\nffffffff\nffffffff\n5a670007\nda67f1ff\nda67f1ff\nda67f1ff\nda67f1e7\nffffffff\nffffffff\n1\nffffffff\nffffffff\nffffffff\n5a67f1ff\n5a67f1f9\n0\n5a670000\n
-
- .include "testutils.inc"
- start
- moveq -1,r3
- asrq 0,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq 2,r3
- asrq 1,r3
- test_move_cc 0 0 0 0
- checkr3 1
-
- moveq -1,r3
- asrq 31,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq -1,r3
- asrq 15,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- move.d 0x5a67f19f,r3
- asrq 12,r3
- test_move_cc 0 0 0 0
- checkr3 5a67f
-
- move.d 0xda67f19f,r3
- move.d 31,r4
- asr.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- move.d 0xda67f19f,r3
- move.d 32,r4
- asr.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- move.d 0xda67f19f,r3
- move.d 33,r4
- asr.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- move.d 0xda67f19f,r3
- move.d 66,r4
- asr.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 f699fc67
-
- moveq -1,r3
- moveq 0,r4
- asr.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq 2,r3
- moveq 1,r4
- asr.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 1
-
- moveq -1,r3
- moveq 31,r4
- asr.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq -1,r3
- moveq 15,r4
- asr.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- move.d 0x5a67f19f,r3
- moveq 12,r4
- asr.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 5a67f
-
- move.d 0xda67f19f,r3
- move.d 31,r4
- asr.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 da67ffff
-
- move.d 0xda67f19f,r3
- move.d 32,r4
- asr.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 da67ffff
-
- move.d 0xda67f19f,r3
- move.d 33,r4
- asr.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 da67ffff
-
- move.d 0xda67f19f,r3
- move.d 66,r4
- asr.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 da67fc67
-
- moveq -1,r3
- moveq 0,r4
- asr.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq -1,r3
- moveq 1,r4
- asr.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq 2,r3
- moveq 1,r4
- asr.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 1
-
- moveq -1,r3
- moveq 31,r4
- asr.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq -1,r3
- moveq 15,r4
- asr.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- move.d 0x5a67719f,r3
- moveq 12,r4
- asr.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 5a670007
-
- move.d 0xda67f19f,r3
- move.d 31,r4
- asr.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 da67f1ff
-
- move.d 0xda67f19f,r3
- move.d 32,r4
- asr.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 da67f1ff
-
- move.d 0xda67f19f,r3
- move.d 33,r4
- asr.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 da67f1ff
-
- move.d 0xda67f19f,r3
- move.d 66,r4
- asr.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 da67f1e7
-
- moveq -1,r3
- moveq 0,r4
- asr.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq -1,r3
- moveq 1,r4
- asr.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq 2,r3
- moveq 1,r4
- asr.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 1
-
- moveq -1,r3
- moveq 31,r4
- asr.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq -1,r3
- moveq 15,r4
- asr.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq -1,r3
- moveq 7,r4
- asr.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
-; FIXME: was wrong.
- move.d 0x5a67f19f,r3
- moveq 12,r4
- asr.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 5a67f1ff
-
-; FIXME: was wrong.
- move.d 0x5a67f19f,r3
- moveq 4,r4
- asr.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 5a67f1f9
-
- move.d 0x5a67f19f,r3
- asrq 31,r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- move.d 0x5a67419f,r3
- moveq 16,r4
- asr.w r4,r3
- test_move_cc 0 1 0 0
- checkr3 5a670000
-
- quit
diff --git a/tests/cris/check_ba.s b/tests/cris/check_ba.s
deleted file mode 100644
index 873a408..0000000
--- a/tests/cris/check_ba.s
+++ /dev/null
@@ -1,93 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: a\n
-
-
- .set smalloffset,0
- .set largeoffset,0
-
-
-	.macro fail
-	jump _fail
-	.endm
-
-	.global	main
-main:
- moveq 0,$r3
-
-; Short forward branch.
- ba 0f
- addq 1,$r3
- fail
-
-; Max short forward branch.
-1:
- ba 2f
- addq 1,$r3
- fail
-
-; Short backward branch.
-0:
- ba 1b
- addq 1,$r3
- fail
-
- .space 254-2+smalloffset+1b-.,0
- moveq 0,$r3
-
-2:
-; Transit branch (long).
- ba 3f
- addq 1,$r3
- fail
-
- moveq 0,$r3
-4:
-; Long forward branch.
- ba 5f
- addq 1,$r3
- fail
-
- .space 256-2-smalloffset+4b-.,0
-
- moveq 0,$r3
-
-; Max short backward branch.
-3:
- ba 4b
- addq 1,$r3
- fail
-
-5:
-; Max long forward branch.
- ba 6f
- addq 1,$r3
- fail
-
- .space 32766+largeoffset-2+5b-.,0
-
- moveq 0,$r3
-6:
-; Transit branch.
- ba 7f
- addq 1,$r3
- fail
-
- moveq 0,$r3
-9:
- jsr pass
- nop
-
-; Transit branch.
- moveq 0,$r3
-7:
- ba 8f
- addq 1,$r3
- fail
-
- .space 32768-largeoffset+9b-.,0
-
-8:
-; Max long backward branch.
- ba 9b
- addq 1,$r3
- fail
diff --git a/tests/cris/check_bas.s b/tests/cris/check_bas.s
deleted file mode 100644
index 11929d4..0000000
--- a/tests/cris/check_bas.s
+++ /dev/null
@@ -1,102 +0,0 @@
-# mach: crisv32
-# output: 0\n0\n0\nfb349abc\n0\n12124243\n0\n0\neab5baad\n0\nefb37832\n
-
- .include "testutils.inc"
- start
-x:
- setf zncv
- bsr 0f
- nop
-0:
- test_cc 1 1 1 1
- move srp,r3
- sub.d 0b,r3
- checkr3 0
-
- bas 1f,mof
- moveq 0,r0
-6:
- nop
- quit
-
-2:
- move srp,r3
- sub.d 3f,r3
- checkr3 0
- move srp,r4
- subq 4,r4
- move.d [r4],r3
- checkr3 fb349abc
-
- basc 4f,mof
- nop
- .dword 0x12124243
-7:
- nop
- quit
-
-8:
- move mof,r3
- sub.d 7f,r3
- checkr3 0
-
- move mof,r4
- subq 4,r4
- move.d [r4],r3
- checkr3 eab5baad
-
- jasc 9f,mof
- nop
- .dword 0xefb37832
-0:
- quit
-
- quit
-9:
- move mof,r3
- sub.d 0b,r3
- checkr3 0
-
- move mof,r4
- subq 4,r4
- move.d [r4],r3
- checkr3 efb37832
-
- quit
-
-4:
- move mof,r3
- sub.d 7b,r3
- checkr3 0
- move mof,r4
- subq 4,r4
- move.d [r4],r3
- checkr3 12124243
- basc 5f,bz
- moveq 0,r3
- .dword 0x7634aeba
- quit
-
- .space 32770,0
-1:
- move mof,r3
- sub.d 6b,r3
- checkr3 0
-
- bsrc 2b
- nop
- .dword 0xfb349abc
-3:
-
- quit
-
-5:
- move mof,r3
- sub.d 7b,r3
- checkr3 0
- move.d 8b,r6
- jasc r6,mof
- nop
- .dword 0xeab5baad
-7:
- quit
diff --git a/tests/cris/check_bcc.s b/tests/cris/check_bcc.s
deleted file mode 100644
index c57ffa6..0000000
--- a/tests/cris/check_bcc.s
+++ /dev/null
@@ -1,197 +0,0 @@
-	.global	main
-	.type	main, @function
-main:
-	clearf nzvc
-	setf   nzv
-	bcc    0f
-	addq   1, $r3
-	jump   dofail
-
-0:
-	clearf nzvc
-	setf   nzv
-	bcs    dofail
-	addq   1,$r3
-
-	clearf nzvc
-	setf   ncv
-	bne    1f
-	addq   1, $r3
-
-fail:
-dofail:
-	jump	_fail
-
-1:
-	clearf nzvc
-	setf ncv
-	beq dofail
-	addq 1,$r3
-
-	clearf nzvc
-	setf ncz
-	bvc 2f
-	addq 1,$r3
-	jump dofail
-
-2:
-	clearf nzvc
-	setf ncz
-	bvs dofail
-	addq 1,$r3
-
-	clearf	nzvc
-	setf	vcz
-	bpl	3f
-	addq	1,$r3
-	jump	fail
-3:
-	clearf	nzvc
-	setf	vcz
-	bmi	dofail
-	addq	1,$r3
-
-	clearf	nzvc
-	setf	nv
-	bls	dofail
-	addq	1,$r3
-
-	clearf	nzvc
-	setf	nv
-	bhi	4f
-	addq	1,$r3
-	jump	dofail
-
-4:
-	clearf	nzvc
-	setf	zc
-	bge	5f
-	addq	1,$r3
-	jump	dofail
-
-5:
-	clearf	nzvc
-	setf zc
-	blt dofail
-	addq 1,$r3
-
-	clearf nzvc
-	setf c
-	bgt 6f
-	addq 1,$r3
-	jump  fail
-
-6:
- clearf nzvc
- setf c
- ble dofail
- addq 1,$r3
-
-;;;;;;;;;;
-
- setf nzvc
- clearf nzv
- bcc dofail
- addq 1,$r3
-
- setf nzvc
- clearf nzv
- bcs 0f
- addq 1,$r3
- jump fail
-
-0:
- setf nzvc
- clearf ncv
- bne dofail
- addq 1,$r3
-
- setf nzvc
- clearf ncv
- beq 1f
- addq 1,$r3
- jump fail
-
-1:
- setf nzvc
- clearf ncz
- bvc dofail
- addq 1,$r3
-
- setf nzvc
- clearf ncz
- bvs 2f
- addq 1,$r3
- jump fail
-
-2:
- setf nzvc
- clearf vcz
- bpl dofail
- addq 1,$r3
-
- setf nzvc
- clearf vcz
- bmi 3f
- addq 1,$r3
- jump fail
-
-3:
- setf nzvc
- clearf nv
- bls 4f
- addq 1,$r3
- jump fail
-
-4:
- setf nzvc
- clearf nv
- bhi dofail
- addq 1,$r3
-
- setf zvc
- clearf nzc
- bge dofail
- addq 1,$r3
-
- setf nzc
- clearf vzc
- blt 5f
- addq 1,$r3
- jump fail
-
-5:
- setf nzvc
- clearf c
- bgt dofail
- addq 1,$r3
-
- setf nzvc
- clearf c
- ble 6f
- addq 1,$r3
- jump fail
-
-6:
-	; do a forward branch.
-	ba   2f
-	nop
-	.fill	100
-1:
-	ba	3f
-	nop
-	.fill	800
-2:
-	ba	1b
-	nop
-	.fill	1024
-3:
-
-	moveq	31, $r0
-1:	bne	1b
-	subq	1, $r0
-
-	jsr	pass
-	moveq	0, $r10
-	ret
-	nop
diff --git a/tests/cris/check_bound.c b/tests/cris/check_bound.c
deleted file mode 100644
index e883175..0000000
--- a/tests/cris/check_bound.c
+++ /dev/null
@@ -1,142 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include "sys.h"
-#include "crisutils.h"
-
-static inline int cris_bound_b(int v, int b)
-{
-	int r = v;
-	asm ("bound.b\t%1, %0\n" : "+r" (r) : "ri" (b));
-	return r;
-}
-
-static inline int cris_bound_w(int v, int b)
-{
-	int r = v;
-	asm ("bound.w\t%1, %0\n" : "+r" (r) : "ri" (b));
-	return r;
-}
-
-static inline int cris_bound_d(int v, int b)
-{
-	int r = v;
-	asm ("bound.d\t%1, %0\n" : "+r" (r) : "ri" (b));
-	return r;
-}
-
-int main(void)
-{
-	int r;
-
-	cris_tst_cc_init();
-	r = cris_bound_d(-1, 2);
-	cris_tst_cc(0, 0, 0, 0);
-	if (r != 2)
-		err();
-
-	cris_tst_cc_init();
-	r = cris_bound_d(2, 0xffffffff);
-	cris_tst_cc(0, 0, 0, 0);
-	if (r != 2)
-		err();
-
-	cris_tst_cc_init();
-	r = cris_bound_d(0xffff, 0xffff);
-	cris_tst_cc(0, 0, 0, 0);
-	if (r != 0xffff)
-		err();
-
-	cris_tst_cc_init();
-	r = cris_bound_d(-1, 0xffffffff);
-	cris_tst_cc(1, 0, 0, 0);
-	if (r != 0xffffffff)
-		err();
-
-	cris_tst_cc_init();
-	r = cris_bound_d(0x78134452, 0x5432f789);
-	cris_tst_cc(0, 0, 0, 0);
-	if (r != 0x5432f789)
-		err();
-
-	cris_tst_cc_init();
-	r = cris_bound_w(-1, 2);
-	cris_tst_cc(0, 0, 0, 0);
-	if (r != 2)
-		err();
-
-	cris_tst_cc_init();
-	r = cris_bound_w(-1, 0xffff);
-	cris_tst_cc(0, 0, 0, 0);
-	if (r != 0xffff)
-		err();
-
-	cris_tst_cc_init();
-	r = cris_bound_w(2, 0xffff);
-	cris_tst_cc(0, 0, 0, 0);
-	if (r != 2)
-		err();
-
-	cris_tst_cc_init();
-	r = cris_bound_w(0xfedaffff, 0xffff);
-	cris_tst_cc(0, 0, 0, 0);
-	if (r != 0xffff)
-		err();
-
-	cris_tst_cc_init();
-	r = cris_bound_w(0x78134452, 0xf789);
-	cris_tst_cc(0, 0, 0, 0);
-	if (r != 0xf789)
-		err();
-
-	cris_tst_cc_init();
-	r = cris_bound_b(-1, 2);
-	cris_tst_cc(0, 0, 0, 0);
-	if (r != 2)
-		err();
-
-	cris_tst_cc_init();
-	r = cris_bound_b(2, 0xff);
-	cris_tst_cc(0, 0, 0, 0);
-	if (r != 2)
-		err();
-
-	cris_tst_cc_init();
-	r = cris_bound_b(-1, 0xff);
-	cris_tst_cc(0, 0, 0, 0);
-	if (r != 0xff)
-		err();
-
-	cris_tst_cc_init();
-	r = cris_bound_b(0xff, 0xff);
-	cris_tst_cc(0, 0, 0, 0);
-	if (r != 0xff)
-		err();
-
-	cris_tst_cc_init();
-	r = cris_bound_b(0xfeda49ff, 0xff);
-	cris_tst_cc(0, 0, 0, 0);
-	if (r != 0xff)
-		err();
-
-	cris_tst_cc_init();
-	r = cris_bound_b(0x78134452, 0x89);
-	cris_tst_cc(0, 0, 0, 0);
-	if (r != 0x89)
-		err();
-
-	cris_tst_cc_init();
-	r = cris_bound_w(0x78134452, 0);
-	cris_tst_cc(0, 1, 0, 0);
-	if (r != 0)
-		err();
-
-	cris_tst_cc_init();
-	r = cris_bound_b(0xffff, -1);
-	cris_tst_cc(0, 0, 0, 0);
-	if (r != 0xff)
-		err();
-
-	pass();
-	return 0;
-}
diff --git a/tests/cris/check_boundc.s b/tests/cris/check_boundc.s
deleted file mode 100644
index fb9e5bc..0000000
--- a/tests/cris/check_boundc.s
+++ /dev/null
@@ -1,101 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 2\n2\nffff\nffffffff\n5432f789\n2\nffff\n2\nffff\nffff\nf789\n2\n2\nff\nff\nff\n89\n0\nff\n
-
- .include "testutils.inc"
- start
- moveq -1,r3
- moveq 2,r4
- bound.d 2,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- moveq 2,r3
- bound.d 0xffffffff,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- move.d 0xffff,r3
- bound.d 0xffff,r3
- test_move_cc 0 0 0 0
- checkr3 ffff
-
- moveq -1,r3
- bound.d 0xffffffff,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- move.d 0x78134452,r3
- bound.d 0x5432f789,r3
- test_move_cc 0 0 0 0
- checkr3 5432f789
-
- moveq -1,r3
- bound.w 2,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- moveq -1,r3
- bound.w 0xffff,r3
- test_move_cc 0 0 0 0
- checkr3 ffff
-
- moveq 2,r3
- bound.w 0xffff,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- move.d 0xffff,r3
- bound.w 0xffff,r3
- test_move_cc 0 0 0 0
- checkr3 ffff
-
- move.d 0xfedaffff,r3
- bound.w 0xffff,r3
- test_move_cc 0 0 0 0
- checkr3 ffff
-
- move.d 0x78134452,r3
- bound.w 0xf789,r3
- test_move_cc 0 0 0 0
- checkr3 f789
-
- moveq -1,r3
- bound.b 2,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- moveq 2,r3
- bound.b 0xff,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- moveq -1,r3
- bound.b 0xff,r3
- test_move_cc 0 0 0 0
- checkr3 ff
-
- move.d 0xff,r3
- bound.b 0xff,r3
- test_move_cc 0 0 0 0
- checkr3 ff
-
- move.d 0xfeda49ff,r3
- bound.b 0xff,r3
- test_move_cc 0 0 0 0
- checkr3 ff
-
- move.d 0x78134452,r3
- bound.b 0x89,r3
- test_move_cc 0 0 0 0
- checkr3 89
-
- bound.w 0,r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- move.d 0xffff,r3
- bound.b -1,r3
- test_move_cc 0 0 0 0
- checkr3 ff
-
- quit
diff --git a/tests/cris/check_boundr.s b/tests/cris/check_boundr.s
deleted file mode 100644
index 5c50cc5..0000000
--- a/tests/cris/check_boundr.s
+++ /dev/null
@@ -1,125 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 2\n2\nffff\nffffffff\n5432f789\n2\n2\nffff\nffff\nffff\nf789\n2\n2\nff\nff\n89\nfeda4953\nfeda4962\n0\n0\n
-
- .include "testutils.inc"
- start
- moveq -1,r3
- moveq 2,r4
- bound.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- moveq 2,r3
- moveq -1,r4
- bound.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- move.d 0xffff,r4
- move.d r4,r3
- bound.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 ffff
-
- moveq -1,r4
- move.d r4,r3
- bound.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- bound.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 5432f789
-
- moveq -1,r3
- moveq 2,r4
- bound.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- moveq 2,r3
- moveq -1,r4
- bound.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- moveq -1,r3
- bound.w r3,r3
- test_move_cc 0 0 0 0
- checkr3 ffff
-
- move.d 0xffff,r4
- move.d r4,r3
- bound.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 ffff
-
- move.d 0xfedaffff,r4
- move.d r4,r3
- bound.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 ffff
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- bound.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 f789
-
- moveq -1,r3
- moveq 2,r4
- bound.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- moveq 2,r3
- moveq -1,r4
- bound.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 2
-
- move.d 0xff,r4
- move.d r4,r3
- bound.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 ff
-
- move.d 0xfeda49ff,r4
- move.d r4,r3
- bound.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 ff
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- bound.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 89
-
- move.d 0xfeda4956,r3
- move.d 0xfeda4953,r4
- bound.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 feda4953
-
- move.d 0xfeda4962,r3
- move.d 0xfeda4963,r4
- bound.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 feda4962
-
- move.d 0xfeda4956,r3
- move.d 0,r4
- bound.d r4,r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- move.d 0xfeda4956,r4
- move.d 0,r3
- bound.d r4,r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- quit
diff --git a/tests/cris/check_btst.s b/tests/cris/check_btst.s
deleted file mode 100644
index e39fc8f..0000000
--- a/tests/cris/check_btst.s
+++ /dev/null
@@ -1,96 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 1111\n
-
- .include "testutils.inc"
- start
- clearf nzvc
- moveq -1,r3
- .if 1 ;..asm.arch.cris.v32
- .else
- setf vc
- .endif
- btstq 0,r3
- test_cc 1 0 0 0
-
- moveq 2,r3
- btstq 1,r3
- test_cc 1 0 0 0
-
- moveq 4,r3
- btstq 1,r3
- test_cc 0 1 0 0
-
- moveq -1,r3
- btstq 31,r3
- test_cc 1 0 0 0
-
- move.d 0x5a67f19f,r3
- btstq 12,r3
- test_cc 1 0 0 0
-
- move.d 0xda67f19f,r3
- move.d 29,r4
- btst r4,r3
- test_cc 0 0 0 0
-
- move.d 0xda67f19f,r3
- move.d 32,r4
- btst r4,r3
- test_cc 1 0 0 0
-
- move.d 0xda67f191,r3
- move.d 33,r4
- btst r4,r3
- test_cc 0 0 0 0
-
- moveq -1,r3
- moveq 0,r4
- btst r4,r3
- test_cc 1 0 0 0
-
- moveq 2,r3
- moveq 1,r4
- btst r4,r3
- test_cc 1 0 0 0
-
- moveq -1,r3
- moveq 31,r4
- btst r4,r3
- test_cc 1 0 0 0
-
- moveq 4,r3
- btstq 1,r3
- test_cc 0 1 0 0
-
- moveq -1,r3
- moveq 15,r4
- btst r4,r3
- test_cc 1 0 0 0
-
- move.d 0x5a67f19f,r3
- moveq 12,r4
- btst r4,r3
- test_cc 1 0 0 0
-
- move.d 0x5a678000,r3
- moveq 11,r4
- btst r4,r3
- test_cc 0 1 0 0
-
- move.d 0x5a67f19f,r3
- btst r3,r3
- test_cc 0 0 0 0
-
- move.d 0x1111,r3
- checkr3 1111
-
- ; check that X gets cleared and that only the NZ flags are touched.
- move.d	0xff, $r0
- move $r0, $ccs
- btst r3,r3
- move $ccs, $r0
- and.d 0xff, $r0
- cmp.d	0xe3, $r0
- test_cc 0 1 0 0
-
- quit
diff --git a/tests/cris/check_clearfv32.s b/tests/cris/check_clearfv32.s
deleted file mode 100644
index 4e91360..0000000
--- a/tests/cris/check_clearfv32.s
+++ /dev/null
@@ -1,19 +0,0 @@
-# mach: crisv32
-# output: ef\nef\n
-
-; Check that "clearf x" doesn't trivially fail.
-
- .include "testutils.inc"
- start
- setf puixnzvc
- clearf x	; Actually, x would be cleared by almost-all other insns.
- move ccs,r3
- and.d 0xff, $r3
- checkr3 ef
-
- setf puixnzvc
- moveq 0, $r3	; moveq should only clear the xflag.
- move ccs,r3
- and.d 0xff, $r3
- checkr3 ef
- quit
diff --git a/tests/cris/check_clrjmp1.s b/tests/cris/check_clrjmp1.s
deleted file mode 100644
index 45a7005..0000000
--- a/tests/cris/check_clrjmp1.s
+++ /dev/null
@@ -1,36 +0,0 @@
-# mach: crisv3 crisv8 crisv10 crisv32
-# output: ffffff00\n
-
-; A bug resulting in a non-effectual clear.b discovered running the GCC
-; testsuite; jump actually wrote to p0.
-
- .include "testutils.inc"
-
- start
- jump 1f
- nop
- .p2align 8
-1:
- move.d y,r4
-
- .if 0 ;0 == ..asm.arch.cris.v32
-; There was a bug causing this insn to set special register p0
-; (byte-clear) to 8 (low 8 bits of location after insn).
- jump [r4+]
- .endif
-
-1:
- move.d 0f,r4
-
-; The corresponding bug would cause this insn too, to set p0.
- jump r4
- nop
- quit
-0:
- moveq -1,r3
- clear.b r3
- checkr3 ffffff00
- quit
-
-y:
- .dword 1b
diff --git a/tests/cris/check_cmp-2.s b/tests/cris/check_cmp-2.s
deleted file mode 100644
index 414d370..0000000
--- a/tests/cris/check_cmp-2.s
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-.include "testutils.inc"
-
-	start
-
-	move.d	4294967283, $r0
-	move.d	$r0, $r10
-	cmp.d	$r0, $r10
-	beq	1f
-	move.d $r10, $r3
-	fail
-1:
-	pass
-	quit
diff --git a/tests/cris/check_cmpc.s b/tests/cris/check_cmpc.s
deleted file mode 100644
index 267c9ba..0000000
--- a/tests/cris/check_cmpc.s
+++ /dev/null
@@ -1,86 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: ffffffff\n2\nffff\nffffffff\n78134452\nffffffff\n2\nffff\nfedaffff\n78134452\nffffffff\n2\nff\nfeda49ff\n78134452\n85649282\n
-
- .include "testutils.inc"
- start
- moveq -1,r3
- cmp.d -2,r3
- test_cc 0 0 0 0
- checkr3 ffffffff
-
- moveq 2,r3
- cmp.d 1,r3
- test_cc 0 0 0 0
- checkr3 2
-
- move.d 0xffff,r3
- cmp.d -0xffff,r3
- test_cc 0 0 0 1
- checkr3 ffff
-
- moveq -1,r3
- cmp.d 1,r3
- test_cc 1 0 0 0
- checkr3 ffffffff
-
- move.d 0x78134452,r3
- cmp.d -0x5432f789,r3
- test_cc 1 0 1 1
- checkr3 78134452
-
- moveq -1,r3
- cmp.w -2,r3
- test_cc 0 0 0 0
- checkr3 ffffffff
-
- moveq 2,r3
- cmp.w 1,r3
- test_cc 0 0 0 0
- checkr3 2
-
- move.d 0xffff,r3
- cmp.w 1,r3
- test_cc 1 0 0 0
- checkr3 ffff
-
- move.d 0xfedaffff,r3
- cmp.w 1,r3
- test_cc 1 0 0 0
- checkr3 fedaffff
-
- move.d 0x78134452,r3
- cmp.w 0x877,r3
- test_cc 0 0 0 0
- checkr3 78134452
-
- moveq -1,r3
- cmp.b -2,r3
- test_cc 0 0 0 0
- checkr3 ffffffff
-
- moveq 2,r3
- cmp.b 1,r3
- test_cc 0 0 0 0
- checkr3 2
-
- move.d 0xff,r3
- cmp.b 1,r3
- test_cc 1 0 0 0
- checkr3 ff
-
- move.d 0xfeda49ff,r3
- cmp.b 1,r3
- test_cc 1 0 0 0
- checkr3 feda49ff
-
- move.d 0x78134452,r3
- cmp.b 0x77,r3
- test_cc 1 0 0 1
- checkr3 78134452
-
- move.d 0x85649282,r3
- cmp.b 0x82,r3
- test_cc 0 1 0 0
- checkr3 85649282
-
- quit
diff --git a/tests/cris/check_cmpm.s b/tests/cris/check_cmpm.s
deleted file mode 100644
index e4dde15..0000000
--- a/tests/cris/check_cmpm.s
+++ /dev/null
@@ -1,96 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: ffffffff\n2\nffff\nffffffff\n78134452\nffffffff\n2\nffff\nfedaffff\n78134452\nffffffff\n2\nff\nfeda49ff\n78134452\n85649222\n
-
- .include "testutils.inc"
- .data
-x:
- .dword -2,1,-0xffff,1,-0x5432f789
- .word -2,1,1,0x877
- .byte -2,1,0x77
- .byte 0x22
-
- start
- moveq -1,r3
- move.d x,r5
- cmp.d [r5+],r3
- test_cc 0 0 0 0
- checkr3 ffffffff
-
- moveq 2,r3
- cmp.d [r5],r3
- test_cc 0 0 0 0
- addq 4,r5
- checkr3 2
-
- move.d 0xffff,r3
- cmp.d [r5+],r3
- test_cc 0 0 0 1
- checkr3 ffff
-
- moveq -1,r3
- cmp.d [r5+],r3
- test_cc 1 0 0 0
- checkr3 ffffffff
-
- move.d 0x78134452,r3
- cmp.d [r5+],r3
- test_cc 1 0 1 1
- checkr3 78134452
-
- moveq -1,r3
- cmp.w [r5+],r3
- test_cc 0 0 0 0
- checkr3 ffffffff
-
- moveq 2,r3
- cmp.w [r5+],r3
- test_cc 0 0 0 0
- checkr3 2
-
- move.d 0xffff,r3
- cmp.w [r5],r3
- test_cc 1 0 0 0
- checkr3 ffff
-
- move.d 0xfedaffff,r3
- cmp.w [r5+],r3
- test_cc 1 0 0 0
- checkr3 fedaffff
-
- move.d 0x78134452,r3
- cmp.w [r5+],r3
- test_cc 0 0 0 0
- checkr3 78134452
-
- moveq -1,r3
- cmp.b [r5],r3
- test_cc 0 0 0 0
- addq 1,r5
- checkr3 ffffffff
-
- moveq 2,r3
- cmp.b [r5],r3
- test_cc 0 0 0 0
- checkr3 2
-
- move.d 0xff,r3
- cmp.b [r5],r3
- test_cc 1 0 0 0
- checkr3 ff
-
- move.d 0xfeda49ff,r3
- cmp.b [r5+],r3
- test_cc 1 0 0 0
- checkr3 feda49ff
-
- move.d 0x78134452,r3
- cmp.b [r5+],r3
- test_cc 1 0 0 1
- checkr3 78134452
-
- move.d 0x85649222,r3
- cmp.b [r5],r3
- test_cc 0 1 0 0
- checkr3 85649222
-
- quit
diff --git a/tests/cris/check_cmpq.s b/tests/cris/check_cmpq.s
deleted file mode 100644
index 5469141..0000000
--- a/tests/cris/check_cmpq.s
+++ /dev/null
@@ -1,75 +0,0 @@
-# mach: crisv3 crisv8 crisv10 crisv32
-# output: 1\n1\n1\n1f\n1f\nffffffe1\nffffffe1\nffffffe0\n0\n0\nffffffff\nffffffff\n10000\n100\n5678900\n
-
- .include "testutils.inc"
- start
- moveq 1,r3
- cmpq 1,r3
- test_cc 0 1 0 0
- checkr3 1
-
- cmpq -1,r3
- test_cc 0 0 0 1
- checkr3 1
-
- cmpq 31,r3
- test_cc 1 0 0 1
- checkr3 1
-
- moveq 31,r3
- cmpq 31,r3
- test_cc 0 1 0 0
- checkr3 1f
-
- cmpq -31,r3
- test_cc 0 0 0 1
- checkr3 1f
-
- movs.b -31,r3
- cmpq -31,r3
- test_cc 0 1 0 0
- checkr3 ffffffe1
-
- cmpq -32,r3
- test_cc 0 0 0 0
- checkr3 ffffffe1
-
- movs.b -32,r3
- cmpq -32,r3
- test_cc 0 1 0 0
- checkr3 ffffffe0
-
- moveq 0,r3
- cmpq 1,r3
- test_cc 1 0 0 1
- checkr3 0
-
- cmpq -32,r3
- test_cc 0 0 0 1
- checkr3 0
-
- moveq -1,r3
- cmpq 1,r3
- test_cc 1 0 0 0
- checkr3 ffffffff
-
- cmpq -1,r3
- test_cc 0 1 0 0
- checkr3 ffffffff
-
- move.d 0x10000,r3
- cmpq 1,r3
- test_cc 0 0 0 0
- checkr3 10000
-
- move.d 0x100,r3
- cmpq 1,r3
- test_cc 0 0 0 0
- checkr3 100
-
- move.d 0x5678900,r3
- cmpq 7,r3
- test_cc 0 0 0 0
- checkr3 5678900
-
- quit
diff --git a/tests/cris/check_cmpr.s b/tests/cris/check_cmpr.s
deleted file mode 100644
index b30af7a..0000000
--- a/tests/cris/check_cmpr.s
+++ /dev/null
@@ -1,102 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: ffffffff\n2\nffff\nffffffff\n78134452\nffffffff\n2\nffff\nfedaffff\n78134452\nffffffff\n2\nff\nfeda49ff\n78134452\n85649222\n
-
- .include "testutils.inc"
- start
- moveq -1,r3
- moveq -2,r4
- cmp.d r4,r3
- test_cc 0 0 0 0
- checkr3 ffffffff
-
- moveq 2,r3
- moveq 1,r4
- cmp.d r4,r3
- test_cc 0 0 0 0
- checkr3 2
-
- move.d 0xffff,r3
- move.d -0xffff,r4
- cmp.d r4,r3
- test_cc 0 0 0 1
- checkr3 ffff
-
- moveq 1,r4
- moveq -1,r3
- cmp.d r4,r3
- test_cc 1 0 0 0
- checkr3 ffffffff
-
- move.d -0x5432f789,r4
- move.d 0x78134452,r3
- cmp.d r4,r3
- test_cc 1 0 1 1
- checkr3 78134452
-
- moveq -1,r3
- moveq -2,r4
- cmp.w r4,r3
- test_cc 0 0 0 0
- checkr3 ffffffff
-
- moveq 2,r3
- moveq 1,r4
- cmp.w r4,r3
- test_cc 0 0 0 0
- checkr3 2
-
- move.d 0xffff,r3
- move.d -0xffff,r4
- cmp.w r4,r3
- test_cc 1 0 0 0
- checkr3 ffff
-
- move.d 0xfedaffff,r3
- move.d -0xfedaffff,r4
- cmp.w r4,r3
- test_cc 1 0 0 0
- checkr3 fedaffff
-
- move.d -0x5432f789,r4
- move.d 0x78134452,r3
- cmp.w r4,r3
- test_cc 0 0 0 0
- checkr3 78134452
-
- moveq -1,r3
- moveq -2,r4
- cmp.b r4,r3
- test_cc 0 0 0 0
- checkr3 ffffffff
-
- moveq 2,r3
- moveq 1,r4
- cmp.b r4,r3
- test_cc 0 0 0 0
- checkr3 2
-
- move.d -0xff,r4
- move.d 0xff,r3
- cmp.b r4,r3
- test_cc 1 0 0 0
- checkr3 ff
-
- move.d -0xfeda49ff,r4
- move.d 0xfeda49ff,r3
- cmp.b r4,r3
- test_cc 1 0 0 0
- checkr3 feda49ff
-
- move.d -0x5432f789,r4
- move.d 0x78134452,r3
- cmp.b r4,r3
- test_cc 1 0 0 1
- checkr3 78134452
-
- move.d 0x85649222,r3
- move.d 0x77445622,r4
- cmp.b r4,r3
- test_cc 0 1 0 0
- checkr3 85649222
-
- quit
diff --git a/tests/cris/check_cmpxc.s b/tests/cris/check_cmpxc.s
deleted file mode 100644
index b237a93..0000000
--- a/tests/cris/check_cmpxc.s
+++ /dev/null
@@ -1,92 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 2\n2\n2\n2\nffff\nffff\nffff\nffff\nffffffff\nffffffff\nffffffff\n78134452\n78134452\n78134452\n78134452\n4452\n80000032\n
-
- .include "testutils.inc"
- start
- moveq 2,r3
- cmps.b 0xff,r3
- test_cc 0 0 0 1
- checkr3 2
-
- moveq 2,r3
- cmps.w 0xffff,r3
- test_cc 0 0 0 1
- checkr3 2
-
- moveq 2,r3
- cmpu.b 0xff,r3
- test_cc 1 0 0 1
- checkr3 2
-
- moveq 2,r3
- move.d 0xffffffff,r4
- cmpu.w -1,r3
- test_cc 1 0 0 1
- checkr3 2
-
- move.d 0xffff,r3
- cmpu.b -1,r3
- test_cc 0 0 0 0
- checkr3 ffff
-
- move.d 0xffff,r3
- cmpu.w -1,r3
- test_cc 0 1 0 0
- checkr3 ffff
-
- move.d 0xffff,r3
- cmps.b 0xff,r3
- test_cc 0 0 0 1
- checkr3 ffff
-
- move.d 0xffff,r3
- cmps.w 0xffff,r3
- test_cc 0 0 0 1
- checkr3 ffff
-
- moveq -1,r3
- cmps.b 0xff,r3
- test_cc 0 1 0 0
- checkr3 ffffffff
-
- moveq -1,r3
- cmps.w 0xff,r3
- test_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq -1,r3
- cmps.w 0xffff,r3
- test_cc 0 1 0 0
- checkr3 ffffffff
-
- move.d 0x78134452,r3
- cmpu.b 0x89,r3
- test_cc 0 0 0 0
- checkr3 78134452
-
- move.d 0x78134452,r3
- cmps.b 0x89,r3
- test_cc 0 0 0 1
- checkr3 78134452
-
- move.d 0x78134452,r3
- cmpu.w 0xf789,r3
- test_cc 0 0 0 0
- checkr3 78134452
-
- move.d 0x78134452,r3
- cmps.w 0xf789,r3
- test_cc 0 0 0 1
- checkr3 78134452
-
- move.d 0x4452,r3
- cmps.w 0x8002,r3
- test_cc 0 0 0 1
- checkr3 4452
-
- move.d 0x80000032,r3
- cmpu.w 0x764,r3
- test_cc 0 0 1 0
- checkr3 80000032
-
- quit
diff --git a/tests/cris/check_cmpxm.s b/tests/cris/check_cmpxm.s
deleted file mode 100644
index 87ea5bf..0000000
--- a/tests/cris/check_cmpxm.s
+++ /dev/null
@@ -1,106 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 2\n2\n2\n2\nffff\nffff\nffff\nffff\nffffffff\nffffffff\nffffffff\n78134452\n78134452\n78134452\n78134452\n4452\n80000032\n
-
- .include "testutils.inc"
- .data
-x:
- .byte 0xff
- .word 0xffff
- .word 0xff
- .word 0xffff
- .byte 0x89
- .word 0xf789
- .word 0x8002
- .word 0x764
-
- start
- moveq 2,r3
- move.d x,r5
- cmps.b [r5+],r3
- test_cc 0 0 0 1
- checkr3 2
-
- moveq 2,r3
- cmps.w [r5+],r3
- test_cc 0 0 0 1
- checkr3 2
-
- moveq 2,r3
- subq 3,r5
- cmpu.b [r5+],r3
- test_cc 1 0 0 1
- checkr3 2
-
- moveq 2,r3
- cmpu.w [r5+],r3
- test_cc 1 0 0 1
- subq 3,r5
- checkr3 2
-
- move.d 0xffff,r3
- cmpu.b [r5],r3
- test_cc 0 0 0 0
- checkr3 ffff
-
- move.d 0xffff,r3
- cmpu.w [r5],r3
- test_cc 0 1 0 0
- checkr3 ffff
-
- move.d 0xffff,r3
- cmps.b [r5],r3
- test_cc 0 0 0 1
- checkr3 ffff
-
- move.d 0xffff,r3
- cmps.w [r5],r3
- test_cc 0 0 0 1
- checkr3 ffff
-
- moveq -1,r3
- cmps.b [r5],r3
- test_cc 0 1 0 0
- addq 3,r5
- checkr3 ffffffff
-
- moveq -1,r3
- cmps.w [r5+],r3
- test_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq -1,r3
- cmps.w [r5+],r3
- test_cc 0 1 0 0
- checkr3 ffffffff
-
- move.d 0x78134452,r3
- cmpu.b [r5],r3
- test_cc 0 0 0 0
- checkr3 78134452
-
- move.d 0x78134452,r3
- cmps.b [r5+],r3
- test_cc 0 0 0 1
- checkr3 78134452
-
- move.d 0x78134452,r3
- cmpu.w [r5],r3
- test_cc 0 0 0 0
- checkr3 78134452
-
- move.d 0x78134452,r3
- cmps.w [r5+],r3
- test_cc 0 0 0 1
- checkr3 78134452
-
- move.d 0x4452,r3
- cmps.w [r5+],r3
- test_cc 0 0 0 1
- checkr3 4452
-
- move.d 0x80000032,r3
- cmpu.w [r5+],r3
- test_cc 0 0 1 0
- checkr3 80000032
-
- quit
diff --git a/tests/cris/check_dstep.s b/tests/cris/check_dstep.s
deleted file mode 100644
index bd43b83..0000000
--- a/tests/cris/check_dstep.s
+++ /dev/null
@@ -1,42 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: fffffffc\n4\nffff\nfffffffe\n9bf3911b\n0\n
-
- .include "testutils.inc"
- start
- moveq -1,r3
- moveq 2,r4
- dstep r4,r3
- test_move_cc 1 0 0 0
- checkr3 fffffffc
-
- moveq 2,r3
- moveq -1,r4
- dstep r4,r3
- test_move_cc 0 0 0 0
- checkr3 4
-
- move.d 0xffff,r4
- move.d r4,r3
- dstep r4,r3
- test_move_cc 0 0 0 0
- checkr3 ffff
-
- moveq -1,r4
- move.d r4,r3
- dstep r4,r3
- test_move_cc 1 0 0 0
- checkr3 fffffffe
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- dstep r4,r3
- test_move_cc 1 0 0 0
- checkr3 9bf3911b
-
- move.d 0xffff,r3
- move.d 0x1fffe,r4
- dstep r4,r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- quit
diff --git a/tests/cris/check_ftag.c b/tests/cris/check_ftag.c
deleted file mode 100644
index 908773a..0000000
--- a/tests/cris/check_ftag.c
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include "sys.h"
-#include "crisutils.h"
-
-static inline void cris_ftag_i(unsigned int x)
-{
-	register unsigned int v asm("$r10") = x;
-	asm ("ftagi\t[%0]\n" : : "r" (v) );
-}
-static inline void cris_ftag_d(unsigned int x)
-{
-	register unsigned int v asm("$r10") = x;
-	asm ("ftagd\t[%0]\n" : : "r" (v) );
-}
-static inline void cris_fidx_i(unsigned int x)
-{
-	register unsigned int v asm("$r10") = x;
-	asm ("fidxi\t[%0]\n" : : "r" (v) );
-}
-static inline void cris_fidx_d(unsigned int x)
-{
-	register unsigned int v asm("$r10") = x;
-	asm ("fidxd\t[%0]\n" : : "r" (v) );
-}
-
-
-int main(void)
-{
-	cris_ftag_i(0);
-	cris_ftag_d(0);
-	cris_fidx_i(0);
-	cris_fidx_d(0);
-	pass();
-	return 0;
-}
diff --git a/tests/cris/check_gcctorture_pr28634-1.c b/tests/cris/check_gcctorture_pr28634-1.c
deleted file mode 100644
index 45ecd15..0000000
--- a/tests/cris/check_gcctorture_pr28634-1.c
+++ /dev/null
@@ -1,15 +0,0 @@
-/* PR rtl-optimization/28634.  On targets with delayed branches,
-   dbr_schedule could do the next iteration's addition in the
-   branch delay slot, then subtract the value again if the branch
-   wasn't taken.  This can lead to rounding errors.  */
-int x = -1;
-int y = 1;
-int
-main (void)
-{
-  while (y > 0)
-    y += x;
-  if (y != x + 1)
-    abort ();
-  exit (0);
-}
diff --git a/tests/cris/check_gcctorture_pr28634.c b/tests/cris/check_gcctorture_pr28634.c
deleted file mode 100644
index a0c5254..0000000
--- a/tests/cris/check_gcctorture_pr28634.c
+++ /dev/null
@@ -1,15 +0,0 @@
-/* PR rtl-optimization/28634.  On targets with delayed branches,
-   dbr_schedule could do the next iteration's addition in the
-   branch delay slot, then subtract the value again if the branch
-   wasn't taken.  This can lead to rounding errors.  */
-double x = -0x1.0p53;
-double y = 1;
-int
-main (void)
-{
-  while (y > 0)
-    y += x;
-  if (y != x + 1)
-    abort ();
-  exit (0);
-}
diff --git a/tests/cris/check_glibc_kernelversion.c b/tests/cris/check_glibc_kernelversion.c
deleted file mode 100644
index 0744872..0000000
--- a/tests/cris/check_glibc_kernelversion.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Check the lz insn.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include "sys.h"
-
-#define __LINUX_KERNEL_VERSION 131584
-
-#define DL_SYSDEP_OSCHECK(FATAL) \
-  do {                                                                        \
-    /* Test whether the kernel is new enough.  This test is only              \
-       performed if the library is not compiled to run on all                 \
-       kernels.  */                                                           \
-    if (__LINUX_KERNEL_VERSION > 0)                                           \
-      {                                                                       \
-        char bufmem[64];                                                      \
-        char *buf = bufmem;                                                   \
-        unsigned int version;                                                 \
-        int parts;                                                            \
-        char *cp;                                                             \
-        struct utsname uts;                                                   \
-                                                                              \
-        /* Try the uname syscall */                                           \
-        if (__uname (&uts))                                                   \
-          {                                                                   \
-            /* This was not successful.  Now try reading the /proc            \
-               filesystem.  */                                                \
-            ssize_t reslen;                                                   \
-            int fd = __open ("/proc/sys/kernel/osrelease", O_RDONLY);         \
-            if (fd == -1                                                      \
-                || (reslen = __read (fd, bufmem, sizeof (bufmem))) <= 0)      \
-              /* This also didn't work.  We give up since we cannot           \
-                 make sure the library can actually work.  */                 \
-              FATAL ("FATAL: cannot determine library version\n");            \
-            __close (fd);                                                     \
-            buf[MIN (reslen, (ssize_t) sizeof (bufmem) - 1)] = '\0';          \
-          }                                                                   \
-        else                                                                  \
-          buf = uts.release;                                                  \
-                                                                              \
-        /* Now convert it into a number.  The string consists of at most      \
-           three parts.  */                                                   \
-        version = 0;                                                          \
-        parts = 0;                                                            \
-        cp = buf;                                                             \
-        while ((*cp >= '0') && (*cp <= '9'))                                  \
-          {                                                                   \
-            unsigned int here = *cp++ - '0';                                  \
-                                                                              \
-            while ((*cp >= '0') && (*cp <= '9'))                              \
-              {                                                               \
-                here *= 10;                                                   \
-                here += *cp++ - '0';                                          \
-              }                                                               \
-                                                                              \
-            ++parts;                                                          \
-            version <<= 8;                                                    \
-            version |= here;                                                  \
-                                                                              \
-            if (*cp++ != '.')                                                 \
-              /* Another part following?  */                                  \
-              break;                                                          \
-          }                                                                   \
-                                                                              \
-        if (parts < 3)                                                        \
-          version <<= 8 * (3 - parts);                                        \
-                                                                              \
-        /* Now we can test with the required version.  */                     \
-        if (version < __LINUX_KERNEL_VERSION)                                 \
-          /* Not sufficient.  */                                               \
-          FATAL ("FATAL: kernel too old\n");                                  \
-                                                                              \
-        _dl_osversion = version;                                              \
-      }                                                                       \
-  } while (0)
-
-int main(void)
-{
-        char bufmem[64] = "2.6.22";
-        char *buf = bufmem;
-        unsigned int version;
-        int parts;
-        char *cp;
-
-        version = 0;
-        parts = 0;
-        cp = buf;
-        while ((*cp >= '0') && (*cp <= '9'))
-          {
-            unsigned int here = *cp++ - '0';
-
-            while ((*cp >= '0') && (*cp <= '9'))
-              {
-                here *= 10;
-                here += *cp++ - '0';
-              }
-
-            ++parts;
-            version <<= 8;
-            version |= here;
-
-            if (*cp++ != '.')
-              /* Another part following?  */
-              break;
-          }
-
-        if (parts < 3)
-          version <<= 8 * (3 - parts);
-	if (version < __LINUX_KERNEL_VERSION)
-		err();
-	pass();
-	exit(0);
-}
diff --git a/tests/cris/check_hello.c b/tests/cris/check_hello.c
deleted file mode 100644
index fb403ba..0000000
--- a/tests/cris/check_hello.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-int main ()
-{
-  printf ("pass\n");
-  exit (0);
-}
diff --git a/tests/cris/check_int64.c b/tests/cris/check_int64.c
deleted file mode 100644
index fc60017..0000000
--- a/tests/cris/check_int64.c
+++ /dev/null
@@ -1,47 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include "sys.h"
-#include "crisutils.h"
-
-
-static inline int64_t add64(const int64_t a, const int64_t b)
-{
-	return a + b;
-}
-
-static inline int64_t sub64(const int64_t a, const int64_t b)
-{
-	return a - b;
-}
-
-int main(void)
-{
-	int64_t a = 1;
-	int64_t b = 2;
-
-	/* FIXME: add some tests.  */
-	a = add64(a, b);
-	if (a != 3)
-		err();
-
-	a = sub64(a, b);
-	if (a != 1)
-		err();
-
-	a = add64(a, -4);
-	if (a != -3)
-		err();
-
-	a = add64(a, 3);
-	if (a != 0)
-		err();
-
-	a = 0;
-	a = sub64(a, 1);
-	if (a != -1)
-		err();
-
-	pass();
-	return 0;
-}
diff --git a/tests/cris/check_jsr.s b/tests/cris/check_jsr.s
deleted file mode 100644
index 1060237..0000000
--- a/tests/cris/check_jsr.s
+++ /dev/null
@@ -1,85 +0,0 @@
-# mach: crisv3 crisv8 crisv10 crisv32
-# output: 0\n0\n0\n0\n0\n0\n
-
-# Test that jsr Rn and jsr [PC+] work.
-
- .include "testutils.inc"
- start
-x:
- move.d 0f,r6
- setf nzvc
- jsr r6
- .if 1; ..asm.arch.cris.v32
- nop
- .endif
-0:
- test_move_cc 1 1 1 1
- move srp,r3
- sub.d 0b,r3
- checkr3 0
-
- move.d 1f,r0
- setf nzvc
- jsr r0
- .if 1 ; ..asm.arch.cris.v32
- moveq 0,r0
- .endif
-6:
- nop
- quit
-
-2:
- test_move_cc 0 0 0 0
- move srp,r3
- sub.d 3f,r3
- checkr3 0
- jsr 4f
- .if 1 ; ..asm.arch.cris.v32
- nop
- .endif
-7:
- nop
- quit
-
-8:
- move srp,r3
- sub.d 7b,r3
- checkr3 0
- quit
-
-4:
- move srp,r3
- sub.d 7b,r3
- checkr3 0
- move.d 5f,r3
- jump r3
- .if 1; ..asm.arch.cris.v32
- moveq 0,r3
- .endif
- quit
-
- .space 32770,0
-1:
- test_move_cc 1 1 1 1
- move srp,r3
- sub.d 6b,r3
- checkr3 0
-
- clearf cznv
- jsr 2b
- .if 1; ..asm.arch.cris.v32
- nop
- .endif
-3:
-
- quit
-
-5:
- move srp,r3
- sub.d 7b,r3
- checkr3 0
- jump 8b
- .if 1 ; ..asm.arch.cris.v32
- nop
- .endif
- quit
diff --git a/tests/cris/check_lapc.s b/tests/cris/check_lapc.s
deleted file mode 100644
index 9a6150b..0000000
--- a/tests/cris/check_lapc.s
+++ /dev/null
@@ -1,78 +0,0 @@
-# mach: crisv32
-# output: 0\n0\nfffffffa\nfffffffe\nffffffda\n1e\n1e\n0\n
-
-.include "testutils.inc"
-
-; To accommodate dumpr3 with more than one instruction, keep it
-; out of lapc operand ranges and difference calculations.
-
- start
- lapc.d 0f,r3
-0:
- sub.d .,r3
- checkr3 0
-
- lapcq 0f,r3
-0:
- sub.d .,r3
- checkr3 0
-
- lapc.d .,r3
- sub.d .,r3
- checkr3 fffffffa
-
- lapcq .,r3
- sub.d .,r3
- checkr3 fffffffe
-
-0:
- .rept 16
- nop
- .endr
- lapc.d 0b,r3
- sub.d .,r3
- checkr3 ffffffda
-
- setf zcvn
- lapc.d 0f,r3
- test_cc 1 1 1 1
- sub.d .,r3
- nop
- nop
- nop
- nop
- nop
- nop
- nop
- nop
- nop
- nop
- nop
- nop
-0:
- checkr3 1e
-0:
- lapcq 0f,r3
- sub.d 0b,r3
- nop
- nop
- nop
- nop
- nop
- nop
- nop
- nop
- nop
- nop
- nop
-0:
- checkr3 1e
- clearf cn
- setf zv
-1:
- lapcq .,r3
- test_cc 0 1 1 0
- sub.d 1b,r3
- checkr3 0
-
- quit
diff --git a/tests/cris/check_lsl.s b/tests/cris/check_lsl.s
deleted file mode 100644
index 9e2ddd7..0000000
--- a/tests/cris/check_lsl.s
+++ /dev/null
@@ -1,217 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: ffffffff\n4\n80000000\nffff8000\n7f19f000\n80000000\n0\n0\n699fc67c\nffffffff\n4\n80000000\nffff8000\n7f19f000\nda670000\nda670000\nda670000\nda67c67c\nffffffff\nfffafffe\n4\nffff0000\nffff8000\n5a67f000\nda67f100\nda67f100\nda67f100\nda67f17c\nfff3faff\nfff3fafe\n4\nffffff00\nffffff00\nffffff80\n5a67f100\n5a67f1f0\n
-
- .include "testutils.inc"
- start
- moveq -1,r3
- lslq 0,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq 2,r3
- lslq 1,r3
- test_move_cc 0 0 0 0
- checkr3 4
-
- moveq -1,r3
- lslq 31,r3
- test_move_cc 1 0 0 0
- checkr3 80000000
-
- moveq -1,r3
- lslq 15,r3
- test_move_cc 1 0 0 0
- checkr3 ffff8000
-
- move.d 0x5a67f19f,r3
- lslq 12,r3
- test_move_cc 0 0 0 0
- checkr3 7f19f000
-
- move.d 0xda67f19f,r3
- move.d 31,r4
- lsl.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 80000000
-
- move.d 0xda67f19f,r3
- move.d 32,r4
- lsl.d r4,r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- move.d 0xda67f19f,r3
- move.d 33,r4
- lsl.d r4,r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- move.d 0xda67f19f,r3
- move.d 66,r4
- lsl.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 699fc67c
-
- moveq -1,r3
- moveq 0,r4
- lsl.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq 2,r3
- moveq 1,r4
- lsl.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 4
-
- moveq -1,r3
- moveq 31,r4
- lsl.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 80000000
-
- moveq -1,r3
- moveq 15,r4
- lsl.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffff8000
-
- move.d 0x5a67f19f,r3
- moveq 12,r4
- lsl.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 7f19f000
-
- move.d 0xda67f19f,r3
- move.d 31,r4
- lsl.w r4,r3
- test_move_cc 0 1 0 0
- checkr3 da670000
-
- move.d 0xda67f19f,r3
- move.d 32,r4
- lsl.w r4,r3
- test_move_cc 0 1 0 0
- checkr3 da670000
-
- move.d 0xda67f19f,r3
- move.d 33,r4
- lsl.w r4,r3
- test_move_cc 0 1 0 0
- checkr3 da670000
-
- move.d 0xda67f19f,r3
- move.d 66,r4
- lsl.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 da67c67c
-
- moveq -1,r3
- moveq 0,r4
- lsl.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- move.d 0xfffaffff,r3
- moveq 1,r4
- lsl.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 fffafffe
-
- moveq 2,r3
- moveq 1,r4
- lsl.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 4
-
- moveq -1,r3
- moveq 31,r4
- lsl.w r4,r3
- test_move_cc 0 1 0 0
- checkr3 ffff0000
-
- moveq -1,r3
- moveq 15,r4
- lsl.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffff8000
-
- move.d 0x5a67f19f,r3
- moveq 12,r4
- lsl.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 5a67f000
-
- move.d 0xda67f19f,r3
- move.d 31,r4
- lsl.b r4,r3
- test_move_cc 0 1 0 0
- checkr3 da67f100
-
- move.d 0xda67f19f,r3
- move.d 32,r4
- lsl.b r4,r3
- test_move_cc 0 1 0 0
- checkr3 da67f100
-
- move.d 0xda67f19f,r3
- move.d 33,r4
- lsl.b r4,r3
- test_move_cc 0 1 0 0
- checkr3 da67f100
-
- move.d 0xda67f19f,r3
- move.d 66,r4
- lsl.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 da67f17c
-
- move.d 0xfff3faff,r3
- moveq 0,r4
- lsl.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 fff3faff
-
- move.d 0xfff3faff,r3
- moveq 1,r4
- lsl.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 fff3fafe
-
- moveq 2,r3
- moveq 1,r4
- lsl.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 4
-
- moveq -1,r3
- moveq 31,r4
- lsl.b r4,r3
- test_move_cc 0 1 0 0
- checkr3 ffffff00
-
- moveq -1,r3
- moveq 15,r4
- lsl.b r4,r3
- test_move_cc 0 1 0 0
- checkr3 ffffff00
-
- moveq -1,r3
- moveq 7,r4
- lsl.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffff80
-
- move.d 0x5a67f19f,r3
- moveq 12,r4
- lsl.b r4,r3
- test_move_cc 0 1 0 0
- checkr3 5a67f100
-
- move.d 0x5a67f19f,r3
- moveq 4,r4
- lsl.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 5a67f1f0
-
- quit
diff --git a/tests/cris/check_lsr.s b/tests/cris/check_lsr.s
deleted file mode 100644
index 18fdbef..0000000
--- a/tests/cris/check_lsr.s
+++ /dev/null
@@ -1,218 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: ffffffff\n1\n1\n1ffff\n5a67f\n1\n0\n0\n3699fc67\nffffffff\n1\n1\n1ffff\n5a67f\nda670000\nda670000\nda670000\nda673c67\nffffffff\nffff7fff\n1\nffff0000\nffff0001\n5a67000f\nda67f100\nda67f100\nda67f100\nda67f127\nffffffff\nffffff7f\n1\nffffff00\nffffff00\nffffff01\n5a67f100\n5a67f109\n
-
- .include "testutils.inc"
- start
- moveq -1,r3
- lsrq 0,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq 2,r3
- lsrq 1,r3
- test_move_cc 0 0 0 0
- checkr3 1
-
- moveq -1,r3
- lsrq 31,r3
- test_move_cc 0 0 0 0
- checkr3 1
-
- moveq -1,r3
- lsrq 15,r3
- test_move_cc 0 0 0 0
- checkr3 1ffff
-
- move.d 0x5a67f19f,r3
- lsrq 12,r3
- test_move_cc 0 0 0 0
- checkr3 5a67f
-
- move.d 0xda67f19f,r3
- move.d 31,r4
- lsr.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 1
-
- move.d 0xda67f19f,r3
- move.d 32,r4
- lsr.d r4,r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- move.d 0xda67f19f,r3
- move.d 33,r4
- lsr.d r4,r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- move.d 0xda67f19f,r3
- move.d 66,r4
- lsr.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 3699fc67
-
- moveq -1,r3
- moveq 0,r4
- lsr.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq 2,r3
- moveq 1,r4
- lsr.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 1
-
- moveq -1,r3
- moveq 31,r4
- lsr.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 1
-
- moveq -1,r3
- moveq 15,r4
- lsr.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 1ffff
-
- move.d 0x5a67f19f,r3
- moveq 12,r4
- lsr.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 5a67f
-
- move.d 0xda67f19f,r3
- move.d 31,r4
- lsr.w r4,r3
- test_move_cc 0 1 0 0
- checkr3 da670000
-
- move.d 0xda67f19f,r3
- move.d 32,r4
- lsr.w r4,r3
- test_move_cc 0 1 0 0
- checkr3 da670000
-
- move.d 0xda67f19f,r3
- move.d 33,r4
- lsr.w r4,r3
- test_move_cc 0 1 0 0
- checkr3 da670000
-
- move.d 0xda67f19f,r3
- move.d 66,r4
- lsr.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 da673c67
-
- moveq -1,r3
- moveq 0,r4
- lsr.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq -1,r3
- moveq 1,r4
- lsr.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 ffff7fff
-
- moveq 2,r3
- moveq 1,r4
- lsr.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 1
-
-;; FIXME: this was wrong. Z should be set.
- moveq -1,r3
- moveq 31,r4
- lsr.w r4,r3
- test_move_cc 0 1 0 0
- checkr3 ffff0000
-
- moveq -1,r3
- moveq 15,r4
- lsr.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 ffff0001
-
- move.d 0x5a67f19f,r3
- moveq 12,r4
- lsr.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 5a67000f
-
- move.d 0xda67f19f,r3
- move.d 31,r4
- lsr.b r4,r3
- test_move_cc 0 1 0 0
- checkr3 da67f100
-
- move.d 0xda67f19f,r3
- move.d 32,r4
- lsr.b r4,r3
- test_move_cc 0 1 0 0
- checkr3 da67f100
-
- move.d 0xda67f19f,r3
- move.d 33,r4
- lsr.b r4,r3
- test_move_cc 0 1 0 0
- checkr3 da67f100
-
- move.d 0xda67f19f,r3
- move.d 66,r4
- lsr.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 da67f127
-
- moveq -1,r3
- moveq 0,r4
- lsr.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq -1,r3
- moveq 1,r4
- lsr.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 ffffff7f
-
- moveq 2,r3
- moveq 1,r4
- lsr.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 1
-
- moveq -1,r3
- moveq 31,r4
- lsr.b r4,r3
- test_move_cc 0 1 0 0
- checkr3 ffffff00
-
- moveq -1,r3
- moveq 15,r4
- lsr.b r4,r3
- test_move_cc 0 1 0 0
- checkr3 ffffff00
-
- moveq -1,r3
- moveq 7,r4
- lsr.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 ffffff01
-
- move.d 0x5a67f19f,r3
- moveq 12,r4
- lsr.b r4,r3
- test_move_cc 0 1 0 0
- checkr3 5a67f100
-
- move.d 0x5a67f19f,r3
- moveq 4,r4
- lsr.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 5a67f109
-
- quit
diff --git a/tests/cris/check_lz.c b/tests/cris/check_lz.c
deleted file mode 100644
index 69c2e6d..0000000
--- a/tests/cris/check_lz.c
+++ /dev/null
@@ -1,49 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include "sys.h"
-
-static inline int cris_lz(int x)
-{
-	int r;
-	asm ("lz\t%1, %0\n" : "=r" (r) : "r" (x));
-	return r;
-}
-
-void check_lz(void)
-{
-	int i;
-
-	if (cris_lz(0) != 32)
-		err();
-	if (cris_lz(1) != 31)
-		err();
-	if (cris_lz(2) != 30)
-		err();
-	if (cris_lz(4) != 29)
-		err();
-	if (cris_lz(8) != 28)
-		err();
-
-	/* try all positions with a single bit.  */
-	for (i = 1; i < 32; i++) {
-		if (cris_lz(1 << (i-1)) != (32 - i))
-			err();
-	}
-
-	/* try all positions with all bits.  */
-	for (i = 1; i < 32; i++) {
-		/* split up this computation to clarify it.  */
-		uint32_t val;
-		val = (unsigned int)-1 >> (32 - i);
-		if (cris_lz(val) != (32 - i))
-			err();
-	}
-}
-
-int main(void)
-{
-	check_lz();
-	pass();
-	exit(0);
-}
diff --git a/tests/cris/check_mapbrk.c b/tests/cris/check_mapbrk.c
deleted file mode 100644
index 1aff762..0000000
--- a/tests/cris/check_mapbrk.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-/* Basic sanity check that syscalls to implement malloc (brk, mmap2,
-   munmap) are trivially functional.  */
-
-int main ()
-{
-  void *p1, *p2, *p3, *p4, *p5, *p6;
-
-  if ((p1 = malloc (8100)) == NULL
-      || (p2 = malloc (16300)) == NULL
-      || (p3 = malloc (4000)) == NULL
-      || (p4 = malloc (500)) == NULL
-      || (p5 = malloc (1023*1024)) == NULL
-      || (p6 = malloc (8191*1024)) == NULL)
-  {
-    printf ("fail\n");
-    exit (1);
-  }
-
-  free (p1);
-  free (p2);
-  free (p3);
-  free (p4);
-  free (p5);
-  free (p6);
-
-  p1 = malloc (64000);
-  if (p1 == NULL)
-  {
-    printf ("fail\n");
-    exit (1);
-  }
-  free (p1);
-
-  printf ("pass\n");
-  exit (0);
-}
diff --git a/tests/cris/check_mcp.s b/tests/cris/check_mcp.s
deleted file mode 100644
index e65ccdd..0000000
--- a/tests/cris/check_mcp.s
+++ /dev/null
@@ -1,49 +0,0 @@
-# mach: crisv32
-# output: fffffffe\n1\n1ffff\nfffffffe\ncc463bdc\n4c463bdc\n0\n
-
- .include "testutils.inc"
- start
-
-; Set R, clear C.
- move 0x100,ccs
- moveq -5,r3
- move 2,mof
- mcp mof,r3
- test_cc 1 0 0 0
- checkr3 fffffffe
-
- moveq 2,r3
- move -1,srp
- mcp srp,r3
- test_cc 0 0 0 0
- checkr3 1
-
- move 0xffff,srp
- move srp,r3
- mcp srp,r3
- test_cc 0 0 0 0
- checkr3 1ffff
-
- move -1,mof
- move mof,r3
- mcp mof,r3
- test_cc 1 0 0 0
- checkr3 fffffffe
-
- move 0x5432f789,mof
- move.d 0x78134452,r3
- mcp mof,r3
- test_cc 1 0 1 0
- checkr3 cc463bdc
-
- move 0x80000000,srp
- mcp srp,r3
- test_cc 0 0 1 0
- checkr3 4c463bdc
-
- move 0xb3b9c423,srp
- mcp srp,r3
- test_cc 0 1 0 0
- checkr3 0
-
- quit
diff --git a/tests/cris/check_mmap1.c b/tests/cris/check_mmap1.c
deleted file mode 100644
index b803f0c..0000000
--- a/tests/cris/check_mmap1.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-#notarget: cris*-*-elf
-*/
-
-#define _GNU_SOURCE
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/mman.h>
-
-int main (int argc, char *argv[])
-{
-  int fd = open (argv[0], O_RDONLY);
-  struct stat sb;
-  int size;
-  void *a;
-  const char *str = "a string you'll only find in the program";
-
-  if (fd == -1)
-    {
-      perror ("open");
-      abort ();
-    }
-
-  if (fstat (fd, &sb) < 0)
-    {
-      perror ("fstat");
-      abort ();
-    }
-
-  size = sb.st_size;
-
-  /* We want to test mmapping a size that isn't exactly a page.  */
-  if ((size & 8191) == 0)
-    size--;
-
-  a = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
-
-  if (memmem (a, size, str, strlen (str) + 1) == NULL)
-    abort ();
-
-  printf ("pass\n");
-  exit (0);
-}
diff --git a/tests/cris/check_mmap2.c b/tests/cris/check_mmap2.c
deleted file mode 100644
index 35139a0..0000000
--- a/tests/cris/check_mmap2.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-#notarget: cris*-*-elf
-*/
-
-#define _GNU_SOURCE
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/mman.h>
-
-int main (int argc, char *argv[])
-{
-  int fd = open (argv[0], O_RDONLY);
-  struct stat sb;
-  int size;
-  void *a;
-  const char *str = "a string you'll only find in the program";
-
-  if (fd == -1)
-    {
-      perror ("open");
-      abort ();
-    }
-
-  if (fstat (fd, &sb) < 0)
-    {
-      perror ("fstat");
-      abort ();
-    }
-
-  size = sb.st_size;
-
-  /* We want to test mmapping a size that isn't exactly a page.  */
-  if ((size & 8191) == 0)
-    size--;
-
-  a = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
-
-  if (memmem (a, size, str, strlen (str) + 1) == NULL)
-    abort ();
-
-  printf ("pass\n");
-  exit (0);
-}
diff --git a/tests/cris/check_mmap3.c b/tests/cris/check_mmap3.c
deleted file mode 100644
index 34401fa..0000000
--- a/tests/cris/check_mmap3.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-#notarget: cris*-*-elf
-*/
-
-#define _GNU_SOURCE
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/mman.h>
-
-int main (int argc, char *argv[])
-{
-  volatile unsigned char *a;
-
-  /* Check that we can map a non-multiple of a page and still get a full page.  */
-  a = mmap (NULL, 0x4c, PROT_READ | PROT_WRITE | PROT_EXEC,
-	    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-  if (a == NULL || a == (unsigned char *) -1)
-    abort ();
-
-  a[0] = 0xbe;
-  a[8191] = 0xef;
-  memset ((char *) a + 1, 0, 8190);
-
-  if (a[0] != 0xbe || a[8191] != 0xef)
-    abort ();
-
-  printf ("pass\n");
-  exit (0);
-}
diff --git a/tests/cris/check_movdelsr1.s b/tests/cris/check_movdelsr1.s
deleted file mode 100644
index 300cc87..0000000
--- a/tests/cris/check_movdelsr1.s
+++ /dev/null
@@ -1,33 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: aa117acd\n
-# output: eeaabb42\n
-
-; Bug with move to special register in delay slot, due to
-; special flush-insn-cache simulator use.  Ordinary move worked;
-; special register caused branch to fail.
-
- .include "testutils.inc"
- start
- move -1,srp
-
- move.d 0xaa117acd,r1
- moveq 3,r9
- cmpq 1,r9
- bhi 0f
- move.d r1,r3
-
- fail
-0:
- checkr3 aa117acd
-
- move.d 0xeeaabb42,r1
- moveq 3,r9
- cmpq 1,r9
- bhi 0f
- move r1,srp
-
- fail
-0:
- move srp,r3
- checkr3 eeaabb42
- quit
diff --git a/tests/cris/check_movecr.s b/tests/cris/check_movecr.s
deleted file mode 100644
index da8ec26..0000000
--- a/tests/cris/check_movecr.s
+++ /dev/null
@@ -1,37 +0,0 @@
-# mach: crisv3 crisv8 crisv10 crisv32
-# output: ffffff42\n94\nffff4321\n9234\n76543210\n76540000\n
-
-; Move constant byte, word, dword to register.  Check that no extension is
-; performed, that only part of the register is set.
-
- .include "testutils.inc"
- startnostack
- moveq -1,r3
- move.b 0x42,r3
- test_move_cc 0 0 0 0
- checkr3 ffffff42
-
- moveq 0,r3
- move.b 0x94,r3
- test_move_cc 1 0 0 0
- checkr3 94
-
- moveq -1,r3
- move.w 0x4321,r3
- test_move_cc 0 0 0 0
- checkr3 ffff4321
-
- moveq 0,r3
- move.w 0x9234,r3
- test_move_cc 1 0 0 0
- checkr3 9234
-
- move.d 0x76543210,r3
- test_move_cc 0 0 0 0
- checkr3 76543210
-
- move.w 0,r3
- test_move_cc 0 1 0 0
- checkr3 76540000
-
- quit
diff --git a/tests/cris/check_movei.s b/tests/cris/check_movei.s
deleted file mode 100644
index bbfa633..0000000
--- a/tests/cris/check_movei.s
+++ /dev/null
@@ -1,50 +0,0 @@
-# mach: crisv32
-# output: fffffffe\n
-# output: fffffffe\n
-
-; Check basic integral-write semantics regarding flags.
-
- .include "testutils.inc"
- start
-
- move.d 0, $r3	
-; A write that works.  Check that flags are set correspondingly.
- move.d d,r4
- ;; store to bring it into the tlb with the right prot bits
- move.d r3,[r4]
- moveq -2,r5
- setf c
- clearf p
- move.d [r4],r3
- ax
- move.d r5,[r4]
- move.d [r4],r3
-
- bcc 0f
- nop
- fail
-
-0:
- checkr3 fffffffe
-
-; A write that fails; check flags too.
- move.d d,r4
- moveq 23,r5
- setf p
- clearf c
- move.d [r4],r3
- ax
- move.d r5,[r4]
- move.d [r4],r3
-
- bcs 0f
- nop
- fail
-
-0:
- checkr3 fffffffe
- quit
-
- .data
-d:
- .dword 42424242
diff --git a/tests/cris/check_movemr.s b/tests/cris/check_movemr.s
deleted file mode 100644
index 88489de..0000000
--- a/tests/cris/check_movemr.s
+++ /dev/null
@@ -1,78 +0,0 @@
-# mach: crisv3 crisv8 crisv10 crisv32
-# output: 12345678\n10234567\n12345678\n12344567\n12344523\n76543210\nffffffaa\naa\n9911\nffff9911\n78\n56\n3456\n6712\n
-
- .include "testutils.inc"
- start
-
- .data
-mem1:
- .dword 0x12345678
-mem2:
- .word 0x4567
-mem3:
- .byte 0x23
- .dword 0x76543210
- .byte 0xaa,0x11,0x99
-
- .text
- move.d mem1,r2
- move.d [r2],r3
- test_move_cc 0 0 0 0
- checkr3 12345678
-
- move.d mem2,r3
- move.d [r3],r3
- test_move_cc 0 0 0 0
- checkr3 10234567
-
- move.d mem1,r2
- move.d [r2+],r3
- test_move_cc 0 0 0 0
- checkr3 12345678
-
- move.w [r2+],r3
- test_move_cc 0 0 0 0
- checkr3 12344567
-
- move.b [r2+],r3
- test_move_cc 0 0 0 0
- checkr3 12344523
-
- move.d [r2+],r3
- test_move_cc 0 0 0 0
- checkr3 76543210
-
- movs.b [r2],r3
- test_move_cc 1 0 0 0
- checkr3 ffffffaa
-
- movu.b [r2+],r3
- test_move_cc 0 0 0 0
- checkr3 aa
-
- movu.w [r2],r3
- test_move_cc 0 0 0 0
- checkr3 9911
-
- movs.w [r2+],r3
- test_move_cc 1 0 0 0
- checkr3 ffff9911
-
- move.d mem1,r13
- movs.b [r13+],r3
- test_move_cc 0 0 0 0
- checkr3 78
-
- movu.b [r13],r3
- test_move_cc 0 0 0 0
- checkr3 56
-
- movs.w [r13+],r3
- test_move_cc 0 0 0 0
- checkr3 3456
-
- movu.w [r13+],r3
- test_move_cc 0 0 0 0
- checkr3 6712
-
- quit
diff --git a/tests/cris/check_movemrv32.s b/tests/cris/check_movemrv32.s
deleted file mode 100644
index 53950ab..0000000
--- a/tests/cris/check_movemrv32.s
+++ /dev/null
@@ -1,96 +0,0 @@
-# mach: crisv32
-# output: 15\n7\n2\nffff1234\nb\n16\nf\n2\nffffffef\nf\nffff1234\nf\nfffffff4\nd\nfffffff2\n10\nfffffff2\nd\n
-
- .include "testutils.inc"
- .data
-x:
- .dword 8,9,10,11
-y:
- .dword -12,13,-14,15,16
-
- start
- moveq 7,r0
- moveq 2,r1
- move.d 0xffff1234,r2
- moveq 21,r3
- move.d x,r4
- setf zcvn
- movem r2,[r4+]
- test_cc 1 1 1 1
- subq 12,r4
-
- checkr3 15
-
- move.d [r4+],r3
- checkr3 7
-
- move.d [r4+],r3
- checkr3 2
-
- move.d [r4+],r3
- checkr3 ffff1234
-
- move.d [r4+],r3
- checkr3 b
-
- subq 16,r4
- moveq 22,r0
- moveq 15,r1
- clearf zcvn
- movem r0,[r4]
- test_cc 0 0 0 0
- move.d [r4+],r3
- checkr3 16
-
- move.d r1,r3
- checkr3 f
-
- move.d [r4+],r3
- checkr3 2
-
- subq 8,r4
- moveq 10,r2
- moveq -17,r0
- clearf zc
- setf vn
- movem r1,[r4]
- test_cc 1 0 1 0
- move.d [r4+],r3
- checkr3 ffffffef
-
- move.d [r4+],r3
- checkr3 f
-
- move.d [r4+],r3
- checkr3 ffff1234
-
- move.d y,r4
- setf zc
- clearf vn
- movem [r4+],r3
- test_cc 0 1 0 1
- checkr3 f
-
- move.d r0,r3
- checkr3 fffffff4
-
- move.d r1,r3
- checkr3 d
-
- move.d r2,r3
- checkr3 fffffff2
-
- move.d [r4],r3
- checkr3 10
-
- subq 8,r4
- setf zcvn
- movem [r4+],r0
- test_cc 1 1 1 1
- move.d r0,r3
- checkr3 fffffff2
-
- move.d r1,r3
- checkr3 d
-
- quit
diff --git a/tests/cris/check_moveq.c b/tests/cris/check_moveq.c
deleted file mode 100644
index 80f2dff..0000000
--- a/tests/cris/check_moveq.c
+++ /dev/null
@@ -1,51 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include "sys.h"
-#include "crisutils.h"
-
-#define cris_moveq(dst, src) \
-               asm volatile ("moveq %1, %0\n" : "=r" (dst) : "i" (src));
-
-
-
-int main(void)
-{
-	int t;
-
-	cris_tst_cc_init();
-	asm volatile ("setf\tzvnc\n");
-	cris_moveq(t, 10);
-	cris_tst_cc(1, 1, 1, 1);
-	if (t != 10)
-		err();
-
-	/* make sure moveq doesn't clobber the zflag.  */
-	cris_tst_cc_init();
-	asm volatile ("setf vnc\n");
-	asm volatile ("clearf z\n");
-	cris_moveq(t, 0);
-	cris_tst_cc(1, 0, 1, 1);
-	if (t != 0)
-		err();
-
-	/* make sure moveq doesn't clobber the nflag.
-	   Also check large immediates  */
-	cris_tst_cc_init();
-	asm volatile ("setf zvc\n");
-	asm volatile ("clearf n\n");
-	cris_moveq(t, -31);
-	cris_tst_cc(0, 1, 1, 1);
-	if (t != -31)
-		err();
-
-	cris_tst_cc_init();
-	asm volatile ("setf nzvc\n");
-	cris_moveq(t, 31);
-	cris_tst_cc(1, 1, 1, 1);
-	if (t != 31)
-		err();
-
-	pass();
-	return 0;
-}
diff --git a/tests/cris/check_mover.s b/tests/cris/check_mover.s
deleted file mode 100644
index b4db595..0000000
--- a/tests/cris/check_mover.s
+++ /dev/null
@@ -1,28 +0,0 @@
-# mach: crisv3 crisv8 crisv10 crisv32
-# output: ffffff05\nffff0005\n5\nffffff00\n
-
-; Move between registers.  Check that just the subreg is copied.
-
- .include "testutils.inc"
- startnostack
- moveq -30,r3
- moveq 5,r4
- move.b r4,r3
- test_move_cc 0 0 0 0  		; FIXME
- checkr3 ffffff05
-
- move.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 ffff0005
-
- move.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 5
-
- moveq -1,r3
- moveq 0,r4
- move.b r4,r3
- test_move_cc 0 1 0 0
- checkr3 ffffff00
-
- quit
diff --git a/tests/cris/check_moverm.s b/tests/cris/check_moverm.s
deleted file mode 100644
index eabc958..0000000
--- a/tests/cris/check_moverm.s
+++ /dev/null
@@ -1,45 +0,0 @@
-# mach: crisv3 crisv8 crisv10 crisv32
-# output: 7823fec2\n10231879\n102318fe\n
-
- .include "testutils.inc"
- start
-
- .data
-mem1:
- .dword 0x12345678
-mem2:
- .word 0x4567
-mem3:
- .byte 0x23
- .dword 0x76543210
- .byte 0xaa,0x11,0x99
-
- .text
- move.d mem1,r2
- move.d 0x7823fec2,r4
- setf nzvc
- move.d r4,[r2+]
- test_cc 1 1 1 1
- subq 4,r2
- move.d [r2],r3
- checkr3 7823fec2
-
- move.d mem2,r3
- move.d 0x45231879,r4
- clearf nzvc
- move.w r4,[r3]
- test_cc 0 0 0 0
- move.d [r3],r3
- checkr3 10231879
-
- move.d mem2,r2
- moveq -2,r4
- clearf nc
- setf zv
- move.b r4,[r2+]
- test_cc 0 1 1 0
- subq 1,r2
- move.d [r2],r3
- checkr3 102318fe
-
- quit
diff --git a/tests/cris/check_movmp.s b/tests/cris/check_movmp.s
deleted file mode 100644
index 7fc11f0..0000000
--- a/tests/cris/check_movmp.s
+++ /dev/null
@@ -1,131 +0,0 @@
-# mach: crisv3 crisv8 crisv10 crisv32
-# output: ffffff00\nffff0000\n0\nffffff00\nffff0000\n0\nffffff00\nffff0000\n0\nbb113344\n664433aa\ncc557788\nabcde012\nabcde000\n77880000\n0\n
-
-# Test generic "move Ps,[]" and "move [],Pd" insns; the ones with
-# functionality common to all models.
-
- .include "testutils.inc"
- start
-
- .data
-filler:
- .byte 0xaa
- .word 0x4433
- .dword 0x55778866
- .byte 0xcc
-
- .text
-; Test that writing to zero-registers is a nop
- .if 0
- ; We used to just ignore the writes, but now an error is emitted.  We
- ; keep the test-code but disabled, in case we need to change this again.
- move 0xaa,p0
- move 0x4433,p4
- move 0x55774433,p8
- .endif
-
- moveq -1,r3
- setf zcvn
- clear.b r3
- test_cc 1 1 1 1
- checkr3 ffffff00
-
- moveq -1,r3
- clearf zcvn
- clear.w r3
- test_cc 0 0 0 0
- checkr3 ffff0000
-
- moveq -1,r3
- clear.d r3
- checkr3 0
-
-; "Write" using ordinary memory references too.
- .if 0 ; See ".if 0" above.
- move.d filler,r6
- move [r6],p0
- move [r6],p4
- move [r6],p8
- .endif
-
-# ffffff00\nffff0000\n0\nffffff00\nffff0000\n0\nbb113344\n664433aa\ncc557788\nabcde012\nabcde000\n77880000\n0\n
-
- moveq -1,r3
- clear.b r3
- checkr3 ffffff00
-
- moveq -1,r3
- clear.w r3
- checkr3 ffff0000
-
- moveq -1,r3
- clear.d r3
- checkr3 0
-
-; And postincremented.
- .if 0 ; See ".if 0" above.
- move [r6+],p0
- move [r6+],p4
- move [r6+],p8
- .endif
-
-# ffffff00\nffff0000\n0\nbb113344\n664433aa\ncc557788\nabcde012\nabcde000\n77880000\n0\n
-
- moveq -1,r3
- clear.b r3
- checkr3 ffffff00
-
- moveq -1,r3
- clear.w r3
- checkr3 ffff0000
-
- moveq -1,r3
- clear.d r3
- checkr3 0
-
-; Now see that we can write to the registers too.
-# bb113344\n664433aa\ncc557788\nabcde012\nabcde000\n77880000\n0\n
-; [PC+]
- move.d filler,r9
- move 0xbb113344,srp
- move srp,r3
- checkr3 bb113344
-
-; [R+]
- move [r9+],srp
- move srp,r3
- checkr3 664433aa
-
-; [R]
- move [r9],srp
- move srp,r3
- checkr3 cc557788
-
-; And check writing to memory, clear and srp.
-
- move.d filler,r9
- move 0xabcde012,srp
- setf zcvn
- move srp,[r9+]
- test_cc 1 1 1 1
- subq 4,r9
- move.d [r9],r3
- checkr3 abcde012
-
- clearf zcvn
- clear.b [r9]
- test_cc 0 0 0 0
- move.d [r9],r3
- checkr3 abcde000
-
- addq 2,r9
- clear.w [r9+]
- subq 2,r9
- move.d [r9],r3
- checkr3 77880000
-
- clear.d [r9]
- move.d [r9],r3
- checkr3 0
-
- quit
diff --git a/tests/cris/check_movpmv32.s b/tests/cris/check_movpmv32.s
deleted file mode 100644
index daf0970..0000000
--- a/tests/cris/check_movpmv32.s
+++ /dev/null
@@ -1,35 +0,0 @@
-# mach: crisv32
-# output: 11223320\nbb113344\naa557711\n
-
-# Test v32-specific special registers.  FIXME: more registers.
-
- .include "testutils.inc"
- start
- .data
-store:
- .dword 0x11223344
- .dword 0x77665544
-
- .text
- moveq -1,r3
- move.d store,r4
- move vr,[r4]
- move [r4+],mof
- move mof,r3
- checkr3 11223320
-
- moveq -1,r3
- clearf zcvn
- move 0xbb113344,mof
- test_cc 0 0 0 0
- move mof,r3
- checkr3 bb113344
-
- setf zcvn
- move 0xaa557711,mof
- test_cc 1 1 1 1
- move mof,[r4]
- move.d [r4],r3
- checkr3 aa557711
-
- quit
diff --git a/tests/cris/check_movpr.s b/tests/cris/check_movpr.s
deleted file mode 100644
index eef9bdb..0000000
--- a/tests/cris/check_movpr.s
+++ /dev/null
@@ -1,28 +0,0 @@
-# mach: crisv3 crisv8 crisv10 crisv32
-# output: ffffff00\nffff0000\n0\nbb113344\n
-
-# Test generic "move Ps,Rd" and "move Rs,Pd" insns; the ones with
-# functionality common to all models.
-
- .include "testutils.inc"
- start
- moveq -1,r3
- clear.b r3
- checkr3 ffffff00
-
- moveq -1,r3
- clear.w r3
- checkr3 ffff0000
-
- moveq -1,r3
- clear.d r3
- checkr3 0
-
- moveq -1,r3
- move.d 0xbb113344,r4
- setf zcvn
- move r4,srp
- move srp,r3
- test_cc 1 1 1 1
- checkr3 bb113344
- quit
diff --git a/tests/cris/check_movprv32.s b/tests/cris/check_movprv32.s
deleted file mode 100644
index d0d90e1..0000000
--- a/tests/cris/check_movprv32.s
+++ /dev/null
@@ -1,21 +0,0 @@
-# mach: crisv32
-# output: ffffff20\nbb113344\n
-
-# Test v32-specific special registers.  FIXME: more registers.
-
- .include "testutils.inc"
- start
- moveq -1,r3
- setf zcvn
- move vr,r3
- test_cc 1 1 1 1
- checkr3 ffffff20
-
- moveq -1,r3
- move.d 0xbb113344,r4
- clearf cvnz
- move r4,mof
- test_cc 0 0 0 0
- move mof,r3
- checkr3 bb113344
- quit
diff --git a/tests/cris/check_movscr.s b/tests/cris/check_movscr.s
deleted file mode 100644
index 53c8ce6..0000000
--- a/tests/cris/check_movscr.s
+++ /dev/null
@@ -1,29 +0,0 @@
-# mach: crisv3 crisv8 crisv10 crisv32
-# output: 42\nffffff85\n7685\nffff8765\n0\n
-
-; Move constant byte, word, dword to register.  Check that sign-extension
-; is performed.
-
- .include "testutils.inc"
- start
- moveq -1,r3
- movs.b 0x42,r3
- checkr3 42
-
- movs.b 0x85,r3
- test_move_cc 1 0 0 0
- checkr3 ffffff85
-
- movs.w 0x7685,r3
- test_move_cc 0 0 0 0
- checkr3 7685
-
- movs.w 0x8765,r3
- test_move_cc 1 0 0 0
- checkr3 ffff8765
-
- movs.w 0,r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- quit
diff --git a/tests/cris/check_movsm.s b/tests/cris/check_movsm.s
deleted file mode 100644
index 7074336..0000000
--- a/tests/cris/check_movsm.s
+++ /dev/null
@@ -1,44 +0,0 @@
-# mach: crisv3 crisv8 crisv10 crisv32
-# output: 5\nfffffff5\n5\nfffffff5\n0\n
-
-; Movs between registers.  Check that sign-extension is performed and the
-; full register is set.
-
- .include "testutils.inc"
-
- .data
-x:
- .byte 5,-11
- .word 5,-11
- .word 0
-
- start
- move.d x,r5
-
- moveq -1,r3
- movs.b [r5+],r3
- test_move_cc 0 0 0 0
- checkr3 5
-
- moveq 0,r3
- movs.b [r5],r3
- test_move_cc 1 0 0 0
- addq 1,r5
- checkr3 fffffff5
-
- moveq -1,r3
- movs.w [r5+],r3
- test_move_cc 0 0 0 0
- checkr3 5
-
- moveq 0,r3
- movs.w [r5],r3
- test_move_cc 1 0 0 0
- addq 2,r5
- checkr3 fffffff5
-
- movs.w [r5],r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- quit
diff --git a/tests/cris/check_movsr.s b/tests/cris/check_movsr.s
deleted file mode 100644
index d1889a7..0000000
--- a/tests/cris/check_movsr.s
+++ /dev/null
@@ -1,46 +0,0 @@
-# mach: crisv3 crisv8 crisv10 crisv32
-# output: 5\nfffffff5\n5\nfffffff5\n0\n
-
-; Movs between registers.  Check that sign-extension is performed and the
-; full register is set.
-
- .include "testutils.inc"
- start
- moveq -1,r5
- moveq 5,r4
- move.b r4,r5
- moveq -1,r3
- movs.b r5,r3
- test_move_cc 0 0 0 0
- checkr3 5
-
- moveq 0,r5
- moveq -11,r4
- move.b r4,r5
- moveq 0,r3
- movs.b r5,r3
- test_move_cc 1 0 0 0
- checkr3 fffffff5
-
- moveq -1,r5
- moveq 5,r4
- move.w r4,r5
- moveq -1,r3
- movs.w r5,r3
- test_move_cc 0 0 0 0
- checkr3 5
-
- moveq 0,r5
- moveq -11,r4
- move.w r4,r5
- moveq 0,r3
- movs.w r5,r3
- test_move_cc 1 0 0 0
- checkr3 fffffff5
-
- moveq 0,r5
- movs.b r5,r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- quit
diff --git a/tests/cris/check_movucr.s b/tests/cris/check_movucr.s
deleted file mode 100644
index 7c8487d..0000000
--- a/tests/cris/check_movucr.s
+++ /dev/null
@@ -1,33 +0,0 @@
-# mach: crisv3 crisv8 crisv10 crisv32
-# output: 42\n85\n7685\n8765\n0\n
-
-; Move constant byte, word, dword to register.  Check that zero-extension
-; is performed.
-
- .include "testutils.inc"
- start
- moveq -1,r3
- movu.b 0x42,r3
- test_move_cc 0 0 0 0
- checkr3 42
-
- moveq -1,r3
- movu.b 0x85,r3
- test_move_cc 0 0 0 0
- checkr3 85
-
- moveq -1,r3
- movu.w 0x7685,r3
- test_move_cc 0 0 0 0
- checkr3 7685
-
- moveq -1,r3
- movu.w 0x8765,r3
- test_move_cc 0 0 0 0
- checkr3 8765
-
- movu.b 0,r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- quit
diff --git a/tests/cris/check_movum.s b/tests/cris/check_movum.s
deleted file mode 100644
index 038e539..0000000
--- a/tests/cris/check_movum.s
+++ /dev/null
@@ -1,40 +0,0 @@
-# mach: crisv3 crisv8 crisv10 crisv32
-# output: 5\nf5\n5\nfff5\n0\n
-
-; Movu between registers.  Check that zero-extension is performed and the
-; full register is set.
-
- .include "testutils.inc"
-
- .data
-x:
- .byte 5,-11
- .word 5,-11
- .word 0
-
- start
- move.d x,r5
-
- movu.b [r5+],r3
- test_move_cc 0 0 0 0
- checkr3 5
-
- movu.b [r5],r3
- test_move_cc 0 0 0 0
- addq 1,r5
- checkr3 f5
-
- movu.w [r5+],r3
- test_move_cc 0 0 0 0
- checkr3 5
-
- movu.w [r5],r3
- test_move_cc 0 0 0 0
- addq 2,r5
- checkr3 fff5
-
- movu.w [r5],r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- quit
diff --git a/tests/cris/check_movur.s b/tests/cris/check_movur.s
deleted file mode 100644
index 3ecf475..0000000
--- a/tests/cris/check_movur.s
+++ /dev/null
@@ -1,45 +0,0 @@
-# mach: crisv3 crisv8 crisv10 crisv32
-# output: 5\nf5\n5\nfff5\n0\n
-
-; Movu between registers.  Check that zero-extension is performed and the
-; full register is set.
-
- .include "testutils.inc"
- start
- moveq -1,r5
- moveq 5,r4
- move.b r4,r5
- moveq -1,r3
- movu.b r5,r3
- test_move_cc 0 0 0 0
- checkr3 5
-
- moveq 0,r5
- moveq -11,r4
- move.b r4,r5
- moveq -1,r3
- movu.b r5,r3
- test_move_cc 0 0 0 0
- checkr3 f5
-
- moveq -1,r5
- moveq 5,r4
- move.w r4,r5
- moveq -1,r3
- movu.w r5,r3
- test_move_cc 0 0 0 0
- checkr3 5
-
- moveq 0,r5
- moveq -11,r4
- move.w r4,r5
- moveq -1,r3
- movu.w r5,r3
- test_move_cc 0 0 0 0
- checkr3 fff5
-
- movu.w 0,r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- quit
diff --git a/tests/cris/check_mulv32.s b/tests/cris/check_mulv32.s
deleted file mode 100644
index f379358..0000000
--- a/tests/cris/check_mulv32.s
+++ /dev/null
@@ -1,51 +0,0 @@
-# mach: crisv32
-# output: fffffffe\n
-# output: ffffffff\n
-# output: fffffffe\n
-# output: 1\n
-# output: fffffffe\n
-# output: ffffffff\n
-# output: fffffffe\n
-# output: 1\n
-
-; Check that carry is not modified on v32.
-
- .include "testutils.inc"
- start
- moveq -1,r3
- moveq 2,r4
- setf c
- muls.d r4,r3
- test_cc 1 0 0 1
- checkr3 fffffffe
- move mof,r3
- checkr3 ffffffff
-
- moveq -1,r3
- moveq 2,r4
- setf c
- mulu.d r4,r3
- test_cc 0 0 1 1
- checkr3 fffffffe
- move mof,r3
- checkr3 1
-
- moveq -1,r3
- moveq 2,r4
- clearf c
- muls.d r4,r3
- test_cc 1 0 0 0
- checkr3 fffffffe
- move mof,r3
- checkr3 ffffffff
-
- moveq -1,r3
- moveq 2,r4
- clearf c
- mulu.d r4,r3
- test_cc 0 0 1 0
- checkr3 fffffffe
- move mof,r3
- checkr3 1
-
- quit
diff --git a/tests/cris/check_mulx.s b/tests/cris/check_mulx.s
deleted file mode 100644
index d43241a..0000000
--- a/tests/cris/check_mulx.s
+++ /dev/null
@@ -1,246 +0,0 @@
-# mach: crisv10 crisv32
-# output: fffffffe\nffffffff\nfffffffe\n1\nfffffffe\nffffffff\nfffffffe\n1\nfffe0001\n0\nfffe0001\n0\n1\n0\n1\nfffffffe\n193eade2\n277e3a49\n193eade2\n277e3a49\nfffffffe\nffffffff\n1fffe\n0\nfffffffe\nffffffff\n1fffe\n0\n1\n0\nfffe0001\n0\nfdbdade2\nffffffff\n420fade2\n0\nfffffffe\nffffffff\n1fe\n0\nfffffffe\nffffffff\n1fe\n0\n1\n0\nfe01\n0\n1\n0\nfe01\n0\nffffd9e2\nffffffff\n2be2\n0\n0\n0\n0\n0\n
-
- .include "testutils.inc"
- start
- moveq -1,r3
- moveq 2,r4
- muls.d r4,r3
- test_cc 1 0 0 0
- checkr3 fffffffe
- move mof,r3
- checkr3 ffffffff
-
- moveq -1,r3
- moveq 2,r4
- mulu.d r4,r3
- test_cc 0 0 1 0
- checkr3 fffffffe
- move mof,r3
- checkr3 1
-
- moveq 2,r3
- moveq -1,r4
- muls.d r4,r3
- test_cc 1 0 0 0
- checkr3 fffffffe
- move mof,r3
- checkr3 ffffffff
-
- moveq 2,r3
- moveq -1,r4
- mulu.d r4,r3
- test_cc 0 0 1 0
- checkr3 fffffffe
- move mof,r3
- checkr3 1
-
- move.d 0xffff,r4
- move.d r4,r3
- muls.d r4,r3
- test_cc 0 0 1 0
- checkr3 fffe0001
- move mof,r3
- checkr3 0
-
- move.d 0xffff,r4
- move.d r4,r3
- mulu.d r4,r3
- test_cc 0 0 0 0
- checkr3 fffe0001
- move mof,r3
- checkr3 0
-
- moveq -1,r4
- move.d r4,r3
- muls.d r4,r3
- test_cc 0 0 0 0
- checkr3 1
- move mof,r3
- checkr3 0
-
- moveq -1,r4
- move.d r4,r3
- mulu.d r4,r3
- test_cc 1 0 1 0
- checkr3 1
- move mof,r3
- checkr3 fffffffe
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- muls.d r4,r3
- test_cc 0 0 1 0
- checkr3 193eade2
- move mof,r3
- checkr3 277e3a49
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- mulu.d r4,r3
- test_cc 0 0 1 0
- checkr3 193eade2
- move mof,r3
- checkr3 277e3a49
-
- move.d 0xffff,r3
- moveq 2,r4
- muls.w r4,r3
- test_cc 1 0 0 0
- checkr3 fffffffe
- move mof,r3
- checkr3 ffffffff
-
- moveq -1,r3
- moveq 2,r4
- mulu.w r4,r3
- test_cc 0 0 0 0
- checkr3 1fffe
- move mof,r3
- checkr3 0
-
- moveq 2,r3
- move.d 0xffff,r4
- muls.w r4,r3
- test_cc 1 0 0 0
- checkr3 fffffffe
- move mof,r3
- checkr3 ffffffff
-
- moveq 2,r3
- moveq -1,r4
- mulu.w r4,r3
- test_cc 0 0 0 0
- checkr3 1fffe
- move mof,r3
- checkr3 0
-
- move.d 0xffff,r4
- move.d r4,r3
- muls.w r4,r3
- test_cc 0 0 0 0
- checkr3 1
- move mof,r3
- checkr3 0
-
- moveq -1,r4
- move.d r4,r3
- mulu.w r4,r3
- test_cc 0 0 0 0
- checkr3 fffe0001
- move mof,r3
- checkr3 0
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- muls.w r4,r3
- test_cc 1 0 0 0
- checkr3 fdbdade2
- move mof,r3
- checkr3 ffffffff
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- mulu.w r4,r3
- test_cc 0 0 0 0
- checkr3 420fade2
- move mof,r3
- checkr3 0
-
- move.d 0xff,r3
- moveq 2,r4
- muls.b r4,r3
- test_cc 1 0 0 0
- checkr3 fffffffe
- move mof,r3
- checkr3 ffffffff
-
- moveq -1,r3
- moveq 2,r4
- mulu.b r4,r3
- test_cc 0 0 0 0
- checkr3 1fe
- move mof,r3
- checkr3 0
-
- moveq 2,r3
- moveq -1,r4
- muls.b r4,r3
- test_cc 1 0 0 0
- checkr3 fffffffe
- move mof,r3
- checkr3 ffffffff
-
- moveq 2,r3
- moveq -1,r4
- mulu.b r4,r3
- test_cc 0 0 0 0
- checkr3 1fe
- move mof,r3
- checkr3 0
-
- move.d 0xff,r4
- move.d r4,r3
- muls.b r4,r3
- test_cc 0 0 0 0
- checkr3 1
- move mof,r3
- checkr3 0
-
- moveq -1,r4
- move.d r4,r3
- mulu.b r4,r3
- test_cc 0 0 0 0
- checkr3 fe01
- move mof,r3
- checkr3 0
-
- move.d 0xfeda49ff,r4
- move.d r4,r3
- muls.b r4,r3
- test_cc 0 0 0 0
- checkr3 1
- move mof,r3
- checkr3 0
-
- move.d 0xfeda49ff,r4
- move.d r4,r3
- mulu.b r4,r3
- test_cc 0 0 0 0
- checkr3 fe01
- move mof,r3
- checkr3 0
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- muls.b r4,r3
- test_cc 1 0 0 0
- checkr3 ffffd9e2
- move mof,r3
- checkr3 ffffffff
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- mulu.b r4,r3
- test_cc 0 0 0 0
- checkr3 2be2
- move mof,r3
- checkr3 0
-
- moveq 0,r3
- move.d 0xf87f4aeb,r4
- muls.d r4,r3
- test_cc 0 1 0 0
- checkr3 0
- move mof,r3
- checkr3 0
-
- move.d 0xf87f4aeb,r3
- moveq 0,r4
- mulu.d r4,r3
- test_cc 0 1 0 0
- checkr3 0
- move mof,r3
- checkr3 0
-
- quit
diff --git a/tests/cris/check_neg.s b/tests/cris/check_neg.s
deleted file mode 100644
index 963c4b6..0000000
--- a/tests/cris/check_neg.s
+++ /dev/null
@@ -1,104 +0,0 @@
-# mach:  crisv0 crisv3 crisv8 crisv10 crisv32
-# output: ffffffff\nffffffff\n0\n80000000\n1\nba987655\nffff\nffff\n0\n89ab8000\nffff0001\n45677655\nff\nff\n0\n89abae80\nffffff01\n45678955\n
-
- .include "testutils.inc"
- start
- moveq 0,r3
- moveq 1,r4
- neg.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq 1,r3
- moveq 0,r4
- neg.d r3,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
-;; FIXME: this was wrong.
- moveq 0,r3
- neg.d r3,r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- move.d 0x80000000,r3
- neg.d r3,r3
- test_move_cc 1 0 0 0
- checkr3 80000000
-
- moveq -1,r3
- neg.d r3,r3
- test_move_cc 0 0 0 0
- checkr3 1
-
- move.d 0x456789ab,r3
- neg.d r3,r3
- test_move_cc 1 0 0 0
- checkr3 ba987655
-
- moveq 0,r3
- moveq 1,r4
- neg.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffff
-
- moveq 1,r3
- moveq 0,r4
- neg.w r3,r3
- test_move_cc 1 0 0 0
- checkr3 ffff
-
- moveq 0,r3
- neg.w r3,r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- move.d 0x89ab8000,r3
- neg.w r3,r3
- test_move_cc 1 0 0 0
- checkr3 89ab8000
-
- moveq -1,r3
- neg.w r3,r3
- test_move_cc 0 0 0 0
- checkr3 ffff0001
-
- move.d 0x456789ab,r3
- neg.w r3,r3
- test_move_cc 0 0 0 0
- checkr3 45677655
-
- moveq 0,r3
- moveq 1,r4
- neg.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 ff
-
- moveq 1,r3
- moveq 0,r4
- neg.b r3,r3
- test_move_cc 1 0 0 0
- checkr3 ff
-
- moveq 0,r3
- neg.b r3,r3
- test_move_cc 0 1 0 0
- checkr3 0
-
-;; FIXME: was wrong.
- move.d 0x89abae80,r3
- neg.b r3,r3
- test_move_cc 1 0 0 1
- checkr3 89abae80
-
- moveq -1,r3
- neg.b r3,r3
- test_move_cc 0 0 0 0
- checkr3 ffffff01
-
- move.d 0x456789ab,r3
- neg.b r3,r3
- test_move_cc 0 0 0 0
- checkr3 45678955
-
- quit
diff --git a/tests/cris/check_not.s b/tests/cris/check_not.s
deleted file mode 100644
index 33bcf15..0000000
--- a/tests/cris/check_not.s
+++ /dev/null
@@ -1,31 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: fffffffe\nfffffffd\nffff0f00\n0\n87ecbbad\n
-
- .include "testutils.inc"
- start
- moveq 1,r3
- not r3
- test_move_cc 1 0 0 0
- checkr3 fffffffe
-
- moveq 2,r3
- not r3
- test_move_cc 1 0 0 0
- checkr3 fffffffd
-
- move.d 0xf0ff,r3
- not r3
- test_move_cc 1 0 0 0
- checkr3 ffff0f00
-
- moveq -1,r3
- not r3
- test_move_cc 0 1 0 0
- checkr3 0
-
- move.d 0x78134452,r3
- not r3
- test_move_cc 1 0 0 0
- checkr3 87ecbbad
-
- quit
diff --git a/tests/cris/check_openpf1.c b/tests/cris/check_openpf1.c
deleted file mode 100644
index fdcf4c5..0000000
--- a/tests/cris/check_openpf1.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Check that --sysroot is applied to open(2).
-#sim: --sysroot=@exedir@
-
-   We assume, with EXE being the name of the executable:
-   - The simulator executes with cwd the same directory where the executable
-     is located (so argv[0] contains a plain filename without directory
-     components).
-   - There's no /EXE on the host file system.  */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-int main (int argc, char *argv[])
-{
-  char *fnam = argv[0];
-  FILE *f;
-  if (argv[0][0] != '/')
-    {
-      fnam = malloc (strlen (argv[0]) + 2);
-      if (fnam == NULL)
-	abort ();
-      strcpy (fnam, "/");
-      strcat (fnam, argv[0]);
-    }
-
-  f = fopen (fnam, "rb");
-  if (f == NULL)
-    abort ();
-  fclose(f);
-
-  /* Cover another execution path.  */
-  if (fopen ("/nonexistent", "rb") != NULL
-      || errno != ENOENT)
-    abort ();
-  printf ("pass\n");
-  return 0;
-}
diff --git a/tests/cris/check_openpf2.c b/tests/cris/check_openpf2.c
deleted file mode 100644
index 5d56189..0000000
--- a/tests/cris/check_openpf2.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/* Check that the simulator has chdir:ed to the --sysroot argument
-#sim: --sysroot=@srcdir@
-   (or that  --sysroot is applied to relative file paths).  */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-int main (int argc, char *argv[])
-{
-  FILE *f = fopen ("check_openpf2.c", "rb");
-  if (f == NULL)
-    abort ();
-  fclose(f);
-  printf ("pass\n");
-  return 0;
-}
diff --git a/tests/cris/check_openpf3.c b/tests/cris/check_openpf3.c
deleted file mode 100644
index 557adee..0000000
--- a/tests/cris/check_openpf3.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Basic file operations (rename, unlink); once without sysroot.  We
-   also test that the simulator has chdir:ed to PREFIX, when defined.  */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#ifndef PREFIX
-#define PREFIX
-#endif
-
-void err (const char *s)
-{
-  perror (s);
-  abort ();
-}
-
-int main (int argc, char *argv[])
-{
-  FILE *f;
-  struct stat buf;
-
-  unlink (PREFIX "testfoo2.tmp");
-
-  f = fopen ("testfoo1.tmp", "w");
-  if (f == NULL)
-    err ("open");
-  fclose (f);
-
-  if (rename (PREFIX "testfoo1.tmp", PREFIX "testfoo2.tmp") != 0)
-    err ("rename");
-
-  if (stat (PREFIX "testfoo2.tmp", &buf) != 0
-      || !S_ISREG (buf.st_mode))
-    err ("stat 1");
-
-  if (stat ("testfoo2.tmp", &buf) != 0
-      || !S_ISREG (buf.st_mode))
-    err ("stat 2");
-
-  if (unlink (PREFIX "testfoo2.tmp") != 0)
-    err ("unlink");
-
-  printf ("pass\n");
-  return 0;
-}
diff --git a/tests/cris/check_openpf4.c b/tests/cris/check_openpf4.c
deleted file mode 100644
index 8bbee41..0000000
--- a/tests/cris/check_openpf4.c
+++ /dev/null
@@ -1,5 +0,0 @@
-/* Basic file operations, now *with* sysroot.
-#sim: --sysroot=@exedir@
-*/
-#define PREFIX "/"
-#include "check_openpf3.c"
diff --git a/tests/cris/check_openpf5.c b/tests/cris/check_openpf5.c
deleted file mode 100644
index 1f86ea2..0000000
--- a/tests/cris/check_openpf5.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Check that TRT happens when error on too many opened files.
-#notarget: cris*-*-elf
-#sim: --sysroot=@exedir@
-*/
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-
-int main (int argc, char *argv[])
-{
-  int i;
-  int filemax;
-
-#ifdef OPEN_MAX
-  filemax = OPEN_MAX;
-#else
-  filemax = sysconf (_SC_OPEN_MAX);
-#endif
-
-  char *fn = malloc (strlen (argv[0]) + 2);
-  if (fn == NULL)
-    abort ();
-  strcpy (fn, "/");
-  strcat (fn, argv[0]);
-
-  for (i = 0; i < filemax + 1; i++)
-    {
-      if (open (fn, O_RDONLY) < 0)
-	{
-	  /* Shouldn't happen too early.  */
-	  if (i < filemax - 3 - 1)
-	    {
-	      fprintf (stderr, "i: %d\n", i);
-	      abort ();
-	    }
-	  if (errno != EMFILE)
-	    {
-	      perror ("open");
-	      abort ();
-	    }
-	  goto ok;
-	}
-    }
-  abort ();
-
-ok:
-  printf ("pass\n");
-  exit (0);
-}
diff --git a/tests/cris/check_orc.s b/tests/cris/check_orc.s
deleted file mode 100644
index c733f03..0000000
--- a/tests/cris/check_orc.s
+++ /dev/null
@@ -1,71 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 3\n3\nffff\nffffffff\n7c33f7db\nffff0003\n3\nfedaffff\n7813f7db\n3\n3\nfeb\n781344db\n
-
- .include "testutils.inc"
- start
- moveq 1,r3
- or.d 2,r3
- test_move_cc 0 0 0 0
- checkr3 3
-
- moveq 2,r3
- or.d 1,r3
- test_move_cc 0 0 0 0
- checkr3 3
-
- move.d 0xf0ff,r3
- or.d 0xff0f,r3
- test_move_cc 0 0 0 0
- checkr3 ffff
-
- moveq -1,r3
- or.d -1,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- move.d 0x78134452,r3
- or.d 0x5432f789,r3
- test_move_cc 0 0 0 0
- checkr3 7c33f7db
-
- move.d 0xffff0001,r3
- or.w 2,r3
- test_move_cc 0 0 0 0
- checkr3 ffff0003
-
- moveq 2,r3
- or.w 1,r3
- test_move_cc 0 0 0 0
- checkr3 3
-
- move.d 0xfedaffaf,r3
- or.w 0xff5f,r3
- test_move_cc 1 0 0 0
- checkr3 fedaffff
-
- move.d 0x78134452,r3
- or.w 0xf789,r3
- test_move_cc 1 0 0 0
- checkr3 7813f7db
-
- moveq 1,r3
- or.b 2,r3
- test_move_cc 0 0 0 0
- checkr3 3
-
- moveq 2,r3
- or.b 1,r3
- test_move_cc 0 0 0 0
- checkr3 3
-
- move.d 0xfa3,r3
- or.b 0x4a,r3
- test_move_cc 1 0 0 0
- checkr3 feb
-
- move.d 0x78134453,r3
- or.b 0x89,r3
- test_move_cc 1 0 0 0
- checkr3 781344db
-
- quit
diff --git a/tests/cris/check_orm.s b/tests/cris/check_orm.s
deleted file mode 100644
index ee723a6..0000000
--- a/tests/cris/check_orm.s
+++ /dev/null
@@ -1,75 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 3\n3\nffff\nffffffff\n7c33f7db\nffff0003\n3\nfedaffff\n7813f7db\n3\n3\nfeb\n781344db\n
-
- .include "testutils.inc"
- .data
-x:
- .dword 2,1,0xff0f,-1,0x5432f789
- .word 2,1,0xff5f,0xf789
- .byte 2,1,0x4a,0x89
-
- start
- moveq 1,r3
- move.d x,r5
- or.d [r5+],r3
- checkr3 3
-
- moveq 2,r3
- or.d [r5],r3
- addq 4,r5
- checkr3 3
-
- move.d 0xf0ff,r3
- or.d [r5+],r3
- checkr3 ffff
-
- moveq -1,r3
- or.d [r5+],r3
- checkr3 ffffffff
-
- move.d 0x78134452,r3
- or.d [r5+],r3
- checkr3 7c33f7db
-
- move.d 0xffff0001,r3
- or.w [r5+],r3
- checkr3 ffff0003
-
- moveq 2,r3
- or.w [r5],r3
- addq 2,r5
- test_move_cc 0 0 0 0
- checkr3 3
-
- move.d 0xfedaffaf,r3
- or.w [r5+],r3
- test_move_cc 1 0 0 0
- checkr3 fedaffff
-
- move.d 0x78134452,r3
- or.w [r5+],r3
- test_move_cc 1 0 0 0
- checkr3 7813f7db
-
- moveq 1,r3
- or.b [r5+],r3
- test_move_cc 0 0 0 0
- checkr3 3
-
- moveq 2,r3
- or.b [r5],r3
- addq 1,r5
- test_move_cc 0 0 0 0
- checkr3 3
-
- move.d 0xfa3,r3
- or.b [r5+],r3
- test_move_cc 1 0 0 0
- checkr3 feb
-
- move.d 0x78134453,r3
- or.b [r5],r3
- test_move_cc 1 0 0 0
- checkr3 781344db
-
- quit
diff --git a/tests/cris/check_orq.s b/tests/cris/check_orq.s
deleted file mode 100644
index 5060edc..0000000
--- a/tests/cris/check_orq.s
+++ /dev/null
@@ -1,41 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 3\n3\nffffffff\nffffffff\n1f\nffffffe0\n7813445e\n
-
- .include "testutils.inc"
- start
- moveq 1,r3
- orq 2,r3
- test_move_cc 0 0 0 0
- checkr3 3
-
- moveq 2,r3
- orq 1,r3
- test_move_cc 0 0 0 0
- checkr3 3
-
- move.d 0xf0ff,r3
- orq -1,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq 0,r3
- orq -1,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- moveq 0,r3
- orq 31,r3
- test_move_cc 0 0 0 0
- checkr3 1f
-
- moveq 0,r3
- orq -32,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffe0
-
- move.d 0x78134452,r3
- orq 12,r3
- test_move_cc 0 0 0 0
- checkr3 7813445e
-
- quit
diff --git a/tests/cris/check_orr.s b/tests/cris/check_orr.s
deleted file mode 100644
index a514c11..0000000
--- a/tests/cris/check_orr.s
+++ /dev/null
@@ -1,84 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 3\n3\nffff\nffffffff\n7c33f7db\nffff0003\n3\nfedaffff\n7813f7db\n3\n3\nfeb\n781344db\n
-
- .include "testutils.inc"
- start
- moveq 1,r3
- moveq 2,r4
- or.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 3
-
- moveq 2,r3
- moveq 1,r4
- or.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 3
-
- move.d 0xff0f,r4
- move.d 0xf0ff,r3
- or.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 ffff
-
- moveq -1,r4
- move.d r4,r3
- or.d r4,r3
- test_move_cc 1 0 0 0
- checkr3 ffffffff
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- or.d r4,r3
- test_move_cc 0 0 0 0
- checkr3 7c33f7db
-
- move.d 0xffff0001,r3
- moveq 2,r4
- or.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 ffff0003
-
- moveq 2,r3
- move.d 0xffff0001,r4
- or.w r4,r3
- test_move_cc 0 0 0 0
- checkr3 3
-
- move.d 0xfedaffaf,r3
- move.d 0xffffff5f,r4
- or.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 fedaffff
-
- move.d 0x5432f789,r4
- move.d 0x78134452,r3
- or.w r4,r3
- test_move_cc 1 0 0 0
- checkr3 7813f7db
-
- moveq 1,r3
- move.d 0xffffff02,r4
- or.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 3
-
- moveq 2,r3
- moveq 1,r4
- or.b r4,r3
- test_move_cc 0 0 0 0
- checkr3 3
-
- move.d 0x4a,r4
- move.d 0xfa3,r3
- or.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 feb
-
- move.d 0x5432f789,r4
- move.d 0x78134453,r3
- or.b r4,r3
- test_move_cc 1 0 0 0
- checkr3 781344db
-
- quit
diff --git a/tests/cris/check_ret.s b/tests/cris/check_ret.s
deleted file mode 100644
index b44fb25..0000000
--- a/tests/cris/check_ret.s
+++ /dev/null
@@ -1,25 +0,0 @@
-# mach: crisv3 crisv8 crisv10
-# output: 3\n
-
-# Test that ret works.
-
- .include "testutils.inc"
- start
-x:
- moveq 0,r3
- jsr z
-w:
- quit
-y:
- addq 1,r3
- checkr3 3
- quit
-
-z:
- addq 1,r3
- move srp,r2
- add.d y-w,r2
- move r2,srp
- ret
- addq 1,r3
- quit
diff --git a/tests/cris/check_scc.s b/tests/cris/check_scc.s
deleted file mode 100644
index 4a8674c..0000000
--- a/tests/cris/check_scc.s
+++ /dev/null
@@ -1,95 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 1\n0\n1\n0\n1\n0\n1\n0\n0\n1\n1\n0\n1\n0\n1\n0\n1\n0\n0\n1\n0\n1\n1\n0\n1\n0\n0\n1\n1\n0\n1\n1\n0\n
-
- .include "testutils.inc"
-
- .macro lcheckr3 v
-	move	 $ccs, $r9
-	checkr3 \v
-	move	$r9, $ccs
- .endm
-
- start
- clearf nzvc
- scc r3
- lcheckr3 1
- scs r3
- lcheckr3 0
- sne r3
- lcheckr3 1
- seq r3
- lcheckr3 0
- svc r3
- lcheckr3 1
- svs r3
- lcheckr3 0
- spl r3
- lcheckr3 1
- smi r3
- lcheckr3 0
- sls r3
- lcheckr3 0
- shi r3
- lcheckr3 1
- sge r3
- lcheckr3 1
- slt r3
- lcheckr3 0
- sgt r3
- lcheckr3 1
- sle r3
- lcheckr3 0
- sa r3
- lcheckr3 1
- setf nzvc
- scc r3
- lcheckr3 0
- scs r3
- lcheckr3 1
- sne r3
- lcheckr3 0
- svc r3
- lcheckr3 0
- svs r3
- lcheckr3 1
- spl r3
- lcheckr3 0
- smi r3
- lcheckr3 1
- sls r3
- lcheckr3 1
- shi r3
- lcheckr3 0
- sge r3
- lcheckr3 1
- slt r3
- lcheckr3 0
- sgt r3
- lcheckr3 0
- sle r3
- lcheckr3 1
- sa r3
- lcheckr3 1
- clearf n
- sge r3
- lcheckr3 0
- slt r3
- lcheckr3 1
-
- .if 1 ;..asm.arch.cris.v32
- setf p
- ssb r3
- .else
- moveq 1,r3
- .endif
- lcheckr3 1
-
- .if 1 ;..asm.arch.cris.v32
- clearf p
- ssb r3
- .else
- moveq 0,r3
- .endif
- lcheckr3 0
-
- quit
diff --git a/tests/cris/check_settls1.c b/tests/cris/check_settls1.c
deleted file mode 100644
index 69d2026..0000000
--- a/tests/cris/check_settls1.c
+++ /dev/null
@@ -1,45 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <sys/syscall.h>
-
-#ifndef SYS_set_thread_area
-#define SYS_set_thread_area 243
-#endif
-
-int main (void)
-{
-    unsigned long tp, old_tp;
-    int ret;
-
-    asm volatile ("move $pid,%0" : "=r" (old_tp));
-    old_tp &= ~0xff;
-
-    ret = syscall (SYS_set_thread_area, 0xf0);
-    if (ret != -1 || errno != EINVAL) {
-        syscall (SYS_set_thread_area, old_tp);
-        perror ("Invalid thread area accepted:");
-        abort();
-    }
-
-    ret = syscall (SYS_set_thread_area, 0xeddeed00);
-    if (ret != 0) {
-        perror ("Valid thread area not accepted: ");
-        abort ();
-    }
-
-    asm volatile ("move $pid,%0" : "=r" (tp));
-    tp &= ~0xff;
-    syscall (SYS_set_thread_area, old_tp);
-
-    if (tp != 0xeddeed00) {
-	* (volatile int *) 0 = 0;
-        perror ("tls2");
-        abort ();
-    }
-
-    printf ("pass\n");
-    return EXIT_SUCCESS;
-}
diff --git a/tests/cris/check_sigalrm.c b/tests/cris/check_sigalrm.c
deleted file mode 100644
index 39fa8d9..0000000
--- a/tests/cris/check_sigalrm.c
+++ /dev/null
@@ -1,26 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <unistd.h>
-
-#define MAGIC (0xdeadbeef)
-
-int s = 0;
-void sighandler(int sig)
-{
-	s = MAGIC;
-}
-
-int main(int argc, char **argv)
-{
-	int p;
-
-	p = getpid();
-	signal(SIGALRM, sighandler);
-	kill(p, SIGALRM);
-	if (s != MAGIC)
-		return EXIT_FAILURE;
-
-	printf ("passed\n");
-	return EXIT_SUCCESS;
-}
diff --git a/tests/cris/check_stat1.c b/tests/cris/check_stat1.c
deleted file mode 100644
index 2e2cae5..0000000
--- a/tests/cris/check_stat1.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-int main (void)
-{
-  struct stat buf;
-
-  if (stat (".", &buf) != 0
-      || !S_ISDIR (buf.st_mode))
-    abort ();
-  printf ("pass\n");
-  exit (0);
-}
diff --git a/tests/cris/check_stat2.c b/tests/cris/check_stat2.c
deleted file mode 100644
index e36172e..0000000
--- a/tests/cris/check_stat2.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-#notarget: cris*-*-elf
-*/
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-int main (void)
-{
-  struct stat buf;
-
-  if (lstat (".", &buf) != 0
-      || !S_ISDIR (buf.st_mode))
-    abort ();
-  printf ("pass\n");
-  exit (0);
-}
diff --git a/tests/cris/check_stat3.c b/tests/cris/check_stat3.c
deleted file mode 100644
index 36a9d5d..0000000
--- a/tests/cris/check_stat3.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Simulator options:
-#sim: --sysroot=@exedir@
-*/
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-int main (int argc, char *argv[])
-{
-  char path[1024] = "/";
-  struct stat buf;
-
-  strncat(path, argv[0], sizeof(path) - 2);
-  if (stat (".", &buf) != 0
-      || !S_ISDIR (buf.st_mode))
-    abort ();
-  if (stat (path, &buf) != 0
-      || !S_ISREG (buf.st_mode))
-    abort ();
-  printf ("pass\n");
-  exit (0);
-}
diff --git a/tests/cris/check_stat4.c b/tests/cris/check_stat4.c
deleted file mode 100644
index 04f21fe..0000000
--- a/tests/cris/check_stat4.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Simulator options:
-#notarget: cris*-*-elf
-#sim: --sysroot=@exedir@
-*/
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-int main (int argc, char *argv[])
-{
-  char path[1024] = "/";
-  struct stat buf;
-
-  strncat(path, argv[0], sizeof(path) - 2);
-  if (lstat (".", &buf) != 0
-      || !S_ISDIR (buf.st_mode))
-    abort ();
-  if (lstat (path, &buf) != 0
-      || !S_ISREG (buf.st_mode))
-    abort ();
-  printf ("pass\n");
-  exit (0);
-}
diff --git a/tests/cris/check_subc.s b/tests/cris/check_subc.s
deleted file mode 100644
index e34b544..0000000
--- a/tests/cris/check_subc.s
+++ /dev/null
@@ -1,87 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n85649200\n
-
- .include "testutils.inc"
- start
-
- moveq -1,r3
- sub.d -2,r3
- test_cc 0 0 0 0
- checkr3 1
-
- moveq 2,r3
- sub.d 1,r3
- test_cc 0 0 0 0
- checkr3 1
-
- move.d 0xffff,r3
- sub.d -0xffff,r3
- test_cc 0 0 0 1
- checkr3 1fffe
-
- moveq -1,r3
- sub.d 1,r3
- test_cc 1 0 0 0
- checkr3 fffffffe
-
- move.d 0x78134452,r3
- sub.d -0x5432f789,r3
- test_cc 1 0 1 1
- checkr3 cc463bdb
-
- moveq -1,r3
- sub.w -2,r3
- test_cc 0 0 0 0
- checkr3 ffff0001
-
- moveq 2,r3
- sub.w 1,r3
- test_cc 0 0 0 0
- checkr3 1
-
- move.d 0xffff,r3
- sub.w 1,r3
- test_cc 1 0 0 0
- checkr3 fffe
-
- move.d 0xfedaffff,r3
- sub.w 1,r3
- test_cc 1 0 0 0
- checkr3 fedafffe
-
- move.d 0x78134452,r3
- sub.w 0x877,r3
- test_cc 0 0 0 0
- checkr3 78133bdb
-
- moveq -1,r3
- sub.b -2,r3
- test_cc 0 0 0 0
- checkr3 ffffff01
-
- moveq 2,r3
- sub.b 1,r3
- test_cc 0 0 0 0
- checkr3 1
-
- move.d 0xff,r3
- sub.b 1,r3
- test_cc 1 0 0 0
- checkr3 fe
-
- move.d 0xfeda49ff,r3
- sub.b 1,r3
- test_cc 1 0 0 0
- checkr3 feda49fe
-
- move.d 0x78134452,r3
- sub.b 0x77,r3
- test_cc 1 0 0 1
- checkr3 781344db
-
- move.d 0x85649282,r3
- sub.b 0x82,r3
- test_cc 0 1 0 0
- checkr3 85649200
-
- quit
diff --git a/tests/cris/check_subm.s b/tests/cris/check_subm.s
deleted file mode 100644
index e07ea02..0000000
--- a/tests/cris/check_subm.s
+++ /dev/null
@@ -1,96 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n85649200\n
-
- .include "testutils.inc"
- .data
-x:
- .dword -2,1,-0xffff,1,-0x5432f789
- .word -2,1,1,0x877
- .byte -2,1,0x77
- .byte 0x22
-
- start
- moveq -1,r3
- move.d x,r5
- sub.d [r5+],r3
- test_cc 0 0 0 0
- checkr3 1
-
- moveq 2,r3
- sub.d [r5],r3
- test_cc 0 0 0 0
- addq 4,r5
- checkr3 1
-
- move.d 0xffff,r3
- sub.d [r5+],r3
- test_cc 0 0 0 1
- checkr3 1fffe
-
- moveq -1,r3
- sub.d [r5+],r3
- test_cc 1 0 0 0
- checkr3 fffffffe
-
- move.d 0x78134452,r3
- sub.d [r5+],r3
- test_cc 1 0 1 1
- checkr3 cc463bdb
-
- moveq -1,r3
- sub.w [r5+],r3
- test_cc 0 0 0 0
- checkr3 ffff0001
-
- moveq 2,r3
- sub.w [r5+],r3
- test_cc 0 0 0 0
- checkr3 1
-
- move.d 0xffff,r3
- sub.w [r5],r3
- test_cc 1 0 0 0
- checkr3 fffe
-
- move.d 0xfedaffff,r3
- sub.w [r5+],r3
- test_cc 1 0 0 0
- checkr3 fedafffe
-
- move.d 0x78134452,r3
- sub.w [r5+],r3
- test_cc 0 0 0 0
- checkr3 78133bdb
-
- moveq -1,r3
- sub.b [r5],r3
- test_cc 0 0 0 0
- addq 1,r5
- checkr3 ffffff01
-
- moveq 2,r3
- sub.b [r5],r3
- test_cc 0 0 0 0
- checkr3 1
-
- move.d 0xff,r3
- sub.b [r5],r3
- test_cc 1 0 0 0
- checkr3 fe
-
- move.d 0xfeda49ff,r3
- sub.b [r5+],r3
- test_cc 1 0 0 0
- checkr3 feda49fe
-
- move.d 0x78134452,r3
- sub.b [r5+],r3
- test_cc 1 0 0 1
- checkr3 781344db
-
- move.d 0x85649222,r3
- sub.b [r5],r3
- test_cc 0 1 0 0
- checkr3 85649200
-
- quit
diff --git a/tests/cris/check_subq.s b/tests/cris/check_subq.s
deleted file mode 100644
index 9e34fa3..0000000
--- a/tests/cris/check_subq.s
+++ /dev/null
@@ -1,52 +0,0 @@
-# mach: crisv3 crisv8 crisv10 crisv32
-# output: 0\nffffffff\nfffffffe\nffff\nff\n56788f9\n56788d9\n567889a\n0\n7ffffffc\n
-
- .include "testutils.inc"
- start
- moveq 1,r3
- subq 1,r3
- test_cc 0 1 0 0
- checkr3 0
-
- subq 1,r3
- test_cc 1 0 0 1
- checkr3 ffffffff
-
- subq 1,r3
- test_cc 1 0 0 0
- checkr3 fffffffe
-
- move.d 0x10000,r3
- subq 1,r3
- test_cc 0 0 0 0
- checkr3 ffff
-
- move.d 0x100,r3
- subq 1,r3
- test_cc 0 0 0 0
- checkr3 ff
-
- move.d 0x5678900,r3
- subq 7,r3
- test_cc 0 0 0 0
- checkr3 56788f9
-
- subq 32,r3
- test_cc 0 0 0 0
- checkr3 56788d9
-
- subq 63,r3
- test_cc 0 0 0 0
- checkr3 567889a
-
- move.d 34,r3
- subq 34,r3
- test_cc 0 1 0 0
- checkr3 0
-
- move.d 0x80000024,r3
- subq 40,r3
- test_cc 0 0 1 0
- checkr3 7ffffffc
-
- quit
diff --git a/tests/cris/check_subr.s b/tests/cris/check_subr.s
deleted file mode 100644
index 742fbc8..0000000
--- a/tests/cris/check_subr.s
+++ /dev/null
@@ -1,102 +0,0 @@
-# mach: crisv0 crisv3 crisv8 crisv10 crisv32
-# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n85649200\n
-
- .include "testutils.inc"
- start
- moveq -1,r3
- moveq -2,r4
- sub.d r4,r3
- test_cc 0 0 0 0
- checkr3 1
-
- moveq 2,r3
- moveq 1,r4
- sub.d r4,r3
- test_cc 0 0 0 0
- checkr3 1
-
- move.d 0xffff,r3
- move.d -0xffff,r4
- sub.d r4,r3
- test_cc 0 0 0 1
- checkr3 1fffe
-
- moveq 1,r4
- moveq -1,r3
- sub.d r4,r3
- test_cc 1 0 0 0
- checkr3 fffffffe
-
- move.d -0x5432f789,r4
- move.d 0x78134452,r3
- sub.d r4,r3
- test_cc 1 0 1 1
- checkr3 cc463bdb
-
- moveq -1,r3
- moveq -2,r4
- sub.w r4,r3
- test_cc 0 0 0 0
- checkr3 ffff0001
-
- moveq 2,r3
- moveq 1,r4
- sub.w r4,r3
- test_cc 0 0 0 0
- checkr3 1
-
- move.d 0xffff,r3
- move.d -0xffff,r4
- sub.w r4,r3
- test_cc 1 0 0 0
- checkr3 fffe
-
- move.d 0xfedaffff,r3
- move.d -0xfedaffff,r4
- sub.w r4,r3
- test_cc 1 0 0 0
- checkr3 fedafffe
-
- move.d -0x5432f789,r4
- move.d 0x78134452,r3
- sub.w r4,r3
- test_cc 0 0 0 0
- checkr3 78133bdb
-
- moveq -1,r3
- moveq -2,r4
- sub.b r4,r3
- test_cc 0 0 0 0
- checkr3 ffffff01
-
- moveq 2,r3
- moveq 1,r4
- sub.b r4,r3
- test_cc 0 0 0 0
- checkr3 1
-
- move.d -0xff,r4
- move.d 0xff,r3
- sub.b r4,r3
- test_cc 1 0 0 0
- checkr3 fe
-
- move.d -0xfeda49ff,r4
- move.d 0xfeda49ff,r3
- sub.b r4,r3
- test_cc 1 0 0 0
- checkr3 feda49fe
-
- move.d -0x5432f789,r4
- move.d 0x78134452,r3
- sub.b r4,r3
- test_cc 1 0 0 1
- checkr3 781344db
-
- move.d 0x85649222,r3
- move.d 0x77445622,r4
- sub.b r4,r3
- test_cc 0 1 0 0
- checkr3 85649200
-
- quit
diff --git a/tests/cris/check_swap.c b/tests/cris/check_swap.c
deleted file mode 100644
index f851cbc..0000000
--- a/tests/cris/check_swap.c
+++ /dev/null
@@ -1,76 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include "sys.h"
-#include "crisutils.h"
-
-#define N 8
-#define W 4
-#define B 2
-#define R 1
-
-static inline int cris_swap(const int mode, int x)
-{
-	switch (mode)
-	{
-		case N: asm ("swapn\t%0\n" : "+r" (x) : "0" (x)); break;
-		case W: asm ("swapw\t%0\n" : "+r" (x) : "0" (x)); break;
-		case B: asm ("swapb\t%0\n" : "+r" (x) : "0" (x)); break;
-		case R: asm ("swapr\t%0\n" : "+r" (x) : "0" (x)); break;
-		case B|R: asm ("swapbr\t%0\n" : "+r" (x) : "0" (x)); break;
-		case W|R: asm ("swapwr\t%0\n" : "+r" (x) : "0" (x)); break;
-		case W|B: asm ("swapwb\t%0\n" : "+r" (x) : "0" (x)); break;
-		case W|B|R: asm ("swapwbr\t%0\n" : "+r" (x) : "0" (x)); break;
-		case N|R: asm ("swapnr\t%0\n" : "+r" (x) : "0" (x)); break;
-		case N|B: asm ("swapnb\t%0\n" : "+r" (x) : "0" (x)); break;
-		case N|B|R: asm ("swapnbr\t%0\n" : "+r" (x) : "0" (x)); break;
-		case N|W: asm ("swapnw\t%0\n" : "+r" (x) : "0" (x)); break;
-		default:
-			err();
-			break;
-	}
-	return x;
-}
-
-/* Made this a macro to be able to pick up the location of the errors.  */
-#define verify_swap(mode, val, expected, n, z)          \
-do {                                                    \
-        int r;                                          \
-        cris_tst_cc_init();                             \
-	r = cris_swap(mode, val);                       \
-        cris_tst_mov_cc(n, z);                          \
-	if (r != expected)                              \
-		err();                                  \
-} while(0)
-
-void check_swap(void)
-{
-	/* Some of these numbers are borrowed from GDB's cris sim
-	   testsuite.  */
-	if (cris_swap(N, 0) != 0xffffffff)
-		err();
-	if (cris_swap(W, 0x12345678) != 0x56781234)
-		err();
-	if (cris_swap(B, 0x12345678) != 0x34127856)
-		err();
-
-	verify_swap(R, 0x78134452, 0x1ec8224a, 0, 0);
-	verify_swap(B, 0x78134452, 0x13785244, 0, 0);
-	verify_swap(B|R, 0x78134452, 0xc81e4a22, 1, 0);
-	verify_swap(W, 0x78134452, 0x44527813, 0, 0);
-	verify_swap(W|R, 0x78134452, 0x224a1ec8, 0, 0);
-	verify_swap(W|B|R, 0x78134452, 0x4a22c81e, 0, 0);
-	verify_swap(N, 0x78134452, 0x87ecbbad, 1, 0);
-	verify_swap(N|R, 0x78134452, 0xe137ddb5, 1, 0);
-	verify_swap(N|B, 0x78134452, 0xec87adbb, 1, 0);
-	verify_swap(N|B|R, 0x78134452, 0x37e1b5dd, 0, 0);
-	verify_swap(N|W, 0x78134452, 0xbbad87ec, 1, 0);
-	verify_swap(N|B|R, 0xffffffff, 0, 0, 1);
-}
-
-int main(void)
-{
-	check_swap();
-	pass();
-	return 0;
-}
diff --git a/tests/cris/check_time1.c b/tests/cris/check_time1.c
deleted file mode 100644
index 3fcf0e1..0000000
--- a/tests/cris/check_time1.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Basic time functionality test: check that milliseconds are
-   incremented for each syscall (does not work on host).  */
-#include <stdio.h>
-#include <time.h>
-#include <sys/time.h>
-#include <string.h>
-#include <stdlib.h>
-
-void err (const char *s)
-{
-  perror (s);
-  abort ();
-}
-
-int
-main (void)
-{
-  struct timeval t_m = {0, 0};
-  struct timezone t_z = {0, 0};
-  struct timeval t_m1 = {0, 0};
-  int i;
-
-  if (gettimeofday (&t_m, &t_z) != 0)
-    err ("gettimeofday");
-
-  for (i = 1; i < 10000; i++)
-    if (gettimeofday (&t_m1, NULL) != 0)
-      err ("gettimeofday 1");
-    else
-      if (t_m1.tv_sec * 1000000 + t_m1.tv_usec
-	  != (t_m.tv_sec * 1000000 + t_m.tv_usec + i * 1000))
-	{
-	  fprintf (stderr, "t0 (%ld, %ld), i %d, t1 (%ld, %ld)\n",
-		   t_m.tv_sec, t_m.tv_usec, i, t_m1.tv_sec, t_m1.tv_usec);
-	  abort ();
-	}
-
-  if (time (NULL) != t_m1.tv_sec)
-    {
-      fprintf (stderr, "time != gettod\n");
-      abort ();
-    }
-
-  printf ("pass\n");
-  exit (0);
-}
diff --git a/tests/cris/check_time2.c b/tests/cris/check_time2.c
deleted file mode 100644
index 20b69b4..0000000
--- a/tests/cris/check_time2.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/* CB_SYS_time doesn't implement the Linux time syscall; the return
-   value isn't written to the argument.  */
-
-#include <time.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-int
-main (void)
-{
-  time_t x = (time_t) -1;
-  time_t t = time (&x);
-
-  if (t == (time_t) -1 || t != x)
-    abort ();
-  printf ("pass\n");
-  exit (0);
-}
diff --git a/tests/cris/check_xarith.s b/tests/cris/check_xarith.s
deleted file mode 100644
index 80038b2..0000000
--- a/tests/cris/check_xarith.s
+++ /dev/null
@@ -1,72 +0,0 @@
-
-.include "testutils.inc"
-
-	start
-
-	moveq	-1, $r0
-	moveq	0, $r1
-	addq	1, $r0
-	ax
-	addq	0, $r1
-
-	move.d	$r0, $r3
-	checkr3 0
-	move.d	$r1, $r3
-	checkr3 1
-
-	move.d  0, $r0
-	moveq	-1, $r1
-	subq	1, $r0
-	ax
-	subq	0, $r1
-
-	move.d	$r0, $r3
-	checkr3 ffffffff
-	move.d	$r1, $r3
-	checkr3 fffffffe
-
-
-	moveq	-1, $r0
-	moveq	-1, $r1
-	cmpq	-1, $r0
-	ax
-	cmpq	-1, $r1
-	beq	1f
-	nop
-	fail
-1:
-	cmpq	0, $r0
-	ax
-	cmpq	-1, $r1
-	bne	1f
-	nop
-	fail
-1:
-
-	;; test for broken X sequence, run it several times.
-	moveq	8, $r0
-1:
-	moveq	0, $r3
-	move.d	$r0, $r1
-	andq	1, $r1
-	lslq	4, $r1
-	moveq	1, $r2
-	or.d	$r1, $r2
-	ba	2f
-	move	$r2, $ccs
-2:
-	addq	0, $r3
-	move.d	$r0, $r4
-	move.d	$r1, $r5
-	move.d	$r2, $r6
-	move.d	$r3, $r7
-	lsrq	4, $r1
-	move.d	$r1, $r8
-	xor	$r1, $r3
-	checkr3	0
-	subq	1, $r0
-	bne	1b
-	nop
-
-	pass
-	quit
diff --git a/tests/cris/crisutils.h b/tests/cris/crisutils.h
deleted file mode 100644
index 29b71cd..0000000
--- a/tests/cris/crisutils.h
+++ /dev/null
@@ -1,71 +0,0 @@
-static char *tst_cc_loc = NULL;
-
-#define cris_tst_cc_init() \
-do { tst_cc_loc = "test_cc failed at " CURRENT_LOCATION; } while(0)
-
-/* We need a real symbol to signal error.  */
-void _err(void) {
-	if (!tst_cc_loc)
-		tst_cc_loc = "tst_cc_failed\n";
-	_fail(tst_cc_loc);
-}
-
-static inline void cris_tst_cc_n1(void)
-{
-	asm volatile ("bpl _err\n"
-		      "nop\n");
-}
-static inline void cris_tst_cc_n0(void)
-{
-	asm volatile ("bmi _err\n"
-		      "nop\n");
-}
-
-static inline void cris_tst_cc_z1(void)
-{
-	asm volatile ("bne _err\n"
-		      "nop\n");
-}
-static inline void cris_tst_cc_z0(void)
-{
-	asm volatile ("beq _err\n"
-		      "nop\n");
-}
-static inline void cris_tst_cc_v1(void)
-{
-	asm volatile ("bvc _err\n"
-		      "nop\n");
-}
-static inline void cris_tst_cc_v0(void)
-{
-	asm volatile ("bvs _err\n"
-		      "nop\n");
-}
-
-static inline void cris_tst_cc_c1(void)
-{
-	asm volatile ("bcc _err\n"
-		      "nop\n");
-}
-static inline void cris_tst_cc_c0(void)
-{
-	asm volatile ("bcs _err\n"
-		      "nop\n");
-}
-
-static inline void cris_tst_mov_cc(int n, int z)
-{
-	if (n) cris_tst_cc_n1(); else cris_tst_cc_n0();
-	if (z) cris_tst_cc_z1(); else cris_tst_cc_z0();
-	asm volatile ("" : : "g" (_err));
-}
-
-static inline void cris_tst_cc(const int n, const int z,
-			       const int v, const int c)
-{
-	if (n) cris_tst_cc_n1(); else cris_tst_cc_n0();
-	if (z) cris_tst_cc_z1(); else cris_tst_cc_z0();
-	if (v) cris_tst_cc_v1(); else cris_tst_cc_v0();
-	if (c) cris_tst_cc_c1(); else cris_tst_cc_c0();
-	asm volatile ("" : : "g" (_err));
-}
diff --git a/tests/cris/crt.s b/tests/cris/crt.s
deleted file mode 100644
index af027d7..0000000
--- a/tests/cris/crt.s
+++ /dev/null
@@ -1,13 +0,0 @@
-	.data
-_stack_start:
-	.space	8192, 0
-_stack_end:
-	.text
-	.global	_start
-_start:
-	move.d	_stack_end, $sp
-	jsr	main
-	nop
-	moveq	0, $r10
-	jump	exit
-	nop
diff --git a/tests/cris/sys.c b/tests/cris/sys.c
deleted file mode 100644
index 551c5dd..0000000
--- a/tests/cris/sys.c
+++ /dev/null
@@ -1,51 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-static inline int mystrlen(char *s) {
-	int i = 0;
-	while (s[i])
-		i++;
-	return i;
-}
-
-void pass(void) {
-	char s[] = "passed.\n";
-	write (1, s, sizeof (s) - 1);
-	exit (0);
-}
-
-void _fail(char *reason) {
-	char s[] = "\nfailed: ";
-	int len = mystrlen(reason);
-	write (1, s, sizeof (s) - 1);
-	write (1, reason, len);
-	write (1, "\n", 1);
-//	exit (1);
-}
-
-void *memset (void *s, int c, size_t n) {
-	char *p = s;
-	int i;
-	for (i = 0; i < n; i++)
-		p[i] = c;
-	return p;
-}
-
-void exit (int status) {
-	asm volatile ("moveq 1, $r9\n" /* NR_exit.  */
-		      "break 13\n");
-	while(1)
-		;
-}
-
-ssize_t write (int fd, const void *buf, size_t count) {
-	int r;
-	asm ("move.d %0, $r10\n"
-	     "move.d %1, $r11\n"
-	     "move.d %2, $r12\n"
-	     "moveq 4, $r9\n" /* NR_write.  */
-	     "break 13\n" : : "r" (fd), "r" (buf), "r" (count) : "memory");
-	asm ("move.d $r10, %0\n" : "=r" (r));
-	return r;
-}
diff --git a/tests/cris/sys.h b/tests/cris/sys.h
deleted file mode 100644
index c5f88e1..0000000
--- a/tests/cris/sys.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <unistd.h>
-
-#define STRINGIFY(x) #x
-#define TOSTRING(x) STRINGIFY(x)
-
-#define CURRENT_LOCATION __FILE__ ":" TOSTRING(__LINE__)
-
-#define err()                         \
-{                                     \
-  _fail("at " CURRENT_LOCATION " ");  \
-}
-
-#define mb() asm volatile ("" : : : "memory")
-
-void pass(void);
-void _fail(char *reason);
diff --git a/tests/cris/testutils.inc b/tests/cris/testutils.inc
deleted file mode 100644
index aa1641b..0000000
--- a/tests/cris/testutils.inc
+++ /dev/null
@@ -1,117 +0,0 @@
-	.syntax	no_register_prefix
-
-	.macro	start
-	.text
-	.global	main
-main:
-	.endm
-
-	.macro	quit
-	jump	pass
-	nop
-	.endm
-
-	.macro	pass
-	jump	pass
-	nop
-	.endm
-
-	.macro	startnostack
-	start
-	.endm
-
-	.macro	fail
-	.data
-99:
-	.asciz " checkr3 failed\n"
-	.text
-	move.d	99b, $r10
-	jsr	_fail
-	nop
-	.endm
-
-	.macro	checkr3 val
-	cmp.d	0x\val, $r3
-	beq	100f
-	nop
-	.data
-99:
-	.asciz "checkr3 failed\n"
-	.text
-	move.d	99b, $r10
-	jsr	_fail
-	nop
-100:
-	.endm
-
-; Test the condition codes
-        .macro test_cc N Z V C
-        .if \N
-        bpl 9f
-        nop
-        .else
-        bmi 9f
-        nop
-        .endif
-        .if \Z
-        bne 9f
-        nop
-        .else
-        beq 9f
-        nop
-        .endif
-        .if \V
-        bvc 9f
-        nop
-        .else
-        bvs 9f
-        nop
-        .endif
-        .if \C
-        bcc 9f
-        nop
-        .else
-        bcs 9f
-        nop
-        .endif
-        ba 8f
-        nop
-9:
-	.data
-99:
-	.asciz "test_move_cc failed\n"
-	.text
-	move.d	99b, $r10
-	jsr	_fail
-	nop
-8:
-        .endm
-
-
-        .macro test_move_cc N Z V C
-        .if \N
-        bpl 9f
-        nop
-        .else
-        bmi 9f
-        nop
-        .endif
-        .if \Z
-        bne 9f
-        nop
-        .else
-        beq 9f
-        nop
-        .endif
-        ba 8f
-        nop
-9:
-	.data
-99:
-	.asciz "test_move_cc failed\n"
-	.text
-	move.d	99b, $r10
-	jsr	_fail
-	nop
-8:
-        .endm
diff --git a/tests/hello-arm.c b/tests/hello-arm.c
deleted file mode 100644
index e0daa7a..0000000
--- a/tests/hello-arm.c
+++ /dev/null
@@ -1,113 +0,0 @@
-#define __NR_SYSCALL_BASE	0x900000
-#define __NR_exit1			(__NR_SYSCALL_BASE+  1)
-#define __NR_write			(__NR_SYSCALL_BASE+  4)
-
-#define __sys2(x) #x
-#define __sys1(x) __sys2(x)
-
-#ifndef __syscall
-#define __syscall(name) "swi\t" __sys1(__NR_##name) "\n\t"
-#endif
-
-#define __syscall_return(type, res)					\
-do {									\
-	return (type) (res);						\
-} while (0)
-
-#define _syscall0(type,name)						\
-type name(void) {							\
-  long __res;								\
-  __asm__ __volatile__ (						\
-  __syscall(name)							\
-  "mov %0,r0"								\
-  :"=r" (__res) : : "r0","lr");						\
-  __syscall_return(type,__res);						\
-}
-
-#define _syscall1(type,name,type1,arg1)					\
-type name(type1 arg1) {							\
-  long __res;								\
-  __asm__ __volatile__ (						\
-  "mov\tr0,%1\n\t"							\
-  __syscall(name)							\
-  "mov %0,r0"								\
-        : "=r" (__res)							\
-        : "r" ((long)(arg1))						\
-	: "r0","lr");							\
-  __syscall_return(type,__res);						\
-}
-
-#define _syscall2(type,name,type1,arg1,type2,arg2)			\
-type name(type1 arg1,type2 arg2) {					\
-  long __res;								\
-  __asm__ __volatile__ (						\
-  "mov\tr0,%1\n\t"							\
-  "mov\tr1,%2\n\t"							\
-  __syscall(name)							\
-  "mov\t%0,r0"								\
-        : "=r" (__res)							\
-        : "r" ((long)(arg1)),"r" ((long)(arg2))				\
-	: "r0","r1","lr");						\
-  __syscall_return(type,__res);						\
-}
-
-
-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)		\
-type name(type1 arg1,type2 arg2,type3 arg3) {				\
-  long __res;								\
-  __asm__ __volatile__ (						\
-  "mov\tr0,%1\n\t"							\
-  "mov\tr1,%2\n\t"							\
-  "mov\tr2,%3\n\t"							\
-  __syscall(name)							\
-  "mov\t%0,r0"								\
-        : "=r" (__res)							\
-        : "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3))	\
-        : "r0","r1","r2","lr");						\
-  __syscall_return(type,__res);						\
-}
-
-
-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)		\
-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) {				\
-  long __res;										\
-  __asm__ __volatile__ (								\
-  "mov\tr0,%1\n\t"									\
-  "mov\tr1,%2\n\t"									\
-  "mov\tr2,%3\n\t"									\
-  "mov\tr3,%4\n\t"									\
-  __syscall(name)									\
-  "mov\t%0,r0"										\
-  	: "=r" (__res)									\
-  	: "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)),"r" ((long)(arg4))	\
-  	: "r0","r1","r2","r3","lr");							\
-  __syscall_return(type,__res);								\
-}
-
-
-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5)	\
-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) {			\
-  long __res;										\
-  __asm__ __volatile__ (								\
-  "mov\tr0,%1\n\t"									\
-  "mov\tr1,%2\n\t"									\
-  "mov\tr2,%3\n\t"									\
-  "mov\tr3,%4\n\t"									\
-  "mov\tr4,%5\n\t"									\
-  __syscall(name)									\
-  "mov\t%0,r0"										\
-  	: "=r" (__res)									\
-  	: "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)),"r" ((long)(arg4)),	\
-	  "r" ((long)(arg5))								\
-	: "r0","r1","r2","r3","r4","lr");						\
-  __syscall_return(type,__res);								\
-}
-
-_syscall1(int,exit1,int,status);
-_syscall3(int,write,int,fd,const char *,buf, int, len);
-
-void _start(void)
-{
-    write(1, "Hello World\n", 12);
-    exit1(0);
-}
diff --git a/tests/hello-i386.c b/tests/hello-i386.c
deleted file mode 100644
index 86afc34..0000000
--- a/tests/hello-i386.c
+++ /dev/null
@@ -1,26 +0,0 @@
-#include <asm/unistd.h>
-
-static inline volatile void exit(int status)
-{
-  int __res;
-  __asm__ volatile ("movl %%ecx,%%ebx\n"\
-		    "int $0x80" \
-		    :  "=a" (__res) : "0" (__NR_exit),"c" ((long)(status)));
-}
-
-static inline int write(int fd, const char * buf, int len)
-{
-  int status;
-  __asm__ volatile ("pushl %%ebx\n"\
-		    "movl %%esi,%%ebx\n"\
-		    "int $0x80\n" \
-		    "popl %%ebx\n"\
-		    : "=a" (status) \
-		    : "0" (__NR_write),"S" ((long)(fd)),"c" ((long)(buf)),"d" ((long)(len)));
-}
-
-void _start(void)
-{
-    write(1, "Hello World\n", 12);
-    exit(0);
-}
diff --git a/tests/hello-mips.c b/tests/hello-mips.c
deleted file mode 100644
index f825673..0000000
--- a/tests/hello-mips.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-* MIPS o32 Linux syscall example
-*
-* http://www.linux-mips.org/wiki/RISC/os
-* http://www.linux-mips.org/wiki/MIPSABIHistory
-* http://www.linux.com/howtos/Assembly-HOWTO/mips.shtml
-*
-* mipsel-linux-gcc -nostdlib -mno-abicalls -fno-PIC -mabi=32 \
-*                  -O2 -static -o hello-mips hello-mips.c
-*
-*/
-#define __NR_SYSCALL_BASE	4000
-#define __NR_exit			(__NR_SYSCALL_BASE+  1)
-#define __NR_write			(__NR_SYSCALL_BASE+  4)
-
-static inline void exit1(int status)
-{
-    register unsigned long __a0 asm("$4") = (unsigned long) status;
-
-    __asm__ __volatile__ (
-        "	.set push	\n"
-        "	.set noreorder	\n"
-        "	li	$2, %0	\n"
-        "	syscall		\n"
-        "	.set pop	"
-        :
-	: "i" (__NR_exit), "r" (__a0)
-	: "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24",
-	  "memory");
-}
-
-static inline int write(int fd, const char *buf, int len)
-{
-    register unsigned long __a0 asm("$4") = (unsigned long) fd;
-    register unsigned long __a1 asm("$5") = (unsigned long) buf;
-    register unsigned long __a2 asm("$6") = (unsigned long) len;
-    register unsigned long __a3 asm("$7");
-    unsigned long __v0;
-
-    __asm__ __volatile__ (
-        "	.set push	\n"
-        "	.set noreorder	\n"
-        "	li	$2, %2	\n"
-        "	syscall		\n"
-        "	move	%0, $2	\n"
-        "	.set pop	"
-        : "=r" (__v0), "=r" (__a3)
-        : "i" (__NR_write), "r" (__a0), "r" (__a1), "r" (__a2)
-	: "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24",
-	  "memory");
-
-/*    if (__a3 == 0) */
-        return (int) __v0;
-/*
-    errno = __v0;
-    return -1;
- */
-}
-
-void __start(void)
-{
-    write (1, "Hello, World!\n", 14);
-    exit1 (42);
-}
diff --git a/tests/linux-test.c b/tests/linux-test.c
deleted file mode 100644
index 2e4a746..0000000
--- a/tests/linux-test.c
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- *  linux and CPU test
- *
- *  Copyright (c) 2003 Fabrice Bellard
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <utime.h>
-#include <time.h>
-#include <sys/time.h>
-#include <sys/uio.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sched.h>
-#include <dirent.h>
-#include <setjmp.h>
-#include <sys/shm.h>
-
-#define TESTPATH "/tmp/linux-test.tmp"
-#define TESTPORT 7654
-#define STACK_SIZE 16384
-
-void error1(const char *filename, int line, const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    fprintf(stderr, "%s:%d: ", filename, line);
-    vfprintf(stderr, fmt, ap);
-    fprintf(stderr, "\n");
-    va_end(ap);
-    exit(1);
-}
-
-int __chk_error(const char *filename, int line, int ret)
-{
-    if (ret < 0) {
-        error1(filename, line, "%m (ret=%d, errno=%d)",
-               ret, errno);
-    }
-    return ret;
-}
-
-#define error(fmt, ...) error1(__FILE__, __LINE__, fmt, ## __VA_ARGS__)
-
-#define chk_error(ret) __chk_error(__FILE__, __LINE__, (ret))
-
-/*******************************************************/
-
-#define FILE_BUF_SIZE 300
-
-void test_file(void)
-{
-    int fd, i, len, ret;
-    uint8_t buf[FILE_BUF_SIZE];
-    uint8_t buf2[FILE_BUF_SIZE];
-    uint8_t buf3[FILE_BUF_SIZE];
-    char cur_dir[1024];
-    struct stat st;
-    struct utimbuf tbuf;
-    struct iovec vecs[2];
-    DIR *dir;
-    struct dirent *de;
-
-    /* clean up, just in case */
-    unlink(TESTPATH "/file1");
-    unlink(TESTPATH "/file2");
-    unlink(TESTPATH "/file3");
-    rmdir(TESTPATH);
-
-    if (getcwd(cur_dir, sizeof(cur_dir)) == NULL)
-        error("getcwd");
-
-    chk_error(mkdir(TESTPATH, 0755));
-
-    chk_error(chdir(TESTPATH));
-
-    /* open/read/write/close/readv/writev/lseek */
-
-    fd = chk_error(open("file1", O_WRONLY | O_TRUNC | O_CREAT, 0644));
-    for(i=0;i < FILE_BUF_SIZE; i++)
-        buf[i] = i;
-    len = chk_error(write(fd, buf, FILE_BUF_SIZE / 2));
-    if (len != (FILE_BUF_SIZE / 2))
-        error("write");
-    vecs[0].iov_base = buf + (FILE_BUF_SIZE / 2);
-    vecs[0].iov_len = 16;
-    vecs[1].iov_base = buf + (FILE_BUF_SIZE / 2) + 16;
-    vecs[1].iov_len = (FILE_BUF_SIZE / 2) - 16;
-    len = chk_error(writev(fd, vecs, 2));
-    if (len != (FILE_BUF_SIZE / 2))
-     error("writev");
-    chk_error(close(fd));
-
-    chk_error(rename("file1", "file2"));
-
-    fd = chk_error(open("file2", O_RDONLY));
-
-    len = chk_error(read(fd, buf2, FILE_BUF_SIZE));
-    if (len != FILE_BUF_SIZE)
-        error("read");
-    if (memcmp(buf, buf2, FILE_BUF_SIZE) != 0)
-        error("memcmp");
-
-#define FOFFSET 16
-    ret = chk_error(lseek(fd, FOFFSET, SEEK_SET));
-    if (ret != 16)
-        error("lseek");
-    vecs[0].iov_base = buf3;
-    vecs[0].iov_len = 32;
-    vecs[1].iov_base = buf3 + 32;
-    vecs[1].iov_len = FILE_BUF_SIZE - FOFFSET - 32;
-    len = chk_error(readv(fd, vecs, 2));
-    if (len != FILE_BUF_SIZE - FOFFSET)
-        error("readv");
-    if (memcmp(buf + FOFFSET, buf3, FILE_BUF_SIZE - FOFFSET) != 0)
-        error("memcmp");
-
-    chk_error(close(fd));
-
-    /* access */
-    chk_error(access("file2", R_OK));
-
-    /* stat/chmod/utime/truncate */
-
-    chk_error(chmod("file2", 0600));
-    tbuf.actime = 1001;
-    tbuf.modtime = 1000;
-    chk_error(truncate("file2", 100));
-    chk_error(utime("file2", &tbuf));
-    chk_error(stat("file2", &st));
-    if (st.st_size != 100)
-        error("stat size");
-    if (!S_ISREG(st.st_mode))
-        error("stat mode");
-    if ((st.st_mode & 0777) != 0600)
-        error("stat mode2");
-    if (st.st_atime != 1001 ||
-        st.st_mtime != 1000)
-        error("stat time");
-
-    chk_error(stat(TESTPATH, &st));
-    if (!S_ISDIR(st.st_mode))
-        error("stat mode");
-
-    /* fstat */
-    fd = chk_error(open("file2", O_RDWR));
-    chk_error(ftruncate(fd, 50));
-    chk_error(fstat(fd, &st));
-    chk_error(close(fd));
-
-    if (st.st_size != 50)
-        error("stat size");
-    if (!S_ISREG(st.st_mode))
-        error("stat mode");
-
-    /* symlink/lstat */
-    chk_error(symlink("file2", "file3"));
-    chk_error(lstat("file3", &st));
-    if (!S_ISLNK(st.st_mode))
-        error("stat mode");
-
-    /* getdents */
-    dir = opendir(TESTPATH);
-    if (!dir)
-        error("opendir");
-    len = 0;
-    for(;;) {
-        de = readdir(dir);
-        if (!de)
-            break;
-        if (strcmp(de->d_name, ".") != 0 &&
-            strcmp(de->d_name, "..") != 0 &&
-            strcmp(de->d_name, "file2") != 0 &&
-            strcmp(de->d_name, "file3") != 0)
-            error("readdir");
-        len++;
-    }
-    closedir(dir);
-    if (len != 4)
-        error("readdir");
-
-    chk_error(unlink("file3"));
-    chk_error(unlink("file2"));
-    chk_error(chdir(cur_dir));
-    chk_error(rmdir(TESTPATH));
-}
-
-void test_fork(void)
-{
-    int pid, status;
-
-    pid = chk_error(fork());
-    if (pid == 0) {
-        /* child */
-        exit(2);
-    }
-    chk_error(waitpid(pid, &status, 0));
-    if (!WIFEXITED(status) || WEXITSTATUS(status) != 2)
-        error("waitpid status=0x%x", status);
-}
-
-void test_time(void)
-{
-    struct timeval tv, tv2;
-    struct timespec ts, rem;
-    struct rusage rusg1, rusg2;
-    int ti, i;
-
-    chk_error(gettimeofday(&tv, NULL));
-    rem.tv_sec = 1;
-    ts.tv_sec = 0;
-    ts.tv_nsec = 20 * 1000000;
-    chk_error(nanosleep(&ts, &rem));
-    if (rem.tv_sec != 1)
-        error("nanosleep");
-    chk_error(gettimeofday(&tv2, NULL));
-    ti = tv2.tv_sec - tv.tv_sec;
-    if (ti >= 2)
-        error("gettimeofday");
-
-    chk_error(getrusage(RUSAGE_SELF, &rusg1));
-    for(i = 0;i < 10000; i++);
-    chk_error(getrusage(RUSAGE_SELF, &rusg2));
-    if ((rusg2.ru_utime.tv_sec - rusg1.ru_utime.tv_sec) < 0 ||
-        (rusg2.ru_stime.tv_sec - rusg1.ru_stime.tv_sec) < 0)
-        error("getrusage");
-}
-
-void pstrcpy(char *buf, int buf_size, const char *str)
-{
-    int c;
-    char *q = buf;
-
-    if (buf_size <= 0)
-        return;
-
-    for(;;) {
-        c = *str++;
-        if (c == 0 || q >= buf + buf_size - 1)
-            break;
-        *q++ = c;
-    }
-    *q = '\0';
-}
-
-/* strcat and truncate. */
-char *pstrcat(char *buf, int buf_size, const char *s)
-{
-    int len;
-    len = strlen(buf);
-    if (len < buf_size)
-        pstrcpy(buf + len, buf_size - len, s);
-    return buf;
-}
-
-int server_socket(void)
-{
-    int val, fd;
-    struct sockaddr_in sockaddr;
-
-    /* server socket */
-    fd = chk_error(socket(PF_INET, SOCK_STREAM, 0));
-
-    val = 1;
-    chk_error(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)));
-
-    sockaddr.sin_family = AF_INET;
-    sockaddr.sin_port = htons(TESTPORT);
-    sockaddr.sin_addr.s_addr = 0;
-    chk_error(bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)));
-    chk_error(listen(fd, 0));
-    return fd;
-
-}
-
-int client_socket(void)
-{
-    int fd;
-    struct sockaddr_in sockaddr;
-
-    /* server socket */
-    fd = chk_error(socket(PF_INET, SOCK_STREAM, 0));
-    sockaddr.sin_family = AF_INET;
-    sockaddr.sin_port = htons(TESTPORT);
-    inet_aton("127.0.0.1", &sockaddr.sin_addr);
-    chk_error(connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)));
-    return fd;
-}
-
-const char socket_msg[] = "hello socket\n";
-
-void test_socket(void)
-{
-    int server_fd, client_fd, fd, pid, ret, val;
-    struct sockaddr_in sockaddr;
-    socklen_t len;
-    char buf[512];
-
-    server_fd = server_socket();
-
-    /* test a few socket options */
-    len = sizeof(val);
-    chk_error(getsockopt(server_fd, SOL_SOCKET, SO_TYPE, &val, &len));
-    if (val != SOCK_STREAM)
-        error("getsockopt");
-
-    pid = chk_error(fork());
-    if (pid == 0) {
-        client_fd = client_socket();
-        send(client_fd, socket_msg, sizeof(socket_msg), 0);
-        close(client_fd);
-        exit(0);
-    }
-    len = sizeof(sockaddr);
-    fd = chk_error(accept(server_fd, (struct sockaddr *)&sockaddr, &len));
-
-    ret = chk_error(recv(fd, buf, sizeof(buf), 0));
-    if (ret != sizeof(socket_msg))
-        error("recv");
-    if (memcmp(buf, socket_msg, sizeof(socket_msg)) != 0)
-        error("socket_msg");
-    chk_error(close(fd));
-    chk_error(close(server_fd));
-}
-
-#define WCOUNT_MAX 512
-
-void test_pipe(void)
-{
-    fd_set rfds, wfds;
-    int fds[2], fd_max, ret;
-    uint8_t ch;
-    int wcount, rcount;
-
-    chk_error(pipe(fds));
-    chk_error(fcntl(fds[0], F_SETFL, O_NONBLOCK));
-    chk_error(fcntl(fds[1], F_SETFL, O_NONBLOCK));
-    wcount = 0;
-    rcount = 0;
-    for(;;) {
-        FD_ZERO(&rfds);
-        fd_max = fds[0];
-        FD_SET(fds[0], &rfds);
-
-        FD_ZERO(&wfds);
-        FD_SET(fds[1], &wfds);
-        if (fds[1] > fd_max)
-            fd_max = fds[1];
-
-        ret = chk_error(select(fd_max + 1, &rfds, &wfds, NULL, NULL));
-        if (ret > 0) {
-            if (FD_ISSET(fds[0], &rfds)) {
-                chk_error(read(fds[0], &ch, 1));
-                rcount++;
-                if (rcount >= WCOUNT_MAX)
-                    break;
-            }
-            if (FD_ISSET(fds[1], &wfds)) {
-                ch = 'a';
-                chk_error(write(fds[0], &ch, 1));
-                wcount++;
-            }
-        }
-    }
-    chk_error(close(fds[0]));
-    chk_error(close(fds[1]));
-}
-
-int thread1_res;
-int thread2_res;
-
-int thread1_func(void *arg)
-{
-    int i;
-    for(i=0;i<5;i++) {
-        thread1_res++;
-        usleep(10 * 1000);
-    }
-    return 0;
-}
-
-int thread2_func(void *arg)
-{
-    int i;
-    for(i=0;i<6;i++) {
-        thread2_res++;
-        usleep(10 * 1000);
-    }
-    return 0;
-}
-
-void test_clone(void)
-{
-    uint8_t *stack1, *stack2;
-    int pid1, pid2, status1, status2;
-
-    stack1 = malloc(STACK_SIZE);
-    pid1 = chk_error(clone(thread1_func, stack1 + STACK_SIZE,
-                           CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello1"));
-
-    stack2 = malloc(STACK_SIZE);
-    pid2 = chk_error(clone(thread2_func, stack2 + STACK_SIZE,
-                           CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello2"));
-
-    while (waitpid(pid1, &status1, 0) != pid1);
-    free(stack1);
-    while (waitpid(pid2, &status2, 0) != pid2);
-    free(stack2);
-    if (thread1_res != 5 ||
-        thread2_res != 6)
-        error("clone");
-}
-
-/***********************************/
-
-volatile int alarm_count;
-jmp_buf jmp_env;
-
-void sig_alarm(int sig)
-{
-    if (sig != SIGALRM)
-        error("signal");
-    alarm_count++;
-}
-
-void sig_segv(int sig, siginfo_t *info, void *puc)
-{
-    if (sig != SIGSEGV)
-        error("signal");
-    longjmp(jmp_env, 1);
-}
-
-void test_signal(void)
-{
-    struct sigaction act;
-    struct itimerval it, oit;
-
-    /* timer test */
-
-    alarm_count = 0;
-
-    act.sa_handler = sig_alarm;
-    sigemptyset(&act.sa_mask);
-    act.sa_flags = 0;
-    chk_error(sigaction(SIGALRM, &act, NULL));
-
-    it.it_interval.tv_sec = 0;
-    it.it_interval.tv_usec = 10 * 1000;
-    it.it_value.tv_sec = 0;
-    it.it_value.tv_usec = 10 * 1000;
-    chk_error(setitimer(ITIMER_REAL, &it, NULL));
-    chk_error(getitimer(ITIMER_REAL, &oit));
-    if (oit.it_value.tv_sec != it.it_value.tv_sec ||
-        oit.it_value.tv_usec != it.it_value.tv_usec)
-        error("itimer");
-
-    while (alarm_count < 5) {
-        usleep(10 * 1000);
-    }
-
-    it.it_interval.tv_sec = 0;
-    it.it_interval.tv_usec = 0;
-    it.it_value.tv_sec = 0;
-    it.it_value.tv_usec = 0;
-    memset(&oit, 0xff, sizeof(oit));
-    chk_error(setitimer(ITIMER_REAL, &it, &oit));
-    if (oit.it_value.tv_sec != 0 ||
-        oit.it_value.tv_usec != 10 * 1000)
-        error("setitimer");
-
-    /* SIGSEGV test */
-    act.sa_sigaction = sig_segv;
-    sigemptyset(&act.sa_mask);
-    act.sa_flags = SA_SIGINFO;
-    chk_error(sigaction(SIGSEGV, &act, NULL));
-    if (setjmp(jmp_env) == 0) {
-        *(uint8_t *)0 = 0;
-    }
-
-    act.sa_handler = SIG_DFL;
-    sigemptyset(&act.sa_mask);
-    act.sa_flags = 0;
-    chk_error(sigaction(SIGSEGV, &act, NULL));
-}
-
-#define SHM_SIZE 32768
-
-void test_shm(void)
-{
-    void *ptr;
-    int shmid;
-
-    shmid = chk_error(shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0777));
-    ptr = shmat(shmid, NULL, 0);
-    if (!ptr)
-        error("shmat");
-
-    memset(ptr, 0, SHM_SIZE);
-
-    chk_error(shmctl(shmid, IPC_RMID, 0));
-    chk_error(shmdt(ptr));
-}
-
-int main(int argc, char **argv)
-{
-    test_file();
-    test_fork();
-    test_time();
-    test_socket();
-    //    test_clone();
-    test_signal();
-    test_shm();
-    return 0;
-}
diff --git a/tests/lm32/Makefile b/tests/lm32/Makefile
deleted file mode 100644
index 03a1abb..0000000
--- a/tests/lm32/Makefile
+++ /dev/null
@@ -1,102 +0,0 @@
--include ../../config-host.mak
-
-CROSS=lm32-elf-
-
-SIM = qemu-system-lm32
-SIMFLAGS = -M lm32-evr -nographic -device lm32-sys -net none -kernel
-
-CC      = $(CROSS)gcc
-AS      = $(CROSS)as
-AS      = $(CC) -x assembler
-SIZE    = $(CROSS)size
-LD      = $(CC)
-OBJCOPY = $(CROSS)objcopy
-
-LDFLAGS = -Tlinker.ld
-
-CRT        = crt.o
-TESTCASES += test_add.tst
-TESTCASES += test_addi.tst
-TESTCASES += test_and.tst
-TESTCASES += test_andhi.tst
-TESTCASES += test_andi.tst
-TESTCASES += test_b.tst
-TESTCASES += test_be.tst
-TESTCASES += test_bg.tst
-TESTCASES += test_bge.tst
-TESTCASES += test_bgeu.tst
-TESTCASES += test_bgu.tst
-TESTCASES += test_bi.tst
-TESTCASES += test_bne.tst
-TESTCASES += test_break.tst
-TESTCASES += test_bret.tst
-TESTCASES += test_call.tst
-TESTCASES += test_calli.tst
-TESTCASES += test_cmpe.tst
-TESTCASES += test_cmpei.tst
-TESTCASES += test_cmpg.tst
-TESTCASES += test_cmpgi.tst
-TESTCASES += test_cmpge.tst
-TESTCASES += test_cmpgei.tst
-TESTCASES += test_cmpgeu.tst
-TESTCASES += test_cmpgeui.tst
-TESTCASES += test_cmpgu.tst
-TESTCASES += test_cmpgui.tst
-TESTCASES += test_cmpne.tst
-TESTCASES += test_cmpnei.tst
-TESTCASES += test_divu.tst
-TESTCASES += test_eret.tst
-TESTCASES += test_lb.tst
-TESTCASES += test_lbu.tst
-TESTCASES += test_lh.tst
-TESTCASES += test_lhu.tst
-TESTCASES += test_lw.tst
-TESTCASES += test_modu.tst
-TESTCASES += test_mul.tst
-TESTCASES += test_muli.tst
-TESTCASES += test_nor.tst
-TESTCASES += test_nori.tst
-TESTCASES += test_or.tst
-TESTCASES += test_ori.tst
-TESTCASES += test_orhi.tst
-#TESTCASES += test_rcsr.tst
-TESTCASES += test_ret.tst
-TESTCASES += test_sb.tst
-TESTCASES += test_scall.tst
-TESTCASES += test_sextb.tst
-TESTCASES += test_sexth.tst
-TESTCASES += test_sh.tst
-TESTCASES += test_sl.tst
-TESTCASES += test_sli.tst
-TESTCASES += test_sr.tst
-TESTCASES += test_sri.tst
-TESTCASES += test_sru.tst
-TESTCASES += test_srui.tst
-TESTCASES += test_sub.tst
-TESTCASES += test_sw.tst
-#TESTCASES += test_wcsr.tst
-TESTCASES += test_xnor.tst
-TESTCASES += test_xnori.tst
-TESTCASES += test_xor.tst
-TESTCASES += test_xori.tst
-
-all: build
-
-%.o: $(SRC_PATH)/tests/lm32/%.c
-	$(CC) $(CFLAGS) -c $< -o $@
-
-%.o: $(SRC_PATH)/tests/lm32/%.S
-	$(AS) $(ASFLAGS) -c $< -o $@
-
-%.tst: %.o macros.inc $(CRT)
-	$(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $< -o $@
-
-build: $(CRT) $(TESTCASES)
-
-check: $(CRT) $(SYS) $(TESTCASES)
-	@for case in $(TESTCASES); do \
-		$(SIM) $(SIMFLAGS) ./$$case; \
-	done
-
-clean:
-	$(RM) -fr $(TESTCASES) $(CRT)
diff --git a/tests/lm32/crt.S b/tests/lm32/crt.S
deleted file mode 100644
index 5f9cfd9..0000000
--- a/tests/lm32/crt.S
+++ /dev/null
@@ -1,84 +0,0 @@
-.text
-.global _start
-
-_start:
-_reset_handler:
-	xor r0, r0, r0
-	mvhi r1, hi(_start)
-	ori r1, r1, lo(_start)
-	wcsr eba, r1
-	wcsr deba, r1
-	bi _main
-	nop
-	nop
-
-_breakpoint_handler:
-	ori r25, r25, 1
-	addi ra, ba, 4
-	ret
-	nop
-	nop
-	nop
-	nop
-	nop
-
-_instruction_bus_error_handler:
-	ori r25, r25, 2
-	addi ra, ea, 4
-	ret
-	nop
-	nop
-	nop
-	nop
-	nop
-
-_watchpoint_handler:
-	ori r25, r25, 4
-	addi ra, ba, 4
-	ret
-	nop
-	nop
-	nop
-	nop
-	nop
-
-_data_bus_error_handler:
-	ori r25, r25, 8
-	addi ra, ea, 4
-	ret
-	nop
-	nop
-	nop
-	nop
-	nop
-
-_divide_by_zero_handler:
-	ori r25, r25, 16
-	addi ra, ea, 4
-	ret
-	nop
-	nop
-	nop
-	nop
-	nop
-
-_interrupt_handler:
-	ori r25, r25, 32
-	addi ra, ea, 4
-	ret
-	nop
-	nop
-	nop
-	nop
-	nop
-
-_system_call_handler:
-	ori r25, r25, 64
-	addi ra, ea, 4
-	ret
-	nop
-	nop
-	nop
-	nop
-	nop
-
diff --git a/tests/lm32/linker.ld b/tests/lm32/linker.ld
deleted file mode 100644
index 52d43a4..0000000
--- a/tests/lm32/linker.ld
+++ /dev/null
@@ -1,55 +0,0 @@
-OUTPUT_FORMAT("elf32-lm32")
-ENTRY(_start)
-
-__DYNAMIC = 0;
-
-MEMORY {
-	ram : ORIGIN = 0x08000000, LENGTH = 0x04000000  /* 64M */
-}
-
-SECTIONS
-{
-	.text :
-	{
-		_ftext = .;
-		*(.text .stub .text.* .gnu.linkonce.t.*)
-		_etext = .;
-	} > ram
-
-	.rodata :
-	{
-		. = ALIGN(4);
-		_frodata = .;
-		*(.rodata .rodata.* .gnu.linkonce.r.*)
-		*(.rodata1)
-		_erodata = .;
-	} > ram
-
-	.data :
-	{
-		. = ALIGN(4);
-		_fdata = .;
-		*(.data .data.* .gnu.linkonce.d.*)
-		*(.data1)
-		_gp = ALIGN(16);
-		*(.sdata .sdata.* .gnu.linkonce.s.*)
-		_edata = .;
-	} > ram
-
-	.bss :
-	{
-		. = ALIGN(4);
-		_fbss = .;
-		*(.dynsbss)
-		*(.sbss .sbss.* .gnu.linkonce.sb.*)
-		*(.scommon)
-		*(.dynbss)
-		*(.bss .bss.* .gnu.linkonce.b.*)
-		*(COMMON)
-		_ebss = .;
-		_end = .;
-	} > ram
-}
-
-PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4);
-
diff --git a/tests/lm32/macros.inc b/tests/lm32/macros.inc
deleted file mode 100644
index 367c7c5..0000000
--- a/tests/lm32/macros.inc
+++ /dev/null
@@ -1,79 +0,0 @@
-
-.macro test_name name
-	.data
-tn_\name:
-	.asciz "\name"
-	.text
-	mvhi r13, hi(tn_\name)
-	ori r13, r13, lo(tn_\name)
-	sw (r12+8), r13
-.endm
-
-.macro load reg val
-	mvhi \reg, hi(\val)
-	ori \reg, \reg, lo(\val)
-.endm
-
-.macro tc_pass
-	mvi r13, 0
-	sw (r12+4), r13
-.endm
-
-.macro tc_fail
-	mvi r13, 1
-	sw (r12+4), r13
-.endm
-
-.macro check_r3 val
-	mvhi r13, hi(\val)
-	ori r13, r13, lo(\val)
-	be r3, r13, 1f
-	tc_fail
-	bi 2f
-1:
-	tc_pass
-2:
-.endm
-
-.macro check_mem adr val
-	mvhi r13, hi(\adr)
-	ori r13, r13, lo(\adr)
-	mvhi r14, hi(\val)
-	ori r14, r14, lo(\val)
-	lw r13, (r13+0)
-	be r13, r14, 1f
-	tc_fail
-	bi 2f
-1:
-	tc_pass
-2:
-.endm
-
-.macro check_excp excp
-	andi r13, r25, \excp
-	bne r13, r0, 1f
-	tc_fail
-	bi 2f
-1:
-	tc_pass
-2:
-.endm
-
-.macro start
-	.global _main
-	.text
-_main:
-	mvhi r12, hi(0xffff0000)      # base address of test block
-	ori r12, r12, lo(0xffff0000)
-.endm
-
-.macro end
-	sw (r12+0), r0
-1:
-	bi 1b
-.endm
-
-# base +
-#  0  ctrl
-#  4  pass/fail
-#  8  ptr to test name
diff --git a/tests/lm32/test_add.S b/tests/lm32/test_add.S
deleted file mode 100644
index 030ad19..0000000
--- a/tests/lm32/test_add.S
+++ /dev/null
@@ -1,75 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name ADD_1
-mvi r1, 0
-mvi r2, 0
-add r3, r1, r2
-check_r3 0
-
-test_name ADD_2
-mvi r1, 0
-mvi r2, 1
-add r3, r1, r2
-check_r3 1
-
-test_name ADD_3
-mvi r1, 1
-mvi r2, 0
-add r3, r1, r2
-check_r3 1
-
-test_name ADD_4
-mvi r1, 1
-mvi r2, -1
-add r3, r1, r2
-check_r3 0
-
-test_name ADD_5
-mvi r1, -1
-mvi r2, 1
-add r3, r1, r2
-check_r3 0
-
-test_name ADD_6
-mvi r1, -1
-mvi r2, 0
-add r3, r1, r2
-check_r3 -1
-
-test_name ADD_7
-mvi r1, 0
-mvi r2, -1
-add r3, r1, r2
-check_r3 -1
-
-test_name ADD_8
-mvi r3, 2
-add r3, r3, r3
-check_r3 4
-
-test_name ADD_9
-mvi r1, 4
-mvi r3, 2
-add r3, r1, r3
-check_r3 6
-
-test_name ADD_10
-mvi r1, 4
-mvi r3, 2
-add r3, r3, r1
-check_r3 6
-
-test_name ADD_11
-mvi r1, 4
-add r3, r1, r1
-check_r3 8
-
-test_name ADD_12
-load r1 0x12345678
-load r2 0xabcdef97
-add r3, r1, r2
-check_r3 0xbe02460f
-
-end
diff --git a/tests/lm32/test_addi.S b/tests/lm32/test_addi.S
deleted file mode 100644
index 68e766d..0000000
--- a/tests/lm32/test_addi.S
+++ /dev/null
@@ -1,56 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name ADDI_1
-mvi r1, 0
-addi r3, r1, 0
-check_r3 0
-
-test_name ADDI_2
-mvi r1, 0
-addi r3, r1, 1
-check_r3 1
-
-test_name ADDI_3
-mvi r1, 1
-addi r3, r1, 0
-check_r3 1
-
-test_name ADDI_4
-mvi r1, 1
-addi r3, r1, -1
-check_r3 0
-
-test_name ADDI_5
-mvi r1, -1
-addi r3, r1, 1
-check_r3 0
-
-test_name ADDI_6
-mvi r1, -1
-addi r3, r1, 0
-check_r3 -1
-
-test_name ADDI_7
-mvi r1, 0
-addi r3, r1, -1
-check_r3 -1
-
-test_name ADDI_8
-mvi r3, 4
-addi r3, r3, 4
-check_r3 8
-
-test_name ADDI_9
-mvi r3, 4
-addi r3, r3, -4
-check_r3 0
-
-test_name ADDI_10
-mvi r3, 4
-addi r3, r3, -5
-check_r3 -1
-
-end
-
diff --git a/tests/lm32/test_and.S b/tests/lm32/test_and.S
deleted file mode 100644
index 80962ce..0000000
--- a/tests/lm32/test_and.S
+++ /dev/null
@@ -1,45 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name AND_1
-mvi r1, 0
-mvi r2, 0
-and r3, r1, r2
-check_r3 0
-
-test_name AND_2
-mvi r1, 0
-mvi r2, 1
-and r3, r1, r2
-check_r3 0
-
-test_name AND_3
-mvi r1, 1
-mvi r2, 1
-and r3, r1, r2
-check_r3 1
-
-test_name AND_4
-mvi r3, 7
-and r3, r3, r3
-check_r3 7
-
-test_name AND_5
-mvi r1, 7
-and r3, r1, r1
-check_r3 7
-
-test_name AND_6
-mvi r1, 7
-mvi r3, 0
-and r3, r1, r3
-check_r3 0
-
-test_name AND_7
-load r1 0xaa55aa55
-load r2 0x55aa55aa
-and r3, r1, r2
-check_r3 0
-
-end
diff --git a/tests/lm32/test_andhi.S b/tests/lm32/test_andhi.S
deleted file mode 100644
index 4f73af5..0000000
--- a/tests/lm32/test_andhi.S
+++ /dev/null
@@ -1,35 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name ANDHI_1
-mvi r1, 0
-andhi r3, r1, 0
-check_r3 0
-
-test_name ANDHI_2
-mvi r1, 1
-andhi r3, r1, 1
-check_r3 0
-
-test_name ANDHI_3
-load r1 0x000f0000
-andhi r3, r1, 1
-check_r3 0x00010000
-
-test_name ANDHI_4
-load r1 0xffffffff
-andhi r3, r1, 0xffff
-check_r3 0xffff0000
-
-test_name ANDHI_5
-load r1 0xffffffff
-andhi r3, r1, 0
-check_r3 0
-
-test_name ANDHI_6
-load r3 0x55aaffff
-andhi r3, r3, 0xaaaa
-check_r3 0x00aa0000
-
-end
diff --git a/tests/lm32/test_andi.S b/tests/lm32/test_andi.S
deleted file mode 100644
index da1b0a3..0000000
--- a/tests/lm32/test_andi.S
+++ /dev/null
@@ -1,35 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name ANDI_1
-mvi r1, 0
-andi r3, r1, 0
-check_r3 0
-
-test_name ANDI_2
-mvi r1, 1
-andi r3, r1, 1
-check_r3 1
-
-test_name ANDI_3
-load r1 0x000f0000
-andi r3, r1, 1
-check_r3 0
-
-test_name ANDI_4
-load r1 0xffffffff
-andi r3, r1, 0xffff
-check_r3 0xffff
-
-test_name ANDI_5
-load r1 0xffffffff
-andi r3, r1, 0
-check_r3 0
-
-test_name ANDI_6
-load r3 0xffff55aa
-andi r3, r3, 0xaaaa
-check_r3 0x000000aa
-
-end
diff --git a/tests/lm32/test_b.S b/tests/lm32/test_b.S
deleted file mode 100644
index 98172d8..0000000
--- a/tests/lm32/test_b.S
+++ /dev/null
@@ -1,13 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name B_1
-load r1 jump
-b r1
-tc_fail
-end
-
-jump:
-tc_pass
-end
diff --git a/tests/lm32/test_be.S b/tests/lm32/test_be.S
deleted file mode 100644
index 635caba..0000000
--- a/tests/lm32/test_be.S
+++ /dev/null
@@ -1,48 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name BE_1
-mvi r1, 0
-mvi r2, 0
-be r1, r2, 1f
-tc_fail
-bi 2f
-1:
-tc_pass
-2:
-
-test_name BE_2
-mvi r1, 1
-mvi r2, 0
-be r1, r2, 1f
-tc_pass
-bi 2f
-1:
-tc_fail
-2:
-
-test_name BE_3
-mvi r1, 0
-mvi r2, 1
-be r1, r2, 1f
-tc_pass
-bi 2f
-1:
-tc_fail
-2:
-
-bi 2f
-1:
-tc_pass
-bi 3f
-2:
-test_name BE_4
-mvi r1, 1
-mvi r2, 1
-be r1, r2, 1b
-tc_fail
-3:
-
-end
-
diff --git a/tests/lm32/test_bg.S b/tests/lm32/test_bg.S
deleted file mode 100644
index 81823c2..0000000
--- a/tests/lm32/test_bg.S
+++ /dev/null
@@ -1,78 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name BG_1
-mvi r1, 0
-mvi r2, 0
-bg r1, r2, 1f
-tc_pass
-bi 2f
-1:
-tc_fail
-2:
-
-test_name BG_2
-mvi r1, 1
-mvi r2, 0
-bg r1, r2, 1f
-tc_fail
-bi 2f
-1:
-tc_pass
-2:
-
-test_name BG_3
-mvi r1, 0
-mvi r2, 1
-bg r1, r2, 1f
-tc_pass
-bi 2f
-1:
-tc_fail
-2:
-
-test_name BG_4
-mvi r1, 0
-mvi r2, -1
-bg r1, r2, 1f
-tc_fail
-bi 2f
-1:
-tc_pass
-2:
-
-test_name BG_5
-mvi r1, -1
-mvi r2, 0
-bg r1, r2, 1f
-tc_pass
-bi 2f
-1:
-tc_fail
-2:
-
-test_name BG_6
-mvi r1, -1
-mvi r2, -1
-bg r1, r2, 1f
-tc_pass
-bi 2f
-1:
-tc_fail
-2:
-
-bi 2f
-1:
-tc_pass
-bi 3f
-2:
-test_name BG_7
-mvi r1, 1
-mvi r2, 0
-bg r1, r2, 1b
-tc_fail
-3:
-
-end
-
diff --git a/tests/lm32/test_bge.S b/tests/lm32/test_bge.S
deleted file mode 100644
index 6684d15..0000000
--- a/tests/lm32/test_bge.S
+++ /dev/null
@@ -1,78 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name BGE_1
-mvi r1, 0
-mvi r2, 0
-bge r1, r2, 1f
-tc_fail
-bi 2f
-1:
-tc_pass
-2:
-
-test_name BGE_2
-mvi r1, 1
-mvi r2, 0
-bge r1, r2, 1f
-tc_fail
-bi 2f
-1:
-tc_pass
-2:
-
-test_name BGE_3
-mvi r1, 0
-mvi r2, 1
-bge r1, r2, 1f
-tc_pass
-bi 2f
-1:
-tc_fail
-2:
-
-test_name BGE_4
-mvi r1, 0
-mvi r2, -1
-bge r1, r2, 1f
-tc_fail
-bi 2f
-1:
-tc_pass
-2:
-
-test_name BGE_5
-mvi r1, -1
-mvi r2, 0
-bge r1, r2, 1f
-tc_pass
-bi 2f
-1:
-tc_fail
-2:
-
-test_name BGE_6
-mvi r1, -1
-mvi r2, -1
-bge r1, r2, 1f
-tc_fail
-bi 2f
-1:
-tc_pass
-2:
-
-bi 2f
-1:
-tc_pass
-bi 3f
-2:
-test_name BGE_7
-mvi r1, 1
-mvi r2, 0
-bge r1, r2, 1b
-tc_fail
-3:
-
-end
-
diff --git a/tests/lm32/test_bgeu.S b/tests/lm32/test_bgeu.S
deleted file mode 100644
index be44030..0000000
--- a/tests/lm32/test_bgeu.S
+++ /dev/null
@@ -1,78 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name BGEU_1
-mvi r1, 0
-mvi r2, 0
-bgeu r1, r2, 1f
-tc_fail
-bi 2f
-1:
-tc_pass
-2:
-
-test_name BGEU_2
-mvi r1, 1
-mvi r2, 0
-bgeu r1, r2, 1f
-tc_fail
-bi 2f
-1:
-tc_pass
-2:
-
-test_name BGEU_3
-mvi r1, 0
-mvi r2, 1
-bgeu r1, r2, 1f
-tc_pass
-bi 2f
-1:
-tc_fail
-2:
-
-test_name BGEU_4
-mvi r1, 0
-mvi r2, -1
-bgeu r1, r2, 1f
-tc_pass
-bi 2f
-1:
-tc_fail
-2:
-
-test_name BGEU_5
-mvi r1, -1
-mvi r2, 0
-bgeu r1, r2, 1f
-tc_fail
-bi 2f
-1:
-tc_pass
-2:
-
-test_name BGEU_6
-mvi r1, -1
-mvi r2, -1
-bgeu r1, r2, 1f
-tc_fail
-bi 2f
-1:
-tc_pass
-2:
-
-bi 2f
-1:
-tc_pass
-bi 3f
-2:
-test_name BGEU_7
-mvi r1, 1
-mvi r2, 0
-bgeu r1, r2, 1b
-tc_fail
-3:
-
-end
-
diff --git a/tests/lm32/test_bgu.S b/tests/lm32/test_bgu.S
deleted file mode 100644
index 8cc695b..0000000
--- a/tests/lm32/test_bgu.S
+++ /dev/null
@@ -1,78 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name BGU_1
-mvi r1, 0
-mvi r2, 0
-bgu r1, r2, 1f
-tc_pass
-bi 2f
-1:
-tc_fail
-2:
-
-test_name BGU_2
-mvi r1, 1
-mvi r2, 0
-bgu r1, r2, 1f
-tc_fail
-bi 2f
-1:
-tc_pass
-2:
-
-test_name BGU_3
-mvi r1, 0
-mvi r2, 1
-bgu r1, r2, 1f
-tc_pass
-bi 2f
-1:
-tc_fail
-2:
-
-test_name BGU_4
-mvi r1, 0
-mvi r2, -1
-bgu r1, r2, 1f
-tc_pass
-bi 2f
-1:
-tc_fail
-2:
-
-test_name BGU_5
-mvi r1, -1
-mvi r2, 0
-bgu r1, r2, 1f
-tc_fail
-bi 2f
-1:
-tc_pass
-2:
-
-test_name BGU_6
-mvi r1, -1
-mvi r2, -1
-bgu r1, r2, 1f
-tc_pass
-bi 2f
-1:
-tc_fail
-2:
-
-bi 2f
-1:
-tc_pass
-bi 3f
-2:
-test_name BGU_7
-mvi r1, 1
-mvi r2, 0
-bgu r1, r2, 1b
-tc_fail
-3:
-
-end
-
diff --git a/tests/lm32/test_bi.S b/tests/lm32/test_bi.S
deleted file mode 100644
index a1fbd6f..0000000
--- a/tests/lm32/test_bi.S
+++ /dev/null
@@ -1,23 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name BI_1
-bi jump
-tc_fail
-end
-
-jump_back:
-tc_pass
-end
-
-jump:
-tc_pass
-
-test_name BI_2
-bi jump_back
-tc_fail
-
-end
-
-
diff --git a/tests/lm32/test_bne.S b/tests/lm32/test_bne.S
deleted file mode 100644
index 871a006..0000000
--- a/tests/lm32/test_bne.S
+++ /dev/null
@@ -1,48 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name BNE_1
-mvi r1, 0
-mvi r2, 0
-bne r1, r2, 1f
-tc_pass
-bi 2f
-1:
-tc_fail
-2:
-
-test_name BNE_2
-mvi r1, 1
-mvi r2, 0
-bne r1, r2, 1f
-tc_fail
-bi 2f
-1:
-tc_pass
-2:
-
-test_name BNE_3
-mvi r1, 0
-mvi r2, 1
-bne r1, r2, 1f
-tc_fail
-bi 2f
-1:
-tc_pass
-2:
-
-bi 2f
-1:
-tc_fail
-bi 3f
-2:
-test_name BNE_4
-mvi r1, 1
-mvi r2, 1
-bne r1, r2, 1b
-tc_pass
-3:
-
-end
-
diff --git a/tests/lm32/test_break.S b/tests/lm32/test_break.S
deleted file mode 100644
index 0384fc6..0000000
--- a/tests/lm32/test_break.S
+++ /dev/null
@@ -1,20 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name BREAK_1
-mvi r1, 1
-wcsr IE, r1
-insn:
-break
-check_excp 1
-
-test_name BREAK_2
-mv r3, ba
-check_r3 insn
-
-test_name BREAK_3
-rcsr r3, IE
-check_r3 4
-
-end
diff --git a/tests/lm32/test_bret.S b/tests/lm32/test_bret.S
deleted file mode 100644
index 645210e..0000000
--- a/tests/lm32/test_bret.S
+++ /dev/null
@@ -1,38 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name BRET_1
-mvi r1, 4
-wcsr IE, r1
-load ba mark
-bret
-tc_fail
-bi 1f
-
-mark:
-tc_pass
-
-1:
-test_name BRET_2
-rcsr r3, IE
-check_r3 5
-
-test_name BRET_3
-mvi r1, 0
-wcsr IE, r1
-load ba mark2
-bret
-tc_fail
-bi 1f
-
-mark2:
-tc_pass
-
-1:
-test_name BRET_4
-rcsr r3, IE
-check_r3 0
-
-end
-
diff --git a/tests/lm32/test_call.S b/tests/lm32/test_call.S
deleted file mode 100644
index 1b91a5f..0000000
--- a/tests/lm32/test_call.S
+++ /dev/null
@@ -1,16 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name CALL_1
-load r1 mark
-call r1
-return:
-
-tc_fail
-end
-
-mark:
-mv r3, ra
-check_r3 return
-end
diff --git a/tests/lm32/test_calli.S b/tests/lm32/test_calli.S
deleted file mode 100644
index 1d87ae6..0000000
--- a/tests/lm32/test_calli.S
+++ /dev/null
@@ -1,15 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name CALLI_1
-calli mark
-return:
-
-tc_fail
-end
-
-mark:
-mv r3, ra
-check_r3 return
-end
diff --git a/tests/lm32/test_cmpe.S b/tests/lm32/test_cmpe.S
deleted file mode 100644
index 60a8855..0000000
--- a/tests/lm32/test_cmpe.S
+++ /dev/null
@@ -1,40 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name CMPE_1
-mvi r1, 0
-mvi r2, 0
-cmpe r3, r1, r2
-check_r3 1
-
-test_name CMPE_2
-mvi r1, 0
-mvi r2, 1
-cmpe r3, r1, r2
-check_r3 0
-
-test_name CMPE_3
-mvi r1, 1
-mvi r2, 0
-cmpe r3, r1, r2
-check_r3 0
-
-test_name CMPE_4
-mvi r3, 0
-mvi r2, 1
-cmpe r3, r3, r2
-check_r3 0
-
-test_name CMPE_5
-mvi r3, 0
-mvi r2, 0
-cmpe r3, r3, r2
-check_r3 1
-
-test_name CMPE_6
-mvi r3, 0
-cmpe r3, r3, r3
-check_r3 1
-
-end
diff --git a/tests/lm32/test_cmpei.S b/tests/lm32/test_cmpei.S
deleted file mode 100644
index c3d3566..0000000
--- a/tests/lm32/test_cmpei.S
+++ /dev/null
@@ -1,35 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name CMPEI_1
-mvi r1, 0
-cmpei r3, r1, 0
-check_r3 1
-
-test_name CMPEI_2
-mvi r1, 0
-cmpei r3, r1, 1
-check_r3 0
-
-test_name CMPEI_3
-mvi r1, 1
-cmpei r3, r1, 0
-check_r3 0
-
-test_name CMPEI_4
-load r1 0xffffffff
-cmpei r3, r1, -1
-check_r3 1
-
-test_name CMPEI_5
-mvi r3, 0
-cmpei r3, r3, 0
-check_r3 1
-
-test_name CMPEI_6
-mvi r3, 0
-cmpei r3, r3, 1
-check_r3 0
-
-end
diff --git a/tests/lm32/test_cmpg.S b/tests/lm32/test_cmpg.S
deleted file mode 100644
index 0124078..0000000
--- a/tests/lm32/test_cmpg.S
+++ /dev/null
@@ -1,64 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name CMPG_1
-mvi r1, 0
-mvi r2, 0
-cmpg r3, r1, r2
-check_r3 0
-
-test_name CMPG_2
-mvi r1, 0
-mvi r2, 1
-cmpg r3, r1, r2
-check_r3 0
-
-test_name CMPG_3
-mvi r1, 1
-mvi r2, 0
-cmpg r3, r1, r2
-check_r3 1
-
-test_name CMPG_4
-mvi r1, 1
-mvi r2, 1
-cmpg r3, r1, r2
-check_r3 0
-
-test_name CMPG_5
-mvi r1, 0
-mvi r2, -1
-cmpg r3, r1, r2
-check_r3 1
-
-test_name CMPG_6
-mvi r1, -1
-mvi r2, 0
-cmpg r3, r1, r2
-check_r3 0
-
-test_name CMPG_7
-mvi r1, -1
-mvi r2, -1
-cmpg r3, r1, r2
-check_r3 0
-
-test_name CMPG_8
-mvi r3, 0
-mvi r2, 1
-cmpg r3, r3, r2
-check_r3 0
-
-test_name CMPG_9
-mvi r3, 1
-mvi r2, 0
-cmpg r3, r3, r2
-check_r3 1
-
-test_name CMPG_10
-mvi r3, 0
-cmpg r3, r3, r3
-check_r3 0
-
-end
diff --git a/tests/lm32/test_cmpge.S b/tests/lm32/test_cmpge.S
deleted file mode 100644
index 84620a0..0000000
--- a/tests/lm32/test_cmpge.S
+++ /dev/null
@@ -1,64 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name CMPGE_1
-mvi r1, 0
-mvi r2, 0
-cmpge r3, r1, r2
-check_r3 1
-
-test_name CMPGE_2
-mvi r1, 0
-mvi r2, 1
-cmpge r3, r1, r2
-check_r3 0
-
-test_name CMPGE_3
-mvi r1, 1
-mvi r2, 0
-cmpge r3, r1, r2
-check_r3 1
-
-test_name CMPGE_4
-mvi r1, 1
-mvi r2, 1
-cmpge r3, r1, r2
-check_r3 1
-
-test_name CMPGE_5
-mvi r1, 0
-mvi r2, -1
-cmpge r3, r1, r2
-check_r3 1
-
-test_name CMPGE_6
-mvi r1, -1
-mvi r2, 0
-cmpge r3, r1, r2
-check_r3 0
-
-test_name CMPGE_7
-mvi r1, -1
-mvi r2, -1
-cmpge r3, r1, r2
-check_r3 1
-
-test_name CMPGE_8
-mvi r3, 0
-mvi r2, 1
-cmpge r3, r3, r2
-check_r3 0
-
-test_name CMPGE_9
-mvi r3, 1
-mvi r2, 0
-cmpge r3, r3, r2
-check_r3 1
-
-test_name CMPGE_10
-mvi r3, 0
-cmpge r3, r3, r3
-check_r3 1
-
-end
diff --git a/tests/lm32/test_cmpgei.S b/tests/lm32/test_cmpgei.S
deleted file mode 100644
index 6a8870f..0000000
--- a/tests/lm32/test_cmpgei.S
+++ /dev/null
@@ -1,55 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name CMPGEI_1
-mvi r1, 0
-cmpgei r3, r1, 0
-check_r3 1
-
-test_name CMPGEI_2
-mvi r1, 0
-cmpgei r3, r1, 1
-check_r3 0
-
-test_name CMPGEI_3
-mvi r1, 1
-cmpgei r3, r1, 0
-check_r3 1
-
-test_name CMPGEI_4
-mvi r1, 1
-cmpgei r3, r1, 1
-check_r3 1
-
-test_name CMPGEI_5
-mvi r1, 0
-cmpgei r3, r1, -1
-check_r3 1
-
-test_name CMPGEI_6
-mvi r1, -1
-cmpgei r3, r1, 0
-check_r3 0
-
-test_name CMPGEI_7
-mvi r1, -1
-cmpgei r3, r1, -1
-check_r3 1
-
-test_name CMPGEI_8
-mvi r3, 0
-cmpgei r3, r3, 1
-check_r3 0
-
-test_name CMPGEI_9
-mvi r3, 1
-cmpgei r3, r3, 0
-check_r3 1
-
-test_name CMPGEI_10
-mvi r3, 0
-cmpgei r3, r3, 0
-check_r3 1
-
-end
diff --git a/tests/lm32/test_cmpgeu.S b/tests/lm32/test_cmpgeu.S
deleted file mode 100644
index 2110ccb..0000000
--- a/tests/lm32/test_cmpgeu.S
+++ /dev/null
@@ -1,64 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name CMPGEU_1
-mvi r1, 0
-mvi r2, 0
-cmpgeu r3, r1, r2
-check_r3 1
-
-test_name CMPGEU_2
-mvi r1, 0
-mvi r2, 1
-cmpgeu r3, r1, r2
-check_r3 0
-
-test_name CMPGEU_3
-mvi r1, 1
-mvi r2, 0
-cmpgeu r3, r1, r2
-check_r3 1
-
-test_name CMPGEU_4
-mvi r1, 1
-mvi r2, 1
-cmpgeu r3, r1, r2
-check_r3 1
-
-test_name CMPGEU_5
-mvi r1, 0
-mvi r2, -1
-cmpgeu r3, r1, r2
-check_r3 0
-
-test_name CMPGEU_6
-mvi r1, -1
-mvi r2, 0
-cmpgeu r3, r1, r2
-check_r3 1
-
-test_name CMPGEU_7
-mvi r1, -1
-mvi r2, -1
-cmpgeu r3, r1, r2
-check_r3 1
-
-test_name CMPGEU_8
-mvi r3, 0
-mvi r2, 1
-cmpgeu r3, r3, r2
-check_r3 0
-
-test_name CMPGEU_9
-mvi r3, 1
-mvi r2, 0
-cmpgeu r3, r3, r2
-check_r3 1
-
-test_name CMPGEU_10
-mvi r3, 0
-cmpgeu r3, r3, r3
-check_r3 1
-
-end
diff --git a/tests/lm32/test_cmpgeui.S b/tests/lm32/test_cmpgeui.S
deleted file mode 100644
index b9d1755..0000000
--- a/tests/lm32/test_cmpgeui.S
+++ /dev/null
@@ -1,55 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name CMPGEUI_1
-mvi r1, 0
-cmpgeui r3, r1, 0
-check_r3 1
-
-test_name CMPGEUI_2
-mvi r1, 0
-cmpgeui r3, r1, 1
-check_r3 0
-
-test_name CMPGEUI_3
-mvi r1, 1
-cmpgeui r3, r1, 0
-check_r3 1
-
-test_name CMPGEUI_4
-mvi r1, 1
-cmpgeui r3, r1, 1
-check_r3 1
-
-test_name CMPGEUI_5
-mvi r1, 0
-cmpgeui r3, r1, 0xffff
-check_r3 0
-
-test_name CMPGEUI_6
-mvi r1, -1
-cmpgeui r3, r1, 0
-check_r3 1
-
-test_name CMPGEUI_7
-mvi r1, -1
-cmpgeui r3, r1, 0xffff
-check_r3 1
-
-test_name CMPGEUI_8
-mvi r3, 0
-cmpgeui r3, r3, 1
-check_r3 0
-
-test_name CMPGEUI_9
-mvi r3, 1
-cmpgeui r3, r3, 0
-check_r3 1
-
-test_name CMPGEUI_10
-mvi r3, 0
-cmpgeui r3, r3, 0
-check_r3 1
-
-end
diff --git a/tests/lm32/test_cmpgi.S b/tests/lm32/test_cmpgi.S
deleted file mode 100644
index 1f622d2..0000000
--- a/tests/lm32/test_cmpgi.S
+++ /dev/null
@@ -1,55 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name CMPGI_1
-mvi r1, 0
-cmpgi r3, r1, 0
-check_r3 0
-
-test_name CMPGI_2
-mvi r1, 0
-cmpgi r3, r1, 1
-check_r3 0
-
-test_name CMPGI_3
-mvi r1, 1
-cmpgi r3, r1, 0
-check_r3 1
-
-test_name CMPGI_4
-mvi r1, 1
-cmpgi r3, r1, 1
-check_r3 0
-
-test_name CMPGI_5
-mvi r1, 0
-cmpgi r3, r1, -1
-check_r3 1
-
-test_name CMPGI_6
-mvi r1, -1
-cmpgi r3, r1, 0
-check_r3 0
-
-test_name CMPGI_7
-mvi r1, -1
-cmpgi r3, r1, -1
-check_r3 0
-
-test_name CMPGI_8
-mvi r3, 0
-cmpgi r3, r3, 1
-check_r3 0
-
-test_name CMPGI_9
-mvi r3, 1
-cmpgi r3, r3, 0
-check_r3 1
-
-test_name CMPGI_10
-mvi r3, 0
-cmpgi r3, r3, 0
-check_r3 0
-
-end
diff --git a/tests/lm32/test_cmpgu.S b/tests/lm32/test_cmpgu.S
deleted file mode 100644
index dd46547..0000000
--- a/tests/lm32/test_cmpgu.S
+++ /dev/null
@@ -1,64 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name CMPGU_1
-mvi r1, 0
-mvi r2, 0
-cmpgu r3, r1, r2
-check_r3 0
-
-test_name CMPGU_2
-mvi r1, 0
-mvi r2, 1
-cmpgu r3, r1, r2
-check_r3 0
-
-test_name CMPGU_3
-mvi r1, 1
-mvi r2, 0
-cmpgu r3, r1, r2
-check_r3 1
-
-test_name CMPGU_4
-mvi r1, 1
-mvi r2, 1
-cmpgu r3, r1, r2
-check_r3 0
-
-test_name CMPGU_5
-mvi r1, 0
-mvi r2, -1
-cmpgu r3, r1, r2
-check_r3 0
-
-test_name CMPGU_6
-mvi r1, -1
-mvi r2, 0
-cmpgu r3, r1, r2
-check_r3 1
-
-test_name CMPGU_7
-mvi r1, -1
-mvi r2, -1
-cmpgu r3, r1, r2
-check_r3 0
-
-test_name CMPGU_8
-mvi r3, 0
-mvi r2, 1
-cmpgu r3, r3, r2
-check_r3 0
-
-test_name CMPGU_9
-mvi r3, 1
-mvi r2, 0
-cmpgu r3, r3, r2
-check_r3 1
-
-test_name CMPGU_10
-mvi r3, 0
-cmpgu r3, r3, r3
-check_r3 0
-
-end
diff --git a/tests/lm32/test_cmpgui.S b/tests/lm32/test_cmpgui.S
deleted file mode 100644
index 759bb64..0000000
--- a/tests/lm32/test_cmpgui.S
+++ /dev/null
@@ -1,55 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name CMPGUI_1
-mvi r1, 0
-cmpgui r3, r1, 0
-check_r3 0
-
-test_name CMPGUI_2
-mvi r1, 0
-cmpgui r3, r1, 1
-check_r3 0
-
-test_name CMPGUI_3
-mvi r1, 1
-cmpgui r3, r1, 0
-check_r3 1
-
-test_name CMPGUI_4
-mvi r1, 1
-cmpgui r3, r1, 1
-check_r3 0
-
-test_name CMPGUI_5
-mvi r1, 0
-cmpgui r3, r1, 0xffff
-check_r3 0
-
-test_name CMPGUI_6
-mvi r1, -1
-cmpgui r3, r1, 0
-check_r3 1
-
-test_name CMPGUI_7
-mvi r1, -1
-cmpgui r3, r1, 0xffff
-check_r3 0
-
-test_name CMPGUI_8
-mvi r3, 0
-cmpgui r3, r3, 1
-check_r3 0
-
-test_name CMPGUI_9
-mvi r3, 1
-cmpgui r3, r3, 0
-check_r3 1
-
-test_name CMPGUI_10
-mvi r3, 0
-cmpgui r3, r3, 0
-check_r3 0
-
-end
diff --git a/tests/lm32/test_cmpne.S b/tests/lm32/test_cmpne.S
deleted file mode 100644
index 0f10781..0000000
--- a/tests/lm32/test_cmpne.S
+++ /dev/null
@@ -1,40 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name CMPNE_1
-mvi r1, 0
-mvi r2, 0
-cmpne r3, r1, r2
-check_r3 0
-
-test_name CMPNE_2
-mvi r1, 0
-mvi r2, 1
-cmpne r3, r1, r2
-check_r3 1
-
-test_name CMPNE_3
-mvi r1, 1
-mvi r2, 0
-cmpne r3, r1, r2
-check_r3 1
-
-test_name CMPNE_4
-mvi r3, 0
-mvi r2, 1
-cmpne r3, r3, r2
-check_r3 1
-
-test_name CMPNE_5
-mvi r3, 0
-mvi r2, 0
-cmpne r3, r3, r2
-check_r3 0
-
-test_name CMPNE_6
-mvi r3, 0
-cmpne r3, r3, r3
-check_r3 0
-
-end
diff --git a/tests/lm32/test_cmpnei.S b/tests/lm32/test_cmpnei.S
deleted file mode 100644
index 060dd9d..0000000
--- a/tests/lm32/test_cmpnei.S
+++ /dev/null
@@ -1,35 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name CMPNEI_1
-mvi r1, 0
-cmpnei r3, r1, 0
-check_r3 0
-
-test_name CMPNEI_2
-mvi r1, 0
-cmpnei r3, r1, 1
-check_r3 1
-
-test_name CMPNEI_3
-mvi r1, 1
-cmpnei r3, r1, 0
-check_r3 1
-
-test_name CMPNEI_4
-load r1 0xffffffff
-cmpnei r3, r1, -1
-check_r3 0
-
-test_name CMPNEI_5
-mvi r3, 0
-cmpnei r3, r3, 0
-check_r3 0
-
-test_name CMPNEI_6
-mvi r3, 0
-cmpnei r3, r3, 1
-check_r3 1
-
-end
diff --git a/tests/lm32/test_divu.S b/tests/lm32/test_divu.S
deleted file mode 100644
index f381d09..0000000
--- a/tests/lm32/test_divu.S
+++ /dev/null
@@ -1,29 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name DIVU_1
-mvi r1, 0
-mvi r2, 1
-divu r3, r1, r2
-check_r3 0
-
-test_name DIVU_2
-mvi r1, 1
-mvi r2, 1
-divu r3, r1, r2
-check_r3 1
-
-test_name DIVU_3
-mvi r1, 0
-mvi r2, 0
-divu r3, r1, r2
-check_excp 16
-
-test_name DIVU_4
-load r1 0xabcdef12
-load r2 0x12345
-divu r3, r1, r2
-check_r3 0x9700
-
-end
diff --git a/tests/lm32/test_eret.S b/tests/lm32/test_eret.S
deleted file mode 100644
index 6830bd1..0000000
--- a/tests/lm32/test_eret.S
+++ /dev/null
@@ -1,38 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name ERET_1
-mvi r1, 2
-wcsr IE, r1
-load ea mark
-eret
-tc_fail
-bi 1f
-
-mark:
-tc_pass
-
-1:
-test_name ERET_2
-rcsr r3, IE
-check_r3 3
-
-test_name ERET_3
-mvi r1, 0
-wcsr IE, r1
-load ea mark2
-eret
-tc_fail
-bi 1f
-
-mark2:
-tc_pass
-
-1:
-test_name ERET_4
-rcsr r3, IE
-check_r3 0
-
-end
-
diff --git a/tests/lm32/test_lb.S b/tests/lm32/test_lb.S
deleted file mode 100644
index f84d21e..0000000
--- a/tests/lm32/test_lb.S
+++ /dev/null
@@ -1,45 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name LB_1
-load r1 data
-lb r3, (r1+0)
-check_r3 0x7e
-
-test_name LB_2
-lb r3, (r1+1)
-check_r3 0x7f
-
-test_name LB_3
-lb r3, (r1+-1)
-check_r3 0x7d
-
-test_name LB_4
-load r1 data_msb
-lb r3, (r1+0)
-check_r3 0xfffffffe
-
-test_name LB_5
-lb r3, (r1+1)
-check_r3 0xffffffff
-
-test_name LB_6
-lb r3, (r1+-1)
-check_r3 0xfffffffd
-
-test_name LB_7
-load r3 data
-lb r3, (r3+0)
-check_r3 0x7e
-
-end
-
-.data
-	.align 4
-	.byte 0x7a, 0x7b, 0x7c, 0x7d
-data:
-	.byte 0x7e, 0x7f, 0x70, 0x71
-	.byte 0xfa, 0xfb, 0xfc, 0xfd
-data_msb:
-	.byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/tests/lm32/test_lbu.S b/tests/lm32/test_lbu.S
deleted file mode 100644
index 4c1786a..0000000
--- a/tests/lm32/test_lbu.S
+++ /dev/null
@@ -1,45 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name LBU_1
-load r1 data
-lbu r3, (r1+0)
-check_r3 0x7e
-
-test_name LBU_2
-lbu r3, (r1+1)
-check_r3 0x7f
-
-test_name LBU_3
-lbu r3, (r1+-1)
-check_r3 0x7d
-
-test_name LBU_4
-load r1 data_msb
-lbu r3, (r1+0)
-check_r3 0xfe
-
-test_name LBU_5
-lbu r3, (r1+1)
-check_r3 0xff
-
-test_name LBU_6
-lbu r3, (r1+-1)
-check_r3 0xfd
-
-test_name LBU_7
-load r3 data
-lbu r3, (r3+0)
-check_r3 0x7e
-
-end
-
-.data
-	.align 4
-	.byte 0x7a, 0x7b, 0x7c, 0x7d
-data:
-	.byte 0x7e, 0x7f, 0x70, 0x71
-	.byte 0xfa, 0xfb, 0xfc, 0xfd
-data_msb:
-	.byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/tests/lm32/test_lh.S b/tests/lm32/test_lh.S
deleted file mode 100644
index e57d9e3..0000000
--- a/tests/lm32/test_lh.S
+++ /dev/null
@@ -1,45 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name LH_1
-load r1 data
-lh r3, (r1+0)
-check_r3 0x7e7f
-
-test_name LH_2
-lh r3, (r1+2)
-check_r3 0x7071
-
-test_name LH_3
-lh r3, (r1+-2)
-check_r3 0x7c7d
-
-test_name LH_4
-load r1 data_msb
-lh r3, (r1+0)
-check_r3 0xfffffeff
-
-test_name LH_5
-lh r3, (r1+2)
-check_r3 0xfffff0f1
-
-test_name LH_6
-lh r3, (r1+-2)
-check_r3 0xfffffcfd
-
-test_name LH_7
-load r3 data
-lh r3, (r3+0)
-check_r3 0x7e7f
-
-end
-
-.data
-	.align 4
-	.byte 0x7a, 0x7b, 0x7c, 0x7d
-data:
-	.byte 0x7e, 0x7f, 0x70, 0x71
-	.byte 0xfa, 0xfb, 0xfc, 0xfd
-data_msb:
-	.byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/tests/lm32/test_lhu.S b/tests/lm32/test_lhu.S
deleted file mode 100644
index e648775..0000000
--- a/tests/lm32/test_lhu.S
+++ /dev/null
@@ -1,45 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name LHU_1
-load r1 data
-lhu r3, (r1+0)
-check_r3 0x7e7f
-
-test_name LHU_2
-lhu r3, (r1+2)
-check_r3 0x7071
-
-test_name LHU_3
-lhu r3, (r1+-2)
-check_r3 0x7c7d
-
-test_name LHU_4
-load r1 data_msb
-lhu r3, (r1+0)
-check_r3 0xfeff
-
-test_name LHU_5
-lhu r3, (r1+2)
-check_r3 0xf0f1
-
-test_name LHU_6
-lhu r3, (r1+-2)
-check_r3 0xfcfd
-
-test_name LHU_7
-load r3 data
-lhu r3, (r3+0)
-check_r3 0x7e7f
-
-end
-
-.data
-	.align 4
-	.byte 0x7a, 0x7b, 0x7c, 0x7d
-data:
-	.byte 0x7e, 0x7f, 0x70, 0x71
-	.byte 0xfa, 0xfb, 0xfc, 0xfd
-data_msb:
-	.byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/tests/lm32/test_lw.S b/tests/lm32/test_lw.S
deleted file mode 100644
index f8c919d..0000000
--- a/tests/lm32/test_lw.S
+++ /dev/null
@@ -1,30 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name LW_1
-load r1 data
-lw r3, (r1+0)
-check_r3 0x7e7f7071
-
-test_name LW_2
-lw r3, (r1+4)
-check_r3 0x72737475
-
-test_name LW_3
-lw r3, (r1+-4)
-check_r3 0x7a7b7c7d
-
-test_name LW_4
-load r3 data
-lw r3, (r3+0)
-check_r3 0x7e7f7071
-
-end
-
-.data
-	.align 4
-	.byte 0x7a, 0x7b, 0x7c, 0x7d
-data:
-	.byte 0x7e, 0x7f, 0x70, 0x71
-	.byte 0x72, 0x73, 0x74, 0x75
diff --git a/tests/lm32/test_modu.S b/tests/lm32/test_modu.S
deleted file mode 100644
index 4248690..0000000
--- a/tests/lm32/test_modu.S
+++ /dev/null
@@ -1,35 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name MODU_1
-mvi r1, 0
-mvi r2, 1
-modu r3, r1, r2
-check_r3 0
-
-test_name MODU_2
-mvi r1, 1
-mvi r2, 1
-modu r3, r1, r2
-check_r3 0
-
-test_name MODU_3
-mvi r1, 3
-mvi r2, 2
-modu r3, r1, r2
-check_r3 1
-
-test_name MODU_4
-mvi r1, 0
-mvi r2, 0
-modu r3, r1, r2
-check_excp 16
-
-test_name MODU_5
-load r1 0xabcdef12
-load r2 0x12345
-modu r3, r1, r2
-check_r3 0x3c12
-
-end
diff --git a/tests/lm32/test_mul.S b/tests/lm32/test_mul.S
deleted file mode 100644
index e9b937e..0000000
--- a/tests/lm32/test_mul.S
+++ /dev/null
@@ -1,70 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name MUL_1
-mvi r1, 0
-mvi r2, 0
-mul r3, r1, r2
-check_r3 0
-
-test_name MUL_2
-mvi r1, 1
-mvi r2, 0
-mul r3, r1, r2
-check_r3 0
-
-test_name MUL_3
-mvi r1, 0
-mvi r2, 1
-mul r3, r1, r2
-check_r3 0
-
-test_name MUL_4
-mvi r1, 1
-mvi r2, 1
-mul r3, r1, r2
-check_r3 1
-
-test_name MUL_5
-mvi r1, 2
-mvi r2, -1
-mul r3, r1, r2
-check_r3 -2
-
-test_name MUL_6
-mvi r1, -2
-mvi r2, -1
-mul r3, r1, r2
-check_r3 2
-
-test_name MUL_7
-mvi r1, 0x1234
-mvi r2, 0x789
-mul r3, r1, r2
-check_r3 0x8929d4
-
-test_name MUL_8
-mvi r3, 4
-mul r3, r3, r3
-check_r3 16
-
-test_name MUL_9
-mvi r2, 2
-mvi r3, 4
-mul r3, r3, r2
-check_r3 8
-
-test_name MUL_10
-load r1 0x12345678
-load r2 0x7bcdef12
-mul r3, r1, r2
-check_r3 0xa801c70
-
-test_name MUL_11
-load r1 0x12345678
-load r2 0xabcdef12
-mul r3, r1, r2
-check_r3 0x8a801c70
-
-end
diff --git a/tests/lm32/test_muli.S b/tests/lm32/test_muli.S
deleted file mode 100644
index d6dd4a0..0000000
--- a/tests/lm32/test_muli.S
+++ /dev/null
@@ -1,45 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name MULI_1
-mvi r1, 0
-muli r3, r1, 0
-check_r3 0
-
-test_name MULI_2
-mvi r1, 1
-muli r3, r1, 0
-check_r3 0
-
-test_name MULI_3
-mvi r1, 0
-muli r3, r1, 1
-check_r3 0
-
-test_name MULI_4
-mvi r1, 1
-muli r3, r1, 1
-check_r3 1
-
-test_name MULI_5
-mvi r1, 2
-muli r3, r1, -1
-check_r3 -2
-
-test_name MULI_6
-mvi r1, -2
-muli r3, r1, -1
-check_r3 2
-
-test_name MULI_7
-mvi r1, 0x1234
-muli r3, r1, 0x789
-check_r3 0x8929d4
-
-test_name MULI_8
-mvi r3, 4
-muli r3, r3, 4
-check_r3 16
-
-end
diff --git a/tests/lm32/test_nor.S b/tests/lm32/test_nor.S
deleted file mode 100644
index 74d7592..0000000
--- a/tests/lm32/test_nor.S
+++ /dev/null
@@ -1,51 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name NOR_1
-mvi r1, 0
-mvi r2, 0
-nor r3, r1, r2
-check_r3 0xffffffff
-
-test_name NOR_2
-mvi r1, 0
-mvi r2, 1
-nor r3, r1, r2
-check_r3 0xfffffffe
-
-test_name NOR_3
-mvi r1, 1
-mvi r2, 1
-nor r3, r1, r2
-check_r3 0xfffffffe
-
-test_name NOR_4
-mvi r1, 1
-mvi r2, 0
-nor r3, r1, r2
-check_r3 0xfffffffe
-
-test_name NOR_5
-load r1 0xaa55aa55
-load r2 0x55aa55aa
-nor r3, r1, r2
-check_r3 0
-
-test_name NOR_6
-load r1 0xaa550000
-load r2 0x0000aa55
-nor r3, r1, r2
-check_r3 0x55aa55aa
-
-test_name NOR_7
-load r1 0xaa55aa55
-nor r3, r1, r1
-check_r3 0x55aa55aa
-
-test_name NOR_8
-load r3 0xaa55aa55
-nor r3, r3, r3
-check_r3 0x55aa55aa
-
-end
diff --git a/tests/lm32/test_nori.S b/tests/lm32/test_nori.S
deleted file mode 100644
index d00309c..0000000
--- a/tests/lm32/test_nori.S
+++ /dev/null
@@ -1,35 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name NORI_1
-mvi r1, 0
-nori r3, r1, 0
-check_r3 0xffffffff
-
-test_name NORI_2
-mvi r1, 0
-nori r3, r1, 1
-check_r3 0xfffffffe
-
-test_name NORI_3
-mvi r1, 1
-nori r3, r1, 1
-check_r3 0xfffffffe
-
-test_name NORI_4
-mvi r1, 1
-nori r3, r1, 0
-check_r3 0xfffffffe
-
-test_name NORI_5
-load r1 0xaa55aa55
-nori r3, r1, 0x55aa
-check_r3 0x55aa0000
-
-test_name NORI_6
-load r3 0xaa55aa55
-nori r3, r3, 0x55aa
-check_r3 0x55aa0000
-
-end
diff --git a/tests/lm32/test_or.S b/tests/lm32/test_or.S
deleted file mode 100644
index 4ed2923..0000000
--- a/tests/lm32/test_or.S
+++ /dev/null
@@ -1,51 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name OR_1
-mvi r1, 0
-mvi r2, 0
-or r3, r1, r2
-check_r3 0
-
-test_name OR_2
-mvi r1, 0
-mvi r2, 1
-or r3, r1, r2
-check_r3 1
-
-test_name OR_3
-mvi r1, 1
-mvi r2, 1
-or r3, r1, r2
-check_r3 1
-
-test_name OR_4
-mvi r1, 1
-mvi r2, 0
-or r3, r1, r2
-check_r3 1
-
-test_name OR_5
-load r1 0xaa55aa55
-load r2 0x55aa55aa
-or r3, r1, r2
-check_r3 0xffffffff
-
-test_name OR_6
-load r1 0xaa550000
-load r2 0x0000aa55
-or r3, r1, r2
-check_r3 0xaa55aa55
-
-test_name OR_7
-load r1 0xaa55aa55
-or r3, r1, r1
-check_r3 0xaa55aa55
-
-test_name OR_8
-load r3 0xaa55aa55
-or r3, r3, r3
-check_r3 0xaa55aa55
-
-end
diff --git a/tests/lm32/test_orhi.S b/tests/lm32/test_orhi.S
deleted file mode 100644
index 78b7600..0000000
--- a/tests/lm32/test_orhi.S
+++ /dev/null
@@ -1,35 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name ORHI_1
-mvi r1, 0
-orhi r3, r1, 0
-check_r3 0
-
-test_name ORHI_2
-mvi r1, 0
-orhi r3, r1, 1
-check_r3 0x00010000
-
-test_name ORHI_3
-load r1 0x00010000
-orhi r3, r1, 1
-check_r3 0x00010000
-
-test_name ORHI_4
-mvi r1, 1
-orhi r3, r1, 0
-check_r3 1
-
-test_name ORHI_5
-load r1 0xaa55aa55
-orhi r3, r1, 0x55aa
-check_r3 0xffffaa55
-
-test_name ORHI_6
-load r3 0xaa55aa55
-orhi r3, r3, 0x55aa
-check_r3 0xffffaa55
-
-end
diff --git a/tests/lm32/test_ori.S b/tests/lm32/test_ori.S
deleted file mode 100644
index 3d576cd..0000000
--- a/tests/lm32/test_ori.S
+++ /dev/null
@@ -1,35 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name ORI_1
-mvi r1, 0
-ori r3, r1, 0
-check_r3 0
-
-test_name ORI_2
-mvi r1, 0
-ori r3, r1, 1
-check_r3 1
-
-test_name ORI_3
-mvi r1, 1
-ori r3, r1, 1
-check_r3 1
-
-test_name ORI_4
-mvi r1, 1
-ori r3, r1, 0
-check_r3 1
-
-test_name ORI_5
-load r1 0xaa55aa55
-ori r3, r1, 0x55aa
-check_r3 0xaa55ffff
-
-test_name ORI_6
-load r3 0xaa55aa55
-ori r3, r3, 0x55aa
-check_r3 0xaa55ffff
-
-end
diff --git a/tests/lm32/test_ret.S b/tests/lm32/test_ret.S
deleted file mode 100644
index 320264f..0000000
--- a/tests/lm32/test_ret.S
+++ /dev/null
@@ -1,14 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name RET_1
-load ra mark
-ret
-
-tc_fail
-end
-
-mark:
-tc_pass
-end
diff --git a/tests/lm32/test_sb.S b/tests/lm32/test_sb.S
deleted file mode 100644
index 89e39d6..0000000
--- a/tests/lm32/test_sb.S
+++ /dev/null
@@ -1,30 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name SB_1
-load r1 data
-load r2 0xf0f1f2aa
-sb (r1+0), r2
-check_mem data 0xaa000000
-
-test_name SB_2
-load r2 0xf0f1f2bb
-sb (r1+1), r2
-check_mem data 0xaabb0000
-
-test_name SB_3
-load r2 0xf0f1f2cc
-sb (r1+-1), r2
-check_mem data0 0x000000cc
-
-end
-
-.data
-	.align 4
-data0:
-	.byte 0, 0, 0, 0
-data:
-	.byte 0, 0, 0, 0
-data1:
-	.byte 0, 0, 0, 0
diff --git a/tests/lm32/test_scall.S b/tests/lm32/test_scall.S
deleted file mode 100644
index b442e32..0000000
--- a/tests/lm32/test_scall.S
+++ /dev/null
@@ -1,20 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name SCALL_1
-mvi r1, 1
-wcsr IE, r1
-insn:
-scall
-check_excp 64
-
-test_name SCALL_2
-mv r3, ea
-check_r3 insn
-
-test_name SCALL_3
-rcsr r3, IE
-check_r3 2
-
-end
diff --git a/tests/lm32/test_sextb.S b/tests/lm32/test_sextb.S
deleted file mode 100644
index 58db8ee..0000000
--- a/tests/lm32/test_sextb.S
+++ /dev/null
@@ -1,20 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name SEXTB_1
-mvi r1, 0
-sextb r3, r1
-check_r3 0
-
-test_name SEXTB_2
-mvi r1, 0x7f
-sextb r3, r1
-check_r3 0x0000007f
-
-test_name SEXTB_3
-mvi r1, 0x80
-sextb r3, r1
-check_r3 0xffffff80
-
-end
diff --git a/tests/lm32/test_sexth.S b/tests/lm32/test_sexth.S
deleted file mode 100644
index a059ec3..0000000
--- a/tests/lm32/test_sexth.S
+++ /dev/null
@@ -1,20 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name SEXTH_1
-mvi r1, 0
-sexth r3, r1
-check_r3 0
-
-test_name SEXTH_2
-load r1 0x7fff
-sexth r3, r1
-check_r3 0x00007fff
-
-test_name SEXTH_3
-load r1 0x8000
-sexth r3, r1
-check_r3 0xffff8000
-
-end
diff --git a/tests/lm32/test_sh.S b/tests/lm32/test_sh.S
deleted file mode 100644
index ea8b3f2..0000000
--- a/tests/lm32/test_sh.S
+++ /dev/null
@@ -1,30 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name SH_1
-load r1 data
-load r2 0xf0f1aaaa
-sh (r1+0), r2
-check_mem data 0xaaaa0000
-
-test_name SH_2
-load r2 0xf0f1bbbb
-sh (r1+2), r2
-check_mem data 0xaaaabbbb
-
-test_name SH_3
-load r2 0xf0f1cccc
-sh (r1+-2), r2
-check_mem data0 0x0000cccc
-
-end
-
-.data
-	.align 4
-data0:
-	.byte 0, 0, 0, 0
-data:
-	.byte 0, 0, 0, 0
-data1:
-	.byte 0, 0, 0, 0
diff --git a/tests/lm32/test_sl.S b/tests/lm32/test_sl.S
deleted file mode 100644
index 0aee17f..0000000
--- a/tests/lm32/test_sl.S
+++ /dev/null
@@ -1,45 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name SL_1
-mvi r1, 1
-mvi r2, 0
-sl r3, r1, r2
-check_r3 1
-
-test_name SL_2
-mvi r1, 0
-mvi r2, 1
-sl r3, r1, r2
-check_r3 0
-
-test_name SL_3
-mvi r1, 1
-mvi r2, 31
-sl r3, r1, r2
-check_r3 0x80000000
-
-test_name SL_4
-mvi r1, 16
-mvi r2, 31
-sl r3, r1, r2
-check_r3 0
-
-test_name SL_5
-mvi r1, 1
-mvi r2, 34
-sl r3, r1, r2
-check_r3 4
-
-test_name SL_6
-mvi r1, 2
-sl r3, r1, r1
-check_r3 8
-
-test_name SL_7
-mvi r3, 2
-sl r3, r3, r3
-check_r3 8
-
-end
diff --git a/tests/lm32/test_sli.S b/tests/lm32/test_sli.S
deleted file mode 100644
index a421de9..0000000
--- a/tests/lm32/test_sli.S
+++ /dev/null
@@ -1,30 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name SLI_1
-mvi r1, 1
-sli r3, r1, 0
-check_r3 1
-
-test_name SLI_2
-mvi r1, 0
-sli r3, r1, 1
-check_r3 0
-
-test_name SLI_3
-mvi r1, 1
-sli r3, r1, 31
-check_r3 0x80000000
-
-test_name SLI_4
-mvi r1, 16
-sli r3, r1, 31
-check_r3 0
-
-test_name SLI_7
-mvi r3, 2
-sli r3, r3, 2
-check_r3 8
-
-end
diff --git a/tests/lm32/test_sr.S b/tests/lm32/test_sr.S
deleted file mode 100644
index 62431a9..0000000
--- a/tests/lm32/test_sr.S
+++ /dev/null
@@ -1,57 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name SR_1
-mvi r1, 1
-mvi r2, 0
-sr r3, r1, r2
-check_r3 1
-
-test_name SR_2
-mvi r1, 0
-mvi r2, 1
-sr r3, r1, r2
-check_r3 0
-
-test_name SR_3
-load r1 0x40000000
-mvi r2, 30
-sr r3, r1, r2
-check_r3 1
-
-test_name SR_4
-load r1 0x40000000
-mvi r2, 31
-sr r3, r1, r2
-check_r3 0
-
-test_name SR_5
-mvi r1, 16
-mvi r2, 34
-sr r3, r1, r2
-check_r3 4
-
-test_name SR_6
-mvi r1, 2
-sr r3, r1, r1
-check_r3 0
-
-test_name SR_7
-mvi r3, 2
-sr r3, r3, r3
-check_r3 0
-
-test_name SR_8
-mvi r1, 0xfffffff0
-mvi r2, 2
-sr r3, r1, r2
-check_r3 0xfffffffc
-
-test_name SR_9
-mvi r1, 0xfffffff0
-mvi r2, 4
-sr r3, r1, r2
-check_r3 0xffffffff
-
-end
diff --git a/tests/lm32/test_sri.S b/tests/lm32/test_sri.S
deleted file mode 100644
index c1be907..0000000
--- a/tests/lm32/test_sri.S
+++ /dev/null
@@ -1,40 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name SRI_1
-mvi r1, 1
-sri r3, r1, 0
-check_r3 1
-
-test_name SRI_2
-mvi r1, 0
-sri r3, r1, 1
-check_r3 0
-
-test_name SRI_3
-load r1 0x40000000
-sri r3, r1, 30
-check_r3 1
-
-test_name SRI_4
-load r1 0x40000000
-sri r3, r1, 31
-check_r3 0
-
-test_name SRI_5
-mvi r3, 2
-sri r3, r3, 2
-check_r3 0
-
-test_name SRI_6
-mvi r1, 0xfffffff0
-sri r3, r1, 2
-check_r3 0xfffffffc
-
-test_name SRI_7
-mvi r1, 0xfffffff0
-sri r3, r1, 4
-check_r3 0xffffffff
-
-end
diff --git a/tests/lm32/test_sru.S b/tests/lm32/test_sru.S
deleted file mode 100644
index 2ab0b54..0000000
--- a/tests/lm32/test_sru.S
+++ /dev/null
@@ -1,57 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name SRU_1
-mvi r1, 1
-mvi r2, 0
-sru r3, r1, r2
-check_r3 1
-
-test_name SRU_2
-mvi r1, 0
-mvi r2, 1
-sru r3, r1, r2
-check_r3 0
-
-test_name SRU_3
-load r1 0x40000000
-mvi r2, 30
-sru r3, r1, r2
-check_r3 1
-
-test_name SRU_4
-load r1 0x40000000
-mvi r2, 31
-sru r3, r1, r2
-check_r3 0
-
-test_name SRU_5
-mvi r1, 16
-mvi r2, 34
-sru r3, r1, r2
-check_r3 4
-
-test_name SRU_6
-mvi r1, 2
-sru r3, r1, r1
-check_r3 0
-
-test_name SRU_7
-mvi r3, 2
-sru r3, r3, r3
-check_r3 0
-
-test_name SRU_8
-mvi r1, 0xfffffff0
-mvi r2, 2
-sru r3, r1, r2
-check_r3 0x3ffffffc
-
-test_name SRU_9
-mvi r1, 0xfffffff0
-mvi r2, 4
-sru r3, r1, r2
-check_r3 0x0fffffff
-
-end
diff --git a/tests/lm32/test_srui.S b/tests/lm32/test_srui.S
deleted file mode 100644
index 872c374..0000000
--- a/tests/lm32/test_srui.S
+++ /dev/null
@@ -1,40 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name SRUI_1
-mvi r1, 1
-srui r3, r1, 0
-check_r3 1
-
-test_name SRUI_2
-mvi r1, 0
-srui r3, r1, 1
-check_r3 0
-
-test_name SRUI_3
-load r1 0x40000000
-srui r3, r1, 30
-check_r3 1
-
-test_name SRUI_4
-load r1 0x40000000
-srui r3, r1, 31
-check_r3 0
-
-test_name SRUI_5
-mvi r3, 2
-srui r3, r3, 2
-check_r3 0
-
-test_name SRUI_6
-mvi r1, 0xfffffff0
-srui r3, r1, 2
-check_r3 0x3ffffffc
-
-test_name SRUI_7
-mvi r1, 0xfffffff0
-srui r3, r1, 4
-check_r3 0x0fffffff
-
-end
diff --git a/tests/lm32/test_sub.S b/tests/lm32/test_sub.S
deleted file mode 100644
index 44b74a9..0000000
--- a/tests/lm32/test_sub.S
+++ /dev/null
@@ -1,75 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name SUB_1
-mvi r1, 0
-mvi r2, 0
-sub r3, r1, r2
-check_r3 0
-
-test_name SUB_2
-mvi r1, 0
-mvi r2, 1
-sub r3, r1, r2
-check_r3 -1
-
-test_name SUB_3
-mvi r1, 1
-mvi r2, 0
-sub r3, r1, r2
-check_r3 1
-
-test_name SUB_4
-mvi r1, 1
-mvi r2, -1
-sub r3, r1, r2
-check_r3 2
-
-test_name SUB_5
-mvi r1, -1
-mvi r2, 1
-sub r3, r1, r2
-check_r3 -2
-
-test_name SUB_6
-mvi r1, -1
-mvi r2, 0
-sub r3, r1, r2
-check_r3 -1
-
-test_name SUB_7
-mvi r1, 0
-mvi r2, -1
-sub r3, r1, r2
-check_r3 1
-
-test_name SUB_8
-mvi r3, 2
-sub r3, r3, r3
-check_r3 0
-
-test_name SUB_9
-mvi r1, 4
-mvi r3, 2
-sub r3, r1, r3
-check_r3 2
-
-test_name SUB_10
-mvi r1, 4
-mvi r3, 2
-sub r3, r3, r1
-check_r3 -2
-
-test_name SUB_11
-mvi r1, 4
-sub r3, r1, r1
-check_r3 0
-
-test_name SUB_12
-load r1 0x12345678
-load r2 0xabcdef97
-sub r3, r1, r2
-check_r3 0x666666e1
-
-end
diff --git a/tests/lm32/test_sw.S b/tests/lm32/test_sw.S
deleted file mode 100644
index d1fdadc..0000000
--- a/tests/lm32/test_sw.S
+++ /dev/null
@@ -1,35 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name SW_1
-load r1 data
-load r2 0xaabbccdd
-sw (r1+0), r2
-check_mem data 0xaabbccdd
-
-test_name SW_2
-load r2 0x00112233
-sw (r1+4), r2
-check_mem data1 0x00112233
-
-test_name SW_3
-load r2 0x44556677
-sw (r1+-4), r2
-check_mem data0 0x44556677
-
-test_name SW_4
-sw (r1+0), r1
-lw r3, (r1+0)
-check_r3 data
-
-end
-
-.data
-	.align 4
-data0:
-	.byte 0, 0, 0, 0
-data:
-	.byte 0, 0, 0, 0
-data1:
-	.byte 0, 0, 0, 0
diff --git a/tests/lm32/test_xnor.S b/tests/lm32/test_xnor.S
deleted file mode 100644
index 14a6207..0000000
--- a/tests/lm32/test_xnor.S
+++ /dev/null
@@ -1,51 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name XNOR_1
-mvi r1, 0
-mvi r2, 0
-xnor r3, r1, r2
-check_r3 0xffffffff
-
-test_name XNOR_2
-mvi r1, 0
-mvi r2, 1
-xnor r3, r1, r2
-check_r3 0xfffffffe
-
-test_name XNOR_3
-mvi r1, 1
-mvi r2, 1
-xnor r3, r1, r2
-check_r3 0xffffffff
-
-test_name XNOR_4
-mvi r1, 1
-mvi r2, 0
-xnor r3, r1, r2
-check_r3 0xfffffffe
-
-test_name XNOR_5
-load r1 0xaa55aa55
-load r2 0x55aa55aa
-xnor r3, r1, r2
-check_r3 0
-
-test_name XNOR_6
-load r1 0xaa550000
-load r2 0x0000aa55
-xnor r3, r1, r2
-check_r3 0x55aa55aa
-
-test_name XNOR_7
-load r1 0xaa55aa55
-xnor r3, r1, r1
-check_r3 0xffffffff
-
-test_name XNOR_8
-load r3 0xaa55aa55
-xnor r3, r3, r3
-check_r3 0xffffffff
-
-end
diff --git a/tests/lm32/test_xnori.S b/tests/lm32/test_xnori.S
deleted file mode 100644
index 9d9c3c6..0000000
--- a/tests/lm32/test_xnori.S
+++ /dev/null
@@ -1,35 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name XNORI_1
-mvi r1, 0
-xnori r3, r1, 0
-check_r3 0xffffffff
-
-test_name XNORI_2
-mvi r1, 0
-xnori r3, r1, 1
-check_r3 0xfffffffe
-
-test_name XNORI_3
-mvi r1, 1
-xnori r3, r1, 1
-check_r3 0xffffffff
-
-test_name XNORI_4
-mvi r1, 1
-xnori r3, r1, 0
-check_r3 0xfffffffe
-
-test_name XNORI_5
-load r1 0xaa55aa55
-xnori r3, r1, 0x5555
-check_r3 0x55aa00ff
-
-test_name XNORI_6
-load r3 0xaa55aa55
-xnori r3, r3, 0x5555
-check_r3 0x55aa00ff
-
-end
diff --git a/tests/lm32/test_xor.S b/tests/lm32/test_xor.S
deleted file mode 100644
index 6c6e712..0000000
--- a/tests/lm32/test_xor.S
+++ /dev/null
@@ -1,51 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name XOR_1
-mvi r1, 0
-mvi r2, 0
-xor r3, r1, r2
-check_r3 0
-
-test_name XOR_2
-mvi r1, 0
-mvi r2, 1
-xor r3, r1, r2
-check_r3 1
-
-test_name XOR_3
-mvi r1, 1
-mvi r2, 1
-xor r3, r1, r2
-check_r3 0
-
-test_name XOR_4
-mvi r1, 1
-mvi r2, 0
-xor r3, r1, r2
-check_r3 1
-
-test_name XOR_5
-load r1 0xaa55aa55
-load r2 0x55aa55aa
-xor r3, r1, r2
-check_r3 0xffffffff
-
-test_name XOR_6
-load r1 0xaa550000
-load r2 0x0000aa55
-xor r3, r1, r2
-check_r3 0xaa55aa55
-
-test_name XOR_7
-load r1 0xaa55aa55
-xor r3, r1, r1
-check_r3 0
-
-test_name XOR_8
-load r3 0xaa55aa55
-xor r3, r3, r3
-check_r3 0
-
-end
diff --git a/tests/lm32/test_xori.S b/tests/lm32/test_xori.S
deleted file mode 100644
index 2051699..0000000
--- a/tests/lm32/test_xori.S
+++ /dev/null
@@ -1,35 +0,0 @@
-.include "macros.inc"
-
-start
-
-test_name XORI_1
-mvi r1, 0
-xori r3, r1, 0
-check_r3 0
-
-test_name XORI_2
-mvi r1, 0
-xori r3, r1, 1
-check_r3 1
-
-test_name XORI_3
-mvi r1, 1
-xori r3, r1, 1
-check_r3 0
-
-test_name XORI_4
-mvi r1, 1
-xori r3, r1, 0
-check_r3 1
-
-test_name XORI_5
-load r1 0xaa55aa55
-xori r3, r1, 0x5555
-check_r3 0xaa55ff00
-
-test_name XORI_6
-load r3 0xaa55aa55
-xori r3, r3, 0x5555
-check_r3 0xaa55ff00
-
-end
diff --git a/tests/pi_10.com b/tests/pi_10.com
deleted file mode 100644
index 8993ba1..0000000
Binary files a/tests/pi_10.com and /dev/null differ
diff --git a/tests/runcom.c b/tests/runcom.c
deleted file mode 100644
index d60342b..0000000
--- a/tests/runcom.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Simple example of use of vm86: launch a basic .com DOS executable
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <signal.h>
-
-#include <linux/unistd.h>
-#include <asm/vm86.h>
-
-extern int vm86 (unsigned long int subfunction,
-		 struct vm86plus_struct *info);
-
-#define VIF_MASK                0x00080000
-
-//#define SIGTEST
-
-#define COM_BASE_ADDR    0x10100
-
-static void usage(void)
-{
-    printf("runcom version 0.1 (c) 2003 Fabrice Bellard\n"
-           "usage: runcom file.com\n"
-           "VM86 Run simple .com DOS executables (linux vm86 test mode)\n");
-    exit(1);
-}
-
-static inline void set_bit(uint8_t *a, unsigned int bit)
-{
-    a[bit / 8] |= (1 << (bit % 8));
-}
-
-static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
-{
-    return (uint8_t *)((seg << 4) + (reg & 0xffff));
-}
-
-static inline void pushw(struct vm86_regs *r, int val)
-{
-    r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
-    *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
-}
-
-void dump_regs(struct vm86_regs *r)
-{
-    fprintf(stderr,
-            "EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n"
-            "ESI=%08lx EDI=%08lx EBP=%08lx ESP=%08lx\n"
-            "EIP=%08lx EFL=%08lx\n"
-            "CS=%04x DS=%04x ES=%04x SS=%04x FS=%04x GS=%04x\n",
-            r->eax, r->ebx, r->ecx, r->edx, r->esi, r->edi, r->ebp, r->esp,
-            r->eip, r->eflags,
-            r->cs, r->ds, r->es, r->ss, r->fs, r->gs);
-}
-
-#ifdef SIGTEST
-void alarm_handler(int sig)
-{
-    fprintf(stderr, "alarm signal=%d\n", sig);
-    alarm(1);
-}
-#endif
-
-int main(int argc, char **argv)
-{
-    uint8_t *vm86_mem;
-    const char *filename;
-    int fd, ret, seg;
-    struct vm86plus_struct ctx;
-    struct vm86_regs *r;
-
-    if (argc != 2)
-        usage();
-    filename = argv[1];
-
-    vm86_mem = mmap((void *)0x00000000, 0x110000,
-                    PROT_WRITE | PROT_READ | PROT_EXEC,
-                    MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
-    if (vm86_mem == MAP_FAILED) {
-        perror("mmap");
-        exit(1);
-    }
-#ifdef SIGTEST
-    {
-        struct sigaction act;
-
-        act.sa_handler = alarm_handler;
-        sigemptyset(&act.sa_mask);
-        act.sa_flags = 0;
-        sigaction(SIGALRM, &act, NULL);
-        alarm(1);
-    }
-#endif
-
-    /* load the MSDOS .com executable */
-    fd = open(filename, O_RDONLY);
-    if (fd < 0) {
-        perror(filename);
-        exit(1);
-    }
-    ret = read(fd, vm86_mem + COM_BASE_ADDR, 65536 - 256);
-    if (ret < 0) {
-        perror("read");
-        exit(1);
-    }
-    close(fd);
-
-    memset(&ctx, 0, sizeof(ctx));
-    /* init basic registers */
-    r = &ctx.regs;
-    r->eip = 0x100;
-    r->esp = 0xfffe;
-    seg = (COM_BASE_ADDR - 0x100) >> 4;
-    r->cs = seg;
-    r->ss = seg;
-    r->ds = seg;
-    r->es = seg;
-    r->fs = seg;
-    r->gs = seg;
-    r->eflags = VIF_MASK;
-
-    /* put return code */
-    set_bit((uint8_t *)&ctx.int_revectored, 0x21);
-    *seg_to_linear(r->cs, 0) = 0xb4; /* mov ah, $0 */
-    *seg_to_linear(r->cs, 1) = 0x00;
-    *seg_to_linear(r->cs, 2) = 0xcd; /* int $0x21 */
-    *seg_to_linear(r->cs, 3) = 0x21;
-    pushw(&ctx.regs, 0x0000);
-
-    /* the value of these registers seem to be assumed by pi_10.com */
-    r->esi = 0x100;
-    r->ecx = 0xff;
-    r->ebp = 0x0900;
-    r->edi = 0xfffe;
-
-    for(;;) {
-        ret = vm86(VM86_ENTER, &ctx);
-        switch(VM86_TYPE(ret)) {
-        case VM86_INTx:
-            {
-                int int_num, ah;
-
-                int_num = VM86_ARG(ret);
-                if (int_num != 0x21)
-                    goto unknown_int;
-                ah = (r->eax >> 8) & 0xff;
-                switch(ah) {
-                case 0x00: /* exit */
-                    exit(0);
-                case 0x02: /* write char */
-                    {
-                        uint8_t c = r->edx;
-                        write(1, &c, 1);
-                    }
-                    break;
-                case 0x09: /* write string */
-                    {
-                        uint8_t c;
-                        for(;;) {
-                            c = *seg_to_linear(r->ds, r->edx);
-                            if (c == '$')
-                                break;
-                            write(1, &c, 1);
-                        }
-                        r->eax = (r->eax & ~0xff) | '$';
-                    }
-                    break;
-                default:
-                unknown_int:
-                    fprintf(stderr, "unsupported int 0x%02x\n", int_num);
-                    dump_regs(&ctx.regs);
-                    //                    exit(1);
-                }
-            }
-            break;
-        case VM86_SIGNAL:
-            /* a signal came, we just ignore that */
-            break;
-        case VM86_STI:
-            break;
-        default:
-            fprintf(stderr, "unhandled vm86 return code (0x%x)\n", ret);
-            dump_regs(&ctx.regs);
-            exit(1);
-        }
-    }
-}
diff --git a/tests/sha1.c b/tests/sha1.c
deleted file mode 100644
index 93b7c8e..0000000
--- a/tests/sha1.c
+++ /dev/null
@@ -1,240 +0,0 @@
-
-/* from valgrind tests */
-
-/* ================ sha1.c ================ */
-/*
-SHA-1 in C
-By Steve Reid <steve at edmweb.com>
-100% Public Domain
-
-Test Vectors (from FIPS PUB 180-1)
-"abc"
-  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
-"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
-A million repetitions of "a"
-  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
-*/
-
-/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
-/* #define SHA1HANDSOFF * Copies data before messing with it. */
-
-#define SHA1HANDSOFF
-
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-
-/* ================ sha1.h ================ */
-/*
-SHA-1 in C
-By Steve Reid <steve at edmweb.com>
-100% Public Domain
-*/
-
-typedef struct {
-    uint32_t state[5];
-    uint32_t count[2];
-    unsigned char buffer[64];
-} SHA1_CTX;
-
-void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]);
-void SHA1Init(SHA1_CTX* context);
-void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len);
-void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
-/* ================ end of sha1.h ================ */
-#include <endian.h>
-
-#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-
-/* blk0() and blk() perform the initial expand. */
-/* I got the idea of expanding during the round function from SSLeay */
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
-    |(rol(block->l[i],8)&0x00FF00FF))
-#elif BYTE_ORDER == BIG_ENDIAN
-#define blk0(i) block->l[i]
-#else
-#error "Endianness not defined!"
-#endif
-#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
-    ^block->l[(i+2)&15]^block->l[i&15],1))
-
-/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
-
-
-/* Hash a single 512-bit block. This is the core of the algorithm. */
-
-void SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
-{
-uint32_t a, b, c, d, e;
-typedef union {
-    unsigned char c[64];
-    uint32_t l[16];
-} CHAR64LONG16;
-#ifdef SHA1HANDSOFF
-CHAR64LONG16 block[1];  /* use array to appear as a pointer */
-    memcpy(block, buffer, 64);
-#else
-    /* The following had better never be used because it causes the
-     * pointer-to-const buffer to be cast into a pointer to non-const.
-     * And the result is written through.  I threw a "const" in, hoping
-     * this will cause a diagnostic.
-     */
-CHAR64LONG16* block = (const CHAR64LONG16*)buffer;
-#endif
-    /* Copy context->state[] to working vars */
-    a = state[0];
-    b = state[1];
-    c = state[2];
-    d = state[3];
-    e = state[4];
-    /* 4 rounds of 20 operations each. Loop unrolled. */
-    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
-    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
-    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
-    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
-    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
-    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
-    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
-    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
-    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
-    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
-    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
-    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
-    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
-    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
-    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
-    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
-    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
-    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
-    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
-    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-    /* Add the working vars back into context.state[] */
-    state[0] += a;
-    state[1] += b;
-    state[2] += c;
-    state[3] += d;
-    state[4] += e;
-    /* Wipe variables */
-    a = b = c = d = e = 0;
-#ifdef SHA1HANDSOFF
-    memset(block, '\0', sizeof(block));
-#endif
-}
-
-
-/* SHA1Init - Initialize new context */
-
-void SHA1Init(SHA1_CTX* context)
-{
-    /* SHA1 initialization constants */
-    context->state[0] = 0x67452301;
-    context->state[1] = 0xEFCDAB89;
-    context->state[2] = 0x98BADCFE;
-    context->state[3] = 0x10325476;
-    context->state[4] = 0xC3D2E1F0;
-    context->count[0] = context->count[1] = 0;
-}
-
-
-/* Run your data through this. */
-
-void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len)
-{
-uint32_t i;
-uint32_t j;
-
-    j = context->count[0];
-    if ((context->count[0] += len << 3) < j)
-	context->count[1]++;
-    context->count[1] += (len>>29);
-    j = (j >> 3) & 63;
-    if ((j + len) > 63) {
-        memcpy(&context->buffer[j], data, (i = 64-j));
-        SHA1Transform(context->state, context->buffer);
-        for ( ; i + 63 < len; i += 64) {
-            SHA1Transform(context->state, &data[i]);
-        }
-        j = 0;
-    }
-    else i = 0;
-    memcpy(&context->buffer[j], &data[i], len - i);
-}
-
-
-/* Add padding and return the message digest. */
-
-void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
-{
-unsigned i;
-unsigned char finalcount[8];
-unsigned char c;
-
-#if 0	/* untested "improvement" by DHR */
-    /* Convert context->count to a sequence of bytes
-     * in finalcount.  Second element first, but
-     * big-endian order within element.
-     * But we do it all backwards.
-     */
-    unsigned char *fcp = &finalcount[8];
-
-    for (i = 0; i < 2; i++)
-    {
-	uint32_t t = context->count[i];
-	int j;
-
-	for (j = 0; j < 4; t >>= 8, j++)
-	    *--fcp = (unsigned char) t;
-    }
-#else
-    for (i = 0; i < 8; i++) {
-        finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
-         >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
-    }
-#endif
-    c = 0200;
-    SHA1Update(context, &c, 1);
-    while ((context->count[0] & 504) != 448) {
-	c = 0000;
-        SHA1Update(context, &c, 1);
-    }
-    SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
-    for (i = 0; i < 20; i++) {
-        digest[i] = (unsigned char)
-         ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
-    }
-    /* Wipe variables */
-    memset(context, '\0', sizeof(*context));
-    memset(&finalcount, '\0', sizeof(finalcount));
-}
-/* ================ end of sha1.c ================ */
-
-#define BUFSIZE 4096
-
-int
-main(int argc, char **argv)
-{
-    SHA1_CTX ctx;
-    unsigned char hash[20], buf[BUFSIZE];
-    int i;
-
-    for(i=0;i<BUFSIZE;i++)
-        buf[i] = i;
-
-    SHA1Init(&ctx);
-    for(i=0;i<1000;i++)
-        SHA1Update(&ctx, buf, BUFSIZE);
-    SHA1Final(hash, &ctx);
-
-    printf("SHA1=");
-    for(i=0;i<20;i++)
-        printf("%02x", hash[i]);
-    printf("\n");
-    return 0;
-}
diff --git a/tests/tcg/Makefile b/tests/tcg/Makefile
new file mode 100644
index 0000000..15e36a2
--- /dev/null
+++ b/tests/tcg/Makefile
@@ -0,0 +1,145 @@
+-include ../config-host.mak
+-include $(SRC_PATH)/rules.mak
+
+$(call set-vpath, $(SRC_PATH)/tests)
+
+QEMU=../i386-linux-user/qemu-i386
+QEMU_X86_64=../x86_64-linux-user/qemu-x86_64
+CC_X86_64=$(CC_I386) -m64
+
+QEMU_INCLUDES += -I..
+CFLAGS=-Wall -O2 -g -fno-strict-aliasing
+#CFLAGS+=-msse2
+LDFLAGS=
+
+# TODO: automatically detect ARM and MIPS compilers, and run those too
+
+# runcom maps page 0, so it requires root privileges
+# also, pi_10.com runs indefinitely
+
+I386_TESTS=hello-i386 \
+	   linux-test \
+	   testthread \
+	   sha1-i386 \
+	   test-i386 \
+	   test-mmap \
+	   # runcom
+
+# native i386 compilers sometimes are not biarch.  assume cross-compilers are
+ifneq ($(ARCH),i386)
+I386_TESTS+=run-test-x86_64
+endif
+
+TESTS = test_path
+ifneq ($(call find-in-path, $(CC_I386)),)
+TESTS += $(I386_TESTS)
+endif
+
+all: $(patsubst %,run-%,$(TESTS))
+
+# rules to run tests
+
+.PHONY: $(patsubst %,run-%,$(TESTS))
+
+run-%: %
+	-$(QEMU) ./$*
+
+run-hello-i386: hello-i386
+run-linux-test: linux-test
+run-testthread: testthread
+run-sha1-i386: sha1-i386
+
+run-test-i386: test-i386
+	./test-i386 > test-i386.ref
+	-$(QEMU) test-i386 > test-i386.out
+	@if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK"; fi
+
+run-test-x86_64: test-x86_64
+	./test-x86_64 > test-x86_64.ref
+	-$(QEMU_X86_64) test-x86_64 > test-x86_64.out
+	@if diff -u test-x86_64.ref test-x86_64.out ; then echo "Auto Test OK"; fi
+
+run-test-mmap: test-mmap
+	-$(QEMU) ./test-mmap
+	-$(QEMU) -p 8192 ./test-mmap 8192
+	-$(QEMU) -p 16384 ./test-mmap 16384
+	-$(QEMU) -p 32768 ./test-mmap 32768
+
+run-runcom: runcom
+	-$(QEMU) ./runcom $(SRC_PATH)/tests/pi_10.com
+
+run-test_path: test_path
+	./test_path
+
+# rules to compile tests
+
+test_path: test_path.o
+test_path.o: test_path.c
+
+hello-i386: hello-i386.c
+	$(CC_I386) -nostdlib $(CFLAGS) -static $(LDFLAGS) -o $@ $<
+	strip $@
+
+testthread: testthread.c
+	$(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $< -lpthread
+
+# i386/x86_64 emulation test (test various opcodes) */
+test-i386: test-i386.c test-i386-code16.S test-i386-vm86.S \
+           test-i386.h test-i386-shift.h test-i386-muldiv.h
+	$(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ \
+              $(<D)/test-i386.c $(<D)/test-i386-code16.S $(<D)/test-i386-vm86.S -lm
+
+test-x86_64: test-i386.c \
+           test-i386.h test-i386-shift.h test-i386-muldiv.h
+	$(CC_X86_64) $(CFLAGS) $(LDFLAGS) -o $@ $(<D)/test-i386.c -lm
+
+# generic Linux and CPU test
+linux-test: linux-test.c
+	$(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $< -lm
+
+# vm86 test
+runcom: runcom.c
+	$(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+test-mmap: test-mmap.c
+	$(CC_I386) -m32 $(CFLAGS) -Wall -O2 $(LDFLAGS) -o $@ $<
+
+# speed test
+sha1-i386: sha1.c
+	$(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+sha1: sha1.c
+	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+speed: sha1 sha1-i386
+	time ./sha1
+	time $(QEMU) ./sha1-i386
+
+# arm test
+hello-arm: hello-arm.o
+	arm-linux-ld -o $@ $<
+
+hello-arm.o: hello-arm.c
+	arm-linux-gcc -Wall -g -O2 -c -o $@ $<
+
+test-arm-iwmmxt: test-arm-iwmmxt.s
+	cpp < $< | arm-linux-gnu-gcc -Wall -static -march=iwmmxt -mabi=aapcs -x assembler - -o $@
+
+# MIPS test
+hello-mips: hello-mips.c
+	mips-linux-gnu-gcc -nostdlib -static -mno-abicalls -fno-PIC -mabi=32 -Wall -Wextra -g -O2 -o $@ $<
+
+hello-mipsel: hello-mips.c
+	mipsel-linux-gnu-gcc -nostdlib -static -mno-abicalls -fno-PIC -mabi=32 -Wall -Wextra -g -O2 -o $@ $<
+
+# testsuite for the CRIS port.
+test-cris:
+	$(MAKE) -C cris check
+
+# testsuite for the LM32 port.
+test-lm32:
+	$(MAKE) -C lm32 check
+
+clean:
+	rm -f *~ *.o test-i386.out test-i386.ref \
+           test-x86_64.log test-x86_64.ref qruncom $(TESTS)
diff --git a/tests/tcg/alpha/Makefile b/tests/tcg/alpha/Makefile
new file mode 100644
index 0000000..2b1f03d
--- /dev/null
+++ b/tests/tcg/alpha/Makefile
@@ -0,0 +1,35 @@
+CROSS=alpha-linux-gnu-
+CC=$(CROSS)gcc
+AS=$(CROSS)as
+
+SIM=../../alpha-linux-user/qemu-alpha
+
+CFLAGS=-O
+LINK=$(CC) -o $@ crt.o $< -nostdlib
+
+TESTS=test-cond test-cmov
+
+all: hello-alpha $(TESTS)
+
+hello-alpha: hello-alpha.o crt.o
+	$(LINK)
+
+test-cond: test-cond.o crt.o
+	$(LINK)
+
+test-cmov.o: test-cond.c
+	$(CC) -c $(CFLAGS) -DTEST_CMOV -o $@ $<
+
+test-cmov: test-cmov.o crt.o
+	$(LINK)
+
+test-ovf: test-ovf.o crt.o
+	$(LINK)
+
+check: $(TESTS)
+	for f in $(TESTS); do $(SIM) $$f || exit 1; done
+
+clean:
+	$(RM) *.o *~ hello-alpha $(TESTS)
+
+.PHONY: clean all check
diff --git a/tests/tcg/alpha/crt.s b/tests/tcg/alpha/crt.s
new file mode 100644
index 0000000..31af882
--- /dev/null
+++ b/tests/tcg/alpha/crt.s
@@ -0,0 +1,26 @@
+	.text
+
+	.globl _start
+	.ent _start,0
+_start:
+	.frame $15,0,$15
+	br $29,1f
+1:	ldgp $29, 0($29)
+	.prologue 0
+	ldq $27,main($29) !literal!1
+	jsr $26,($27)
+	or $0,$0,$16
+	.end _start
+
+	.globl _exit
+_exit:
+	lda $0,1
+	callsys
+
+	call_pal 0
+
+	.globl write
+write:
+	lda $0,4
+	callsys
+	ret
diff --git a/tests/tcg/alpha/hello-alpha.c b/tests/tcg/alpha/hello-alpha.c
new file mode 100644
index 0000000..79892e6
--- /dev/null
+++ b/tests/tcg/alpha/hello-alpha.c
@@ -0,0 +1,5 @@
+int main (void)
+{
+  write (1, "hello\n", 6);
+  return 0;
+}
diff --git a/tests/tcg/alpha/test-cond.c b/tests/tcg/alpha/test-cond.c
new file mode 100644
index 0000000..74adffa
--- /dev/null
+++ b/tests/tcg/alpha/test-cond.c
@@ -0,0 +1,87 @@
+
+#ifdef TEST_CMOV
+
+#define TEST_COND(N) 				\
+int test_##N (long a)				\
+{						\
+  int res = 1;					\
+						\
+  asm ("cmov"#N" %1,$31,%0"			\
+       : "+r" (res) : "r" (a));			\
+  return !res;					\
+}
+
+#else
+
+#define TEST_COND(N) 				\
+int test_##N (long a)				\
+{						\
+  int res = 1;					\
+						\
+  asm ("b"#N" %1,1f\n\t"			\
+       "addq $31,$31,%0\n\t"			\
+       "1: unop\n"				\
+       : "+r" (res) : "r" (a));			\
+  return res;					\
+}
+
+#endif
+
+TEST_COND(eq)
+TEST_COND(ne)
+TEST_COND(ge)
+TEST_COND(gt)
+TEST_COND(lbc)
+TEST_COND(lbs)
+TEST_COND(le)
+TEST_COND(lt)
+
+static struct {
+  int (*func)(long);
+  long v;
+  int r;
+} vectors[] =
+  {
+    {test_eq, 0, 1},
+    {test_eq, 1, 0},
+
+    {test_ne, 0, 0},
+    {test_ne, 1, 1},
+
+    {test_ge, 0, 1},
+    {test_ge, 1, 1},
+    {test_ge, -1, 0},
+
+    {test_gt, 0, 0},
+    {test_gt, 1, 1},
+    {test_gt, -1, 0},
+
+    {test_lbc, 0, 1},
+    {test_lbc, 1, 0},
+    {test_lbc, -1, 0},
+
+    {test_lbs, 0, 0},
+    {test_lbs, 1, 1},
+    {test_lbs, -1, 1},
+
+    {test_le, 0, 1},
+    {test_le, 1, 0},
+    {test_le, -1, 1},
+
+    {test_lt, 0, 0},
+    {test_lt, 1, 0},
+    {test_lt, -1, 1},
+  };
+
+int main (void)
+{
+  int i;
+
+  for (i = 0; i < sizeof (vectors)/sizeof(vectors[0]); i++)
+    if ((*vectors[i].func)(vectors[i].v) != vectors[i].r) {
+      write(1, "Failed\n", 7);
+      return 1;
+    }
+  write(1, "OK\n", 3);
+  return 0;
+}
diff --git a/tests/tcg/alpha/test-ovf.c b/tests/tcg/alpha/test-ovf.c
new file mode 100644
index 0000000..01c80e7
--- /dev/null
+++ b/tests/tcg/alpha/test-ovf.c
@@ -0,0 +1,29 @@
+static long test_subqv (long a, long b)
+{
+  long res;
+
+  asm ("subq/v %1,%2,%0"
+       : "=r" (res) : "r" (a), "r" (b));
+  return res;
+}
+static struct {
+  long (*func)(long, long);
+  long a;
+  long b;
+  long r;
+} vectors[] =
+  {
+    {test_subqv, 0, 0x7d54000, 0xfffffffff82ac000L}
+  };
+
+int main (void)
+{
+  int i;
+
+  for (i = 0; i < sizeof (vectors)/sizeof(vectors[0]); i++)
+    if ((*vectors[i].func)(vectors[i].a, vectors[i].b) != vectors[i].r) {
+      write(1, "Failed\n", 7);
+    }
+  write(1, "OK\n", 3);
+  return 0;
+}
diff --git a/tests/tcg/cris/.gdbinit b/tests/tcg/cris/.gdbinit
new file mode 100644
index 0000000..5e8c1d3
--- /dev/null
+++ b/tests/tcg/cris/.gdbinit
@@ -0,0 +1,11 @@
+b main
+b _fail
+b exit
+display /i $pc
+display /x $srp
+display /x $r0
+display /x $r1
+display /x $r2
+display /x $r3
+display /x $r4
+display /t $ccs
diff --git a/tests/tcg/cris/Makefile b/tests/tcg/cris/Makefile
new file mode 100644
index 0000000..b86bcad
--- /dev/null
+++ b/tests/tcg/cris/Makefile
@@ -0,0 +1,155 @@
+-include ../../config-host.mak
+
+CROSS=crisv32-axis-linux-gnu-
+SIM=../../cris-linux-user/qemu-cris -L ./
+SIMG=cris-axis-linux-gnu-run --sysroot=./
+
+CC      = $(CROSS)gcc
+#AS      = $(CROSS)as
+AS	= $(CC) -x assembler-with-cpp
+SIZE    = $(CROSS)size
+LD      = $(CC)
+OBJCOPY = $(CROSS)objcopy
+
+# we rely on GCC inline:ing the stuff we tell it to in many places here.
+CFLAGS  = -Winline -Wall -g -O2 -static
+NOSTDFLAGS = -nostartfiles -nostdlib
+ASFLAGS += -g -Wa,-I,$(SRC_PATH)/tests/cris/
+LDLIBS  =
+NOSTDLIBS = -lgcc
+
+CRT        = crt.o
+SYS        = sys.o
+TESTCASES += check_abs.tst
+TESTCASES += check_addc.tst
+TESTCASES += check_addcm.tst
+TESTCASES += check_addo.tst
+TESTCASES += check_addoq.tst
+TESTCASES += check_addi.tst
+TESTCASES += check_addiv32.tst
+TESTCASES += check_addm.tst
+TESTCASES += check_addr.tst
+TESTCASES += check_addq.tst
+TESTCASES += check_addxc.tst
+TESTCASES += check_addxm.tst
+TESTCASES += check_addxr.tst
+TESTCASES += check_andc.tst
+TESTCASES += check_andm.tst
+TESTCASES += check_andr.tst
+TESTCASES += check_andq.tst
+TESTCASES += check_asr.tst
+TESTCASES += check_ba.tst
+TESTCASES += check_bas.tst
+TESTCASES += check_bcc.tst
+TESTCASES += check_bound.tst
+TESTCASES += check_boundc.tst
+TESTCASES += check_boundr.tst
+TESTCASES += check_btst.tst
+TESTCASES += check_clearfv32.tst
+TESTCASES += check_cmpc.tst
+TESTCASES += check_cmpr.tst
+TESTCASES += check_cmpq.tst
+TESTCASES += check_cmpm.tst
+TESTCASES += check_cmpxc.tst
+TESTCASES += check_cmpxm.tst
+TESTCASES += check_cmp-2.tst
+TESTCASES += check_clrjmp1.tst
+TESTCASES += check_dstep.tst
+TESTCASES += check_ftag.tst
+TESTCASES += check_int64.tst
+# check_jsr is broken.
+#TESTCASES += check_jsr.tst
+TESTCASES += check_mcp.tst
+TESTCASES += check_movei.tst
+TESTCASES += check_mover.tst
+TESTCASES += check_moverm.tst
+TESTCASES += check_moveq.tst
+TESTCASES += check_movemr.tst
+TESTCASES += check_movemrv32.tst
+TESTCASES += check_movecr.tst
+TESTCASES += check_movmp.tst
+TESTCASES += check_movpr.tst
+TESTCASES += check_movprv32.tst
+TESTCASES += check_movdelsr1.tst
+TESTCASES += check_movpmv32.tst
+TESTCASES += check_movsr.tst
+TESTCASES += check_movsm.tst
+TESTCASES += check_movscr.tst
+TESTCASES += check_movur.tst
+TESTCASES += check_movum.tst
+TESTCASES += check_movucr.tst
+TESTCASES += check_mulx.tst
+TESTCASES += check_mulv32.tst
+TESTCASES += check_neg.tst
+TESTCASES += check_not.tst
+TESTCASES += check_lz.tst
+TESTCASES += check_lapc.tst
+TESTCASES += check_lsl.tst
+TESTCASES += check_lsr.tst
+TESTCASES += check_orc.tst
+TESTCASES += check_orm.tst
+TESTCASES += check_orr.tst
+TESTCASES += check_orq.tst
+TESTCASES += check_ret.tst
+TESTCASES += check_swap.tst
+TESTCASES += check_scc.tst
+TESTCASES += check_subc.tst
+TESTCASES += check_subq.tst
+TESTCASES += check_subr.tst
+TESTCASES += check_subm.tst
+TESTCASES += check_glibc_kernelversion.tst
+TESTCASES += check_xarith.tst
+
+TESTCASES += check_hello.ctst
+TESTCASES += check_stat1.ctst
+TESTCASES += check_stat2.ctst
+TESTCASES += check_stat3.ctst
+TESTCASES += check_stat4.ctst
+TESTCASES += check_openpf1.ctst
+TESTCASES += check_openpf2.ctst
+TESTCASES += check_openpf3.ctst
+TESTCASES += check_openpf4.ctst
+TESTCASES += check_openpf5.ctst
+TESTCASES += check_mapbrk.ctst
+TESTCASES += check_mmap1.ctst
+TESTCASES += check_mmap2.ctst
+TESTCASES += check_mmap3.ctst
+TESTCASES += check_sigalrm.ctst
+TESTCASES += check_time1.ctst
+TESTCASES += check_time2.ctst
+TESTCASES += check_settls1.ctst
+
+TESTCASES += check_gcctorture_pr28634-1.ctst
+#TESTCASES += check_gcctorture_pr28634.ctst
+
+all: build
+
+%.o: $(SRC_PATH)/tests/cris/%.c
+	$(CC) $(CFLAGS) -c $< -o $@
+
+%.o: $(SRC_PATH)/tests/cris/%.s
+	$(AS) $(ASFLAGS) -c $< -o $@
+
+%.tst: %.o
+	$(CC) $(CFLAGS) $(NOSTDFLAGS) $(LDLIBS) $(NOSTDLIBS) $(CRT) $< $(SYS) -o $@
+
+%.ctst: %.o
+	$(CC) $(CFLAGS) $(LDLIBS) $< -o $@
+
+build: $(CRT) $(SYS) $(TESTCASES)
+
+check: $(CRT) $(SYS) $(TESTCASES)
+	@echo -e "\nQEMU simulator."
+	for case in $(TESTCASES); do \
+		echo -n "$$case "; \
+		$(SIM) ./$$case; \
+	done
+check-g: $(CRT) $(SYS) $(TESTCASES)
+	@echo -e "\nGDB simulator."
+	@for case in $(TESTCASES); do \
+		echo -n "$$case "; \
+		$(SIMG) $$case; \
+	done
+
+clean:
+	$(RM) -fr $(TESTCASES) $(CRT) $(SYS)
diff --git a/tests/tcg/cris/README b/tests/tcg/cris/README
new file mode 100644
index 0000000..2e65a76
--- /dev/null
+++ b/tests/tcg/cris/README
@@ -0,0 +1 @@
+Test-suite for the cris port. Heavily based on the test-suite for the CRIS port of sim by Hans-Peter Nilsson.
diff --git a/tests/tcg/cris/check_abs.c b/tests/tcg/cris/check_abs.c
new file mode 100644
index 0000000..9770a8d
--- /dev/null
+++ b/tests/tcg/cris/check_abs.c
@@ -0,0 +1,40 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+static inline int cris_abs(int n)
+{
+	int r;
+	asm ("abs\t%1, %0\n" : "=r" (r) : "r" (n));
+	return r;
+}
+
+static inline void
+verify_abs(int val, int res,
+	   const int n, const int z, const int v, const int c)
+{
+	int r;
+
+	cris_tst_cc_init();
+	r = cris_abs(val);
+	cris_tst_cc(n, z, v, c);
+	if (r != res)
+		err();
+}
+
+int main(void)
+{
+	verify_abs(-1, 1, 0, 0, 0, 0);
+	verify_abs(0x80000000, 0x80000000, 1, 0, 0, 0);
+	verify_abs(0x7fffffff, 0x7fffffff, 0, 0, 0, 0);
+	verify_abs(42, 42, 0, 0, 0, 0);
+	verify_abs(1, 1, 0, 0, 0, 0);
+	verify_abs(0xffff, 0xffff, 0, 0, 0, 0);
+	verify_abs(0xffff, 0xffff, 0, 0, 0, 0);
+	verify_abs(-31, 0x1f, 0, 0, 0, 0);
+	verify_abs(0, 0, 0, 1, 0, 0);
+	pass();
+	return 0;
+}
diff --git a/tests/tcg/cris/check_addc.c b/tests/tcg/cris/check_addc.c
new file mode 100644
index 0000000..facd1be
--- /dev/null
+++ b/tests/tcg/cris/check_addc.c
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+static inline int cris_addc(int a, const int b)
+{
+	asm ("addc\t%1, %0\n" : "+r" (a) : "r" (b));
+	return a;
+}
+
+#define verify_addc(a, b, res, n, z, v, c)  \
+{                                           \
+	int r;                              \
+	r = cris_addc((a), (b));            \
+	cris_tst_cc((n), (z), (v), (c));    \
+	if (r != (res))                     \
+		err();                      \
+}
+
+int main(void)
+{
+	cris_tst_cc_init();
+	asm volatile ("clearf cz");
+	verify_addc(0, 0, 0, 0, 0, 0, 0);
+
+	cris_tst_cc_init();
+	asm volatile ("setf z");
+	verify_addc(0, 0, 0, 0, 1, 0, 0);
+
+	cris_tst_cc_init();
+	asm volatile ("setf cz");
+	verify_addc(0, 0, 1, 0, 0, 0, 0);
+	cris_tst_cc_init();
+	asm volatile ("clearf c");
+	verify_addc(-1, 2, 1, 0, 0, 0, 1);
+
+	cris_tst_cc_init();
+	asm volatile ("clearf nzv");
+	asm volatile ("setf c");
+	verify_addc(-1, 2, 2, 0, 0, 0, 1);
+
+	cris_tst_cc_init();
+	asm volatile ("setf c");
+	verify_addc(0xffff, 0xffff, 0x1ffff, 0, 0, 0, 0);
+
+	cris_tst_cc_init();
+	asm volatile ("clearf nzvc");
+	verify_addc(-1, -1, 0xfffffffe, 1, 0, 0, 1);
+
+	cris_tst_cc_init();
+	asm volatile ("setf c");
+	verify_addc(0x78134452, 0x5432f789, 0xcc463bdc, 1, 0, 1, 0);
+
+	pass();
+	return 0;
+}
diff --git a/tests/tcg/cris/check_addcm.c b/tests/tcg/cris/check_addcm.c
new file mode 100644
index 0000000..7928bc9
--- /dev/null
+++ b/tests/tcg/cris/check_addcm.c
@@ -0,0 +1,85 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+/* need to avoid acr as source here.  */
+static inline int cris_addc_m(int a, const int *b)
+{
+	asm volatile ("addc [%1], %0\n" : "+r" (a) : "r" (b));
+	return a;
+}
+
+/* 'b' is a crisv32 constrain to avoid postinc with $acr.  */
+static inline int cris_addc_pi_m(int a, int **b)
+{
+	asm volatile ("addc [%1+], %0\n" : "+r" (a), "+b" (*b));
+	return a;
+}
+
+#define verify_addc_m(a, b, res, n, z, v, c)  \
+{                                           \
+	int r;                              \
+	r = cris_addc_m((a), (b));            \
+	cris_tst_cc((n), (z), (v), (c));    \
+	if (r != (res))                     \
+		err();                      \
+}
+
+#define verify_addc_pi_m(a, b, res, n, z, v, c)  \
+{                                           \
+	int r;                              \
+	r = cris_addc_pi_m((a), (b));            \
+	cris_tst_cc((n), (z), (v), (c));    \
+	if (r != (res))                     \
+		err();                      \
+}
+
+int x[] = { 0, 0, 2, -1, 0xffff, -1, 0x5432f789};
+
+int main(void)
+{
+	int *p = (void *)&x[0];
+#if 1
+	cris_tst_cc_init();
+	asm volatile ("clearf cz");
+	verify_addc_m(0, p, 0, 0, 0, 0, 0);
+
+	cris_tst_cc_init();
+	asm volatile ("setf z");
+	verify_addc_m(0, p, 0, 0, 1, 0, 0);
+
+	cris_tst_cc_init();
+	asm volatile ("setf c");
+	verify_addc_m(0, p, 1, 0, 0, 0, 0);
+
+	cris_tst_cc_init();
+	asm volatile ("clearf c");
+	verify_addc_pi_m(0, &p, 0, 0, 1, 0, 0);
+
+	p = &x[1];
+	cris_tst_cc_init();
+	asm volatile ("setf c");
+	verify_addc_pi_m(0, &p, 1, 0, 0, 0, 0);
+
+	if (p != &x[2])
+		err();
+
+	cris_tst_cc_init();
+	asm volatile ("clearf c");
+	verify_addc_pi_m(-1, &p, 1, 0, 0, 0, 1);
+
+	if (p != &x[3])
+		err();
+#endif
+	p = &x[3];
+	/* TODO: investigate why this one fails.  */
+	cris_tst_cc_init();
+	asm volatile ("setf c");
+	verify_addc_m(2, p, 2, 0, 0, 0, 1);
+	p += 4;
+
+	pass();
+	return 0;
+}
diff --git a/tests/tcg/cris/check_addi.s b/tests/tcg/cris/check_addi.s
new file mode 100644
index 0000000..a00dec0
--- /dev/null
+++ b/tests/tcg/cris/check_addi.s
@@ -0,0 +1,57 @@
+# mach:  crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 0\n1\n2\n4\nbe02460f\n69d035a6\nc16c14d4\n
+
+ .include "testutils.inc"
+ start
+ moveq 0,r3
+ moveq 0,r4
+ clearf zcvn
+ addi r4.b,r3
+ test_cc 0 0 0 0
+ checkr3 0
+
+ moveq 0,r3
+ moveq 1,r4
+ setf zcvn
+ addi r4.b,r3
+ test_cc 1 1 1 1
+ checkr3 1
+
+ moveq 0,r3
+ moveq 1,r4
+ setf cv
+ clearf zn
+ addi r4.w,r3
+ test_cc 0 0 1 1
+ checkr3 2
+
+ moveq 0,r3
+ moveq 1,r4
+ clearf cv
+ setf zn
+ addi r4.d,r3
+ test_cc 1 1 0 0
+ checkr3 4
+
+ move.d 0x12345678,r3
+ move.d 0xabcdef97,r4
+ clearf cn
+ setf zv
+ addi r4.b,r3
+ test_cc 0 1 1 0
+ checkr3 be02460f
+
+ move.d 0x12345678,r3
+ move.d 0xabcdef97,r4
+ setf cn
+ clearf zv
+ addi r4.w,r3
+ test_cc 1 0 0 1
+ checkr3 69d035a6
+
+ move.d 0x12345678,r3
+ move.d 0xabcdef97,r4
+ addi r4.d,r3
+ checkr3 c16c14d4
+
+ quit
diff --git a/tests/tcg/cris/check_addiv32.s b/tests/tcg/cris/check_addiv32.s
new file mode 100644
index 0000000..20ba25d
--- /dev/null
+++ b/tests/tcg/cris/check_addiv32.s
@@ -0,0 +1,62 @@
+# mach: crisv32
+# output: 4455aa77\n4455aa77\nee19ccff\nff22\n4455aa77\nff224455\n55aa77ff\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword 0x55aa77ff
+ .dword 0xccff2244
+ .dword 0x88ccee19
+
+ start
+ setf cv
+ moveq -1,r0
+ move.d x-32768,r5
+ move.d 32769,r6
+ addi r6.b,r5,acr
+ test_cc 0 0 1 1
+ move.d [acr],r3
+ checkr3 4455aa77
+
+ addu.w 32771,r5
+ setf znvc
+ moveq -1,r8
+ addi r8.w,r5,acr
+ test_cc 1 1 1 1
+ move.d [acr],r3
+ checkr3 4455aa77
+
+ moveq 5,r10
+ clearf znvc
+ addi r10.b,acr,acr
+ test_cc 0 0 0 0
+ move.d [acr],r3
+ checkr3 ee19ccff
+
+ subq 1,r5
+ move.d r5,r8
+ subq 1,r8
+ moveq 1,r9
+ addi r9.d,r8,acr
+ test_cc 0 0 0 0
+ movu.w [acr],r3
+ checkr3 ff22
+
+ moveq -2,r11
+ addi r11.w,acr,acr
+ move.d [acr],r3
+ checkr3 4455aa77
+
+ moveq 5,r9
+ addi r9.d,acr,acr
+ subq 18,acr
+ move.d [acr],r3
+ checkr3 ff224455
+
+ move.d -76789888/4,r12
+ addi r12.d,r5,acr
+ add.d 76789886,acr
+ move.d [acr],r3
+ checkr3 55aa77ff
+
+ quit
diff --git a/tests/tcg/cris/check_addm.s b/tests/tcg/cris/check_addm.s
new file mode 100644
index 0000000..efece9f
--- /dev/null
+++ b/tests/tcg/cris/check_addm.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n781344d0\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword 2,-1,0xffff,-1,0x5432f789
+ .word 2,-1,0xffff,0xf789
+ .byte 2,0xff,0x89
+ .byte 0x7e
+
+ start
+ moveq -1,r3
+ move.d x,r5
+ add.d [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ add.d [r5],r3
+ test_cc 0 0 0 1
+ addq 4,r5
+ checkr3 1
+
+ move.d 0xffff,r3
+ add.d [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+
+ moveq -1,r3
+ add.d [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ move.d 0x78134452,r3
+ add.d [r5+],r3
+ test_cc 1 0 1 0
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ add.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 ffff0001
+
+ moveq 2,r3
+ add.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xffff,r3
+ add.w [r5],r3
+ test_cc 1 0 0 1
+ checkr3 fffe
+
+ move.d 0xfedaffff,r3
+ add.w [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 fedafffe
+
+ move.d 0x78134452,r3
+ add.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 78133bdb
+
+ moveq -1,r3
+ add.b [r5],r3
+ test_cc 0 0 0 1
+ addq 1,r5
+ checkr3 ffffff01
+
+ moveq 2,r3
+ add.b [r5],r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xff,r3
+ add.b [r5],r3
+ test_cc 1 0 0 1
+ checkr3 fe
+
+ move.d 0xfeda49ff,r3
+ add.b [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 feda49fe
+
+ move.d 0x78134452,r3
+ add.b [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 781344db
+
+ move.d 0x78134452,r3
+ add.b [r5],r3
+ test_cc 1 0 1 0
+ checkr3 781344d0
+
+ quit
diff --git a/tests/tcg/cris/check_addo.c b/tests/tcg/cris/check_addo.c
new file mode 100644
index 0000000..3d8e789
--- /dev/null
+++ b/tests/tcg/cris/check_addo.c
@@ -0,0 +1,125 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+/* this would be better to do in asm, it's an orgy in GCC inline asm now.  */
+
+#define cris_addo_b(o, v) \
+	asm volatile ("addo.b\t[%0], %1, $acr\n" : : "r" (o), "r" (v) : "acr");
+#define cris_addo_w(o, v) \
+	asm volatile ("addo.w\t[%0], %1, $acr\n" : : "r" (o), "r" (v) : "acr");
+#define cris_addo_d(o, v) \
+	asm volatile ("addo.d\t[%0], %1, $acr\n" : : "r" (o), "r" (v) : "acr");
+#define cris_addo_pi_b(o, v) \
+	asm volatile ("addo.b\t[%0+], %1, $acr\n" \
+                         : "+b" (o): "r" (v) : "acr");
+#define cris_addo_pi_w(o, v) \
+	asm volatile ("addo.w\t[%0+], %1, $acr\n" \
+                         : "+b" (o): "r" (v) : "acr");
+#define cris_addo_pi_d(o, v) \
+	asm volatile ("addo.d\t[%0+], %1, $acr\n" \
+                         : "+b" (o): "r" (v) : "acr");
+
+struct {
+	uint32_t v1;
+	uint16_t v2;
+	uint32_t v3;
+	uint8_t v4;
+	uint8_t v5;
+	uint16_t v6;
+	uint32_t v7;
+} y = {
+	32769,
+	-1,
+	5,
+	3, -4,
+	2,
+	-76789887
+};
+
+static int x[3] = {0x55aa77ff, 0xccff2244, 0x88ccee19};
+
+int main(void)
+{
+	int *r;
+	unsigned char *t, *p;
+
+	/* Note, this test-case will trig an unaligned access, partly
+	   to x[0] and to [x1].  */
+	t = (unsigned char *)x;
+	t -= 32768;
+	p = (unsigned char *) &y.v1;
+	mb(); /* dont reorder anything beyond here.  */
+	cris_tst_cc_init();
+	asm volatile ("setf\tzvnc\n");
+	cris_addo_pi_d(p, t);
+	cris_tst_cc(1, 1, 1, 1);
+	asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+	if (*r != 0x4455aa77)
+		err();
+
+
+	t += 32770;
+	mb(); /* dont reorder anything beyond here.  */
+	cris_tst_cc_init();
+	asm volatile ("setf\tzvnc\n");
+	cris_addo_pi_w(p, t);
+	cris_tst_cc(1, 1, 1, 1);
+	asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+	if (*r != 0x4455aa77)
+		err();
+
+	mb(); /* dont reorder anything beyond here.  */
+	cris_tst_cc_init();
+	asm volatile ("setf\tzvnc\n");
+	cris_addo_d(p, r);
+	cris_tst_cc(1, 1, 1, 1);
+	p += 4;
+	asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+	if (*r != 0xee19ccff)
+		err();
+
+	mb(); /* dont reorder anything beyond here.  */
+	cris_tst_cc_init();
+	asm volatile ("setf\tzvnc\n");
+	cris_addo_pi_b(p, t);
+	cris_tst_cc(0, 0, 0, 0);
+	asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+	if (*(uint16_t*)r != 0xff22)
+		err();
+
+	mb(); /* dont reorder anything beyond here.  */
+	cris_tst_cc_init();
+	asm volatile ("setf\tzvnc\n");
+	cris_addo_b(p, r);
+	cris_tst_cc(1, 1, 1, 1);
+	p += 1;
+	asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+	if (*r != 0x4455aa77)
+		err();
+
+	mb(); /* dont reorder anything beyond here.  */
+	cris_tst_cc_init();
+	asm volatile ("setf\tzvnc\n");
+	cris_addo_w(p, r);
+	cris_tst_cc(1, 1, 1, 1);
+	p += 2;
+	asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+	if (*r != 0xff224455)
+		err();
+
+	mb(); /* dont reorder anything beyond here.  */
+	cris_tst_cc_init();
+	asm volatile ("setf\tzvnc\n");
+	cris_addo_pi_d(p, t);
+	cris_tst_cc(0, 0, 0, 0);
+	asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+	r = (void*)(((char *)r) + 76789885);
+	if (*r != 0x55aa77ff)
+		err();
+
+	pass();
+	return 0;
+}
diff --git a/tests/tcg/cris/check_addoq.c b/tests/tcg/cris/check_addoq.c
new file mode 100644
index 0000000..ed509e2
--- /dev/null
+++ b/tests/tcg/cris/check_addoq.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+/* this would be better to do in asm, it's an orgy in GCC inline asm now.  */
+
+/* ACR will be clobbered.  */
+#define cris_addoq(o, v) \
+	asm volatile ("addoq\t%1, %0, $acr\n" : : "r" (v), "i" (o) : "acr");
+
+
+int main(void)
+{
+	int x[3] = {0x55aa77ff, 0xccff2244, 0x88ccee19};
+	int *p, *t = x + 1;
+
+	cris_tst_cc_init();
+	asm volatile ("setf\tzvnc\n");
+	cris_addoq(0, t);
+	cris_tst_cc(1, 1, 1, 1);
+	asm volatile ("move.d\t$acr, %0\n" : "=r" (p));
+	if (*p != 0xccff2244)
+		err();
+
+	cris_tst_cc_init();
+	asm volatile ("setf\tzvnc\n");
+	cris_addoq(4, t);
+	cris_tst_cc(0, 0, 0, 0);
+	asm volatile ("move.d\t$acr, %0\n" : "=r" (p));
+	if (*p != 0x88ccee19)
+		err();
+
+	cris_tst_cc_init();
+	asm volatile ("clearf\tzvnc\n");
+	cris_addoq(-8, t + 1);
+	cris_tst_cc(0, 0, 0, 0);
+	asm volatile ("move.d\t$acr, %0\n" : "=r" (p));
+	if (*p != 0x55aa77ff)
+		err();
+	pass();
+	return 0;
+}
diff --git a/tests/tcg/cris/check_addq.s b/tests/tcg/cris/check_addq.s
new file mode 100644
index 0000000..e6f874f
--- /dev/null
+++ b/tests/tcg/cris/check_addq.s
@@ -0,0 +1,47 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n0\n1\n100\n10000\n47\n67\na6\n80000001\n
+
+ .include "testutils.inc"
+ start
+ moveq -2,r3
+ addq 1,r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ addq 1,r3
+ test_cc 0 1 0 1
+ checkr3 0
+
+ addq 1,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xff,r3
+ addq 1,r3
+ test_cc 0 0 0 0
+ checkr3 100
+
+ move.d 0xffff,r3
+ addq 1,r3
+ test_cc 0 0 0 0
+ checkr3 10000
+
+ move.d 0x42,r3
+ addq 5,r3
+ test_cc 0 0 0 0
+ checkr3 47
+
+ addq 32,r3
+ test_cc 0 0 0 0
+ checkr3 67
+
+ addq 63,r3
+ test_cc 0 0 0 0
+ checkr3 a6
+
+ move.d 0x7ffffffe,r3
+ addq 3,r3
+ test_cc 1 0 1 0
+ checkr3 80000001
+
+ quit
diff --git a/tests/tcg/cris/check_addr.s b/tests/tcg/cris/check_addr.s
new file mode 100644
index 0000000..7f55cdc
--- /dev/null
+++ b/tests/tcg/cris/check_addr.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ add.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ moveq -1,r4
+ add.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ add.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+
+ moveq -1,r4
+ move.d r4,r3
+ add.d r4,r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.d r4,r3
+ test_cc 1 0 1 0
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ moveq 2,r4
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 ffff0001
+
+ moveq 2,r3
+ moveq -1,r4
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ add.w r4,r3
+ test_cc 1 0 0 1
+ checkr3 fffe
+
+ move.d 0xfedaffff,r4
+ move.d r4,r3
+ add.w r4,r3
+ test_cc 1 0 0 1
+ checkr3 fedafffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 78133bdb
+
+ moveq -1,r3
+ moveq 2,r4
+ add.b r4,r3
+ test_cc 0 0 0 1
+ checkr3 ffffff01
+
+ moveq 2,r3
+ moveq -1,r4
+ add.b r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xff,r4
+ move.d r4,r3
+ add.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 fe
+
+ move.d 0xfeda49ff,r4
+ move.d r4,r3
+ add.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 feda49fe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 781344db
+
+ quit
diff --git a/tests/tcg/cris/check_addxc.s b/tests/tcg/cris/check_addxc.s
new file mode 100644
index 0000000..09c8355
--- /dev/null
+++ b/tests/tcg/cris/check_addxc.s
@@ -0,0 +1,91 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n101\n10001\n100fe\n1fffe\nfffe\nfffe\nfffffffe\nfe\nfffffffe\n781344db\n781343db\n78143bdb\n78133bdb\n800000ed\n0\n
+
+ .include "testutils.inc"
+ start
+ moveq 2,r3
+ adds.b 0xff,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ adds.w 0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ addu.b 0xff,r3
+ checkr3 101
+
+ moveq 2,r3
+ move.d 0xffffffff,r4
+ addu.w -1,r3
+ test_cc 0 0 0 0
+ checkr3 10001
+
+ move.d 0xffff,r3
+ addu.b -1,r3
+ test_cc 0 0 0 0
+ checkr3 100fe
+
+ move.d 0xffff,r3
+ addu.w -1,r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+
+ move.d 0xffff,r3
+ adds.b 0xff,r3
+ test_cc 0 0 0 1
+ checkr3 fffe
+
+ move.d 0xffff,r3
+ adds.w 0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 fffe
+
+ moveq -1,r3
+ adds.b 0xff,r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ moveq -1,r3
+ adds.w 0xff,r3
+ test_cc 0 0 0 1
+ checkr3 fe
+
+ moveq -1,r3
+ adds.w 0xffff,r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ move.d 0x78134452,r3
+ addu.b 0x89,r3
+ test_cc 0 0 0 0
+ checkr3 781344db
+
+ move.d 0x78134452,r3
+ adds.b 0x89,r3
+ test_cc 0 0 0 1
+ checkr3 781343db
+
+ move.d 0x78134452,r3
+ addu.w 0xf789,r3
+ test_cc 0 0 0 0
+ checkr3 78143bdb
+
+ move.d 0x78134452,r3
+ adds.w 0xf789,r3
+ test_cc 0 0 0 1
+ checkr3 78133bdb
+
+ move.d 0x7fffffee,r3
+ addu.b 0xff,r3
+ test_cc 1 0 1 0
+ checkr3 800000ed
+
+ move.d 0x1,r3
+ adds.w 0xffff,r3
+ test_cc 0 1 0 1
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_addxm.s b/tests/tcg/cris/check_addxm.s
new file mode 100644
index 0000000..7563494
--- /dev/null
+++ b/tests/tcg/cris/check_addxm.s
@@ -0,0 +1,106 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n101\n10001\n100fe\n1fffe\nfffe\nfffe\nfffffffe\nfe\nfffffffe\n781344db\n781343db\n78143bdb\n78133bdb\n800000ed\n0\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .byte 0xff
+ .word 0xffff
+ .word 0xff
+ .word 0xffff
+ .byte 0x89
+ .word 0xf789
+ .byte 0xff
+ .word 0xffff
+
+ start
+ moveq 2,r3
+ move.d x,r5
+ adds.b [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ adds.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ subq 3,r5
+ addu.b [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 101
+
+ moveq 2,r3
+ addu.w [r5+],r3
+ subq 3,r5
+ test_cc 0 0 0 0
+ checkr3 10001
+
+ move.d 0xffff,r3
+ addu.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 100fe
+
+ move.d 0xffff,r3
+ addu.w [r5],r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+
+ move.d 0xffff,r3
+ adds.b [r5],r3
+ test_cc 0 0 0 1
+ checkr3 fffe
+
+ move.d 0xffff,r3
+ adds.w [r5],r3
+ test_cc 0 0 0 1
+ checkr3 fffe
+
+ moveq -1,r3
+ adds.b [r5],r3
+ test_cc 1 0 0 1
+ addq 3,r5
+ checkr3 fffffffe
+
+ moveq -1,r3
+ adds.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 fe
+
+ moveq -1,r3
+ adds.w [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ move.d 0x78134452,r3
+ addu.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 781344db
+
+ move.d 0x78134452,r3
+ adds.b [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 781343db
+
+ move.d 0x78134452,r3
+ addu.w [r5],r3
+ test_cc 0 0 0 0
+ checkr3 78143bdb
+
+ move.d 0x78134452,r3
+ adds.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 78133bdb
+
+ move.d 0x7fffffee,r3
+ addu.b [r5+],r3
+ test_cc 1 0 1 0
+ checkr3 800000ed
+
+ move.d 0x1,r3
+ adds.w [r5+],r3
+ test_cc 0 1 0 1
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_addxr.s b/tests/tcg/cris/check_addxr.s
new file mode 100644
index 0000000..7f55cdc
--- /dev/null
+++ b/tests/tcg/cris/check_addxr.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ add.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ moveq -1,r4
+ add.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ add.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+
+ moveq -1,r4
+ move.d r4,r3
+ add.d r4,r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.d r4,r3
+ test_cc 1 0 1 0
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ moveq 2,r4
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 ffff0001
+
+ moveq 2,r3
+ moveq -1,r4
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ add.w r4,r3
+ test_cc 1 0 0 1
+ checkr3 fffe
+
+ move.d 0xfedaffff,r4
+ move.d r4,r3
+ add.w r4,r3
+ test_cc 1 0 0 1
+ checkr3 fedafffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 78133bdb
+
+ moveq -1,r3
+ moveq 2,r4
+ add.b r4,r3
+ test_cc 0 0 0 1
+ checkr3 ffffff01
+
+ moveq 2,r3
+ moveq -1,r4
+ add.b r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xff,r4
+ move.d r4,r3
+ add.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 fe
+
+ move.d 0xfeda49ff,r4
+ move.d r4,r3
+ add.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 feda49fe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 781344db
+
+ quit
diff --git a/tests/tcg/cris/check_andc.s b/tests/tcg/cris/check_andc.s
new file mode 100644
index 0000000..a947b77
--- /dev/null
+++ b/tests/tcg/cris/check_andc.s
@@ -0,0 +1,80 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n50124400\nffff0002\n2\nfffff\nfedaff0f\n78134400\nffffff02\n2\nf02\n78134401\n78134400\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ and.d 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ and.d -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ and.d 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r3
+ and.d -1,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ and.d 0x5432f789,r3
+ test_move_cc 0 0 0 0
+ checkr3 50124400
+
+ moveq -1,r3
+ and.w 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0002
+
+ moveq 2,r3
+ and.w -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xfffff,r3
+ and.w 0xffff,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffff
+
+ move.d 0xfedaffaf,r3
+ and.w 0xff5f,r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaff0f
+
+ move.d 0x78134452,r3
+ and.w 0xf789,r3
+ test_move_cc 0 0 0 0
+ checkr3 78134400
+
+ moveq -1,r3
+ and.b 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff02
+
+ moveq 2,r3
+ and.b -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xfa7,r3
+ and.b 0x5a,r3
+ test_move_cc 0 0 0 0
+ checkr3 f02
+
+ move.d 0x78134453,r3
+ and.b 0x89,r3
+ test_move_cc 0 0 0 0
+ checkr3 78134401
+
+ and.b 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 78134400
+
+ quit
diff --git a/tests/tcg/cris/check_andm.s b/tests/tcg/cris/check_andm.s
new file mode 100644
index 0000000..9385886
--- /dev/null
+++ b/tests/tcg/cris/check_andm.s
@@ -0,0 +1,90 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n50124400\nffff0002\n2\nfffff\nfedaff0f\n78134400\nffffff02\n2\nf02\n78134401\n78134400\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword 2,-1,0xffff,-1,0x5432f789
+ .word 2,-1,0xffff,0xff5f,0xf789
+ .byte 2,-1,0x5a,0x89,0
+
+ start
+ moveq -1,r3
+ move.d x,r5
+ and.d [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ and.d [r5],r3
+ test_move_cc 0 0 0 0
+ addq 4,r5
+ checkr3 2
+
+ move.d 0xffff,r3
+ and.d [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r3
+ and.d [r5+],r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ and.d [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 50124400
+
+ moveq -1,r3
+ and.w [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0002
+
+ moveq 2,r3
+ and.w [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xfffff,r3
+ and.w [r5],r3
+ test_move_cc 1 0 0 0
+ addq 2,r5
+ checkr3 fffff
+
+ move.d 0xfedaffaf,r3
+ and.w [r5+],r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaff0f
+
+ move.d 0x78134452,r3
+ and.w [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 78134400
+
+ moveq -1,r3
+ and.b [r5],r3
+ test_move_cc 0 0 0 0
+ addq 1,r5
+ checkr3 ffffff02
+
+ moveq 2,r3
+ and.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xfa7,r3
+ and.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 f02
+
+ move.d 0x78134453,r3
+ and.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 78134401
+
+ and.b [r5],r3
+ test_move_cc 0 1 0 0
+ checkr3 78134400
+
+ quit
diff --git a/tests/tcg/cris/check_andq.s b/tests/tcg/cris/check_andq.s
new file mode 100644
index 0000000..55aa7b0
--- /dev/null
+++ b/tests/tcg/cris/check_andq.s
@@ -0,0 +1,46 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n1f\nffffffe0\n78134452\n0\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ andq 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ andq -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ andq -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r3
+ andq -1,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ andq 31,r3
+ test_move_cc 0 0 0 0
+ checkr3 1f
+
+ moveq -1,r3
+ andq -32,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffe0
+
+ move.d 0x78134457,r3
+ andq -14,r3
+ test_move_cc 0 0 0 0
+ checkr3 78134452
+
+ moveq 0,r3
+ andq -14,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_andr.s b/tests/tcg/cris/check_andr.s
new file mode 100644
index 0000000..61aa1dc
--- /dev/null
+++ b/tests/tcg/cris/check_andr.s
@@ -0,0 +1,95 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n50124400\nffff0002\n2\nfffff\nfedaff0f\n78134400\nffffff02\n2\nf02\n78134401\n78134400\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ and.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ moveq -1,r4
+ and.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ and.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r4
+ move.d r4,r3
+ and.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ and.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 50124400
+
+ moveq -1,r3
+ moveq 2,r4
+ and.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0002
+
+ moveq 2,r3
+ moveq -1,r4
+ and.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xfffff,r3
+ move.d 0xffff,r4
+ and.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffff
+
+ move.d 0xfedaffaf,r3
+ move.d 0xff5f,r4
+ and.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaff0f
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ and.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 78134400
+
+ moveq -1,r3
+ moveq 2,r4
+ and.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff02
+
+ moveq 2,r3
+ moveq -1,r4
+ and.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0x5a,r4
+ move.d 0xfa7,r3
+ and.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 f02
+
+ move.d 0x5432f789,r4
+ move.d 0x78134453,r3
+ and.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 78134401
+
+ moveq 0,r7
+ and.b r7,r3
+ test_move_cc 0 1 0 0
+ checkr3 78134400
+
+ quit
diff --git a/tests/tcg/cris/check_asr.s b/tests/tcg/cris/check_asr.s
new file mode 100644
index 0000000..0a02ae6
--- /dev/null
+++ b/tests/tcg/cris/check_asr.s
@@ -0,0 +1,230 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n1\nffffffff\nffffffff\n5a67f\nffffffff\nffffffff\nffffffff\nf699fc67\nffffffff\n1\nffffffff\nffffffff\n5a67f\nda67ffff\nda67ffff\nda67ffff\nda67fc67\nffffffff\nffffffff\n1\nffffffff\nffffffff\n5a670007\nda67f1ff\nda67f1ff\nda67f1ff\nda67f1e7\nffffffff\nffffffff\n1\nffffffff\nffffffff\nffffffff\n5a67f1ff\n5a67f1f9\n0\n5a670000\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ asrq 0,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ asrq 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ asrq 31,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ asrq 15,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5a67f19f,r3
+ asrq 12,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67f
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 f699fc67
+
+ moveq -1,r3
+ moveq 0,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ asr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 31,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 15,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ asr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67f
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67ffff
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67ffff
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67ffff
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67fc67
+
+ moveq -1,r3
+ moveq 0,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 1,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ asr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 31,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 15,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5a67719f,r3
+ moveq 12,r4
+ asr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a670007
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67f1ff
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67f1ff
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67f1ff
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67f1e7
+
+ moveq -1,r3
+ moveq 0,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 1,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ asr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 31,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 15,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 7,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+; FIXME: was wrong.
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 5a67f1ff
+
+; FIXME: was wrong.
+ move.d 0x5a67f19f,r3
+ moveq 4,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 5a67f1f9
+
+ move.d 0x5a67f19f,r3
+ asrq 31,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0x5a67419f,r3
+ moveq 16,r4
+ asr.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 5a670000
+
+ quit
diff --git a/tests/tcg/cris/check_ba.s b/tests/tcg/cris/check_ba.s
new file mode 100644
index 0000000..873a408
--- /dev/null
+++ b/tests/tcg/cris/check_ba.s
@@ -0,0 +1,93 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: a\n
+
+
+ .set smalloffset,0
+ .set largeoffset,0
+
+
+	.macro fail
+	jump _fail
+	.endm
+
+	.global	main
+main:
+ moveq 0,$r3
+
+; Short forward branch.
+ ba 0f
+ addq 1,$r3
+ fail
+
+; Max short forward branch.
+1:
+ ba 2f
+ addq 1,$r3
+ fail
+
+; Short backward branch.
+0:
+ ba 1b
+ addq 1,$r3
+ fail
+
+ .space 254-2+smalloffset+1b-.,0
+ moveq 0,$r3
+
+2:
+; Transit branch (long).
+ ba 3f
+ addq 1,$r3
+ fail
+
+ moveq 0,$r3
+4:
+; Long forward branch.
+ ba 5f
+ addq 1,$r3
+ fail
+
+ .space 256-2-smalloffset+4b-.,0
+
+ moveq 0,$r3
+
+; Max short backward branch.
+3:
+ ba 4b
+ addq 1,$r3
+ fail
+
+5:
+; Max long forward branch.
+ ba 6f
+ addq 1,$r3
+ fail
+
+ .space 32766+largeoffset-2+5b-.,0
+
+ moveq 0,$r3
+6:
+; Transit branch.
+ ba 7f
+ addq 1,$r3
+ fail
+
+ moveq 0,$r3
+9:
+ jsr pass
+ nop
+
+; Transit branch.
+ moveq 0,$r3
+7:
+ ba 8f
+ addq 1,$r3
+ fail
+
+ .space 32768-largeoffset+9b-.,0
+
+8:
+; Max long backward branch.
+ ba 9b
+ addq 1,$r3
+ fail
diff --git a/tests/tcg/cris/check_bas.s b/tests/tcg/cris/check_bas.s
new file mode 100644
index 0000000..11929d4
--- /dev/null
+++ b/tests/tcg/cris/check_bas.s
@@ -0,0 +1,102 @@
+# mach: crisv32
+# output: 0\n0\n0\nfb349abc\n0\n12124243\n0\n0\neab5baad\n0\nefb37832\n
+
+ .include "testutils.inc"
+ start
+x:
+ setf zncv
+ bsr 0f
+ nop
+0:
+ test_cc 1 1 1 1
+ move srp,r3
+ sub.d 0b,r3
+ checkr3 0
+
+ bas 1f,mof
+ moveq 0,r0
+6:
+ nop
+ quit
+
+2:
+ move srp,r3
+ sub.d 3f,r3
+ checkr3 0
+ move srp,r4
+ subq 4,r4
+ move.d [r4],r3
+ checkr3 fb349abc
+
+ basc 4f,mof
+ nop
+ .dword 0x12124243
+7:
+ nop
+ quit
+
+8:
+ move mof,r3
+ sub.d 7f,r3
+ checkr3 0
+
+ move mof,r4
+ subq 4,r4
+ move.d [r4],r3
+ checkr3 eab5baad
+
+ jasc 9f,mof
+ nop
+ .dword 0xefb37832
+0:
+ quit
+
+ quit
+9:
+ move mof,r3
+ sub.d 0b,r3
+ checkr3 0
+
+ move mof,r4
+ subq 4,r4
+ move.d [r4],r3
+ checkr3 efb37832
+
+ quit
+
+4:
+ move mof,r3
+ sub.d 7b,r3
+ checkr3 0
+ move mof,r4
+ subq 4,r4
+ move.d [r4],r3
+ checkr3 12124243
+ basc 5f,bz
+ moveq 0,r3
+ .dword 0x7634aeba
+ quit
+
+ .space 32770,0
+1:
+ move mof,r3
+ sub.d 6b,r3
+ checkr3 0
+
+ bsrc 2b
+ nop
+ .dword 0xfb349abc
+3:
+
+ quit
+
+5:
+ move mof,r3
+ sub.d 7b,r3
+ checkr3 0
+ move.d 8b,r6
+ jasc r6,mof
+ nop
+ .dword 0xeab5baad
+7:
+ quit
diff --git a/tests/tcg/cris/check_bcc.s b/tests/tcg/cris/check_bcc.s
new file mode 100644
index 0000000..c57ffa6
--- /dev/null
+++ b/tests/tcg/cris/check_bcc.s
@@ -0,0 +1,197 @@
+	.global	main
+	.type	main, @function
+main:
+	clearf nzvc
+	setf   nzv
+	bcc    0f
+	addq   1, $r3
+	jump   dofail
+
+0:
+	clearf nzvc
+	setf   nzv
+	bcs    dofail
+	addq   1,$r3
+
+	clearf nzvc
+	setf   ncv
+	bne    1f
+	addq   1, $r3
+
+fail:
+dofail:
+	jump	_fail
+
+1:
+	clearf nzvc
+	setf ncv
+	beq dofail
+	addq 1,$r3
+
+	clearf nzvc
+	setf ncz
+	bvc 2f
+	addq 1,$r3
+	jump dofail
+
+2:
+	clearf nzvc
+	setf ncz
+	bvs dofail
+	addq 1,$r3
+
+	clearf	nzvc
+	setf	vcz
+	bpl	3f
+	addq	1,$r3
+	jump	fail
+3:
+	clearf	nzvc
+	setf	vcz
+	bmi	dofail
+	addq	1,$r3
+
+	clearf	nzvc
+	setf	nv
+	bls	dofail
+	addq	1,$r3
+
+	clearf	nzvc
+	setf	nv
+	bhi	4f
+	addq	1,$r3
+	jump	dofail
+
+4:
+	clearf	nzvc
+	setf	zc
+	bge	5f
+	addq	1,$r3
+	jump	dofail
+
+5:
+	clearf	nzvc
+	setf zc
+	blt dofail
+	addq 1,$r3
+
+	clearf nzvc
+	setf c
+	bgt 6f
+	addq 1,$r3
+	jump  fail
+
+6:
+ clearf nzvc
+ setf c
+ ble dofail
+ addq 1,$r3
+
+;;;;;;;;;;
+
+ setf nzvc
+ clearf nzv
+ bcc dofail
+ addq 1,$r3
+
+ setf nzvc
+ clearf nzv
+ bcs 0f
+ addq 1,$r3
+ jump fail
+
+0:
+ setf nzvc
+ clearf ncv
+ bne dofail
+ addq 1,$r3
+
+ setf nzvc
+ clearf ncv
+ beq 1f
+ addq 1,$r3
+ jump fail
+
+1:
+ setf nzvc
+ clearf ncz
+ bvc dofail
+ addq 1,$r3
+
+ setf nzvc
+ clearf ncz
+ bvs 2f
+ addq 1,$r3
+ jump fail
+
+2:
+ setf nzvc
+ clearf vcz
+ bpl dofail
+ addq 1,$r3
+
+ setf nzvc
+ clearf vcz
+ bmi 3f
+ addq 1,$r3
+ jump fail
+
+3:
+ setf nzvc
+ clearf nv
+ bls 4f
+ addq 1,$r3
+ jump fail
+
+4:
+ setf nzvc
+ clearf nv
+ bhi dofail
+ addq 1,$r3
+
+ setf zvc
+ clearf nzc
+ bge dofail
+ addq 1,$r3
+
+ setf nzc
+ clearf vzc
+ blt 5f
+ addq 1,$r3
+ jump fail
+
+5:
+ setf nzvc
+ clearf c
+ bgt dofail
+ addq 1,$r3
+
+ setf nzvc
+ clearf c
+ ble 6f
+ addq 1,$r3
+ jump fail
+
+6:
+	; do a forward branch.
+	ba   2f
+	nop
+	.fill	100
+1:
+	ba	3f
+	nop
+	.fill	800
+2:
+	ba	1b
+	nop
+	.fill	1024
+3:
+
+	moveq	31, $r0
+1:	bne	1b
+	subq	1, $r0
+
+	jsr	pass
+	moveq	0, $r10
+	ret
+	nop
diff --git a/tests/tcg/cris/check_bound.c b/tests/tcg/cris/check_bound.c
new file mode 100644
index 0000000..e883175
--- /dev/null
+++ b/tests/tcg/cris/check_bound.c
@@ -0,0 +1,142 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+static inline int cris_bound_b(int v, int b)
+{
+	int r = v;
+	asm ("bound.b\t%1, %0\n" : "+r" (r) : "ri" (b));
+	return r;
+}
+
+static inline int cris_bound_w(int v, int b)
+{
+	int r = v;
+	asm ("bound.w\t%1, %0\n" : "+r" (r) : "ri" (b));
+	return r;
+}
+
+static inline int cris_bound_d(int v, int b)
+{
+	int r = v;
+	asm ("bound.d\t%1, %0\n" : "+r" (r) : "ri" (b));
+	return r;
+}
+
+int main(void)
+{
+	int r;
+
+	cris_tst_cc_init();
+	r = cris_bound_d(-1, 2);
+	cris_tst_cc(0, 0, 0, 0);
+	if (r != 2)
+		err();
+
+	cris_tst_cc_init();
+	r = cris_bound_d(2, 0xffffffff);
+	cris_tst_cc(0, 0, 0, 0);
+	if (r != 2)
+		err();
+
+	cris_tst_cc_init();
+	r = cris_bound_d(0xffff, 0xffff);
+	cris_tst_cc(0, 0, 0, 0);
+	if (r != 0xffff)
+		err();
+
+	cris_tst_cc_init();
+	r = cris_bound_d(-1, 0xffffffff);
+	cris_tst_cc(1, 0, 0, 0);
+	if (r != 0xffffffff)
+		err();
+
+	cris_tst_cc_init();
+	r = cris_bound_d(0x78134452, 0x5432f789);
+	cris_tst_cc(0, 0, 0, 0);
+	if (r != 0x5432f789)
+		err();
+
+	cris_tst_cc_init();
+	r = cris_bound_w(-1, 2);
+	cris_tst_cc(0, 0, 0, 0);
+	if (r != 2)
+		err();
+
+	cris_tst_cc_init();
+	r = cris_bound_w(-1, 0xffff);
+	cris_tst_cc(0, 0, 0, 0);
+	if (r != 0xffff)
+		err();
+
+	cris_tst_cc_init();
+	r = cris_bound_w(2, 0xffff);
+	cris_tst_cc(0, 0, 0, 0);
+	if (r != 2)
+		err();
+
+	cris_tst_cc_init();
+	r = cris_bound_w(0xfedaffff, 0xffff);
+	cris_tst_cc(0, 0, 0, 0);
+	if (r != 0xffff)
+		err();
+
+	cris_tst_cc_init();
+	r = cris_bound_w(0x78134452, 0xf789);
+	cris_tst_cc(0, 0, 0, 0);
+	if (r != 0xf789)
+		err();
+
+	cris_tst_cc_init();
+	r = cris_bound_b(-1, 2);
+	cris_tst_cc(0, 0, 0, 0);
+	if (r != 2)
+		err();
+
+	cris_tst_cc_init();
+	r = cris_bound_b(2, 0xff);
+	cris_tst_cc(0, 0, 0, 0);
+	if (r != 2)
+		err();
+
+	cris_tst_cc_init();
+	r = cris_bound_b(-1, 0xff);
+	cris_tst_cc(0, 0, 0, 0);
+	if (r != 0xff)
+		err();
+
+	cris_tst_cc_init();
+	r = cris_bound_b(0xff, 0xff);
+	cris_tst_cc(0, 0, 0, 0);
+	if (r != 0xff)
+		err();
+
+	cris_tst_cc_init();
+	r = cris_bound_b(0xfeda49ff, 0xff);
+	cris_tst_cc(0, 0, 0, 0);
+	if (r != 0xff)
+		err();
+
+	cris_tst_cc_init();
+	r = cris_bound_b(0x78134452, 0x89);
+	cris_tst_cc(0, 0, 0, 0);
+	if (r != 0x89)
+		err();
+
+	cris_tst_cc_init();
+	r = cris_bound_w(0x78134452, 0);
+	cris_tst_cc(0, 1, 0, 0);
+	if (r != 0)
+		err();
+
+	cris_tst_cc_init();
+	r = cris_bound_b(0xffff, -1);
+	cris_tst_cc(0, 0, 0, 0);
+	if (r != 0xff)
+		err();
+
+	pass();
+	return 0;
+}
diff --git a/tests/tcg/cris/check_boundc.s b/tests/tcg/cris/check_boundc.s
new file mode 100644
index 0000000..fb9e5bc
--- /dev/null
+++ b/tests/tcg/cris/check_boundc.s
@@ -0,0 +1,101 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n5432f789\n2\nffff\n2\nffff\nffff\nf789\n2\n2\nff\nff\nff\n89\n0\nff\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ bound.d 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ bound.d 0xffffffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ bound.d 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r3
+ bound.d 0xffffffff,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ bound.d 0x5432f789,r3
+ test_move_cc 0 0 0 0
+ checkr3 5432f789
+
+ moveq -1,r3
+ bound.w 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq -1,r3
+ bound.w 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq 2,r3
+ bound.w 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ bound.w 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0xfedaffff,r3
+ bound.w 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0x78134452,r3
+ bound.w 0xf789,r3
+ test_move_cc 0 0 0 0
+ checkr3 f789
+
+ moveq -1,r3
+ bound.b 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ bound.b 0xff,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq -1,r3
+ bound.b 0xff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0xff,r3
+ bound.b 0xff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0xfeda49ff,r3
+ bound.b 0xff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0x78134452,r3
+ bound.b 0x89,r3
+ test_move_cc 0 0 0 0
+ checkr3 89
+
+ bound.w 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xffff,r3
+ bound.b -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ quit
diff --git a/tests/tcg/cris/check_boundr.s b/tests/tcg/cris/check_boundr.s
new file mode 100644
index 0000000..5c50cc5
--- /dev/null
+++ b/tests/tcg/cris/check_boundr.s
@@ -0,0 +1,125 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n5432f789\n2\n2\nffff\nffff\nffff\nf789\n2\n2\nff\nff\n89\nfeda4953\nfeda4962\n0\n0\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ bound.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ moveq -1,r4
+ bound.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ bound.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r4
+ move.d r4,r3
+ bound.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ bound.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5432f789
+
+ moveq -1,r3
+ moveq 2,r4
+ bound.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ moveq -1,r4
+ bound.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq -1,r3
+ bound.w r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ bound.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0xfedaffff,r4
+ move.d r4,r3
+ bound.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ bound.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 f789
+
+ moveq -1,r3
+ moveq 2,r4
+ bound.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ moveq -1,r4
+ bound.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xff,r4
+ move.d r4,r3
+ bound.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0xfeda49ff,r4
+ move.d r4,r3
+ bound.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ bound.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 89
+
+ move.d 0xfeda4956,r3
+ move.d 0xfeda4953,r4
+ bound.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 feda4953
+
+ move.d 0xfeda4962,r3
+ move.d 0xfeda4963,r4
+ bound.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 feda4962
+
+ move.d 0xfeda4956,r3
+ move.d 0,r4
+ bound.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xfeda4956,r4
+ move.d 0,r3
+ bound.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_btst.s b/tests/tcg/cris/check_btst.s
new file mode 100644
index 0000000..e39fc8f
--- /dev/null
+++ b/tests/tcg/cris/check_btst.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1111\n
+
+ .include "testutils.inc"
+ start
+ clearf nzvc
+ moveq -1,r3
+ .if 1 ;..asm.arch.cris.v32
+ .else
+ setf vc
+ .endif
+ btstq 0,r3
+ test_cc 1 0 0 0
+
+ moveq 2,r3
+ btstq 1,r3
+ test_cc 1 0 0 0
+
+ moveq 4,r3
+ btstq 1,r3
+ test_cc 0 1 0 0
+
+ moveq -1,r3
+ btstq 31,r3
+ test_cc 1 0 0 0
+
+ move.d 0x5a67f19f,r3
+ btstq 12,r3
+ test_cc 1 0 0 0
+
+ move.d 0xda67f19f,r3
+ move.d 29,r4
+ btst r4,r3
+ test_cc 0 0 0 0
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ move.d 0xda67f191,r3
+ move.d 33,r4
+ btst r4,r3
+ test_cc 0 0 0 0
+
+ moveq -1,r3
+ moveq 0,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ moveq 2,r3
+ moveq 1,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ moveq -1,r3
+ moveq 31,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ moveq 4,r3
+ btstq 1,r3
+ test_cc 0 1 0 0
+
+ moveq -1,r3
+ moveq 15,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ move.d 0x5a678000,r3
+ moveq 11,r4
+ btst r4,r3
+ test_cc 0 1 0 0
+
+ move.d 0x5a67f19f,r3
+ btst r3,r3
+ test_cc 0 0 0 0
+
+ move.d 0x1111,r3
+ checkr3 1111
+
+ ; check that X gets cleared and that only the NZ flags are touched.
+ move.d	0xff, $r0
+ move $r0, $ccs
+ btst r3,r3
+ move $ccs, $r0
+ and.d 0xff, $r0
+ cmp.d	0xe3, $r0
+ test_cc 0 1 0 0
+
+ quit
diff --git a/tests/tcg/cris/check_clearfv32.s b/tests/tcg/cris/check_clearfv32.s
new file mode 100644
index 0000000..4e91360
--- /dev/null
+++ b/tests/tcg/cris/check_clearfv32.s
@@ -0,0 +1,19 @@
+# mach: crisv32
+# output: ef\nef\n
+
+; Check that "clearf x" doesn't trivially fail.
+
+ .include "testutils.inc"
+ start
+ setf puixnzvc
+ clearf x	; Actually, x would be cleared by almost-all other insns.
+ move ccs,r3
+ and.d 0xff, $r3
+ checkr3 ef
+
+ setf puixnzvc
+ moveq 0, $r3	; moveq should only clear the xflag.
+ move ccs,r3
+ and.d 0xff, $r3
+ checkr3 ef
+ quit
diff --git a/tests/tcg/cris/check_clrjmp1.s b/tests/tcg/cris/check_clrjmp1.s
new file mode 100644
index 0000000..45a7005
--- /dev/null
+++ b/tests/tcg/cris/check_clrjmp1.s
@@ -0,0 +1,36 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffff00\n
+
+; A bug resulting in a non-effectual clear.b discovered running the GCC
+; testsuite; jump actually wrote to p0.
+
+ .include "testutils.inc"
+
+ start
+ jump 1f
+ nop
+ .p2align 8
+1:
+ move.d y,r4
+
+ .if 0 ;0 == ..asm.arch.cris.v32
+; There was a bug causing this insn to set special register p0
+; (byte-clear) to 8 (low 8 bits of location after insn).
+ jump [r4+]
+ .endif
+
+1:
+ move.d 0f,r4
+
+; The corresponding bug would cause this insn too, to set p0.
+ jump r4
+ nop
+ quit
+0:
+ moveq -1,r3
+ clear.b r3
+ checkr3 ffffff00
+ quit
+
+y:
+ .dword 1b
diff --git a/tests/tcg/cris/check_cmp-2.s b/tests/tcg/cris/check_cmp-2.s
new file mode 100644
index 0000000..414d370
--- /dev/null
+++ b/tests/tcg/cris/check_cmp-2.s
@@ -0,0 +1,15 @@
+
+
+.include "testutils.inc"
+
+	start
+
+	move.d	4294967283, $r0
+	move.d	$r0, $r10
+	cmp.d	$r0, $r10
+	beq	1f
+	move.d $r10, $r3
+	fail
+1:
+	pass
+	quit
diff --git a/tests/tcg/cris/check_cmpc.s b/tests/tcg/cris/check_cmpc.s
new file mode 100644
index 0000000..267c9ba
--- /dev/null
+++ b/tests/tcg/cris/check_cmpc.s
@@ -0,0 +1,86 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n2\nffff\nffffffff\n78134452\nffffffff\n2\nffff\nfedaffff\n78134452\nffffffff\n2\nff\nfeda49ff\n78134452\n85649282\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ cmp.d -2,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.d 1,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmp.d -0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ moveq -1,r3
+ cmp.d 1,r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ cmp.d -0x5432f789,r3
+ test_cc 1 0 1 1
+ checkr3 78134452
+
+ moveq -1,r3
+ cmp.w -2,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.w 1,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmp.w 1,r3
+ test_cc 1 0 0 0
+ checkr3 ffff
+
+ move.d 0xfedaffff,r3
+ cmp.w 1,r3
+ test_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d 0x78134452,r3
+ cmp.w 0x877,r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ moveq -1,r3
+ cmp.b -2,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.b 1,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xff,r3
+ cmp.b 1,r3
+ test_cc 1 0 0 0
+ checkr3 ff
+
+ move.d 0xfeda49ff,r3
+ cmp.b 1,r3
+ test_cc 1 0 0 0
+ checkr3 feda49ff
+
+ move.d 0x78134452,r3
+ cmp.b 0x77,r3
+ test_cc 1 0 0 1
+ checkr3 78134452
+
+ move.d 0x85649282,r3
+ cmp.b 0x82,r3
+ test_cc 0 1 0 0
+ checkr3 85649282
+
+ quit
diff --git a/tests/tcg/cris/check_cmpm.s b/tests/tcg/cris/check_cmpm.s
new file mode 100644
index 0000000..e4dde15
--- /dev/null
+++ b/tests/tcg/cris/check_cmpm.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n2\nffff\nffffffff\n78134452\nffffffff\n2\nffff\nfedaffff\n78134452\nffffffff\n2\nff\nfeda49ff\n78134452\n85649222\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword -2,1,-0xffff,1,-0x5432f789
+ .word -2,1,1,0x877
+ .byte -2,1,0x77
+ .byte 0x22
+
+ start
+ moveq -1,r3
+ move.d x,r5
+ cmp.d [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.d [r5],r3
+ test_cc 0 0 0 0
+ addq 4,r5
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmp.d [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ moveq -1,r3
+ cmp.d [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ cmp.d [r5+],r3
+ test_cc 1 0 1 1
+ checkr3 78134452
+
+ moveq -1,r3
+ cmp.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmp.w [r5],r3
+ test_cc 1 0 0 0
+ checkr3 ffff
+
+ move.d 0xfedaffff,r3
+ cmp.w [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d 0x78134452,r3
+ cmp.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ moveq -1,r3
+ cmp.b [r5],r3
+ test_cc 0 0 0 0
+ addq 1,r5
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xff,r3
+ cmp.b [r5],r3
+ test_cc 1 0 0 0
+ checkr3 ff
+
+ move.d 0xfeda49ff,r3
+ cmp.b [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 feda49ff
+
+ move.d 0x78134452,r3
+ cmp.b [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 78134452
+
+ move.d 0x85649222,r3
+ cmp.b [r5],r3
+ test_cc 0 1 0 0
+ checkr3 85649222
+
+ quit
diff --git a/tests/tcg/cris/check_cmpq.s b/tests/tcg/cris/check_cmpq.s
new file mode 100644
index 0000000..5469141
--- /dev/null
+++ b/tests/tcg/cris/check_cmpq.s
@@ -0,0 +1,75 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1\n1f\n1f\nffffffe1\nffffffe1\nffffffe0\n0\n0\nffffffff\nffffffff\n10000\n100\n5678900\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ cmpq 1,r3
+ test_cc 0 1 0 0
+ checkr3 1
+
+ cmpq -1,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ cmpq 31,r3
+ test_cc 1 0 0 1
+ checkr3 1
+
+ moveq 31,r3
+ cmpq 31,r3
+ test_cc 0 1 0 0
+ checkr3 1f
+
+ cmpq -31,r3
+ test_cc 0 0 0 1
+ checkr3 1f
+
+ movs.b -31,r3
+ cmpq -31,r3
+ test_cc 0 1 0 0
+ checkr3 ffffffe1
+
+ cmpq -32,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffe1
+
+ movs.b -32,r3
+ cmpq -32,r3
+ test_cc 0 1 0 0
+ checkr3 ffffffe0
+
+ moveq 0,r3
+ cmpq 1,r3
+ test_cc 1 0 0 1
+ checkr3 0
+
+ cmpq -32,r3
+ test_cc 0 0 0 1
+ checkr3 0
+
+ moveq -1,r3
+ cmpq 1,r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ cmpq -1,r3
+ test_cc 0 1 0 0
+ checkr3 ffffffff
+
+ move.d 0x10000,r3
+ cmpq 1,r3
+ test_cc 0 0 0 0
+ checkr3 10000
+
+ move.d 0x100,r3
+ cmpq 1,r3
+ test_cc 0 0 0 0
+ checkr3 100
+
+ move.d 0x5678900,r3
+ cmpq 7,r3
+ test_cc 0 0 0 0
+ checkr3 5678900
+
+ quit
diff --git a/tests/tcg/cris/check_cmpr.s b/tests/tcg/cris/check_cmpr.s
new file mode 100644
index 0000000..b30af7a
--- /dev/null
+++ b/tests/tcg/cris/check_cmpr.s
@@ -0,0 +1,102 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n2\nffff\nffffffff\n78134452\nffffffff\n2\nffff\nfedaffff\n78134452\nffffffff\n2\nff\nfeda49ff\n78134452\n85649222\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq -2,r4
+ cmp.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ cmp.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ move.d -0xffff,r4
+ cmp.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ moveq 1,r4
+ moveq -1,r3
+ cmp.d r4,r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ cmp.d r4,r3
+ test_cc 1 0 1 1
+ checkr3 78134452
+
+ moveq -1,r3
+ moveq -2,r4
+ cmp.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ cmp.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ move.d -0xffff,r4
+ cmp.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 ffff
+
+ move.d 0xfedaffff,r3
+ move.d -0xfedaffff,r4
+ cmp.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ cmp.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ moveq -1,r3
+ moveq -2,r4
+ cmp.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ cmp.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d -0xff,r4
+ move.d 0xff,r3
+ cmp.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 ff
+
+ move.d -0xfeda49ff,r4
+ move.d 0xfeda49ff,r3
+ cmp.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 feda49ff
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ cmp.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 78134452
+
+ move.d 0x85649222,r3
+ move.d 0x77445622,r4
+ cmp.b r4,r3
+ test_cc 0 1 0 0
+ checkr3 85649222
+
+ quit
diff --git a/tests/tcg/cris/check_cmpxc.s b/tests/tcg/cris/check_cmpxc.s
new file mode 100644
index 0000000..b237a93
--- /dev/null
+++ b/tests/tcg/cris/check_cmpxc.s
@@ -0,0 +1,92 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\n2\n2\nffff\nffff\nffff\nffff\nffffffff\nffffffff\nffffffff\n78134452\n78134452\n78134452\n78134452\n4452\n80000032\n
+
+ .include "testutils.inc"
+ start
+ moveq 2,r3
+ cmps.b 0xff,r3
+ test_cc 0 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ cmps.w 0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ cmpu.b 0xff,r3
+ test_cc 1 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ move.d 0xffffffff,r4
+ cmpu.w -1,r3
+ test_cc 1 0 0 1
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmpu.b -1,r3
+ test_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmpu.w -1,r3
+ test_cc 0 1 0 0
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmps.b 0xff,r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmps.w 0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ moveq -1,r3
+ cmps.b 0xff,r3
+ test_cc 0 1 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ cmps.w 0xff,r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ cmps.w 0xffff,r3
+ test_cc 0 1 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ cmpu.b 0x89,r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmps.b 0x89,r3
+ test_cc 0 0 0 1
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmpu.w 0xf789,r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmps.w 0xf789,r3
+ test_cc 0 0 0 1
+ checkr3 78134452
+
+ move.d 0x4452,r3
+ cmps.w 0x8002,r3
+ test_cc 0 0 0 1
+ checkr3 4452
+
+ move.d 0x80000032,r3
+ cmpu.w 0x764,r3
+ test_cc 0 0 1 0
+ checkr3 80000032
+
+ quit
diff --git a/tests/tcg/cris/check_cmpxm.s b/tests/tcg/cris/check_cmpxm.s
new file mode 100644
index 0000000..87ea5bf
--- /dev/null
+++ b/tests/tcg/cris/check_cmpxm.s
@@ -0,0 +1,106 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\n2\n2\nffff\nffff\nffff\nffff\nffffffff\nffffffff\nffffffff\n78134452\n78134452\n78134452\n78134452\n4452\n80000032\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .byte 0xff
+ .word 0xffff
+ .word 0xff
+ .word 0xffff
+ .byte 0x89
+ .word 0xf789
+ .word 0x8002
+ .word 0x764
+
+ start
+ moveq 2,r3
+ move.d x,r5
+ cmps.b [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ cmps.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ subq 3,r5
+ cmpu.b [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ cmpu.w [r5+],r3
+ test_cc 1 0 0 1
+ subq 3,r5
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmpu.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmpu.w [r5],r3
+ test_cc 0 1 0 0
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmps.b [r5],r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmps.w [r5],r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ moveq -1,r3
+ cmps.b [r5],r3
+ test_cc 0 1 0 0
+ addq 3,r5
+ checkr3 ffffffff
+
+ moveq -1,r3
+ cmps.w [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ cmps.w [r5+],r3
+ test_cc 0 1 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ cmpu.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmps.b [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmpu.w [r5],r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmps.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 78134452
+
+ move.d 0x4452,r3
+ cmps.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 4452
+
+ move.d 0x80000032,r3
+ cmpu.w [r5+],r3
+ test_cc 0 0 1 0
+ checkr3 80000032
+
+ quit
diff --git a/tests/tcg/cris/check_dstep.s b/tests/tcg/cris/check_dstep.s
new file mode 100644
index 0000000..bd43b83
--- /dev/null
+++ b/tests/tcg/cris/check_dstep.s
@@ -0,0 +1,42 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: fffffffc\n4\nffff\nfffffffe\n9bf3911b\n0\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ dstep r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffffc
+
+ moveq 2,r3
+ moveq -1,r4
+ dstep r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 4
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ dstep r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r4
+ move.d r4,r3
+ dstep r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ dstep r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 9bf3911b
+
+ move.d 0xffff,r3
+ move.d 0x1fffe,r4
+ dstep r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_ftag.c b/tests/tcg/cris/check_ftag.c
new file mode 100644
index 0000000..908773a
--- /dev/null
+++ b/tests/tcg/cris/check_ftag.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+static inline void cris_ftag_i(unsigned int x)
+{
+	register unsigned int v asm("$r10") = x;
+	asm ("ftagi\t[%0]\n" : : "r" (v) );
+}
+static inline void cris_ftag_d(unsigned int x)
+{
+	register unsigned int v asm("$r10") = x;
+	asm ("ftagd\t[%0]\n" : : "r" (v) );
+}
+static inline void cris_fidx_i(unsigned int x)
+{
+	register unsigned int v asm("$r10") = x;
+	asm ("fidxi\t[%0]\n" : : "r" (v) );
+}
+static inline void cris_fidx_d(unsigned int x)
+{
+	register unsigned int v asm("$r10") = x;
+	asm ("fidxd\t[%0]\n" : : "r" (v) );
+}
+
+
+int main(void)
+{
+	cris_ftag_i(0);
+	cris_ftag_d(0);
+	cris_fidx_i(0);
+	cris_fidx_d(0);
+	pass();
+	return 0;
+}
diff --git a/tests/tcg/cris/check_gcctorture_pr28634-1.c b/tests/tcg/cris/check_gcctorture_pr28634-1.c
new file mode 100644
index 0000000..45ecd15
--- /dev/null
+++ b/tests/tcg/cris/check_gcctorture_pr28634-1.c
@@ -0,0 +1,15 @@
+/* PR rtl-optimization/28634.  On targets with delayed branches,
+   dbr_schedule could do the next iteration's addition in the
+   branch delay slot, then subtract the value again if the branch
+   wasn't taken.  This can lead to rounding errors.  */
+int x = -1;
+int y = 1;
+int
+main (void)
+{
+  while (y > 0)
+    y += x;
+  if (y != x + 1)
+    abort ();
+  exit (0);
+}
diff --git a/tests/tcg/cris/check_gcctorture_pr28634.c b/tests/tcg/cris/check_gcctorture_pr28634.c
new file mode 100644
index 0000000..a0c5254
--- /dev/null
+++ b/tests/tcg/cris/check_gcctorture_pr28634.c
@@ -0,0 +1,15 @@
+/* PR rtl-optimization/28634.  On targets with delayed branches,
+   dbr_schedule could do the next iteration's addition in the
+   branch delay slot, then subtract the value again if the branch
+   wasn't taken.  This can lead to rounding errors.  */
+double x = -0x1.0p53;
+double y = 1;
+int
+main (void)
+{
+  while (y > 0)
+    y += x;
+  if (y != x + 1)
+    abort ();
+  exit (0);
+}
diff --git a/tests/tcg/cris/check_glibc_kernelversion.c b/tests/tcg/cris/check_glibc_kernelversion.c
new file mode 100644
index 0000000..0744872
--- /dev/null
+++ b/tests/tcg/cris/check_glibc_kernelversion.c
@@ -0,0 +1,116 @@
+/*
+ * Check the lz insn.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+
+#define __LINUX_KERNEL_VERSION 131584
+
+#define DL_SYSDEP_OSCHECK(FATAL) \
+  do {                                                                        \
+    /* Test whether the kernel is new enough.  This test is only              \
+       performed if the library is not compiled to run on all                 \
+       kernels.  */                                                           \
+    if (__LINUX_KERNEL_VERSION > 0)                                           \
+      {                                                                       \
+        char bufmem[64];                                                      \
+        char *buf = bufmem;                                                   \
+        unsigned int version;                                                 \
+        int parts;                                                            \
+        char *cp;                                                             \
+        struct utsname uts;                                                   \
+                                                                              \
+        /* Try the uname syscall */                                           \
+        if (__uname (&uts))                                                   \
+          {                                                                   \
+            /* This was not successful.  Now try reading the /proc            \
+               filesystem.  */                                                \
+            ssize_t reslen;                                                   \
+            int fd = __open ("/proc/sys/kernel/osrelease", O_RDONLY);         \
+            if (fd == -1                                                      \
+                || (reslen = __read (fd, bufmem, sizeof (bufmem))) <= 0)      \
+              /* This also didn't work.  We give up since we cannot           \
+                 make sure the library can actually work.  */                 \
+              FATAL ("FATAL: cannot determine library version\n");            \
+            __close (fd);                                                     \
+            buf[MIN (reslen, (ssize_t) sizeof (bufmem) - 1)] = '\0';          \
+          }                                                                   \
+        else                                                                  \
+          buf = uts.release;                                                  \
+                                                                              \
+        /* Now convert it into a number.  The string consists of at most      \
+           three parts.  */                                                   \
+        version = 0;                                                          \
+        parts = 0;                                                            \
+        cp = buf;                                                             \
+        while ((*cp >= '0') && (*cp <= '9'))                                  \
+          {                                                                   \
+            unsigned int here = *cp++ - '0';                                  \
+                                                                              \
+            while ((*cp >= '0') && (*cp <= '9'))                              \
+              {                                                               \
+                here *= 10;                                                   \
+                here += *cp++ - '0';                                          \
+              }                                                               \
+                                                                              \
+            ++parts;                                                          \
+            version <<= 8;                                                    \
+            version |= here;                                                  \
+                                                                              \
+            if (*cp++ != '.')                                                 \
+              /* Another part following?  */                                  \
+              break;                                                          \
+          }                                                                   \
+                                                                              \
+        if (parts < 3)                                                        \
+          version <<= 8 * (3 - parts);                                        \
+                                                                              \
+        /* Now we can test with the required version.  */                     \
+        if (version < __LINUX_KERNEL_VERSION)                                 \
+          /* Not sufficient.  */                                               \
+          FATAL ("FATAL: kernel too old\n");                                  \
+                                                                              \
+        _dl_osversion = version;                                              \
+      }                                                                       \
+  } while (0)
+
+int main(void)
+{
+        char bufmem[64] = "2.6.22";
+        char *buf = bufmem;
+        unsigned int version;
+        int parts;
+        char *cp;
+
+        version = 0;
+        parts = 0;
+        cp = buf;
+        while ((*cp >= '0') && (*cp <= '9'))
+          {
+            unsigned int here = *cp++ - '0';
+
+            while ((*cp >= '0') && (*cp <= '9'))
+              {
+                here *= 10;
+                here += *cp++ - '0';
+              }
+
+            ++parts;
+            version <<= 8;
+            version |= here;
+
+            if (*cp++ != '.')
+              /* Another part following?  */
+              break;
+          }
+
+        if (parts < 3)
+          version <<= 8 * (3 - parts);
+	if (version < __LINUX_KERNEL_VERSION)
+		err();
+	pass();
+	exit(0);
+}
diff --git a/tests/tcg/cris/check_hello.c b/tests/tcg/cris/check_hello.c
new file mode 100644
index 0000000..fb403ba
--- /dev/null
+++ b/tests/tcg/cris/check_hello.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include <stdlib.h>
+int main ()
+{
+  printf ("pass\n");
+  exit (0);
+}
diff --git a/tests/tcg/cris/check_int64.c b/tests/tcg/cris/check_int64.c
new file mode 100644
index 0000000..fc60017
--- /dev/null
+++ b/tests/tcg/cris/check_int64.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+
+static inline int64_t add64(const int64_t a, const int64_t b)
+{
+	return a + b;
+}
+
+static inline int64_t sub64(const int64_t a, const int64_t b)
+{
+	return a - b;
+}
+
+int main(void)
+{
+	int64_t a = 1;
+	int64_t b = 2;
+
+	/* FIXME: add some tests.  */
+	a = add64(a, b);
+	if (a != 3)
+		err();
+
+	a = sub64(a, b);
+	if (a != 1)
+		err();
+
+	a = add64(a, -4);
+	if (a != -3)
+		err();
+
+	a = add64(a, 3);
+	if (a != 0)
+		err();
+
+	a = 0;
+	a = sub64(a, 1);
+	if (a != -1)
+		err();
+
+	pass();
+	return 0;
+}
diff --git a/tests/tcg/cris/check_jsr.s b/tests/tcg/cris/check_jsr.s
new file mode 100644
index 0000000..1060237
--- /dev/null
+++ b/tests/tcg/cris/check_jsr.s
@@ -0,0 +1,85 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 0\n0\n0\n0\n0\n0\n
+
+# Test that jsr Rn and jsr [PC+] work.
+
+ .include "testutils.inc"
+ start
+x:
+ move.d 0f,r6
+ setf nzvc
+ jsr r6
+ .if 1; ..asm.arch.cris.v32
+ nop
+ .endif
+0:
+ test_move_cc 1 1 1 1
+ move srp,r3
+ sub.d 0b,r3
+ checkr3 0
+
+ move.d 1f,r0
+ setf nzvc
+ jsr r0
+ .if 1 ; ..asm.arch.cris.v32
+ moveq 0,r0
+ .endif
+6:
+ nop
+ quit
+
+2:
+ test_move_cc 0 0 0 0
+ move srp,r3
+ sub.d 3f,r3
+ checkr3 0
+ jsr 4f
+ .if 1 ; ..asm.arch.cris.v32
+ nop
+ .endif
+7:
+ nop
+ quit
+
+8:
+ move srp,r3
+ sub.d 7b,r3
+ checkr3 0
+ quit
+
+4:
+ move srp,r3
+ sub.d 7b,r3
+ checkr3 0
+ move.d 5f,r3
+ jump r3
+ .if 1; ..asm.arch.cris.v32
+ moveq 0,r3
+ .endif
+ quit
+
+ .space 32770,0
+1:
+ test_move_cc 1 1 1 1
+ move srp,r3
+ sub.d 6b,r3
+ checkr3 0
+
+ clearf cznv
+ jsr 2b
+ .if 1; ..asm.arch.cris.v32
+ nop
+ .endif
+3:
+
+ quit
+
+5:
+ move srp,r3
+ sub.d 7b,r3
+ checkr3 0
+ jump 8b
+ .if 1 ; ..asm.arch.cris.v32
+ nop
+ .endif
+ quit
diff --git a/tests/tcg/cris/check_lapc.s b/tests/tcg/cris/check_lapc.s
new file mode 100644
index 0000000..9a6150b
--- /dev/null
+++ b/tests/tcg/cris/check_lapc.s
@@ -0,0 +1,78 @@
+# mach: crisv32
+# output: 0\n0\nfffffffa\nfffffffe\nffffffda\n1e\n1e\n0\n
+
+.include "testutils.inc"
+
+; To accommodate dumpr3 with more than one instruction, keep it
+; out of lapc operand ranges and difference calculations.
+
+ start
+ lapc.d 0f,r3
+0:
+ sub.d .,r3
+ checkr3 0
+
+ lapcq 0f,r3
+0:
+ sub.d .,r3
+ checkr3 0
+
+ lapc.d .,r3
+ sub.d .,r3
+ checkr3 fffffffa
+
+ lapcq .,r3
+ sub.d .,r3
+ checkr3 fffffffe
+
+0:
+ .rept 16
+ nop
+ .endr
+ lapc.d 0b,r3
+ sub.d .,r3
+ checkr3 ffffffda
+
+ setf zcvn
+ lapc.d 0f,r3
+ test_cc 1 1 1 1
+ sub.d .,r3
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+0:
+ checkr3 1e
+0:
+ lapcq 0f,r3
+ sub.d 0b,r3
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+0:
+ checkr3 1e
+ clearf cn
+ setf zv
+1:
+ lapcq .,r3
+ test_cc 0 1 1 0
+ sub.d 1b,r3
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_lsl.s b/tests/tcg/cris/check_lsl.s
new file mode 100644
index 0000000..9e2ddd7
--- /dev/null
+++ b/tests/tcg/cris/check_lsl.s
@@ -0,0 +1,217 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n4\n80000000\nffff8000\n7f19f000\n80000000\n0\n0\n699fc67c\nffffffff\n4\n80000000\nffff8000\n7f19f000\nda670000\nda670000\nda670000\nda67c67c\nffffffff\nfffafffe\n4\nffff0000\nffff8000\n5a67f000\nda67f100\nda67f100\nda67f100\nda67f17c\nfff3faff\nfff3fafe\n4\nffffff00\nffffff00\nffffff80\n5a67f100\n5a67f1f0\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ lslq 0,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ lslq 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 4
+
+ moveq -1,r3
+ lslq 31,r3
+ test_move_cc 1 0 0 0
+ checkr3 80000000
+
+ moveq -1,r3
+ lslq 15,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff8000
+
+ move.d 0x5a67f19f,r3
+ lslq 12,r3
+ test_move_cc 0 0 0 0
+ checkr3 7f19f000
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsl.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 80000000
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsl.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsl.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsl.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 699fc67c
+
+ moveq -1,r3
+ moveq 0,r4
+ lsl.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ lsl.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 4
+
+ moveq -1,r3
+ moveq 31,r4
+ lsl.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 80000000
+
+ moveq -1,r3
+ moveq 15,r4
+ lsl.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff8000
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsl.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 7f19f000
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsl.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsl.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsl.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsl.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67c67c
+
+ moveq -1,r3
+ moveq 0,r4
+ lsl.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0xfffaffff,r3
+ moveq 1,r4
+ lsl.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffafffe
+
+ moveq 2,r3
+ moveq 1,r4
+ lsl.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 4
+
+ moveq -1,r3
+ moveq 31,r4
+ lsl.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffff0000
+
+ moveq -1,r3
+ moveq 15,r4
+ lsl.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff8000
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsl.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 5a67f000
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsl.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 da67f17c
+
+ move.d 0xfff3faff,r3
+ moveq 0,r4
+ lsl.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fff3faff
+
+ move.d 0xfff3faff,r3
+ moveq 1,r4
+ lsl.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fff3fafe
+
+ moveq 2,r3
+ moveq 1,r4
+ lsl.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 4
+
+ moveq -1,r3
+ moveq 31,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffffff00
+
+ moveq -1,r3
+ moveq 15,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffffff00
+
+ moveq -1,r3
+ moveq 7,r4
+ lsl.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffff80
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 5a67f100
+
+ move.d 0x5a67f19f,r3
+ moveq 4,r4
+ lsl.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 5a67f1f0
+
+ quit
diff --git a/tests/tcg/cris/check_lsr.s b/tests/tcg/cris/check_lsr.s
new file mode 100644
index 0000000..18fdbef
--- /dev/null
+++ b/tests/tcg/cris/check_lsr.s
@@ -0,0 +1,218 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n1\n1\n1ffff\n5a67f\n1\n0\n0\n3699fc67\nffffffff\n1\n1\n1ffff\n5a67f\nda670000\nda670000\nda670000\nda673c67\nffffffff\nffff7fff\n1\nffff0000\nffff0001\n5a67000f\nda67f100\nda67f100\nda67f100\nda67f127\nffffffff\nffffff7f\n1\nffffff00\nffffff00\nffffff01\n5a67f100\n5a67f109\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ lsrq 0,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ lsrq 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ lsrq 31,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ lsrq 15,r3
+ test_move_cc 0 0 0 0
+ checkr3 1ffff
+
+ move.d 0x5a67f19f,r3
+ lsrq 12,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67f
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsr.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsr.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3699fc67
+
+ moveq -1,r3
+ moveq 0,r4
+ lsr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 31,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 15,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1ffff
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67f
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsr.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsr.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsr.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 da673c67
+
+ moveq -1,r3
+ moveq 0,r4
+ lsr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 1,r4
+ lsr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff7fff
+
+ moveq 2,r3
+ moveq 1,r4
+ lsr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+;; FIXME: this was wrong. Z should be set.
+ moveq -1,r3
+ moveq 31,r4
+ lsr.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffff0000
+
+ moveq -1,r3
+ moveq 15,r4
+ lsr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0001
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67000f
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 da67f127
+
+ moveq -1,r3
+ moveq 0,r4
+ lsr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 1,r4
+ lsr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff7f
+
+ moveq 2,r3
+ moveq 1,r4
+ lsr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 31,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffffff00
+
+ moveq -1,r3
+ moveq 15,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffffff00
+
+ moveq -1,r3
+ moveq 7,r4
+ lsr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff01
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 5a67f100
+
+ move.d 0x5a67f19f,r3
+ moveq 4,r4
+ lsr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67f109
+
+ quit
diff --git a/tests/tcg/cris/check_lz.c b/tests/tcg/cris/check_lz.c
new file mode 100644
index 0000000..69c2e6d
--- /dev/null
+++ b/tests/tcg/cris/check_lz.c
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+
+static inline int cris_lz(int x)
+{
+	int r;
+	asm ("lz\t%1, %0\n" : "=r" (r) : "r" (x));
+	return r;
+}
+
+void check_lz(void)
+{
+	int i;
+
+	if (cris_lz(0) != 32)
+		err();
+	if (cris_lz(1) != 31)
+		err();
+	if (cris_lz(2) != 30)
+		err();
+	if (cris_lz(4) != 29)
+		err();
+	if (cris_lz(8) != 28)
+		err();
+
+	/* try all positions with a single bit.  */
+	for (i = 1; i < 32; i++) {
+		if (cris_lz(1 << (i-1)) != (32 - i))
+			err();
+	}
+
+	/* try all positions with all bits.  */
+	for (i = 1; i < 32; i++) {
+		/* split up this computation to clarify it.  */
+		uint32_t val;
+		val = (unsigned int)-1 >> (32 - i);
+		if (cris_lz(val) != (32 - i))
+			err();
+	}
+}
+
+int main(void)
+{
+	check_lz();
+	pass();
+	exit(0);
+}
diff --git a/tests/tcg/cris/check_mapbrk.c b/tests/tcg/cris/check_mapbrk.c
new file mode 100644
index 0000000..1aff762
--- /dev/null
+++ b/tests/tcg/cris/check_mapbrk.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Basic sanity check that syscalls to implement malloc (brk, mmap2,
+   munmap) are trivially functional.  */
+
+int main ()
+{
+  void *p1, *p2, *p3, *p4, *p5, *p6;
+
+  if ((p1 = malloc (8100)) == NULL
+      || (p2 = malloc (16300)) == NULL
+      || (p3 = malloc (4000)) == NULL
+      || (p4 = malloc (500)) == NULL
+      || (p5 = malloc (1023*1024)) == NULL
+      || (p6 = malloc (8191*1024)) == NULL)
+  {
+    printf ("fail\n");
+    exit (1);
+  }
+
+  free (p1);
+  free (p2);
+  free (p3);
+  free (p4);
+  free (p5);
+  free (p6);
+
+  p1 = malloc (64000);
+  if (p1 == NULL)
+  {
+    printf ("fail\n");
+    exit (1);
+  }
+  free (p1);
+
+  printf ("pass\n");
+  exit (0);
+}
diff --git a/tests/tcg/cris/check_mcp.s b/tests/tcg/cris/check_mcp.s
new file mode 100644
index 0000000..e65ccdd
--- /dev/null
+++ b/tests/tcg/cris/check_mcp.s
@@ -0,0 +1,49 @@
+# mach: crisv32
+# output: fffffffe\n1\n1ffff\nfffffffe\ncc463bdc\n4c463bdc\n0\n
+
+ .include "testutils.inc"
+ start
+
+; Set R, clear C.
+ move 0x100,ccs
+ moveq -5,r3
+ move 2,mof
+ mcp mof,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ moveq 2,r3
+ move -1,srp
+ mcp srp,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move 0xffff,srp
+ move srp,r3
+ mcp srp,r3
+ test_cc 0 0 0 0
+ checkr3 1ffff
+
+ move -1,mof
+ move mof,r3
+ mcp mof,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move 0x5432f789,mof
+ move.d 0x78134452,r3
+ mcp mof,r3
+ test_cc 1 0 1 0
+ checkr3 cc463bdc
+
+ move 0x80000000,srp
+ mcp srp,r3
+ test_cc 0 0 1 0
+ checkr3 4c463bdc
+
+ move 0xb3b9c423,srp
+ mcp srp,r3
+ test_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_mmap1.c b/tests/tcg/cris/check_mmap1.c
new file mode 100644
index 0000000..b803f0c
--- /dev/null
+++ b/tests/tcg/cris/check_mmap1.c
@@ -0,0 +1,48 @@
+/*
+#notarget: cris*-*-elf
+*/
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+int main (int argc, char *argv[])
+{
+  int fd = open (argv[0], O_RDONLY);
+  struct stat sb;
+  int size;
+  void *a;
+  const char *str = "a string you'll only find in the program";
+
+  if (fd == -1)
+    {
+      perror ("open");
+      abort ();
+    }
+
+  if (fstat (fd, &sb) < 0)
+    {
+      perror ("fstat");
+      abort ();
+    }
+
+  size = sb.st_size;
+
+  /* We want to test mmapping a size that isn't exactly a page.  */
+  if ((size & 8191) == 0)
+    size--;
+
+  a = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+
+  if (memmem (a, size, str, strlen (str) + 1) == NULL)
+    abort ();
+
+  printf ("pass\n");
+  exit (0);
+}
diff --git a/tests/tcg/cris/check_mmap2.c b/tests/tcg/cris/check_mmap2.c
new file mode 100644
index 0000000..35139a0
--- /dev/null
+++ b/tests/tcg/cris/check_mmap2.c
@@ -0,0 +1,48 @@
+/*
+#notarget: cris*-*-elf
+*/
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+int main (int argc, char *argv[])
+{
+  int fd = open (argv[0], O_RDONLY);
+  struct stat sb;
+  int size;
+  void *a;
+  const char *str = "a string you'll only find in the program";
+
+  if (fd == -1)
+    {
+      perror ("open");
+      abort ();
+    }
+
+  if (fstat (fd, &sb) < 0)
+    {
+      perror ("fstat");
+      abort ();
+    }
+
+  size = sb.st_size;
+
+  /* We want to test mmapping a size that isn't exactly a page.  */
+  if ((size & 8191) == 0)
+    size--;
+
+  a = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+
+  if (memmem (a, size, str, strlen (str) + 1) == NULL)
+    abort ();
+
+  printf ("pass\n");
+  exit (0);
+}
diff --git a/tests/tcg/cris/check_mmap3.c b/tests/tcg/cris/check_mmap3.c
new file mode 100644
index 0000000..34401fa
--- /dev/null
+++ b/tests/tcg/cris/check_mmap3.c
@@ -0,0 +1,33 @@
+/*
+#notarget: cris*-*-elf
+*/
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+int main (int argc, char *argv[])
+{
+  volatile unsigned char *a;
+
+  /* Check that we can map a non-multiple of a page and still get a full page.  */
+  a = mmap (NULL, 0x4c, PROT_READ | PROT_WRITE | PROT_EXEC,
+	    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  if (a == NULL || a == (unsigned char *) -1)
+    abort ();
+
+  a[0] = 0xbe;
+  a[8191] = 0xef;
+  memset ((char *) a + 1, 0, 8190);
+
+  if (a[0] != 0xbe || a[8191] != 0xef)
+    abort ();
+
+  printf ("pass\n");
+  exit (0);
+}
diff --git a/tests/tcg/cris/check_movdelsr1.s b/tests/tcg/cris/check_movdelsr1.s
new file mode 100644
index 0000000..300cc87
--- /dev/null
+++ b/tests/tcg/cris/check_movdelsr1.s
@@ -0,0 +1,33 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: aa117acd\n
+# output: eeaabb42\n
+
+; Bug with move to special register in delay slot, due to
+; special flush-insn-cache simulator use.  Ordinary move worked;
+; special register caused branch to fail.
+
+ .include "testutils.inc"
+ start
+ move -1,srp
+
+ move.d 0xaa117acd,r1
+ moveq 3,r9
+ cmpq 1,r9
+ bhi 0f
+ move.d r1,r3
+
+ fail
+0:
+ checkr3 aa117acd
+
+ move.d 0xeeaabb42,r1
+ moveq 3,r9
+ cmpq 1,r9
+ bhi 0f
+ move r1,srp
+
+ fail
+0:
+ move srp,r3
+ checkr3 eeaabb42
+ quit
diff --git a/tests/tcg/cris/check_movecr.s b/tests/tcg/cris/check_movecr.s
new file mode 100644
index 0000000..da8ec26
--- /dev/null
+++ b/tests/tcg/cris/check_movecr.s
@@ -0,0 +1,37 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffff42\n94\nffff4321\n9234\n76543210\n76540000\n
+
+; Move constant byte, word, dword to register.  Check that no extension is
+; performed, that only part of the register is set.
+
+ .include "testutils.inc"
+ startnostack
+ moveq -1,r3
+ move.b 0x42,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff42
+
+ moveq 0,r3
+ move.b 0x94,r3
+ test_move_cc 1 0 0 0
+ checkr3 94
+
+ moveq -1,r3
+ move.w 0x4321,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff4321
+
+ moveq 0,r3
+ move.w 0x9234,r3
+ test_move_cc 1 0 0 0
+ checkr3 9234
+
+ move.d 0x76543210,r3
+ test_move_cc 0 0 0 0
+ checkr3 76543210
+
+ move.w 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 76540000
+
+ quit
diff --git a/tests/tcg/cris/check_movei.s b/tests/tcg/cris/check_movei.s
new file mode 100644
index 0000000..bbfa633
--- /dev/null
+++ b/tests/tcg/cris/check_movei.s
@@ -0,0 +1,50 @@
+# mach: crisv32
+# output: fffffffe\n
+# output: fffffffe\n
+
+; Check basic integral-write semantics regarding flags.
+
+ .include "testutils.inc"
+ start
+
+ move.d 0, $r3	
+; A write that works.  Check that flags are set correspondingly.
+ move.d d,r4
+ ;; store to bring it into the tlb with the right prot bits
+ move.d r3,[r4]
+ moveq -2,r5
+ setf c
+ clearf p
+ move.d [r4],r3
+ ax
+ move.d r5,[r4]
+ move.d [r4],r3
+
+ bcc 0f
+ nop
+ fail
+
+0:
+ checkr3 fffffffe
+
+; A write that fails; check flags too.
+ move.d d,r4
+ moveq 23,r5
+ setf p
+ clearf c
+ move.d [r4],r3
+ ax
+ move.d r5,[r4]
+ move.d [r4],r3
+
+ bcs 0f
+ nop
+ fail
+
+0:
+ checkr3 fffffffe
+ quit
+
+ .data
+d:
+ .dword 42424242
diff --git a/tests/tcg/cris/check_movemr.s b/tests/tcg/cris/check_movemr.s
new file mode 100644
index 0000000..88489de
--- /dev/null
+++ b/tests/tcg/cris/check_movemr.s
@@ -0,0 +1,78 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 12345678\n10234567\n12345678\n12344567\n12344523\n76543210\nffffffaa\naa\n9911\nffff9911\n78\n56\n3456\n6712\n
+
+ .include "testutils.inc"
+ start
+
+ .data
+mem1:
+ .dword 0x12345678
+mem2:
+ .word 0x4567
+mem3:
+ .byte 0x23
+ .dword 0x76543210
+ .byte 0xaa,0x11,0x99
+
+ .text
+ move.d mem1,r2
+ move.d [r2],r3
+ test_move_cc 0 0 0 0
+ checkr3 12345678
+
+ move.d mem2,r3
+ move.d [r3],r3
+ test_move_cc 0 0 0 0
+ checkr3 10234567
+
+ move.d mem1,r2
+ move.d [r2+],r3
+ test_move_cc 0 0 0 0
+ checkr3 12345678
+
+ move.w [r2+],r3
+ test_move_cc 0 0 0 0
+ checkr3 12344567
+
+ move.b [r2+],r3
+ test_move_cc 0 0 0 0
+ checkr3 12344523
+
+ move.d [r2+],r3
+ test_move_cc 0 0 0 0
+ checkr3 76543210
+
+ movs.b [r2],r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffaa
+
+ movu.b [r2+],r3
+ test_move_cc 0 0 0 0
+ checkr3 aa
+
+ movu.w [r2],r3
+ test_move_cc 0 0 0 0
+ checkr3 9911
+
+ movs.w [r2+],r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff9911
+
+ move.d mem1,r13
+ movs.b [r13+],r3
+ test_move_cc 0 0 0 0
+ checkr3 78
+
+ movu.b [r13],r3
+ test_move_cc 0 0 0 0
+ checkr3 56
+
+ movs.w [r13+],r3
+ test_move_cc 0 0 0 0
+ checkr3 3456
+
+ movu.w [r13+],r3
+ test_move_cc 0 0 0 0
+ checkr3 6712
+
+ quit
diff --git a/tests/tcg/cris/check_movemrv32.s b/tests/tcg/cris/check_movemrv32.s
new file mode 100644
index 0000000..53950ab
--- /dev/null
+++ b/tests/tcg/cris/check_movemrv32.s
@@ -0,0 +1,96 @@
+# mach: crisv32
+# output: 15\n7\n2\nffff1234\nb\n16\nf\n2\nffffffef\nf\nffff1234\nf\nfffffff4\nd\nfffffff2\n10\nfffffff2\nd\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword 8,9,10,11
+y:
+ .dword -12,13,-14,15,16
+
+ start
+ moveq 7,r0
+ moveq 2,r1
+ move.d 0xffff1234,r2
+ moveq 21,r3
+ move.d x,r4
+ setf zcvn
+ movem r2,[r4+]
+ test_cc 1 1 1 1
+ subq 12,r4
+
+ checkr3 15
+
+ move.d [r4+],r3
+ checkr3 7
+
+ move.d [r4+],r3
+ checkr3 2
+
+ move.d [r4+],r3
+ checkr3 ffff1234
+
+ move.d [r4+],r3
+ checkr3 b
+
+ subq 16,r4
+ moveq 22,r0
+ moveq 15,r1
+ clearf zcvn
+ movem r0,[r4]
+ test_cc 0 0 0 0
+ move.d [r4+],r3
+ checkr3 16
+
+ move.d r1,r3
+ checkr3 f
+
+ move.d [r4+],r3
+ checkr3 2
+
+ subq 8,r4
+ moveq 10,r2
+ moveq -17,r0
+ clearf zc
+ setf vn
+ movem r1,[r4]
+ test_cc 1 0 1 0
+ move.d [r4+],r3
+ checkr3 ffffffef
+
+ move.d [r4+],r3
+ checkr3 f
+
+ move.d [r4+],r3
+ checkr3 ffff1234
+
+ move.d y,r4
+ setf zc
+ clearf vn
+ movem [r4+],r3
+ test_cc 0 1 0 1
+ checkr3 f
+
+ move.d r0,r3
+ checkr3 fffffff4
+
+ move.d r1,r3
+ checkr3 d
+
+ move.d r2,r3
+ checkr3 fffffff2
+
+ move.d [r4],r3
+ checkr3 10
+
+ subq 8,r4
+ setf zcvn
+ movem [r4+],r0
+ test_cc 1 1 1 1
+ move.d r0,r3
+ checkr3 fffffff2
+
+ move.d r1,r3
+ checkr3 d
+
+ quit
diff --git a/tests/tcg/cris/check_moveq.c b/tests/tcg/cris/check_moveq.c
new file mode 100644
index 0000000..80f2dff
--- /dev/null
+++ b/tests/tcg/cris/check_moveq.c
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+#define cris_moveq(dst, src) \
+               asm volatile ("moveq %1, %0\n" : "=r" (dst) : "i" (src));
+
+
+
+int main(void)
+{
+	int t;
+
+	cris_tst_cc_init();
+	asm volatile ("setf\tzvnc\n");
+	cris_moveq(t, 10);
+	cris_tst_cc(1, 1, 1, 1);
+	if (t != 10)
+		err();
+
+	/* make sure moveq doesn't clobber the zflag.  */
+	cris_tst_cc_init();
+	asm volatile ("setf vnc\n");
+	asm volatile ("clearf z\n");
+	cris_moveq(t, 0);
+	cris_tst_cc(1, 0, 1, 1);
+	if (t != 0)
+		err();
+
+	/* make sure moveq doesn't clobber the nflag.
+	   Also check large immediates  */
+	cris_tst_cc_init();
+	asm volatile ("setf zvc\n");
+	asm volatile ("clearf n\n");
+	cris_moveq(t, -31);
+	cris_tst_cc(0, 1, 1, 1);
+	if (t != -31)
+		err();
+
+	cris_tst_cc_init();
+	asm volatile ("setf nzvc\n");
+	cris_moveq(t, 31);
+	cris_tst_cc(1, 1, 1, 1);
+	if (t != 31)
+		err();
+
+	pass();
+	return 0;
+}
diff --git a/tests/tcg/cris/check_mover.s b/tests/tcg/cris/check_mover.s
new file mode 100644
index 0000000..b4db595
--- /dev/null
+++ b/tests/tcg/cris/check_mover.s
@@ -0,0 +1,28 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffff05\nffff0005\n5\nffffff00\n
+
+; Move between registers.  Check that just the subreg is copied.
+
+ .include "testutils.inc"
+ startnostack
+ moveq -30,r3
+ moveq 5,r4
+ move.b r4,r3
+ test_move_cc 0 0 0 0  		; FIXME
+ checkr3 ffffff05
+
+ move.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0005
+
+ move.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq -1,r3
+ moveq 0,r4
+ move.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffffff00
+
+ quit
diff --git a/tests/tcg/cris/check_moverm.s b/tests/tcg/cris/check_moverm.s
new file mode 100644
index 0000000..eabc958
--- /dev/null
+++ b/tests/tcg/cris/check_moverm.s
@@ -0,0 +1,45 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 7823fec2\n10231879\n102318fe\n
+
+ .include "testutils.inc"
+ start
+
+ .data
+mem1:
+ .dword 0x12345678
+mem2:
+ .word 0x4567
+mem3:
+ .byte 0x23
+ .dword 0x76543210
+ .byte 0xaa,0x11,0x99
+
+ .text
+ move.d mem1,r2
+ move.d 0x7823fec2,r4
+ setf nzvc
+ move.d r4,[r2+]
+ test_cc 1 1 1 1
+ subq 4,r2
+ move.d [r2],r3
+ checkr3 7823fec2
+
+ move.d mem2,r3
+ move.d 0x45231879,r4
+ clearf nzvc
+ move.w r4,[r3]
+ test_cc 0 0 0 0
+ move.d [r3],r3
+ checkr3 10231879
+
+ move.d mem2,r2
+ moveq -2,r4
+ clearf nc
+ setf zv
+ move.b r4,[r2+]
+ test_cc 0 1 1 0
+ subq 1,r2
+ move.d [r2],r3
+ checkr3 102318fe
+
+ quit
diff --git a/tests/tcg/cris/check_movmp.s b/tests/tcg/cris/check_movmp.s
new file mode 100644
index 0000000..7fc11f0
--- /dev/null
+++ b/tests/tcg/cris/check_movmp.s
@@ -0,0 +1,131 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffff00\nffff0000\n0\nffffff00\nffff0000\n0\nffffff00\nffff0000\n0\nbb113344\n664433aa\ncc557788\nabcde012\nabcde000\n77880000\n0\n
+
+# Test generic "move Ps,[]" and "move [],Pd" insns; the ones with
+# functionality common to all models.
+
+ .include "testutils.inc"
+ start
+
+ .data
+filler:
+ .byte 0xaa
+ .word 0x4433
+ .dword 0x55778866
+ .byte 0xcc
+
+ .text
+; Test that writing to zero-registers is a nop
+ .if 0
+ ; We used to just ignore the writes, but now an error is emitted.  We
+ ; keep the test-code but disabled, in case we need to change this again.
+ move 0xaa,p0
+ move 0x4433,p4
+ move 0x55774433,p8
+ .endif
+
+ moveq -1,r3
+ setf zcvn
+ clear.b r3
+ test_cc 1 1 1 1
+ checkr3 ffffff00
+
+ moveq -1,r3
+ clearf zcvn
+ clear.w r3
+ test_cc 0 0 0 0
+ checkr3 ffff0000
+
+ moveq -1,r3
+ clear.d r3
+ checkr3 0
+
+; "Write" using ordinary memory references too.
+ .if 0 ; See ".if 0" above.
+ move.d filler,r6
+ move [r6],p0
+ move [r6],p4
+ move [r6],p8
+ .endif
+
+# ffffff00\nffff0000\n0\nffffff00\nffff0000\n0\nbb113344\n664433aa\ncc557788\nabcde012\nabcde000\n77880000\n0\n
+
+ moveq -1,r3
+ clear.b r3
+ checkr3 ffffff00
+
+ moveq -1,r3
+ clear.w r3
+ checkr3 ffff0000
+
+ moveq -1,r3
+ clear.d r3
+ checkr3 0
+
+; And postincremented.
+ .if 0 ; See ".if 0" above.
+ move [r6+],p0
+ move [r6+],p4
+ move [r6+],p8
+ .endif
+
+# ffffff00\nffff0000\n0\nbb113344\n664433aa\ncc557788\nabcde012\nabcde000\n77880000\n0\n
+
+ moveq -1,r3
+ clear.b r3
+ checkr3 ffffff00
+
+ moveq -1,r3
+ clear.w r3
+ checkr3 ffff0000
+
+ moveq -1,r3
+ clear.d r3
+ checkr3 0
+
+; Now see that we can write to the registers too.
+# bb113344\n664433aa\ncc557788\nabcde012\nabcde000\n77880000\n0\n
+; [PC+]
+ move.d filler,r9
+ move 0xbb113344,srp
+ move srp,r3
+ checkr3 bb113344
+
+; [R+]
+ move [r9+],srp
+ move srp,r3
+ checkr3 664433aa
+
+; [R]
+ move [r9],srp
+ move srp,r3
+ checkr3 cc557788
+
+; And check writing to memory, clear and srp.
+
+ move.d filler,r9
+ move 0xabcde012,srp
+ setf zcvn
+ move srp,[r9+]
+ test_cc 1 1 1 1
+ subq 4,r9
+ move.d [r9],r3
+ checkr3 abcde012
+
+ clearf zcvn
+ clear.b [r9]
+ test_cc 0 0 0 0
+ move.d [r9],r3
+ checkr3 abcde000
+
+ addq 2,r9
+ clear.w [r9+]
+ subq 2,r9
+ move.d [r9],r3
+ checkr3 77880000
+
+ clear.d [r9]
+ move.d [r9],r3
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_movpmv32.s b/tests/tcg/cris/check_movpmv32.s
new file mode 100644
index 0000000..daf0970
--- /dev/null
+++ b/tests/tcg/cris/check_movpmv32.s
@@ -0,0 +1,35 @@
+# mach: crisv32
+# output: 11223320\nbb113344\naa557711\n
+
+# Test v32-specific special registers.  FIXME: more registers.
+
+ .include "testutils.inc"
+ start
+ .data
+store:
+ .dword 0x11223344
+ .dword 0x77665544
+
+ .text
+ moveq -1,r3
+ move.d store,r4
+ move vr,[r4]
+ move [r4+],mof
+ move mof,r3
+ checkr3 11223320
+
+ moveq -1,r3
+ clearf zcvn
+ move 0xbb113344,mof
+ test_cc 0 0 0 0
+ move mof,r3
+ checkr3 bb113344
+
+ setf zcvn
+ move 0xaa557711,mof
+ test_cc 1 1 1 1
+ move mof,[r4]
+ move.d [r4],r3
+ checkr3 aa557711
+
+ quit
diff --git a/tests/tcg/cris/check_movpr.s b/tests/tcg/cris/check_movpr.s
new file mode 100644
index 0000000..eef9bdb
--- /dev/null
+++ b/tests/tcg/cris/check_movpr.s
@@ -0,0 +1,28 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffff00\nffff0000\n0\nbb113344\n
+
+# Test generic "move Ps,Rd" and "move Rs,Pd" insns; the ones with
+# functionality common to all models.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ clear.b r3
+ checkr3 ffffff00
+
+ moveq -1,r3
+ clear.w r3
+ checkr3 ffff0000
+
+ moveq -1,r3
+ clear.d r3
+ checkr3 0
+
+ moveq -1,r3
+ move.d 0xbb113344,r4
+ setf zcvn
+ move r4,srp
+ move srp,r3
+ test_cc 1 1 1 1
+ checkr3 bb113344
+ quit
diff --git a/tests/tcg/cris/check_movprv32.s b/tests/tcg/cris/check_movprv32.s
new file mode 100644
index 0000000..d0d90e1
--- /dev/null
+++ b/tests/tcg/cris/check_movprv32.s
@@ -0,0 +1,21 @@
+# mach: crisv32
+# output: ffffff20\nbb113344\n
+
+# Test v32-specific special registers.  FIXME: more registers.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ setf zcvn
+ move vr,r3
+ test_cc 1 1 1 1
+ checkr3 ffffff20
+
+ moveq -1,r3
+ move.d 0xbb113344,r4
+ clearf cvnz
+ move r4,mof
+ test_cc 0 0 0 0
+ move mof,r3
+ checkr3 bb113344
+ quit
diff --git a/tests/tcg/cris/check_movscr.s b/tests/tcg/cris/check_movscr.s
new file mode 100644
index 0000000..53c8ce6
--- /dev/null
+++ b/tests/tcg/cris/check_movscr.s
@@ -0,0 +1,29 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 42\nffffff85\n7685\nffff8765\n0\n
+
+; Move constant byte, word, dword to register.  Check that sign-extension
+; is performed.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ movs.b 0x42,r3
+ checkr3 42
+
+ movs.b 0x85,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffff85
+
+ movs.w 0x7685,r3
+ test_move_cc 0 0 0 0
+ checkr3 7685
+
+ movs.w 0x8765,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff8765
+
+ movs.w 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_movsm.s b/tests/tcg/cris/check_movsm.s
new file mode 100644
index 0000000..7074336
--- /dev/null
+++ b/tests/tcg/cris/check_movsm.s
@@ -0,0 +1,44 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 5\nfffffff5\n5\nfffffff5\n0\n
+
+; Movs between registers.  Check that sign-extension is performed and the
+; full register is set.
+
+ .include "testutils.inc"
+
+ .data
+x:
+ .byte 5,-11
+ .word 5,-11
+ .word 0
+
+ start
+ move.d x,r5
+
+ moveq -1,r3
+ movs.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r3
+ movs.b [r5],r3
+ test_move_cc 1 0 0 0
+ addq 1,r5
+ checkr3 fffffff5
+
+ moveq -1,r3
+ movs.w [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r3
+ movs.w [r5],r3
+ test_move_cc 1 0 0 0
+ addq 2,r5
+ checkr3 fffffff5
+
+ movs.w [r5],r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_movsr.s b/tests/tcg/cris/check_movsr.s
new file mode 100644
index 0000000..d1889a7
--- /dev/null
+++ b/tests/tcg/cris/check_movsr.s
@@ -0,0 +1,46 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 5\nfffffff5\n5\nfffffff5\n0\n
+
+; Movs between registers.  Check that sign-extension is performed and the
+; full register is set.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r5
+ moveq 5,r4
+ move.b r4,r5
+ moveq -1,r3
+ movs.b r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r5
+ moveq -11,r4
+ move.b r4,r5
+ moveq 0,r3
+ movs.b r5,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffff5
+
+ moveq -1,r5
+ moveq 5,r4
+ move.w r4,r5
+ moveq -1,r3
+ movs.w r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r5
+ moveq -11,r4
+ move.w r4,r5
+ moveq 0,r3
+ movs.w r5,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffff5
+
+ moveq 0,r5
+ movs.b r5,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_movucr.s b/tests/tcg/cris/check_movucr.s
new file mode 100644
index 0000000..7c8487d
--- /dev/null
+++ b/tests/tcg/cris/check_movucr.s
@@ -0,0 +1,33 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 42\n85\n7685\n8765\n0\n
+
+; Move constant byte, word, dword to register.  Check that zero-extension
+; is performed.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ movu.b 0x42,r3
+ test_move_cc 0 0 0 0
+ checkr3 42
+
+ moveq -1,r3
+ movu.b 0x85,r3
+ test_move_cc 0 0 0 0
+ checkr3 85
+
+ moveq -1,r3
+ movu.w 0x7685,r3
+ test_move_cc 0 0 0 0
+ checkr3 7685
+
+ moveq -1,r3
+ movu.w 0x8765,r3
+ test_move_cc 0 0 0 0
+ checkr3 8765
+
+ movu.b 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_movum.s b/tests/tcg/cris/check_movum.s
new file mode 100644
index 0000000..038e539
--- /dev/null
+++ b/tests/tcg/cris/check_movum.s
@@ -0,0 +1,40 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 5\nf5\n5\nfff5\n0\n
+
+; Movu between registers.  Check that zero-extension is performed and the
+; full register is set.
+
+ .include "testutils.inc"
+
+ .data
+x:
+ .byte 5,-11
+ .word 5,-11
+ .word 0
+
+ start
+ move.d x,r5
+
+ movu.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ movu.b [r5],r3
+ test_move_cc 0 0 0 0
+ addq 1,r5
+ checkr3 f5
+
+ movu.w [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ movu.w [r5],r3
+ test_move_cc 0 0 0 0
+ addq 2,r5
+ checkr3 fff5
+
+ movu.w [r5],r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_movur.s b/tests/tcg/cris/check_movur.s
new file mode 100644
index 0000000..3ecf475
--- /dev/null
+++ b/tests/tcg/cris/check_movur.s
@@ -0,0 +1,45 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 5\nf5\n5\nfff5\n0\n
+
+; Movu between registers.  Check that zero-extension is performed and the
+; full register is set.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r5
+ moveq 5,r4
+ move.b r4,r5
+ moveq -1,r3
+ movu.b r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r5
+ moveq -11,r4
+ move.b r4,r5
+ moveq -1,r3
+ movu.b r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 f5
+
+ moveq -1,r5
+ moveq 5,r4
+ move.w r4,r5
+ moveq -1,r3
+ movu.w r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r5
+ moveq -11,r4
+ move.w r4,r5
+ moveq -1,r3
+ movu.w r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 fff5
+
+ movu.w 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_mulv32.s b/tests/tcg/cris/check_mulv32.s
new file mode 100644
index 0000000..f379358
--- /dev/null
+++ b/tests/tcg/cris/check_mulv32.s
@@ -0,0 +1,51 @@
+# mach: crisv32
+# output: fffffffe\n
+# output: ffffffff\n
+# output: fffffffe\n
+# output: 1\n
+# output: fffffffe\n
+# output: ffffffff\n
+# output: fffffffe\n
+# output: 1\n
+
+; Check that carry is not modified on v32.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ setf c
+ muls.d r4,r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 2,r4
+ setf c
+ mulu.d r4,r3
+ test_cc 0 0 1 1
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 1
+
+ moveq -1,r3
+ moveq 2,r4
+ clearf c
+ muls.d r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 2,r4
+ clearf c
+ mulu.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 1
+
+ quit
diff --git a/tests/tcg/cris/check_mulx.s b/tests/tcg/cris/check_mulx.s
new file mode 100644
index 0000000..d43241a
--- /dev/null
+++ b/tests/tcg/cris/check_mulx.s
@@ -0,0 +1,246 @@
+# mach: crisv10 crisv32
+# output: fffffffe\nffffffff\nfffffffe\n1\nfffffffe\nffffffff\nfffffffe\n1\nfffe0001\n0\nfffe0001\n0\n1\n0\n1\nfffffffe\n193eade2\n277e3a49\n193eade2\n277e3a49\nfffffffe\nffffffff\n1fffe\n0\nfffffffe\nffffffff\n1fffe\n0\n1\n0\nfffe0001\n0\nfdbdade2\nffffffff\n420fade2\n0\nfffffffe\nffffffff\n1fe\n0\nfffffffe\nffffffff\n1fe\n0\n1\n0\nfe01\n0\n1\n0\nfe01\n0\nffffd9e2\nffffffff\n2be2\n0\n0\n0\n0\n0\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ muls.d r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 2,r4
+ mulu.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 1
+
+ moveq 2,r3
+ moveq -1,r4
+ muls.d r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq -1,r4
+ mulu.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 1
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ muls.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 fffe0001
+ move mof,r3
+ checkr3 0
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ mulu.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 fffe0001
+ move mof,r3
+ checkr3 0
+
+ moveq -1,r4
+ move.d r4,r3
+ muls.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+ move mof,r3
+ checkr3 0
+
+ moveq -1,r4
+ move.d r4,r3
+ mulu.d r4,r3
+ test_cc 1 0 1 0
+ checkr3 1
+ move mof,r3
+ checkr3 fffffffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ muls.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 193eade2
+ move mof,r3
+ checkr3 277e3a49
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ mulu.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 193eade2
+ move mof,r3
+ checkr3 277e3a49
+
+ move.d 0xffff,r3
+ moveq 2,r4
+ muls.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 2,r4
+ mulu.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+ move mof,r3
+ checkr3 0
+
+ moveq 2,r3
+ move.d 0xffff,r4
+ muls.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq -1,r4
+ mulu.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+ move mof,r3
+ checkr3 0
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ muls.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+ move mof,r3
+ checkr3 0
+
+ moveq -1,r4
+ move.d r4,r3
+ mulu.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 fffe0001
+ move mof,r3
+ checkr3 0
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ muls.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fdbdade2
+ move mof,r3
+ checkr3 ffffffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ mulu.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 420fade2
+ move mof,r3
+ checkr3 0
+
+ move.d 0xff,r3
+ moveq 2,r4
+ muls.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 2,r4
+ mulu.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fe
+ move mof,r3
+ checkr3 0
+
+ moveq 2,r3
+ moveq -1,r4
+ muls.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq -1,r4
+ mulu.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fe
+ move mof,r3
+ checkr3 0
+
+ move.d 0xff,r4
+ move.d r4,r3
+ muls.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+ move mof,r3
+ checkr3 0
+
+ moveq -1,r4
+ move.d r4,r3
+ mulu.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 fe01
+ move mof,r3
+ checkr3 0
+
+ move.d 0xfeda49ff,r4
+ move.d r4,r3
+ muls.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+ move mof,r3
+ checkr3 0
+
+ move.d 0xfeda49ff,r4
+ move.d r4,r3
+ mulu.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 fe01
+ move mof,r3
+ checkr3 0
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ muls.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 ffffd9e2
+ move mof,r3
+ checkr3 ffffffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ mulu.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 2be2
+ move mof,r3
+ checkr3 0
+
+ moveq 0,r3
+ move.d 0xf87f4aeb,r4
+ muls.d r4,r3
+ test_cc 0 1 0 0
+ checkr3 0
+ move mof,r3
+ checkr3 0
+
+ move.d 0xf87f4aeb,r3
+ moveq 0,r4
+ mulu.d r4,r3
+ test_cc 0 1 0 0
+ checkr3 0
+ move mof,r3
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_neg.s b/tests/tcg/cris/check_neg.s
new file mode 100644
index 0000000..963c4b6
--- /dev/null
+++ b/tests/tcg/cris/check_neg.s
@@ -0,0 +1,104 @@
+# mach:  crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\nffffffff\n0\n80000000\n1\nba987655\nffff\nffff\n0\n89ab8000\nffff0001\n45677655\nff\nff\n0\n89abae80\nffffff01\n45678955\n
+
+ .include "testutils.inc"
+ start
+ moveq 0,r3
+ moveq 1,r4
+ neg.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 1,r3
+ moveq 0,r4
+ neg.d r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+;; FIXME: this was wrong.
+ moveq 0,r3
+ neg.d r3,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0x80000000,r3
+ neg.d r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 80000000
+
+ moveq -1,r3
+ neg.d r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0x456789ab,r3
+ neg.d r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 ba987655
+
+ moveq 0,r3
+ moveq 1,r4
+ neg.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff
+
+ moveq 1,r3
+ moveq 0,r4
+ neg.w r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff
+
+ moveq 0,r3
+ neg.w r3,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0x89ab8000,r3
+ neg.w r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 89ab8000
+
+ moveq -1,r3
+ neg.w r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0001
+
+ move.d 0x456789ab,r3
+ neg.w r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 45677655
+
+ moveq 0,r3
+ moveq 1,r4
+ neg.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ff
+
+ moveq 1,r3
+ moveq 0,r4
+ neg.b r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 ff
+
+ moveq 0,r3
+ neg.b r3,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+;; FIXME: was wrong.
+ move.d 0x89abae80,r3
+ neg.b r3,r3
+ test_move_cc 1 0 0 1
+ checkr3 89abae80
+
+ moveq -1,r3
+ neg.b r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff01
+
+ move.d 0x456789ab,r3
+ neg.b r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 45678955
+
+ quit
diff --git a/tests/tcg/cris/check_not.s b/tests/tcg/cris/check_not.s
new file mode 100644
index 0000000..33bcf15
--- /dev/null
+++ b/tests/tcg/cris/check_not.s
@@ -0,0 +1,31 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: fffffffe\nfffffffd\nffff0f00\n0\n87ecbbad\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ not r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffffe
+
+ moveq 2,r3
+ not r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffffd
+
+ move.d 0xf0ff,r3
+ not r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff0f00
+
+ moveq -1,r3
+ not r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0x78134452,r3
+ not r3
+ test_move_cc 1 0 0 0
+ checkr3 87ecbbad
+
+ quit
diff --git a/tests/tcg/cris/check_openpf1.c b/tests/tcg/cris/check_openpf1.c
new file mode 100644
index 0000000..fdcf4c5
--- /dev/null
+++ b/tests/tcg/cris/check_openpf1.c
@@ -0,0 +1,38 @@
+/* Check that --sysroot is applied to open(2).
+#sim: --sysroot=@exedir@
+
+   We assume, with EXE being the name of the executable:
+   - The simulator executes with cwd the same directory where the executable
+     is located (so argv[0] contains a plain filename without directory
+     components).
+   - There's no /EXE on the host file system.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+int main (int argc, char *argv[])
+{
+  char *fnam = argv[0];
+  FILE *f;
+  if (argv[0][0] != '/')
+    {
+      fnam = malloc (strlen (argv[0]) + 2);
+      if (fnam == NULL)
+	abort ();
+      strcpy (fnam, "/");
+      strcat (fnam, argv[0]);
+    }
+
+  f = fopen (fnam, "rb");
+  if (f == NULL)
+    abort ();
+  fclose(f);
+
+  /* Cover another execution path.  */
+  if (fopen ("/nonexistent", "rb") != NULL
+      || errno != ENOENT)
+    abort ();
+  printf ("pass\n");
+  return 0;
+}
diff --git a/tests/tcg/cris/check_openpf2.c b/tests/tcg/cris/check_openpf2.c
new file mode 100644
index 0000000..5d56189
--- /dev/null
+++ b/tests/tcg/cris/check_openpf2.c
@@ -0,0 +1,16 @@
+/* Check that the simulator has chdir:ed to the --sysroot argument
+#sim: --sysroot=@srcdir@
+   (or that  --sysroot is applied to relative file paths).  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+int main (int argc, char *argv[])
+{
+  FILE *f = fopen ("check_openpf2.c", "rb");
+  if (f == NULL)
+    abort ();
+  fclose(f);
+  printf ("pass\n");
+  return 0;
+}
diff --git a/tests/tcg/cris/check_openpf3.c b/tests/tcg/cris/check_openpf3.c
new file mode 100644
index 0000000..557adee
--- /dev/null
+++ b/tests/tcg/cris/check_openpf3.c
@@ -0,0 +1,49 @@
+/* Basic file operations (rename, unlink); once without sysroot.  We
+   also test that the simulator has chdir:ed to PREFIX, when defined.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#ifndef PREFIX
+#define PREFIX
+#endif
+
+void err (const char *s)
+{
+  perror (s);
+  abort ();
+}
+
+int main (int argc, char *argv[])
+{
+  FILE *f;
+  struct stat buf;
+
+  unlink (PREFIX "testfoo2.tmp");
+
+  f = fopen ("testfoo1.tmp", "w");
+  if (f == NULL)
+    err ("open");
+  fclose (f);
+
+  if (rename (PREFIX "testfoo1.tmp", PREFIX "testfoo2.tmp") != 0)
+    err ("rename");
+
+  if (stat (PREFIX "testfoo2.tmp", &buf) != 0
+      || !S_ISREG (buf.st_mode))
+    err ("stat 1");
+
+  if (stat ("testfoo2.tmp", &buf) != 0
+      || !S_ISREG (buf.st_mode))
+    err ("stat 2");
+
+  if (unlink (PREFIX "testfoo2.tmp") != 0)
+    err ("unlink");
+
+  printf ("pass\n");
+  return 0;
+}
diff --git a/tests/tcg/cris/check_openpf4.c b/tests/tcg/cris/check_openpf4.c
new file mode 100644
index 0000000..8bbee41
--- /dev/null
+++ b/tests/tcg/cris/check_openpf4.c
@@ -0,0 +1,5 @@
+/* Basic file operations, now *with* sysroot.
+#sim: --sysroot=@exedir@
+*/
+#define PREFIX "/"
+#include "check_openpf3.c"
diff --git a/tests/tcg/cris/check_openpf5.c b/tests/tcg/cris/check_openpf5.c
new file mode 100644
index 0000000..1f86ea2
--- /dev/null
+++ b/tests/tcg/cris/check_openpf5.c
@@ -0,0 +1,56 @@
+/* Check that TRT happens when error on too many opened files.
+#notarget: cris*-*-elf
+#sim: --sysroot=@exedir@
+*/
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+int main (int argc, char *argv[])
+{
+  int i;
+  int filemax;
+
+#ifdef OPEN_MAX
+  filemax = OPEN_MAX;
+#else
+  filemax = sysconf (_SC_OPEN_MAX);
+#endif
+
+  char *fn = malloc (strlen (argv[0]) + 2);
+  if (fn == NULL)
+    abort ();
+  strcpy (fn, "/");
+  strcat (fn, argv[0]);
+
+  for (i = 0; i < filemax + 1; i++)
+    {
+      if (open (fn, O_RDONLY) < 0)
+	{
+	  /* Shouldn't happen too early.  */
+	  if (i < filemax - 3 - 1)
+	    {
+	      fprintf (stderr, "i: %d\n", i);
+	      abort ();
+	    }
+	  if (errno != EMFILE)
+	    {
+	      perror ("open");
+	      abort ();
+	    }
+	  goto ok;
+	}
+    }
+  abort ();
+
+ok:
+  printf ("pass\n");
+  exit (0);
+}
diff --git a/tests/tcg/cris/check_orc.s b/tests/tcg/cris/check_orc.s
new file mode 100644
index 0000000..c733f03
--- /dev/null
+++ b/tests/tcg/cris/check_orc.s
@@ -0,0 +1,71 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 3\n3\nffff\nffffffff\n7c33f7db\nffff0003\n3\nfedaffff\n7813f7db\n3\n3\nfeb\n781344db\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ or.d 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ or.d 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xf0ff,r3
+ or.d 0xff0f,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r3
+ or.d -1,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ or.d 0x5432f789,r3
+ test_move_cc 0 0 0 0
+ checkr3 7c33f7db
+
+ move.d 0xffff0001,r3
+ or.w 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0003
+
+ moveq 2,r3
+ or.w 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xfedaffaf,r3
+ or.w 0xff5f,r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d 0x78134452,r3
+ or.w 0xf789,r3
+ test_move_cc 1 0 0 0
+ checkr3 7813f7db
+
+ moveq 1,r3
+ or.b 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ or.b 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xfa3,r3
+ or.b 0x4a,r3
+ test_move_cc 1 0 0 0
+ checkr3 feb
+
+ move.d 0x78134453,r3
+ or.b 0x89,r3
+ test_move_cc 1 0 0 0
+ checkr3 781344db
+
+ quit
diff --git a/tests/tcg/cris/check_orm.s b/tests/tcg/cris/check_orm.s
new file mode 100644
index 0000000..ee723a6
--- /dev/null
+++ b/tests/tcg/cris/check_orm.s
@@ -0,0 +1,75 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 3\n3\nffff\nffffffff\n7c33f7db\nffff0003\n3\nfedaffff\n7813f7db\n3\n3\nfeb\n781344db\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword 2,1,0xff0f,-1,0x5432f789
+ .word 2,1,0xff5f,0xf789
+ .byte 2,1,0x4a,0x89
+
+ start
+ moveq 1,r3
+ move.d x,r5
+ or.d [r5+],r3
+ checkr3 3
+
+ moveq 2,r3
+ or.d [r5],r3
+ addq 4,r5
+ checkr3 3
+
+ move.d 0xf0ff,r3
+ or.d [r5+],r3
+ checkr3 ffff
+
+ moveq -1,r3
+ or.d [r5+],r3
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ or.d [r5+],r3
+ checkr3 7c33f7db
+
+ move.d 0xffff0001,r3
+ or.w [r5+],r3
+ checkr3 ffff0003
+
+ moveq 2,r3
+ or.w [r5],r3
+ addq 2,r5
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xfedaffaf,r3
+ or.w [r5+],r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d 0x78134452,r3
+ or.w [r5+],r3
+ test_move_cc 1 0 0 0
+ checkr3 7813f7db
+
+ moveq 1,r3
+ or.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ or.b [r5],r3
+ addq 1,r5
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xfa3,r3
+ or.b [r5+],r3
+ test_move_cc 1 0 0 0
+ checkr3 feb
+
+ move.d 0x78134453,r3
+ or.b [r5],r3
+ test_move_cc 1 0 0 0
+ checkr3 781344db
+
+ quit
diff --git a/tests/tcg/cris/check_orq.s b/tests/tcg/cris/check_orq.s
new file mode 100644
index 0000000..5060edc
--- /dev/null
+++ b/tests/tcg/cris/check_orq.s
@@ -0,0 +1,41 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 3\n3\nffffffff\nffffffff\n1f\nffffffe0\n7813445e\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ orq 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ orq 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xf0ff,r3
+ orq -1,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 0,r3
+ orq -1,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 0,r3
+ orq 31,r3
+ test_move_cc 0 0 0 0
+ checkr3 1f
+
+ moveq 0,r3
+ orq -32,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffe0
+
+ move.d 0x78134452,r3
+ orq 12,r3
+ test_move_cc 0 0 0 0
+ checkr3 7813445e
+
+ quit
diff --git a/tests/tcg/cris/check_orr.s b/tests/tcg/cris/check_orr.s
new file mode 100644
index 0000000..a514c11
--- /dev/null
+++ b/tests/tcg/cris/check_orr.s
@@ -0,0 +1,84 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 3\n3\nffff\nffffffff\n7c33f7db\nffff0003\n3\nfedaffff\n7813f7db\n3\n3\nfeb\n781344db\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ moveq 2,r4
+ or.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ moveq 1,r4
+ or.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xff0f,r4
+ move.d 0xf0ff,r3
+ or.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r4
+ move.d r4,r3
+ or.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ or.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 7c33f7db
+
+ move.d 0xffff0001,r3
+ moveq 2,r4
+ or.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0003
+
+ moveq 2,r3
+ move.d 0xffff0001,r4
+ or.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xfedaffaf,r3
+ move.d 0xffffff5f,r4
+ or.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ or.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 7813f7db
+
+ moveq 1,r3
+ move.d 0xffffff02,r4
+ or.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ moveq 1,r4
+ or.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0x4a,r4
+ move.d 0xfa3,r3
+ or.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 feb
+
+ move.d 0x5432f789,r4
+ move.d 0x78134453,r3
+ or.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 781344db
+
+ quit
diff --git a/tests/tcg/cris/check_ret.s b/tests/tcg/cris/check_ret.s
new file mode 100644
index 0000000..b44fb25
--- /dev/null
+++ b/tests/tcg/cris/check_ret.s
@@ -0,0 +1,25 @@
+# mach: crisv3 crisv8 crisv10
+# output: 3\n
+
+# Test that ret works.
+
+ .include "testutils.inc"
+ start
+x:
+ moveq 0,r3
+ jsr z
+w:
+ quit
+y:
+ addq 1,r3
+ checkr3 3
+ quit
+
+z:
+ addq 1,r3
+ move srp,r2
+ add.d y-w,r2
+ move r2,srp
+ ret
+ addq 1,r3
+ quit
diff --git a/tests/tcg/cris/check_scc.s b/tests/tcg/cris/check_scc.s
new file mode 100644
index 0000000..4a8674c
--- /dev/null
+++ b/tests/tcg/cris/check_scc.s
@@ -0,0 +1,95 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n0\n1\n0\n1\n0\n1\n0\n0\n1\n1\n0\n1\n0\n1\n0\n1\n0\n0\n1\n0\n1\n1\n0\n1\n0\n0\n1\n1\n0\n1\n1\n0\n
+
+ .include "testutils.inc"
+
+ .macro lcheckr3 v
+	move	 $ccs, $r9
+	checkr3 \v
+	move	$r9, $ccs
+ .endm
+
+ start
+ clearf nzvc
+ scc r3
+ lcheckr3 1
+ scs r3
+ lcheckr3 0
+ sne r3
+ lcheckr3 1
+ seq r3
+ lcheckr3 0
+ svc r3
+ lcheckr3 1
+ svs r3
+ lcheckr3 0
+ spl r3
+ lcheckr3 1
+ smi r3
+ lcheckr3 0
+ sls r3
+ lcheckr3 0
+ shi r3
+ lcheckr3 1
+ sge r3
+ lcheckr3 1
+ slt r3
+ lcheckr3 0
+ sgt r3
+ lcheckr3 1
+ sle r3
+ lcheckr3 0
+ sa r3
+ lcheckr3 1
+ setf nzvc
+ scc r3
+ lcheckr3 0
+ scs r3
+ lcheckr3 1
+ sne r3
+ lcheckr3 0
+ svc r3
+ lcheckr3 0
+ svs r3
+ lcheckr3 1
+ spl r3
+ lcheckr3 0
+ smi r3
+ lcheckr3 1
+ sls r3
+ lcheckr3 1
+ shi r3
+ lcheckr3 0
+ sge r3
+ lcheckr3 1
+ slt r3
+ lcheckr3 0
+ sgt r3
+ lcheckr3 0
+ sle r3
+ lcheckr3 1
+ sa r3
+ lcheckr3 1
+ clearf n
+ sge r3
+ lcheckr3 0
+ slt r3
+ lcheckr3 1
+
+ .if 1 ;..asm.arch.cris.v32
+ setf p
+ ssb r3
+ .else
+ moveq 1,r3
+ .endif
+ lcheckr3 1
+
+ .if 1 ;..asm.arch.cris.v32
+ clearf p
+ ssb r3
+ .else
+ moveq 0,r3
+ .endif
+ lcheckr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_settls1.c b/tests/tcg/cris/check_settls1.c
new file mode 100644
index 0000000..69d2026
--- /dev/null
+++ b/tests/tcg/cris/check_settls1.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sys/syscall.h>
+
+#ifndef SYS_set_thread_area
+#define SYS_set_thread_area 243
+#endif
+
+int main (void)
+{
+    unsigned long tp, old_tp;
+    int ret;
+
+    asm volatile ("move $pid,%0" : "=r" (old_tp));
+    old_tp &= ~0xff;
+
+    ret = syscall (SYS_set_thread_area, 0xf0);
+    if (ret != -1 || errno != EINVAL) {
+        syscall (SYS_set_thread_area, old_tp);
+        perror ("Invalid thread area accepted:");
+        abort();
+    }
+
+    ret = syscall (SYS_set_thread_area, 0xeddeed00);
+    if (ret != 0) {
+        perror ("Valid thread area not accepted: ");
+        abort ();
+    }
+
+    asm volatile ("move $pid,%0" : "=r" (tp));
+    tp &= ~0xff;
+    syscall (SYS_set_thread_area, old_tp);
+
+    if (tp != 0xeddeed00) {
+	* (volatile int *) 0 = 0;
+        perror ("tls2");
+        abort ();
+    }
+
+    printf ("pass\n");
+    return EXIT_SUCCESS;
+}
diff --git a/tests/tcg/cris/check_sigalrm.c b/tests/tcg/cris/check_sigalrm.c
new file mode 100644
index 0000000..39fa8d9
--- /dev/null
+++ b/tests/tcg/cris/check_sigalrm.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+
+#define MAGIC (0xdeadbeef)
+
+int s = 0;
+void sighandler(int sig)
+{
+	s = MAGIC;
+}
+
+int main(int argc, char **argv)
+{
+	int p;
+
+	p = getpid();
+	signal(SIGALRM, sighandler);
+	kill(p, SIGALRM);
+	if (s != MAGIC)
+		return EXIT_FAILURE;
+
+	printf ("passed\n");
+	return EXIT_SUCCESS;
+}
diff --git a/tests/tcg/cris/check_stat1.c b/tests/tcg/cris/check_stat1.c
new file mode 100644
index 0000000..2e2cae5
--- /dev/null
+++ b/tests/tcg/cris/check_stat1.c
@@ -0,0 +1,16 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main (void)
+{
+  struct stat buf;
+
+  if (stat (".", &buf) != 0
+      || !S_ISDIR (buf.st_mode))
+    abort ();
+  printf ("pass\n");
+  exit (0);
+}
diff --git a/tests/tcg/cris/check_stat2.c b/tests/tcg/cris/check_stat2.c
new file mode 100644
index 0000000..e36172e
--- /dev/null
+++ b/tests/tcg/cris/check_stat2.c
@@ -0,0 +1,20 @@
+/*
+#notarget: cris*-*-elf
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main (void)
+{
+  struct stat buf;
+
+  if (lstat (".", &buf) != 0
+      || !S_ISDIR (buf.st_mode))
+    abort ();
+  printf ("pass\n");
+  exit (0);
+}
diff --git a/tests/tcg/cris/check_stat3.c b/tests/tcg/cris/check_stat3.c
new file mode 100644
index 0000000..36a9d5d
--- /dev/null
+++ b/tests/tcg/cris/check_stat3.c
@@ -0,0 +1,25 @@
+/* Simulator options:
+#sim: --sysroot=@exedir@
+*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+int main (int argc, char *argv[])
+{
+  char path[1024] = "/";
+  struct stat buf;
+
+  strncat(path, argv[0], sizeof(path) - 2);
+  if (stat (".", &buf) != 0
+      || !S_ISDIR (buf.st_mode))
+    abort ();
+  if (stat (path, &buf) != 0
+      || !S_ISREG (buf.st_mode))
+    abort ();
+  printf ("pass\n");
+  exit (0);
+}
diff --git a/tests/tcg/cris/check_stat4.c b/tests/tcg/cris/check_stat4.c
new file mode 100644
index 0000000..04f21fe
--- /dev/null
+++ b/tests/tcg/cris/check_stat4.c
@@ -0,0 +1,27 @@
+/* Simulator options:
+#notarget: cris*-*-elf
+#sim: --sysroot=@exedir@
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+int main (int argc, char *argv[])
+{
+  char path[1024] = "/";
+  struct stat buf;
+
+  strncat(path, argv[0], sizeof(path) - 2);
+  if (lstat (".", &buf) != 0
+      || !S_ISDIR (buf.st_mode))
+    abort ();
+  if (lstat (path, &buf) != 0
+      || !S_ISREG (buf.st_mode))
+    abort ();
+  printf ("pass\n");
+  exit (0);
+}
diff --git a/tests/tcg/cris/check_subc.s b/tests/tcg/cris/check_subc.s
new file mode 100644
index 0000000..e34b544
--- /dev/null
+++ b/tests/tcg/cris/check_subc.s
@@ -0,0 +1,87 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n85649200\n
+
+ .include "testutils.inc"
+ start
+
+ moveq -1,r3
+ sub.d -2,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ moveq 2,r3
+ sub.d 1,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xffff,r3
+ sub.d -0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 1fffe
+
+ moveq -1,r3
+ sub.d 1,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move.d 0x78134452,r3
+ sub.d -0x5432f789,r3
+ test_cc 1 0 1 1
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ sub.w -2,r3
+ test_cc 0 0 0 0
+ checkr3 ffff0001
+
+ moveq 2,r3
+ sub.w 1,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xffff,r3
+ sub.w 1,r3
+ test_cc 1 0 0 0
+ checkr3 fffe
+
+ move.d 0xfedaffff,r3
+ sub.w 1,r3
+ test_cc 1 0 0 0
+ checkr3 fedafffe
+
+ move.d 0x78134452,r3
+ sub.w 0x877,r3
+ test_cc 0 0 0 0
+ checkr3 78133bdb
+
+ moveq -1,r3
+ sub.b -2,r3
+ test_cc 0 0 0 0
+ checkr3 ffffff01
+
+ moveq 2,r3
+ sub.b 1,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xff,r3
+ sub.b 1,r3
+ test_cc 1 0 0 0
+ checkr3 fe
+
+ move.d 0xfeda49ff,r3
+ sub.b 1,r3
+ test_cc 1 0 0 0
+ checkr3 feda49fe
+
+ move.d 0x78134452,r3
+ sub.b 0x77,r3
+ test_cc 1 0 0 1
+ checkr3 781344db
+
+ move.d 0x85649282,r3
+ sub.b 0x82,r3
+ test_cc 0 1 0 0
+ checkr3 85649200
+
+ quit
diff --git a/tests/tcg/cris/check_subm.s b/tests/tcg/cris/check_subm.s
new file mode 100644
index 0000000..e07ea02
--- /dev/null
+++ b/tests/tcg/cris/check_subm.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n85649200\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword -2,1,-0xffff,1,-0x5432f789
+ .word -2,1,1,0x877
+ .byte -2,1,0x77
+ .byte 0x22
+
+ start
+ moveq -1,r3
+ move.d x,r5
+ sub.d [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ moveq 2,r3
+ sub.d [r5],r3
+ test_cc 0 0 0 0
+ addq 4,r5
+ checkr3 1
+
+ move.d 0xffff,r3
+ sub.d [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 1fffe
+
+ moveq -1,r3
+ sub.d [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move.d 0x78134452,r3
+ sub.d [r5+],r3
+ test_cc 1 0 1 1
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ sub.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 ffff0001
+
+ moveq 2,r3
+ sub.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xffff,r3
+ sub.w [r5],r3
+ test_cc 1 0 0 0
+ checkr3 fffe
+
+ move.d 0xfedaffff,r3
+ sub.w [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 fedafffe
+
+ move.d 0x78134452,r3
+ sub.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 78133bdb
+
+ moveq -1,r3
+ sub.b [r5],r3
+ test_cc 0 0 0 0
+ addq 1,r5
+ checkr3 ffffff01
+
+ moveq 2,r3
+ sub.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xff,r3
+ sub.b [r5],r3
+ test_cc 1 0 0 0
+ checkr3 fe
+
+ move.d 0xfeda49ff,r3
+ sub.b [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 feda49fe
+
+ move.d 0x78134452,r3
+ sub.b [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 781344db
+
+ move.d 0x85649222,r3
+ sub.b [r5],r3
+ test_cc 0 1 0 0
+ checkr3 85649200
+
+ quit
diff --git a/tests/tcg/cris/check_subq.s b/tests/tcg/cris/check_subq.s
new file mode 100644
index 0000000..9e34fa3
--- /dev/null
+++ b/tests/tcg/cris/check_subq.s
@@ -0,0 +1,52 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 0\nffffffff\nfffffffe\nffff\nff\n56788f9\n56788d9\n567889a\n0\n7ffffffc\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ subq 1,r3
+ test_cc 0 1 0 0
+ checkr3 0
+
+ subq 1,r3
+ test_cc 1 0 0 1
+ checkr3 ffffffff
+
+ subq 1,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move.d 0x10000,r3
+ subq 1,r3
+ test_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0x100,r3
+ subq 1,r3
+ test_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0x5678900,r3
+ subq 7,r3
+ test_cc 0 0 0 0
+ checkr3 56788f9
+
+ subq 32,r3
+ test_cc 0 0 0 0
+ checkr3 56788d9
+
+ subq 63,r3
+ test_cc 0 0 0 0
+ checkr3 567889a
+
+ move.d 34,r3
+ subq 34,r3
+ test_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0x80000024,r3
+ subq 40,r3
+ test_cc 0 0 1 0
+ checkr3 7ffffffc
+
+ quit
diff --git a/tests/tcg/cris/check_subr.s b/tests/tcg/cris/check_subr.s
new file mode 100644
index 0000000..742fbc8
--- /dev/null
+++ b/tests/tcg/cris/check_subr.s
@@ -0,0 +1,102 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n85649200\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq -2,r4
+ sub.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ moveq 2,r3
+ moveq 1,r4
+ sub.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xffff,r3
+ move.d -0xffff,r4
+ sub.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 1fffe
+
+ moveq 1,r4
+ moveq -1,r3
+ sub.d r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ sub.d r4,r3
+ test_cc 1 0 1 1
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ moveq -2,r4
+ sub.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 ffff0001
+
+ moveq 2,r3
+ moveq 1,r4
+ sub.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xffff,r3
+ move.d -0xffff,r4
+ sub.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffe
+
+ move.d 0xfedaffff,r3
+ move.d -0xfedaffff,r4
+ sub.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fedafffe
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ sub.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 78133bdb
+
+ moveq -1,r3
+ moveq -2,r4
+ sub.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 ffffff01
+
+ moveq 2,r3
+ moveq 1,r4
+ sub.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d -0xff,r4
+ move.d 0xff,r3
+ sub.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 fe
+
+ move.d -0xfeda49ff,r4
+ move.d 0xfeda49ff,r3
+ sub.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 feda49fe
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ sub.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 781344db
+
+ move.d 0x85649222,r3
+ move.d 0x77445622,r4
+ sub.b r4,r3
+ test_cc 0 1 0 0
+ checkr3 85649200
+
+ quit
diff --git a/tests/tcg/cris/check_swap.c b/tests/tcg/cris/check_swap.c
new file mode 100644
index 0000000..f851cbc
--- /dev/null
+++ b/tests/tcg/cris/check_swap.c
@@ -0,0 +1,76 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+#define N 8
+#define W 4
+#define B 2
+#define R 1
+
+static inline int cris_swap(const int mode, int x)
+{
+	switch (mode)
+	{
+		case N: asm ("swapn\t%0\n" : "+r" (x) : "0" (x)); break;
+		case W: asm ("swapw\t%0\n" : "+r" (x) : "0" (x)); break;
+		case B: asm ("swapb\t%0\n" : "+r" (x) : "0" (x)); break;
+		case R: asm ("swapr\t%0\n" : "+r" (x) : "0" (x)); break;
+		case B|R: asm ("swapbr\t%0\n" : "+r" (x) : "0" (x)); break;
+		case W|R: asm ("swapwr\t%0\n" : "+r" (x) : "0" (x)); break;
+		case W|B: asm ("swapwb\t%0\n" : "+r" (x) : "0" (x)); break;
+		case W|B|R: asm ("swapwbr\t%0\n" : "+r" (x) : "0" (x)); break;
+		case N|R: asm ("swapnr\t%0\n" : "+r" (x) : "0" (x)); break;
+		case N|B: asm ("swapnb\t%0\n" : "+r" (x) : "0" (x)); break;
+		case N|B|R: asm ("swapnbr\t%0\n" : "+r" (x) : "0" (x)); break;
+		case N|W: asm ("swapnw\t%0\n" : "+r" (x) : "0" (x)); break;
+		default:
+			err();
+			break;
+	}
+	return x;
+}
+
+/* Made this a macro to be able to pick up the location of the errors.  */
+#define verify_swap(mode, val, expected, n, z)          \
+do {                                                    \
+        int r;                                          \
+        cris_tst_cc_init();                             \
+	r = cris_swap(mode, val);                       \
+        cris_tst_mov_cc(n, z);                          \
+	if (r != expected)                              \
+		err();                                  \
+} while(0)
+
+void check_swap(void)
+{
+	/* Some of these numbers are borrowed from GDB's cris sim
+	   testsuite.  */
+	if (cris_swap(N, 0) != 0xffffffff)
+		err();
+	if (cris_swap(W, 0x12345678) != 0x56781234)
+		err();
+	if (cris_swap(B, 0x12345678) != 0x34127856)
+		err();
+
+	verify_swap(R, 0x78134452, 0x1ec8224a, 0, 0);
+	verify_swap(B, 0x78134452, 0x13785244, 0, 0);
+	verify_swap(B|R, 0x78134452, 0xc81e4a22, 1, 0);
+	verify_swap(W, 0x78134452, 0x44527813, 0, 0);
+	verify_swap(W|R, 0x78134452, 0x224a1ec8, 0, 0);
+	verify_swap(W|B|R, 0x78134452, 0x4a22c81e, 0, 0);
+	verify_swap(N, 0x78134452, 0x87ecbbad, 1, 0);
+	verify_swap(N|R, 0x78134452, 0xe137ddb5, 1, 0);
+	verify_swap(N|B, 0x78134452, 0xec87adbb, 1, 0);
+	verify_swap(N|B|R, 0x78134452, 0x37e1b5dd, 0, 0);
+	verify_swap(N|W, 0x78134452, 0xbbad87ec, 1, 0);
+	verify_swap(N|B|R, 0xffffffff, 0, 0, 1);
+}
+
+int main(void)
+{
+	check_swap();
+	pass();
+	return 0;
+}
diff --git a/tests/tcg/cris/check_time1.c b/tests/tcg/cris/check_time1.c
new file mode 100644
index 0000000..3fcf0e1
--- /dev/null
+++ b/tests/tcg/cris/check_time1.c
@@ -0,0 +1,46 @@
+/* Basic time functionality test: check that milliseconds are
+   incremented for each syscall (does not work on host).  */
+#include <stdio.h>
+#include <time.h>
+#include <sys/time.h>
+#include <string.h>
+#include <stdlib.h>
+
+void err (const char *s)
+{
+  perror (s);
+  abort ();
+}
+
+int
+main (void)
+{
+  struct timeval t_m = {0, 0};
+  struct timezone t_z = {0, 0};
+  struct timeval t_m1 = {0, 0};
+  int i;
+
+  if (gettimeofday (&t_m, &t_z) != 0)
+    err ("gettimeofday");
+
+  for (i = 1; i < 10000; i++)
+    if (gettimeofday (&t_m1, NULL) != 0)
+      err ("gettimeofday 1");
+    else
+      if (t_m1.tv_sec * 1000000 + t_m1.tv_usec
+	  != (t_m.tv_sec * 1000000 + t_m.tv_usec + i * 1000))
+	{
+	  fprintf (stderr, "t0 (%ld, %ld), i %d, t1 (%ld, %ld)\n",
+		   t_m.tv_sec, t_m.tv_usec, i, t_m1.tv_sec, t_m1.tv_usec);
+	  abort ();
+	}
+
+  if (time (NULL) != t_m1.tv_sec)
+    {
+      fprintf (stderr, "time != gettod\n");
+      abort ();
+    }
+
+  printf ("pass\n");
+  exit (0);
+}
diff --git a/tests/tcg/cris/check_time2.c b/tests/tcg/cris/check_time2.c
new file mode 100644
index 0000000..20b69b4
--- /dev/null
+++ b/tests/tcg/cris/check_time2.c
@@ -0,0 +1,18 @@
+/* CB_SYS_time doesn't implement the Linux time syscall; the return
+   value isn't written to the argument.  */
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  time_t x = (time_t) -1;
+  time_t t = time (&x);
+
+  if (t == (time_t) -1 || t != x)
+    abort ();
+  printf ("pass\n");
+  exit (0);
+}
diff --git a/tests/tcg/cris/check_xarith.s b/tests/tcg/cris/check_xarith.s
new file mode 100644
index 0000000..80038b2
--- /dev/null
+++ b/tests/tcg/cris/check_xarith.s
@@ -0,0 +1,72 @@
+
+.include "testutils.inc"
+
+	start
+
+	moveq	-1, $r0
+	moveq	0, $r1
+	addq	1, $r0
+	ax
+	addq	0, $r1
+
+	move.d	$r0, $r3
+	checkr3 0
+	move.d	$r1, $r3
+	checkr3 1
+
+	move.d  0, $r0
+	moveq	-1, $r1
+	subq	1, $r0
+	ax
+	subq	0, $r1
+
+	move.d	$r0, $r3
+	checkr3 ffffffff
+	move.d	$r1, $r3
+	checkr3 fffffffe
+
+
+	moveq	-1, $r0
+	moveq	-1, $r1
+	cmpq	-1, $r0
+	ax
+	cmpq	-1, $r1
+	beq	1f
+	nop
+	fail
+1:
+	cmpq	0, $r0
+	ax
+	cmpq	-1, $r1
+	bne	1f
+	nop
+	fail
+1:
+
+	;; test for broken X sequence, run it several times.
+	moveq	8, $r0
+1:
+	moveq	0, $r3
+	move.d	$r0, $r1
+	andq	1, $r1
+	lslq	4, $r1
+	moveq	1, $r2
+	or.d	$r1, $r2
+	ba	2f
+	move	$r2, $ccs
+2:
+	addq	0, $r3
+	move.d	$r0, $r4
+	move.d	$r1, $r5
+	move.d	$r2, $r6
+	move.d	$r3, $r7
+	lsrq	4, $r1
+	move.d	$r1, $r8
+	xor	$r1, $r3
+	checkr3	0
+	subq	1, $r0
+	bne	1b
+	nop
+
+	pass
+	quit
diff --git a/tests/tcg/cris/crisutils.h b/tests/tcg/cris/crisutils.h
new file mode 100644
index 0000000..29b71cd
--- /dev/null
+++ b/tests/tcg/cris/crisutils.h
@@ -0,0 +1,71 @@
+static char *tst_cc_loc = NULL;
+
+#define cris_tst_cc_init() \
+do { tst_cc_loc = "test_cc failed at " CURRENT_LOCATION; } while(0)
+
+/* We need a real symbol to signal error.  */
+void _err(void) {
+	if (!tst_cc_loc)
+		tst_cc_loc = "tst_cc_failed\n";
+	_fail(tst_cc_loc);
+}
+
+static inline void cris_tst_cc_n1(void)
+{
+	asm volatile ("bpl _err\n"
+		      "nop\n");
+}
+static inline void cris_tst_cc_n0(void)
+{
+	asm volatile ("bmi _err\n"
+		      "nop\n");
+}
+
+static inline void cris_tst_cc_z1(void)
+{
+	asm volatile ("bne _err\n"
+		      "nop\n");
+}
+static inline void cris_tst_cc_z0(void)
+{
+	asm volatile ("beq _err\n"
+		      "nop\n");
+}
+static inline void cris_tst_cc_v1(void)
+{
+	asm volatile ("bvc _err\n"
+		      "nop\n");
+}
+static inline void cris_tst_cc_v0(void)
+{
+	asm volatile ("bvs _err\n"
+		      "nop\n");
+}
+
+static inline void cris_tst_cc_c1(void)
+{
+	asm volatile ("bcc _err\n"
+		      "nop\n");
+}
+static inline void cris_tst_cc_c0(void)
+{
+	asm volatile ("bcs _err\n"
+		      "nop\n");
+}
+
+static inline void cris_tst_mov_cc(int n, int z)
+{
+	if (n) cris_tst_cc_n1(); else cris_tst_cc_n0();
+	if (z) cris_tst_cc_z1(); else cris_tst_cc_z0();
+	asm volatile ("" : : "g" (_err));
+}
+
+static inline void cris_tst_cc(const int n, const int z,
+			       const int v, const int c)
+{
+	if (n) cris_tst_cc_n1(); else cris_tst_cc_n0();
+	if (z) cris_tst_cc_z1(); else cris_tst_cc_z0();
+	if (v) cris_tst_cc_v1(); else cris_tst_cc_v0();
+	if (c) cris_tst_cc_c1(); else cris_tst_cc_c0();
+	asm volatile ("" : : "g" (_err));
+}
diff --git a/tests/tcg/cris/crt.s b/tests/tcg/cris/crt.s
new file mode 100644
index 0000000..af027d7
--- /dev/null
+++ b/tests/tcg/cris/crt.s
@@ -0,0 +1,13 @@
+	.data
+_stack_start:
+	.space	8192, 0
+_stack_end:
+	.text
+	.global	_start
+_start:
+	move.d	_stack_end, $sp
+	jsr	main
+	nop
+	moveq	0, $r10
+	jump	exit
+	nop
diff --git a/tests/tcg/cris/sys.c b/tests/tcg/cris/sys.c
new file mode 100644
index 0000000..551c5dd
--- /dev/null
+++ b/tests/tcg/cris/sys.c
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static inline int mystrlen(char *s) {
+	int i = 0;
+	while (s[i])
+		i++;
+	return i;
+}
+
+void pass(void) {
+	char s[] = "passed.\n";
+	write (1, s, sizeof (s) - 1);
+	exit (0);
+}
+
+void _fail(char *reason) {
+	char s[] = "\nfailed: ";
+	int len = mystrlen(reason);
+	write (1, s, sizeof (s) - 1);
+	write (1, reason, len);
+	write (1, "\n", 1);
+//	exit (1);
+}
+
+void *memset (void *s, int c, size_t n) {
+	char *p = s;
+	int i;
+	for (i = 0; i < n; i++)
+		p[i] = c;
+	return p;
+}
+
+void exit (int status) {
+	asm volatile ("moveq 1, $r9\n" /* NR_exit.  */
+		      "break 13\n");
+	while(1)
+		;
+}
+
+ssize_t write (int fd, const void *buf, size_t count) {
+	int r;
+	asm ("move.d %0, $r10\n"
+	     "move.d %1, $r11\n"
+	     "move.d %2, $r12\n"
+	     "moveq 4, $r9\n" /* NR_write.  */
+	     "break 13\n" : : "r" (fd), "r" (buf), "r" (count) : "memory");
+	asm ("move.d $r10, %0\n" : "=r" (r));
+	return r;
+}
diff --git a/tests/tcg/cris/sys.h b/tests/tcg/cris/sys.h
new file mode 100644
index 0000000..c5f88e1
--- /dev/null
+++ b/tests/tcg/cris/sys.h
@@ -0,0 +1,16 @@
+#include <unistd.h>
+
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+
+#define CURRENT_LOCATION __FILE__ ":" TOSTRING(__LINE__)
+
+#define err()                         \
+{                                     \
+  _fail("at " CURRENT_LOCATION " ");  \
+}
+
+#define mb() asm volatile ("" : : : "memory")
+
+void pass(void);
+void _fail(char *reason);
diff --git a/tests/tcg/cris/testutils.inc b/tests/tcg/cris/testutils.inc
new file mode 100644
index 0000000..aa1641b
--- /dev/null
+++ b/tests/tcg/cris/testutils.inc
@@ -0,0 +1,117 @@
+	.syntax	no_register_prefix
+
+	.macro	start
+	.text
+	.global	main
+main:
+	.endm
+
+	.macro	quit
+	jump	pass
+	nop
+	.endm
+
+	.macro	pass
+	jump	pass
+	nop
+	.endm
+
+	.macro	startnostack
+	start
+	.endm
+
+	.macro	fail
+	.data
+99:
+	.asciz " checkr3 failed\n"
+	.text
+	move.d	99b, $r10
+	jsr	_fail
+	nop
+	.endm
+
+	.macro	checkr3 val
+	cmp.d	0x\val, $r3
+	beq	100f
+	nop
+	.data
+99:
+	.asciz "checkr3 failed\n"
+	.text
+	move.d	99b, $r10
+	jsr	_fail
+	nop
+100:
+	.endm
+
+; Test the condition codes
+        .macro test_cc N Z V C
+        .if \N
+        bpl 9f
+        nop
+        .else
+        bmi 9f
+        nop
+        .endif
+        .if \Z
+        bne 9f
+        nop
+        .else
+        beq 9f
+        nop
+        .endif
+        .if \V
+        bvc 9f
+        nop
+        .else
+        bvs 9f
+        nop
+        .endif
+        .if \C
+        bcc 9f
+        nop
+        .else
+        bcs 9f
+        nop
+        .endif
+        ba 8f
+        nop
+9:
+	.data
+99:
+	.asciz "test_move_cc failed\n"
+	.text
+	move.d	99b, $r10
+	jsr	_fail
+	nop
+8:
+        .endm
+
+
+        .macro test_move_cc N Z V C
+        .if \N
+        bpl 9f
+        nop
+        .else
+        bmi 9f
+        nop
+        .endif
+        .if \Z
+        bne 9f
+        nop
+        .else
+        beq 9f
+        nop
+        .endif
+        ba 8f
+        nop
+9:
+	.data
+99:
+	.asciz "test_move_cc failed\n"
+	.text
+	move.d	99b, $r10
+	jsr	_fail
+	nop
+8:
+        .endm
diff --git a/tests/tcg/hello-arm.c b/tests/tcg/hello-arm.c
new file mode 100644
index 0000000..e0daa7a
--- /dev/null
+++ b/tests/tcg/hello-arm.c
@@ -0,0 +1,113 @@
+#define __NR_SYSCALL_BASE	0x900000
+#define __NR_exit1			(__NR_SYSCALL_BASE+  1)
+#define __NR_write			(__NR_SYSCALL_BASE+  4)
+
+#define __sys2(x) #x
+#define __sys1(x) __sys2(x)
+
+#ifndef __syscall
+#define __syscall(name) "swi\t" __sys1(__NR_##name) "\n\t"
+#endif
+
+#define __syscall_return(type, res)					\
+do {									\
+	return (type) (res);						\
+} while (0)
+
+#define _syscall0(type,name)						\
+type name(void) {							\
+  long __res;								\
+  __asm__ __volatile__ (						\
+  __syscall(name)							\
+  "mov %0,r0"								\
+  :"=r" (__res) : : "r0","lr");						\
+  __syscall_return(type,__res);						\
+}
+
+#define _syscall1(type,name,type1,arg1)					\
+type name(type1 arg1) {							\
+  long __res;								\
+  __asm__ __volatile__ (						\
+  "mov\tr0,%1\n\t"							\
+  __syscall(name)							\
+  "mov %0,r0"								\
+        : "=r" (__res)							\
+        : "r" ((long)(arg1))						\
+	: "r0","lr");							\
+  __syscall_return(type,__res);						\
+}
+
+#define _syscall2(type,name,type1,arg1,type2,arg2)			\
+type name(type1 arg1,type2 arg2) {					\
+  long __res;								\
+  __asm__ __volatile__ (						\
+  "mov\tr0,%1\n\t"							\
+  "mov\tr1,%2\n\t"							\
+  __syscall(name)							\
+  "mov\t%0,r0"								\
+        : "=r" (__res)							\
+        : "r" ((long)(arg1)),"r" ((long)(arg2))				\
+	: "r0","r1","lr");						\
+  __syscall_return(type,__res);						\
+}
+
+
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)		\
+type name(type1 arg1,type2 arg2,type3 arg3) {				\
+  long __res;								\
+  __asm__ __volatile__ (						\
+  "mov\tr0,%1\n\t"							\
+  "mov\tr1,%2\n\t"							\
+  "mov\tr2,%3\n\t"							\
+  __syscall(name)							\
+  "mov\t%0,r0"								\
+        : "=r" (__res)							\
+        : "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3))	\
+        : "r0","r1","r2","lr");						\
+  __syscall_return(type,__res);						\
+}
+
+
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)		\
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) {				\
+  long __res;										\
+  __asm__ __volatile__ (								\
+  "mov\tr0,%1\n\t"									\
+  "mov\tr1,%2\n\t"									\
+  "mov\tr2,%3\n\t"									\
+  "mov\tr3,%4\n\t"									\
+  __syscall(name)									\
+  "mov\t%0,r0"										\
+  	: "=r" (__res)									\
+  	: "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)),"r" ((long)(arg4))	\
+  	: "r0","r1","r2","r3","lr");							\
+  __syscall_return(type,__res);								\
+}
+
+
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5)	\
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) {			\
+  long __res;										\
+  __asm__ __volatile__ (								\
+  "mov\tr0,%1\n\t"									\
+  "mov\tr1,%2\n\t"									\
+  "mov\tr2,%3\n\t"									\
+  "mov\tr3,%4\n\t"									\
+  "mov\tr4,%5\n\t"									\
+  __syscall(name)									\
+  "mov\t%0,r0"										\
+  	: "=r" (__res)									\
+  	: "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)),"r" ((long)(arg4)),	\
+	  "r" ((long)(arg5))								\
+	: "r0","r1","r2","r3","r4","lr");						\
+  __syscall_return(type,__res);								\
+}
+
+_syscall1(int,exit1,int,status);
+_syscall3(int,write,int,fd,const char *,buf, int, len);
+
+void _start(void)
+{
+    write(1, "Hello World\n", 12);
+    exit1(0);
+}
diff --git a/tests/tcg/hello-i386.c b/tests/tcg/hello-i386.c
new file mode 100644
index 0000000..86afc34
--- /dev/null
+++ b/tests/tcg/hello-i386.c
@@ -0,0 +1,26 @@
+#include <asm/unistd.h>
+
+static inline volatile void exit(int status)
+{
+  int __res;
+  __asm__ volatile ("movl %%ecx,%%ebx\n"\
+		    "int $0x80" \
+		    :  "=a" (__res) : "0" (__NR_exit),"c" ((long)(status)));
+}
+
+static inline int write(int fd, const char * buf, int len)
+{
+  int status;
+  __asm__ volatile ("pushl %%ebx\n"\
+		    "movl %%esi,%%ebx\n"\
+		    "int $0x80\n" \
+		    "popl %%ebx\n"\
+		    : "=a" (status) \
+		    : "0" (__NR_write),"S" ((long)(fd)),"c" ((long)(buf)),"d" ((long)(len)));
+}
+
+void _start(void)
+{
+    write(1, "Hello World\n", 12);
+    exit(0);
+}
diff --git a/tests/tcg/hello-mips.c b/tests/tcg/hello-mips.c
new file mode 100644
index 0000000..f825673
--- /dev/null
+++ b/tests/tcg/hello-mips.c
@@ -0,0 +1,64 @@
+/*
+* MIPS o32 Linux syscall example
+*
+* http://www.linux-mips.org/wiki/RISC/os
+* http://www.linux-mips.org/wiki/MIPSABIHistory
+* http://www.linux.com/howtos/Assembly-HOWTO/mips.shtml
+*
+* mipsel-linux-gcc -nostdlib -mno-abicalls -fno-PIC -mabi=32 \
+*                  -O2 -static -o hello-mips hello-mips.c
+*
+*/
+#define __NR_SYSCALL_BASE	4000
+#define __NR_exit			(__NR_SYSCALL_BASE+  1)
+#define __NR_write			(__NR_SYSCALL_BASE+  4)
+
+static inline void exit1(int status)
+{
+    register unsigned long __a0 asm("$4") = (unsigned long) status;
+
+    __asm__ __volatile__ (
+        "	.set push	\n"
+        "	.set noreorder	\n"
+        "	li	$2, %0	\n"
+        "	syscall		\n"
+        "	.set pop	"
+        :
+	: "i" (__NR_exit), "r" (__a0)
+	: "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24",
+	  "memory");
+}
+
+static inline int write(int fd, const char *buf, int len)
+{
+    register unsigned long __a0 asm("$4") = (unsigned long) fd;
+    register unsigned long __a1 asm("$5") = (unsigned long) buf;
+    register unsigned long __a2 asm("$6") = (unsigned long) len;
+    register unsigned long __a3 asm("$7");
+    unsigned long __v0;
+
+    __asm__ __volatile__ (
+        "	.set push	\n"
+        "	.set noreorder	\n"
+        "	li	$2, %2	\n"
+        "	syscall		\n"
+        "	move	%0, $2	\n"
+        "	.set pop	"
+        : "=r" (__v0), "=r" (__a3)
+        : "i" (__NR_write), "r" (__a0), "r" (__a1), "r" (__a2)
+	: "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24",
+	  "memory");
+
+/*    if (__a3 == 0) */
+        return (int) __v0;
+/*
+    errno = __v0;
+    return -1;
+ */
+}
+
+void __start(void)
+{
+    write (1, "Hello, World!\n", 14);
+    exit1 (42);
+}
diff --git a/tests/tcg/linux-test.c b/tests/tcg/linux-test.c
new file mode 100644
index 0000000..2e4a746
--- /dev/null
+++ b/tests/tcg/linux-test.c
@@ -0,0 +1,537 @@
+/*
+ *  linux and CPU test
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <utime.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sched.h>
+#include <dirent.h>
+#include <setjmp.h>
+#include <sys/shm.h>
+
+#define TESTPATH "/tmp/linux-test.tmp"
+#define TESTPORT 7654
+#define STACK_SIZE 16384
+
+void error1(const char *filename, int line, const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    fprintf(stderr, "%s:%d: ", filename, line);
+    vfprintf(stderr, fmt, ap);
+    fprintf(stderr, "\n");
+    va_end(ap);
+    exit(1);
+}
+
+int __chk_error(const char *filename, int line, int ret)
+{
+    if (ret < 0) {
+        error1(filename, line, "%m (ret=%d, errno=%d)",
+               ret, errno);
+    }
+    return ret;
+}
+
+#define error(fmt, ...) error1(__FILE__, __LINE__, fmt, ## __VA_ARGS__)
+
+#define chk_error(ret) __chk_error(__FILE__, __LINE__, (ret))
+
+/*******************************************************/
+
+#define FILE_BUF_SIZE 300
+
+void test_file(void)
+{
+    int fd, i, len, ret;
+    uint8_t buf[FILE_BUF_SIZE];
+    uint8_t buf2[FILE_BUF_SIZE];
+    uint8_t buf3[FILE_BUF_SIZE];
+    char cur_dir[1024];
+    struct stat st;
+    struct utimbuf tbuf;
+    struct iovec vecs[2];
+    DIR *dir;
+    struct dirent *de;
+
+    /* clean up, just in case */
+    unlink(TESTPATH "/file1");
+    unlink(TESTPATH "/file2");
+    unlink(TESTPATH "/file3");
+    rmdir(TESTPATH);
+
+    if (getcwd(cur_dir, sizeof(cur_dir)) == NULL)
+        error("getcwd");
+
+    chk_error(mkdir(TESTPATH, 0755));
+
+    chk_error(chdir(TESTPATH));
+
+    /* open/read/write/close/readv/writev/lseek */
+
+    fd = chk_error(open("file1", O_WRONLY | O_TRUNC | O_CREAT, 0644));
+    for(i=0;i < FILE_BUF_SIZE; i++)
+        buf[i] = i;
+    len = chk_error(write(fd, buf, FILE_BUF_SIZE / 2));
+    if (len != (FILE_BUF_SIZE / 2))
+        error("write");
+    vecs[0].iov_base = buf + (FILE_BUF_SIZE / 2);
+    vecs[0].iov_len = 16;
+    vecs[1].iov_base = buf + (FILE_BUF_SIZE / 2) + 16;
+    vecs[1].iov_len = (FILE_BUF_SIZE / 2) - 16;
+    len = chk_error(writev(fd, vecs, 2));
+    if (len != (FILE_BUF_SIZE / 2))
+     error("writev");
+    chk_error(close(fd));
+
+    chk_error(rename("file1", "file2"));
+
+    fd = chk_error(open("file2", O_RDONLY));
+
+    len = chk_error(read(fd, buf2, FILE_BUF_SIZE));
+    if (len != FILE_BUF_SIZE)
+        error("read");
+    if (memcmp(buf, buf2, FILE_BUF_SIZE) != 0)
+        error("memcmp");
+
+#define FOFFSET 16
+    ret = chk_error(lseek(fd, FOFFSET, SEEK_SET));
+    if (ret != 16)
+        error("lseek");
+    vecs[0].iov_base = buf3;
+    vecs[0].iov_len = 32;
+    vecs[1].iov_base = buf3 + 32;
+    vecs[1].iov_len = FILE_BUF_SIZE - FOFFSET - 32;
+    len = chk_error(readv(fd, vecs, 2));
+    if (len != FILE_BUF_SIZE - FOFFSET)
+        error("readv");
+    if (memcmp(buf + FOFFSET, buf3, FILE_BUF_SIZE - FOFFSET) != 0)
+        error("memcmp");
+
+    chk_error(close(fd));
+
+    /* access */
+    chk_error(access("file2", R_OK));
+
+    /* stat/chmod/utime/truncate */
+
+    chk_error(chmod("file2", 0600));
+    tbuf.actime = 1001;
+    tbuf.modtime = 1000;
+    chk_error(truncate("file2", 100));
+    chk_error(utime("file2", &tbuf));
+    chk_error(stat("file2", &st));
+    if (st.st_size != 100)
+        error("stat size");
+    if (!S_ISREG(st.st_mode))
+        error("stat mode");
+    if ((st.st_mode & 0777) != 0600)
+        error("stat mode2");
+    if (st.st_atime != 1001 ||
+        st.st_mtime != 1000)
+        error("stat time");
+
+    chk_error(stat(TESTPATH, &st));
+    if (!S_ISDIR(st.st_mode))
+        error("stat mode");
+
+    /* fstat */
+    fd = chk_error(open("file2", O_RDWR));
+    chk_error(ftruncate(fd, 50));
+    chk_error(fstat(fd, &st));
+    chk_error(close(fd));
+
+    if (st.st_size != 50)
+        error("stat size");
+    if (!S_ISREG(st.st_mode))
+        error("stat mode");
+
+    /* symlink/lstat */
+    chk_error(symlink("file2", "file3"));
+    chk_error(lstat("file3", &st));
+    if (!S_ISLNK(st.st_mode))
+        error("stat mode");
+
+    /* getdents */
+    dir = opendir(TESTPATH);
+    if (!dir)
+        error("opendir");
+    len = 0;
+    for(;;) {
+        de = readdir(dir);
+        if (!de)
+            break;
+        if (strcmp(de->d_name, ".") != 0 &&
+            strcmp(de->d_name, "..") != 0 &&
+            strcmp(de->d_name, "file2") != 0 &&
+            strcmp(de->d_name, "file3") != 0)
+            error("readdir");
+        len++;
+    }
+    closedir(dir);
+    if (len != 4)
+        error("readdir");
+
+    chk_error(unlink("file3"));
+    chk_error(unlink("file2"));
+    chk_error(chdir(cur_dir));
+    chk_error(rmdir(TESTPATH));
+}
+
+void test_fork(void)
+{
+    int pid, status;
+
+    pid = chk_error(fork());
+    if (pid == 0) {
+        /* child */
+        exit(2);
+    }
+    chk_error(waitpid(pid, &status, 0));
+    if (!WIFEXITED(status) || WEXITSTATUS(status) != 2)
+        error("waitpid status=0x%x", status);
+}
+
+void test_time(void)
+{
+    struct timeval tv, tv2;
+    struct timespec ts, rem;
+    struct rusage rusg1, rusg2;
+    int ti, i;
+
+    chk_error(gettimeofday(&tv, NULL));
+    rem.tv_sec = 1;
+    ts.tv_sec = 0;
+    ts.tv_nsec = 20 * 1000000;
+    chk_error(nanosleep(&ts, &rem));
+    if (rem.tv_sec != 1)
+        error("nanosleep");
+    chk_error(gettimeofday(&tv2, NULL));
+    ti = tv2.tv_sec - tv.tv_sec;
+    if (ti >= 2)
+        error("gettimeofday");
+
+    chk_error(getrusage(RUSAGE_SELF, &rusg1));
+    for(i = 0;i < 10000; i++);
+    chk_error(getrusage(RUSAGE_SELF, &rusg2));
+    if ((rusg2.ru_utime.tv_sec - rusg1.ru_utime.tv_sec) < 0 ||
+        (rusg2.ru_stime.tv_sec - rusg1.ru_stime.tv_sec) < 0)
+        error("getrusage");
+}
+
+void pstrcpy(char *buf, int buf_size, const char *str)
+{
+    int c;
+    char *q = buf;
+
+    if (buf_size <= 0)
+        return;
+
+    for(;;) {
+        c = *str++;
+        if (c == 0 || q >= buf + buf_size - 1)
+            break;
+        *q++ = c;
+    }
+    *q = '\0';
+}
+
+/* strcat and truncate. */
+char *pstrcat(char *buf, int buf_size, const char *s)
+{
+    int len;
+    len = strlen(buf);
+    if (len < buf_size)
+        pstrcpy(buf + len, buf_size - len, s);
+    return buf;
+}
+
+int server_socket(void)
+{
+    int val, fd;
+    struct sockaddr_in sockaddr;
+
+    /* server socket */
+    fd = chk_error(socket(PF_INET, SOCK_STREAM, 0));
+
+    val = 1;
+    chk_error(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)));
+
+    sockaddr.sin_family = AF_INET;
+    sockaddr.sin_port = htons(TESTPORT);
+    sockaddr.sin_addr.s_addr = 0;
+    chk_error(bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)));
+    chk_error(listen(fd, 0));
+    return fd;
+
+}
+
+int client_socket(void)
+{
+    int fd;
+    struct sockaddr_in sockaddr;
+
+    /* server socket */
+    fd = chk_error(socket(PF_INET, SOCK_STREAM, 0));
+    sockaddr.sin_family = AF_INET;
+    sockaddr.sin_port = htons(TESTPORT);
+    inet_aton("127.0.0.1", &sockaddr.sin_addr);
+    chk_error(connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)));
+    return fd;
+}
+
+const char socket_msg[] = "hello socket\n";
+
+void test_socket(void)
+{
+    int server_fd, client_fd, fd, pid, ret, val;
+    struct sockaddr_in sockaddr;
+    socklen_t len;
+    char buf[512];
+
+    server_fd = server_socket();
+
+    /* test a few socket options */
+    len = sizeof(val);
+    chk_error(getsockopt(server_fd, SOL_SOCKET, SO_TYPE, &val, &len));
+    if (val != SOCK_STREAM)
+        error("getsockopt");
+
+    pid = chk_error(fork());
+    if (pid == 0) {
+        client_fd = client_socket();
+        send(client_fd, socket_msg, sizeof(socket_msg), 0);
+        close(client_fd);
+        exit(0);
+    }
+    len = sizeof(sockaddr);
+    fd = chk_error(accept(server_fd, (struct sockaddr *)&sockaddr, &len));
+
+    ret = chk_error(recv(fd, buf, sizeof(buf), 0));
+    if (ret != sizeof(socket_msg))
+        error("recv");
+    if (memcmp(buf, socket_msg, sizeof(socket_msg)) != 0)
+        error("socket_msg");
+    chk_error(close(fd));
+    chk_error(close(server_fd));
+}
+
+#define WCOUNT_MAX 512
+
+void test_pipe(void)
+{
+    fd_set rfds, wfds;
+    int fds[2], fd_max, ret;
+    uint8_t ch;
+    int wcount, rcount;
+
+    chk_error(pipe(fds));
+    chk_error(fcntl(fds[0], F_SETFL, O_NONBLOCK));
+    chk_error(fcntl(fds[1], F_SETFL, O_NONBLOCK));
+    wcount = 0;
+    rcount = 0;
+    for(;;) {
+        FD_ZERO(&rfds);
+        fd_max = fds[0];
+        FD_SET(fds[0], &rfds);
+
+        FD_ZERO(&wfds);
+        FD_SET(fds[1], &wfds);
+        if (fds[1] > fd_max)
+            fd_max = fds[1];
+
+        ret = chk_error(select(fd_max + 1, &rfds, &wfds, NULL, NULL));
+        if (ret > 0) {
+            if (FD_ISSET(fds[0], &rfds)) {
+                chk_error(read(fds[0], &ch, 1));
+                rcount++;
+                if (rcount >= WCOUNT_MAX)
+                    break;
+            }
+            if (FD_ISSET(fds[1], &wfds)) {
+                ch = 'a';
+                chk_error(write(fds[0], &ch, 1));
+                wcount++;
+            }
+        }
+    }
+    chk_error(close(fds[0]));
+    chk_error(close(fds[1]));
+}
+
+int thread1_res;
+int thread2_res;
+
+int thread1_func(void *arg)
+{
+    int i;
+    for(i=0;i<5;i++) {
+        thread1_res++;
+        usleep(10 * 1000);
+    }
+    return 0;
+}
+
+int thread2_func(void *arg)
+{
+    int i;
+    for(i=0;i<6;i++) {
+        thread2_res++;
+        usleep(10 * 1000);
+    }
+    return 0;
+}
+
+void test_clone(void)
+{
+    uint8_t *stack1, *stack2;
+    int pid1, pid2, status1, status2;
+
+    stack1 = malloc(STACK_SIZE);
+    pid1 = chk_error(clone(thread1_func, stack1 + STACK_SIZE,
+                           CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello1"));
+
+    stack2 = malloc(STACK_SIZE);
+    pid2 = chk_error(clone(thread2_func, stack2 + STACK_SIZE,
+                           CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello2"));
+
+    while (waitpid(pid1, &status1, 0) != pid1);
+    free(stack1);
+    while (waitpid(pid2, &status2, 0) != pid2);
+    free(stack2);
+    if (thread1_res != 5 ||
+        thread2_res != 6)
+        error("clone");
+}
+
+/***********************************/
+
+volatile int alarm_count;
+jmp_buf jmp_env;
+
+void sig_alarm(int sig)
+{
+    if (sig != SIGALRM)
+        error("signal");
+    alarm_count++;
+}
+
+void sig_segv(int sig, siginfo_t *info, void *puc)
+{
+    if (sig != SIGSEGV)
+        error("signal");
+    longjmp(jmp_env, 1);
+}
+
+void test_signal(void)
+{
+    struct sigaction act;
+    struct itimerval it, oit;
+
+    /* timer test */
+
+    alarm_count = 0;
+
+    act.sa_handler = sig_alarm;
+    sigemptyset(&act.sa_mask);
+    act.sa_flags = 0;
+    chk_error(sigaction(SIGALRM, &act, NULL));
+
+    it.it_interval.tv_sec = 0;
+    it.it_interval.tv_usec = 10 * 1000;
+    it.it_value.tv_sec = 0;
+    it.it_value.tv_usec = 10 * 1000;
+    chk_error(setitimer(ITIMER_REAL, &it, NULL));
+    chk_error(getitimer(ITIMER_REAL, &oit));
+    if (oit.it_value.tv_sec != it.it_value.tv_sec ||
+        oit.it_value.tv_usec != it.it_value.tv_usec)
+        error("itimer");
+
+    while (alarm_count < 5) {
+        usleep(10 * 1000);
+    }
+
+    it.it_interval.tv_sec = 0;
+    it.it_interval.tv_usec = 0;
+    it.it_value.tv_sec = 0;
+    it.it_value.tv_usec = 0;
+    memset(&oit, 0xff, sizeof(oit));
+    chk_error(setitimer(ITIMER_REAL, &it, &oit));
+    if (oit.it_value.tv_sec != 0 ||
+        oit.it_value.tv_usec != 10 * 1000)
+        error("setitimer");
+
+    /* SIGSEGV test */
+    act.sa_sigaction = sig_segv;
+    sigemptyset(&act.sa_mask);
+    act.sa_flags = SA_SIGINFO;
+    chk_error(sigaction(SIGSEGV, &act, NULL));
+    if (setjmp(jmp_env) == 0) {
+        *(uint8_t *)0 = 0;
+    }
+
+    act.sa_handler = SIG_DFL;
+    sigemptyset(&act.sa_mask);
+    act.sa_flags = 0;
+    chk_error(sigaction(SIGSEGV, &act, NULL));
+}
+
+#define SHM_SIZE 32768
+
+void test_shm(void)
+{
+    void *ptr;
+    int shmid;
+
+    shmid = chk_error(shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0777));
+    ptr = shmat(shmid, NULL, 0);
+    if (!ptr)
+        error("shmat");
+
+    memset(ptr, 0, SHM_SIZE);
+
+    chk_error(shmctl(shmid, IPC_RMID, 0));
+    chk_error(shmdt(ptr));
+}
+
+int main(int argc, char **argv)
+{
+    test_file();
+    test_fork();
+    test_time();
+    test_socket();
+    //    test_clone();
+    test_signal();
+    test_shm();
+    return 0;
+}
diff --git a/tests/tcg/lm32/Makefile b/tests/tcg/lm32/Makefile
new file mode 100644
index 0000000..03a1abb
--- /dev/null
+++ b/tests/tcg/lm32/Makefile
@@ -0,0 +1,102 @@
+-include ../../config-host.mak
+
+CROSS=lm32-elf-
+
+SIM = qemu-system-lm32
+SIMFLAGS = -M lm32-evr -nographic -device lm32-sys -net none -kernel
+
+CC      = $(CROSS)gcc
+AS      = $(CROSS)as
+AS      = $(CC) -x assembler
+SIZE    = $(CROSS)size
+LD      = $(CC)
+OBJCOPY = $(CROSS)objcopy
+
+LDFLAGS = -Tlinker.ld
+
+CRT        = crt.o
+TESTCASES += test_add.tst
+TESTCASES += test_addi.tst
+TESTCASES += test_and.tst
+TESTCASES += test_andhi.tst
+TESTCASES += test_andi.tst
+TESTCASES += test_b.tst
+TESTCASES += test_be.tst
+TESTCASES += test_bg.tst
+TESTCASES += test_bge.tst
+TESTCASES += test_bgeu.tst
+TESTCASES += test_bgu.tst
+TESTCASES += test_bi.tst
+TESTCASES += test_bne.tst
+TESTCASES += test_break.tst
+TESTCASES += test_bret.tst
+TESTCASES += test_call.tst
+TESTCASES += test_calli.tst
+TESTCASES += test_cmpe.tst
+TESTCASES += test_cmpei.tst
+TESTCASES += test_cmpg.tst
+TESTCASES += test_cmpgi.tst
+TESTCASES += test_cmpge.tst
+TESTCASES += test_cmpgei.tst
+TESTCASES += test_cmpgeu.tst
+TESTCASES += test_cmpgeui.tst
+TESTCASES += test_cmpgu.tst
+TESTCASES += test_cmpgui.tst
+TESTCASES += test_cmpne.tst
+TESTCASES += test_cmpnei.tst
+TESTCASES += test_divu.tst
+TESTCASES += test_eret.tst
+TESTCASES += test_lb.tst
+TESTCASES += test_lbu.tst
+TESTCASES += test_lh.tst
+TESTCASES += test_lhu.tst
+TESTCASES += test_lw.tst
+TESTCASES += test_modu.tst
+TESTCASES += test_mul.tst
+TESTCASES += test_muli.tst
+TESTCASES += test_nor.tst
+TESTCASES += test_nori.tst
+TESTCASES += test_or.tst
+TESTCASES += test_ori.tst
+TESTCASES += test_orhi.tst
+#TESTCASES += test_rcsr.tst
+TESTCASES += test_ret.tst
+TESTCASES += test_sb.tst
+TESTCASES += test_scall.tst
+TESTCASES += test_sextb.tst
+TESTCASES += test_sexth.tst
+TESTCASES += test_sh.tst
+TESTCASES += test_sl.tst
+TESTCASES += test_sli.tst
+TESTCASES += test_sr.tst
+TESTCASES += test_sri.tst
+TESTCASES += test_sru.tst
+TESTCASES += test_srui.tst
+TESTCASES += test_sub.tst
+TESTCASES += test_sw.tst
+#TESTCASES += test_wcsr.tst
+TESTCASES += test_xnor.tst
+TESTCASES += test_xnori.tst
+TESTCASES += test_xor.tst
+TESTCASES += test_xori.tst
+
+all: build
+
+%.o: $(SRC_PATH)/tests/lm32/%.c
+	$(CC) $(CFLAGS) -c $< -o $@
+
+%.o: $(SRC_PATH)/tests/lm32/%.S
+	$(AS) $(ASFLAGS) -c $< -o $@
+
+%.tst: %.o macros.inc $(CRT)
+	$(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $< -o $@
+
+build: $(CRT) $(TESTCASES)
+
+check: $(CRT) $(SYS) $(TESTCASES)
+	@for case in $(TESTCASES); do \
+		$(SIM) $(SIMFLAGS) ./$$case; \
+	done
+
+clean:
+	$(RM) -fr $(TESTCASES) $(CRT)
diff --git a/tests/tcg/lm32/crt.S b/tests/tcg/lm32/crt.S
new file mode 100644
index 0000000..5f9cfd9
--- /dev/null
+++ b/tests/tcg/lm32/crt.S
@@ -0,0 +1,84 @@
+.text
+.global _start
+
+_start:
+_reset_handler:
+	xor r0, r0, r0
+	mvhi r1, hi(_start)
+	ori r1, r1, lo(_start)
+	wcsr eba, r1
+	wcsr deba, r1
+	bi _main
+	nop
+	nop
+
+_breakpoint_handler:
+	ori r25, r25, 1
+	addi ra, ba, 4
+	ret
+	nop
+	nop
+	nop
+	nop
+	nop
+
+_instruction_bus_error_handler:
+	ori r25, r25, 2
+	addi ra, ea, 4
+	ret
+	nop
+	nop
+	nop
+	nop
+	nop
+
+_watchpoint_handler:
+	ori r25, r25, 4
+	addi ra, ba, 4
+	ret
+	nop
+	nop
+	nop
+	nop
+	nop
+
+_data_bus_error_handler:
+	ori r25, r25, 8
+	addi ra, ea, 4
+	ret
+	nop
+	nop
+	nop
+	nop
+	nop
+
+_divide_by_zero_handler:
+	ori r25, r25, 16
+	addi ra, ea, 4
+	ret
+	nop
+	nop
+	nop
+	nop
+	nop
+
+_interrupt_handler:
+	ori r25, r25, 32
+	addi ra, ea, 4
+	ret
+	nop
+	nop
+	nop
+	nop
+	nop
+
+_system_call_handler:
+	ori r25, r25, 64
+	addi ra, ea, 4
+	ret
+	nop
+	nop
+	nop
+	nop
+	nop
+
diff --git a/tests/tcg/lm32/linker.ld b/tests/tcg/lm32/linker.ld
new file mode 100644
index 0000000..52d43a4
--- /dev/null
+++ b/tests/tcg/lm32/linker.ld
@@ -0,0 +1,55 @@
+OUTPUT_FORMAT("elf32-lm32")
+ENTRY(_start)
+
+__DYNAMIC = 0;
+
+MEMORY {
+	ram : ORIGIN = 0x08000000, LENGTH = 0x04000000  /* 64M */
+}
+
+SECTIONS
+{
+	.text :
+	{
+		_ftext = .;
+		*(.text .stub .text.* .gnu.linkonce.t.*)
+		_etext = .;
+	} > ram
+
+	.rodata :
+	{
+		. = ALIGN(4);
+		_frodata = .;
+		*(.rodata .rodata.* .gnu.linkonce.r.*)
+		*(.rodata1)
+		_erodata = .;
+	} > ram
+
+	.data :
+	{
+		. = ALIGN(4);
+		_fdata = .;
+		*(.data .data.* .gnu.linkonce.d.*)
+		*(.data1)
+		_gp = ALIGN(16);
+		*(.sdata .sdata.* .gnu.linkonce.s.*)
+		_edata = .;
+	} > ram
+
+	.bss :
+	{
+		. = ALIGN(4);
+		_fbss = .;
+		*(.dynsbss)
+		*(.sbss .sbss.* .gnu.linkonce.sb.*)
+		*(.scommon)
+		*(.dynbss)
+		*(.bss .bss.* .gnu.linkonce.b.*)
+		*(COMMON)
+		_ebss = .;
+		_end = .;
+	} > ram
+}
+
+PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4);
+
diff --git a/tests/tcg/lm32/macros.inc b/tests/tcg/lm32/macros.inc
new file mode 100644
index 0000000..367c7c5
--- /dev/null
+++ b/tests/tcg/lm32/macros.inc
@@ -0,0 +1,79 @@
+
+.macro test_name name
+	.data
+tn_\name:
+	.asciz "\name"
+	.text
+	mvhi r13, hi(tn_\name)
+	ori r13, r13, lo(tn_\name)
+	sw (r12+8), r13
+.endm
+
+.macro load reg val
+	mvhi \reg, hi(\val)
+	ori \reg, \reg, lo(\val)
+.endm
+
+.macro tc_pass
+	mvi r13, 0
+	sw (r12+4), r13
+.endm
+
+.macro tc_fail
+	mvi r13, 1
+	sw (r12+4), r13
+.endm
+
+.macro check_r3 val
+	mvhi r13, hi(\val)
+	ori r13, r13, lo(\val)
+	be r3, r13, 1f
+	tc_fail
+	bi 2f
+1:
+	tc_pass
+2:
+.endm
+
+.macro check_mem adr val
+	mvhi r13, hi(\adr)
+	ori r13, r13, lo(\adr)
+	mvhi r14, hi(\val)
+	ori r14, r14, lo(\val)
+	lw r13, (r13+0)
+	be r13, r14, 1f
+	tc_fail
+	bi 2f
+1:
+	tc_pass
+2:
+.endm
+
+.macro check_excp excp
+	andi r13, r25, \excp
+	bne r13, r0, 1f
+	tc_fail
+	bi 2f
+1:
+	tc_pass
+2:
+.endm
+
+.macro start
+	.global _main
+	.text
+_main:
+	mvhi r12, hi(0xffff0000)      # base address of test block
+	ori r12, r12, lo(0xffff0000)
+.endm
+
+.macro end
+	sw (r12+0), r0
+1:
+	bi 1b
+.endm
+
+# base +
+#  0  ctrl
+#  4  pass/fail
+#  8  ptr to test name
diff --git a/tests/tcg/lm32/test_add.S b/tests/tcg/lm32/test_add.S
new file mode 100644
index 0000000..030ad19
--- /dev/null
+++ b/tests/tcg/lm32/test_add.S
@@ -0,0 +1,75 @@
+.include "macros.inc"
+
+start
+
+test_name ADD_1
+mvi r1, 0
+mvi r2, 0
+add r3, r1, r2
+check_r3 0
+
+test_name ADD_2
+mvi r1, 0
+mvi r2, 1
+add r3, r1, r2
+check_r3 1
+
+test_name ADD_3
+mvi r1, 1
+mvi r2, 0
+add r3, r1, r2
+check_r3 1
+
+test_name ADD_4
+mvi r1, 1
+mvi r2, -1
+add r3, r1, r2
+check_r3 0
+
+test_name ADD_5
+mvi r1, -1
+mvi r2, 1
+add r3, r1, r2
+check_r3 0
+
+test_name ADD_6
+mvi r1, -1
+mvi r2, 0
+add r3, r1, r2
+check_r3 -1
+
+test_name ADD_7
+mvi r1, 0
+mvi r2, -1
+add r3, r1, r2
+check_r3 -1
+
+test_name ADD_8
+mvi r3, 2
+add r3, r3, r3
+check_r3 4
+
+test_name ADD_9
+mvi r1, 4
+mvi r3, 2
+add r3, r1, r3
+check_r3 6
+
+test_name ADD_10
+mvi r1, 4
+mvi r3, 2
+add r3, r3, r1
+check_r3 6
+
+test_name ADD_11
+mvi r1, 4
+add r3, r1, r1
+check_r3 8
+
+test_name ADD_12
+load r1 0x12345678
+load r2 0xabcdef97
+add r3, r1, r2
+check_r3 0xbe02460f
+
+end
diff --git a/tests/tcg/lm32/test_addi.S b/tests/tcg/lm32/test_addi.S
new file mode 100644
index 0000000..68e766d
--- /dev/null
+++ b/tests/tcg/lm32/test_addi.S
@@ -0,0 +1,56 @@
+.include "macros.inc"
+
+start
+
+test_name ADDI_1
+mvi r1, 0
+addi r3, r1, 0
+check_r3 0
+
+test_name ADDI_2
+mvi r1, 0
+addi r3, r1, 1
+check_r3 1
+
+test_name ADDI_3
+mvi r1, 1
+addi r3, r1, 0
+check_r3 1
+
+test_name ADDI_4
+mvi r1, 1
+addi r3, r1, -1
+check_r3 0
+
+test_name ADDI_5
+mvi r1, -1
+addi r3, r1, 1
+check_r3 0
+
+test_name ADDI_6
+mvi r1, -1
+addi r3, r1, 0
+check_r3 -1
+
+test_name ADDI_7
+mvi r1, 0
+addi r3, r1, -1
+check_r3 -1
+
+test_name ADDI_8
+mvi r3, 4
+addi r3, r3, 4
+check_r3 8
+
+test_name ADDI_9
+mvi r3, 4
+addi r3, r3, -4
+check_r3 0
+
+test_name ADDI_10
+mvi r3, 4
+addi r3, r3, -5
+check_r3 -1
+
+end
+
diff --git a/tests/tcg/lm32/test_and.S b/tests/tcg/lm32/test_and.S
new file mode 100644
index 0000000..80962ce
--- /dev/null
+++ b/tests/tcg/lm32/test_and.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name AND_1
+mvi r1, 0
+mvi r2, 0
+and r3, r1, r2
+check_r3 0
+
+test_name AND_2
+mvi r1, 0
+mvi r2, 1
+and r3, r1, r2
+check_r3 0
+
+test_name AND_3
+mvi r1, 1
+mvi r2, 1
+and r3, r1, r2
+check_r3 1
+
+test_name AND_4
+mvi r3, 7
+and r3, r3, r3
+check_r3 7
+
+test_name AND_5
+mvi r1, 7
+and r3, r1, r1
+check_r3 7
+
+test_name AND_6
+mvi r1, 7
+mvi r3, 0
+and r3, r1, r3
+check_r3 0
+
+test_name AND_7
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+and r3, r1, r2
+check_r3 0
+
+end
diff --git a/tests/tcg/lm32/test_andhi.S b/tests/tcg/lm32/test_andhi.S
new file mode 100644
index 0000000..4f73af5
--- /dev/null
+++ b/tests/tcg/lm32/test_andhi.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name ANDHI_1
+mvi r1, 0
+andhi r3, r1, 0
+check_r3 0
+
+test_name ANDHI_2
+mvi r1, 1
+andhi r3, r1, 1
+check_r3 0
+
+test_name ANDHI_3
+load r1 0x000f0000
+andhi r3, r1, 1
+check_r3 0x00010000
+
+test_name ANDHI_4
+load r1 0xffffffff
+andhi r3, r1, 0xffff
+check_r3 0xffff0000
+
+test_name ANDHI_5
+load r1 0xffffffff
+andhi r3, r1, 0
+check_r3 0
+
+test_name ANDHI_6
+load r3 0x55aaffff
+andhi r3, r3, 0xaaaa
+check_r3 0x00aa0000
+
+end
diff --git a/tests/tcg/lm32/test_andi.S b/tests/tcg/lm32/test_andi.S
new file mode 100644
index 0000000..da1b0a3
--- /dev/null
+++ b/tests/tcg/lm32/test_andi.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name ANDI_1
+mvi r1, 0
+andi r3, r1, 0
+check_r3 0
+
+test_name ANDI_2
+mvi r1, 1
+andi r3, r1, 1
+check_r3 1
+
+test_name ANDI_3
+load r1 0x000f0000
+andi r3, r1, 1
+check_r3 0
+
+test_name ANDI_4
+load r1 0xffffffff
+andi r3, r1, 0xffff
+check_r3 0xffff
+
+test_name ANDI_5
+load r1 0xffffffff
+andi r3, r1, 0
+check_r3 0
+
+test_name ANDI_6
+load r3 0xffff55aa
+andi r3, r3, 0xaaaa
+check_r3 0x000000aa
+
+end
diff --git a/tests/tcg/lm32/test_b.S b/tests/tcg/lm32/test_b.S
new file mode 100644
index 0000000..98172d8
--- /dev/null
+++ b/tests/tcg/lm32/test_b.S
@@ -0,0 +1,13 @@
+.include "macros.inc"
+
+start
+
+test_name B_1
+load r1 jump
+b r1
+tc_fail
+end
+
+jump:
+tc_pass
+end
diff --git a/tests/tcg/lm32/test_be.S b/tests/tcg/lm32/test_be.S
new file mode 100644
index 0000000..635caba
--- /dev/null
+++ b/tests/tcg/lm32/test_be.S
@@ -0,0 +1,48 @@
+.include "macros.inc"
+
+start
+
+test_name BE_1
+mvi r1, 0
+mvi r2, 0
+be r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BE_2
+mvi r1, 1
+mvi r2, 0
+be r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BE_3
+mvi r1, 0
+mvi r2, 1
+be r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BE_4
+mvi r1, 1
+mvi r2, 1
+be r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/tests/tcg/lm32/test_bg.S b/tests/tcg/lm32/test_bg.S
new file mode 100644
index 0000000..81823c2
--- /dev/null
+++ b/tests/tcg/lm32/test_bg.S
@@ -0,0 +1,78 @@
+.include "macros.inc"
+
+start
+
+test_name BG_1
+mvi r1, 0
+mvi r2, 0
+bg r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BG_2
+mvi r1, 1
+mvi r2, 0
+bg r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BG_3
+mvi r1, 0
+mvi r2, 1
+bg r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BG_4
+mvi r1, 0
+mvi r2, -1
+bg r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BG_5
+mvi r1, -1
+mvi r2, 0
+bg r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BG_6
+mvi r1, -1
+mvi r2, -1
+bg r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BG_7
+mvi r1, 1
+mvi r2, 0
+bg r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/tests/tcg/lm32/test_bge.S b/tests/tcg/lm32/test_bge.S
new file mode 100644
index 0000000..6684d15
--- /dev/null
+++ b/tests/tcg/lm32/test_bge.S
@@ -0,0 +1,78 @@
+.include "macros.inc"
+
+start
+
+test_name BGE_1
+mvi r1, 0
+mvi r2, 0
+bge r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGE_2
+mvi r1, 1
+mvi r2, 0
+bge r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGE_3
+mvi r1, 0
+mvi r2, 1
+bge r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGE_4
+mvi r1, 0
+mvi r2, -1
+bge r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGE_5
+mvi r1, -1
+mvi r2, 0
+bge r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGE_6
+mvi r1, -1
+mvi r2, -1
+bge r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BGE_7
+mvi r1, 1
+mvi r2, 0
+bge r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/tests/tcg/lm32/test_bgeu.S b/tests/tcg/lm32/test_bgeu.S
new file mode 100644
index 0000000..be44030
--- /dev/null
+++ b/tests/tcg/lm32/test_bgeu.S
@@ -0,0 +1,78 @@
+.include "macros.inc"
+
+start
+
+test_name BGEU_1
+mvi r1, 0
+mvi r2, 0
+bgeu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGEU_2
+mvi r1, 1
+mvi r2, 0
+bgeu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGEU_3
+mvi r1, 0
+mvi r2, 1
+bgeu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGEU_4
+mvi r1, 0
+mvi r2, -1
+bgeu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGEU_5
+mvi r1, -1
+mvi r2, 0
+bgeu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGEU_6
+mvi r1, -1
+mvi r2, -1
+bgeu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BGEU_7
+mvi r1, 1
+mvi r2, 0
+bgeu r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/tests/tcg/lm32/test_bgu.S b/tests/tcg/lm32/test_bgu.S
new file mode 100644
index 0000000..8cc695b
--- /dev/null
+++ b/tests/tcg/lm32/test_bgu.S
@@ -0,0 +1,78 @@
+.include "macros.inc"
+
+start
+
+test_name BGU_1
+mvi r1, 0
+mvi r2, 0
+bgu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGU_2
+mvi r1, 1
+mvi r2, 0
+bgu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGU_3
+mvi r1, 0
+mvi r2, 1
+bgu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGU_4
+mvi r1, 0
+mvi r2, -1
+bgu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGU_5
+mvi r1, -1
+mvi r2, 0
+bgu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGU_6
+mvi r1, -1
+mvi r2, -1
+bgu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BGU_7
+mvi r1, 1
+mvi r2, 0
+bgu r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/tests/tcg/lm32/test_bi.S b/tests/tcg/lm32/test_bi.S
new file mode 100644
index 0000000..a1fbd6f
--- /dev/null
+++ b/tests/tcg/lm32/test_bi.S
@@ -0,0 +1,23 @@
+.include "macros.inc"
+
+start
+
+test_name BI_1
+bi jump
+tc_fail
+end
+
+jump_back:
+tc_pass
+end
+
+jump:
+tc_pass
+
+test_name BI_2
+bi jump_back
+tc_fail
+
+end
+
+
diff --git a/tests/tcg/lm32/test_bne.S b/tests/tcg/lm32/test_bne.S
new file mode 100644
index 0000000..871a006
--- /dev/null
+++ b/tests/tcg/lm32/test_bne.S
@@ -0,0 +1,48 @@
+.include "macros.inc"
+
+start
+
+test_name BNE_1
+mvi r1, 0
+mvi r2, 0
+bne r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BNE_2
+mvi r1, 1
+mvi r2, 0
+bne r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BNE_3
+mvi r1, 0
+mvi r2, 1
+bne r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+bi 2f
+1:
+tc_fail
+bi 3f
+2:
+test_name BNE_4
+mvi r1, 1
+mvi r2, 1
+bne r1, r2, 1b
+tc_pass
+3:
+
+end
+
diff --git a/tests/tcg/lm32/test_break.S b/tests/tcg/lm32/test_break.S
new file mode 100644
index 0000000..0384fc6
--- /dev/null
+++ b/tests/tcg/lm32/test_break.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+start
+
+test_name BREAK_1
+mvi r1, 1
+wcsr IE, r1
+insn:
+break
+check_excp 1
+
+test_name BREAK_2
+mv r3, ba
+check_r3 insn
+
+test_name BREAK_3
+rcsr r3, IE
+check_r3 4
+
+end
diff --git a/tests/tcg/lm32/test_bret.S b/tests/tcg/lm32/test_bret.S
new file mode 100644
index 0000000..645210e
--- /dev/null
+++ b/tests/tcg/lm32/test_bret.S
@@ -0,0 +1,38 @@
+.include "macros.inc"
+
+start
+
+test_name BRET_1
+mvi r1, 4
+wcsr IE, r1
+load ba mark
+bret
+tc_fail
+bi 1f
+
+mark:
+tc_pass
+
+1:
+test_name BRET_2
+rcsr r3, IE
+check_r3 5
+
+test_name BRET_3
+mvi r1, 0
+wcsr IE, r1
+load ba mark2
+bret
+tc_fail
+bi 1f
+
+mark2:
+tc_pass
+
+1:
+test_name BRET_4
+rcsr r3, IE
+check_r3 0
+
+end
+
diff --git a/tests/tcg/lm32/test_call.S b/tests/tcg/lm32/test_call.S
new file mode 100644
index 0000000..1b91a5f
--- /dev/null
+++ b/tests/tcg/lm32/test_call.S
@@ -0,0 +1,16 @@
+.include "macros.inc"
+
+start
+
+test_name CALL_1
+load r1 mark
+call r1
+return:
+
+tc_fail
+end
+
+mark:
+mv r3, ra
+check_r3 return
+end
diff --git a/tests/tcg/lm32/test_calli.S b/tests/tcg/lm32/test_calli.S
new file mode 100644
index 0000000..1d87ae6
--- /dev/null
+++ b/tests/tcg/lm32/test_calli.S
@@ -0,0 +1,15 @@
+.include "macros.inc"
+
+start
+
+test_name CALLI_1
+calli mark
+return:
+
+tc_fail
+end
+
+mark:
+mv r3, ra
+check_r3 return
+end
diff --git a/tests/tcg/lm32/test_cmpe.S b/tests/tcg/lm32/test_cmpe.S
new file mode 100644
index 0000000..60a8855
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpe.S
@@ -0,0 +1,40 @@
+.include "macros.inc"
+
+start
+
+test_name CMPE_1
+mvi r1, 0
+mvi r2, 0
+cmpe r3, r1, r2
+check_r3 1
+
+test_name CMPE_2
+mvi r1, 0
+mvi r2, 1
+cmpe r3, r1, r2
+check_r3 0
+
+test_name CMPE_3
+mvi r1, 1
+mvi r2, 0
+cmpe r3, r1, r2
+check_r3 0
+
+test_name CMPE_4
+mvi r3, 0
+mvi r2, 1
+cmpe r3, r3, r2
+check_r3 0
+
+test_name CMPE_5
+mvi r3, 0
+mvi r2, 0
+cmpe r3, r3, r2
+check_r3 1
+
+test_name CMPE_6
+mvi r3, 0
+cmpe r3, r3, r3
+check_r3 1
+
+end
diff --git a/tests/tcg/lm32/test_cmpei.S b/tests/tcg/lm32/test_cmpei.S
new file mode 100644
index 0000000..c3d3566
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpei.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name CMPEI_1
+mvi r1, 0
+cmpei r3, r1, 0
+check_r3 1
+
+test_name CMPEI_2
+mvi r1, 0
+cmpei r3, r1, 1
+check_r3 0
+
+test_name CMPEI_3
+mvi r1, 1
+cmpei r3, r1, 0
+check_r3 0
+
+test_name CMPEI_4
+load r1 0xffffffff
+cmpei r3, r1, -1
+check_r3 1
+
+test_name CMPEI_5
+mvi r3, 0
+cmpei r3, r3, 0
+check_r3 1
+
+test_name CMPEI_6
+mvi r3, 0
+cmpei r3, r3, 1
+check_r3 0
+
+end
diff --git a/tests/tcg/lm32/test_cmpg.S b/tests/tcg/lm32/test_cmpg.S
new file mode 100644
index 0000000..0124078
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpg.S
@@ -0,0 +1,64 @@
+.include "macros.inc"
+
+start
+
+test_name CMPG_1
+mvi r1, 0
+mvi r2, 0
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_2
+mvi r1, 0
+mvi r2, 1
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_3
+mvi r1, 1
+mvi r2, 0
+cmpg r3, r1, r2
+check_r3 1
+
+test_name CMPG_4
+mvi r1, 1
+mvi r2, 1
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_5
+mvi r1, 0
+mvi r2, -1
+cmpg r3, r1, r2
+check_r3 1
+
+test_name CMPG_6
+mvi r1, -1
+mvi r2, 0
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_7
+mvi r1, -1
+mvi r2, -1
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_8
+mvi r3, 0
+mvi r2, 1
+cmpg r3, r3, r2
+check_r3 0
+
+test_name CMPG_9
+mvi r3, 1
+mvi r2, 0
+cmpg r3, r3, r2
+check_r3 1
+
+test_name CMPG_10
+mvi r3, 0
+cmpg r3, r3, r3
+check_r3 0
+
+end
diff --git a/tests/tcg/lm32/test_cmpge.S b/tests/tcg/lm32/test_cmpge.S
new file mode 100644
index 0000000..84620a0
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpge.S
@@ -0,0 +1,64 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGE_1
+mvi r1, 0
+mvi r2, 0
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_2
+mvi r1, 0
+mvi r2, 1
+cmpge r3, r1, r2
+check_r3 0
+
+test_name CMPGE_3
+mvi r1, 1
+mvi r2, 0
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_4
+mvi r1, 1
+mvi r2, 1
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_5
+mvi r1, 0
+mvi r2, -1
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_6
+mvi r1, -1
+mvi r2, 0
+cmpge r3, r1, r2
+check_r3 0
+
+test_name CMPGE_7
+mvi r1, -1
+mvi r2, -1
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_8
+mvi r3, 0
+mvi r2, 1
+cmpge r3, r3, r2
+check_r3 0
+
+test_name CMPGE_9
+mvi r3, 1
+mvi r2, 0
+cmpge r3, r3, r2
+check_r3 1
+
+test_name CMPGE_10
+mvi r3, 0
+cmpge r3, r3, r3
+check_r3 1
+
+end
diff --git a/tests/tcg/lm32/test_cmpgei.S b/tests/tcg/lm32/test_cmpgei.S
new file mode 100644
index 0000000..6a8870f
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpgei.S
@@ -0,0 +1,55 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGEI_1
+mvi r1, 0
+cmpgei r3, r1, 0
+check_r3 1
+
+test_name CMPGEI_2
+mvi r1, 0
+cmpgei r3, r1, 1
+check_r3 0
+
+test_name CMPGEI_3
+mvi r1, 1
+cmpgei r3, r1, 0
+check_r3 1
+
+test_name CMPGEI_4
+mvi r1, 1
+cmpgei r3, r1, 1
+check_r3 1
+
+test_name CMPGEI_5
+mvi r1, 0
+cmpgei r3, r1, -1
+check_r3 1
+
+test_name CMPGEI_6
+mvi r1, -1
+cmpgei r3, r1, 0
+check_r3 0
+
+test_name CMPGEI_7
+mvi r1, -1
+cmpgei r3, r1, -1
+check_r3 1
+
+test_name CMPGEI_8
+mvi r3, 0
+cmpgei r3, r3, 1
+check_r3 0
+
+test_name CMPGEI_9
+mvi r3, 1
+cmpgei r3, r3, 0
+check_r3 1
+
+test_name CMPGEI_10
+mvi r3, 0
+cmpgei r3, r3, 0
+check_r3 1
+
+end
diff --git a/tests/tcg/lm32/test_cmpgeu.S b/tests/tcg/lm32/test_cmpgeu.S
new file mode 100644
index 0000000..2110ccb
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpgeu.S
@@ -0,0 +1,64 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGEU_1
+mvi r1, 0
+mvi r2, 0
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_2
+mvi r1, 0
+mvi r2, 1
+cmpgeu r3, r1, r2
+check_r3 0
+
+test_name CMPGEU_3
+mvi r1, 1
+mvi r2, 0
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_4
+mvi r1, 1
+mvi r2, 1
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_5
+mvi r1, 0
+mvi r2, -1
+cmpgeu r3, r1, r2
+check_r3 0
+
+test_name CMPGEU_6
+mvi r1, -1
+mvi r2, 0
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_7
+mvi r1, -1
+mvi r2, -1
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_8
+mvi r3, 0
+mvi r2, 1
+cmpgeu r3, r3, r2
+check_r3 0
+
+test_name CMPGEU_9
+mvi r3, 1
+mvi r2, 0
+cmpgeu r3, r3, r2
+check_r3 1
+
+test_name CMPGEU_10
+mvi r3, 0
+cmpgeu r3, r3, r3
+check_r3 1
+
+end
diff --git a/tests/tcg/lm32/test_cmpgeui.S b/tests/tcg/lm32/test_cmpgeui.S
new file mode 100644
index 0000000..b9d1755
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpgeui.S
@@ -0,0 +1,55 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGEUI_1
+mvi r1, 0
+cmpgeui r3, r1, 0
+check_r3 1
+
+test_name CMPGEUI_2
+mvi r1, 0
+cmpgeui r3, r1, 1
+check_r3 0
+
+test_name CMPGEUI_3
+mvi r1, 1
+cmpgeui r3, r1, 0
+check_r3 1
+
+test_name CMPGEUI_4
+mvi r1, 1
+cmpgeui r3, r1, 1
+check_r3 1
+
+test_name CMPGEUI_5
+mvi r1, 0
+cmpgeui r3, r1, 0xffff
+check_r3 0
+
+test_name CMPGEUI_6
+mvi r1, -1
+cmpgeui r3, r1, 0
+check_r3 1
+
+test_name CMPGEUI_7
+mvi r1, -1
+cmpgeui r3, r1, 0xffff
+check_r3 1
+
+test_name CMPGEUI_8
+mvi r3, 0
+cmpgeui r3, r3, 1
+check_r3 0
+
+test_name CMPGEUI_9
+mvi r3, 1
+cmpgeui r3, r3, 0
+check_r3 1
+
+test_name CMPGEUI_10
+mvi r3, 0
+cmpgeui r3, r3, 0
+check_r3 1
+
+end
diff --git a/tests/tcg/lm32/test_cmpgi.S b/tests/tcg/lm32/test_cmpgi.S
new file mode 100644
index 0000000..1f622d2
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpgi.S
@@ -0,0 +1,55 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGI_1
+mvi r1, 0
+cmpgi r3, r1, 0
+check_r3 0
+
+test_name CMPGI_2
+mvi r1, 0
+cmpgi r3, r1, 1
+check_r3 0
+
+test_name CMPGI_3
+mvi r1, 1
+cmpgi r3, r1, 0
+check_r3 1
+
+test_name CMPGI_4
+mvi r1, 1
+cmpgi r3, r1, 1
+check_r3 0
+
+test_name CMPGI_5
+mvi r1, 0
+cmpgi r3, r1, -1
+check_r3 1
+
+test_name CMPGI_6
+mvi r1, -1
+cmpgi r3, r1, 0
+check_r3 0
+
+test_name CMPGI_7
+mvi r1, -1
+cmpgi r3, r1, -1
+check_r3 0
+
+test_name CMPGI_8
+mvi r3, 0
+cmpgi r3, r3, 1
+check_r3 0
+
+test_name CMPGI_9
+mvi r3, 1
+cmpgi r3, r3, 0
+check_r3 1
+
+test_name CMPGI_10
+mvi r3, 0
+cmpgi r3, r3, 0
+check_r3 0
+
+end
diff --git a/tests/tcg/lm32/test_cmpgu.S b/tests/tcg/lm32/test_cmpgu.S
new file mode 100644
index 0000000..dd46547
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpgu.S
@@ -0,0 +1,64 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGU_1
+mvi r1, 0
+mvi r2, 0
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_2
+mvi r1, 0
+mvi r2, 1
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_3
+mvi r1, 1
+mvi r2, 0
+cmpgu r3, r1, r2
+check_r3 1
+
+test_name CMPGU_4
+mvi r1, 1
+mvi r2, 1
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_5
+mvi r1, 0
+mvi r2, -1
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_6
+mvi r1, -1
+mvi r2, 0
+cmpgu r3, r1, r2
+check_r3 1
+
+test_name CMPGU_7
+mvi r1, -1
+mvi r2, -1
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_8
+mvi r3, 0
+mvi r2, 1
+cmpgu r3, r3, r2
+check_r3 0
+
+test_name CMPGU_9
+mvi r3, 1
+mvi r2, 0
+cmpgu r3, r3, r2
+check_r3 1
+
+test_name CMPGU_10
+mvi r3, 0
+cmpgu r3, r3, r3
+check_r3 0
+
+end
diff --git a/tests/tcg/lm32/test_cmpgui.S b/tests/tcg/lm32/test_cmpgui.S
new file mode 100644
index 0000000..759bb64
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpgui.S
@@ -0,0 +1,55 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGUI_1
+mvi r1, 0
+cmpgui r3, r1, 0
+check_r3 0
+
+test_name CMPGUI_2
+mvi r1, 0
+cmpgui r3, r1, 1
+check_r3 0
+
+test_name CMPGUI_3
+mvi r1, 1
+cmpgui r3, r1, 0
+check_r3 1
+
+test_name CMPGUI_4
+mvi r1, 1
+cmpgui r3, r1, 1
+check_r3 0
+
+test_name CMPGUI_5
+mvi r1, 0
+cmpgui r3, r1, 0xffff
+check_r3 0
+
+test_name CMPGUI_6
+mvi r1, -1
+cmpgui r3, r1, 0
+check_r3 1
+
+test_name CMPGUI_7
+mvi r1, -1
+cmpgui r3, r1, 0xffff
+check_r3 0
+
+test_name CMPGUI_8
+mvi r3, 0
+cmpgui r3, r3, 1
+check_r3 0
+
+test_name CMPGUI_9
+mvi r3, 1
+cmpgui r3, r3, 0
+check_r3 1
+
+test_name CMPGUI_10
+mvi r3, 0
+cmpgui r3, r3, 0
+check_r3 0
+
+end
diff --git a/tests/tcg/lm32/test_cmpne.S b/tests/tcg/lm32/test_cmpne.S
new file mode 100644
index 0000000..0f10781
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpne.S
@@ -0,0 +1,40 @@
+.include "macros.inc"
+
+start
+
+test_name CMPNE_1
+mvi r1, 0
+mvi r2, 0
+cmpne r3, r1, r2
+check_r3 0
+
+test_name CMPNE_2
+mvi r1, 0
+mvi r2, 1
+cmpne r3, r1, r2
+check_r3 1
+
+test_name CMPNE_3
+mvi r1, 1
+mvi r2, 0
+cmpne r3, r1, r2
+check_r3 1
+
+test_name CMPNE_4
+mvi r3, 0
+mvi r2, 1
+cmpne r3, r3, r2
+check_r3 1
+
+test_name CMPNE_5
+mvi r3, 0
+mvi r2, 0
+cmpne r3, r3, r2
+check_r3 0
+
+test_name CMPNE_6
+mvi r3, 0
+cmpne r3, r3, r3
+check_r3 0
+
+end
diff --git a/tests/tcg/lm32/test_cmpnei.S b/tests/tcg/lm32/test_cmpnei.S
new file mode 100644
index 0000000..060dd9d
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpnei.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name CMPNEI_1
+mvi r1, 0
+cmpnei r3, r1, 0
+check_r3 0
+
+test_name CMPNEI_2
+mvi r1, 0
+cmpnei r3, r1, 1
+check_r3 1
+
+test_name CMPNEI_3
+mvi r1, 1
+cmpnei r3, r1, 0
+check_r3 1
+
+test_name CMPNEI_4
+load r1 0xffffffff
+cmpnei r3, r1, -1
+check_r3 0
+
+test_name CMPNEI_5
+mvi r3, 0
+cmpnei r3, r3, 0
+check_r3 0
+
+test_name CMPNEI_6
+mvi r3, 0
+cmpnei r3, r3, 1
+check_r3 1
+
+end
diff --git a/tests/tcg/lm32/test_divu.S b/tests/tcg/lm32/test_divu.S
new file mode 100644
index 0000000..f381d09
--- /dev/null
+++ b/tests/tcg/lm32/test_divu.S
@@ -0,0 +1,29 @@
+.include "macros.inc"
+
+start
+
+test_name DIVU_1
+mvi r1, 0
+mvi r2, 1
+divu r3, r1, r2
+check_r3 0
+
+test_name DIVU_2
+mvi r1, 1
+mvi r2, 1
+divu r3, r1, r2
+check_r3 1
+
+test_name DIVU_3
+mvi r1, 0
+mvi r2, 0
+divu r3, r1, r2
+check_excp 16
+
+test_name DIVU_4
+load r1 0xabcdef12
+load r2 0x12345
+divu r3, r1, r2
+check_r3 0x9700
+
+end
diff --git a/tests/tcg/lm32/test_eret.S b/tests/tcg/lm32/test_eret.S
new file mode 100644
index 0000000..6830bd1
--- /dev/null
+++ b/tests/tcg/lm32/test_eret.S
@@ -0,0 +1,38 @@
+.include "macros.inc"
+
+start
+
+test_name ERET_1
+mvi r1, 2
+wcsr IE, r1
+load ea mark
+eret
+tc_fail
+bi 1f
+
+mark:
+tc_pass
+
+1:
+test_name ERET_2
+rcsr r3, IE
+check_r3 3
+
+test_name ERET_3
+mvi r1, 0
+wcsr IE, r1
+load ea mark2
+eret
+tc_fail
+bi 1f
+
+mark2:
+tc_pass
+
+1:
+test_name ERET_4
+rcsr r3, IE
+check_r3 0
+
+end
+
diff --git a/tests/tcg/lm32/test_lb.S b/tests/tcg/lm32/test_lb.S
new file mode 100644
index 0000000..f84d21e
--- /dev/null
+++ b/tests/tcg/lm32/test_lb.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name LB_1
+load r1 data
+lb r3, (r1+0)
+check_r3 0x7e
+
+test_name LB_2
+lb r3, (r1+1)
+check_r3 0x7f
+
+test_name LB_3
+lb r3, (r1+-1)
+check_r3 0x7d
+
+test_name LB_4
+load r1 data_msb
+lb r3, (r1+0)
+check_r3 0xfffffffe
+
+test_name LB_5
+lb r3, (r1+1)
+check_r3 0xffffffff
+
+test_name LB_6
+lb r3, (r1+-1)
+check_r3 0xfffffffd
+
+test_name LB_7
+load r3 data
+lb r3, (r3+0)
+check_r3 0x7e
+
+end
+
+.data
+	.align 4
+	.byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+	.byte 0x7e, 0x7f, 0x70, 0x71
+	.byte 0xfa, 0xfb, 0xfc, 0xfd
+data_msb:
+	.byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/tests/tcg/lm32/test_lbu.S b/tests/tcg/lm32/test_lbu.S
new file mode 100644
index 0000000..4c1786a
--- /dev/null
+++ b/tests/tcg/lm32/test_lbu.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name LBU_1
+load r1 data
+lbu r3, (r1+0)
+check_r3 0x7e
+
+test_name LBU_2
+lbu r3, (r1+1)
+check_r3 0x7f
+
+test_name LBU_3
+lbu r3, (r1+-1)
+check_r3 0x7d
+
+test_name LBU_4
+load r1 data_msb
+lbu r3, (r1+0)
+check_r3 0xfe
+
+test_name LBU_5
+lbu r3, (r1+1)
+check_r3 0xff
+
+test_name LBU_6
+lbu r3, (r1+-1)
+check_r3 0xfd
+
+test_name LBU_7
+load r3 data
+lbu r3, (r3+0)
+check_r3 0x7e
+
+end
+
+.data
+	.align 4
+	.byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+	.byte 0x7e, 0x7f, 0x70, 0x71
+	.byte 0xfa, 0xfb, 0xfc, 0xfd
+data_msb:
+	.byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/tests/tcg/lm32/test_lh.S b/tests/tcg/lm32/test_lh.S
new file mode 100644
index 0000000..e57d9e3
--- /dev/null
+++ b/tests/tcg/lm32/test_lh.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name LH_1
+load r1 data
+lh r3, (r1+0)
+check_r3 0x7e7f
+
+test_name LH_2
+lh r3, (r1+2)
+check_r3 0x7071
+
+test_name LH_3
+lh r3, (r1+-2)
+check_r3 0x7c7d
+
+test_name LH_4
+load r1 data_msb
+lh r3, (r1+0)
+check_r3 0xfffffeff
+
+test_name LH_5
+lh r3, (r1+2)
+check_r3 0xfffff0f1
+
+test_name LH_6
+lh r3, (r1+-2)
+check_r3 0xfffffcfd
+
+test_name LH_7
+load r3 data
+lh r3, (r3+0)
+check_r3 0x7e7f
+
+end
+
+.data
+	.align 4
+	.byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+	.byte 0x7e, 0x7f, 0x70, 0x71
+	.byte 0xfa, 0xfb, 0xfc, 0xfd
+data_msb:
+	.byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/tests/tcg/lm32/test_lhu.S b/tests/tcg/lm32/test_lhu.S
new file mode 100644
index 0000000..e648775
--- /dev/null
+++ b/tests/tcg/lm32/test_lhu.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name LHU_1
+load r1 data
+lhu r3, (r1+0)
+check_r3 0x7e7f
+
+test_name LHU_2
+lhu r3, (r1+2)
+check_r3 0x7071
+
+test_name LHU_3
+lhu r3, (r1+-2)
+check_r3 0x7c7d
+
+test_name LHU_4
+load r1 data_msb
+lhu r3, (r1+0)
+check_r3 0xfeff
+
+test_name LHU_5
+lhu r3, (r1+2)
+check_r3 0xf0f1
+
+test_name LHU_6
+lhu r3, (r1+-2)
+check_r3 0xfcfd
+
+test_name LHU_7
+load r3 data
+lhu r3, (r3+0)
+check_r3 0x7e7f
+
+end
+
+.data
+	.align 4
+	.byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+	.byte 0x7e, 0x7f, 0x70, 0x71
+	.byte 0xfa, 0xfb, 0xfc, 0xfd
+data_msb:
+	.byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/tests/tcg/lm32/test_lw.S b/tests/tcg/lm32/test_lw.S
new file mode 100644
index 0000000..f8c919d
--- /dev/null
+++ b/tests/tcg/lm32/test_lw.S
@@ -0,0 +1,30 @@
+.include "macros.inc"
+
+start
+
+test_name LW_1
+load r1 data
+lw r3, (r1+0)
+check_r3 0x7e7f7071
+
+test_name LW_2
+lw r3, (r1+4)
+check_r3 0x72737475
+
+test_name LW_3
+lw r3, (r1+-4)
+check_r3 0x7a7b7c7d
+
+test_name LW_4
+load r3 data
+lw r3, (r3+0)
+check_r3 0x7e7f7071
+
+end
+
+.data
+	.align 4
+	.byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+	.byte 0x7e, 0x7f, 0x70, 0x71
+	.byte 0x72, 0x73, 0x74, 0x75
diff --git a/tests/tcg/lm32/test_modu.S b/tests/tcg/lm32/test_modu.S
new file mode 100644
index 0000000..4248690
--- /dev/null
+++ b/tests/tcg/lm32/test_modu.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name MODU_1
+mvi r1, 0
+mvi r2, 1
+modu r3, r1, r2
+check_r3 0
+
+test_name MODU_2
+mvi r1, 1
+mvi r2, 1
+modu r3, r1, r2
+check_r3 0
+
+test_name MODU_3
+mvi r1, 3
+mvi r2, 2
+modu r3, r1, r2
+check_r3 1
+
+test_name MODU_4
+mvi r1, 0
+mvi r2, 0
+modu r3, r1, r2
+check_excp 16
+
+test_name MODU_5
+load r1 0xabcdef12
+load r2 0x12345
+modu r3, r1, r2
+check_r3 0x3c12
+
+end
diff --git a/tests/tcg/lm32/test_mul.S b/tests/tcg/lm32/test_mul.S
new file mode 100644
index 0000000..e9b937e
--- /dev/null
+++ b/tests/tcg/lm32/test_mul.S
@@ -0,0 +1,70 @@
+.include "macros.inc"
+
+start
+
+test_name MUL_1
+mvi r1, 0
+mvi r2, 0
+mul r3, r1, r2
+check_r3 0
+
+test_name MUL_2
+mvi r1, 1
+mvi r2, 0
+mul r3, r1, r2
+check_r3 0
+
+test_name MUL_3
+mvi r1, 0
+mvi r2, 1
+mul r3, r1, r2
+check_r3 0
+
+test_name MUL_4
+mvi r1, 1
+mvi r2, 1
+mul r3, r1, r2
+check_r3 1
+
+test_name MUL_5
+mvi r1, 2
+mvi r2, -1
+mul r3, r1, r2
+check_r3 -2
+
+test_name MUL_6
+mvi r1, -2
+mvi r2, -1
+mul r3, r1, r2
+check_r3 2
+
+test_name MUL_7
+mvi r1, 0x1234
+mvi r2, 0x789
+mul r3, r1, r2
+check_r3 0x8929d4
+
+test_name MUL_8
+mvi r3, 4
+mul r3, r3, r3
+check_r3 16
+
+test_name MUL_9
+mvi r2, 2
+mvi r3, 4
+mul r3, r3, r2
+check_r3 8
+
+test_name MUL_10
+load r1 0x12345678
+load r2 0x7bcdef12
+mul r3, r1, r2
+check_r3 0xa801c70
+
+test_name MUL_11
+load r1 0x12345678
+load r2 0xabcdef12
+mul r3, r1, r2
+check_r3 0x8a801c70
+
+end
diff --git a/tests/tcg/lm32/test_muli.S b/tests/tcg/lm32/test_muli.S
new file mode 100644
index 0000000..d6dd4a0
--- /dev/null
+++ b/tests/tcg/lm32/test_muli.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name MULI_1
+mvi r1, 0
+muli r3, r1, 0
+check_r3 0
+
+test_name MULI_2
+mvi r1, 1
+muli r3, r1, 0
+check_r3 0
+
+test_name MULI_3
+mvi r1, 0
+muli r3, r1, 1
+check_r3 0
+
+test_name MULI_4
+mvi r1, 1
+muli r3, r1, 1
+check_r3 1
+
+test_name MULI_5
+mvi r1, 2
+muli r3, r1, -1
+check_r3 -2
+
+test_name MULI_6
+mvi r1, -2
+muli r3, r1, -1
+check_r3 2
+
+test_name MULI_7
+mvi r1, 0x1234
+muli r3, r1, 0x789
+check_r3 0x8929d4
+
+test_name MULI_8
+mvi r3, 4
+muli r3, r3, 4
+check_r3 16
+
+end
diff --git a/tests/tcg/lm32/test_nor.S b/tests/tcg/lm32/test_nor.S
new file mode 100644
index 0000000..74d7592
--- /dev/null
+++ b/tests/tcg/lm32/test_nor.S
@@ -0,0 +1,51 @@
+.include "macros.inc"
+
+start
+
+test_name NOR_1
+mvi r1, 0
+mvi r2, 0
+nor r3, r1, r2
+check_r3 0xffffffff
+
+test_name NOR_2
+mvi r1, 0
+mvi r2, 1
+nor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name NOR_3
+mvi r1, 1
+mvi r2, 1
+nor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name NOR_4
+mvi r1, 1
+mvi r2, 0
+nor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name NOR_5
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+nor r3, r1, r2
+check_r3 0
+
+test_name NOR_6
+load r1 0xaa550000
+load r2 0x0000aa55
+nor r3, r1, r2
+check_r3 0x55aa55aa
+
+test_name NOR_7
+load r1 0xaa55aa55
+nor r3, r1, r1
+check_r3 0x55aa55aa
+
+test_name NOR_8
+load r3 0xaa55aa55
+nor r3, r3, r3
+check_r3 0x55aa55aa
+
+end
diff --git a/tests/tcg/lm32/test_nori.S b/tests/tcg/lm32/test_nori.S
new file mode 100644
index 0000000..d00309c
--- /dev/null
+++ b/tests/tcg/lm32/test_nori.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name NORI_1
+mvi r1, 0
+nori r3, r1, 0
+check_r3 0xffffffff
+
+test_name NORI_2
+mvi r1, 0
+nori r3, r1, 1
+check_r3 0xfffffffe
+
+test_name NORI_3
+mvi r1, 1
+nori r3, r1, 1
+check_r3 0xfffffffe
+
+test_name NORI_4
+mvi r1, 1
+nori r3, r1, 0
+check_r3 0xfffffffe
+
+test_name NORI_5
+load r1 0xaa55aa55
+nori r3, r1, 0x55aa
+check_r3 0x55aa0000
+
+test_name NORI_6
+load r3 0xaa55aa55
+nori r3, r3, 0x55aa
+check_r3 0x55aa0000
+
+end
diff --git a/tests/tcg/lm32/test_or.S b/tests/tcg/lm32/test_or.S
new file mode 100644
index 0000000..4ed2923
--- /dev/null
+++ b/tests/tcg/lm32/test_or.S
@@ -0,0 +1,51 @@
+.include "macros.inc"
+
+start
+
+test_name OR_1
+mvi r1, 0
+mvi r2, 0
+or r3, r1, r2
+check_r3 0
+
+test_name OR_2
+mvi r1, 0
+mvi r2, 1
+or r3, r1, r2
+check_r3 1
+
+test_name OR_3
+mvi r1, 1
+mvi r2, 1
+or r3, r1, r2
+check_r3 1
+
+test_name OR_4
+mvi r1, 1
+mvi r2, 0
+or r3, r1, r2
+check_r3 1
+
+test_name OR_5
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+or r3, r1, r2
+check_r3 0xffffffff
+
+test_name OR_6
+load r1 0xaa550000
+load r2 0x0000aa55
+or r3, r1, r2
+check_r3 0xaa55aa55
+
+test_name OR_7
+load r1 0xaa55aa55
+or r3, r1, r1
+check_r3 0xaa55aa55
+
+test_name OR_8
+load r3 0xaa55aa55
+or r3, r3, r3
+check_r3 0xaa55aa55
+
+end
diff --git a/tests/tcg/lm32/test_orhi.S b/tests/tcg/lm32/test_orhi.S
new file mode 100644
index 0000000..78b7600
--- /dev/null
+++ b/tests/tcg/lm32/test_orhi.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name ORHI_1
+mvi r1, 0
+orhi r3, r1, 0
+check_r3 0
+
+test_name ORHI_2
+mvi r1, 0
+orhi r3, r1, 1
+check_r3 0x00010000
+
+test_name ORHI_3
+load r1 0x00010000
+orhi r3, r1, 1
+check_r3 0x00010000
+
+test_name ORHI_4
+mvi r1, 1
+orhi r3, r1, 0
+check_r3 1
+
+test_name ORHI_5
+load r1 0xaa55aa55
+orhi r3, r1, 0x55aa
+check_r3 0xffffaa55
+
+test_name ORHI_6
+load r3 0xaa55aa55
+orhi r3, r3, 0x55aa
+check_r3 0xffffaa55
+
+end
diff --git a/tests/tcg/lm32/test_ori.S b/tests/tcg/lm32/test_ori.S
new file mode 100644
index 0000000..3d576cd
--- /dev/null
+++ b/tests/tcg/lm32/test_ori.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name ORI_1
+mvi r1, 0
+ori r3, r1, 0
+check_r3 0
+
+test_name ORI_2
+mvi r1, 0
+ori r3, r1, 1
+check_r3 1
+
+test_name ORI_3
+mvi r1, 1
+ori r3, r1, 1
+check_r3 1
+
+test_name ORI_4
+mvi r1, 1
+ori r3, r1, 0
+check_r3 1
+
+test_name ORI_5
+load r1 0xaa55aa55
+ori r3, r1, 0x55aa
+check_r3 0xaa55ffff
+
+test_name ORI_6
+load r3 0xaa55aa55
+ori r3, r3, 0x55aa
+check_r3 0xaa55ffff
+
+end
diff --git a/tests/tcg/lm32/test_ret.S b/tests/tcg/lm32/test_ret.S
new file mode 100644
index 0000000..320264f
--- /dev/null
+++ b/tests/tcg/lm32/test_ret.S
@@ -0,0 +1,14 @@
+.include "macros.inc"
+
+start
+
+test_name RET_1
+load ra mark
+ret
+
+tc_fail
+end
+
+mark:
+tc_pass
+end
diff --git a/tests/tcg/lm32/test_sb.S b/tests/tcg/lm32/test_sb.S
new file mode 100644
index 0000000..89e39d6
--- /dev/null
+++ b/tests/tcg/lm32/test_sb.S
@@ -0,0 +1,30 @@
+.include "macros.inc"
+
+start
+
+test_name SB_1
+load r1 data
+load r2 0xf0f1f2aa
+sb (r1+0), r2
+check_mem data 0xaa000000
+
+test_name SB_2
+load r2 0xf0f1f2bb
+sb (r1+1), r2
+check_mem data 0xaabb0000
+
+test_name SB_3
+load r2 0xf0f1f2cc
+sb (r1+-1), r2
+check_mem data0 0x000000cc
+
+end
+
+.data
+	.align 4
+data0:
+	.byte 0, 0, 0, 0
+data:
+	.byte 0, 0, 0, 0
+data1:
+	.byte 0, 0, 0, 0
diff --git a/tests/tcg/lm32/test_scall.S b/tests/tcg/lm32/test_scall.S
new file mode 100644
index 0000000..b442e32
--- /dev/null
+++ b/tests/tcg/lm32/test_scall.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+start
+
+test_name SCALL_1
+mvi r1, 1
+wcsr IE, r1
+insn:
+scall
+check_excp 64
+
+test_name SCALL_2
+mv r3, ea
+check_r3 insn
+
+test_name SCALL_3
+rcsr r3, IE
+check_r3 2
+
+end
diff --git a/tests/tcg/lm32/test_sextb.S b/tests/tcg/lm32/test_sextb.S
new file mode 100644
index 0000000..58db8ee
--- /dev/null
+++ b/tests/tcg/lm32/test_sextb.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+start
+
+test_name SEXTB_1
+mvi r1, 0
+sextb r3, r1
+check_r3 0
+
+test_name SEXTB_2
+mvi r1, 0x7f
+sextb r3, r1
+check_r3 0x0000007f
+
+test_name SEXTB_3
+mvi r1, 0x80
+sextb r3, r1
+check_r3 0xffffff80
+
+end
diff --git a/tests/tcg/lm32/test_sexth.S b/tests/tcg/lm32/test_sexth.S
new file mode 100644
index 0000000..a059ec3
--- /dev/null
+++ b/tests/tcg/lm32/test_sexth.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+start
+
+test_name SEXTH_1
+mvi r1, 0
+sexth r3, r1
+check_r3 0
+
+test_name SEXTH_2
+load r1 0x7fff
+sexth r3, r1
+check_r3 0x00007fff
+
+test_name SEXTH_3
+load r1 0x8000
+sexth r3, r1
+check_r3 0xffff8000
+
+end
diff --git a/tests/tcg/lm32/test_sh.S b/tests/tcg/lm32/test_sh.S
new file mode 100644
index 0000000..ea8b3f2
--- /dev/null
+++ b/tests/tcg/lm32/test_sh.S
@@ -0,0 +1,30 @@
+.include "macros.inc"
+
+start
+
+test_name SH_1
+load r1 data
+load r2 0xf0f1aaaa
+sh (r1+0), r2
+check_mem data 0xaaaa0000
+
+test_name SH_2
+load r2 0xf0f1bbbb
+sh (r1+2), r2
+check_mem data 0xaaaabbbb
+
+test_name SH_3
+load r2 0xf0f1cccc
+sh (r1+-2), r2
+check_mem data0 0x0000cccc
+
+end
+
+.data
+	.align 4
+data0:
+	.byte 0, 0, 0, 0
+data:
+	.byte 0, 0, 0, 0
+data1:
+	.byte 0, 0, 0, 0
diff --git a/tests/tcg/lm32/test_sl.S b/tests/tcg/lm32/test_sl.S
new file mode 100644
index 0000000..0aee17f
--- /dev/null
+++ b/tests/tcg/lm32/test_sl.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name SL_1
+mvi r1, 1
+mvi r2, 0
+sl r3, r1, r2
+check_r3 1
+
+test_name SL_2
+mvi r1, 0
+mvi r2, 1
+sl r3, r1, r2
+check_r3 0
+
+test_name SL_3
+mvi r1, 1
+mvi r2, 31
+sl r3, r1, r2
+check_r3 0x80000000
+
+test_name SL_4
+mvi r1, 16
+mvi r2, 31
+sl r3, r1, r2
+check_r3 0
+
+test_name SL_5
+mvi r1, 1
+mvi r2, 34
+sl r3, r1, r2
+check_r3 4
+
+test_name SL_6
+mvi r1, 2
+sl r3, r1, r1
+check_r3 8
+
+test_name SL_7
+mvi r3, 2
+sl r3, r3, r3
+check_r3 8
+
+end
diff --git a/tests/tcg/lm32/test_sli.S b/tests/tcg/lm32/test_sli.S
new file mode 100644
index 0000000..a421de9
--- /dev/null
+++ b/tests/tcg/lm32/test_sli.S
@@ -0,0 +1,30 @@
+.include "macros.inc"
+
+start
+
+test_name SLI_1
+mvi r1, 1
+sli r3, r1, 0
+check_r3 1
+
+test_name SLI_2
+mvi r1, 0
+sli r3, r1, 1
+check_r3 0
+
+test_name SLI_3
+mvi r1, 1
+sli r3, r1, 31
+check_r3 0x80000000
+
+test_name SLI_4
+mvi r1, 16
+sli r3, r1, 31
+check_r3 0
+
+test_name SLI_7
+mvi r3, 2
+sli r3, r3, 2
+check_r3 8
+
+end
diff --git a/tests/tcg/lm32/test_sr.S b/tests/tcg/lm32/test_sr.S
new file mode 100644
index 0000000..62431a9
--- /dev/null
+++ b/tests/tcg/lm32/test_sr.S
@@ -0,0 +1,57 @@
+.include "macros.inc"
+
+start
+
+test_name SR_1
+mvi r1, 1
+mvi r2, 0
+sr r3, r1, r2
+check_r3 1
+
+test_name SR_2
+mvi r1, 0
+mvi r2, 1
+sr r3, r1, r2
+check_r3 0
+
+test_name SR_3
+load r1 0x40000000
+mvi r2, 30
+sr r3, r1, r2
+check_r3 1
+
+test_name SR_4
+load r1 0x40000000
+mvi r2, 31
+sr r3, r1, r2
+check_r3 0
+
+test_name SR_5
+mvi r1, 16
+mvi r2, 34
+sr r3, r1, r2
+check_r3 4
+
+test_name SR_6
+mvi r1, 2
+sr r3, r1, r1
+check_r3 0
+
+test_name SR_7
+mvi r3, 2
+sr r3, r3, r3
+check_r3 0
+
+test_name SR_8
+mvi r1, 0xfffffff0
+mvi r2, 2
+sr r3, r1, r2
+check_r3 0xfffffffc
+
+test_name SR_9
+mvi r1, 0xfffffff0
+mvi r2, 4
+sr r3, r1, r2
+check_r3 0xffffffff
+
+end
diff --git a/tests/tcg/lm32/test_sri.S b/tests/tcg/lm32/test_sri.S
new file mode 100644
index 0000000..c1be907
--- /dev/null
+++ b/tests/tcg/lm32/test_sri.S
@@ -0,0 +1,40 @@
+.include "macros.inc"
+
+start
+
+test_name SRI_1
+mvi r1, 1
+sri r3, r1, 0
+check_r3 1
+
+test_name SRI_2
+mvi r1, 0
+sri r3, r1, 1
+check_r3 0
+
+test_name SRI_3
+load r1 0x40000000
+sri r3, r1, 30
+check_r3 1
+
+test_name SRI_4
+load r1 0x40000000
+sri r3, r1, 31
+check_r3 0
+
+test_name SRI_5
+mvi r3, 2
+sri r3, r3, 2
+check_r3 0
+
+test_name SRI_6
+mvi r1, 0xfffffff0
+sri r3, r1, 2
+check_r3 0xfffffffc
+
+test_name SRI_7
+mvi r1, 0xfffffff0
+sri r3, r1, 4
+check_r3 0xffffffff
+
+end
diff --git a/tests/tcg/lm32/test_sru.S b/tests/tcg/lm32/test_sru.S
new file mode 100644
index 0000000..2ab0b54
--- /dev/null
+++ b/tests/tcg/lm32/test_sru.S
@@ -0,0 +1,57 @@
+.include "macros.inc"
+
+start
+
+test_name SRU_1
+mvi r1, 1
+mvi r2, 0
+sru r3, r1, r2
+check_r3 1
+
+test_name SRU_2
+mvi r1, 0
+mvi r2, 1
+sru r3, r1, r2
+check_r3 0
+
+test_name SRU_3
+load r1 0x40000000
+mvi r2, 30
+sru r3, r1, r2
+check_r3 1
+
+test_name SRU_4
+load r1 0x40000000
+mvi r2, 31
+sru r3, r1, r2
+check_r3 0
+
+test_name SRU_5
+mvi r1, 16
+mvi r2, 34
+sru r3, r1, r2
+check_r3 4
+
+test_name SRU_6
+mvi r1, 2
+sru r3, r1, r1
+check_r3 0
+
+test_name SRU_7
+mvi r3, 2
+sru r3, r3, r3
+check_r3 0
+
+test_name SRU_8
+mvi r1, 0xfffffff0
+mvi r2, 2
+sru r3, r1, r2
+check_r3 0x3ffffffc
+
+test_name SRU_9
+mvi r1, 0xfffffff0
+mvi r2, 4
+sru r3, r1, r2
+check_r3 0x0fffffff
+
+end
diff --git a/tests/tcg/lm32/test_srui.S b/tests/tcg/lm32/test_srui.S
new file mode 100644
index 0000000..872c374
--- /dev/null
+++ b/tests/tcg/lm32/test_srui.S
@@ -0,0 +1,40 @@
+.include "macros.inc"
+
+start
+
+test_name SRUI_1
+mvi r1, 1
+srui r3, r1, 0
+check_r3 1
+
+test_name SRUI_2
+mvi r1, 0
+srui r3, r1, 1
+check_r3 0
+
+test_name SRUI_3
+load r1 0x40000000
+srui r3, r1, 30
+check_r3 1
+
+test_name SRUI_4
+load r1 0x40000000
+srui r3, r1, 31
+check_r3 0
+
+test_name SRUI_5
+mvi r3, 2
+srui r3, r3, 2
+check_r3 0
+
+test_name SRUI_6
+mvi r1, 0xfffffff0
+srui r3, r1, 2
+check_r3 0x3ffffffc
+
+test_name SRUI_7
+mvi r1, 0xfffffff0
+srui r3, r1, 4
+check_r3 0x0fffffff
+
+end
diff --git a/tests/tcg/lm32/test_sub.S b/tests/tcg/lm32/test_sub.S
new file mode 100644
index 0000000..44b74a9
--- /dev/null
+++ b/tests/tcg/lm32/test_sub.S
@@ -0,0 +1,75 @@
+.include "macros.inc"
+
+start
+
+test_name SUB_1
+mvi r1, 0
+mvi r2, 0
+sub r3, r1, r2
+check_r3 0
+
+test_name SUB_2
+mvi r1, 0
+mvi r2, 1
+sub r3, r1, r2
+check_r3 -1
+
+test_name SUB_3
+mvi r1, 1
+mvi r2, 0
+sub r3, r1, r2
+check_r3 1
+
+test_name SUB_4
+mvi r1, 1
+mvi r2, -1
+sub r3, r1, r2
+check_r3 2
+
+test_name SUB_5
+mvi r1, -1
+mvi r2, 1
+sub r3, r1, r2
+check_r3 -2
+
+test_name SUB_6
+mvi r1, -1
+mvi r2, 0
+sub r3, r1, r2
+check_r3 -1
+
+test_name SUB_7
+mvi r1, 0
+mvi r2, -1
+sub r3, r1, r2
+check_r3 1
+
+test_name SUB_8
+mvi r3, 2
+sub r3, r3, r3
+check_r3 0
+
+test_name SUB_9
+mvi r1, 4
+mvi r3, 2
+sub r3, r1, r3
+check_r3 2
+
+test_name SUB_10
+mvi r1, 4
+mvi r3, 2
+sub r3, r3, r1
+check_r3 -2
+
+test_name SUB_11
+mvi r1, 4
+sub r3, r1, r1
+check_r3 0
+
+test_name SUB_12
+load r1 0x12345678
+load r2 0xabcdef97
+sub r3, r1, r2
+check_r3 0x666666e1
+
+end
diff --git a/tests/tcg/lm32/test_sw.S b/tests/tcg/lm32/test_sw.S
new file mode 100644
index 0000000..d1fdadc
--- /dev/null
+++ b/tests/tcg/lm32/test_sw.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name SW_1
+load r1 data
+load r2 0xaabbccdd
+sw (r1+0), r2
+check_mem data 0xaabbccdd
+
+test_name SW_2
+load r2 0x00112233
+sw (r1+4), r2
+check_mem data1 0x00112233
+
+test_name SW_3
+load r2 0x44556677
+sw (r1+-4), r2
+check_mem data0 0x44556677
+
+test_name SW_4
+sw (r1+0), r1
+lw r3, (r1+0)
+check_r3 data
+
+end
+
+.data
+	.align 4
+data0:
+	.byte 0, 0, 0, 0
+data:
+	.byte 0, 0, 0, 0
+data1:
+	.byte 0, 0, 0, 0
diff --git a/tests/tcg/lm32/test_xnor.S b/tests/tcg/lm32/test_xnor.S
new file mode 100644
index 0000000..14a6207
--- /dev/null
+++ b/tests/tcg/lm32/test_xnor.S
@@ -0,0 +1,51 @@
+.include "macros.inc"
+
+start
+
+test_name XNOR_1
+mvi r1, 0
+mvi r2, 0
+xnor r3, r1, r2
+check_r3 0xffffffff
+
+test_name XNOR_2
+mvi r1, 0
+mvi r2, 1
+xnor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name XNOR_3
+mvi r1, 1
+mvi r2, 1
+xnor r3, r1, r2
+check_r3 0xffffffff
+
+test_name XNOR_4
+mvi r1, 1
+mvi r2, 0
+xnor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name XNOR_5
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+xnor r3, r1, r2
+check_r3 0
+
+test_name XNOR_6
+load r1 0xaa550000
+load r2 0x0000aa55
+xnor r3, r1, r2
+check_r3 0x55aa55aa
+
+test_name XNOR_7
+load r1 0xaa55aa55
+xnor r3, r1, r1
+check_r3 0xffffffff
+
+test_name XNOR_8
+load r3 0xaa55aa55
+xnor r3, r3, r3
+check_r3 0xffffffff
+
+end
diff --git a/tests/tcg/lm32/test_xnori.S b/tests/tcg/lm32/test_xnori.S
new file mode 100644
index 0000000..9d9c3c6
--- /dev/null
+++ b/tests/tcg/lm32/test_xnori.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name XNORI_1
+mvi r1, 0
+xnori r3, r1, 0
+check_r3 0xffffffff
+
+test_name XNORI_2
+mvi r1, 0
+xnori r3, r1, 1
+check_r3 0xfffffffe
+
+test_name XNORI_3
+mvi r1, 1
+xnori r3, r1, 1
+check_r3 0xffffffff
+
+test_name XNORI_4
+mvi r1, 1
+xnori r3, r1, 0
+check_r3 0xfffffffe
+
+test_name XNORI_5
+load r1 0xaa55aa55
+xnori r3, r1, 0x5555
+check_r3 0x55aa00ff
+
+test_name XNORI_6
+load r3 0xaa55aa55
+xnori r3, r3, 0x5555
+check_r3 0x55aa00ff
+
+end
diff --git a/tests/tcg/lm32/test_xor.S b/tests/tcg/lm32/test_xor.S
new file mode 100644
index 0000000..6c6e712
--- /dev/null
+++ b/tests/tcg/lm32/test_xor.S
@@ -0,0 +1,51 @@
+.include "macros.inc"
+
+start
+
+test_name XOR_1
+mvi r1, 0
+mvi r2, 0
+xor r3, r1, r2
+check_r3 0
+
+test_name XOR_2
+mvi r1, 0
+mvi r2, 1
+xor r3, r1, r2
+check_r3 1
+
+test_name XOR_3
+mvi r1, 1
+mvi r2, 1
+xor r3, r1, r2
+check_r3 0
+
+test_name XOR_4
+mvi r1, 1
+mvi r2, 0
+xor r3, r1, r2
+check_r3 1
+
+test_name XOR_5
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+xor r3, r1, r2
+check_r3 0xffffffff
+
+test_name XOR_6
+load r1 0xaa550000
+load r2 0x0000aa55
+xor r3, r1, r2
+check_r3 0xaa55aa55
+
+test_name XOR_7
+load r1 0xaa55aa55
+xor r3, r1, r1
+check_r3 0
+
+test_name XOR_8
+load r3 0xaa55aa55
+xor r3, r3, r3
+check_r3 0
+
+end
diff --git a/tests/tcg/lm32/test_xori.S b/tests/tcg/lm32/test_xori.S
new file mode 100644
index 0000000..2051699
--- /dev/null
+++ b/tests/tcg/lm32/test_xori.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name XORI_1
+mvi r1, 0
+xori r3, r1, 0
+check_r3 0
+
+test_name XORI_2
+mvi r1, 0
+xori r3, r1, 1
+check_r3 1
+
+test_name XORI_3
+mvi r1, 1
+xori r3, r1, 1
+check_r3 0
+
+test_name XORI_4
+mvi r1, 1
+xori r3, r1, 0
+check_r3 1
+
+test_name XORI_5
+load r1 0xaa55aa55
+xori r3, r1, 0x5555
+check_r3 0xaa55ff00
+
+test_name XORI_6
+load r3 0xaa55aa55
+xori r3, r3, 0x5555
+check_r3 0xaa55ff00
+
+end
diff --git a/tests/tcg/pi_10.com b/tests/tcg/pi_10.com
new file mode 100644
index 0000000..8993ba1
Binary files /dev/null and b/tests/tcg/pi_10.com differ
diff --git a/tests/tcg/runcom.c b/tests/tcg/runcom.c
new file mode 100644
index 0000000..d60342b
--- /dev/null
+++ b/tests/tcg/runcom.c
@@ -0,0 +1,192 @@
+/*
+ * Simple example of use of vm86: launch a basic .com DOS executable
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <signal.h>
+
+#include <linux/unistd.h>
+#include <asm/vm86.h>
+
+extern int vm86 (unsigned long int subfunction,
+		 struct vm86plus_struct *info);
+
+#define VIF_MASK                0x00080000
+
+//#define SIGTEST
+
+#define COM_BASE_ADDR    0x10100
+
+static void usage(void)
+{
+    printf("runcom version 0.1 (c) 2003 Fabrice Bellard\n"
+           "usage: runcom file.com\n"
+           "VM86 Run simple .com DOS executables (linux vm86 test mode)\n");
+    exit(1);
+}
+
+static inline void set_bit(uint8_t *a, unsigned int bit)
+{
+    a[bit / 8] |= (1 << (bit % 8));
+}
+
+static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
+{
+    return (uint8_t *)((seg << 4) + (reg & 0xffff));
+}
+
+static inline void pushw(struct vm86_regs *r, int val)
+{
+    r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
+    *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
+}
+
+void dump_regs(struct vm86_regs *r)
+{
+    fprintf(stderr,
+            "EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n"
+            "ESI=%08lx EDI=%08lx EBP=%08lx ESP=%08lx\n"
+            "EIP=%08lx EFL=%08lx\n"
+            "CS=%04x DS=%04x ES=%04x SS=%04x FS=%04x GS=%04x\n",
+            r->eax, r->ebx, r->ecx, r->edx, r->esi, r->edi, r->ebp, r->esp,
+            r->eip, r->eflags,
+            r->cs, r->ds, r->es, r->ss, r->fs, r->gs);
+}
+
+#ifdef SIGTEST
+void alarm_handler(int sig)
+{
+    fprintf(stderr, "alarm signal=%d\n", sig);
+    alarm(1);
+}
+#endif
+
+int main(int argc, char **argv)
+{
+    uint8_t *vm86_mem;
+    const char *filename;
+    int fd, ret, seg;
+    struct vm86plus_struct ctx;
+    struct vm86_regs *r;
+
+    if (argc != 2)
+        usage();
+    filename = argv[1];
+
+    vm86_mem = mmap((void *)0x00000000, 0x110000,
+                    PROT_WRITE | PROT_READ | PROT_EXEC,
+                    MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
+    if (vm86_mem == MAP_FAILED) {
+        perror("mmap");
+        exit(1);
+    }
+#ifdef SIGTEST
+    {
+        struct sigaction act;
+
+        act.sa_handler = alarm_handler;
+        sigemptyset(&act.sa_mask);
+        act.sa_flags = 0;
+        sigaction(SIGALRM, &act, NULL);
+        alarm(1);
+    }
+#endif
+
+    /* load the MSDOS .com executable */
+    fd = open(filename, O_RDONLY);
+    if (fd < 0) {
+        perror(filename);
+        exit(1);
+    }
+    ret = read(fd, vm86_mem + COM_BASE_ADDR, 65536 - 256);
+    if (ret < 0) {
+        perror("read");
+        exit(1);
+    }
+    close(fd);
+
+    memset(&ctx, 0, sizeof(ctx));
+    /* init basic registers */
+    r = &ctx.regs;
+    r->eip = 0x100;
+    r->esp = 0xfffe;
+    seg = (COM_BASE_ADDR - 0x100) >> 4;
+    r->cs = seg;
+    r->ss = seg;
+    r->ds = seg;
+    r->es = seg;
+    r->fs = seg;
+    r->gs = seg;
+    r->eflags = VIF_MASK;
+
+    /* put return code */
+    set_bit((uint8_t *)&ctx.int_revectored, 0x21);
+    *seg_to_linear(r->cs, 0) = 0xb4; /* mov ah, $0 */
+    *seg_to_linear(r->cs, 1) = 0x00;
+    *seg_to_linear(r->cs, 2) = 0xcd; /* int $0x21 */
+    *seg_to_linear(r->cs, 3) = 0x21;
+    pushw(&ctx.regs, 0x0000);
+
+    /* the value of these registers seem to be assumed by pi_10.com */
+    r->esi = 0x100;
+    r->ecx = 0xff;
+    r->ebp = 0x0900;
+    r->edi = 0xfffe;
+
+    for(;;) {
+        ret = vm86(VM86_ENTER, &ctx);
+        switch(VM86_TYPE(ret)) {
+        case VM86_INTx:
+            {
+                int int_num, ah;
+
+                int_num = VM86_ARG(ret);
+                if (int_num != 0x21)
+                    goto unknown_int;
+                ah = (r->eax >> 8) & 0xff;
+                switch(ah) {
+                case 0x00: /* exit */
+                    exit(0);
+                case 0x02: /* write char */
+                    {
+                        uint8_t c = r->edx;
+                        write(1, &c, 1);
+                    }
+                    break;
+                case 0x09: /* write string */
+                    {
+                        uint8_t c;
+                        for(;;) {
+                            c = *seg_to_linear(r->ds, r->edx);
+                            if (c == '$')
+                                break;
+                            write(1, &c, 1);
+                        }
+                        r->eax = (r->eax & ~0xff) | '$';
+                    }
+                    break;
+                default:
+                unknown_int:
+                    fprintf(stderr, "unsupported int 0x%02x\n", int_num);
+                    dump_regs(&ctx.regs);
+                    //                    exit(1);
+                }
+            }
+            break;
+        case VM86_SIGNAL:
+            /* a signal came, we just ignore that */
+            break;
+        case VM86_STI:
+            break;
+        default:
+            fprintf(stderr, "unhandled vm86 return code (0x%x)\n", ret);
+            dump_regs(&ctx.regs);
+            exit(1);
+        }
+    }
+}
diff --git a/tests/tcg/sha1.c b/tests/tcg/sha1.c
new file mode 100644
index 0000000..93b7c8e
--- /dev/null
+++ b/tests/tcg/sha1.c
@@ -0,0 +1,240 @@
+
+/* from valgrind tests */
+
+/* ================ sha1.c ================ */
+/*
+SHA-1 in C
+By Steve Reid <steve at edmweb.com>
+100% Public Domain
+
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
+/* #define SHA1HANDSOFF * Copies data before messing with it. */
+
+#define SHA1HANDSOFF
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+/* ================ sha1.h ================ */
+/*
+SHA-1 in C
+By Steve Reid <steve at edmweb.com>
+100% Public Domain
+*/
+
+typedef struct {
+    uint32_t state[5];
+    uint32_t count[2];
+    unsigned char buffer[64];
+} SHA1_CTX;
+
+void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]);
+void SHA1Init(SHA1_CTX* context);
+void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len);
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
+/* ================ end of sha1.h ================ */
+#include <endian.h>
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+    |(rol(block->l[i],8)&0x00FF00FF))
+#elif BYTE_ORDER == BIG_ENDIAN
+#define blk0(i) block->l[i]
+#else
+#error "Endianness not defined!"
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+    ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
+{
+uint32_t a, b, c, d, e;
+typedef union {
+    unsigned char c[64];
+    uint32_t l[16];
+} CHAR64LONG16;
+#ifdef SHA1HANDSOFF
+CHAR64LONG16 block[1];  /* use array to appear as a pointer */
+    memcpy(block, buffer, 64);
+#else
+    /* The following had better never be used because it causes the
+     * pointer-to-const buffer to be cast into a pointer to non-const.
+     * And the result is written through.  I threw a "const" in, hoping
+     * this will cause a diagnostic.
+     */
+CHAR64LONG16* block = (const CHAR64LONG16*)buffer;
+#endif
+    /* Copy context->state[] to working vars */
+    a = state[0];
+    b = state[1];
+    c = state[2];
+    d = state[3];
+    e = state[4];
+    /* 4 rounds of 20 operations each. Loop unrolled. */
+    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+    /* Add the working vars back into context.state[] */
+    state[0] += a;
+    state[1] += b;
+    state[2] += c;
+    state[3] += d;
+    state[4] += e;
+    /* Wipe variables */
+    a = b = c = d = e = 0;
+#ifdef SHA1HANDSOFF
+    memset(block, '\0', sizeof(block));
+#endif
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void SHA1Init(SHA1_CTX* context)
+{
+    /* SHA1 initialization constants */
+    context->state[0] = 0x67452301;
+    context->state[1] = 0xEFCDAB89;
+    context->state[2] = 0x98BADCFE;
+    context->state[3] = 0x10325476;
+    context->state[4] = 0xC3D2E1F0;
+    context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len)
+{
+uint32_t i;
+uint32_t j;
+
+    j = context->count[0];
+    if ((context->count[0] += len << 3) < j)
+	context->count[1]++;
+    context->count[1] += (len>>29);
+    j = (j >> 3) & 63;
+    if ((j + len) > 63) {
+        memcpy(&context->buffer[j], data, (i = 64-j));
+        SHA1Transform(context->state, context->buffer);
+        for ( ; i + 63 < len; i += 64) {
+            SHA1Transform(context->state, &data[i]);
+        }
+        j = 0;
+    }
+    else i = 0;
+    memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+{
+unsigned i;
+unsigned char finalcount[8];
+unsigned char c;
+
+#if 0	/* untested "improvement" by DHR */
+    /* Convert context->count to a sequence of bytes
+     * in finalcount.  Second element first, but
+     * big-endian order within element.
+     * But we do it all backwards.
+     */
+    unsigned char *fcp = &finalcount[8];
+
+    for (i = 0; i < 2; i++)
+    {
+	uint32_t t = context->count[i];
+	int j;
+
+	for (j = 0; j < 4; t >>= 8, j++)
+	    *--fcp = (unsigned char) t;
+    }
+#else
+    for (i = 0; i < 8; i++) {
+        finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+         >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
+    }
+#endif
+    c = 0200;
+    SHA1Update(context, &c, 1);
+    while ((context->count[0] & 504) != 448) {
+	c = 0000;
+        SHA1Update(context, &c, 1);
+    }
+    SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
+    for (i = 0; i < 20; i++) {
+        digest[i] = (unsigned char)
+         ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+    }
+    /* Wipe variables */
+    memset(context, '\0', sizeof(*context));
+    memset(&finalcount, '\0', sizeof(finalcount));
+}
+/* ================ end of sha1.c ================ */
+
+#define BUFSIZE 4096
+
+int
+main(int argc, char **argv)
+{
+    SHA1_CTX ctx;
+    unsigned char hash[20], buf[BUFSIZE];
+    int i;
+
+    for(i=0;i<BUFSIZE;i++)
+        buf[i] = i;
+
+    SHA1Init(&ctx);
+    for(i=0;i<1000;i++)
+        SHA1Update(&ctx, buf, BUFSIZE);
+    SHA1Final(hash, &ctx);
+
+    printf("SHA1=");
+    for(i=0;i<20;i++)
+        printf("%02x", hash[i]);
+    printf("\n");
+    return 0;
+}
diff --git a/tests/tcg/test-arm-iwmmxt.s b/tests/tcg/test-arm-iwmmxt.s
new file mode 100644
index 0000000..d647f94
--- /dev/null
+++ b/tests/tcg/test-arm-iwmmxt.s
@@ -0,0 +1,49 @@
+@ Checks whether iwMMXt is functional.
+.code	32
+.globl	main
+
+main:
+ldr	r0, =data0
+ldr	r1, =data1
+ldr	r2, =data2
+#ifndef FPA
+wldrd	wr0, [r0, #0]
+wldrd	wr1, [r0, #8]
+wldrd	wr2, [r1, #0]
+wldrd	wr3, [r1, #8]
+wsubb	wr2, wr2, wr0
+wsubb	wr3, wr3, wr1
+wldrd	wr0, [r2, #0]
+wldrd	wr1, [r2, #8]
+waddb	wr0, wr0, wr2
+waddb	wr1, wr1, wr3
+wstrd	wr0, [r2, #0]
+wstrd	wr1, [r2, #8]
+#else
+ldfe	f0, [r0, #0]
+ldfe	f1, [r0, #8]
+ldfe	f2, [r1, #0]
+ldfe	f3, [r1, #8]
+adfdp	f2, f2, f0
+adfdp	f3, f3, f1
+ldfe	f0, [r2, #0]
+ldfe	f1, [r2, #8]
+adfd	f0, f0, f2
+adfd	f1, f1, f3
+stfe	f0, [r2, #0]
+stfe	f1, [r2, #8]
+#endif
+mov	r0, #1
+mov	r1, r2
+mov	r2, #0x11
+swi	#0x900004
+mov	r0, #0
+swi	#0x900001
+
+.data
+data0:
+.string	"aaaabbbbccccdddd"
+data1:
+.string	"bbbbccccddddeeee"
+data2:
+.string	"hvLLWs\x1fsdrs9\x1fNJ-\n"
diff --git a/tests/tcg/test-i386-code16.S b/tests/tcg/test-i386-code16.S
new file mode 100644
index 0000000..816c24b
--- /dev/null
+++ b/tests/tcg/test-i386-code16.S
@@ -0,0 +1,79 @@
+        .code16
+        .globl code16_start
+        .globl code16_end
+
+CS_SEG = 0xf
+
+code16_start:
+
+        .globl code16_func1
+
+        /* basic test */
+code16_func1 = . - code16_start
+        mov $1, %eax
+        data32 lret
+
+/* test push/pop in 16 bit mode */
+        .globl code16_func2
+code16_func2 = . - code16_start
+        xor %eax, %eax
+        mov $0x12345678, %ebx
+        movl %esp, %ecx
+        push %bx
+        subl %esp, %ecx
+        pop %ax
+        data32 lret
+
+/* test various jmp opcodes */
+        .globl code16_func3
+code16_func3 = . - code16_start
+        jmp 1f
+        nop
+1:
+        mov $4, %eax
+        mov $0x12345678, %ebx
+        xor %bx, %bx
+        jz 2f
+        add $2, %ax
+2:
+
+        call myfunc
+
+        lcall $CS_SEG, $(myfunc2 - code16_start)
+
+        ljmp $CS_SEG, $(myjmp1 - code16_start)
+myjmp1_next:
+
+        cs lcall *myfunc2_addr - code16_start
+
+        cs ljmp *myjmp2_addr - code16_start
+myjmp2_next:
+
+        data32 lret
+
+myfunc2_addr:
+        .short myfunc2 - code16_start
+        .short CS_SEG
+
+myjmp2_addr:
+        .short myjmp2 - code16_start
+        .short CS_SEG
+
+myjmp1:
+        add $8, %ax
+        jmp myjmp1_next
+
+myjmp2:
+        add $16, %ax
+        jmp myjmp2_next
+
+myfunc:
+        add $1, %ax
+        ret
+
+myfunc2:
+        add $4, %ax
+        lret
+
+
+code16_end:
diff --git a/tests/tcg/test-i386-muldiv.h b/tests/tcg/test-i386-muldiv.h
new file mode 100644
index 0000000..015f59e
--- /dev/null
+++ b/tests/tcg/test-i386-muldiv.h
@@ -0,0 +1,76 @@
+
+void glue(glue(test_, OP), b)(long op0, long op1)
+{
+    long res, s1, s0, flags;
+    s0 = op0;
+    s1 = op1;
+    res = s0;
+    flags = 0;
+    asm ("push %4\n\t"
+         "popf\n\t"
+         stringify(OP)"b %b2\n\t"
+         "pushf\n\t"
+         "pop %1\n\t"
+         : "=a" (res), "=g" (flags)
+         : "q" (s1), "0" (res), "1" (flags));
+    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
+           stringify(OP) "b", s0, s1, res, flags & CC_MASK);
+}
+
+void glue(glue(test_, OP), w)(long op0h, long op0, long op1)
+{
+    long res, s1, flags, resh;
+    s1 = op1;
+    resh = op0h;
+    res = op0;
+    flags = 0;
+    asm ("push %5\n\t"
+         "popf\n\t"
+         stringify(OP) "w %w3\n\t"
+         "pushf\n\t"
+         "pop %1\n\t"
+         : "=a" (res), "=g" (flags), "=d" (resh)
+         : "q" (s1), "0" (res), "1" (flags), "2" (resh));
+    printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n",
+           stringify(OP) "w", op0h, op0, s1, resh, res, flags & CC_MASK);
+}
+
+void glue(glue(test_, OP), l)(long op0h, long op0, long op1)
+{
+    long res, s1, flags, resh;
+    s1 = op1;
+    resh = op0h;
+    res = op0;
+    flags = 0;
+    asm ("push %5\n\t"
+         "popf\n\t"
+         stringify(OP) "l %k3\n\t"
+         "pushf\n\t"
+         "pop %1\n\t"
+         : "=a" (res), "=g" (flags), "=d" (resh)
+         : "q" (s1), "0" (res), "1" (flags), "2" (resh));
+    printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n",
+           stringify(OP) "l", op0h, op0, s1, resh, res, flags & CC_MASK);
+}
+
+#if defined(__x86_64__)
+void glue(glue(test_, OP), q)(long op0h, long op0, long op1)
+{
+    long res, s1, flags, resh;
+    s1 = op1;
+    resh = op0h;
+    res = op0;
+    flags = 0;
+    asm ("push %5\n\t"
+         "popf\n\t"
+         stringify(OP) "q %3\n\t"
+         "pushf\n\t"
+         "pop %1\n\t"
+         : "=a" (res), "=g" (flags), "=d" (resh)
+         : "q" (s1), "0" (res), "1" (flags), "2" (resh));
+    printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n",
+           stringify(OP) "q", op0h, op0, s1, resh, res, flags & CC_MASK);
+}
+#endif
+
+#undef OP
diff --git a/tests/tcg/test-i386-shift.h b/tests/tcg/test-i386-shift.h
new file mode 100644
index 0000000..3d8f84b
--- /dev/null
+++ b/tests/tcg/test-i386-shift.h
@@ -0,0 +1,185 @@
+
+#define exec_op glue(exec_, OP)
+#define exec_opq glue(glue(exec_, OP), q)
+#define exec_opl glue(glue(exec_, OP), l)
+#define exec_opw glue(glue(exec_, OP), w)
+#define exec_opb glue(glue(exec_, OP), b)
+
+#ifndef OP_SHIFTD
+
+#ifdef OP_NOBYTE
+#define EXECSHIFT(size, rsize, res, s1, s2, flags) \
+    asm ("push %4\n\t"\
+         "popf\n\t"\
+         stringify(OP) size " %" rsize "2, %" rsize "0\n\t" \
+         "pushf\n\t"\
+         "pop %1\n\t"\
+         : "=g" (res), "=g" (flags)\
+         : "r" (s1), "0" (res), "1" (flags));
+#else
+#define EXECSHIFT(size, rsize, res, s1, s2, flags) \
+    asm ("push %4\n\t"\
+         "popf\n\t"\
+         stringify(OP) size " %%cl, %" rsize "0\n\t" \
+         "pushf\n\t"\
+         "pop %1\n\t"\
+         : "=q" (res), "=g" (flags)\
+         : "c" (s1), "0" (res), "1" (flags));
+#endif
+
+#if defined(__x86_64__)
+void exec_opq(long s2, long s0, long s1, long iflags)
+{
+    long res, flags;
+    res = s0;
+    flags = iflags;
+    EXECSHIFT("q", "", res, s1, s2, flags);
+    /* overflow is undefined if count != 1 */
+    if (s1 != 1)
+      flags &= ~CC_O;
+    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+           stringify(OP) "q", s0, s1, res, iflags, flags & CC_MASK);
+}
+#endif
+
+void exec_opl(long s2, long s0, long s1, long iflags)
+{
+    long res, flags;
+    res = s0;
+    flags = iflags;
+    EXECSHIFT("l", "k", res, s1, s2, flags);
+    /* overflow is undefined if count != 1 */
+    if (s1 != 1)
+      flags &= ~CC_O;
+    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+           stringify(OP) "l", s0, s1, res, iflags, flags & CC_MASK);
+}
+
+void exec_opw(long s2, long s0, long s1, long iflags)
+{
+    long res, flags;
+    res = s0;
+    flags = iflags;
+    EXECSHIFT("w", "w", res, s1, s2, flags);
+    /* overflow is undefined if count != 1 */
+    if (s1 != 1)
+      flags &= ~CC_O;
+    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+           stringify(OP) "w", s0, s1, res, iflags, flags & CC_MASK);
+}
+
+#else
+#define EXECSHIFT(size, rsize, res, s1, s2, flags) \
+    asm ("push %4\n\t"\
+         "popf\n\t"\
+         stringify(OP) size " %%cl, %" rsize "5, %" rsize "0\n\t" \
+         "pushf\n\t"\
+         "pop %1\n\t"\
+         : "=g" (res), "=g" (flags)\
+         : "c" (s1), "0" (res), "1" (flags), "r" (s2));
+
+#if defined(__x86_64__)
+void exec_opq(long s2, long s0, long s1, long iflags)
+{
+    long res, flags;
+    res = s0;
+    flags = iflags;
+    EXECSHIFT("q", "", res, s1, s2, flags);
+    /* overflow is undefined if count != 1 */
+    if (s1 != 1)
+      flags &= ~CC_O;
+    printf("%-10s A=" FMTLX " B=" FMTLX " C=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+           stringify(OP) "q", s0, s2, s1, res, iflags, flags & CC_MASK);
+}
+#endif
+
+void exec_opl(long s2, long s0, long s1, long iflags)
+{
+    long res, flags;
+    res = s0;
+    flags = iflags;
+    EXECSHIFT("l", "k", res, s1, s2, flags);
+    /* overflow is undefined if count != 1 */
+    if (s1 != 1)
+      flags &= ~CC_O;
+    printf("%-10s A=" FMTLX " B=" FMTLX " C=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+           stringify(OP) "l", s0, s2, s1, res, iflags, flags & CC_MASK);
+}
+
+void exec_opw(long s2, long s0, long s1, long iflags)
+{
+    long res, flags;
+    res = s0;
+    flags = iflags;
+    EXECSHIFT("w", "w", res, s1, s2, flags);
+    /* overflow is undefined if count != 1 */
+    if (s1 != 1)
+      flags &= ~CC_O;
+    printf("%-10s A=" FMTLX " B=" FMTLX " C=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+           stringify(OP) "w", s0, s2, s1, res, iflags, flags & CC_MASK);
+}
+
+#endif
+
+#ifndef OP_NOBYTE
+void exec_opb(long s0, long s1, long iflags)
+{
+    long res, flags;
+    res = s0;
+    flags = iflags;
+    EXECSHIFT("b", "b", res, s1, 0, flags);
+    /* overflow is undefined if count != 1 */
+    if (s1 != 1)
+      flags &= ~CC_O;
+    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+           stringify(OP) "b", s0, s1, res, iflags, flags & CC_MASK);
+}
+#endif
+
+void exec_op(long s2, long s0, long s1)
+{
+    s2 = i2l(s2);
+    s0 = i2l(s0);
+#if defined(__x86_64__)
+    exec_opq(s2, s0, s1, 0);
+#endif
+    exec_opl(s2, s0, s1, 0);
+#ifdef OP_SHIFTD
+    exec_opw(s2, s0, s1, 0);
+#else
+    exec_opw(s2, s0, s1, 0);
+#endif
+#ifndef OP_NOBYTE
+    exec_opb(s0, s1, 0);
+#endif
+#ifdef OP_CC
+#if defined(__x86_64__)
+    exec_opq(s2, s0, s1, CC_C);
+#endif
+    exec_opl(s2, s0, s1, CC_C);
+    exec_opw(s2, s0, s1, CC_C);
+    exec_opb(s0, s1, CC_C);
+#endif
+}
+
+void glue(test_, OP)(void)
+{
+    int i, n;
+#if defined(__x86_64__)
+    n = 64;
+#else
+    n = 32;
+#endif
+    for(i = 0; i < n; i++)
+        exec_op(0x21ad3d34, 0x12345678, i);
+    for(i = 0; i < n; i++)
+        exec_op(0x813f3421, 0x82345679, i);
+}
+
+void *glue(_test_, OP) __init_call = glue(test_, OP);
+
+#undef OP
+#undef OP_CC
+#undef OP_SHIFTD
+#undef OP_NOBYTE
+#undef EXECSHIFT
diff --git a/tests/tcg/test-i386-ssse3.c b/tests/tcg/test-i386-ssse3.c
new file mode 100644
index 0000000..0a42bd0
--- /dev/null
+++ b/tests/tcg/test-i386-ssse3.c
@@ -0,0 +1,57 @@
+/* See if various MMX/SSE SSSE3 instructions give expected results */
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+int main(int argc, char *argv[]) {
+	char hello[16];
+	const char ehlo[8] = "EHLO    ";
+	uint64_t mask = 0x8080800302020001;
+
+	uint64_t a = 0x0000000000090007;
+	uint64_t b = 0x0000000000000000;
+	uint32_t c;
+	uint16_t d;
+
+	const char e[16] = "LLOaaaaaaaaaaaaa";
+	const char f[16] = "aaaaaaaaaaaaaaHE";
+
+	/* pshufb mm1/xmm1, mm2/xmm2 */
+	asm volatile ("movq    (%0), %%mm0" : : "r" (ehlo) : "mm0", "mm1");
+	asm volatile ("movq    %0, %%mm1" : : "m" (mask));
+	asm volatile ("pshufb  %mm1, %mm0");
+	asm volatile ("movq    %%mm0, %0" : "=m" (hello));
+	printf("%s\n", hello);
+
+	/* pshufb mm1/xmm1, m64/m128 */
+	asm volatile ("movq    (%0), %%mm0" : : "r" (ehlo) : "mm0");
+	asm volatile ("pshufb  %0, %%mm0" : : "m" (mask));
+	asm volatile ("movq    %%mm0, %0" : "=m" (hello));
+	printf("%s\n", hello);
+
+	/* psubsw mm1/xmm1, m64/m128 */
+	asm volatile ("movq    %0, %%mm0" : : "r" (a) : "mm0");
+	asm volatile ("phsubsw %0, %%mm0" : : "m" (b));
+	asm volatile ("movq    %%mm0, %0" : "=m" (a));
+	printf("%i - %i = %i\n", 9, 7, -(int16_t) a);
+
+	/* palignr mm1/xmm1, m64/m128, imm8 */
+	asm volatile ("movdqa  (%0), %%xmm0" : : "r" (e) : "xmm0");
+	asm volatile ("palignr $14, (%0), %%xmm0" : : "r" (f));
+	asm volatile ("movdqa  %%xmm0, (%0)" : : "r" (hello));
+	printf("%5.5s\n", hello);
+
+#if 1 /* SSE4 */
+	/* popcnt r64, r/m64 */
+	asm volatile ("movq    $0x8421000010009c63, %%rax" : : : "rax");
+	asm volatile ("popcnt  %%ax, %%dx" : : : "dx");
+	asm volatile ("popcnt  %%eax, %%ecx" : : : "ecx");
+	asm volatile ("popcnt  %rax, %rax");
+	asm volatile ("movq    %%rax, %0" : "=m" (a));
+	asm volatile ("movl    %%ecx, %0" : "=m" (c));
+	asm volatile ("movw    %%dx, %0" : "=m" (d));
+	printf("%i = %i\n%i = %i = %i\n", 13, (int) a, 9, c, d + 1);
+#endif
+
+	return 0;
+}
diff --git a/tests/tcg/test-i386-vm86.S b/tests/tcg/test-i386-vm86.S
new file mode 100644
index 0000000..3bb96c9
--- /dev/null
+++ b/tests/tcg/test-i386-vm86.S
@@ -0,0 +1,103 @@
+        .code16
+        .globl vm86_code_start
+        .globl vm86_code_end
+
+#define GET_OFFSET(x) ((x) - vm86_code_start + 0x100)
+
+vm86_code_start:
+        movw $GET_OFFSET(hello_world), %dx
+        movb $0x09, %ah
+        int $0x21
+
+        /* prepare int 0x90 vector */
+        xorw %ax, %ax
+        movw %ax, %es
+        es movw $GET_OFFSET(int90_test), 0x90 * 4
+        es movw %cs, 0x90 * 4 + 2
+
+        /* launch int 0x90 */
+
+        int $0x90
+
+        /* test IF support */
+        movw $GET_OFFSET(IF_msg), %dx
+        movb $0x09, %ah
+        int $0x21
+
+        pushf
+        popw %dx
+        movb $0xff, %ah
+        int $0x21
+
+        cli
+        pushf
+        popw %dx
+        movb $0xff, %ah
+        int $0x21
+
+        sti
+        pushfl
+        popl %edx
+        movb $0xff, %ah
+        int $0x21
+
+#if 0
+        movw $GET_OFFSET(IF_msg1), %dx
+        movb $0x09, %ah
+        int $0x21
+
+        pushf
+        movw %sp, %bx
+        andw $~0x200, (%bx)
+        popf
+#else
+        cli
+#endif
+
+        pushf
+        popw %dx
+        movb $0xff, %ah
+        int $0x21
+
+        pushfl
+        movw %sp, %bx
+        orw $0x200, (%bx)
+        popfl
+
+        pushfl
+        popl %edx
+        movb $0xff, %ah
+        int $0x21
+
+        movb $0x00, %ah
+        int $0x21
+
+int90_test:
+        pushf
+        pop %dx
+        movb $0xff, %ah
+        int $0x21
+
+        movw %sp, %bx
+        movw 4(%bx), %dx
+        movb $0xff, %ah
+        int $0x21
+
+        movw $GET_OFFSET(int90_msg), %dx
+        movb $0x09, %ah
+        int $0x21
+        iret
+
+int90_msg:
+        .string "INT90 started\n$"
+
+hello_world:
+        .string "Hello VM86 world\n$"
+
+IF_msg:
+        .string "VM86 IF test\n$"
+
+IF_msg1:
+        .string "If you see a diff here, your Linux kernel is buggy, please update to 2.4.20 kernel\n$"
+
+vm86_code_end:
diff --git a/tests/tcg/test-i386.c b/tests/tcg/test-i386.c
new file mode 100644
index 0000000..8e64bba
--- /dev/null
+++ b/tests/tcg/test-i386.c
@@ -0,0 +1,2764 @@
+/*
+ *  x86 CPU test
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <errno.h>
+#include <sys/ucontext.h>
+#include <sys/mman.h>
+
+#if !defined(__x86_64__)
+//#define TEST_VM86
+#define TEST_SEGS
+#endif
+//#define LINUX_VM86_IOPL_FIX
+//#define TEST_P4_FLAGS
+#ifdef __SSE__
+#define TEST_SSE
+#define TEST_CMOV  1
+#define TEST_FCOMI 1
+#else
+#undef TEST_SSE
+#define TEST_CMOV  1
+#define TEST_FCOMI 1
+#endif
+
+#if defined(__x86_64__)
+#define FMT64X "%016lx"
+#define FMTLX "%016lx"
+#define X86_64_ONLY(x) x
+#else
+#define FMT64X "%016" PRIx64
+#define FMTLX "%08lx"
+#define X86_64_ONLY(x)
+#endif
+
+#ifdef TEST_VM86
+#include <asm/vm86.h>
+#endif
+
+#define xglue(x, y) x ## y
+#define glue(x, y) xglue(x, y)
+#define stringify(s)	tostring(s)
+#define tostring(s)	#s
+
+#define CC_C   	0x0001
+#define CC_P 	0x0004
+#define CC_A	0x0010
+#define CC_Z	0x0040
+#define CC_S    0x0080
+#define CC_O    0x0800
+
+#define __init_call	__attribute__ ((unused,__section__ ("initcall")))
+
+#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
+
+#if defined(__x86_64__)
+static inline long i2l(long v)
+{
+    return v | ((v ^ 0xabcd) << 32);
+}
+#else
+static inline long i2l(long v)
+{
+    return v;
+}
+#endif
+
+#define OP add
+#include "test-i386.h"
+
+#define OP sub
+#include "test-i386.h"
+
+#define OP xor
+#include "test-i386.h"
+
+#define OP and
+#include "test-i386.h"
+
+#define OP or
+#include "test-i386.h"
+
+#define OP cmp
+#include "test-i386.h"
+
+#define OP adc
+#define OP_CC
+#include "test-i386.h"
+
+#define OP sbb
+#define OP_CC
+#include "test-i386.h"
+
+#define OP inc
+#define OP_CC
+#define OP1
+#include "test-i386.h"
+
+#define OP dec
+#define OP_CC
+#define OP1
+#include "test-i386.h"
+
+#define OP neg
+#define OP_CC
+#define OP1
+#include "test-i386.h"
+
+#define OP not
+#define OP_CC
+#define OP1
+#include "test-i386.h"
+
+#undef CC_MASK
+#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)
+
+#define OP shl
+#include "test-i386-shift.h"
+
+#define OP shr
+#include "test-i386-shift.h"
+
+#define OP sar
+#include "test-i386-shift.h"
+
+#define OP rol
+#include "test-i386-shift.h"
+
+#define OP ror
+#include "test-i386-shift.h"
+
+#define OP rcr
+#define OP_CC
+#include "test-i386-shift.h"
+
+#define OP rcl
+#define OP_CC
+#include "test-i386-shift.h"
+
+#define OP shld
+#define OP_SHIFTD
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+#define OP shrd
+#define OP_SHIFTD
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+/* XXX: should be more precise ? */
+#undef CC_MASK
+#define CC_MASK (CC_C)
+
+#define OP bt
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+#define OP bts
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+#define OP btr
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+#define OP btc
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+/* lea test (modrm support) */
+#define TEST_LEAQ(STR)\
+{\
+    asm("lea " STR ", %0"\
+        : "=r" (res)\
+        : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
+    printf("lea %s = " FMTLX "\n", STR, res);\
+}
+
+#define TEST_LEA(STR)\
+{\
+    asm("lea " STR ", %0"\
+        : "=r" (res)\
+        : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
+    printf("lea %s = " FMTLX "\n", STR, res);\
+}
+
+#define TEST_LEA16(STR)\
+{\
+    asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\
+        : "=wq" (res)\
+        : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
+    printf("lea %s = %08lx\n", STR, res);\
+}
+
+
+void test_lea(void)
+{
+    long eax, ebx, ecx, edx, esi, edi, res;
+    eax = i2l(0x0001);
+    ebx = i2l(0x0002);
+    ecx = i2l(0x0004);
+    edx = i2l(0x0008);
+    esi = i2l(0x0010);
+    edi = i2l(0x0020);
+
+    TEST_LEA("0x4000");
+
+    TEST_LEA("(%%eax)");
+    TEST_LEA("(%%ebx)");
+    TEST_LEA("(%%ecx)");
+    TEST_LEA("(%%edx)");
+    TEST_LEA("(%%esi)");
+    TEST_LEA("(%%edi)");
+
+    TEST_LEA("0x40(%%eax)");
+    TEST_LEA("0x40(%%ebx)");
+    TEST_LEA("0x40(%%ecx)");
+    TEST_LEA("0x40(%%edx)");
+    TEST_LEA("0x40(%%esi)");
+    TEST_LEA("0x40(%%edi)");
+
+    TEST_LEA("0x4000(%%eax)");
+    TEST_LEA("0x4000(%%ebx)");
+    TEST_LEA("0x4000(%%ecx)");
+    TEST_LEA("0x4000(%%edx)");
+    TEST_LEA("0x4000(%%esi)");
+    TEST_LEA("0x4000(%%edi)");
+
+    TEST_LEA("(%%eax, %%ecx)");
+    TEST_LEA("(%%ebx, %%edx)");
+    TEST_LEA("(%%ecx, %%ecx)");
+    TEST_LEA("(%%edx, %%ecx)");
+    TEST_LEA("(%%esi, %%ecx)");
+    TEST_LEA("(%%edi, %%ecx)");
+
+    TEST_LEA("0x40(%%eax, %%ecx)");
+    TEST_LEA("0x4000(%%ebx, %%edx)");
+
+    TEST_LEA("(%%ecx, %%ecx, 2)");
+    TEST_LEA("(%%edx, %%ecx, 4)");
+    TEST_LEA("(%%esi, %%ecx, 8)");
+
+    TEST_LEA("(,%%eax, 2)");
+    TEST_LEA("(,%%ebx, 4)");
+    TEST_LEA("(,%%ecx, 8)");
+
+    TEST_LEA("0x40(,%%eax, 2)");
+    TEST_LEA("0x40(,%%ebx, 4)");
+    TEST_LEA("0x40(,%%ecx, 8)");
+
+
+    TEST_LEA("-10(%%ecx, %%ecx, 2)");
+    TEST_LEA("-10(%%edx, %%ecx, 4)");
+    TEST_LEA("-10(%%esi, %%ecx, 8)");
+
+    TEST_LEA("0x4000(%%ecx, %%ecx, 2)");
+    TEST_LEA("0x4000(%%edx, %%ecx, 4)");
+    TEST_LEA("0x4000(%%esi, %%ecx, 8)");
+
+#if defined(__x86_64__)
+    TEST_LEAQ("0x4000");
+    TEST_LEAQ("0x4000(%%rip)");
+
+    TEST_LEAQ("(%%rax)");
+    TEST_LEAQ("(%%rbx)");
+    TEST_LEAQ("(%%rcx)");
+    TEST_LEAQ("(%%rdx)");
+    TEST_LEAQ("(%%rsi)");
+    TEST_LEAQ("(%%rdi)");
+
+    TEST_LEAQ("0x40(%%rax)");
+    TEST_LEAQ("0x40(%%rbx)");
+    TEST_LEAQ("0x40(%%rcx)");
+    TEST_LEAQ("0x40(%%rdx)");
+    TEST_LEAQ("0x40(%%rsi)");
+    TEST_LEAQ("0x40(%%rdi)");
+
+    TEST_LEAQ("0x4000(%%rax)");
+    TEST_LEAQ("0x4000(%%rbx)");
+    TEST_LEAQ("0x4000(%%rcx)");
+    TEST_LEAQ("0x4000(%%rdx)");
+    TEST_LEAQ("0x4000(%%rsi)");
+    TEST_LEAQ("0x4000(%%rdi)");
+
+    TEST_LEAQ("(%%rax, %%rcx)");
+    TEST_LEAQ("(%%rbx, %%rdx)");
+    TEST_LEAQ("(%%rcx, %%rcx)");
+    TEST_LEAQ("(%%rdx, %%rcx)");
+    TEST_LEAQ("(%%rsi, %%rcx)");
+    TEST_LEAQ("(%%rdi, %%rcx)");
+
+    TEST_LEAQ("0x40(%%rax, %%rcx)");
+    TEST_LEAQ("0x4000(%%rbx, %%rdx)");
+
+    TEST_LEAQ("(%%rcx, %%rcx, 2)");
+    TEST_LEAQ("(%%rdx, %%rcx, 4)");
+    TEST_LEAQ("(%%rsi, %%rcx, 8)");
+
+    TEST_LEAQ("(,%%rax, 2)");
+    TEST_LEAQ("(,%%rbx, 4)");
+    TEST_LEAQ("(,%%rcx, 8)");
+
+    TEST_LEAQ("0x40(,%%rax, 2)");
+    TEST_LEAQ("0x40(,%%rbx, 4)");
+    TEST_LEAQ("0x40(,%%rcx, 8)");
+
+
+    TEST_LEAQ("-10(%%rcx, %%rcx, 2)");
+    TEST_LEAQ("-10(%%rdx, %%rcx, 4)");
+    TEST_LEAQ("-10(%%rsi, %%rcx, 8)");
+
+    TEST_LEAQ("0x4000(%%rcx, %%rcx, 2)");
+    TEST_LEAQ("0x4000(%%rdx, %%rcx, 4)");
+    TEST_LEAQ("0x4000(%%rsi, %%rcx, 8)");
+#else
+    /* limited 16 bit addressing test */
+    TEST_LEA16("0x4000");
+    TEST_LEA16("(%%bx)");
+    TEST_LEA16("(%%si)");
+    TEST_LEA16("(%%di)");
+    TEST_LEA16("0x40(%%bx)");
+    TEST_LEA16("0x40(%%si)");
+    TEST_LEA16("0x40(%%di)");
+    TEST_LEA16("0x4000(%%bx)");
+    TEST_LEA16("0x4000(%%si)");
+    TEST_LEA16("(%%bx,%%si)");
+    TEST_LEA16("(%%bx,%%di)");
+    TEST_LEA16("0x40(%%bx,%%si)");
+    TEST_LEA16("0x40(%%bx,%%di)");
+    TEST_LEA16("0x4000(%%bx,%%si)");
+    TEST_LEA16("0x4000(%%bx,%%di)");
+#endif
+}
+
+#define TEST_JCC(JCC, v1, v2)\
+{\
+    int res;\
+    asm("movl $1, %0\n\t"\
+        "cmpl %2, %1\n\t"\
+        "j" JCC " 1f\n\t"\
+        "movl $0, %0\n\t"\
+        "1:\n\t"\
+        : "=r" (res)\
+        : "r" (v1), "r" (v2));\
+    printf("%-10s %d\n", "j" JCC, res);\
+\
+    asm("movl $0, %0\n\t"\
+        "cmpl %2, %1\n\t"\
+        "set" JCC " %b0\n\t"\
+        : "=r" (res)\
+        : "r" (v1), "r" (v2));\
+    printf("%-10s %d\n", "set" JCC, res);\
+ if (TEST_CMOV) {\
+    long val = i2l(1);\
+    long res = i2l(0x12345678);\
+X86_64_ONLY(\
+    asm("cmpl %2, %1\n\t"\
+        "cmov" JCC "q %3, %0\n\t"\
+        : "=r" (res)\
+        : "r" (v1), "r" (v2), "m" (val), "0" (res));\
+        printf("%-10s R=" FMTLX "\n", "cmov" JCC "q", res);)\
+    asm("cmpl %2, %1\n\t"\
+        "cmov" JCC "l %k3, %k0\n\t"\
+        : "=r" (res)\
+        : "r" (v1), "r" (v2), "m" (val), "0" (res));\
+        printf("%-10s R=" FMTLX "\n", "cmov" JCC "l", res);\
+    asm("cmpl %2, %1\n\t"\
+        "cmov" JCC "w %w3, %w0\n\t"\
+        : "=r" (res)\
+        : "r" (v1), "r" (v2), "r" (1), "0" (res));\
+        printf("%-10s R=" FMTLX "\n", "cmov" JCC "w", res);\
+ } \
+}
+
+/* various jump tests */
+void test_jcc(void)
+{
+    TEST_JCC("ne", 1, 1);
+    TEST_JCC("ne", 1, 0);
+
+    TEST_JCC("e", 1, 1);
+    TEST_JCC("e", 1, 0);
+
+    TEST_JCC("l", 1, 1);
+    TEST_JCC("l", 1, 0);
+    TEST_JCC("l", 1, -1);
+
+    TEST_JCC("le", 1, 1);
+    TEST_JCC("le", 1, 0);
+    TEST_JCC("le", 1, -1);
+
+    TEST_JCC("ge", 1, 1);
+    TEST_JCC("ge", 1, 0);
+    TEST_JCC("ge", -1, 1);
+
+    TEST_JCC("g", 1, 1);
+    TEST_JCC("g", 1, 0);
+    TEST_JCC("g", 1, -1);
+
+    TEST_JCC("b", 1, 1);
+    TEST_JCC("b", 1, 0);
+    TEST_JCC("b", 1, -1);
+
+    TEST_JCC("be", 1, 1);
+    TEST_JCC("be", 1, 0);
+    TEST_JCC("be", 1, -1);
+
+    TEST_JCC("ae", 1, 1);
+    TEST_JCC("ae", 1, 0);
+    TEST_JCC("ae", 1, -1);
+
+    TEST_JCC("a", 1, 1);
+    TEST_JCC("a", 1, 0);
+    TEST_JCC("a", 1, -1);
+
+
+    TEST_JCC("p", 1, 1);
+    TEST_JCC("p", 1, 0);
+
+    TEST_JCC("np", 1, 1);
+    TEST_JCC("np", 1, 0);
+
+    TEST_JCC("o", 0x7fffffff, 0);
+    TEST_JCC("o", 0x7fffffff, -1);
+
+    TEST_JCC("no", 0x7fffffff, 0);
+    TEST_JCC("no", 0x7fffffff, -1);
+
+    TEST_JCC("s", 0, 1);
+    TEST_JCC("s", 0, -1);
+    TEST_JCC("s", 0, 0);
+
+    TEST_JCC("ns", 0, 1);
+    TEST_JCC("ns", 0, -1);
+    TEST_JCC("ns", 0, 0);
+}
+
+#define TEST_LOOP(insn) \
+{\
+    for(i = 0; i < sizeof(ecx_vals) / sizeof(long); i++) {\
+        ecx = ecx_vals[i];\
+        for(zf = 0; zf < 2; zf++) {\
+    asm("test %2, %2\n\t"\
+        "movl $1, %0\n\t"\
+          insn " 1f\n\t" \
+        "movl $0, %0\n\t"\
+        "1:\n\t"\
+        : "=a" (res)\
+        : "c" (ecx), "b" (!zf)); \
+    printf("%-10s ECX=" FMTLX " ZF=%ld r=%d\n", insn, ecx, zf, res);      \
+        }\
+   }\
+}
+
+void test_loop(void)
+{
+    long ecx, zf;
+    const long ecx_vals[] = {
+        0,
+        1,
+        0x10000,
+        0x10001,
+#if defined(__x86_64__)
+        0x100000000L,
+        0x100000001L,
+#endif
+    };
+    int i, res;
+
+#if !defined(__x86_64__)
+    TEST_LOOP("jcxz");
+    TEST_LOOP("loopw");
+    TEST_LOOP("loopzw");
+    TEST_LOOP("loopnzw");
+#endif
+
+    TEST_LOOP("jecxz");
+    TEST_LOOP("loopl");
+    TEST_LOOP("loopzl");
+    TEST_LOOP("loopnzl");
+}
+
+#undef CC_MASK
+#ifdef TEST_P4_FLAGS
+#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
+#else
+#define CC_MASK (CC_O | CC_C)
+#endif
+
+#define OP mul
+#include "test-i386-muldiv.h"
+
+#define OP imul
+#include "test-i386-muldiv.h"
+
+void test_imulw2(long op0, long op1)
+{
+    long res, s1, s0, flags;
+    s0 = op0;
+    s1 = op1;
+    res = s0;
+    flags = 0;
+    asm volatile ("push %4\n\t"
+         "popf\n\t"
+         "imulw %w2, %w0\n\t"
+         "pushf\n\t"
+         "pop %1\n\t"
+         : "=q" (res), "=g" (flags)
+         : "q" (s1), "0" (res), "1" (flags));
+    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
+           "imulw", s0, s1, res, flags & CC_MASK);
+}
+
+void test_imull2(long op0, long op1)
+{
+    long res, s1, s0, flags;
+    s0 = op0;
+    s1 = op1;
+    res = s0;
+    flags = 0;
+    asm volatile ("push %4\n\t"
+         "popf\n\t"
+         "imull %k2, %k0\n\t"
+         "pushf\n\t"
+         "pop %1\n\t"
+         : "=q" (res), "=g" (flags)
+         : "q" (s1), "0" (res), "1" (flags));
+    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
+           "imull", s0, s1, res, flags & CC_MASK);
+}
+
+#if defined(__x86_64__)
+void test_imulq2(long op0, long op1)
+{
+    long res, s1, s0, flags;
+    s0 = op0;
+    s1 = op1;
+    res = s0;
+    flags = 0;
+    asm volatile ("push %4\n\t"
+         "popf\n\t"
+         "imulq %2, %0\n\t"
+         "pushf\n\t"
+         "pop %1\n\t"
+         : "=q" (res), "=g" (flags)
+         : "q" (s1), "0" (res), "1" (flags));
+    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
+           "imulq", s0, s1, res, flags & CC_MASK);
+}
+#endif
+
+#define TEST_IMUL_IM(size, rsize, op0, op1)\
+{\
+    long res, flags, s1;\
+    flags = 0;\
+    res = 0;\
+    s1 = op1;\
+    asm volatile ("push %3\n\t"\
+         "popf\n\t"\
+         "imul" size " $" #op0 ", %" rsize "2, %" rsize "0\n\t" \
+         "pushf\n\t"\
+         "pop %1\n\t"\
+         : "=r" (res), "=g" (flags)\
+         : "r" (s1), "1" (flags), "0" (res));\
+    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",\
+           "imul" size " im", (long)op0, (long)op1, res, flags & CC_MASK);\
+}
+
+
+#undef CC_MASK
+#define CC_MASK (0)
+
+#define OP div
+#include "test-i386-muldiv.h"
+
+#define OP idiv
+#include "test-i386-muldiv.h"
+
+void test_mul(void)
+{
+    test_imulb(0x1234561d, 4);
+    test_imulb(3, -4);
+    test_imulb(0x80, 0x80);
+    test_imulb(0x10, 0x10);
+
+    test_imulw(0, 0x1234001d, 45);
+    test_imulw(0, 23, -45);
+    test_imulw(0, 0x8000, 0x8000);
+    test_imulw(0, 0x100, 0x100);
+
+    test_imull(0, 0x1234001d, 45);
+    test_imull(0, 23, -45);
+    test_imull(0, 0x80000000, 0x80000000);
+    test_imull(0, 0x10000, 0x10000);
+
+    test_mulb(0x1234561d, 4);
+    test_mulb(3, -4);
+    test_mulb(0x80, 0x80);
+    test_mulb(0x10, 0x10);
+
+    test_mulw(0, 0x1234001d, 45);
+    test_mulw(0, 23, -45);
+    test_mulw(0, 0x8000, 0x8000);
+    test_mulw(0, 0x100, 0x100);
+
+    test_mull(0, 0x1234001d, 45);
+    test_mull(0, 23, -45);
+    test_mull(0, 0x80000000, 0x80000000);
+    test_mull(0, 0x10000, 0x10000);
+
+    test_imulw2(0x1234001d, 45);
+    test_imulw2(23, -45);
+    test_imulw2(0x8000, 0x8000);
+    test_imulw2(0x100, 0x100);
+
+    test_imull2(0x1234001d, 45);
+    test_imull2(23, -45);
+    test_imull2(0x80000000, 0x80000000);
+    test_imull2(0x10000, 0x10000);
+
+    TEST_IMUL_IM("w", "w", 45, 0x1234);
+    TEST_IMUL_IM("w", "w", -45, 23);
+    TEST_IMUL_IM("w", "w", 0x8000, 0x80000000);
+    TEST_IMUL_IM("w", "w", 0x7fff, 0x1000);
+
+    TEST_IMUL_IM("l", "k", 45, 0x1234);
+    TEST_IMUL_IM("l", "k", -45, 23);
+    TEST_IMUL_IM("l", "k", 0x8000, 0x80000000);
+    TEST_IMUL_IM("l", "k", 0x7fff, 0x1000);
+
+    test_idivb(0x12341678, 0x127e);
+    test_idivb(0x43210123, -5);
+    test_idivb(0x12340004, -1);
+
+    test_idivw(0, 0x12345678, 12347);
+    test_idivw(0, -23223, -45);
+    test_idivw(0, 0x12348000, -1);
+    test_idivw(0x12343, 0x12345678, 0x81238567);
+
+    test_idivl(0, 0x12345678, 12347);
+    test_idivl(0, -233223, -45);
+    test_idivl(0, 0x80000000, -1);
+    test_idivl(0x12343, 0x12345678, 0x81234567);
+
+    test_divb(0x12341678, 0x127e);
+    test_divb(0x43210123, -5);
+    test_divb(0x12340004, -1);
+
+    test_divw(0, 0x12345678, 12347);
+    test_divw(0, -23223, -45);
+    test_divw(0, 0x12348000, -1);
+    test_divw(0x12343, 0x12345678, 0x81238567);
+
+    test_divl(0, 0x12345678, 12347);
+    test_divl(0, -233223, -45);
+    test_divl(0, 0x80000000, -1);
+    test_divl(0x12343, 0x12345678, 0x81234567);
+
+#if defined(__x86_64__)
+    test_imulq(0, 0x1234001d1234001d, 45);
+    test_imulq(0, 23, -45);
+    test_imulq(0, 0x8000000000000000, 0x8000000000000000);
+    test_imulq(0, 0x100000000, 0x100000000);
+
+    test_mulq(0, 0x1234001d1234001d, 45);
+    test_mulq(0, 23, -45);
+    test_mulq(0, 0x8000000000000000, 0x8000000000000000);
+    test_mulq(0, 0x100000000, 0x100000000);
+
+    test_imulq2(0x1234001d1234001d, 45);
+    test_imulq2(23, -45);
+    test_imulq2(0x8000000000000000, 0x8000000000000000);
+    test_imulq2(0x100000000, 0x100000000);
+
+    TEST_IMUL_IM("q", "", 45, 0x12341234);
+    TEST_IMUL_IM("q", "", -45, 23);
+    TEST_IMUL_IM("q", "", 0x8000, 0x8000000000000000);
+    TEST_IMUL_IM("q", "", 0x7fff, 0x10000000);
+
+    test_idivq(0, 0x12345678abcdef, 12347);
+    test_idivq(0, -233223, -45);
+    test_idivq(0, 0x8000000000000000, -1);
+    test_idivq(0x12343, 0x12345678, 0x81234567);
+
+    test_divq(0, 0x12345678abcdef, 12347);
+    test_divq(0, -233223, -45);
+    test_divq(0, 0x8000000000000000, -1);
+    test_divq(0x12343, 0x12345678, 0x81234567);
+#endif
+}
+
+#define TEST_BSX(op, size, op0)\
+{\
+    long res, val, resz;\
+    val = op0;\
+    asm("xor %1, %1\n"\
+        "mov $0x12345678, %0\n"\
+        #op " %" size "2, %" size "0 ; setz %b1" \
+        : "=&r" (res), "=&q" (resz)\
+        : "r" (val));\
+    printf("%-10s A=" FMTLX " R=" FMTLX " %ld\n", #op, val, res, resz);\
+}
+
+void test_bsx(void)
+{
+    TEST_BSX(bsrw, "w", 0);
+    TEST_BSX(bsrw, "w", 0x12340128);
+    TEST_BSX(bsfw, "w", 0);
+    TEST_BSX(bsfw, "w", 0x12340128);
+    TEST_BSX(bsrl, "k", 0);
+    TEST_BSX(bsrl, "k", 0x00340128);
+    TEST_BSX(bsfl, "k", 0);
+    TEST_BSX(bsfl, "k", 0x00340128);
+#if defined(__x86_64__)
+    TEST_BSX(bsrq, "", 0);
+    TEST_BSX(bsrq, "", 0x003401281234);
+    TEST_BSX(bsfq, "", 0);
+    TEST_BSX(bsfq, "", 0x003401281234);
+#endif
+}
+
+/**********************************************/
+
+union float64u {
+    double d;
+    uint64_t l;
+};
+
+union float64u q_nan = { .l = 0xFFF8000000000000LL };
+union float64u s_nan = { .l = 0xFFF0000000000000LL };
+
+void test_fops(double a, double b)
+{
+    printf("a=%f b=%f a+b=%f\n", a, b, a + b);
+    printf("a=%f b=%f a-b=%f\n", a, b, a - b);
+    printf("a=%f b=%f a*b=%f\n", a, b, a * b);
+    printf("a=%f b=%f a/b=%f\n", a, b, a / b);
+    printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b));
+    printf("a=%f sqrt(a)=%f\n", a, sqrt(a));
+    printf("a=%f sin(a)=%f\n", a, sin(a));
+    printf("a=%f cos(a)=%f\n", a, cos(a));
+    printf("a=%f tan(a)=%f\n", a, tan(a));
+    printf("a=%f log(a)=%f\n", a, log(a));
+    printf("a=%f exp(a)=%f\n", a, exp(a));
+    printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
+    /* just to test some op combining */
+    printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a)));
+    printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a)));
+    printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));
+
+}
+
+void fpu_clear_exceptions(void)
+{
+    struct QEMU_PACKED {
+        uint16_t fpuc;
+        uint16_t dummy1;
+        uint16_t fpus;
+        uint16_t dummy2;
+        uint16_t fptag;
+        uint16_t dummy3;
+        uint32_t ignored[4];
+        long double fpregs[8];
+    } float_env32;
+
+    asm volatile ("fnstenv %0\n" : : "m" (float_env32));
+    float_env32.fpus &= ~0x7f;
+    asm volatile ("fldenv %0\n" : : "m" (float_env32));
+}
+
+/* XXX: display exception bits when supported */
+#define FPUS_EMASK 0x0000
+//#define FPUS_EMASK 0x007f
+
+void test_fcmp(double a, double b)
+{
+    long eflags, fpus;
+
+    fpu_clear_exceptions();
+    asm("fcom %2\n"
+        "fstsw %%ax\n"
+        : "=a" (fpus)
+        : "t" (a), "u" (b));
+    printf("fcom(%f %f)=%04lx\n",
+           a, b, fpus & (0x4500 | FPUS_EMASK));
+    fpu_clear_exceptions();
+    asm("fucom %2\n"
+        "fstsw %%ax\n"
+        : "=a" (fpus)
+        : "t" (a), "u" (b));
+    printf("fucom(%f %f)=%04lx\n",
+           a, b, fpus & (0x4500 | FPUS_EMASK));
+    if (TEST_FCOMI) {
+        /* test f(u)comi instruction */
+        fpu_clear_exceptions();
+        asm("fcomi %3, %2\n"
+            "fstsw %%ax\n"
+            "pushf\n"
+            "pop %0\n"
+            : "=r" (eflags), "=a" (fpus)
+            : "t" (a), "u" (b));
+        printf("fcomi(%f %f)=%04lx %02lx\n",
+               a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C));
+        fpu_clear_exceptions();
+        asm("fucomi %3, %2\n"
+            "fstsw %%ax\n"
+            "pushf\n"
+            "pop %0\n"
+            : "=r" (eflags), "=a" (fpus)
+            : "t" (a), "u" (b));
+        printf("fucomi(%f %f)=%04lx %02lx\n",
+               a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C));
+    }
+    fpu_clear_exceptions();
+    asm volatile("fxam\n"
+                 "fstsw %%ax\n"
+                 : "=a" (fpus)
+                 : "t" (a));
+    printf("fxam(%f)=%04lx\n", a, fpus & 0x4700);
+    fpu_clear_exceptions();
+}
+
+void test_fcvt(double a)
+{
+    float fa;
+    long double la;
+    int16_t fpuc;
+    int i;
+    int64_t lla;
+    int ia;
+    int16_t wa;
+    double ra;
+
+    fa = a;
+    la = a;
+    printf("(float)%f = %f\n", a, fa);
+    printf("(long double)%f = %Lf\n", a, la);
+    printf("a=" FMT64X "\n", *(uint64_t *)&a);
+    printf("la=" FMT64X " %04x\n", *(uint64_t *)&la,
+           *(unsigned short *)((char *)(&la) + 8));
+
+    /* test all roundings */
+    asm volatile ("fstcw %0" : "=m" (fpuc));
+    for(i=0;i<4;i++) {
+        uint16_t val16;
+        val16 = (fpuc & ~0x0c00) | (i << 10);
+        asm volatile ("fldcw %0" : : "m" (val16));
+        asm volatile ("fist %0" : "=m" (wa) : "t" (a));
+        asm volatile ("fistl %0" : "=m" (ia) : "t" (a));
+        asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st");
+        asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a));
+        asm volatile ("fldcw %0" : : "m" (fpuc));
+        printf("(short)a = %d\n", wa);
+        printf("(int)a = %d\n", ia);
+        printf("(int64_t)a = " FMT64X "\n", lla);
+        printf("rint(a) = %f\n", ra);
+    }
+}
+
+#define TEST(N) \
+    asm("fld" #N : "=t" (a)); \
+    printf("fld" #N "= %f\n", a);
+
+void test_fconst(void)
+{
+    double a;
+    TEST(1);
+    TEST(l2t);
+    TEST(l2e);
+    TEST(pi);
+    TEST(lg2);
+    TEST(ln2);
+    TEST(z);
+}
+
+void test_fbcd(double a)
+{
+    unsigned short bcd[5];
+    double b;
+
+    asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st");
+    asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
+    printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n",
+           a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);
+}
+
+#define TEST_ENV(env, save, restore)\
+{\
+    memset((env), 0xaa, sizeof(*(env)));\
+    for(i=0;i<5;i++)\
+        asm volatile ("fldl %0" : : "m" (dtab[i]));\
+    asm volatile (save " %0\n" : : "m" (*(env)));\
+    asm volatile (restore " %0\n": : "m" (*(env)));\
+    for(i=0;i<5;i++)\
+        asm volatile ("fstpl %0" : "=m" (rtab[i]));\
+    for(i=0;i<5;i++)\
+        printf("res[%d]=%f\n", i, rtab[i]);\
+    printf("fpuc=%04x fpus=%04x fptag=%04x\n",\
+           (env)->fpuc,\
+           (env)->fpus & 0xff00,\
+           (env)->fptag);\
+}
+
+void test_fenv(void)
+{
+    struct QEMU_PACKED {
+        uint16_t fpuc;
+        uint16_t dummy1;
+        uint16_t fpus;
+        uint16_t dummy2;
+        uint16_t fptag;
+        uint16_t dummy3;
+        uint32_t ignored[4];
+        long double fpregs[8];
+    } float_env32;
+    struct QEMU_PACKED {
+        uint16_t fpuc;
+        uint16_t fpus;
+        uint16_t fptag;
+        uint16_t ignored[4];
+        long double fpregs[8];
+    } float_env16;
+    double dtab[8];
+    double rtab[8];
+    int i;
+
+    for(i=0;i<8;i++)
+        dtab[i] = i + 1;
+
+    TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv");
+    TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor");
+    TEST_ENV(&float_env32, "fnstenv", "fldenv");
+    TEST_ENV(&float_env32, "fnsave", "frstor");
+
+    /* test for ffree */
+    for(i=0;i<5;i++)
+        asm volatile ("fldl %0" : : "m" (dtab[i]));
+    asm volatile("ffree %st(2)");
+    asm volatile ("fnstenv %0\n" : : "m" (float_env32));
+    asm volatile ("fninit");
+    printf("fptag=%04x\n", float_env32.fptag);
+}
+
+
+#define TEST_FCMOV(a, b, eflags, CC)\
+{\
+    double res;\
+    asm("push %3\n"\
+        "popf\n"\
+        "fcmov" CC " %2, %0\n"\
+        : "=t" (res)\
+        : "0" (a), "u" (b), "g" (eflags));\
+    printf("fcmov%s eflags=0x%04lx-> %f\n", \
+           CC, (long)eflags, res);\
+}
+
+void test_fcmov(void)
+{
+    double a, b;
+    long eflags, i;
+
+    a = 1.0;
+    b = 2.0;
+    for(i = 0; i < 4; i++) {
+        eflags = 0;
+        if (i & 1)
+            eflags |= CC_C;
+        if (i & 2)
+            eflags |= CC_Z;
+        TEST_FCMOV(a, b, eflags, "b");
+        TEST_FCMOV(a, b, eflags, "e");
+        TEST_FCMOV(a, b, eflags, "be");
+        TEST_FCMOV(a, b, eflags, "nb");
+        TEST_FCMOV(a, b, eflags, "ne");
+        TEST_FCMOV(a, b, eflags, "nbe");
+    }
+    TEST_FCMOV(a, b, 0, "u");
+    TEST_FCMOV(a, b, CC_P, "u");
+    TEST_FCMOV(a, b, 0, "nu");
+    TEST_FCMOV(a, b, CC_P, "nu");
+}
+
+void test_floats(void)
+{
+    test_fops(2, 3);
+    test_fops(1.4, -5);
+    test_fcmp(2, -1);
+    test_fcmp(2, 2);
+    test_fcmp(2, 3);
+    test_fcmp(2, q_nan.d);
+    test_fcmp(q_nan.d, -1);
+    test_fcmp(-1.0/0.0, -1);
+    test_fcmp(1.0/0.0, -1);
+    test_fcvt(0.5);
+    test_fcvt(-0.5);
+    test_fcvt(1.0/7.0);
+    test_fcvt(-1.0/9.0);
+    test_fcvt(32768);
+    test_fcvt(-1e20);
+    test_fcvt(-1.0/0.0);
+    test_fcvt(1.0/0.0);
+    test_fcvt(q_nan.d);
+    test_fconst();
+    test_fbcd(1234567890123456.0);
+    test_fbcd(-123451234567890.0);
+    test_fenv();
+    if (TEST_CMOV) {
+        test_fcmov();
+    }
+}
+
+/**********************************************/
+#if !defined(__x86_64__)
+
+#define TEST_BCD(op, op0, cc_in, cc_mask)\
+{\
+    int res, flags;\
+    res = op0;\
+    flags = cc_in;\
+    asm ("push %3\n\t"\
+         "popf\n\t"\
+         #op "\n\t"\
+         "pushf\n\t"\
+         "pop %1\n\t"\
+        : "=a" (res), "=g" (flags)\
+        : "0" (res), "1" (flags));\
+    printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\
+           #op, op0, res, cc_in, flags & cc_mask);\
+}
+
+void test_bcd(void)
+{
+    TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+
+    TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+    TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+
+    TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A));
+    TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A));
+    TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A));
+    TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A));
+    TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A));
+    TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A));
+    TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A));
+    TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A));
+
+    TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A));
+    TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A));
+    TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A));
+    TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A));
+    TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A));
+    TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A));
+    TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A));
+    TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A));
+
+    TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
+    TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
+}
+#endif
+
+#define TEST_XCHG(op, size, opconst)\
+{\
+    long op0, op1;\
+    op0 = i2l(0x12345678);\
+    op1 = i2l(0xfbca7654);\
+    asm(#op " %" size "0, %" size "1" \
+        : "=q" (op0), opconst (op1) \
+        : "0" (op0));\
+    printf("%-10s A=" FMTLX " B=" FMTLX "\n",\
+           #op, op0, op1);\
+}
+
+#define TEST_CMPXCHG(op, size, opconst, eax)\
+{\
+    long op0, op1, op2;\
+    op0 = i2l(0x12345678);\
+    op1 = i2l(0xfbca7654);\
+    op2 = i2l(eax);\
+    asm(#op " %" size "0, %" size "1" \
+        : "=q" (op0), opconst (op1) \
+        : "0" (op0), "a" (op2));\
+    printf("%-10s EAX=" FMTLX " A=" FMTLX " C=" FMTLX "\n",\
+           #op, op2, op0, op1);\
+}
+
+void test_xchg(void)
+{
+#if defined(__x86_64__)
+    TEST_XCHG(xchgq, "", "+q");
+#endif
+    TEST_XCHG(xchgl, "k", "+q");
+    TEST_XCHG(xchgw, "w", "+q");
+    TEST_XCHG(xchgb, "b", "+q");
+
+#if defined(__x86_64__)
+    TEST_XCHG(xchgq, "", "=m");
+#endif
+    TEST_XCHG(xchgl, "k", "+m");
+    TEST_XCHG(xchgw, "w", "+m");
+    TEST_XCHG(xchgb, "b", "+m");
+
+#if defined(__x86_64__)
+    TEST_XCHG(xaddq, "", "+q");
+#endif
+    TEST_XCHG(xaddl, "k", "+q");
+    TEST_XCHG(xaddw, "w", "+q");
+    TEST_XCHG(xaddb, "b", "+q");
+
+    {
+        int res;
+        res = 0x12345678;
+        asm("xaddl %1, %0" : "=r" (res) : "0" (res));
+        printf("xaddl same res=%08x\n", res);
+    }
+
+#if defined(__x86_64__)
+    TEST_XCHG(xaddq, "", "+m");
+#endif
+    TEST_XCHG(xaddl, "k", "+m");
+    TEST_XCHG(xaddw, "w", "+m");
+    TEST_XCHG(xaddb, "b", "+m");
+
+#if defined(__x86_64__)
+    TEST_CMPXCHG(cmpxchgq, "", "+q", 0xfbca7654);
+#endif
+    TEST_CMPXCHG(cmpxchgl, "k", "+q", 0xfbca7654);
+    TEST_CMPXCHG(cmpxchgw, "w", "+q", 0xfbca7654);
+    TEST_CMPXCHG(cmpxchgb, "b", "+q", 0xfbca7654);
+
+#if defined(__x86_64__)
+    TEST_CMPXCHG(cmpxchgq, "", "+q", 0xfffefdfc);
+#endif
+    TEST_CMPXCHG(cmpxchgl, "k", "+q", 0xfffefdfc);
+    TEST_CMPXCHG(cmpxchgw, "w", "+q", 0xfffefdfc);
+    TEST_CMPXCHG(cmpxchgb, "b", "+q", 0xfffefdfc);
+
+#if defined(__x86_64__)
+    TEST_CMPXCHG(cmpxchgq, "", "+m", 0xfbca7654);
+#endif
+    TEST_CMPXCHG(cmpxchgl, "k", "+m", 0xfbca7654);
+    TEST_CMPXCHG(cmpxchgw, "w", "+m", 0xfbca7654);
+    TEST_CMPXCHG(cmpxchgb, "b", "+m", 0xfbca7654);
+
+#if defined(__x86_64__)
+    TEST_CMPXCHG(cmpxchgq, "", "+m", 0xfffefdfc);
+#endif
+    TEST_CMPXCHG(cmpxchgl, "k", "+m", 0xfffefdfc);
+    TEST_CMPXCHG(cmpxchgw, "w", "+m", 0xfffefdfc);
+    TEST_CMPXCHG(cmpxchgb, "b", "+m", 0xfffefdfc);
+
+    {
+        uint64_t op0, op1, op2;
+        long eax, edx;
+        long i, eflags;
+
+        for(i = 0; i < 2; i++) {
+            op0 = 0x123456789abcdLL;
+            eax = i2l(op0 & 0xffffffff);
+            edx = i2l(op0 >> 32);
+            if (i == 0)
+                op1 = 0xfbca765423456LL;
+            else
+                op1 = op0;
+            op2 = 0x6532432432434LL;
+            asm("cmpxchg8b %2\n"
+                "pushf\n"
+                "pop %3\n"
+                : "=a" (eax), "=d" (edx), "=m" (op1), "=g" (eflags)
+                : "0" (eax), "1" (edx), "m" (op1), "b" ((int)op2), "c" ((int)(op2 >> 32)));
+            printf("cmpxchg8b: eax=" FMTLX " edx=" FMTLX " op1=" FMT64X " CC=%02lx\n",
+                   eax, edx, op1, eflags & CC_Z);
+        }
+    }
+}
+
+#ifdef TEST_SEGS
+/**********************************************/
+/* segmentation tests */
+
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <asm/ldt.h>
+#include <linux/version.h>
+
+static inline int modify_ldt(int func, void * ptr, unsigned long bytecount)
+{
+    return syscall(__NR_modify_ldt, func, ptr, bytecount);
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
+#define modify_ldt_ldt_s user_desc
+#endif
+
+#define MK_SEL(n) (((n) << 3) | 7)
+
+uint8_t seg_data1[4096];
+uint8_t seg_data2[4096];
+
+#define TEST_LR(op, size, seg, mask)\
+{\
+    int res, res2;\
+    uint16_t mseg = seg;\
+    res = 0x12345678;\
+    asm (op " %" size "2, %" size "0\n" \
+         "movl $0, %1\n"\
+         "jnz 1f\n"\
+         "movl $1, %1\n"\
+         "1:\n"\
+         : "=r" (res), "=r" (res2) : "m" (mseg), "0" (res));\
+    printf(op ": Z=%d %08x\n", res2, res & ~(mask));\
+}
+
+#define TEST_ARPL(op, size, op1, op2)\
+{\
+    long a, b, c;                               \
+    a = (op1);                                  \
+    b = (op2);                                  \
+    asm volatile(op " %" size "3, %" size "0\n"\
+                 "movl $0,%1\n"\
+                 "jnz 1f\n"\
+                 "movl $1,%1\n"\
+                 "1:\n"\
+                 : "=r" (a), "=r" (c) : "0" (a), "r" (b));    \
+    printf(op size " A=" FMTLX " B=" FMTLX " R=" FMTLX " z=%ld\n",\
+           (long)(op1), (long)(op2), a, c);\
+}
+
+/* NOTE: we use Linux modify_ldt syscall */
+void test_segs(void)
+{
+    struct modify_ldt_ldt_s ldt;
+    long long ldt_table[3];
+    int res, res2;
+    char tmp;
+    struct {
+        uint32_t offset;
+        uint16_t seg;
+    } QEMU_PACKED segoff;
+
+    ldt.entry_number = 1;
+    ldt.base_addr = (unsigned long)&seg_data1;
+    ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
+    ldt.seg_32bit = 1;
+    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
+    ldt.read_exec_only = 0;
+    ldt.limit_in_pages = 1;
+    ldt.seg_not_present = 0;
+    ldt.useable = 1;
+    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
+
+    ldt.entry_number = 2;
+    ldt.base_addr = (unsigned long)&seg_data2;
+    ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12;
+    ldt.seg_32bit = 1;
+    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
+    ldt.read_exec_only = 0;
+    ldt.limit_in_pages = 1;
+    ldt.seg_not_present = 0;
+    ldt.useable = 1;
+    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
+
+    modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */
+#if 0
+    {
+        int i;
+        for(i=0;i<3;i++)
+            printf("%d: %016Lx\n", i, ldt_table[i]);
+    }
+#endif
+    /* do some tests with fs or gs */
+    asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
+
+    seg_data1[1] = 0xaa;
+    seg_data2[1] = 0x55;
+
+    asm volatile ("fs movzbl 0x1, %0" : "=r" (res));
+    printf("FS[1] = %02x\n", res);
+
+    asm volatile ("pushl %%gs\n"
+                  "movl %1, %%gs\n"
+                  "gs movzbl 0x1, %0\n"
+                  "popl %%gs\n"
+                  : "=r" (res)
+                  : "r" (MK_SEL(2)));
+    printf("GS[1] = %02x\n", res);
+
+    /* tests with ds/ss (implicit segment case) */
+    tmp = 0xa5;
+    asm volatile ("pushl %%ebp\n\t"
+                  "pushl %%ds\n\t"
+                  "movl %2, %%ds\n\t"
+                  "movl %3, %%ebp\n\t"
+                  "movzbl 0x1, %0\n\t"
+                  "movzbl (%%ebp), %1\n\t"
+                  "popl %%ds\n\t"
+                  "popl %%ebp\n\t"
+                  : "=r" (res), "=r" (res2)
+                  : "r" (MK_SEL(1)), "r" (&tmp));
+    printf("DS[1] = %02x\n", res);
+    printf("SS[tmp] = %02x\n", res2);
+
+    segoff.seg = MK_SEL(2);
+    segoff.offset = 0xabcdef12;
+    asm volatile("lfs %2, %0\n\t"
+                 "movl %%fs, %1\n\t"
+                 : "=r" (res), "=g" (res2)
+                 : "m" (segoff));
+    printf("FS:reg = %04x:%08x\n", res2, res);
+
+    TEST_LR("larw", "w", MK_SEL(2), 0x0100);
+    TEST_LR("larl", "", MK_SEL(2), 0x0100);
+    TEST_LR("lslw", "w", MK_SEL(2), 0);
+    TEST_LR("lsll", "", MK_SEL(2), 0);
+
+    TEST_LR("larw", "w", 0xfff8, 0);
+    TEST_LR("larl", "", 0xfff8, 0);
+    TEST_LR("lslw", "w", 0xfff8, 0);
+    TEST_LR("lsll", "", 0xfff8, 0);
+
+    TEST_ARPL("arpl", "w", 0x12345678 | 3, 0x762123c | 1);
+    TEST_ARPL("arpl", "w", 0x12345678 | 1, 0x762123c | 3);
+    TEST_ARPL("arpl", "w", 0x12345678 | 1, 0x762123c | 1);
+}
+
+/* 16 bit code test */
+extern char code16_start, code16_end;
+extern char code16_func1;
+extern char code16_func2;
+extern char code16_func3;
+
+void test_code16(void)
+{
+    struct modify_ldt_ldt_s ldt;
+    int res, res2;
+
+    /* build a code segment */
+    ldt.entry_number = 1;
+    ldt.base_addr = (unsigned long)&code16_start;
+    ldt.limit = &code16_end - &code16_start;
+    ldt.seg_32bit = 0;
+    ldt.contents = MODIFY_LDT_CONTENTS_CODE;
+    ldt.read_exec_only = 0;
+    ldt.limit_in_pages = 0;
+    ldt.seg_not_present = 0;
+    ldt.useable = 1;
+    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
+
+    /* call the first function */
+    asm volatile ("lcall %1, %2"
+                  : "=a" (res)
+                  : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc");
+    printf("func1() = 0x%08x\n", res);
+    asm volatile ("lcall %2, %3"
+                  : "=a" (res), "=c" (res2)
+                  : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc");
+    printf("func2() = 0x%08x spdec=%d\n", res, res2);
+    asm volatile ("lcall %1, %2"
+                  : "=a" (res)
+                  : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc");
+    printf("func3() = 0x%08x\n", res);
+}
+#endif
+
+#if defined(__x86_64__)
+asm(".globl func_lret\n"
+    "func_lret:\n"
+    "movl $0x87654641, %eax\n"
+    "lretq\n");
+#else
+asm(".globl func_lret\n"
+    "func_lret:\n"
+    "movl $0x87654321, %eax\n"
+    "lret\n"
+
+    ".globl func_iret\n"
+    "func_iret:\n"
+    "movl $0xabcd4321, %eax\n"
+    "iret\n");
+#endif
+
+extern char func_lret;
+extern char func_iret;
+
+void test_misc(void)
+{
+    char table[256];
+    long res, i;
+
+    for(i=0;i<256;i++) table[i] = 256 - i;
+    res = 0x12345678;
+    asm ("xlat" : "=a" (res) : "b" (table), "0" (res));
+    printf("xlat: EAX=" FMTLX "\n", res);
+
+#if defined(__x86_64__)
+#if 0
+    {
+        /* XXX: see if Intel Core2 and AMD64 behavior really
+           differ. Here we implemented the Intel way which is not
+           compatible yet with QEMU. */
+        static struct QEMU_PACKED {
+            uint64_t offset;
+            uint16_t seg;
+        } desc;
+        long cs_sel;
+
+        asm volatile ("mov %%cs, %0" : "=r" (cs_sel));
+
+        asm volatile ("push %1\n"
+                      "call func_lret\n"
+                      : "=a" (res)
+                      : "r" (cs_sel) : "memory", "cc");
+        printf("func_lret=" FMTLX "\n", res);
+
+        desc.offset = (long)&func_lret;
+        desc.seg = cs_sel;
+
+        asm volatile ("xor %%rax, %%rax\n"
+                      "rex64 lcall *(%%rcx)\n"
+                      : "=a" (res)
+                      : "c" (&desc)
+                      : "memory", "cc");
+        printf("func_lret2=" FMTLX "\n", res);
+
+        asm volatile ("push %2\n"
+                      "mov $ 1f, %%rax\n"
+                      "push %%rax\n"
+                      "rex64 ljmp *(%%rcx)\n"
+                      "1:\n"
+                      : "=a" (res)
+                      : "c" (&desc), "b" (cs_sel)
+                      : "memory", "cc");
+        printf("func_lret3=" FMTLX "\n", res);
+    }
+#endif
+#else
+    asm volatile ("push %%cs ; call %1"
+                  : "=a" (res)
+                  : "m" (func_lret): "memory", "cc");
+    printf("func_lret=" FMTLX "\n", res);
+
+    asm volatile ("pushf ; push %%cs ; call %1"
+                  : "=a" (res)
+                  : "m" (func_iret): "memory", "cc");
+    printf("func_iret=" FMTLX "\n", res);
+#endif
+
+#if defined(__x86_64__)
+    /* specific popl test */
+    asm volatile ("push $12345432 ; push $0x9abcdef ; pop (%%rsp) ; pop %0"
+                  : "=g" (res));
+    printf("popl esp=" FMTLX "\n", res);
+#else
+    /* specific popl test */
+    asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popl (%%esp) ; popl %0"
+                  : "=g" (res));
+    printf("popl esp=" FMTLX "\n", res);
+
+    /* specific popw test */
+    asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popw (%%esp) ; addl $2, %%esp ; popl %0"
+                  : "=g" (res));
+    printf("popw esp=" FMTLX "\n", res);
+#endif
+}
+
+uint8_t str_buffer[4096];
+
+#define TEST_STRING1(OP, size, DF, REP)\
+{\
+    long esi, edi, eax, ecx, eflags;\
+\
+    esi = (long)(str_buffer + sizeof(str_buffer) / 2);\
+    edi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\
+    eax = i2l(0x12345678);\
+    ecx = 17;\
+\
+    asm volatile ("push $0\n\t"\
+                  "popf\n\t"\
+                  DF "\n\t"\
+                  REP #OP size "\n\t"\
+                  "cld\n\t"\
+                  "pushf\n\t"\
+                  "pop %4\n\t"\
+                  : "=S" (esi), "=D" (edi), "=a" (eax), "=c" (ecx), "=g" (eflags)\
+                  : "0" (esi), "1" (edi), "2" (eax), "3" (ecx));\
+    printf("%-10s ESI=" FMTLX " EDI=" FMTLX " EAX=" FMTLX " ECX=" FMTLX " EFL=%04x\n",\
+           REP #OP size, esi, edi, eax, ecx,\
+           (int)(eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)));\
+}
+
+#define TEST_STRING(OP, REP)\
+    TEST_STRING1(OP, "b", "", REP);\
+    TEST_STRING1(OP, "w", "", REP);\
+    TEST_STRING1(OP, "l", "", REP);\
+    X86_64_ONLY(TEST_STRING1(OP, "q", "", REP));\
+    TEST_STRING1(OP, "b", "std", REP);\
+    TEST_STRING1(OP, "w", "std", REP);\
+    TEST_STRING1(OP, "l", "std", REP);\
+    X86_64_ONLY(TEST_STRING1(OP, "q", "std", REP))
+
+void test_string(void)
+{
+    int i;
+    for(i = 0;i < sizeof(str_buffer); i++)
+        str_buffer[i] = i + 0x56;
+   TEST_STRING(stos, "");
+   TEST_STRING(stos, "rep ");
+   TEST_STRING(lods, ""); /* to verify stos */
+   TEST_STRING(lods, "rep ");
+   TEST_STRING(movs, "");
+   TEST_STRING(movs, "rep ");
+   TEST_STRING(lods, ""); /* to verify stos */
+
+   /* XXX: better tests */
+   TEST_STRING(scas, "");
+   TEST_STRING(scas, "repz ");
+   TEST_STRING(scas, "repnz ");
+   TEST_STRING(cmps, "");
+   TEST_STRING(cmps, "repz ");
+   TEST_STRING(cmps, "repnz ");
+}
+
+#ifdef TEST_VM86
+/* VM86 test */
+
+static inline void set_bit(uint8_t *a, unsigned int bit)
+{
+    a[bit / 8] |= (1 << (bit % 8));
+}
+
+static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
+{
+    return (uint8_t *)((seg << 4) + (reg & 0xffff));
+}
+
+static inline void pushw(struct vm86_regs *r, int val)
+{
+    r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
+    *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
+}
+
+static inline int vm86(int func, struct vm86plus_struct *v86)
+{
+    return syscall(__NR_vm86, func, v86);
+}
+
+extern char vm86_code_start;
+extern char vm86_code_end;
+
+#define VM86_CODE_CS 0x100
+#define VM86_CODE_IP 0x100
+
+void test_vm86(void)
+{
+    struct vm86plus_struct ctx;
+    struct vm86_regs *r;
+    uint8_t *vm86_mem;
+    int seg, ret;
+
+    vm86_mem = mmap((void *)0x00000000, 0x110000,
+                    PROT_WRITE | PROT_READ | PROT_EXEC,
+                    MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
+    if (vm86_mem == MAP_FAILED) {
+        printf("ERROR: could not map vm86 memory");
+        return;
+    }
+    memset(&ctx, 0, sizeof(ctx));
+
+    /* init basic registers */
+    r = &ctx.regs;
+    r->eip = VM86_CODE_IP;
+    r->esp = 0xfffe;
+    seg = VM86_CODE_CS;
+    r->cs = seg;
+    r->ss = seg;
+    r->ds = seg;
+    r->es = seg;
+    r->fs = seg;
+    r->gs = seg;
+    r->eflags = VIF_MASK;
+
+    /* move code to proper address. We use the same layout as a .com
+       dos program. */
+    memcpy(vm86_mem + (VM86_CODE_CS << 4) + VM86_CODE_IP,
+           &vm86_code_start, &vm86_code_end - &vm86_code_start);
+
+    /* mark int 0x21 as being emulated */
+    set_bit((uint8_t *)&ctx.int_revectored, 0x21);
+
+    for(;;) {
+        ret = vm86(VM86_ENTER, &ctx);
+        switch(VM86_TYPE(ret)) {
+        case VM86_INTx:
+            {
+                int int_num, ah, v;
+
+                int_num = VM86_ARG(ret);
+                if (int_num != 0x21)
+                    goto unknown_int;
+                ah = (r->eax >> 8) & 0xff;
+                switch(ah) {
+                case 0x00: /* exit */
+                    goto the_end;
+                case 0x02: /* write char */
+                    {
+                        uint8_t c = r->edx;
+                        putchar(c);
+                    }
+                    break;
+                case 0x09: /* write string */
+                    {
+                        uint8_t c, *ptr;
+                        ptr = seg_to_linear(r->ds, r->edx);
+                        for(;;) {
+                            c = *ptr++;
+                            if (c == '$')
+                                break;
+                            putchar(c);
+                        }
+                        r->eax = (r->eax & ~0xff) | '$';
+                    }
+                    break;
+                case 0xff: /* extension: write eflags number in edx */
+                    v = (int)r->edx;
+#ifndef LINUX_VM86_IOPL_FIX
+                    v &= ~0x3000;
+#endif
+                    printf("%08x\n", v);
+                    break;
+                default:
+                unknown_int:
+                    printf("unsupported int 0x%02x\n", int_num);
+                    goto the_end;
+                }
+            }
+            break;
+        case VM86_SIGNAL:
+            /* a signal came, we just ignore that */
+            break;
+        case VM86_STI:
+            break;
+        default:
+            printf("ERROR: unhandled vm86 return code (0x%x)\n", ret);
+            goto the_end;
+        }
+    }
+ the_end:
+    printf("VM86 end\n");
+    munmap(vm86_mem, 0x110000);
+}
+#endif
+
+/* exception tests */
+#if defined(__i386__) && !defined(REG_EAX)
+#define REG_EAX EAX
+#define REG_EBX EBX
+#define REG_ECX ECX
+#define REG_EDX EDX
+#define REG_ESI ESI
+#define REG_EDI EDI
+#define REG_EBP EBP
+#define REG_ESP ESP
+#define REG_EIP EIP
+#define REG_EFL EFL
+#define REG_TRAPNO TRAPNO
+#define REG_ERR ERR
+#endif
+
+#if defined(__x86_64__)
+#define REG_EIP REG_RIP
+#endif
+
+jmp_buf jmp_env;
+int v1;
+int tab[2];
+
+void sig_handler(int sig, siginfo_t *info, void *puc)
+{
+    struct ucontext *uc = puc;
+
+    printf("si_signo=%d si_errno=%d si_code=%d",
+           info->si_signo, info->si_errno, info->si_code);
+    printf(" si_addr=0x%08lx",
+           (unsigned long)info->si_addr);
+    printf("\n");
+
+    printf("trapno=" FMTLX " err=" FMTLX,
+           (long)uc->uc_mcontext.gregs[REG_TRAPNO],
+           (long)uc->uc_mcontext.gregs[REG_ERR]);
+    printf(" EIP=" FMTLX, (long)uc->uc_mcontext.gregs[REG_EIP]);
+    printf("\n");
+    longjmp(jmp_env, 1);
+}
+
+void test_exceptions(void)
+{
+    struct sigaction act;
+    volatile int val;
+
+    act.sa_sigaction = sig_handler;
+    sigemptyset(&act.sa_mask);
+    act.sa_flags = SA_SIGINFO | SA_NODEFER;
+    sigaction(SIGFPE, &act, NULL);
+    sigaction(SIGILL, &act, NULL);
+    sigaction(SIGSEGV, &act, NULL);
+    sigaction(SIGBUS, &act, NULL);
+    sigaction(SIGTRAP, &act, NULL);
+
+    /* test division by zero reporting */
+    printf("DIVZ exception:\n");
+    if (setjmp(jmp_env) == 0) {
+        /* now divide by zero */
+        v1 = 0;
+        v1 = 2 / v1;
+    }
+
+#if !defined(__x86_64__)
+    printf("BOUND exception:\n");
+    if (setjmp(jmp_env) == 0) {
+        /* bound exception */
+        tab[0] = 1;
+        tab[1] = 10;
+        asm volatile ("bound %0, %1" : : "r" (11), "m" (tab[0]));
+    }
+#endif
+
+#ifdef TEST_SEGS
+    printf("segment exceptions:\n");
+    if (setjmp(jmp_env) == 0) {
+        /* load an invalid segment */
+        asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 1));
+    }
+    if (setjmp(jmp_env) == 0) {
+        /* null data segment is valid */
+        asm volatile ("movl %0, %%fs" : : "r" (3));
+        /* null stack segment */
+        asm volatile ("movl %0, %%ss" : : "r" (3));
+    }
+
+    {
+        struct modify_ldt_ldt_s ldt;
+        ldt.entry_number = 1;
+        ldt.base_addr = (unsigned long)&seg_data1;
+        ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
+        ldt.seg_32bit = 1;
+        ldt.contents = MODIFY_LDT_CONTENTS_DATA;
+        ldt.read_exec_only = 0;
+        ldt.limit_in_pages = 1;
+        ldt.seg_not_present = 1;
+        ldt.useable = 1;
+        modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
+
+        if (setjmp(jmp_env) == 0) {
+            /* segment not present */
+            asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
+        }
+    }
+#endif
+
+    /* test SEGV reporting */
+    printf("PF exception:\n");
+    if (setjmp(jmp_env) == 0) {
+        val = 1;
+        /* we add a nop to test a weird PC retrieval case */
+        asm volatile ("nop");
+        /* now store in an invalid address */
+        *(char *)0x1234 = 1;
+    }
+
+    /* test SEGV reporting */
+    printf("PF exception:\n");
+    if (setjmp(jmp_env) == 0) {
+        val = 1;
+        /* read from an invalid address */
+        v1 = *(char *)0x1234;
+    }
+
+    /* test illegal instruction reporting */
+    printf("UD2 exception:\n");
+    if (setjmp(jmp_env) == 0) {
+        /* now execute an invalid instruction */
+        asm volatile("ud2");
+    }
+    printf("lock nop exception:\n");
+    if (setjmp(jmp_env) == 0) {
+        /* now execute an invalid instruction */
+        asm volatile("lock nop");
+    }
+
+    printf("INT exception:\n");
+    if (setjmp(jmp_env) == 0) {
+        asm volatile ("int $0xfd");
+    }
+    if (setjmp(jmp_env) == 0) {
+        asm volatile ("int $0x01");
+    }
+    if (setjmp(jmp_env) == 0) {
+        asm volatile (".byte 0xcd, 0x03");
+    }
+    if (setjmp(jmp_env) == 0) {
+        asm volatile ("int $0x04");
+    }
+    if (setjmp(jmp_env) == 0) {
+        asm volatile ("int $0x05");
+    }
+
+    printf("INT3 exception:\n");
+    if (setjmp(jmp_env) == 0) {
+        asm volatile ("int3");
+    }
+
+    printf("CLI exception:\n");
+    if (setjmp(jmp_env) == 0) {
+        asm volatile ("cli");
+    }
+
+    printf("STI exception:\n");
+    if (setjmp(jmp_env) == 0) {
+        asm volatile ("cli");
+    }
+
+#if !defined(__x86_64__)
+    printf("INTO exception:\n");
+    if (setjmp(jmp_env) == 0) {
+        /* overflow exception */
+        asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff));
+    }
+#endif
+
+    printf("OUTB exception:\n");
+    if (setjmp(jmp_env) == 0) {
+        asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0));
+    }
+
+    printf("INB exception:\n");
+    if (setjmp(jmp_env) == 0) {
+        asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321));
+    }
+
+    printf("REP OUTSB exception:\n");
+    if (setjmp(jmp_env) == 0) {
+        asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1));
+    }
+
+    printf("REP INSB exception:\n");
+    if (setjmp(jmp_env) == 0) {
+        asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1));
+    }
+
+    printf("HLT exception:\n");
+    if (setjmp(jmp_env) == 0) {
+        asm volatile ("hlt");
+    }
+
+    printf("single step exception:\n");
+    val = 0;
+    if (setjmp(jmp_env) == 0) {
+        asm volatile ("pushf\n"
+                      "orl $0x00100, (%%esp)\n"
+                      "popf\n"
+                      "movl $0xabcd, %0\n"
+                      "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory");
+    }
+    printf("val=0x%x\n", val);
+}
+
+#if !defined(__x86_64__)
+/* specific precise single step test */
+void sig_trap_handler(int sig, siginfo_t *info, void *puc)
+{
+    struct ucontext *uc = puc;
+    printf("EIP=" FMTLX "\n", (long)uc->uc_mcontext.gregs[REG_EIP]);
+}
+
+const uint8_t sstep_buf1[4] = { 1, 2, 3, 4};
+uint8_t sstep_buf2[4];
+
+void test_single_step(void)
+{
+    struct sigaction act;
+    volatile int val;
+    int i;
+
+    val = 0;
+    act.sa_sigaction = sig_trap_handler;
+    sigemptyset(&act.sa_mask);
+    act.sa_flags = SA_SIGINFO;
+    sigaction(SIGTRAP, &act, NULL);
+    asm volatile ("pushf\n"
+                  "orl $0x00100, (%%esp)\n"
+                  "popf\n"
+                  "movl $0xabcd, %0\n"
+
+                  /* jmp test */
+                  "movl $3, %%ecx\n"
+                  "1:\n"
+                  "addl $1, %0\n"
+                  "decl %%ecx\n"
+                  "jnz 1b\n"
+
+                  /* movsb: the single step should stop at each movsb iteration */
+                  "movl $sstep_buf1, %%esi\n"
+                  "movl $sstep_buf2, %%edi\n"
+                  "movl $0, %%ecx\n"
+                  "rep movsb\n"
+                  "movl $3, %%ecx\n"
+                  "rep movsb\n"
+                  "movl $1, %%ecx\n"
+                  "rep movsb\n"
+
+                  /* cmpsb: the single step should stop at each cmpsb iteration */
+                  "movl $sstep_buf1, %%esi\n"
+                  "movl $sstep_buf2, %%edi\n"
+                  "movl $0, %%ecx\n"
+                  "rep cmpsb\n"
+                  "movl $4, %%ecx\n"
+                  "rep cmpsb\n"
+
+                  /* getpid() syscall: single step should skip one
+                     instruction */
+                  "movl $20, %%eax\n"
+                  "int $0x80\n"
+                  "movl $0, %%eax\n"
+
+                  /* when modifying SS, trace is not done on the next
+                     instruction */
+                  "movl %%ss, %%ecx\n"
+                  "movl %%ecx, %%ss\n"
+                  "addl $1, %0\n"
+                  "movl $1, %%eax\n"
+                  "movl %%ecx, %%ss\n"
+                  "jmp 1f\n"
+                  "addl $1, %0\n"
+                  "1:\n"
+                  "movl $1, %%eax\n"
+                  "pushl %%ecx\n"
+                  "popl %%ss\n"
+                  "addl $1, %0\n"
+                  "movl $1, %%eax\n"
+
+                  "pushf\n"
+                  "andl $~0x00100, (%%esp)\n"
+                  "popf\n"
+                  : "=m" (val)
+                  :
+                  : "cc", "memory", "eax", "ecx", "esi", "edi");
+    printf("val=%d\n", val);
+    for(i = 0; i < 4; i++)
+        printf("sstep_buf2[%d] = %d\n", i, sstep_buf2[i]);
+}
+
+/* self modifying code test */
+uint8_t code[] = {
+    0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */
+    0xc3, /* ret */
+};
+
+asm(".section \".data\"\n"
+    "smc_code2:\n"
+    "movl 4(%esp), %eax\n"
+    "movl %eax, smc_patch_addr2 + 1\n"
+    "nop\n"
+    "nop\n"
+    "nop\n"
+    "nop\n"
+    "nop\n"
+    "nop\n"
+    "nop\n"
+    "nop\n"
+    "smc_patch_addr2:\n"
+    "movl $1, %eax\n"
+    "ret\n"
+    ".previous\n"
+    );
+
+typedef int FuncType(void);
+extern int smc_code2(int);
+void test_self_modifying_code(void)
+{
+    int i;
+    printf("self modifying code:\n");
+    printf("func1 = 0x%x\n", ((FuncType *)code)());
+    for(i = 2; i <= 4; i++) {
+        code[1] = i;
+        printf("func%d = 0x%x\n", i, ((FuncType *)code)());
+    }
+
+    /* more difficult test : the modified code is just after the
+       modifying instruction. It is forbidden in Intel specs, but it
+       is used by old DOS programs */
+    for(i = 2; i <= 4; i++) {
+        printf("smc_code2(%d) = %d\n", i, smc_code2(i));
+    }
+}
+#endif
+
+long enter_stack[4096];
+
+#if defined(__x86_64__)
+#define RSP "%%rsp"
+#define RBP "%%rbp"
+#else
+#define RSP "%%esp"
+#define RBP "%%ebp"
+#endif
+
+#if !defined(__x86_64__)
+/* causes an infinite loop, disable it for now.  */
+#define TEST_ENTER(size, stack_type, level)
+#else
+#define TEST_ENTER(size, stack_type, level)\
+{\
+    long esp_save, esp_val, ebp_val, ebp_save, i;\
+    stack_type *ptr, *stack_end, *stack_ptr;\
+    memset(enter_stack, 0, sizeof(enter_stack));\
+    stack_end = stack_ptr = (stack_type *)(enter_stack + 4096);\
+    ebp_val = (long)stack_ptr;\
+    for(i=1;i<=32;i++)\
+       *--stack_ptr = i;\
+    esp_val = (long)stack_ptr;\
+    asm("mov " RSP ", %[esp_save]\n"\
+        "mov " RBP ", %[ebp_save]\n"\
+        "mov %[esp_val], " RSP "\n"\
+        "mov %[ebp_val], " RBP "\n"\
+        "enter" size " $8, $" #level "\n"\
+        "mov " RSP ", %[esp_val]\n"\
+        "mov " RBP ", %[ebp_val]\n"\
+        "mov %[esp_save], " RSP "\n"\
+        "mov %[ebp_save], " RBP "\n"\
+        : [esp_save] "=r" (esp_save),\
+        [ebp_save] "=r" (ebp_save),\
+        [esp_val] "=r" (esp_val),\
+        [ebp_val] "=r" (ebp_val)\
+        :  "[esp_val]" (esp_val),\
+        "[ebp_val]" (ebp_val));\
+    printf("level=%d:\n", level);\
+    printf("esp_val=" FMTLX "\n", esp_val - (long)stack_end);\
+    printf("ebp_val=" FMTLX "\n", ebp_val - (long)stack_end);\
+    for(ptr = (stack_type *)esp_val; ptr < stack_end; ptr++)\
+        printf(FMTLX "\n", (long)ptr[0]);\
+}
+#endif
+
+static void test_enter(void)
+{
+#if defined(__x86_64__)
+    TEST_ENTER("q", uint64_t, 0);
+    TEST_ENTER("q", uint64_t, 1);
+    TEST_ENTER("q", uint64_t, 2);
+    TEST_ENTER("q", uint64_t, 31);
+#else
+    TEST_ENTER("l", uint32_t, 0);
+    TEST_ENTER("l", uint32_t, 1);
+    TEST_ENTER("l", uint32_t, 2);
+    TEST_ENTER("l", uint32_t, 31);
+#endif
+
+    TEST_ENTER("w", uint16_t, 0);
+    TEST_ENTER("w", uint16_t, 1);
+    TEST_ENTER("w", uint16_t, 2);
+    TEST_ENTER("w", uint16_t, 31);
+}
+
+#ifdef TEST_SSE
+
+typedef int __m64 __attribute__ ((__mode__ (__V2SI__)));
+typedef float __m128 __attribute__ ((__mode__(__V4SF__)));
+
+typedef union {
+    double d[2];
+    float s[4];
+    uint32_t l[4];
+    uint64_t q[2];
+    __m128 dq;
+} XMMReg;
+
+static uint64_t __attribute__((aligned(16))) test_values[4][2] = {
+    { 0x456723c698694873, 0xdc515cff944a58ec },
+    { 0x1f297ccd58bad7ab, 0x41f21efba9e3e146 },
+    { 0x007c62c2085427f8, 0x231be9e8cde7438d },
+    { 0x0f76255a085427f8, 0xc233e9e8c4c9439a },
+};
+
+#define SSE_OP(op)\
+{\
+    asm volatile (#op " %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
+    printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
+           #op,\
+           a.q[1], a.q[0],\
+           b.q[1], b.q[0],\
+           r.q[1], r.q[0]);\
+}
+
+#define SSE_OP2(op)\
+{\
+    int i;\
+    for(i=0;i<2;i++) {\
+    a.q[0] = test_values[2*i][0];\
+    a.q[1] = test_values[2*i][1];\
+    b.q[0] = test_values[2*i+1][0];\
+    b.q[1] = test_values[2*i+1][1];\
+    SSE_OP(op);\
+    }\
+}
+
+#define MMX_OP2(op)\
+{\
+    int i;\
+    for(i=0;i<2;i++) {\
+    a.q[0] = test_values[2*i][0];\
+    b.q[0] = test_values[2*i+1][0];\
+    asm volatile (#op " %2, %0" : "=y" (r.q[0]) : "0" (a.q[0]), "y" (b.q[0]));\
+    printf("%-9s: a=" FMT64X " b=" FMT64X " r=" FMT64X "\n",\
+           #op,\
+           a.q[0],\
+           b.q[0],\
+           r.q[0]);\
+    }\
+    SSE_OP2(op);\
+}
+
+#define SHUF_OP(op, ib)\
+{\
+    a.q[0] = test_values[0][0];\
+    a.q[1] = test_values[0][1];\
+    b.q[0] = test_values[1][0];\
+    b.q[1] = test_values[1][1];\
+    asm volatile (#op " $" #ib ", %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
+    printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
+           #op,\
+           a.q[1], a.q[0],\
+           b.q[1], b.q[0],\
+           ib,\
+           r.q[1], r.q[0]);\
+}
+
+#define PSHUF_OP(op, ib)\
+{\
+    int i;\
+    for(i=0;i<2;i++) {\
+    a.q[0] = test_values[2*i][0];\
+    a.q[1] = test_values[2*i][1];\
+    asm volatile (#op " $" #ib ", %1, %0" : "=x" (r.dq) : "x" (a.dq));\
+    printf("%-9s: a=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
+           #op,\
+           a.q[1], a.q[0],\
+           ib,\
+           r.q[1], r.q[0]);\
+    }\
+}
+
+#define SHIFT_IM(op, ib)\
+{\
+    int i;\
+    for(i=0;i<2;i++) {\
+    a.q[0] = test_values[2*i][0];\
+    a.q[1] = test_values[2*i][1];\
+    asm volatile (#op " $" #ib ", %0" : "=x" (r.dq) : "0" (a.dq));\
+    printf("%-9s: a=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
+           #op,\
+           a.q[1], a.q[0],\
+           ib,\
+           r.q[1], r.q[0]);\
+    }\
+}
+
+#define SHIFT_OP(op, ib)\
+{\
+    int i;\
+    SHIFT_IM(op, ib);\
+    for(i=0;i<2;i++) {\
+    a.q[0] = test_values[2*i][0];\
+    a.q[1] = test_values[2*i][1];\
+    b.q[0] = ib;\
+    b.q[1] = 0;\
+    asm volatile (#op " %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
+    printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
+           #op,\
+           a.q[1], a.q[0],\
+           b.q[1], b.q[0],\
+           r.q[1], r.q[0]);\
+    }\
+}
+
+#define MOVMSK(op)\
+{\
+    int i, reg;\
+    for(i=0;i<2;i++) {\
+    a.q[0] = test_values[2*i][0];\
+    a.q[1] = test_values[2*i][1];\
+    asm volatile (#op " %1, %0" : "=r" (reg) : "x" (a.dq));\
+    printf("%-9s: a=" FMT64X "" FMT64X " r=%08x\n",\
+           #op,\
+           a.q[1], a.q[0],\
+           reg);\
+    }\
+}
+
+#define SSE_OPS(a) \
+SSE_OP(a ## ps);\
+SSE_OP(a ## ss);
+
+#define SSE_OPD(a) \
+SSE_OP(a ## pd);\
+SSE_OP(a ## sd);
+
+#define SSE_COMI(op, field)\
+{\
+    unsigned int eflags;\
+    XMMReg a, b;\
+    a.field[0] = a1;\
+    b.field[0] = b1;\
+    asm volatile (#op " %2, %1\n"\
+        "pushf\n"\
+        "pop %0\n"\
+        : "=m" (eflags)\
+        : "x" (a.dq), "x" (b.dq));\
+    printf("%-9s: a=%f b=%f cc=%04x\n",\
+           #op, a1, b1,\
+           eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\
+}
+
+void test_sse_comi(double a1, double b1)
+{
+    SSE_COMI(ucomiss, s);
+    SSE_COMI(ucomisd, d);
+    SSE_COMI(comiss, s);
+    SSE_COMI(comisd, d);
+}
+
+#define CVT_OP_XMM(op)\
+{\
+    asm volatile (#op " %1, %0" : "=x" (r.dq) : "x" (a.dq));\
+    printf("%-9s: a=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
+           #op,\
+           a.q[1], a.q[0],\
+           r.q[1], r.q[0]);\
+}
+
+/* Force %xmm0 usage to avoid the case where both register index are 0
+   to test instruction decoding more extensively */
+#define CVT_OP_XMM2MMX(op)\
+{\
+    asm volatile (#op " %1, %0" : "=y" (r.q[0]) : "x" (a.dq) \
+                  : "%xmm0"); \
+    asm volatile("emms\n"); \
+    printf("%-9s: a=" FMT64X "" FMT64X " r=" FMT64X "\n",\
+           #op,\
+           a.q[1], a.q[0],\
+           r.q[0]);\
+}
+
+#define CVT_OP_MMX2XMM(op)\
+{\
+    asm volatile (#op " %1, %0" : "=x" (r.dq) : "y" (a.q[0]));\
+    asm volatile("emms\n"); \
+    printf("%-9s: a=" FMT64X " r=" FMT64X "" FMT64X "\n",\
+           #op,\
+           a.q[0],\
+           r.q[1], r.q[0]);\
+}
+
+#define CVT_OP_REG2XMM(op)\
+{\
+    asm volatile (#op " %1, %0" : "=x" (r.dq) : "r" (a.l[0]));\
+    printf("%-9s: a=%08x r=" FMT64X "" FMT64X "\n",\
+           #op,\
+           a.l[0],\
+           r.q[1], r.q[0]);\
+}
+
+#define CVT_OP_XMM2REG(op)\
+{\
+    asm volatile (#op " %1, %0" : "=r" (r.l[0]) : "x" (a.dq));\
+    printf("%-9s: a=" FMT64X "" FMT64X " r=%08x\n",\
+           #op,\
+           a.q[1], a.q[0],\
+           r.l[0]);\
+}
+
+struct fpxstate {
+    uint16_t fpuc;
+    uint16_t fpus;
+    uint16_t fptag;
+    uint16_t fop;
+    uint32_t fpuip;
+    uint16_t cs_sel;
+    uint16_t dummy0;
+    uint32_t fpudp;
+    uint16_t ds_sel;
+    uint16_t dummy1;
+    uint32_t mxcsr;
+    uint32_t mxcsr_mask;
+    uint8_t fpregs1[8 * 16];
+    uint8_t xmm_regs[8 * 16];
+    uint8_t dummy2[224];
+};
+
+static struct fpxstate fpx_state __attribute__((aligned(16)));
+static struct fpxstate fpx_state2 __attribute__((aligned(16)));
+
+void test_fxsave(void)
+{
+    struct fpxstate *fp = &fpx_state;
+    struct fpxstate *fp2 = &fpx_state2;
+    int i, nb_xmm;
+    XMMReg a, b;
+    a.q[0] = test_values[0][0];
+    a.q[1] = test_values[0][1];
+    b.q[0] = test_values[1][0];
+    b.q[1] = test_values[1][1];
+
+    asm("movdqa %2, %%xmm0\n"
+        "movdqa %3, %%xmm7\n"
+#if defined(__x86_64__)
+        "movdqa %2, %%xmm15\n"
+#endif
+        " fld1\n"
+        " fldpi\n"
+        " fldln2\n"
+        " fxsave %0\n"
+        " fxrstor %0\n"
+        " fxsave %1\n"
+        " fninit\n"
+        : "=m" (*(uint32_t *)fp2), "=m" (*(uint32_t *)fp)
+        : "m" (a), "m" (b));
+    printf("fpuc=%04x\n", fp->fpuc);
+    printf("fpus=%04x\n", fp->fpus);
+    printf("fptag=%04x\n", fp->fptag);
+    for(i = 0; i < 3; i++) {
+        printf("ST%d: " FMT64X " %04x\n",
+               i,
+               *(uint64_t *)&fp->fpregs1[i * 16],
+               *(uint16_t *)&fp->fpregs1[i * 16 + 8]);
+    }
+    printf("mxcsr=%08x\n", fp->mxcsr & 0x1f80);
+#if defined(__x86_64__)
+    nb_xmm = 16;
+#else
+    nb_xmm = 8;
+#endif
+    for(i = 0; i < nb_xmm; i++) {
+        printf("xmm%d: " FMT64X "" FMT64X "\n",
+               i,
+               *(uint64_t *)&fp->xmm_regs[i * 16],
+               *(uint64_t *)&fp->xmm_regs[i * 16 + 8]);
+    }
+}
+
+void test_sse(void)
+{
+    XMMReg r, a, b;
+    int i;
+
+    MMX_OP2(punpcklbw);
+    MMX_OP2(punpcklwd);
+    MMX_OP2(punpckldq);
+    MMX_OP2(packsswb);
+    MMX_OP2(pcmpgtb);
+    MMX_OP2(pcmpgtw);
+    MMX_OP2(pcmpgtd);
+    MMX_OP2(packuswb);
+    MMX_OP2(punpckhbw);
+    MMX_OP2(punpckhwd);
+    MMX_OP2(punpckhdq);
+    MMX_OP2(packssdw);
+    MMX_OP2(pcmpeqb);
+    MMX_OP2(pcmpeqw);
+    MMX_OP2(pcmpeqd);
+
+    MMX_OP2(paddq);
+    MMX_OP2(pmullw);
+    MMX_OP2(psubusb);
+    MMX_OP2(psubusw);
+    MMX_OP2(pminub);
+    MMX_OP2(pand);
+    MMX_OP2(paddusb);
+    MMX_OP2(paddusw);
+    MMX_OP2(pmaxub);
+    MMX_OP2(pandn);
+
+    MMX_OP2(pmulhuw);
+    MMX_OP2(pmulhw);
+
+    MMX_OP2(psubsb);
+    MMX_OP2(psubsw);
+    MMX_OP2(pminsw);
+    MMX_OP2(por);
+    MMX_OP2(paddsb);
+    MMX_OP2(paddsw);
+    MMX_OP2(pmaxsw);
+    MMX_OP2(pxor);
+    MMX_OP2(pmuludq);
+    MMX_OP2(pmaddwd);
+    MMX_OP2(psadbw);
+    MMX_OP2(psubb);
+    MMX_OP2(psubw);
+    MMX_OP2(psubd);
+    MMX_OP2(psubq);
+    MMX_OP2(paddb);
+    MMX_OP2(paddw);
+    MMX_OP2(paddd);
+
+    MMX_OP2(pavgb);
+    MMX_OP2(pavgw);
+
+    asm volatile ("pinsrw $1, %1, %0" : "=y" (r.q[0]) : "r" (0x12345678));
+    printf("%-9s: r=" FMT64X "\n", "pinsrw", r.q[0]);
+
+    asm volatile ("pinsrw $5, %1, %0" : "=x" (r.dq) : "r" (0x12345678));
+    printf("%-9s: r=" FMT64X "" FMT64X "\n", "pinsrw", r.q[1], r.q[0]);
+
+    a.q[0] = test_values[0][0];
+    a.q[1] = test_values[0][1];
+    asm volatile ("pextrw $1, %1, %0" : "=r" (r.l[0]) : "y" (a.q[0]));
+    printf("%-9s: r=%08x\n", "pextrw", r.l[0]);
+
+    asm volatile ("pextrw $5, %1, %0" : "=r" (r.l[0]) : "x" (a.dq));
+    printf("%-9s: r=%08x\n", "pextrw", r.l[0]);
+
+    asm volatile ("pmovmskb %1, %0" : "=r" (r.l[0]) : "y" (a.q[0]));
+    printf("%-9s: r=%08x\n", "pmovmskb", r.l[0]);
+
+    asm volatile ("pmovmskb %1, %0" : "=r" (r.l[0]) : "x" (a.dq));
+    printf("%-9s: r=%08x\n", "pmovmskb", r.l[0]);
+
+    {
+        r.q[0] = -1;
+        r.q[1] = -1;
+
+        a.q[0] = test_values[0][0];
+        a.q[1] = test_values[0][1];
+        b.q[0] = test_values[1][0];
+        b.q[1] = test_values[1][1];
+        asm volatile("maskmovq %1, %0" :
+                     : "y" (a.q[0]), "y" (b.q[0]), "D" (&r)
+                     : "memory");
+        printf("%-9s: r=" FMT64X " a=" FMT64X " b=" FMT64X "\n",
+               "maskmov",
+               r.q[0],
+               a.q[0],
+               b.q[0]);
+        asm volatile("maskmovdqu %1, %0" :
+                     : "x" (a.dq), "x" (b.dq), "D" (&r)
+                     : "memory");
+        printf("%-9s: r=" FMT64X "" FMT64X " a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X "\n",
+               "maskmov",
+               r.q[1], r.q[0],
+               a.q[1], a.q[0],
+               b.q[1], b.q[0]);
+    }
+
+    asm volatile ("emms");
+
+    SSE_OP2(punpcklqdq);
+    SSE_OP2(punpckhqdq);
+    SSE_OP2(andps);
+    SSE_OP2(andpd);
+    SSE_OP2(andnps);
+    SSE_OP2(andnpd);
+    SSE_OP2(orps);
+    SSE_OP2(orpd);
+    SSE_OP2(xorps);
+    SSE_OP2(xorpd);
+
+    SSE_OP2(unpcklps);
+    SSE_OP2(unpcklpd);
+    SSE_OP2(unpckhps);
+    SSE_OP2(unpckhpd);
+
+    SHUF_OP(shufps, 0x78);
+    SHUF_OP(shufpd, 0x02);
+
+    PSHUF_OP(pshufd, 0x78);
+    PSHUF_OP(pshuflw, 0x78);
+    PSHUF_OP(pshufhw, 0x78);
+
+    SHIFT_OP(psrlw, 7);
+    SHIFT_OP(psrlw, 16);
+    SHIFT_OP(psraw, 7);
+    SHIFT_OP(psraw, 16);
+    SHIFT_OP(psllw, 7);
+    SHIFT_OP(psllw, 16);
+
+    SHIFT_OP(psrld, 7);
+    SHIFT_OP(psrld, 32);
+    SHIFT_OP(psrad, 7);
+    SHIFT_OP(psrad, 32);
+    SHIFT_OP(pslld, 7);
+    SHIFT_OP(pslld, 32);
+
+    SHIFT_OP(psrlq, 7);
+    SHIFT_OP(psrlq, 32);
+    SHIFT_OP(psllq, 7);
+    SHIFT_OP(psllq, 32);
+
+    SHIFT_IM(psrldq, 16);
+    SHIFT_IM(psrldq, 7);
+    SHIFT_IM(pslldq, 16);
+    SHIFT_IM(pslldq, 7);
+
+    MOVMSK(movmskps);
+    MOVMSK(movmskpd);
+
+    /* FPU specific ops */
+
+    {
+        uint32_t mxcsr;
+        asm volatile("stmxcsr %0" : "=m" (mxcsr));
+        printf("mxcsr=%08x\n", mxcsr & 0x1f80);
+        asm volatile("ldmxcsr %0" : : "m" (mxcsr));
+    }
+
+    test_sse_comi(2, -1);
+    test_sse_comi(2, 2);
+    test_sse_comi(2, 3);
+    test_sse_comi(2, q_nan.d);
+    test_sse_comi(q_nan.d, -1);
+
+    for(i = 0; i < 2; i++) {
+        a.s[0] = 2.7;
+        a.s[1] = 3.4;
+        a.s[2] = 4;
+        a.s[3] = -6.3;
+        b.s[0] = 45.7;
+        b.s[1] = 353.4;
+        b.s[2] = 4;
+        b.s[3] = 56.3;
+        if (i == 1) {
+            a.s[0] = q_nan.d;
+            b.s[3] = q_nan.d;
+        }
+
+        SSE_OPS(add);
+        SSE_OPS(mul);
+        SSE_OPS(sub);
+        SSE_OPS(min);
+        SSE_OPS(div);
+        SSE_OPS(max);
+        SSE_OPS(sqrt);
+        SSE_OPS(cmpeq);
+        SSE_OPS(cmplt);
+        SSE_OPS(cmple);
+        SSE_OPS(cmpunord);
+        SSE_OPS(cmpneq);
+        SSE_OPS(cmpnlt);
+        SSE_OPS(cmpnle);
+        SSE_OPS(cmpord);
+
+
+        a.d[0] = 2.7;
+        a.d[1] = -3.4;
+        b.d[0] = 45.7;
+        b.d[1] = -53.4;
+        if (i == 1) {
+            a.d[0] = q_nan.d;
+            b.d[1] = q_nan.d;
+        }
+        SSE_OPD(add);
+        SSE_OPD(mul);
+        SSE_OPD(sub);
+        SSE_OPD(min);
+        SSE_OPD(div);
+        SSE_OPD(max);
+        SSE_OPD(sqrt);
+        SSE_OPD(cmpeq);
+        SSE_OPD(cmplt);
+        SSE_OPD(cmple);
+        SSE_OPD(cmpunord);
+        SSE_OPD(cmpneq);
+        SSE_OPD(cmpnlt);
+        SSE_OPD(cmpnle);
+        SSE_OPD(cmpord);
+    }
+
+    /* float to float/int */
+    a.s[0] = 2.7;
+    a.s[1] = 3.4;
+    a.s[2] = 4;
+    a.s[3] = -6.3;
+    CVT_OP_XMM(cvtps2pd);
+    CVT_OP_XMM(cvtss2sd);
+    CVT_OP_XMM2MMX(cvtps2pi);
+    CVT_OP_XMM2MMX(cvttps2pi);
+    CVT_OP_XMM2REG(cvtss2si);
+    CVT_OP_XMM2REG(cvttss2si);
+    CVT_OP_XMM(cvtps2dq);
+    CVT_OP_XMM(cvttps2dq);
+
+    a.d[0] = 2.6;
+    a.d[1] = -3.4;
+    CVT_OP_XMM(cvtpd2ps);
+    CVT_OP_XMM(cvtsd2ss);
+    CVT_OP_XMM2MMX(cvtpd2pi);
+    CVT_OP_XMM2MMX(cvttpd2pi);
+    CVT_OP_XMM2REG(cvtsd2si);
+    CVT_OP_XMM2REG(cvttsd2si);
+    CVT_OP_XMM(cvtpd2dq);
+    CVT_OP_XMM(cvttpd2dq);
+
+    /* sse/mmx moves */
+    CVT_OP_XMM2MMX(movdq2q);
+    CVT_OP_MMX2XMM(movq2dq);
+
+    /* int to float */
+    a.l[0] = -6;
+    a.l[1] = 2;
+    a.l[2] = 100;
+    a.l[3] = -60000;
+    CVT_OP_MMX2XMM(cvtpi2ps);
+    CVT_OP_MMX2XMM(cvtpi2pd);
+    CVT_OP_REG2XMM(cvtsi2ss);
+    CVT_OP_REG2XMM(cvtsi2sd);
+    CVT_OP_XMM(cvtdq2ps);
+    CVT_OP_XMM(cvtdq2pd);
+
+    /* XXX: test PNI insns */
+#if 0
+    SSE_OP2(movshdup);
+#endif
+    asm volatile ("emms");
+}
+
+#endif
+
+#define TEST_CONV_RAX(op)\
+{\
+    unsigned long a, r;\
+    a = i2l(0x8234a6f8);\
+    r = a;\
+    asm volatile(#op : "=a" (r) : "0" (r));\
+    printf("%-10s A=" FMTLX " R=" FMTLX "\n", #op, a, r);\
+}
+
+#define TEST_CONV_RAX_RDX(op)\
+{\
+    unsigned long a, d, r, rh;                   \
+    a = i2l(0x8234a6f8);\
+    d = i2l(0x8345a1f2);\
+    r = a;\
+    rh = d;\
+    asm volatile(#op : "=a" (r), "=d" (rh) : "0" (r), "1" (rh));   \
+    printf("%-10s A=" FMTLX " R=" FMTLX ":" FMTLX "\n", #op, a, r, rh);  \
+}
+
+void test_conv(void)
+{
+    TEST_CONV_RAX(cbw);
+    TEST_CONV_RAX(cwde);
+#if defined(__x86_64__)
+    TEST_CONV_RAX(cdqe);
+#endif
+
+    TEST_CONV_RAX_RDX(cwd);
+    TEST_CONV_RAX_RDX(cdq);
+#if defined(__x86_64__)
+    TEST_CONV_RAX_RDX(cqo);
+#endif
+
+    {
+        unsigned long a, r;
+        a = i2l(0x12345678);
+        asm volatile("bswapl %k0" : "=r" (r) : "0" (a));
+        printf("%-10s: A=" FMTLX " R=" FMTLX "\n", "bswapl", a, r);
+    }
+#if defined(__x86_64__)
+    {
+        unsigned long a, r;
+        a = i2l(0x12345678);
+        asm volatile("bswapq %0" : "=r" (r) : "0" (a));
+        printf("%-10s: A=" FMTLX " R=" FMTLX "\n", "bswapq", a, r);
+    }
+#endif
+}
+
+extern void *__start_initcall;
+extern void *__stop_initcall;
+
+
+int main(int argc, char **argv)
+{
+    void **ptr;
+    void (*func)(void);
+
+    ptr = &__start_initcall;
+    while (ptr != &__stop_initcall) {
+        func = *ptr++;
+        func();
+    }
+    test_bsx();
+    test_mul();
+    test_jcc();
+    test_loop();
+    test_floats();
+#if !defined(__x86_64__)
+    test_bcd();
+#endif
+    test_xchg();
+    test_string();
+    test_misc();
+    test_lea();
+#ifdef TEST_SEGS
+    test_segs();
+    test_code16();
+#endif
+#ifdef TEST_VM86
+    test_vm86();
+#endif
+#if !defined(__x86_64__)
+    test_exceptions();
+    test_self_modifying_code();
+    test_single_step();
+#endif
+    test_enter();
+    test_conv();
+#ifdef TEST_SSE
+    test_sse();
+    test_fxsave();
+#endif
+    return 0;
+}
diff --git a/tests/tcg/test-i386.h b/tests/tcg/test-i386.h
new file mode 100644
index 0000000..75106b8
--- /dev/null
+++ b/tests/tcg/test-i386.h
@@ -0,0 +1,152 @@
+
+#define exec_op glue(exec_, OP)
+#define exec_opq glue(glue(exec_, OP), q)
+#define exec_opl glue(glue(exec_, OP), l)
+#define exec_opw glue(glue(exec_, OP), w)
+#define exec_opb glue(glue(exec_, OP), b)
+
+#define EXECOP2(size, rsize, res, s1, flags) \
+    asm ("push %4\n\t"\
+         "popf\n\t"\
+         stringify(OP) size " %" rsize "2, %" rsize "0\n\t" \
+         "pushf\n\t"\
+         "pop %1\n\t"\
+         : "=q" (res), "=g" (flags)\
+         : "q" (s1), "0" (res), "1" (flags)); \
+    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n", \
+           stringify(OP) size, s0, s1, res, iflags, flags & CC_MASK);
+
+#define EXECOP1(size, rsize, res, flags) \
+    asm ("push %3\n\t"\
+         "popf\n\t"\
+         stringify(OP) size " %" rsize "0\n\t" \
+         "pushf\n\t"\
+         "pop %1\n\t"\
+         : "=q" (res), "=g" (flags)\
+         : "0" (res), "1" (flags)); \
+    printf("%-10s A=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n", \
+           stringify(OP) size, s0, res, iflags, flags & CC_MASK);
+
+#ifdef OP1
+#if defined(__x86_64__)
+void exec_opq(long s0, long s1, long iflags)
+{
+    long res, flags;
+    res = s0;
+    flags = iflags;
+    EXECOP1("q", "", res, flags);
+}
+#endif
+
+void exec_opl(long s0, long s1, long iflags)
+{
+    long res, flags;
+    res = s0;
+    flags = iflags;
+    EXECOP1("l", "k", res, flags);
+}
+
+void exec_opw(long s0, long s1, long iflags)
+{
+    long res, flags;
+    res = s0;
+    flags = iflags;
+    EXECOP1("w", "w", res, flags);
+}
+
+void exec_opb(long s0, long s1, long iflags)
+{
+    long res, flags;
+    res = s0;
+    flags = iflags;
+    EXECOP1("b", "b", res, flags);
+}
+#else
+#if defined(__x86_64__)
+void exec_opq(long s0, long s1, long iflags)
+{
+    long res, flags;
+    res = s0;
+    flags = iflags;
+    EXECOP2("q", "", res, s1, flags);
+}
+#endif
+
+void exec_opl(long s0, long s1, long iflags)
+{
+    long res, flags;
+    res = s0;
+    flags = iflags;
+    EXECOP2("l", "k", res, s1, flags);
+}
+
+void exec_opw(long s0, long s1, long iflags)
+{
+    long res, flags;
+    res = s0;
+    flags = iflags;
+    EXECOP2("w", "w", res, s1, flags);
+}
+
+void exec_opb(long s0, long s1, long iflags)
+{
+    long res, flags;
+    res = s0;
+    flags = iflags;
+    EXECOP2("b", "b", res, s1, flags);
+}
+#endif
+
+void exec_op(long s0, long s1)
+{
+    s0 = i2l(s0);
+    s1 = i2l(s1);
+#if defined(__x86_64__)
+    exec_opq(s0, s1, 0);
+#endif
+    exec_opl(s0, s1, 0);
+    exec_opw(s0, s1, 0);
+    exec_opb(s0, s1, 0);
+#ifdef OP_CC
+#if defined(__x86_64__)
+    exec_opq(s0, s1, CC_C);
+#endif
+    exec_opl(s0, s1, CC_C);
+    exec_opw(s0, s1, CC_C);
+    exec_opb(s0, s1, CC_C);
+#endif
+}
+
+void glue(test_, OP)(void)
+{
+    exec_op(0x12345678, 0x812FADA);
+    exec_op(0x12341, 0x12341);
+    exec_op(0x12341, -0x12341);
+    exec_op(0xffffffff, 0);
+    exec_op(0xffffffff, -1);
+    exec_op(0xffffffff, 1);
+    exec_op(0xffffffff, 2);
+    exec_op(0x7fffffff, 0);
+    exec_op(0x7fffffff, 1);
+    exec_op(0x7fffffff, -1);
+    exec_op(0x80000000, -1);
+    exec_op(0x80000000, 1);
+    exec_op(0x80000000, -2);
+    exec_op(0x12347fff, 0);
+    exec_op(0x12347fff, 1);
+    exec_op(0x12347fff, -1);
+    exec_op(0x12348000, -1);
+    exec_op(0x12348000, 1);
+    exec_op(0x12348000, -2);
+    exec_op(0x12347f7f, 0);
+    exec_op(0x12347f7f, 1);
+    exec_op(0x12347f7f, -1);
+    exec_op(0x12348080, -1);
+    exec_op(0x12348080, 1);
+    exec_op(0x12348080, -2);
+}
+
+void *glue(_test_, OP) __init_call = glue(test_, OP);
+
+#undef OP
+#undef OP_CC
diff --git a/tests/tcg/test-mmap.c b/tests/tcg/test-mmap.c
new file mode 100644
index 0000000..c67174a
--- /dev/null
+++ b/tests/tcg/test-mmap.c
@@ -0,0 +1,476 @@
+/*
+ * Small test program to verify simulated mmap behaviour.
+ *
+ * When running qemu-linux-user with the -p flag, you may need to tell
+ * this test program about the pagesize because getpagesize() will not reflect
+ * the -p choice. Simply pass one argument beeing the pagesize.
+ *
+ * Copyright (c) 2007 AXIS Communications AB
+ * Written by Edgar E. Iglesias.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+
+#define D(x)
+
+#define fail_unless(x)                                         \
+do                                                             \
+{                                                              \
+  if (!(x)) {                                                  \
+    fprintf (stderr, "FAILED at %s:%d\n", __FILE__, __LINE__); \
+    exit (EXIT_FAILURE);                                       \
+  }                                                            \
+} while (0);
+
+unsigned char *dummybuf;
+static unsigned int pagesize;
+static unsigned int pagemask;
+int test_fd;
+size_t test_fsize;
+
+void check_aligned_anonymous_unfixed_mmaps(void)
+{
+	void *p1;
+	void *p2;
+	void *p3;
+	void *p4;
+	void *p5;
+	uintptr_t p;
+	int i;
+
+	fprintf (stderr, "%s", __func__);
+	for (i = 0; i < 0x1fff; i++)
+	{
+		size_t len;
+
+		len = pagesize + (pagesize * i & 7);
+		p1 = mmap(NULL, len, PROT_READ, 
+			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+		p2 = mmap(NULL, len, PROT_READ, 
+			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+		p3 = mmap(NULL, len, PROT_READ, 
+			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+		p4 = mmap(NULL, len, PROT_READ, 
+			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+		p5 = mmap(NULL, len, PROT_READ, 
+			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+		/* Make sure we get pages aligned with the pagesize. The
+		   target expects this.  */
+		fail_unless (p1 != MAP_FAILED);
+		fail_unless (p2 != MAP_FAILED);
+		fail_unless (p3 != MAP_FAILED);
+		fail_unless (p4 != MAP_FAILED);
+		fail_unless (p5 != MAP_FAILED);
+		p = (uintptr_t) p1;
+		D(printf ("p=%x\n", p));
+		fail_unless ((p & pagemask) == 0);
+		p = (uintptr_t) p2;
+		fail_unless ((p & pagemask) == 0);
+		p = (uintptr_t) p3;
+		fail_unless ((p & pagemask) == 0);
+		p = (uintptr_t) p4;
+		fail_unless ((p & pagemask) == 0);
+		p = (uintptr_t) p5;
+		fail_unless ((p & pagemask) == 0);
+
+		/* Make sure we can read from the entire area.  */
+		memcpy (dummybuf, p1, pagesize);
+		memcpy (dummybuf, p2, pagesize);
+		memcpy (dummybuf, p3, pagesize);
+		memcpy (dummybuf, p4, pagesize);
+		memcpy (dummybuf, p5, pagesize);
+
+		munmap (p1, len);
+		munmap (p2, len);
+		munmap (p3, len);
+		munmap (p4, len);
+		munmap (p5, len);
+	}
+	fprintf (stderr, " passed\n");
+}
+
+void check_large_anonymous_unfixed_mmap(void)
+{
+	void *p1;
+	uintptr_t p;
+	size_t len;
+
+	fprintf (stderr, "%s", __func__);
+
+	len = 0x02000000;
+	p1 = mmap(NULL, len, PROT_READ, 
+		  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+	/* Make sure we get pages aligned with the pagesize. The
+	   target expects this.  */
+	fail_unless (p1 != MAP_FAILED);
+	p = (uintptr_t) p1;
+	fail_unless ((p & pagemask) == 0);
+	
+	/* Make sure we can read from the entire area.  */
+	memcpy (dummybuf, p1, pagesize);
+	munmap (p1, len);
+	fprintf (stderr, " passed\n");
+}
+
+void check_aligned_anonymous_unfixed_colliding_mmaps(void)
+{
+	char *p1;
+	char *p2;
+	char *p3;
+	uintptr_t p;
+	int i;
+
+	fprintf (stderr, "%s", __func__);
+	for (i = 0; i < 0x2fff; i++)
+	{
+		int nlen;
+		p1 = mmap(NULL, pagesize, PROT_READ, 
+			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+		fail_unless (p1 != MAP_FAILED);
+		p = (uintptr_t) p1;
+		fail_unless ((p & pagemask) == 0);
+		memcpy (dummybuf, p1, pagesize);
+
+		p2 = mmap(NULL, pagesize, PROT_READ, 
+			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+		fail_unless (p2 != MAP_FAILED);
+		p = (uintptr_t) p2;
+		fail_unless ((p & pagemask) == 0);
+		memcpy (dummybuf, p2, pagesize);
+
+
+		munmap (p1, pagesize);
+		nlen = pagesize * 8;
+		p3 = mmap(NULL, nlen, PROT_READ, 
+			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+		fail_unless (p3 != MAP_FAILED);
+
+		/* Check if the mmaped areas collide.  */
+		if (p3 < p2 
+		    && (p3 + nlen) > p2)
+			fail_unless (0);
+
+		memcpy (dummybuf, p3, pagesize);
+
+		/* Make sure we get pages aligned with the pagesize. The
+		   target expects this.  */
+		p = (uintptr_t) p3;
+		fail_unless ((p & pagemask) == 0);
+		munmap (p2, pagesize);
+		munmap (p3, nlen);
+	}
+	fprintf (stderr, " passed\n");
+}
+
+void check_aligned_anonymous_fixed_mmaps(void)
+{
+	char *addr;
+	void *p1;
+	uintptr_t p;
+	int i;
+
+	/* Find a suitable address to start with.  */
+	addr = mmap(NULL, pagesize * 40, PROT_READ | PROT_WRITE, 
+		    MAP_PRIVATE | MAP_ANONYMOUS,
+		    -1, 0);
+	fprintf (stderr, "%s addr=%p", __func__, addr);
+	fail_unless (addr != MAP_FAILED);
+
+	for (i = 0; i < 40; i++)
+	{
+		/* Create submaps within our unfixed map.  */
+		p1 = mmap(addr, pagesize, PROT_READ, 
+			  MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
+			  -1, 0);
+		/* Make sure we get pages aligned with the pagesize. 
+		   The target expects this.  */
+		p = (uintptr_t) p1;
+		fail_unless (p1 == addr);
+		fail_unless ((p & pagemask) == 0);		
+		memcpy (dummybuf, p1, pagesize);
+		munmap (p1, pagesize);
+		addr += pagesize;
+	}
+	fprintf (stderr, " passed\n");
+}
+
+void check_aligned_anonymous_fixed_mmaps_collide_with_host(void)
+{
+	char *addr;
+	void *p1;
+	uintptr_t p;
+	int i;
+
+	/* Find a suitable address to start with.  Right were the x86 hosts
+	 stack is.  */
+	addr = ((void *)0x80000000);
+	fprintf (stderr, "%s addr=%p", __func__, addr);
+	fprintf (stderr, "FIXME: QEMU fails to track pages used by the host.");
+
+	for (i = 0; i < 20; i++)
+	{
+		/* Create submaps within our unfixed map.  */
+		p1 = mmap(addr, pagesize, PROT_READ | PROT_WRITE, 
+			  MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
+			  -1, 0);
+		/* Make sure we get pages aligned with the pagesize. 
+		   The target expects this.  */
+		p = (uintptr_t) p1;
+		fail_unless (p1 == addr);
+		fail_unless ((p & pagemask) == 0);		
+		memcpy (p1, dummybuf, pagesize);
+		munmap (p1, pagesize);
+		addr += pagesize;
+	}
+	fprintf (stderr, " passed\n");
+}
+
+void check_file_unfixed_mmaps(void)
+{
+	unsigned int *p1, *p2, *p3;
+	uintptr_t p;
+	int i;
+
+	fprintf (stderr, "%s", __func__);
+	for (i = 0; i < 0x10; i++)
+	{
+		size_t len;
+
+		len = pagesize;
+		p1 = mmap(NULL, len, PROT_READ, 
+			  MAP_PRIVATE, 
+			  test_fd, 0);
+		p2 = mmap(NULL, len, PROT_READ, 
+			  MAP_PRIVATE, 
+			  test_fd, pagesize);
+		p3 = mmap(NULL, len, PROT_READ, 
+			  MAP_PRIVATE, 
+			  test_fd, pagesize * 2);
+
+		fail_unless (p1 != MAP_FAILED);
+		fail_unless (p2 != MAP_FAILED);
+		fail_unless (p3 != MAP_FAILED);
+
+		/* Make sure we get pages aligned with the pagesize. The
+		   target expects this.  */
+		p = (uintptr_t) p1;
+		fail_unless ((p & pagemask) == 0);
+		p = (uintptr_t) p2;
+		fail_unless ((p & pagemask) == 0);
+		p = (uintptr_t) p3;
+		fail_unless ((p & pagemask) == 0);
+
+		/* Verify that the file maps was made correctly.  */
+		D(printf ("p1=%d p2=%d p3=%d\n", *p1, *p2, *p3));
+		fail_unless (*p1 == 0);
+		fail_unless (*p2 == (pagesize / sizeof *p2));
+		fail_unless (*p3 == ((pagesize * 2) / sizeof *p3));
+
+		memcpy (dummybuf, p1, pagesize);
+		memcpy (dummybuf, p2, pagesize);
+		memcpy (dummybuf, p3, pagesize);
+		munmap (p1, len);
+		munmap (p2, len);
+		munmap (p3, len);
+	}
+	fprintf (stderr, " passed\n");
+}
+
+void check_file_unfixed_eof_mmaps(void)
+{
+	char *cp;
+	unsigned int *p1;
+	uintptr_t p;
+	int i;
+
+	fprintf (stderr, "%s", __func__);
+	for (i = 0; i < 0x10; i++)
+	{
+		p1 = mmap(NULL, pagesize, PROT_READ, 
+			  MAP_PRIVATE, 
+			  test_fd, 
+			  (test_fsize - sizeof *p1) & ~pagemask);
+
+		fail_unless (p1 != MAP_FAILED);
+
+		/* Make sure we get pages aligned with the pagesize. The
+		   target expects this.  */
+		p = (uintptr_t) p1;
+		fail_unless ((p & pagemask) == 0);
+		/* Verify that the file maps was made correctly.  */
+		fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1]
+			     == ((test_fsize - sizeof *p1) / sizeof *p1));
+
+		/* Verify that the end of page is accessible and zeroed.  */
+		cp = (void *) p1;
+		fail_unless (cp[pagesize - 4] == 0);
+		munmap (p1, pagesize);
+	}
+	fprintf (stderr, " passed\n");
+}
+
+void check_file_fixed_eof_mmaps(void)
+{
+	char *addr;
+	char *cp;
+	unsigned int *p1;
+	uintptr_t p;
+	int i;
+
+	/* Find a suitable address to start with.  */
+	addr = mmap(NULL, pagesize * 44, PROT_READ, 
+		    MAP_PRIVATE | MAP_ANONYMOUS,
+		    -1, 0);
+
+	fprintf (stderr, "%s addr=%p", __func__, (void *)addr);
+	fail_unless (addr != MAP_FAILED);
+
+	for (i = 0; i < 0x10; i++)
+	{
+		/* Create submaps within our unfixed map.  */
+		p1 = mmap(addr, pagesize, PROT_READ, 
+			  MAP_PRIVATE | MAP_FIXED, 
+			  test_fd, 
+			  (test_fsize - sizeof *p1) & ~pagemask);
+
+		fail_unless (p1 != MAP_FAILED);
+
+		/* Make sure we get pages aligned with the pagesize. The
+		   target expects this.  */
+		p = (uintptr_t) p1;
+		fail_unless ((p & pagemask) == 0);
+
+		/* Verify that the file maps was made correctly.  */
+		fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1]
+			     == ((test_fsize - sizeof *p1) / sizeof *p1));
+
+		/* Verify that the end of page is accessible and zeroed.  */
+		cp = (void *)p1;
+		fail_unless (cp[pagesize - 4] == 0);
+		munmap (p1, pagesize);
+		addr += pagesize;
+	}
+	fprintf (stderr, " passed\n");
+}
+
+void check_file_fixed_mmaps(void)
+{
+	unsigned char *addr;
+	unsigned int *p1, *p2, *p3, *p4;
+	int i;
+
+	/* Find a suitable address to start with.  */
+	addr = mmap(NULL, pagesize * 40 * 4, PROT_READ, 
+		    MAP_PRIVATE | MAP_ANONYMOUS,
+		    -1, 0);
+	fprintf (stderr, "%s addr=%p", __func__, (void *)addr);
+	fail_unless (addr != MAP_FAILED);
+
+	for (i = 0; i < 40; i++)
+	{
+		p1 = mmap(addr, pagesize, PROT_READ, 
+			  MAP_PRIVATE | MAP_FIXED,
+			  test_fd, 0);
+		p2 = mmap(addr + pagesize, pagesize, PROT_READ, 
+			  MAP_PRIVATE | MAP_FIXED,
+			  test_fd, pagesize);
+		p3 = mmap(addr + pagesize * 2, pagesize, PROT_READ, 
+			  MAP_PRIVATE | MAP_FIXED,
+			  test_fd, pagesize * 2);
+		p4 = mmap(addr + pagesize * 3, pagesize, PROT_READ, 
+			  MAP_PRIVATE | MAP_FIXED,
+			  test_fd, pagesize * 3);
+
+		/* Make sure we get pages aligned with the pagesize. 
+		   The target expects this.  */
+		fail_unless (p1 == (void *)addr);
+		fail_unless (p2 == (void *)addr + pagesize);
+		fail_unless (p3 == (void *)addr + pagesize * 2);
+		fail_unless (p4 == (void *)addr + pagesize * 3);
+
+		/* Verify that the file maps was made correctly.  */
+		fail_unless (*p1 == 0);
+		fail_unless (*p2 == (pagesize / sizeof *p2));
+		fail_unless (*p3 == ((pagesize * 2) / sizeof *p3));
+		fail_unless (*p4 == ((pagesize * 3) / sizeof *p4));
+
+		memcpy (dummybuf, p1, pagesize);
+		memcpy (dummybuf, p2, pagesize);
+		memcpy (dummybuf, p3, pagesize);
+		memcpy (dummybuf, p4, pagesize);
+
+		munmap (p1, pagesize);
+		munmap (p2, pagesize);
+		munmap (p3, pagesize);
+		munmap (p4, pagesize);
+		addr += pagesize * 4;
+	}
+	fprintf (stderr, " passed\n");
+}
+
+int main(int argc, char **argv)
+{
+	char tempname[] = "/tmp/.cmmapXXXXXX";
+	unsigned int i;
+
+	/* Trust the first argument, otherwise probe the system for our
+	   pagesize.  */
+	if (argc > 1)
+		pagesize = strtoul(argv[1], NULL, 0);
+	else
+		pagesize = sysconf(_SC_PAGESIZE);
+
+	/* Assume pagesize is a power of two.  */
+	pagemask = pagesize - 1;
+	dummybuf = malloc (pagesize);
+	printf ("pagesize=%u pagemask=%x\n", pagesize, pagemask);
+
+	test_fd = mkstemp(tempname);
+	unlink(tempname);
+
+	/* Fill the file with int's counting from zero and up.  */
+	for (i = 0; i < (pagesize * 4) / sizeof i; i++)
+		write (test_fd, &i, sizeof i);
+	/* Append a few extra writes to make the file end at non 
+	   page boundary.  */
+	write (test_fd, &i, sizeof i); i++;
+	write (test_fd, &i, sizeof i); i++;
+	write (test_fd, &i, sizeof i); i++;
+
+	test_fsize = lseek(test_fd, 0, SEEK_CUR);
+
+	/* Run the tests.  */
+	check_aligned_anonymous_unfixed_mmaps();
+	check_aligned_anonymous_unfixed_colliding_mmaps();
+	check_aligned_anonymous_fixed_mmaps();
+	check_file_unfixed_mmaps();
+	check_file_fixed_mmaps();
+	check_file_fixed_eof_mmaps();
+	check_file_unfixed_eof_mmaps();
+
+	/* Fails at the moment.  */
+	/* check_aligned_anonymous_fixed_mmaps_collide_with_host(); */
+
+	return EXIT_SUCCESS;
+}
diff --git a/tests/tcg/test_path.c b/tests/tcg/test_path.c
new file mode 100644
index 0000000..7265a94
--- /dev/null
+++ b/tests/tcg/test_path.c
@@ -0,0 +1,160 @@
+/* Test path override code */
+#include "../config-host.h"
+#include "../qemu-malloc.c"
+#include "../cutils.c"
+#include "../path.c"
+#include "../trace.c"
+#ifdef CONFIG_TRACE_SIMPLE
+#include "../simpletrace.c"
+#endif
+
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+void qemu_log(const char *fmt, ...);
+
+/* Any log message kills the test. */
+void qemu_log(const char *fmt, ...)
+{
+    va_list ap;
+
+    fprintf(stderr, "FATAL: ");
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+    exit(1);
+}
+
+#define NO_CHANGE(_path)						\
+	do {								\
+	    if (strcmp(path(_path), _path) != 0) return __LINE__;	\
+	} while(0)
+
+#define CHANGE_TO(_path, _newpath)					\
+	do {								\
+	    if (strcmp(path(_path), _newpath) != 0) return __LINE__;	\
+	} while(0)
+
+static void cleanup(void)
+{
+    unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE");
+    unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE2");
+    unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE3");
+    unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE4");
+    unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE5");
+    rmdir("/tmp/qemu-test_path/DIR1/DIR2");
+    rmdir("/tmp/qemu-test_path/DIR1/DIR3");
+    rmdir("/tmp/qemu-test_path/DIR1");
+    rmdir("/tmp/qemu-test_path");
+}
+
+static unsigned int do_test(void)
+{
+    if (mkdir("/tmp/qemu-test_path", 0700) != 0)
+	return __LINE__;
+
+    if (mkdir("/tmp/qemu-test_path/DIR1", 0700) != 0)
+	return __LINE__;
+
+    if (mkdir("/tmp/qemu-test_path/DIR1/DIR2", 0700) != 0)
+	return __LINE__;
+
+    if (mkdir("/tmp/qemu-test_path/DIR1/DIR3", 0700) != 0)
+	return __LINE__;
+
+    if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE", 0600)) != 0)
+	return __LINE__;
+
+    if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE2", 0600)) != 0)
+	return __LINE__;
+
+    if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE3", 0600)) != 0)
+	return __LINE__;
+
+    if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE4", 0600)) != 0)
+	return __LINE__;
+
+    if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE5", 0600)) != 0)
+	return __LINE__;
+
+    init_paths("/tmp/qemu-test_path");
+
+    NO_CHANGE("/tmp");
+    NO_CHANGE("/tmp/");
+    NO_CHANGE("/tmp/qemu-test_path");
+    NO_CHANGE("/tmp/qemu-test_path/");
+    NO_CHANGE("/tmp/qemu-test_path/D");
+    NO_CHANGE("/tmp/qemu-test_path/DI");
+    NO_CHANGE("/tmp/qemu-test_path/DIR");
+    NO_CHANGE("/tmp/qemu-test_path/DIR1");
+    NO_CHANGE("/tmp/qemu-test_path/DIR1/");
+
+    NO_CHANGE("/D");
+    NO_CHANGE("/DI");
+    NO_CHANGE("/DIR");
+    NO_CHANGE("/DIR2");
+    NO_CHANGE("/DIR1.");
+
+    CHANGE_TO("/DIR1", "/tmp/qemu-test_path/DIR1");
+    CHANGE_TO("/DIR1/", "/tmp/qemu-test_path/DIR1");
+
+    NO_CHANGE("/DIR1/D");
+    NO_CHANGE("/DIR1/DI");
+    NO_CHANGE("/DIR1/DIR");
+    NO_CHANGE("/DIR1/DIR1");
+
+    CHANGE_TO("/DIR1/DIR2", "/tmp/qemu-test_path/DIR1/DIR2");
+    CHANGE_TO("/DIR1/DIR2/", "/tmp/qemu-test_path/DIR1/DIR2");
+
+    CHANGE_TO("/DIR1/DIR3", "/tmp/qemu-test_path/DIR1/DIR3");
+    CHANGE_TO("/DIR1/DIR3/", "/tmp/qemu-test_path/DIR1/DIR3");
+
+    NO_CHANGE("/DIR1/DIR2/F");
+    NO_CHANGE("/DIR1/DIR2/FI");
+    NO_CHANGE("/DIR1/DIR2/FIL");
+    NO_CHANGE("/DIR1/DIR2/FIL.");
+
+    CHANGE_TO("/DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+    CHANGE_TO("/DIR1/DIR2/FILE2", "/tmp/qemu-test_path/DIR1/DIR2/FILE2");
+    CHANGE_TO("/DIR1/DIR2/FILE3", "/tmp/qemu-test_path/DIR1/DIR2/FILE3");
+    CHANGE_TO("/DIR1/DIR2/FILE4", "/tmp/qemu-test_path/DIR1/DIR2/FILE4");
+    CHANGE_TO("/DIR1/DIR2/FILE5", "/tmp/qemu-test_path/DIR1/DIR2/FILE5");
+
+    NO_CHANGE("/DIR1/DIR2/FILE6");
+    NO_CHANGE("/DIR1/DIR2/FILE/X");
+
+    CHANGE_TO("/DIR1/../DIR1", "/tmp/qemu-test_path/DIR1");
+    CHANGE_TO("/DIR1/../DIR1/", "/tmp/qemu-test_path/DIR1");
+    CHANGE_TO("/../DIR1", "/tmp/qemu-test_path/DIR1");
+    CHANGE_TO("/../DIR1/", "/tmp/qemu-test_path/DIR1");
+    CHANGE_TO("/DIR1/DIR2/../DIR2", "/tmp/qemu-test_path/DIR1/DIR2");
+    CHANGE_TO("/DIR1/DIR2/../DIR2/../../DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+    CHANGE_TO("/DIR1/DIR2/../DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+
+    NO_CHANGE("/DIR1/DIR2/../DIR1");
+    NO_CHANGE("/DIR1/DIR2/../FILE");
+
+    CHANGE_TO("/./DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+    CHANGE_TO("/././DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+    CHANGE_TO("/DIR1/./DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+    CHANGE_TO("/DIR1/././DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+    CHANGE_TO("/DIR1/DIR2/./FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+    CHANGE_TO("/DIR1/DIR2/././FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+    CHANGE_TO("/./DIR1/./DIR2/./FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+
+    return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    int ret;
+
+    ret = do_test();
+    cleanup();
+    if (ret) {
+	fprintf(stderr, "test_path: failed on line %i\n", ret);
+	return 1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/testthread.c b/tests/tcg/testthread.c
new file mode 100644
index 0000000..27e4825
--- /dev/null
+++ b/tests/tcg/testthread.c
@@ -0,0 +1,51 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <sys/wait.h>
+#include <sched.h>
+
+void *thread1_func(void *arg)
+{
+    int i;
+    char buf[512];
+
+    for(i=0;i<10;i++) {
+        snprintf(buf, sizeof(buf), "thread1: %d %s\n", i, (char *)arg);
+        write(1, buf, strlen(buf));
+        usleep(100 * 1000);
+    }
+    return NULL;
+}
+
+void *thread2_func(void *arg)
+{
+    int i;
+    char buf[512];
+    for(i=0;i<20;i++) {
+        snprintf(buf, sizeof(buf), "thread2: %d %s\n", i, (char *)arg);
+        write(1, buf, strlen(buf));
+        usleep(150 * 1000);
+    }
+    return NULL;
+}
+
+void test_pthread(void)
+{
+    pthread_t tid1, tid2;
+
+    pthread_create(&tid1, NULL, thread1_func, "hello1");
+    pthread_create(&tid2, NULL, thread2_func, "hello2");
+    pthread_join(tid1, NULL);
+    pthread_join(tid2, NULL);
+    printf("End of pthread test.\n");
+}
+
+int main(int argc, char **argv)
+{
+    test_pthread();
+    return 0;
+}
diff --git a/tests/tcg/xtensa/Makefile b/tests/tcg/xtensa/Makefile
new file mode 100644
index 0000000..8713af1
--- /dev/null
+++ b/tests/tcg/xtensa/Makefile
@@ -0,0 +1,75 @@
+-include ../../config-host.mak
+
+CROSS=xtensa-dc232b-elf-
+
+ifndef XT
+SIM = qemu-system-xtensa
+SIMFLAGS = -M sim -cpu dc232b -nographic -semihosting $(EXTFLAGS) -kernel
+SIMDEBUG = -s -S
+else
+SIM = xt-run
+SIMFLAGS = --xtensa-core=DC_B_232L --exit_with_target_code $(EXTFLAGS)
+SIMDEBUG = --gdbserve=0
+endif
+
+CC      = $(CROSS)gcc
+AS      = $(CROSS)gcc -x assembler
+LD      = $(CROSS)ld
+
+LDFLAGS = -Tlinker.ld
+
+CRT        = crt.o vectors.o
+
+TESTCASES += test_b.tst
+TESTCASES += test_bi.tst
+#TESTCASES += test_boolean.tst
+TESTCASES += test_bz.tst
+TESTCASES += test_clamps.tst
+TESTCASES += test_fail.tst
+TESTCASES += test_interrupt.tst
+TESTCASES += test_loop.tst
+TESTCASES += test_mac16.tst
+TESTCASES += test_max.tst
+TESTCASES += test_min.tst
+TESTCASES += test_mmu.tst
+TESTCASES += test_mul16.tst
+TESTCASES += test_mul32.tst
+TESTCASES += test_nsa.tst
+ifdef XT
+TESTCASES += test_pipeline.tst
+endif
+TESTCASES += test_quo.tst
+TESTCASES += test_rem.tst
+TESTCASES += test_rst0.tst
+TESTCASES += test_sar.tst
+TESTCASES += test_sext.tst
+TESTCASES += test_shift.tst
+TESTCASES += test_timer.tst
+TESTCASES += test_windowed.tst
+
+all: build
+
+%.o: $(SRC_PATH)/tests/xtensa/%.c
+	$(CC) $(CFLAGS) -c $< -o $@
+
+%.o: $(SRC_PATH)/tests/xtensa/%.S
+	$(AS) $(ASFLAGS) -c $< -o $@
+
+%.tst: %.o macros.inc $(CRT) Makefile
+	$(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $< -o $@
+
+build: $(TESTCASES)
+
+check: $(addprefix run-, $(TESTCASES))
+
+run-%.tst: %.tst
+	$(SIM) $(SIMFLAGS) ./$<
+
+run-test_fail.tst: test_fail.tst
+	! $(SIM) $(SIMFLAGS) ./$<
+
+debug-%.tst: %.tst
+	$(SIM) $(SIMDEBUG) $(SIMFLAGS) ./$<
+
+clean:
+	$(RM) -fr $(TESTCASES) $(CRT)
diff --git a/tests/tcg/xtensa/crt.S b/tests/tcg/xtensa/crt.S
new file mode 100644
index 0000000..d9846ac
--- /dev/null
+++ b/tests/tcg/xtensa/crt.S
@@ -0,0 +1,24 @@
+.section .init
+    j       1f
+.section .init.text
+1:
+    movi    a2, _start
+    jx      a2
+
+.text
+.global _start
+_start:
+    movi    a2, 1
+    wsr     a2, windowstart
+    movi    a2, 0
+    wsr     a2, windowbase
+    movi    a1, _fstack
+    movi    a2, 0x4000f
+    wsr     a2, ps
+    isync
+
+    call0   main
+
+    mov     a3, a2
+    movi    a2, 1
+    simcall
diff --git a/tests/tcg/xtensa/linker.ld b/tests/tcg/xtensa/linker.ld
new file mode 100644
index 0000000..4d0b307
--- /dev/null
+++ b/tests/tcg/xtensa/linker.ld
@@ -0,0 +1,112 @@
+OUTPUT_FORMAT("elf32-xtensa-le")
+ENTRY(_start)
+
+__DYNAMIC = 0;
+
+MEMORY {
+	ram : ORIGIN = 0xd0000000, LENGTH = 0x08000000  /* 128M */
+	rom : ORIGIN = 0xfe000000, LENGTH = 0x00001000  /* 4k */
+}
+
+SECTIONS
+{
+    .init :
+    {
+        *(.init)
+		*(.init.*)
+    } > rom
+
+    .vector :
+    {
+    . = 0x00000000;
+        *(.vector.window_overflow_4)
+        *(.vector.window_overflow_4.*)
+    . = 0x00000040;
+        *(.vector.window_underflow_4)
+        *(.vector.window_underflow_4.*)
+    . = 0x00000080;
+        *(.vector.window_overflow_8)
+        *(.vector.window_overflow_8.*)
+    . = 0x000000c0;
+        *(.vector.window_underflow_8)
+        *(.vector.window_underflow_8.*)
+    . = 0x00000100;
+        *(.vector.window_overflow_12)
+        *(.vector.window_overflow_12.*)
+    . = 0x00000140;
+        *(.vector.window_underflow_12)
+        *(.vector.window_underflow_12.*)
+
+    . = 0x00000180;
+        *(.vector.level2)
+        *(.vector.level2.*)
+    . = 0x000001c0;
+        *(.vector.level3)
+        *(.vector.level3.*)
+    . = 0x00000200;
+        *(.vector.level4)
+        *(.vector.level4.*)
+    . = 0x00000240;
+        *(.vector.level5)
+        *(.vector.level5.*)
+    . = 0x00000280;
+        *(.vector.level6)
+        *(.vector.level6.*)
+    . = 0x000002c0;
+        *(.vector.level7)
+        *(.vector.level7.*)
+
+    . = 0x00000300;
+        *(.vector.kernel)
+        *(.vector.kernel.*)
+    . = 0x00000340;
+        *(.vector.user)
+        *(.vector.user.*)
+    . = 0x000003c0;
+        *(.vector.double)
+        *(.vector.double.*)
+    } > ram
+
+	.text :
+	{
+		_ftext = .;
+		*(.text .stub .text.* .gnu.linkonce.t.* .literal .literal.*)
+		_etext = .;
+	} > ram
+
+	.rodata :
+	{
+		. = ALIGN(4);
+		_frodata = .;
+		*(.rodata .rodata.* .gnu.linkonce.r.*)
+		*(.rodata1)
+		_erodata = .;
+	} > ram
+
+	.data :
+	{
+		. = ALIGN(4);
+		_fdata = .;
+		*(.data .data.* .gnu.linkonce.d.*)
+		*(.data1)
+		_gp = ALIGN(16);
+		*(.sdata .sdata.* .gnu.linkonce.s.*)
+		_edata = .;
+	} > ram
+
+	.bss :
+	{
+		. = ALIGN(4);
+		_fbss = .;
+		*(.dynsbss)
+		*(.sbss .sbss.* .gnu.linkonce.sb.*)
+		*(.scommon)
+		*(.dynbss)
+		*(.bss .bss.* .gnu.linkonce.b.*)
+		*(COMMON)
+		_ebss = .;
+		_end = .;
+	} > ram
+}
+
+PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4);
diff --git a/tests/tcg/xtensa/macros.inc b/tests/tcg/xtensa/macros.inc
new file mode 100644
index 0000000..2d4515e
--- /dev/null
+++ b/tests/tcg/xtensa/macros.inc
@@ -0,0 +1,68 @@
+.macro test_suite name
+.data
+status: .word result
+result: .space 20
+.text
+.global main
+.align 4
+main:
+.endm
+
+.macro reset_ps
+    movi    a2, 0x4000f
+    wsr     a2, ps
+    isync
+.endm
+
+.macro test_suite_end
+    reset_ps
+    movi    a0, status
+    l32i    a2, a0, 0
+    movi    a0, result
+    sub     a2, a2, a0
+    movi    a3, 0
+    loopnez a2, 1f
+    l8ui    a2, a0, 0
+    or      a3, a3, a2
+    addi    a0, a0, 1
+1:
+    exit
+.endm
+
+.macro test name
+.endm
+
+.macro test_end
+99:
+    reset_ps
+    movi    a2, status
+    l32i    a3, a2, 0
+    addi    a3, a3, 1
+    s32i    a3, a2, 0
+.endm
+
+.macro exit
+    movi    a2, 1
+    simcall
+.endm
+
+.macro test_fail
+    movi    a2, status
+    l32i    a2, a2, 0
+    movi    a3, 1
+    s8i     a3, a2, 0
+    j       99f
+.endm
+
+.macro assert cond, arg1, arg2
+    b\cond  \arg1, \arg2, 90f
+    test_fail
+90:
+    nop
+.endm
+
+.macro set_vector vector, addr
+    movi    a2, handler_\vector
+    movi    a3, \addr
+    s32i    a3, a2, 0
+.endm
diff --git a/tests/tcg/xtensa/test_b.S b/tests/tcg/xtensa/test_b.S
new file mode 100644
index 0000000..6cbe5f1
--- /dev/null
+++ b/tests/tcg/xtensa/test_b.S
@@ -0,0 +1,221 @@
+.include "macros.inc"
+
+test_suite b
+
+test bnone
+    movi    a2, 0xa5a5ff00
+    movi    a3, 0x5a5a00ff
+    bnone   a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 0xa5a5ff01
+    bnone   a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test beq
+    movi    a2, 0
+    movi    a3, 0
+    beq     a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 1
+    beq     a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test blt
+    movi    a2, 6
+    movi    a3, 7
+    blt     a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 0xffffffff
+    blt     a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 7
+    blt     a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bltu
+    movi    a2, 6
+    movi    a3, 7
+    bltu    a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 7
+    bltu    a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+    movi    a2, 0xffffffff
+    bltu    a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test ball
+    movi    a2, 0xa5a5ffa5
+    movi    a3, 0xa5a5ff00
+    ball    a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 0xa5a5a5a5
+    ball    a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bbc
+    movi    a2, 0xfffffffd
+    movi    a3, 0xffffff01
+    bbc     a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 8
+    movi    a3, 0xffffff03
+    bbc     a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bbci
+    movi    a2, 0xfffdffff
+    bbci    a2, 17, 1f
+    test_fail
+1:
+    movi    a2, 0x00020000
+    bbci    a2, 17, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bany
+    movi    a2, 0xa5a5ff01
+    movi    a3, 0x5a5a00ff
+    bany    a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 0xa5a5ff00
+    bany    a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bne
+    movi    a2, 1
+    movi    a3, 0
+    bne     a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 0
+    bne     a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bge
+    movi    a2, 7
+    movi    a3, 7
+    bge     a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 6
+    bge     a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+    movi    a2, 0xffffffff
+    bge     a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bgeu
+    movi    a2, 7
+    movi    a3, 7
+    bgeu    a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 0xffffffff
+    bgeu    a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 6
+    bgeu    a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bnall
+    movi    a2, 0xa5a5a5a5
+    movi    a3, 0xa5a5ff00
+    bnall   a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 0xa5a5ffa5
+    bnall   a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bbs
+    movi    a2, 8
+    movi    a3, 0xffffff03
+    bbs     a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 0xfffffffd
+    movi    a3, 0xffffff01
+    bbs     a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bbsi
+    movi    a2, 0x00020000
+    bbsi    a2, 17, 1f
+    test_fail
+1:
+    movi    a2, 0xfffdffff
+    bbsi    a2, 17, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_bi.S b/tests/tcg/xtensa/test_bi.S
new file mode 100644
index 0000000..6a5f1df
--- /dev/null
+++ b/tests/tcg/xtensa/test_bi.S
@@ -0,0 +1,103 @@
+.include "macros.inc"
+
+test_suite bi
+
+test beqi
+    movi    a2, 7
+    beqi    a2, 7, 1f
+    test_fail
+1:
+    movi    a2, 1
+    beqi    a2, 7, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bnei
+    movi    a2, 1
+    bnei    a2, 7, 1f
+    test_fail
+1:
+    movi    a2, 7
+    bnei    a2, 7, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test blti
+    movi    a2, 6
+    blti    a2, 7, 1f
+    test_fail
+1:
+    movi    a2, 0xffffffff
+    blti    a2, 7, 1f
+    test_fail
+1:
+    movi    a2, 7
+    blti    a2, 7, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bgei
+    movi    a2, 7
+    bgei    a2, 7, 1f
+    test_fail
+1:
+    movi    a2, 6
+    bgei    a2, 7, 1f
+    j       2f
+1:
+    test_fail
+2:
+    movi    a2, 0xffffffff
+    bgei    a2, 7, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bltui
+    movi    a2, 6
+    bltui   a2, 7, 1f
+    test_fail
+1:
+    movi    a2, 7
+    bltui   a2, 7, 1f
+    j       2f
+1:
+    test_fail
+2:
+    movi    a2, 0xffffffff
+    bltui   a2, 7, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bgeui
+    movi    a2, 7
+    bgeui   a2, 7, 1f
+    test_fail
+1:
+    movi    a2, 0xffffffff
+    bgeui   a2, 7, 1f
+    test_fail
+1:
+    movi    a2, 6
+    bgeui   a2, 7, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_boolean.S b/tests/tcg/xtensa/test_boolean.S
new file mode 100644
index 0000000..50e6d2c
--- /dev/null
+++ b/tests/tcg/xtensa/test_boolean.S
@@ -0,0 +1,23 @@
+.include "macros.inc"
+
+test_suite boolean
+
+test all4
+    movi    a2, 0xfec0
+    wsr     a2, br
+    all4    b0, b0
+    rsr     a3, br
+    assert  eq, a2, a3
+    all4    b0, b4
+    rsr     a3, br
+    assert  eq, a2, a3
+    all4    b0, b8
+    rsr     a3, br
+    assert  eq, a2, a3
+    all4    b0, b12
+    rsr     a3, br
+    addi    a2, a2, 1
+    assert  eq, a2, a3
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_bz.S b/tests/tcg/xtensa/test_bz.S
new file mode 100644
index 0000000..f9ba6e2
--- /dev/null
+++ b/tests/tcg/xtensa/test_bz.S
@@ -0,0 +1,57 @@
+.include "macros.inc"
+
+test_suite bz
+
+test beqz
+    movi    a2, 0
+    _beqz   a2, 1f
+    test_fail
+1:
+    movi    a2, 1
+    _beqz   a2, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bnez
+    movi    a2, 1
+    _bnez   a2, 1f
+    test_fail
+1:
+    movi    a2, 0
+    _bnez   a2, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bltz
+    movi    a2, 0xffffffff
+    bltz    a2, 1f
+    test_fail
+1:
+    movi    a2, 0
+    bltz    a2, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bgez
+    movi    a2, 0
+    bgez    a2, 1f
+    test_fail
+1:
+    movi    a2, 0xffffffff
+    bgez    a2, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_clamps.S b/tests/tcg/xtensa/test_clamps.S
new file mode 100644
index 0000000..c186cc9
--- /dev/null
+++ b/tests/tcg/xtensa/test_clamps.S
@@ -0,0 +1,42 @@
+.include "macros.inc"
+
+test_suite clamps
+
+test clamps
+    movi    a2, 0
+    movi    a3, 0
+    clamps  a4, a2, 7
+    assert  eq, a3, a4
+
+    movi    a2, 0x7f
+    movi    a3, 0x7f
+    clamps  a4, a2, 7
+    assert  eq, a3, a4
+
+    movi    a2, 0xffffff80
+    movi    a3, 0xffffff80
+    clamps  a4, a2, 7
+    assert  eq, a3, a4
+
+    movi    a2, 0x80
+    movi    a3, 0x7f
+    clamps  a2, a2, 7
+    assert  eq, a3, a2
+
+    movi    a2, 0xffffff7f
+    movi    a3, 0xffffff80
+    clamps  a2, a2, 7
+    assert  eq, a3, a2
+
+    movi    a2, 0x7fffffff
+    movi    a3, 0x7f
+    clamps  a2, a2, 7
+    assert  eq, a3, a2
+
+    movi    a2, 0x80000000
+    movi    a3, 0xffffff80
+    clamps  a2, a2, 7
+    assert  eq, a3, a2
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_fail.S b/tests/tcg/xtensa/test_fail.S
new file mode 100644
index 0000000..e8d1b42
--- /dev/null
+++ b/tests/tcg/xtensa/test_fail.S
@@ -0,0 +1,9 @@
+.include "macros.inc"
+
+test_suite fail
+
+test fail
+    test_fail
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_interrupt.S b/tests/tcg/xtensa/test_interrupt.S
new file mode 100644
index 0000000..68b3ee1
--- /dev/null
+++ b/tests/tcg/xtensa/test_interrupt.S
@@ -0,0 +1,194 @@
+.include "macros.inc"
+
+test_suite interrupt
+
+.macro clear_interrupts
+    movi    a2, 0
+    wsr     a2, intenable
+    wsr     a2, ccompare0
+    wsr     a2, ccompare1
+    wsr     a2, ccompare2
+    esync
+    rsr     a2, interrupt
+    wsr     a2, intclear
+
+    esync
+    rsr     a2, interrupt
+    assert  eqi, a2, 0
+.endm
+
+.macro check_l1
+    rsr     a2, ps
+    movi    a3, 0x1f        /* EXCM | INTMASK */
+    and     a2, a2, a3
+    assert  eqi, a2, 0x10   /* only EXCM is set for level-1 interrupt */
+    rsr     a2, exccause
+    assert  eqi, a2, 4
+.endm
+
+test rsil
+    clear_interrupts
+
+    rsr     a2, ps
+    rsil    a3, 7
+    rsr     a4, ps
+    assert  eq, a2, a3
+    movi    a2, 0xf
+    and     a2, a4, a2
+    assert  eqi, a2, 7
+    xor     a3, a3, a4
+    movi    a2, 0xfffffff0
+    and     a2, a3, a2
+    assert  eqi, a2, 0
+test_end
+
+test soft_disabled
+    set_vector kernel, 1f
+    clear_interrupts
+
+    movi    a2, 0x80
+    wsr     a2, intset
+    esync
+    rsr     a3, interrupt
+    assert  eq, a2, a3
+    wsr     a2, intclear
+    esync
+    rsr     a3, interrupt
+    assert  eqi, a3, 0
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test soft_intenable
+    set_vector kernel, 1f
+    clear_interrupts
+
+    movi    a2, 0x80
+    wsr     a2, intset
+    esync
+    rsr     a3, interrupt
+    assert  eq, a2, a3
+    rsil    a3, 0
+    wsr     a2, intenable
+    esync
+    test_fail
+1:
+    check_l1
+test_end
+
+test soft_rsil
+    set_vector kernel, 1f
+    clear_interrupts
+
+    movi    a2, 0x80
+    wsr     a2, intset
+    esync
+    rsr     a3, interrupt
+    assert  eq, a2, a3
+    wsr     a2, intenable
+    rsil    a3, 0
+    esync
+    test_fail
+1:
+    check_l1
+test_end
+
+test soft_waiti
+    set_vector kernel, 1f
+    clear_interrupts
+
+    movi    a2, 0x80
+    wsr     a2, intset
+    esync
+    rsr     a3, interrupt
+    assert  eq, a2, a3
+    wsr     a2, intenable
+    waiti   0
+    test_fail
+1:
+    check_l1
+test_end
+
+test soft_user
+    set_vector kernel, 1f
+    set_vector user, 2f
+    clear_interrupts
+
+    movi    a2, 0x80
+    wsr     a2, intset
+    esync
+    rsr     a3, interrupt
+    assert  eq, a2, a3
+    wsr     a2, intenable
+
+    rsr     a2, ps
+    movi    a3, 0x20
+    or      a2, a2, a3
+    wsr     a2, ps
+    waiti   0
+1:
+    test_fail
+2:
+    check_l1
+test_end
+
+test soft_priority
+    set_vector kernel, 1f
+    set_vector level3, 2f
+    clear_interrupts
+
+    movi    a2, 0x880
+    wsr     a2, intenable
+    rsil    a3, 0
+    esync
+    wsr     a2, intset
+    esync
+1:
+    test_fail
+2:
+    rsr     a2, ps
+    movi    a3, 0x1f        /* EXCM | INTMASK */
+    and     a2, a2, a3
+    movi    a3, 0x13
+    assert  eq, a2, a3      /* EXCM and INTMASK are set
+                               for high-priority interrupt */
+test_end
+
+test eps_epc_rfi
+    set_vector level3, 3f
+    clear_interrupts
+    reset_ps
+
+    movi    a2, 0x880
+    wsr     a2, intenable
+    rsil    a3, 0
+    rsr     a3, ps
+    esync
+    wsr     a2, intset
+1:
+    esync
+2:
+    test_fail
+3:
+    rsr     a2, eps3
+    assert  eq, a2, a3
+    rsr     a2, epc3
+    movi    a3, 1b
+    assert  ge, a2, a3
+    movi    a3, 2b
+    assert  ge, a3, a2
+    movi    a2, 4f
+    wsr     a2, epc3
+    movi    a2, 0x40003
+    wsr     a2, eps3
+    rfi     3
+    test_fail
+4:
+    rsr     a2, ps
+    movi    a3, 0x40003
+    assert  eq, a2, a3
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_loop.S b/tests/tcg/xtensa/test_loop.S
new file mode 100644
index 0000000..a5ea933
--- /dev/null
+++ b/tests/tcg/xtensa/test_loop.S
@@ -0,0 +1,77 @@
+.include "macros.inc"
+
+test_suite loop
+
+test loop
+    movi    a2, 0
+    movi    a3, 5
+    loop    a3, 1f
+    addi    a2, a2, 1
+1:
+    assert  eqi, a2, 5
+test_end
+
+test loop0
+    movi    a2, 0
+    loop    a2, 1f
+    rsr     a2, lcount
+    assert  eqi, a2, -1
+    j       1f
+1:
+test_end
+
+test loop_jump
+    movi    a2, 0
+    movi    a3, 5
+    loop    a3, 1f
+    addi    a2, a2, 1
+    j       1f
+1:
+    assert  eqi, a2, 1
+test_end
+
+test loop_branch
+    movi    a2, 0
+    movi    a3, 5
+    loop    a3, 1f
+    addi    a2, a2, 1
+    beqi    a2, 3, 1f
+1:
+    assert  eqi, a2, 3
+test_end
+
+test loop_manual
+    movi    a2, 0
+    movi    a3, 5
+    movi    a4, 1f
+    movi    a5, 2f
+    wsr     a3, lcount
+    wsr     a4, lbeg
+    wsr     a5, lend
+    isync
+    j       1f
+.align 4
+1:
+    addi    a2, a2, 1
+2:
+    assert  eqi, a2, 6
+test_end
+
+test loop_excm
+    movi    a2, 0
+    movi    a3, 5
+    rsr     a4, ps
+    movi    a5, 0x10
+    or      a4, a4, a5
+    wsr     a4, ps
+    isync
+    loop    a3, 1f
+    addi    a2, a2, 1
+1:
+    xor     a4, a4, a5
+    isync
+    wsr     a4, ps
+    assert  eqi, a2, 1
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_mac16.S b/tests/tcg/xtensa/test_mac16.S
new file mode 100644
index 0000000..5ddd160
--- /dev/null
+++ b/tests/tcg/xtensa/test_mac16.S
@@ -0,0 +1,243 @@
+.include "macros.inc"
+
+test_suite mac16
+
+#define ext16(v) (((v) & 0xffff) | (((v) & 0x8000) * 0x1ffffffe))
+#define mul16(a, b) ((ext16(a) * ext16(b)))
+
+.macro assert_acc_value v
+    rsr     a4, ACCLO
+    movi    a5, (\v) & 0xffffffff
+    assert  eq, a4, a5
+    rsr     a4, ACCHI
+    movi    a5, (\v) >> 32
+    sext    a5, a5, 7
+    assert  eq, a4, a5
+.endm
+
+.macro init_reg sr, reg, val
+    .if (\sr)
+    movi    a4, \val
+    wsr     a4, \reg
+    .else
+    movi    \reg, \val
+    .endif
+.endm
+
+.macro test_mulxx mulop, comb, s, t, a, b
+    init_reg \comb & 2, \s, \a
+    init_reg \comb & 1, \t, \b
+
+    \mulop\().ll \s, \t
+    assert_acc_value mul16(\a, \b)
+
+    \mulop\().lh \s, \t
+    assert_acc_value mul16(\a, (\b >> 16))
+
+    \mulop\().hl \s, \t
+    assert_acc_value mul16((\a >> 16), \b)
+
+    \mulop\().hh \s, \t
+    assert_acc_value mul16((\a >> 16), (\b >> 16))
+.endm
+
+test mul_aa
+    test_mulxx mul.aa, 0, a2, a3, 0xf7315a5a, 0xa5a5137f
+test_end
+
+test mul_ad
+    test_mulxx mul.ad, 1, a2, m2, 0xf7315a5a, 0xa5a5137f
+test_end
+
+test mul_da
+    test_mulxx mul.da, 2, m1, a3, 0xf7315a5a, 0xa5a5137f
+test_end
+
+test mul_dd
+    test_mulxx mul.dd, 3, m0, m3, 0xf7315a5a, 0xa5a5137f
+test_end
+
+
+.macro init_acc iv
+    movi    a4, (\iv) & 0xffffffff
+    wsr     a4, ACCLO
+    movi    a4, (\iv) >> 32
+    wsr     a4, ACCHI
+.endm
+
+.macro test_mulxxx mulop, comb, s, t, a, b, iv, op
+    init_reg \comb & 2, \s, \a
+    init_reg \comb & 1, \t, \b
+
+    init_acc \iv
+    \mulop\().ll \s, \t
+    assert_acc_value (\iv \op mul16(\a, \b))
+
+    init_acc \iv
+    \mulop\().lh \s, \t
+    assert_acc_value (\iv \op mul16(\a, (\b >> 16)))
+
+    init_acc \iv
+    \mulop\().hl \s, \t
+    assert_acc_value (\iv \op mul16((\a >> 16), \b))
+
+    init_acc \iv
+    \mulop\().hh \s, \t
+    assert_acc_value (\iv \op mul16((\a >> 16), (\b >> 16)))
+.endm
+
+
+test mula_aa
+    test_mulxxx mula.aa, 0, a2, a3, 0xf7315a5a, 0xa5a5137f, 0xfff73155aa, +
+test_end
+
+test mula_ad
+    test_mulxxx mula.ad, 1, a2, m2, 0xf7315a5a, 0xa5a5137f, 0xfff73155aa, +
+test_end
+
+test mula_da
+    test_mulxxx mula.da, 2, m1, a3, 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+test_end
+
+test mula_dd
+    test_mulxxx mula.dd, 3, m0, m3, 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+test_end
+
+
+test muls_aa
+    test_mulxxx muls.aa, 0, a2, a3, 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, -
+test_end
+
+test muls_ad
+    test_mulxxx muls.ad, 1, a2, m2, 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, -
+test_end
+
+test muls_da
+    test_mulxxx muls.da, 2, m1, a3, 0xf7315a5a, 0xa5a5137f, 0xfff73155aa, -
+test_end
+
+test muls_dd
+    test_mulxxx muls.dd, 3, m0, m3, 0xf7315a5a, 0xa5a5137f, 0xfff73155aa, -
+test_end
+
+test ldinc
+    movi    a2, 1f - 4
+    ldinc   m0, a2
+    movi    a3, 1f
+    assert  eq, a2, a3
+    rsr     a3, m0
+    movi    a4, 0x55aa137f
+    assert  eq, a3, a4
+    ldinc   m1, a2
+    movi    a3, 1f + 4
+    assert  eq, a2, a3
+    rsr     a3, m1
+    movi    a4, 0x12345678
+    assert  eq, a3, a4
+
+.data
+1:  .word 0x55aa137f, 0x12345678, 0x137fa5a5
+.text
+test_end
+
+test lddec
+    movi    a2, 1f
+    lddec   m2, a2
+    movi    a3, 1f - 4
+    assert  eq, a2, a3
+    rsr     a3, m2
+    movi    a4, 0x12345678
+    assert  eq, a3, a4
+    lddec   m3, a2
+    movi    a3, 1f - 8
+    assert  eq, a2, a3
+    rsr     a3, m3
+    movi    a4, 0x55aa137f
+    assert  eq, a3, a4
+.data
+    .word 0x55aa137f, 0x12345678
+1:
+.text
+test_end
+
+
+.macro test_mulxxx_ld mulop, ldop, comb, w, x, s, t, a, b, iv, op
+    init_reg \comb & 2, \s, \a
+    init_reg \comb & 1, \t, \b
+
+    init_acc \iv
+    \mulop\().ll.\ldop \w, \x, \s, \t
+    assert_acc_value (\iv \op mul16(\a, \b))
+
+    init_acc \iv
+    \mulop\().lh.\ldop \w, \x, \s, \t
+    assert_acc_value (\iv \op mul16(\a, (\b >> 16)))
+
+    init_acc \iv
+    \mulop\().hl.\ldop \w, \x, \s, \t
+    assert_acc_value (\iv \op mul16((\a >> 16), \b))
+
+    init_acc \iv
+    \mulop\().hh.\ldop \w, \x, \s, \t
+    assert_acc_value (\iv \op mul16((\a >> 16), (\b >> 16)))
+.endm
+
+test mula_da_ldinc
+    movi    a2, 1f - 4
+    test_mulxxx_ld mula.da, ldinc, 2, m1, a2, m1, a3, \
+        0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+    movi    a3, 1f + 12
+    assert  eq, a2, a3
+    rsr     a2, m1
+    movi    a3, 0x12345678
+    assert  eq, a2, a3
+.data
+1:  .word 0xf7315a5a, 0xf7315a5a, 0xf7315a5a, 0x12345678
+.text
+test_end
+
+test mula_dd_ldinc
+    movi    a2, 1f - 4
+    test_mulxxx_ld mula.dd, ldinc, 3, m2, a2, m1, m2, \
+        0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+    movi    a3, 1f + 12
+    assert  eq, a2, a3
+    rsr     a2, m2
+    movi    a3, 0x12345678
+    assert  eq, a2, a3
+.data
+1:  .word 0xa5a5137f, 0xa5a5137f, 0xa5a5137f, 0x12345678
+.text
+test_end
+
+test mula_da_lddec
+    movi    a2, 1f
+    test_mulxxx_ld mula.da, lddec, 2, m1, a2, m1, a3, \
+        0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+    movi    a3, 1f - 16
+    assert  eq, a2, a3
+    rsr     a2, m1
+    movi    a3, 0x12345678
+    assert  eq, a2, a3
+.data
+    .word 0x12345678, 0xf7315a5a, 0xf7315a5a, 0xf7315a5a
+1:
+.text
+test_end
+
+test mula_dd_lddec
+    movi    a2, 1f
+    test_mulxxx_ld mula.dd, lddec, 3, m2, a2, m1, m2, \
+        0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+    movi    a3, 1f - 16
+    assert  eq, a2, a3
+    rsr     a2, m2
+    movi    a3, 0x12345678
+    assert  eq, a2, a3
+.data
+    .word 0x12345678, 0xa5a5137f, 0xa5a5137f, 0xa5a5137f
+1:
+.text
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_max.S b/tests/tcg/xtensa/test_max.S
new file mode 100644
index 0000000..2534c9d
--- /dev/null
+++ b/tests/tcg/xtensa/test_max.S
@@ -0,0 +1,81 @@
+.include "macros.inc"
+
+test_suite max
+
+test max
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 1
+    max     a5, a2, a3
+    assert  eq, a5, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 1
+    max     a5, a2, a3
+    assert  eq, a5, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 1
+    max     a2, a2, a3
+    assert  eq, a2, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 1
+    max     a3, a2, a3
+    assert  eq, a3, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 1
+    max     a2, a2, a3
+    assert  eq, a2, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 1
+    max     a3, a2, a3
+    assert  eq, a3, a4
+test_end
+
+test maxu
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 0xffffffff
+    maxu    a5, a2, a3
+    assert  eq, a5, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 0xffffffff
+    maxu    a5, a2, a3
+    assert  eq, a5, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 0xffffffff
+    maxu    a2, a2, a3
+    assert  eq, a2, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 0xffffffff
+    maxu    a3, a2, a3
+    assert  eq, a3, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 0xffffffff
+    maxu    a2, a2, a3
+    assert  eq, a2, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 0xffffffff
+    maxu    a3, a2, a3
+    assert  eq, a3, a4
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_min.S b/tests/tcg/xtensa/test_min.S
new file mode 100644
index 0000000..6d9ddeb
--- /dev/null
+++ b/tests/tcg/xtensa/test_min.S
@@ -0,0 +1,81 @@
+.include "macros.inc"
+
+test_suite min
+
+test min
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 0xffffffff
+    min     a5, a2, a3
+    assert  eq, a5, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 0xffffffff
+    min     a5, a2, a3
+    assert  eq, a5, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 0xffffffff
+    min     a2, a2, a3
+    assert  eq, a2, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 0xffffffff
+    min     a3, a2, a3
+    assert  eq, a3, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 0xffffffff
+    min     a2, a2, a3
+    assert  eq, a2, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 0xffffffff
+    min     a3, a2, a3
+    assert  eq, a3, a4
+test_end
+
+test minu
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 1
+    minu    a5, a2, a3
+    assert  eq, a5, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 1
+    minu    a5, a2, a3
+    assert  eq, a5, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 1
+    minu    a2, a2, a3
+    assert  eq, a2, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 1
+    minu    a3, a2, a3
+    assert  eq, a3, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 1
+    minu    a2, a2, a3
+    assert  eq, a2, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 1
+    minu    a3, a2, a3
+    assert  eq, a3, a4
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_mmu.S b/tests/tcg/xtensa/test_mmu.S
new file mode 100644
index 0000000..52d5774
--- /dev/null
+++ b/tests/tcg/xtensa/test_mmu.S
@@ -0,0 +1,318 @@
+.include "macros.inc"
+
+test_suite mmu
+
+.purgem test
+
+.macro test name
+    movi    a2, 0x00000004
+    idtlb   a2
+    movi    a2, 0x00100004
+    idtlb   a2
+    movi    a2, 0x00200004
+    idtlb   a2
+    movi    a2, 0x00300004
+    idtlb   a2
+    movi    a2, 0x00000007
+    idtlb   a2
+.endm
+
+test tlb_group
+    movi    a2, 0x04000002 /* PPN */
+    movi    a3, 0x01200004 /* VPN */
+    wdtlb   a2, a3
+    witlb   a2, a3
+    movi    a3, 0x00200004
+    rdtlb0  a1, a3
+    ritlb0  a2, a3
+    movi    a3, 0x01000001
+    assert  eq, a1, a3
+    assert  eq, a2, a3
+    movi    a3, 0x00200004
+    rdtlb1  a1, a3
+    ritlb1  a2, a3
+    movi    a3, 0x04000002
+    assert  eq, a1, a3
+    assert  eq, a2, a3
+    movi    a3, 0x01234567
+    pdtlb   a1, a3
+    pitlb   a2, a3
+    movi    a3, 0x01234014
+    assert  eq, a1, a3
+    movi    a3, 0x0123400c
+    assert  eq, a2, a3
+    movi    a3, 0x00200004
+    idtlb   a3
+    iitlb   a3
+    movi    a3, 0x01234567
+    pdtlb   a1, a3
+    pitlb   a2, a3
+    movi    a3, 0x00000010
+    and     a1, a1, a3
+    assert  eqi, a1, 0
+    movi    a3, 0x00000008
+    and     a2, a2, a3
+    assert  eqi, a2, 0
+test_end
+
+test itlb_miss
+    set_vector kernel, 1f
+
+    movi    a3, 0x00100000
+    jx      a3
+    test_fail
+1:
+    rsr     a2, excvaddr
+    assert  eq, a2, a3
+    rsr     a2, exccause
+    movi    a3, 16
+    assert  eq, a2, a3
+test_end
+
+test dtlb_miss
+    set_vector kernel, 1f
+
+    movi    a3, 0x00100000
+    l8ui    a2, a3, 0
+    test_fail
+1:
+    rsr     a2, excvaddr
+    assert  eq, a2, a3
+    rsr     a2, exccause
+    movi    a3, 24
+    assert  eq, a2, a3
+test_end
+
+test itlb_multi_hit
+    set_vector kernel, 1f
+
+    movi    a2, 0x04000002 /* PPN */
+    movi    a3, 0xf0000004 /* VPN */
+    witlb   a2, a3
+    movi    a3, 0xf0000000
+    pitlb   a2, a3
+    test_fail
+1:
+    rsr     a2, exccause
+    movi    a3, 17
+    assert  eq, a2, a3
+test_end
+
+test dtlb_multi_hit
+    set_vector kernel, 1f
+
+    movi    a2, 0x04000002 /* PPN */
+    movi    a3, 0x01200004 /* VPN */
+    wdtlb   a2, a3
+    movi    a3, 0x01200007 /* VPN */
+    wdtlb   a2, a3
+    movi    a3, 0x01200000
+    pdtlb   a2, a3
+    test_fail
+1:
+    rsr     a2, exccause
+    movi    a3, 25
+    assert  eq, a2, a3
+test_end
+
+test inst_fetch_privilege
+    set_vector kernel, 3f
+
+    movi    a2, 0x4004f
+    wsr     a2, ps
+1:
+    isync
+    nop
+2:
+    test_fail
+3:
+    movi    a1, 1b
+    rsr     a2, excvaddr
+    rsr     a3, epc1
+    assert  ge, a2, a1
+    assert  ge, a3, a1
+    movi    a1, 2b
+    assert  lt, a2, a1
+    assert  lt, a3, a1
+    rsr     a2, exccause
+    movi    a3, 18
+    assert  eq, a2, a3
+    rsr     a2, ps
+    movi    a3, 0x4005f
+    assert  eq, a2, a3
+test_end
+
+test load_store_privilege
+    set_vector kernel, 2f
+
+    movi    a3, 10f
+    pitlb   a3, a3
+    ritlb1  a2, a3
+    movi    a1, 0x10
+    or      a2, a2, a1
+    movi    a1, 0x000ff000
+    and     a3, a3, a1
+    movi    a1, 4
+    or      a3, a3, a1
+    witlb   a2, a3
+    movi    a3, 10f
+    movi    a1, 0x000fffff
+    and     a1, a3, a1
+
+    movi    a2, 0x04000003 /* PPN */
+    movi    a3, 0x01200004 /* VPN */
+    wdtlb   a2, a3
+    movi    a3, 0x01200001
+    movi    a2, 0x4004f
+    jx      a1
+10:
+    wsr     a2, ps
+    isync
+1:
+    l8ui    a2, a3, 0
+    test_fail
+2:
+    rsr     a2, excvaddr
+    assert  eq, a2, a3
+    rsr     a2, epc1
+    movi    a3, 1b
+    movi    a1, 0x000fffff
+    and     a3, a3, a1
+    assert  eq, a2, a3
+    rsr     a2, exccause
+    movi    a3, 26
+    assert  eq, a2, a3
+    rsr     a2, ps
+    movi    a3, 0x4005f
+    assert  eq, a2, a3
+test_end
+
+test cring_load_store_privilege
+    set_vector kernel, 0
+    set_vector double, 2f
+
+    movi    a2, 0x04000003 /* PPN */
+    movi    a3, 0x01200004 /* VPN */
+    wdtlb   a2, a3
+    movi    a3, 0x01200004
+    movi    a2, 0x4005f    /* ring 1 + excm => cring == 0 */
+    wsr     a2, ps
+    isync
+    l8ui    a2, a3, 0      /* cring used */
+1:
+    l32e    a2, a3, -4     /* ring used */
+    test_fail
+2:
+    rsr     a2, excvaddr
+    addi    a2, a2, 4
+    assert  eq, a2, a3
+    rsr     a2, depc
+    movi    a3, 1b
+    assert  eq, a2, a3
+    rsr     a2, exccause
+    movi    a3, 26
+    assert  eq, a2, a3
+    rsr     a2, ps
+    movi    a3, 0x4005f
+    assert  eq, a2, a3
+test_end
+
+test inst_fetch_prohibited
+    set_vector kernel, 2f
+
+    movi    a3, 10f
+    pitlb   a3, a3
+    ritlb1  a2, a3
+    movi    a1, 0xfffff000
+    and     a2, a2, a1
+    movi    a1, 0x4
+    or      a2, a2, a1
+    movi    a1, 0x000ff000
+    and     a3, a3, a1
+    movi    a1, 4
+    or      a3, a3, a1
+    witlb   a2, a3
+    movi    a3, 10f
+    movi    a1, 0x000fffff
+    and     a1, a3, a1
+    jx      a1
+    .align  4
+10:
+    nop
+    test_fail
+2:
+    rsr     a2, excvaddr
+    assert  eq, a2, a1
+    rsr     a2, epc1
+    assert  eq, a2, a1
+    rsr     a2, exccause
+    movi    a3, 20
+    assert  eq, a2, a3
+test_end
+
+test load_prohibited
+    set_vector kernel, 2f
+
+    movi    a2, 0x0400000c /* PPN */
+    movi    a3, 0x01200004 /* VPN */
+    wdtlb   a2, a3
+    movi    a3, 0x01200002
+1:
+    l8ui    a2, a3, 0
+    test_fail
+2:
+    rsr     a2, excvaddr
+    assert  eq, a2, a3
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+    rsr     a2, exccause
+    movi    a3, 28
+    assert  eq, a2, a3
+test_end
+
+test store_prohibited
+    set_vector kernel, 2f
+
+    movi    a2, 0x04000001 /* PPN */
+    movi    a3, 0x01200004 /* VPN */
+    wdtlb   a2, a3
+    movi    a3, 0x01200003
+    l8ui    a2, a3, 0
+1:
+    s8i     a2, a3, 0
+    test_fail
+2:
+    rsr     a2, excvaddr
+    assert  eq, a2, a3
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+    rsr     a2, exccause
+    movi    a3, 29
+    assert  eq, a2, a3
+test_end
+
+test dtlb_autoload
+    set_vector kernel, 0
+
+    movi    a2, 0xd4000000
+    wsr     a2, ptevaddr
+    movi    a3, 0x00001013
+    s32i    a3, a2, 4
+    pdtlb   a2, a3
+    movi    a1, 0x10
+    and     a1, a1, a2
+    assert  eqi, a1, 0
+    l8ui    a1, a3, 0
+    pdtlb   a2, a3
+    movi    a1, 0xfffff010
+    and     a1, a1, a2
+    movi    a3, 0x00001010
+    assert  eq, a1, a3
+    movi    a1, 0xf
+    and     a1, a1, a2
+    assert  lti, a1, 4
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_mul16.S b/tests/tcg/xtensa/test_mul16.S
new file mode 100644
index 0000000..bf94376
--- /dev/null
+++ b/tests/tcg/xtensa/test_mul16.S
@@ -0,0 +1,83 @@
+.include "macros.inc"
+
+test_suite mul16
+
+test mul16u_pp
+    movi    a2, 0x137f5a5a
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x06e180a6
+    mul16u  a5, a2, a4
+    assert  eq, a5, a6
+    mul16u  a2, a2, a4
+    assert  eq, a2, a6
+    mul16u  a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test mul16u_np
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x0c9d6bdb
+    mul16u  a5, a2, a4
+    assert  eq, a5, a6
+    mul16u  a2, a2, a4
+    assert  eq, a2, a6
+    mul16u  a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test mul16u_nn
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5f731
+    movi    a6, 0x9ff1e795
+    mul16u  a5, a2, a4
+    assert  eq, a5, a6
+    mul16u  a2, a2, a4
+    assert  eq, a2, a6
+    mul16u  a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test mul16s_pp
+    movi    a2, 0x137f5a5a
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x06e180a6
+    mul16s  a5, a2, a4
+    assert  eq, a5, a6
+    mul16s  a2, a2, a4
+    assert  eq, a2, a6
+    mul16s  a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test mul16s_np
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xf91e6bdb
+    mul16s  a5, a2, a4
+    assert  eq, a5, a6
+    mul16s  a2, a2, a4
+    assert  eq, a2, a6
+    mul16s  a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test mul16s_nn
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5f731
+    movi    a6, 0x031be795
+    mul16s  a5, a2, a4
+    assert  eq, a5, a6
+    mul16s  a2, a2, a4
+    assert  eq, a2, a6
+    mul16s  a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_mul32.S b/tests/tcg/xtensa/test_mul32.S
new file mode 100644
index 0000000..fdaf573
--- /dev/null
+++ b/tests/tcg/xtensa/test_mul32.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+test_suite mul32
+
+test mull
+    movi    a2, 0x137f5a5a
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x5de480a6
+    mull    a5, a2, a4
+    assert  eq, a5, a6
+    mull    a2, a2, a4
+    assert  eq, a2, a6
+    mull    a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+/* unfortunately dc232b doesn't have muluh/mulsh*/
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_nsa.S b/tests/tcg/xtensa/test_nsa.S
new file mode 100644
index 0000000..a5fe5de
--- /dev/null
+++ b/tests/tcg/xtensa/test_nsa.S
@@ -0,0 +1,59 @@
+.include "macros.inc"
+
+test_suite nsa
+
+test nsa
+    movi    a2, 0
+    movi    a3, 31
+    nsa     a4, a2
+    assert  eq, a3, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 31
+    nsa     a4, a2
+    assert  eq, a3, a4
+
+    movi    a2, 1
+    movi    a3, 30
+    nsa     a2, a2
+    assert  eq, a3, a2
+
+    movi    a2, 0xfffffffe
+    movi    a3, 30
+    nsa     a2, a2
+    assert  eq, a3, a2
+
+    movi    a2, 0x5a5a5a5a
+    movi    a3, 0
+    nsa     a4, a2
+    assert  eq, a3, a4
+
+    movi    a2, 0xa5a5a5a5
+    movi    a3, 0
+    nsa     a4, a2
+    assert  eq, a3, a4
+test_end
+
+test nsau
+    movi    a2, 0
+    movi    a3, 32
+    nsau    a4, a2
+    assert  eq, a3, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 0
+    nsau    a4, a2
+    assert  eq, a3, a4
+
+    movi    a2, 1
+    movi    a3, 31
+    nsau    a2, a2
+    assert  eq, a3, a2
+
+    movi    a2, 0x5a5a5a5a
+    movi    a3, 1
+    nsau    a2, a2
+    assert  eq, a3, a2
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_pipeline.S b/tests/tcg/xtensa/test_pipeline.S
new file mode 100644
index 0000000..6be6085
--- /dev/null
+++ b/tests/tcg/xtensa/test_pipeline.S
@@ -0,0 +1,157 @@
+.include "macros.inc"
+
+.purgem test
+.macro test name
+    movi    a2, 1f
+    movi    a3, 99f
+0:
+    ipf     a2, 0
+    ipf     a2, 4
+    ipf     a2, 8
+    ipf     a2, 12
+    addi    a2, a2, 16
+    blt     a2, a3, 0b
+    j       1f
+    .align 4
+1:
+.endm
+
+test_suite pipeline
+
+test register_no_stall
+    rsr     a3, ccount
+    add     a5, a6, a6
+    add     a6, a5, a5
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 3
+test_end
+
+test register_stall
+    l32i    a5, a1, 0   /* data cache preload */
+    nop
+    rsr     a3, ccount
+    l32i    a5, a1, 0
+    add     a6, a5, a5  /* M-to-E interlock */
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 4
+test_end
+
+test j0_stall
+    rsr     a3, ccount
+    j       1f          /* E + 2-cycle penalty */
+1:
+    rsr     a4, ccount  /* E */
+    sub     a3, a4, a3
+    assert  eqi, a3, 4
+test_end
+
+test j1_stall
+    rsr     a3, ccount
+    j       1f
+    nop
+1:
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 4
+test_end
+
+test j5_stall
+    rsr     a3, ccount
+    j       1f
+    nop
+    nop
+    nop
+    nop
+    nop
+1:
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 4
+test_end
+
+test b_no_stall
+    movi    a5, 1
+    rsr     a3, ccount
+    beqi    a5, 2, 1f
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 2
+1:
+test_end
+
+test b1_stall
+    movi    a5, 1
+    rsr     a3, ccount
+    beqi    a5, 1, 1f
+    nop
+1:
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 4
+test_end
+
+test b5_stall
+    movi    a5, 1
+    rsr     a3, ccount
+    beqi    a5, 1, 1f
+    nop
+    nop
+    nop
+    nop
+    nop
+1:
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 4
+test_end
+
+/* PS *SYNC */
+
+test ps_dsync
+    rsr     a5, ps
+    isync
+    rsr     a3, ccount
+    wsr     a5, ps
+    dsync
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 5
+test_end
+
+test ps_esync
+    rsr     a5, ps
+    isync
+    rsr     a3, ccount
+    wsr     a5, ps
+    esync
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 5
+test_end
+
+test ps_rsync
+    rsr     a5, ps
+    isync
+    rsr     a3, ccount
+    wsr     a5, ps
+    rsync
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 5
+test_end
+
+test ps_isync
+    rsr     a5, ps
+    isync
+    rsr     a3, ccount
+    wsr     a5, ps
+    isync
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    movi    a4, 9
+    assert  eq, a3, a4
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_quo.S b/tests/tcg/xtensa/test_quo.S
new file mode 100644
index 0000000..12debf1
--- /dev/null
+++ b/tests/tcg/xtensa/test_quo.S
@@ -0,0 +1,147 @@
+.include "macros.inc"
+
+test_suite quo
+
+test quou_pp
+    movi    a2, 0x5a5a137f
+    mov     a3, a2
+    movi    a4, 0x137f5a5a
+    movi    a6, 0x4
+    quou    a5, a2, a4
+    assert  eq, a5, a6
+    quou    a2, a2, a4
+    assert  eq, a2, a6
+    quou    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test quou_np
+    movi    a2, 0xa5a5137f
+    mov     a3, a2
+    movi    a4, 0x137f5a5a
+    movi    a6, 0x8
+    quou    a5, a2, a4
+    assert  eq, a5, a6
+    quou    a2, a2, a4
+    assert  eq, a2, a6
+    quou    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test quou_pn
+    movi    a2, 0x5a5a137f
+    mov     a3, a2
+    movi    a4, 0xf7315a5a
+    movi    a6, 0
+    quou    a5, a2, a4
+    assert  eq, a5, a6
+    quou    a2, a2, a4
+    assert  eq, a2, a6
+    quou    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test quou_nn
+    movi    a2, 0xf7315a5a
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x1
+    quou    a5, a2, a4
+    assert  eq, a5, a6
+    quou    a2, a2, a4
+    assert  eq, a2, a6
+    quou    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test quou_exc
+    set_vector kernel, 2f
+    movi    a2, 0xf7315a5a
+    movi    a4, 0x00000000
+1:
+    quou    a5, a2, a4
+    test_fail
+2:
+    rsr     a2, exccause
+    assert  eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+test_end
+
+test quos_pp
+    movi    a2, 0x5a5a137f
+    mov     a3, a2
+    movi    a4, 0x137f5a5a
+    movi    a6, 0x4
+    quos    a5, a2, a4
+    assert  eq, a5, a6
+    quos    a2, a2, a4
+    assert  eq, a2, a6
+    quos    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test quos_np
+    movi    a2, 0xa5a5137f
+    mov     a3, a2
+    movi    a4, 0x137f5a5a
+    movi    a6, 0xfffffffc
+    quos    a5, a2, a4
+    assert  eq, a5, a6
+    quos    a2, a2, a4
+    assert  eq, a2, a6
+    quos    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test quos_pn
+    movi    a2, 0x5a5a137f
+    mov     a3, a2
+    movi    a4, 0xf7315a5a
+    movi    a6, 0xfffffff6
+    quos    a5, a2, a4
+    assert  eq, a5, a6
+    quos    a2, a2, a4
+    assert  eq, a2, a6
+    quos    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test quos_nn
+    movi    a2, 0xf7315a5a
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0
+    quos    a5, a2, a4
+    assert  eq, a5, a6
+    quos    a2, a2, a4
+    assert  eq, a2, a6
+    quos    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test quos_over
+    movi    a2, 0x80000000
+    movi    a4, 0xffffffff
+    movi    a6, 0x80000000
+    quos    a5, a2, a4
+    assert  eq, a5, a6
+test_end
+
+test quos_exc
+    set_vector kernel, 2f
+    movi    a2, 0xf7315a5a
+    movi    a4, 0x00000000
+1:
+    quos    a5, a2, a4
+    test_fail
+2:
+    rsr     a2, exccause
+    assert  eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_rem.S b/tests/tcg/xtensa/test_rem.S
new file mode 100644
index 0000000..bb0d5fe
--- /dev/null
+++ b/tests/tcg/xtensa/test_rem.S
@@ -0,0 +1,147 @@
+.include "macros.inc"
+
+test_suite rem
+
+test remu_pp
+    movi    a2, 0x5a5a137f
+    mov     a3, a2
+    movi    a4, 0x137f5a5a
+    movi    a6, 0x0c5caa17
+    remu    a5, a2, a4
+    assert  eq, a5, a6
+    remu    a2, a2, a4
+    assert  eq, a2, a6
+    remu    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test remu_np
+    movi    a2, 0xa5a5137f
+    mov     a3, a2
+    movi    a4, 0x137f5a5a
+    movi    a6, 0x9aa40af
+    remu    a5, a2, a4
+    assert  eq, a5, a6
+    remu    a2, a2, a4
+    assert  eq, a2, a6
+    remu    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test remu_pn
+    movi    a2, 0x5a5a137f
+    mov     a3, a2
+    movi    a4, 0xf7315a5a
+    movi    a6, 0x5a5a137f
+    remu    a5, a2, a4
+    assert  eq, a5, a6
+    remu    a2, a2, a4
+    assert  eq, a2, a6
+    remu    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test remu_nn
+    movi    a2, 0xf7315a5a
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x518c46db
+    remu    a5, a2, a4
+    assert  eq, a5, a6
+    remu    a2, a2, a4
+    assert  eq, a2, a6
+    remu    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test remu_exc
+    set_vector kernel, 2f
+    movi    a2, 0xf7315a5a
+    movi    a4, 0x00000000
+1:
+    remu    a5, a2, a4
+    test_fail
+2:
+    rsr     a2, exccause
+    assert  eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+test_end
+
+test rems_pp
+    movi    a2, 0x5a5a137f
+    mov     a3, a2
+    movi    a4, 0x137f5a5a
+    movi    a6, 0x0c5caa17
+    rems    a5, a2, a4
+    assert  eq, a5, a6
+    rems    a2, a2, a4
+    assert  eq, a2, a6
+    rems    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test rems_np
+    movi    a2, 0xa5a5137f
+    mov     a3, a2
+    movi    a4, 0x137f5a5a
+    movi    a6, 0xf3a27ce7
+    rems    a5, a2, a4
+    assert  eq, a5, a6
+    rems    a2, a2, a4
+    assert  eq, a2, a6
+    rems    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test rems_pn
+    movi    a2, 0x5a5a137f
+    mov     a3, a2
+    movi    a4, 0xf7315a5a
+    movi    a6, 0x02479b03
+    rems    a5, a2, a4
+    assert  eq, a5, a6
+    rems    a2, a2, a4
+    assert  eq, a2, a6
+    rems    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test rems_nn
+    movi    a2, 0xf7315a5a
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xf7315a5a
+    rems    a5, a2, a4
+    assert  eq, a5, a6
+    rems    a2, a2, a4
+    assert  eq, a2, a6
+    rems    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test rems_over
+    movi    a2, 0x80000000
+    movi    a4, 0xffffffff
+    movi    a6, 0
+    rems    a5, a2, a4
+    assert  eq, a5, a6
+test_end
+
+test rems_exc
+    set_vector kernel, 2f
+    movi    a2, 0xf7315a5a
+    movi    a4, 0x00000000
+1:
+    rems    a5, a2, a4
+    test_fail
+2:
+    rsr     a2, exccause
+    assert  eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_rst0.S b/tests/tcg/xtensa/test_rst0.S
new file mode 100644
index 0000000..3eda565
--- /dev/null
+++ b/tests/tcg/xtensa/test_rst0.S
@@ -0,0 +1,148 @@
+.include "macros.inc"
+
+test_suite rst0
+
+test and
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x01250125
+    and     a5, a2, a4
+    assert  eq, a5, a6
+    and     a2, a2, a4
+    assert  eq, a2, a6
+    and     a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test or
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xb7ffb7ff
+    or      a5, a2, a4
+    assert  eq, a5, a6
+    or      a2, a2, a4
+    assert  eq, a2, a6
+    or      a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test xor
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xb6dab6da
+    xor     a5, a2, a4
+    assert  eq, a5, a6
+    xor     a2, a2, a4
+    assert  eq, a2, a6
+    xor     a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test add
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xb924b924
+    add     a5, a2, a4
+    assert  eq, a5, a6
+    add     a2, a2, a4
+    assert  eq, a2, a6
+    add     a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test addx2
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xcca45ec9
+    addx2   a5, a2, a4
+    assert  eq, a5, a6
+    addx2   a2, a2, a4
+    assert  eq, a2, a6
+    addx2   a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test addx4
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xf3a3aa13
+    addx4   a5, a2, a4
+    assert  eq, a5, a6
+    addx4   a2, a2, a4
+    assert  eq, a2, a6
+    addx4   a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test addx8
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x41a240a7
+    addx8   a5, a2, a4
+    assert  eq, a5, a6
+    addx8   a2, a2, a4
+    assert  eq, a2, a6
+    addx8   a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test sub
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x6dda9226
+    sub     a5, a2, a4
+    assert  eq, a5, a6
+    sub     a2, a2, a4
+    assert  eq, a2, a6
+    sub     a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test subx2
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x815a37cb
+    subx2   a5, a2, a4
+    assert  eq, a5, a6
+    subx2   a2, a2, a4
+    assert  eq, a2, a6
+    subx2   a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test subx4
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xa8598315
+    subx4   a5, a2, a4
+    assert  eq, a5, a6
+    subx4   a2, a2, a4
+    assert  eq, a2, a6
+    subx4   a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test subx8
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xf65819a9
+    subx8   a5, a2, a4
+    assert  eq, a5, a6
+    subx8   a2, a2, a4
+    assert  eq, a2, a6
+    subx8   a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_sar.S b/tests/tcg/xtensa/test_sar.S
new file mode 100644
index 0000000..40c649f
--- /dev/null
+++ b/tests/tcg/xtensa/test_sar.S
@@ -0,0 +1,111 @@
+.include "macros.inc"
+
+test_suite sar
+
+.macro test_sar prefix, imm
+    \prefix\()_set \imm
+    \prefix\()_ver \imm
+.endm
+
+.macro tests_sar prefix
+    test_sar \prefix, 0
+    test_sar \prefix, 1
+    test_sar \prefix, 2
+    test_sar \prefix, 3
+    test_sar \prefix, 0x1f
+    test_sar \prefix, 0x20
+    test_sar \prefix, 0x3f
+    test_sar \prefix, 0x40
+    test_sar \prefix, 0xfffffffe
+.endm
+
+.macro sar_set imm
+    movi    a2, \imm
+    wsr     a2, sar
+.endm
+
+.macro sar_ver imm
+    rsr     a3, sar
+    movi    a2, \imm & 0x3f
+    assert  eq, a2, a3
+.endm
+
+test sar
+    tests_sar sar
+test_end
+
+.macro ssr_set imm
+    movi    a2, \imm
+    ssr     a2
+.endm
+
+.macro ssr_ver imm
+    rsr     a3, sar
+    movi    a2, \imm & 0x1f
+    assert  eq, a2, a3
+.endm
+
+test ssr
+    tests_sar ssr
+test_end
+
+.macro ssl_set imm
+    movi    a2, \imm
+    ssl     a2
+.endm
+
+.macro ssl_ver imm
+    rsr     a3, sar
+    movi    a2, 32 - (\imm & 0x1f)
+    assert  eq, a2, a3
+.endm
+
+test ssl
+    tests_sar ssl
+test_end
+
+.macro ssa8l_set imm
+    movi    a2, \imm
+    ssa8l   a2
+.endm
+
+.macro ssa8l_ver imm
+    rsr     a3, sar
+    movi    a2, (\imm & 0x3) << 3
+    assert  eq, a2, a3
+.endm
+
+test ssa8l
+    tests_sar ssa8l
+test_end
+
+.macro ssa8b_set imm
+    movi    a2, \imm
+    ssa8b   a2
+.endm
+
+.macro ssa8b_ver imm
+    rsr     a3, sar
+    movi    a2, 32 - ((\imm & 0x3) << 3)
+    assert  eq, a2, a3
+.endm
+
+test ssa8b
+    tests_sar ssa8b
+test_end
+
+.macro ssai_set imm
+    ssai    \imm & 0x1f
+.endm
+
+.macro ssai_ver imm
+    rsr     a3, sar
+    movi    a2, \imm & 0x1f
+    assert  eq, a2, a3
+.endm
+
+test ssai
+    tests_sar ssai
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_sext.S b/tests/tcg/xtensa/test_sext.S
new file mode 100644
index 0000000..04dc650
--- /dev/null
+++ b/tests/tcg/xtensa/test_sext.S
@@ -0,0 +1,69 @@
+.include "macros.inc"
+
+test_suite sext
+
+test sext
+    movi    a2, 0xffffff5a
+    movi    a3, 0x0000005a
+    sext    a4, a2, 7
+    assert  eq, a3, a4
+
+    movi    a2, 0x000000a5
+    movi    a3, 0xffffffa5
+    sext    a4, a2, 7
+    assert  eq, a3, a4
+
+    movi    a2, 0xfffffaa5
+    movi    a3, 0x000000a5
+    sext    a4, a2, 8
+    assert  eq, a3, a4
+
+    movi    a2, 0x0000055a
+    movi    a3, 0xffffff5a
+    sext    a4, a2, 8
+    assert  eq, a3, a4
+
+    movi    a2, 0xffff5a5a
+    movi    a3, 0x00005a5a
+    sext    a4, a2, 15
+    assert  eq, a3, a4
+
+    movi    a2, 0x0000a5a5
+    movi    a3, 0xffffa5a5
+    sext    a4, a2, 15
+    assert  eq, a3, a4
+
+    movi    a2, 0x00055a5a
+    movi    a3, 0xffff5a5a
+    sext    a4, a2, 16
+    assert  eq, a3, a4
+
+    movi    a2, 0x000aa5a5
+    movi    a3, 0x0000a5a5
+    sext    a4, a2, 16
+    assert  eq, a3, a4
+
+    movi    a2, 0x005a5a5a
+    movi    a3, 0xffda5a5a
+    sext    a4, a2, 22
+    assert  eq, a3, a4
+
+    movi    a2, 0xffa5a5a5
+    movi    a3, 0x0025a5a5
+    sext    a4, a2, 22
+    assert  eq, a3, a4
+test_end
+
+test sext_same_rs
+    movi    a2, 0xffffff5a
+    movi    a3, 0x0000005a
+    sext    a2, a2, 7
+    assert  eq, a3, a2
+
+    movi    a2, 0x000000a5
+    movi    a3, 0xffffffa5
+    sext    a2, a2, 7
+    assert  eq, a3, a2
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_shift.S b/tests/tcg/xtensa/test_shift.S
new file mode 100644
index 0000000..a8e4364
--- /dev/null
+++ b/tests/tcg/xtensa/test_shift.S
@@ -0,0 +1,206 @@
+.include "macros.inc"
+
+test_suite shift
+
+.macro test_shift prefix, dst, src, v, imm
+    \prefix\()_set \dst, \src, \v, \imm
+    \prefix\()_ver \dst, \v, \imm
+.endm
+
+.macro test_shift_sd prefix, v, imm
+    test_shift \prefix, a3, a2, \v, \imm
+    test_shift \prefix, a2, a2, \v, \imm
+.endm
+
+.macro tests_imm_shift prefix, v
+    test_shift_sd \prefix, \v, 1
+    test_shift_sd \prefix, \v, 2
+    test_shift_sd \prefix, \v, 7
+    test_shift_sd \prefix, \v, 8
+    test_shift_sd \prefix, \v, 15
+    test_shift_sd \prefix, \v, 16
+    test_shift_sd \prefix, \v, 31
+.endm
+
+.macro tests_shift prefix, v
+    test_shift_sd \prefix, \v, 0
+    tests_imm_shift \prefix, \v
+    test_shift_sd \prefix, \v, 32
+.endm
+
+
+.macro slli_set dst, src, v, imm
+    movi    \src, \v
+    slli    \dst, \src, \imm
+.endm
+
+.macro slli_ver dst, v, imm
+    mov     a2, \dst
+    movi    a3, ((\v) << (\imm)) & 0xffffffff
+    assert  eq, a2, a3
+.endm
+
+test slli
+    tests_imm_shift slli, 0xa3c51249
+test_end
+
+
+.macro srai_set dst, src, v, imm
+    movi    \src, \v
+    srai    \dst, \src, \imm
+.endm
+
+.macro srai_ver dst, v, imm
+    mov     a2, \dst
+    .if (\imm)
+    movi    a3, (((\v) >> (\imm)) & 0xffffffff) | \
+                ~((((\v) & 0x80000000) >> ((\imm) - 1)) - 1)
+    .else
+    movi    a3, \v
+    .endif
+    assert  eq, a2, a3
+.endm
+
+test srai
+    tests_imm_shift srai, 0x49a3c512
+    tests_imm_shift srai, 0xa3c51249
+test_end
+
+
+.macro srli_set dst, src, v, imm
+    movi    \src, \v
+    srli    \dst, \src, \imm
+.endm
+
+.macro srli_ver dst, v, imm
+    mov     a2, \dst
+    movi    a3, (((\v) >> (\imm)) & 0xffffffff)
+    assert  eq, a2, a3
+.endm
+
+test srli
+    tests_imm_shift srli, 0x49a3c512
+    tests_imm_shift srli, 0xa3c51249
+test_end
+
+
+.macro sll_set dst, src, v, imm
+    movi    a2, \imm
+    ssl     a2
+    movi    \src, \v
+    sll     \dst, \src
+.endm
+
+.macro sll_sar_set dst, src, v, imm
+    movi    a2, 32 - \imm
+    wsr     a2, sar
+    movi    \src, \v
+    sll     \dst, \src
+.endm
+
+.macro sll_ver dst, v, imm
+    slli_ver \dst, \v, (\imm) & 0x1f
+.endm
+
+.macro sll_sar_ver dst, v, imm
+    slli_ver \dst, \v, \imm
+.endm
+
+test sll
+    tests_shift sll, 0xa3c51249
+    tests_shift sll_sar, 0xa3c51249
+test_end
+
+
+.macro srl_set dst, src, v, imm
+    movi    a2, \imm
+    ssr     a2
+    movi    \src, \v
+    srl     \dst, \src
+.endm
+
+.macro srl_sar_set dst, src, v, imm
+    movi    a2, \imm
+    wsr     a2, sar
+    movi    \src, \v
+    srl     \dst, \src
+.endm
+
+.macro srl_ver dst, v, imm
+    srli_ver \dst, \v, (\imm) & 0x1f
+.endm
+
+.macro srl_sar_ver dst, v, imm
+    srli_ver \dst, \v, \imm
+.endm
+
+test srl
+    tests_shift srl, 0xa3c51249
+    tests_shift srl_sar, 0xa3c51249
+    tests_shift srl, 0x49a3c512
+    tests_shift srl_sar, 0x49a3c512
+test_end
+
+
+.macro sra_set dst, src, v, imm
+    movi    a2, \imm
+    ssr     a2
+    movi    \src, \v
+    sra     \dst, \src
+.endm
+
+.macro sra_sar_set dst, src, v, imm
+    movi    a2, \imm
+    wsr     a2, sar
+    movi    \src, \v
+    sra     \dst, \src
+.endm
+
+.macro sra_ver dst, v, imm
+    srai_ver \dst, \v, (\imm) & 0x1f
+.endm
+
+.macro sra_sar_ver dst, v, imm
+    srai_ver \dst, \v, \imm
+.endm
+
+test sra
+    tests_shift sra, 0xa3c51249
+    tests_shift sra_sar, 0xa3c51249
+    tests_shift sra, 0x49a3c512
+    tests_shift sra_sar, 0x49a3c512
+test_end
+
+
+.macro src_set dst, src, v, imm
+    movi    a2, \imm
+    ssr     a2
+    movi    \src, (\v) & 0xffffffff
+    movi    a4, (\v) >> 32
+    src     \dst, a4, \src
+.endm
+
+.macro src_sar_set dst, src, v, imm
+    movi    a2, \imm
+    wsr     a2, sar
+    movi    \src, (\v) & 0xffffffff
+    movi    a4, (\v) >> 32
+    src     \dst, a4, \src
+.endm
+
+.macro src_ver dst, v, imm
+    src_sar_ver \dst, \v, (\imm) & 0x1f
+.endm
+
+.macro src_sar_ver dst, v, imm
+    mov     a2, \dst
+    movi    a3, ((\v) >> (\imm)) & 0xffffffff
+    assert  eq, a2, a3
+.endm
+
+test src
+    tests_shift src, 0xa3c51249215c3a94
+    tests_shift src_sar, 0xa3c51249215c3a94
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_timer.S b/tests/tcg/xtensa/test_timer.S
new file mode 100644
index 0000000..1041cc6
--- /dev/null
+++ b/tests/tcg/xtensa/test_timer.S
@@ -0,0 +1,178 @@
+.include "macros.inc"
+
+test_suite timer
+
+test ccount
+    rsr     a3, ccount
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 1
+test_end
+
+test ccompare
+    movi    a2, 0
+    wsr     a2, intenable
+    rsr     a2, interrupt
+    wsr     a2, intclear
+    movi    a2, 0
+    wsr     a2, ccompare1
+    wsr     a2, ccompare2
+
+    movi    a3, 20
+    rsr     a2, ccount
+    addi    a2, a2, 20
+    wsr     a2, ccompare0
+    rsr     a2, interrupt
+    assert  eqi, a2, 0
+    loop    a3, 1f
+    rsr     a3, interrupt
+    bnez    a3, 2f
+1:
+    test_fail
+2:
+test_end
+
+test ccompare0_interrupt
+    set_vector kernel, 2f
+    movi    a2, 0
+    wsr     a2, intenable
+    rsr     a2, interrupt
+    wsr     a2, intclear
+    movi    a2, 0
+    wsr     a2, ccompare1
+    wsr     a2, ccompare2
+
+    movi    a3, 20
+    rsr     a2, ccount
+    addi    a2, a2, 20
+    wsr     a2, ccompare0
+    rsync
+    rsr     a2, interrupt
+    assert  eqi, a2, 0
+
+    movi    a2, 0x40
+    wsr     a2, intenable
+    rsil    a2, 0
+    loop    a3, 1f
+    nop
+1:
+    test_fail
+2:
+    rsr     a2, exccause
+    assert  eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
+test_end
+
+test ccompare1_interrupt
+    set_vector level3, 2f
+    movi    a2, 0
+    wsr     a2, intenable
+    rsr     a2, interrupt
+    wsr     a2, intclear
+    movi    a2, 0
+    wsr     a2, ccompare0
+    wsr     a2, ccompare2
+
+    movi    a3, 20
+    rsr     a2, ccount
+    addi    a2, a2, 20
+    wsr     a2, ccompare1
+    rsync
+    rsr     a2, interrupt
+    assert  eqi, a2, 0
+    movi    a2, 0x400
+    wsr     a2, intenable
+    rsil    a2, 2
+    loop    a3, 1f
+    nop
+1:
+    test_fail
+2:
+test_end
+
+test ccompare2_interrupt
+    set_vector level5, 2f
+    movi    a2, 0
+    wsr     a2, intenable
+    rsr     a2, interrupt
+    wsr     a2, intclear
+    movi    a2, 0
+    wsr     a2, ccompare0
+    wsr     a2, ccompare1
+
+    movi    a3, 20
+    rsr     a2, ccount
+    addi    a2, a2, 20
+    wsr     a2, ccompare2
+    rsync
+    rsr     a2, interrupt
+    assert  eqi, a2, 0
+    movi    a2, 0x2000
+    wsr     a2, intenable
+    rsil    a2, 4
+    loop    a3, 1f
+    nop
+1:
+    test_fail
+2:
+test_end
+
+test ccompare_interrupt_masked
+    set_vector kernel, 2f
+    movi    a2, 0
+    wsr     a2, intenable
+    rsr     a2, interrupt
+    wsr     a2, intclear
+    movi    a2, 0
+    wsr     a2, ccompare2
+
+    movi    a3, 40
+    rsr     a2, ccount
+    addi    a2, a2, 20
+    wsr     a2, ccompare1
+    addi    a2, a2, 20
+    wsr     a2, ccompare0
+    rsync
+    rsr     a2, interrupt
+    assert  eqi, a2, 0
+
+    movi    a2, 0x40
+    wsr     a2, intenable
+    rsil    a2, 0
+    loop    a3, 1f
+    nop
+1:
+    test_fail
+2:
+    rsr     a2, exccause
+    assert  eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
+test_end
+
+test ccompare_interrupt_masked_waiti
+    set_vector kernel, 2f
+    movi    a2, 0
+    wsr     a2, intenable
+    rsr     a2, interrupt
+    wsr     a2, intclear
+    movi    a2, 0
+    wsr     a2, ccompare2
+
+    movi    a3, 40
+    rsr     a2, ccount
+    addi    a2, a2, 20
+    wsr     a2, ccompare1
+    addi    a2, a2, 20
+    wsr     a2, ccompare0
+    rsync
+    rsr     a2, interrupt
+    assert  eqi, a2, 0
+
+    movi    a2, 0x40
+    wsr     a2, intenable
+    waiti   0
+    test_fail
+2:
+    rsr     a2, exccause
+    assert  eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_windowed.S b/tests/tcg/xtensa/test_windowed.S
new file mode 100644
index 0000000..cb2d39e
--- /dev/null
+++ b/tests/tcg/xtensa/test_windowed.S
@@ -0,0 +1,302 @@
+.include "macros.inc"
+
+test_suite windowed
+
+.altmacro
+
+.macro reset_window start
+    movi    a2, 0xff
+    wsr     a2, windowstart
+    rsync
+    movi    a2, 0
+    wsr     a2, windowbase
+    rsync
+    movi    a2, \start
+    wsr     a2, windowstart
+    rsync
+.endm
+
+.macro overflow_test shift, window, probe_ok, probe_ex
+    set_vector window_overflow_4, 0
+    set_vector window_overflow_8, 0
+    set_vector window_overflow_12, 0
+
+    movi    a2, 1 | (((1 << ((\window) / 4)) | 1) << ((\shift) / 4))
+    wsr     a2, windowstart
+    reset_ps
+
+    mov     a2, a\probe_ok
+    set_vector window_overflow_\window, 10f
+1:
+    mov     a2, a\probe_ex
+    test_fail
+10:
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+    movi    a2, 2f
+    wsr     a2, epc1
+
+    rsr     a2, windowbase
+    movi    a3, (\shift) / 4
+    assert  eq, a2, a3
+    rsr     a2, ps
+    movi    a3, 0x4001f
+    assert  eq, a2, a3
+    rfwo
+    test_fail
+2:
+    rsr     a2, windowbase
+    assert  eqi, a2, 0
+    rsr     a2, windowstart
+    movi    a3, 1 | ((1 << ((\window) / 4)) << ((\shift) / 4))
+    assert  eq, a2, a3
+    rsr     a2, ps
+    movi    a3, 0x4000f
+    assert  eq, a2, a3
+.endm
+
+.macro overflow_tests shift, window, probe
+    .if \probe < 15
+    overflow_test \shift, \window, %((\shift) - 1), \probe
+    overflow_tests \shift, \window, %((\probe) + 1)
+    .endif
+.endm
+
+.macro all_overflow_tests
+    .irp shift, 4, 8, 12
+    .irp window, 4, 8, 12
+    overflow_tests \shift, \window, \shift
+    .endr
+    .endr
+.endm
+
+test overflow
+    all_overflow_tests
+test_end
+
+
+.macro underflow_test window
+    set_vector window_underflow_4, 0
+    set_vector window_underflow_8, 0
+    set_vector window_underflow_12, 0
+
+    set_vector window_underflow_\window, 10f
+
+    reset_window 1
+    reset_ps
+
+    ssai    2
+    movi    a2, 2f
+    slli    a2, a2, 2
+    movi    a3, (\window) / 4
+    src     a0, a3, a2
+1:
+    retw
+    test_fail
+10:
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+    movi    a2, 2f
+    wsr     a2, epc1
+
+    rsr     a2, ps
+    movi    a3, 0x4001f
+    assert  eq, a2, a3
+    rsr     a2, windowbase
+    assert  eqi, a2, 8 - ((\window) / 4)
+    rsr     a2, windowstart
+    assert  eqi, a2, 1
+    rfwu
+2:
+    rsr     a2, ps
+    movi    a3, 0x4000f
+    assert  eq, a2, a3
+    rsr     a2, windowbase
+    assert  eqi, a2, 0
+    rsr     a2, windowstart
+    assert  bsi, a2, 0
+    assert  bsi, a2, 8 - ((\window) / 4)
+.endm
+
+test underflow
+    set_vector window_overflow_4, 0
+    set_vector window_overflow_8, 0
+    set_vector window_overflow_12, 0
+
+    underflow_test 4
+    underflow_test 8
+    underflow_test 12
+test_end
+
+
+.macro retw_test window
+    reset_window %(1 | (1 << (8 - (\window) / 4)))
+    reset_ps
+
+    ssai    2
+    movi    a2, 1f
+    slli    a2, a2, 2
+    movi    a3, (\window) / 4
+    src     a0, a3, a2
+    retw
+    test_fail
+1:
+    rsr     a2, ps
+    movi    a3, 0x4000f
+    assert  eq, a2, a3
+    rsr     a2, windowbase
+    assert  eqi, a2, 8 - ((\window) / 4)
+    rsr     a2, windowstart
+    assert  bci, a2, 0
+    assert  bsi, a2, 8 - ((\window) / 4)
+.endm
+
+test retw
+    set_vector window_underflow_4, 0
+    set_vector window_underflow_8, 0
+    set_vector window_underflow_12, 0
+
+    retw_test 4
+    retw_test 8
+    retw_test 12
+test_end
+
+test movsp
+    set_vector kernel, 2f
+
+    reset_window 1
+    reset_ps
+1:
+    movsp   a2, a3
+    test_fail
+2:
+    rsr     a2, exccause
+    assert  eqi, a2, 5
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+
+    set_vector kernel, 0
+
+    reset_window 0x81
+    reset_ps
+
+    movsp   a2, a3
+test_end
+
+test rotw
+    reset_window 0x4b
+    reset_ps
+
+    movi    a3, 0x10
+
+    rotw    1
+    rsr     a2, windowbase
+    assert  eqi, a2, 1
+    movi    a3, 0x11
+    movi    a7, 0x12
+
+    rotw    2
+    rsr     a2, windowbase
+    assert  eqi, a2, 3
+    movi    a3, 0x13
+    movi    a7, 0x14
+    movi    a11, 0x15
+
+    rotw    3
+    rsr     a2, windowbase
+    assert  eqi, a2, 6
+    movi    a3, 0x16
+    movi    a7, 0x17
+
+    movi    a2, 0x44
+    wsr     a2, windowstart
+    rsync
+
+    movi    a2, 0x10
+    assert  eq, a2, a11
+    movi    a11, 0x18
+    movi    a2, 0x11
+    assert  eq, a2, a15
+    movi    a15, 0x19
+
+    rotw    4
+    movi    a2, 0x12
+    assert  eq, a2, a3
+    movi    a2, 0x13
+    assert  eq, a2, a7
+    movi    a2, 0x14
+    assert  eq, a2, a11
+    movi    a2, 0x15
+    assert  eq, a2, a15
+
+    movi    a2, 0x5
+    wsr     a2, windowstart
+    rsync
+
+    rotw    -2
+    movi    a2, 0x18
+    assert  eq, a2, a3
+    movi    a2, 0x19
+    assert  eq, a2, a7
+test_end
+
+.macro callw_test window
+    call\window 2f
+1:
+    test_fail
+    .align  4
+2:
+    rsr     a2, windowbase
+    assert  eqi, a2, 0
+    rsr     a2, ps
+    movi    a3, 0x4000f | ((\window) << 14)
+    assert  eq, a2, a3
+    movi    a2, 1b
+    slli    a2, a2, 2
+    ssai    2
+    movi    a3, (\window) / 4
+    src     a2, a3, a2
+    assert  eq, a2, a\window
+.endm
+
+test callw
+    reset_window 0x1
+    reset_ps
+
+    callw_test 4
+    callw_test 8
+    callw_test 12
+test_end
+
+
+.macro entry_test window
+    reset_window 0x1
+    reset_ps
+    movi    a2, 0x4000f | ((\window) << 14)
+    wsr     a2, ps
+    isync
+    movi    a3, 0x12345678
+    j       1f
+    .align  4
+1:
+    entry   a3, 0x5678
+    movi    a2, 0x12340000
+    assert  eq, a2, a3
+    rsr     a2, windowbase
+    assert  eqi, a2, (\window) / 4
+    rsr     a2, windowstart
+    movi    a3, 1 | (1 << ((\window) / 4))
+    assert  eq, a2, a3
+    rotw    -(\window) / 4
+.endm
+
+test entry
+    entry_test 4
+    entry_test 8
+    entry_test 12
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/vectors.S b/tests/tcg/xtensa/vectors.S
new file mode 100644
index 0000000..265a181
--- /dev/null
+++ b/tests/tcg/xtensa/vectors.S
@@ -0,0 +1,39 @@
+.macro vector name
+
+.section .vector.\name
+    j       1f
+.section .vector.\name\().text
+1:
+    wsr     a2, excsave1
+    movi    a2, handler_\name
+    l32i    a2, a2, 0
+    beqz    a2, 1f
+    jx      a2
+1:
+    movi    a3, 1b
+    movi    a2, 1
+    simcall
+
+.align 4
+.global handler_\name
+handler_\name\(): .word 0
+
+.endm
+
+vector window_overflow_4
+vector window_overflow_8
+vector window_overflow_12
+vector window_underflow_4
+vector window_underflow_8
+vector window_underflow_12
+
+vector level2
+vector level3
+vector level4
+vector level5
+vector level6
+vector level7
+
+vector kernel
+vector user
+vector double
diff --git a/tests/test-arm-iwmmxt.s b/tests/test-arm-iwmmxt.s
deleted file mode 100644
index d647f94..0000000
--- a/tests/test-arm-iwmmxt.s
+++ /dev/null
@@ -1,49 +0,0 @@
-@ Checks whether iwMMXt is functional.
-.code	32
-.globl	main
-
-main:
-ldr	r0, =data0
-ldr	r1, =data1
-ldr	r2, =data2
-#ifndef FPA
-wldrd	wr0, [r0, #0]
-wldrd	wr1, [r0, #8]
-wldrd	wr2, [r1, #0]
-wldrd	wr3, [r1, #8]
-wsubb	wr2, wr2, wr0
-wsubb	wr3, wr3, wr1
-wldrd	wr0, [r2, #0]
-wldrd	wr1, [r2, #8]
-waddb	wr0, wr0, wr2
-waddb	wr1, wr1, wr3
-wstrd	wr0, [r2, #0]
-wstrd	wr1, [r2, #8]
-#else
-ldfe	f0, [r0, #0]
-ldfe	f1, [r0, #8]
-ldfe	f2, [r1, #0]
-ldfe	f3, [r1, #8]
-adfdp	f2, f2, f0
-adfdp	f3, f3, f1
-ldfe	f0, [r2, #0]
-ldfe	f1, [r2, #8]
-adfd	f0, f0, f2
-adfd	f1, f1, f3
-stfe	f0, [r2, #0]
-stfe	f1, [r2, #8]
-#endif
-mov	r0, #1
-mov	r1, r2
-mov	r2, #0x11
-swi	#0x900004
-mov	r0, #0
-swi	#0x900001
-
-.data
-data0:
-.string	"aaaabbbbccccdddd"
-data1:
-.string	"bbbbccccddddeeee"
-data2:
-.string	"hvLLWs\x1fsdrs9\x1fNJ-\n"
diff --git a/tests/test-i386-code16.S b/tests/test-i386-code16.S
deleted file mode 100644
index 816c24b..0000000
--- a/tests/test-i386-code16.S
+++ /dev/null
@@ -1,79 +0,0 @@
-        .code16
-        .globl code16_start
-        .globl code16_end
-
-CS_SEG = 0xf
-
-code16_start:
-
-        .globl code16_func1
-
-        /* basic test */
-code16_func1 = . - code16_start
-        mov $1, %eax
-        data32 lret
-
-/* test push/pop in 16 bit mode */
-        .globl code16_func2
-code16_func2 = . - code16_start
-        xor %eax, %eax
-        mov $0x12345678, %ebx
-        movl %esp, %ecx
-        push %bx
-        subl %esp, %ecx
-        pop %ax
-        data32 lret
-
-/* test various jmp opcodes */
-        .globl code16_func3
-code16_func3 = . - code16_start
-        jmp 1f
-        nop
-1:
-        mov $4, %eax
-        mov $0x12345678, %ebx
-        xor %bx, %bx
-        jz 2f
-        add $2, %ax
-2:
-
-        call myfunc
-
-        lcall $CS_SEG, $(myfunc2 - code16_start)
-
-        ljmp $CS_SEG, $(myjmp1 - code16_start)
-myjmp1_next:
-
-        cs lcall *myfunc2_addr - code16_start
-
-        cs ljmp *myjmp2_addr - code16_start
-myjmp2_next:
-
-        data32 lret
-
-myfunc2_addr:
-        .short myfunc2 - code16_start
-        .short CS_SEG
-
-myjmp2_addr:
-        .short myjmp2 - code16_start
-        .short CS_SEG
-
-myjmp1:
-        add $8, %ax
-        jmp myjmp1_next
-
-myjmp2:
-        add $16, %ax
-        jmp myjmp2_next
-
-myfunc:
-        add $1, %ax
-        ret
-
-myfunc2:
-        add $4, %ax
-        lret
-
-
-code16_end:
diff --git a/tests/test-i386-muldiv.h b/tests/test-i386-muldiv.h
deleted file mode 100644
index 015f59e..0000000
--- a/tests/test-i386-muldiv.h
+++ /dev/null
@@ -1,76 +0,0 @@
-
-void glue(glue(test_, OP), b)(long op0, long op1)
-{
-    long res, s1, s0, flags;
-    s0 = op0;
-    s1 = op1;
-    res = s0;
-    flags = 0;
-    asm ("push %4\n\t"
-         "popf\n\t"
-         stringify(OP)"b %b2\n\t"
-         "pushf\n\t"
-         "pop %1\n\t"
-         : "=a" (res), "=g" (flags)
-         : "q" (s1), "0" (res), "1" (flags));
-    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
-           stringify(OP) "b", s0, s1, res, flags & CC_MASK);
-}
-
-void glue(glue(test_, OP), w)(long op0h, long op0, long op1)
-{
-    long res, s1, flags, resh;
-    s1 = op1;
-    resh = op0h;
-    res = op0;
-    flags = 0;
-    asm ("push %5\n\t"
-         "popf\n\t"
-         stringify(OP) "w %w3\n\t"
-         "pushf\n\t"
-         "pop %1\n\t"
-         : "=a" (res), "=g" (flags), "=d" (resh)
-         : "q" (s1), "0" (res), "1" (flags), "2" (resh));
-    printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n",
-           stringify(OP) "w", op0h, op0, s1, resh, res, flags & CC_MASK);
-}
-
-void glue(glue(test_, OP), l)(long op0h, long op0, long op1)
-{
-    long res, s1, flags, resh;
-    s1 = op1;
-    resh = op0h;
-    res = op0;
-    flags = 0;
-    asm ("push %5\n\t"
-         "popf\n\t"
-         stringify(OP) "l %k3\n\t"
-         "pushf\n\t"
-         "pop %1\n\t"
-         : "=a" (res), "=g" (flags), "=d" (resh)
-         : "q" (s1), "0" (res), "1" (flags), "2" (resh));
-    printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n",
-           stringify(OP) "l", op0h, op0, s1, resh, res, flags & CC_MASK);
-}
-
-#if defined(__x86_64__)
-void glue(glue(test_, OP), q)(long op0h, long op0, long op1)
-{
-    long res, s1, flags, resh;
-    s1 = op1;
-    resh = op0h;
-    res = op0;
-    flags = 0;
-    asm ("push %5\n\t"
-         "popf\n\t"
-         stringify(OP) "q %3\n\t"
-         "pushf\n\t"
-         "pop %1\n\t"
-         : "=a" (res), "=g" (flags), "=d" (resh)
-         : "q" (s1), "0" (res), "1" (flags), "2" (resh));
-    printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n",
-           stringify(OP) "q", op0h, op0, s1, resh, res, flags & CC_MASK);
-}
-#endif
-
-#undef OP
diff --git a/tests/test-i386-shift.h b/tests/test-i386-shift.h
deleted file mode 100644
index 3d8f84b..0000000
--- a/tests/test-i386-shift.h
+++ /dev/null
@@ -1,185 +0,0 @@
-
-#define exec_op glue(exec_, OP)
-#define exec_opq glue(glue(exec_, OP), q)
-#define exec_opl glue(glue(exec_, OP), l)
-#define exec_opw glue(glue(exec_, OP), w)
-#define exec_opb glue(glue(exec_, OP), b)
-
-#ifndef OP_SHIFTD
-
-#ifdef OP_NOBYTE
-#define EXECSHIFT(size, rsize, res, s1, s2, flags) \
-    asm ("push %4\n\t"\
-         "popf\n\t"\
-         stringify(OP) size " %" rsize "2, %" rsize "0\n\t" \
-         "pushf\n\t"\
-         "pop %1\n\t"\
-         : "=g" (res), "=g" (flags)\
-         : "r" (s1), "0" (res), "1" (flags));
-#else
-#define EXECSHIFT(size, rsize, res, s1, s2, flags) \
-    asm ("push %4\n\t"\
-         "popf\n\t"\
-         stringify(OP) size " %%cl, %" rsize "0\n\t" \
-         "pushf\n\t"\
-         "pop %1\n\t"\
-         : "=q" (res), "=g" (flags)\
-         : "c" (s1), "0" (res), "1" (flags));
-#endif
-
-#if defined(__x86_64__)
-void exec_opq(long s2, long s0, long s1, long iflags)
-{
-    long res, flags;
-    res = s0;
-    flags = iflags;
-    EXECSHIFT("q", "", res, s1, s2, flags);
-    /* overflow is undefined if count != 1 */
-    if (s1 != 1)
-      flags &= ~CC_O;
-    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
-           stringify(OP) "q", s0, s1, res, iflags, flags & CC_MASK);
-}
-#endif
-
-void exec_opl(long s2, long s0, long s1, long iflags)
-{
-    long res, flags;
-    res = s0;
-    flags = iflags;
-    EXECSHIFT("l", "k", res, s1, s2, flags);
-    /* overflow is undefined if count != 1 */
-    if (s1 != 1)
-      flags &= ~CC_O;
-    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
-           stringify(OP) "l", s0, s1, res, iflags, flags & CC_MASK);
-}
-
-void exec_opw(long s2, long s0, long s1, long iflags)
-{
-    long res, flags;
-    res = s0;
-    flags = iflags;
-    EXECSHIFT("w", "w", res, s1, s2, flags);
-    /* overflow is undefined if count != 1 */
-    if (s1 != 1)
-      flags &= ~CC_O;
-    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
-           stringify(OP) "w", s0, s1, res, iflags, flags & CC_MASK);
-}
-
-#else
-#define EXECSHIFT(size, rsize, res, s1, s2, flags) \
-    asm ("push %4\n\t"\
-         "popf\n\t"\
-         stringify(OP) size " %%cl, %" rsize "5, %" rsize "0\n\t" \
-         "pushf\n\t"\
-         "pop %1\n\t"\
-         : "=g" (res), "=g" (flags)\
-         : "c" (s1), "0" (res), "1" (flags), "r" (s2));
-
-#if defined(__x86_64__)
-void exec_opq(long s2, long s0, long s1, long iflags)
-{
-    long res, flags;
-    res = s0;
-    flags = iflags;
-    EXECSHIFT("q", "", res, s1, s2, flags);
-    /* overflow is undefined if count != 1 */
-    if (s1 != 1)
-      flags &= ~CC_O;
-    printf("%-10s A=" FMTLX " B=" FMTLX " C=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
-           stringify(OP) "q", s0, s2, s1, res, iflags, flags & CC_MASK);
-}
-#endif
-
-void exec_opl(long s2, long s0, long s1, long iflags)
-{
-    long res, flags;
-    res = s0;
-    flags = iflags;
-    EXECSHIFT("l", "k", res, s1, s2, flags);
-    /* overflow is undefined if count != 1 */
-    if (s1 != 1)
-      flags &= ~CC_O;
-    printf("%-10s A=" FMTLX " B=" FMTLX " C=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
-           stringify(OP) "l", s0, s2, s1, res, iflags, flags & CC_MASK);
-}
-
-void exec_opw(long s2, long s0, long s1, long iflags)
-{
-    long res, flags;
-    res = s0;
-    flags = iflags;
-    EXECSHIFT("w", "w", res, s1, s2, flags);
-    /* overflow is undefined if count != 1 */
-    if (s1 != 1)
-      flags &= ~CC_O;
-    printf("%-10s A=" FMTLX " B=" FMTLX " C=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
-           stringify(OP) "w", s0, s2, s1, res, iflags, flags & CC_MASK);
-}
-
-#endif
-
-#ifndef OP_NOBYTE
-void exec_opb(long s0, long s1, long iflags)
-{
-    long res, flags;
-    res = s0;
-    flags = iflags;
-    EXECSHIFT("b", "b", res, s1, 0, flags);
-    /* overflow is undefined if count != 1 */
-    if (s1 != 1)
-      flags &= ~CC_O;
-    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
-           stringify(OP) "b", s0, s1, res, iflags, flags & CC_MASK);
-}
-#endif
-
-void exec_op(long s2, long s0, long s1)
-{
-    s2 = i2l(s2);
-    s0 = i2l(s0);
-#if defined(__x86_64__)
-    exec_opq(s2, s0, s1, 0);
-#endif
-    exec_opl(s2, s0, s1, 0);
-#ifdef OP_SHIFTD
-    exec_opw(s2, s0, s1, 0);
-#else
-    exec_opw(s2, s0, s1, 0);
-#endif
-#ifndef OP_NOBYTE
-    exec_opb(s0, s1, 0);
-#endif
-#ifdef OP_CC
-#if defined(__x86_64__)
-    exec_opq(s2, s0, s1, CC_C);
-#endif
-    exec_opl(s2, s0, s1, CC_C);
-    exec_opw(s2, s0, s1, CC_C);
-    exec_opb(s0, s1, CC_C);
-#endif
-}
-
-void glue(test_, OP)(void)
-{
-    int i, n;
-#if defined(__x86_64__)
-    n = 64;
-#else
-    n = 32;
-#endif
-    for(i = 0; i < n; i++)
-        exec_op(0x21ad3d34, 0x12345678, i);
-    for(i = 0; i < n; i++)
-        exec_op(0x813f3421, 0x82345679, i);
-}
-
-void *glue(_test_, OP) __init_call = glue(test_, OP);
-
-#undef OP
-#undef OP_CC
-#undef OP_SHIFTD
-#undef OP_NOBYTE
-#undef EXECSHIFT
diff --git a/tests/test-i386-ssse3.c b/tests/test-i386-ssse3.c
deleted file mode 100644
index 0a42bd0..0000000
--- a/tests/test-i386-ssse3.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* See if various MMX/SSE SSSE3 instructions give expected results */
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-
-int main(int argc, char *argv[]) {
-	char hello[16];
-	const char ehlo[8] = "EHLO    ";
-	uint64_t mask = 0x8080800302020001;
-
-	uint64_t a = 0x0000000000090007;
-	uint64_t b = 0x0000000000000000;
-	uint32_t c;
-	uint16_t d;
-
-	const char e[16] = "LLOaaaaaaaaaaaaa";
-	const char f[16] = "aaaaaaaaaaaaaaHE";
-
-	/* pshufb mm1/xmm1, mm2/xmm2 */
-	asm volatile ("movq    (%0), %%mm0" : : "r" (ehlo) : "mm0", "mm1");
-	asm volatile ("movq    %0, %%mm1" : : "m" (mask));
-	asm volatile ("pshufb  %mm1, %mm0");
-	asm volatile ("movq    %%mm0, %0" : "=m" (hello));
-	printf("%s\n", hello);
-
-	/* pshufb mm1/xmm1, m64/m128 */
-	asm volatile ("movq    (%0), %%mm0" : : "r" (ehlo) : "mm0");
-	asm volatile ("pshufb  %0, %%mm0" : : "m" (mask));
-	asm volatile ("movq    %%mm0, %0" : "=m" (hello));
-	printf("%s\n", hello);
-
-	/* psubsw mm1/xmm1, m64/m128 */
-	asm volatile ("movq    %0, %%mm0" : : "r" (a) : "mm0");
-	asm volatile ("phsubsw %0, %%mm0" : : "m" (b));
-	asm volatile ("movq    %%mm0, %0" : "=m" (a));
-	printf("%i - %i = %i\n", 9, 7, -(int16_t) a);
-
-	/* palignr mm1/xmm1, m64/m128, imm8 */
-	asm volatile ("movdqa  (%0), %%xmm0" : : "r" (e) : "xmm0");
-	asm volatile ("palignr $14, (%0), %%xmm0" : : "r" (f));
-	asm volatile ("movdqa  %%xmm0, (%0)" : : "r" (hello));
-	printf("%5.5s\n", hello);
-
-#if 1 /* SSE4 */
-	/* popcnt r64, r/m64 */
-	asm volatile ("movq    $0x8421000010009c63, %%rax" : : : "rax");
-	asm volatile ("popcnt  %%ax, %%dx" : : : "dx");
-	asm volatile ("popcnt  %%eax, %%ecx" : : : "ecx");
-	asm volatile ("popcnt  %rax, %rax");
-	asm volatile ("movq    %%rax, %0" : "=m" (a));
-	asm volatile ("movl    %%ecx, %0" : "=m" (c));
-	asm volatile ("movw    %%dx, %0" : "=m" (d));
-	printf("%i = %i\n%i = %i = %i\n", 13, (int) a, 9, c, d + 1);
-#endif
-
-	return 0;
-}
diff --git a/tests/test-i386-vm86.S b/tests/test-i386-vm86.S
deleted file mode 100644
index 3bb96c9..0000000
--- a/tests/test-i386-vm86.S
+++ /dev/null
@@ -1,103 +0,0 @@
-        .code16
-        .globl vm86_code_start
-        .globl vm86_code_end
-
-#define GET_OFFSET(x) ((x) - vm86_code_start + 0x100)
-
-vm86_code_start:
-        movw $GET_OFFSET(hello_world), %dx
-        movb $0x09, %ah
-        int $0x21
-
-        /* prepare int 0x90 vector */
-        xorw %ax, %ax
-        movw %ax, %es
-        es movw $GET_OFFSET(int90_test), 0x90 * 4
-        es movw %cs, 0x90 * 4 + 2
-
-        /* launch int 0x90 */
-
-        int $0x90
-
-        /* test IF support */
-        movw $GET_OFFSET(IF_msg), %dx
-        movb $0x09, %ah
-        int $0x21
-
-        pushf
-        popw %dx
-        movb $0xff, %ah
-        int $0x21
-
-        cli
-        pushf
-        popw %dx
-        movb $0xff, %ah
-        int $0x21
-
-        sti
-        pushfl
-        popl %edx
-        movb $0xff, %ah
-        int $0x21
-
-#if 0
-        movw $GET_OFFSET(IF_msg1), %dx
-        movb $0x09, %ah
-        int $0x21
-
-        pushf
-        movw %sp, %bx
-        andw $~0x200, (%bx)
-        popf
-#else
-        cli
-#endif
-
-        pushf
-        popw %dx
-        movb $0xff, %ah
-        int $0x21
-
-        pushfl
-        movw %sp, %bx
-        orw $0x200, (%bx)
-        popfl
-
-        pushfl
-        popl %edx
-        movb $0xff, %ah
-        int $0x21
-
-        movb $0x00, %ah
-        int $0x21
-
-int90_test:
-        pushf
-        pop %dx
-        movb $0xff, %ah
-        int $0x21
-
-        movw %sp, %bx
-        movw 4(%bx), %dx
-        movb $0xff, %ah
-        int $0x21
-
-        movw $GET_OFFSET(int90_msg), %dx
-        movb $0x09, %ah
-        int $0x21
-        iret
-
-int90_msg:
-        .string "INT90 started\n$"
-
-hello_world:
-        .string "Hello VM86 world\n$"
-
-IF_msg:
-        .string "VM86 IF test\n$"
-
-IF_msg1:
-        .string "If you see a diff here, your Linux kernel is buggy, please update to 2.4.20 kernel\n$"
-
-vm86_code_end:
diff --git a/tests/test-i386.c b/tests/test-i386.c
deleted file mode 100644
index 8e64bba..0000000
--- a/tests/test-i386.c
+++ /dev/null
@@ -1,2764 +0,0 @@
-/*
- *  x86 CPU test
- *
- *  Copyright (c) 2003 Fabrice Bellard
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-#define _GNU_SOURCE
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-#include <math.h>
-#include <signal.h>
-#include <setjmp.h>
-#include <errno.h>
-#include <sys/ucontext.h>
-#include <sys/mman.h>
-
-#if !defined(__x86_64__)
-//#define TEST_VM86
-#define TEST_SEGS
-#endif
-//#define LINUX_VM86_IOPL_FIX
-//#define TEST_P4_FLAGS
-#ifdef __SSE__
-#define TEST_SSE
-#define TEST_CMOV  1
-#define TEST_FCOMI 1
-#else
-#undef TEST_SSE
-#define TEST_CMOV  1
-#define TEST_FCOMI 1
-#endif
-
-#if defined(__x86_64__)
-#define FMT64X "%016lx"
-#define FMTLX "%016lx"
-#define X86_64_ONLY(x) x
-#else
-#define FMT64X "%016" PRIx64
-#define FMTLX "%08lx"
-#define X86_64_ONLY(x)
-#endif
-
-#ifdef TEST_VM86
-#include <asm/vm86.h>
-#endif
-
-#define xglue(x, y) x ## y
-#define glue(x, y) xglue(x, y)
-#define stringify(s)	tostring(s)
-#define tostring(s)	#s
-
-#define CC_C   	0x0001
-#define CC_P 	0x0004
-#define CC_A	0x0010
-#define CC_Z	0x0040
-#define CC_S    0x0080
-#define CC_O    0x0800
-
-#define __init_call	__attribute__ ((unused,__section__ ("initcall")))
-
-#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
-
-#if defined(__x86_64__)
-static inline long i2l(long v)
-{
-    return v | ((v ^ 0xabcd) << 32);
-}
-#else
-static inline long i2l(long v)
-{
-    return v;
-}
-#endif
-
-#define OP add
-#include "test-i386.h"
-
-#define OP sub
-#include "test-i386.h"
-
-#define OP xor
-#include "test-i386.h"
-
-#define OP and
-#include "test-i386.h"
-
-#define OP or
-#include "test-i386.h"
-
-#define OP cmp
-#include "test-i386.h"
-
-#define OP adc
-#define OP_CC
-#include "test-i386.h"
-
-#define OP sbb
-#define OP_CC
-#include "test-i386.h"
-
-#define OP inc
-#define OP_CC
-#define OP1
-#include "test-i386.h"
-
-#define OP dec
-#define OP_CC
-#define OP1
-#include "test-i386.h"
-
-#define OP neg
-#define OP_CC
-#define OP1
-#include "test-i386.h"
-
-#define OP not
-#define OP_CC
-#define OP1
-#include "test-i386.h"
-
-#undef CC_MASK
-#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)
-
-#define OP shl
-#include "test-i386-shift.h"
-
-#define OP shr
-#include "test-i386-shift.h"
-
-#define OP sar
-#include "test-i386-shift.h"
-
-#define OP rol
-#include "test-i386-shift.h"
-
-#define OP ror
-#include "test-i386-shift.h"
-
-#define OP rcr
-#define OP_CC
-#include "test-i386-shift.h"
-
-#define OP rcl
-#define OP_CC
-#include "test-i386-shift.h"
-
-#define OP shld
-#define OP_SHIFTD
-#define OP_NOBYTE
-#include "test-i386-shift.h"
-
-#define OP shrd
-#define OP_SHIFTD
-#define OP_NOBYTE
-#include "test-i386-shift.h"
-
-/* XXX: should be more precise ? */
-#undef CC_MASK
-#define CC_MASK (CC_C)
-
-#define OP bt
-#define OP_NOBYTE
-#include "test-i386-shift.h"
-
-#define OP bts
-#define OP_NOBYTE
-#include "test-i386-shift.h"
-
-#define OP btr
-#define OP_NOBYTE
-#include "test-i386-shift.h"
-
-#define OP btc
-#define OP_NOBYTE
-#include "test-i386-shift.h"
-
-/* lea test (modrm support) */
-#define TEST_LEAQ(STR)\
-{\
-    asm("lea " STR ", %0"\
-        : "=r" (res)\
-        : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
-    printf("lea %s = " FMTLX "\n", STR, res);\
-}
-
-#define TEST_LEA(STR)\
-{\
-    asm("lea " STR ", %0"\
-        : "=r" (res)\
-        : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
-    printf("lea %s = " FMTLX "\n", STR, res);\
-}
-
-#define TEST_LEA16(STR)\
-{\
-    asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\
-        : "=wq" (res)\
-        : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
-    printf("lea %s = %08lx\n", STR, res);\
-}
-
-
-void test_lea(void)
-{
-    long eax, ebx, ecx, edx, esi, edi, res;
-    eax = i2l(0x0001);
-    ebx = i2l(0x0002);
-    ecx = i2l(0x0004);
-    edx = i2l(0x0008);
-    esi = i2l(0x0010);
-    edi = i2l(0x0020);
-
-    TEST_LEA("0x4000");
-
-    TEST_LEA("(%%eax)");
-    TEST_LEA("(%%ebx)");
-    TEST_LEA("(%%ecx)");
-    TEST_LEA("(%%edx)");
-    TEST_LEA("(%%esi)");
-    TEST_LEA("(%%edi)");
-
-    TEST_LEA("0x40(%%eax)");
-    TEST_LEA("0x40(%%ebx)");
-    TEST_LEA("0x40(%%ecx)");
-    TEST_LEA("0x40(%%edx)");
-    TEST_LEA("0x40(%%esi)");
-    TEST_LEA("0x40(%%edi)");
-
-    TEST_LEA("0x4000(%%eax)");
-    TEST_LEA("0x4000(%%ebx)");
-    TEST_LEA("0x4000(%%ecx)");
-    TEST_LEA("0x4000(%%edx)");
-    TEST_LEA("0x4000(%%esi)");
-    TEST_LEA("0x4000(%%edi)");
-
-    TEST_LEA("(%%eax, %%ecx)");
-    TEST_LEA("(%%ebx, %%edx)");
-    TEST_LEA("(%%ecx, %%ecx)");
-    TEST_LEA("(%%edx, %%ecx)");
-    TEST_LEA("(%%esi, %%ecx)");
-    TEST_LEA("(%%edi, %%ecx)");
-
-    TEST_LEA("0x40(%%eax, %%ecx)");
-    TEST_LEA("0x4000(%%ebx, %%edx)");
-
-    TEST_LEA("(%%ecx, %%ecx, 2)");
-    TEST_LEA("(%%edx, %%ecx, 4)");
-    TEST_LEA("(%%esi, %%ecx, 8)");
-
-    TEST_LEA("(,%%eax, 2)");
-    TEST_LEA("(,%%ebx, 4)");
-    TEST_LEA("(,%%ecx, 8)");
-
-    TEST_LEA("0x40(,%%eax, 2)");
-    TEST_LEA("0x40(,%%ebx, 4)");
-    TEST_LEA("0x40(,%%ecx, 8)");
-
-
-    TEST_LEA("-10(%%ecx, %%ecx, 2)");
-    TEST_LEA("-10(%%edx, %%ecx, 4)");
-    TEST_LEA("-10(%%esi, %%ecx, 8)");
-
-    TEST_LEA("0x4000(%%ecx, %%ecx, 2)");
-    TEST_LEA("0x4000(%%edx, %%ecx, 4)");
-    TEST_LEA("0x4000(%%esi, %%ecx, 8)");
-
-#if defined(__x86_64__)
-    TEST_LEAQ("0x4000");
-    TEST_LEAQ("0x4000(%%rip)");
-
-    TEST_LEAQ("(%%rax)");
-    TEST_LEAQ("(%%rbx)");
-    TEST_LEAQ("(%%rcx)");
-    TEST_LEAQ("(%%rdx)");
-    TEST_LEAQ("(%%rsi)");
-    TEST_LEAQ("(%%rdi)");
-
-    TEST_LEAQ("0x40(%%rax)");
-    TEST_LEAQ("0x40(%%rbx)");
-    TEST_LEAQ("0x40(%%rcx)");
-    TEST_LEAQ("0x40(%%rdx)");
-    TEST_LEAQ("0x40(%%rsi)");
-    TEST_LEAQ("0x40(%%rdi)");
-
-    TEST_LEAQ("0x4000(%%rax)");
-    TEST_LEAQ("0x4000(%%rbx)");
-    TEST_LEAQ("0x4000(%%rcx)");
-    TEST_LEAQ("0x4000(%%rdx)");
-    TEST_LEAQ("0x4000(%%rsi)");
-    TEST_LEAQ("0x4000(%%rdi)");
-
-    TEST_LEAQ("(%%rax, %%rcx)");
-    TEST_LEAQ("(%%rbx, %%rdx)");
-    TEST_LEAQ("(%%rcx, %%rcx)");
-    TEST_LEAQ("(%%rdx, %%rcx)");
-    TEST_LEAQ("(%%rsi, %%rcx)");
-    TEST_LEAQ("(%%rdi, %%rcx)");
-
-    TEST_LEAQ("0x40(%%rax, %%rcx)");
-    TEST_LEAQ("0x4000(%%rbx, %%rdx)");
-
-    TEST_LEAQ("(%%rcx, %%rcx, 2)");
-    TEST_LEAQ("(%%rdx, %%rcx, 4)");
-    TEST_LEAQ("(%%rsi, %%rcx, 8)");
-
-    TEST_LEAQ("(,%%rax, 2)");
-    TEST_LEAQ("(,%%rbx, 4)");
-    TEST_LEAQ("(,%%rcx, 8)");
-
-    TEST_LEAQ("0x40(,%%rax, 2)");
-    TEST_LEAQ("0x40(,%%rbx, 4)");
-    TEST_LEAQ("0x40(,%%rcx, 8)");
-
-
-    TEST_LEAQ("-10(%%rcx, %%rcx, 2)");
-    TEST_LEAQ("-10(%%rdx, %%rcx, 4)");
-    TEST_LEAQ("-10(%%rsi, %%rcx, 8)");
-
-    TEST_LEAQ("0x4000(%%rcx, %%rcx, 2)");
-    TEST_LEAQ("0x4000(%%rdx, %%rcx, 4)");
-    TEST_LEAQ("0x4000(%%rsi, %%rcx, 8)");
-#else
-    /* limited 16 bit addressing test */
-    TEST_LEA16("0x4000");
-    TEST_LEA16("(%%bx)");
-    TEST_LEA16("(%%si)");
-    TEST_LEA16("(%%di)");
-    TEST_LEA16("0x40(%%bx)");
-    TEST_LEA16("0x40(%%si)");
-    TEST_LEA16("0x40(%%di)");
-    TEST_LEA16("0x4000(%%bx)");
-    TEST_LEA16("0x4000(%%si)");
-    TEST_LEA16("(%%bx,%%si)");
-    TEST_LEA16("(%%bx,%%di)");
-    TEST_LEA16("0x40(%%bx,%%si)");
-    TEST_LEA16("0x40(%%bx,%%di)");
-    TEST_LEA16("0x4000(%%bx,%%si)");
-    TEST_LEA16("0x4000(%%bx,%%di)");
-#endif
-}
-
-#define TEST_JCC(JCC, v1, v2)\
-{\
-    int res;\
-    asm("movl $1, %0\n\t"\
-        "cmpl %2, %1\n\t"\
-        "j" JCC " 1f\n\t"\
-        "movl $0, %0\n\t"\
-        "1:\n\t"\
-        : "=r" (res)\
-        : "r" (v1), "r" (v2));\
-    printf("%-10s %d\n", "j" JCC, res);\
-\
-    asm("movl $0, %0\n\t"\
-        "cmpl %2, %1\n\t"\
-        "set" JCC " %b0\n\t"\
-        : "=r" (res)\
-        : "r" (v1), "r" (v2));\
-    printf("%-10s %d\n", "set" JCC, res);\
- if (TEST_CMOV) {\
-    long val = i2l(1);\
-    long res = i2l(0x12345678);\
-X86_64_ONLY(\
-    asm("cmpl %2, %1\n\t"\
-        "cmov" JCC "q %3, %0\n\t"\
-        : "=r" (res)\
-        : "r" (v1), "r" (v2), "m" (val), "0" (res));\
-        printf("%-10s R=" FMTLX "\n", "cmov" JCC "q", res);)\
-    asm("cmpl %2, %1\n\t"\
-        "cmov" JCC "l %k3, %k0\n\t"\
-        : "=r" (res)\
-        : "r" (v1), "r" (v2), "m" (val), "0" (res));\
-        printf("%-10s R=" FMTLX "\n", "cmov" JCC "l", res);\
-    asm("cmpl %2, %1\n\t"\
-        "cmov" JCC "w %w3, %w0\n\t"\
-        : "=r" (res)\
-        : "r" (v1), "r" (v2), "r" (1), "0" (res));\
-        printf("%-10s R=" FMTLX "\n", "cmov" JCC "w", res);\
- } \
-}
-
-/* various jump tests */
-void test_jcc(void)
-{
-    TEST_JCC("ne", 1, 1);
-    TEST_JCC("ne", 1, 0);
-
-    TEST_JCC("e", 1, 1);
-    TEST_JCC("e", 1, 0);
-
-    TEST_JCC("l", 1, 1);
-    TEST_JCC("l", 1, 0);
-    TEST_JCC("l", 1, -1);
-
-    TEST_JCC("le", 1, 1);
-    TEST_JCC("le", 1, 0);
-    TEST_JCC("le", 1, -1);
-
-    TEST_JCC("ge", 1, 1);
-    TEST_JCC("ge", 1, 0);
-    TEST_JCC("ge", -1, 1);
-
-    TEST_JCC("g", 1, 1);
-    TEST_JCC("g", 1, 0);
-    TEST_JCC("g", 1, -1);
-
-    TEST_JCC("b", 1, 1);
-    TEST_JCC("b", 1, 0);
-    TEST_JCC("b", 1, -1);
-
-    TEST_JCC("be", 1, 1);
-    TEST_JCC("be", 1, 0);
-    TEST_JCC("be", 1, -1);
-
-    TEST_JCC("ae", 1, 1);
-    TEST_JCC("ae", 1, 0);
-    TEST_JCC("ae", 1, -1);
-
-    TEST_JCC("a", 1, 1);
-    TEST_JCC("a", 1, 0);
-    TEST_JCC("a", 1, -1);
-
-
-    TEST_JCC("p", 1, 1);
-    TEST_JCC("p", 1, 0);
-
-    TEST_JCC("np", 1, 1);
-    TEST_JCC("np", 1, 0);
-
-    TEST_JCC("o", 0x7fffffff, 0);
-    TEST_JCC("o", 0x7fffffff, -1);
-
-    TEST_JCC("no", 0x7fffffff, 0);
-    TEST_JCC("no", 0x7fffffff, -1);
-
-    TEST_JCC("s", 0, 1);
-    TEST_JCC("s", 0, -1);
-    TEST_JCC("s", 0, 0);
-
-    TEST_JCC("ns", 0, 1);
-    TEST_JCC("ns", 0, -1);
-    TEST_JCC("ns", 0, 0);
-}
-
-#define TEST_LOOP(insn) \
-{\
-    for(i = 0; i < sizeof(ecx_vals) / sizeof(long); i++) {\
-        ecx = ecx_vals[i];\
-        for(zf = 0; zf < 2; zf++) {\
-    asm("test %2, %2\n\t"\
-        "movl $1, %0\n\t"\
-          insn " 1f\n\t" \
-        "movl $0, %0\n\t"\
-        "1:\n\t"\
-        : "=a" (res)\
-        : "c" (ecx), "b" (!zf)); \
-    printf("%-10s ECX=" FMTLX " ZF=%ld r=%d\n", insn, ecx, zf, res);      \
-        }\
-   }\
-}
-
-void test_loop(void)
-{
-    long ecx, zf;
-    const long ecx_vals[] = {
-        0,
-        1,
-        0x10000,
-        0x10001,
-#if defined(__x86_64__)
-        0x100000000L,
-        0x100000001L,
-#endif
-    };
-    int i, res;
-
-#if !defined(__x86_64__)
-    TEST_LOOP("jcxz");
-    TEST_LOOP("loopw");
-    TEST_LOOP("loopzw");
-    TEST_LOOP("loopnzw");
-#endif
-
-    TEST_LOOP("jecxz");
-    TEST_LOOP("loopl");
-    TEST_LOOP("loopzl");
-    TEST_LOOP("loopnzl");
-}
-
-#undef CC_MASK
-#ifdef TEST_P4_FLAGS
-#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
-#else
-#define CC_MASK (CC_O | CC_C)
-#endif
-
-#define OP mul
-#include "test-i386-muldiv.h"
-
-#define OP imul
-#include "test-i386-muldiv.h"
-
-void test_imulw2(long op0, long op1)
-{
-    long res, s1, s0, flags;
-    s0 = op0;
-    s1 = op1;
-    res = s0;
-    flags = 0;
-    asm volatile ("push %4\n\t"
-         "popf\n\t"
-         "imulw %w2, %w0\n\t"
-         "pushf\n\t"
-         "pop %1\n\t"
-         : "=q" (res), "=g" (flags)
-         : "q" (s1), "0" (res), "1" (flags));
-    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
-           "imulw", s0, s1, res, flags & CC_MASK);
-}
-
-void test_imull2(long op0, long op1)
-{
-    long res, s1, s0, flags;
-    s0 = op0;
-    s1 = op1;
-    res = s0;
-    flags = 0;
-    asm volatile ("push %4\n\t"
-         "popf\n\t"
-         "imull %k2, %k0\n\t"
-         "pushf\n\t"
-         "pop %1\n\t"
-         : "=q" (res), "=g" (flags)
-         : "q" (s1), "0" (res), "1" (flags));
-    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
-           "imull", s0, s1, res, flags & CC_MASK);
-}
-
-#if defined(__x86_64__)
-void test_imulq2(long op0, long op1)
-{
-    long res, s1, s0, flags;
-    s0 = op0;
-    s1 = op1;
-    res = s0;
-    flags = 0;
-    asm volatile ("push %4\n\t"
-         "popf\n\t"
-         "imulq %2, %0\n\t"
-         "pushf\n\t"
-         "pop %1\n\t"
-         : "=q" (res), "=g" (flags)
-         : "q" (s1), "0" (res), "1" (flags));
-    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
-           "imulq", s0, s1, res, flags & CC_MASK);
-}
-#endif
-
-#define TEST_IMUL_IM(size, rsize, op0, op1)\
-{\
-    long res, flags, s1;\
-    flags = 0;\
-    res = 0;\
-    s1 = op1;\
-    asm volatile ("push %3\n\t"\
-         "popf\n\t"\
-         "imul" size " $" #op0 ", %" rsize "2, %" rsize "0\n\t" \
-         "pushf\n\t"\
-         "pop %1\n\t"\
-         : "=r" (res), "=g" (flags)\
-         : "r" (s1), "1" (flags), "0" (res));\
-    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",\
-           "imul" size " im", (long)op0, (long)op1, res, flags & CC_MASK);\
-}
-
-
-#undef CC_MASK
-#define CC_MASK (0)
-
-#define OP div
-#include "test-i386-muldiv.h"
-
-#define OP idiv
-#include "test-i386-muldiv.h"
-
-void test_mul(void)
-{
-    test_imulb(0x1234561d, 4);
-    test_imulb(3, -4);
-    test_imulb(0x80, 0x80);
-    test_imulb(0x10, 0x10);
-
-    test_imulw(0, 0x1234001d, 45);
-    test_imulw(0, 23, -45);
-    test_imulw(0, 0x8000, 0x8000);
-    test_imulw(0, 0x100, 0x100);
-
-    test_imull(0, 0x1234001d, 45);
-    test_imull(0, 23, -45);
-    test_imull(0, 0x80000000, 0x80000000);
-    test_imull(0, 0x10000, 0x10000);
-
-    test_mulb(0x1234561d, 4);
-    test_mulb(3, -4);
-    test_mulb(0x80, 0x80);
-    test_mulb(0x10, 0x10);
-
-    test_mulw(0, 0x1234001d, 45);
-    test_mulw(0, 23, -45);
-    test_mulw(0, 0x8000, 0x8000);
-    test_mulw(0, 0x100, 0x100);
-
-    test_mull(0, 0x1234001d, 45);
-    test_mull(0, 23, -45);
-    test_mull(0, 0x80000000, 0x80000000);
-    test_mull(0, 0x10000, 0x10000);
-
-    test_imulw2(0x1234001d, 45);
-    test_imulw2(23, -45);
-    test_imulw2(0x8000, 0x8000);
-    test_imulw2(0x100, 0x100);
-
-    test_imull2(0x1234001d, 45);
-    test_imull2(23, -45);
-    test_imull2(0x80000000, 0x80000000);
-    test_imull2(0x10000, 0x10000);
-
-    TEST_IMUL_IM("w", "w", 45, 0x1234);
-    TEST_IMUL_IM("w", "w", -45, 23);
-    TEST_IMUL_IM("w", "w", 0x8000, 0x80000000);
-    TEST_IMUL_IM("w", "w", 0x7fff, 0x1000);
-
-    TEST_IMUL_IM("l", "k", 45, 0x1234);
-    TEST_IMUL_IM("l", "k", -45, 23);
-    TEST_IMUL_IM("l", "k", 0x8000, 0x80000000);
-    TEST_IMUL_IM("l", "k", 0x7fff, 0x1000);
-
-    test_idivb(0x12341678, 0x127e);
-    test_idivb(0x43210123, -5);
-    test_idivb(0x12340004, -1);
-
-    test_idivw(0, 0x12345678, 12347);
-    test_idivw(0, -23223, -45);
-    test_idivw(0, 0x12348000, -1);
-    test_idivw(0x12343, 0x12345678, 0x81238567);
-
-    test_idivl(0, 0x12345678, 12347);
-    test_idivl(0, -233223, -45);
-    test_idivl(0, 0x80000000, -1);
-    test_idivl(0x12343, 0x12345678, 0x81234567);
-
-    test_divb(0x12341678, 0x127e);
-    test_divb(0x43210123, -5);
-    test_divb(0x12340004, -1);
-
-    test_divw(0, 0x12345678, 12347);
-    test_divw(0, -23223, -45);
-    test_divw(0, 0x12348000, -1);
-    test_divw(0x12343, 0x12345678, 0x81238567);
-
-    test_divl(0, 0x12345678, 12347);
-    test_divl(0, -233223, -45);
-    test_divl(0, 0x80000000, -1);
-    test_divl(0x12343, 0x12345678, 0x81234567);
-
-#if defined(__x86_64__)
-    test_imulq(0, 0x1234001d1234001d, 45);
-    test_imulq(0, 23, -45);
-    test_imulq(0, 0x8000000000000000, 0x8000000000000000);
-    test_imulq(0, 0x100000000, 0x100000000);
-
-    test_mulq(0, 0x1234001d1234001d, 45);
-    test_mulq(0, 23, -45);
-    test_mulq(0, 0x8000000000000000, 0x8000000000000000);
-    test_mulq(0, 0x100000000, 0x100000000);
-
-    test_imulq2(0x1234001d1234001d, 45);
-    test_imulq2(23, -45);
-    test_imulq2(0x8000000000000000, 0x8000000000000000);
-    test_imulq2(0x100000000, 0x100000000);
-
-    TEST_IMUL_IM("q", "", 45, 0x12341234);
-    TEST_IMUL_IM("q", "", -45, 23);
-    TEST_IMUL_IM("q", "", 0x8000, 0x8000000000000000);
-    TEST_IMUL_IM("q", "", 0x7fff, 0x10000000);
-
-    test_idivq(0, 0x12345678abcdef, 12347);
-    test_idivq(0, -233223, -45);
-    test_idivq(0, 0x8000000000000000, -1);
-    test_idivq(0x12343, 0x12345678, 0x81234567);
-
-    test_divq(0, 0x12345678abcdef, 12347);
-    test_divq(0, -233223, -45);
-    test_divq(0, 0x8000000000000000, -1);
-    test_divq(0x12343, 0x12345678, 0x81234567);
-#endif
-}
-
-#define TEST_BSX(op, size, op0)\
-{\
-    long res, val, resz;\
-    val = op0;\
-    asm("xor %1, %1\n"\
-        "mov $0x12345678, %0\n"\
-        #op " %" size "2, %" size "0 ; setz %b1" \
-        : "=&r" (res), "=&q" (resz)\
-        : "r" (val));\
-    printf("%-10s A=" FMTLX " R=" FMTLX " %ld\n", #op, val, res, resz);\
-}
-
-void test_bsx(void)
-{
-    TEST_BSX(bsrw, "w", 0);
-    TEST_BSX(bsrw, "w", 0x12340128);
-    TEST_BSX(bsfw, "w", 0);
-    TEST_BSX(bsfw, "w", 0x12340128);
-    TEST_BSX(bsrl, "k", 0);
-    TEST_BSX(bsrl, "k", 0x00340128);
-    TEST_BSX(bsfl, "k", 0);
-    TEST_BSX(bsfl, "k", 0x00340128);
-#if defined(__x86_64__)
-    TEST_BSX(bsrq, "", 0);
-    TEST_BSX(bsrq, "", 0x003401281234);
-    TEST_BSX(bsfq, "", 0);
-    TEST_BSX(bsfq, "", 0x003401281234);
-#endif
-}
-
-/**********************************************/
-
-union float64u {
-    double d;
-    uint64_t l;
-};
-
-union float64u q_nan = { .l = 0xFFF8000000000000LL };
-union float64u s_nan = { .l = 0xFFF0000000000000LL };
-
-void test_fops(double a, double b)
-{
-    printf("a=%f b=%f a+b=%f\n", a, b, a + b);
-    printf("a=%f b=%f a-b=%f\n", a, b, a - b);
-    printf("a=%f b=%f a*b=%f\n", a, b, a * b);
-    printf("a=%f b=%f a/b=%f\n", a, b, a / b);
-    printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b));
-    printf("a=%f sqrt(a)=%f\n", a, sqrt(a));
-    printf("a=%f sin(a)=%f\n", a, sin(a));
-    printf("a=%f cos(a)=%f\n", a, cos(a));
-    printf("a=%f tan(a)=%f\n", a, tan(a));
-    printf("a=%f log(a)=%f\n", a, log(a));
-    printf("a=%f exp(a)=%f\n", a, exp(a));
-    printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
-    /* just to test some op combining */
-    printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a)));
-    printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a)));
-    printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));
-
-}
-
-void fpu_clear_exceptions(void)
-{
-    struct QEMU_PACKED {
-        uint16_t fpuc;
-        uint16_t dummy1;
-        uint16_t fpus;
-        uint16_t dummy2;
-        uint16_t fptag;
-        uint16_t dummy3;
-        uint32_t ignored[4];
-        long double fpregs[8];
-    } float_env32;
-
-    asm volatile ("fnstenv %0\n" : : "m" (float_env32));
-    float_env32.fpus &= ~0x7f;
-    asm volatile ("fldenv %0\n" : : "m" (float_env32));
-}
-
-/* XXX: display exception bits when supported */
-#define FPUS_EMASK 0x0000
-//#define FPUS_EMASK 0x007f
-
-void test_fcmp(double a, double b)
-{
-    long eflags, fpus;
-
-    fpu_clear_exceptions();
-    asm("fcom %2\n"
-        "fstsw %%ax\n"
-        : "=a" (fpus)
-        : "t" (a), "u" (b));
-    printf("fcom(%f %f)=%04lx\n",
-           a, b, fpus & (0x4500 | FPUS_EMASK));
-    fpu_clear_exceptions();
-    asm("fucom %2\n"
-        "fstsw %%ax\n"
-        : "=a" (fpus)
-        : "t" (a), "u" (b));
-    printf("fucom(%f %f)=%04lx\n",
-           a, b, fpus & (0x4500 | FPUS_EMASK));
-    if (TEST_FCOMI) {
-        /* test f(u)comi instruction */
-        fpu_clear_exceptions();
-        asm("fcomi %3, %2\n"
-            "fstsw %%ax\n"
-            "pushf\n"
-            "pop %0\n"
-            : "=r" (eflags), "=a" (fpus)
-            : "t" (a), "u" (b));
-        printf("fcomi(%f %f)=%04lx %02lx\n",
-               a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C));
-        fpu_clear_exceptions();
-        asm("fucomi %3, %2\n"
-            "fstsw %%ax\n"
-            "pushf\n"
-            "pop %0\n"
-            : "=r" (eflags), "=a" (fpus)
-            : "t" (a), "u" (b));
-        printf("fucomi(%f %f)=%04lx %02lx\n",
-               a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C));
-    }
-    fpu_clear_exceptions();
-    asm volatile("fxam\n"
-                 "fstsw %%ax\n"
-                 : "=a" (fpus)
-                 : "t" (a));
-    printf("fxam(%f)=%04lx\n", a, fpus & 0x4700);
-    fpu_clear_exceptions();
-}
-
-void test_fcvt(double a)
-{
-    float fa;
-    long double la;
-    int16_t fpuc;
-    int i;
-    int64_t lla;
-    int ia;
-    int16_t wa;
-    double ra;
-
-    fa = a;
-    la = a;
-    printf("(float)%f = %f\n", a, fa);
-    printf("(long double)%f = %Lf\n", a, la);
-    printf("a=" FMT64X "\n", *(uint64_t *)&a);
-    printf("la=" FMT64X " %04x\n", *(uint64_t *)&la,
-           *(unsigned short *)((char *)(&la) + 8));
-
-    /* test all roundings */
-    asm volatile ("fstcw %0" : "=m" (fpuc));
-    for(i=0;i<4;i++) {
-        uint16_t val16;
-        val16 = (fpuc & ~0x0c00) | (i << 10);
-        asm volatile ("fldcw %0" : : "m" (val16));
-        asm volatile ("fist %0" : "=m" (wa) : "t" (a));
-        asm volatile ("fistl %0" : "=m" (ia) : "t" (a));
-        asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st");
-        asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a));
-        asm volatile ("fldcw %0" : : "m" (fpuc));
-        printf("(short)a = %d\n", wa);
-        printf("(int)a = %d\n", ia);
-        printf("(int64_t)a = " FMT64X "\n", lla);
-        printf("rint(a) = %f\n", ra);
-    }
-}
-
-#define TEST(N) \
-    asm("fld" #N : "=t" (a)); \
-    printf("fld" #N "= %f\n", a);
-
-void test_fconst(void)
-{
-    double a;
-    TEST(1);
-    TEST(l2t);
-    TEST(l2e);
-    TEST(pi);
-    TEST(lg2);
-    TEST(ln2);
-    TEST(z);
-}
-
-void test_fbcd(double a)
-{
-    unsigned short bcd[5];
-    double b;
-
-    asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st");
-    asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
-    printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n",
-           a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);
-}
-
-#define TEST_ENV(env, save, restore)\
-{\
-    memset((env), 0xaa, sizeof(*(env)));\
-    for(i=0;i<5;i++)\
-        asm volatile ("fldl %0" : : "m" (dtab[i]));\
-    asm volatile (save " %0\n" : : "m" (*(env)));\
-    asm volatile (restore " %0\n": : "m" (*(env)));\
-    for(i=0;i<5;i++)\
-        asm volatile ("fstpl %0" : "=m" (rtab[i]));\
-    for(i=0;i<5;i++)\
-        printf("res[%d]=%f\n", i, rtab[i]);\
-    printf("fpuc=%04x fpus=%04x fptag=%04x\n",\
-           (env)->fpuc,\
-           (env)->fpus & 0xff00,\
-           (env)->fptag);\
-}
-
-void test_fenv(void)
-{
-    struct QEMU_PACKED {
-        uint16_t fpuc;
-        uint16_t dummy1;
-        uint16_t fpus;
-        uint16_t dummy2;
-        uint16_t fptag;
-        uint16_t dummy3;
-        uint32_t ignored[4];
-        long double fpregs[8];
-    } float_env32;
-    struct QEMU_PACKED {
-        uint16_t fpuc;
-        uint16_t fpus;
-        uint16_t fptag;
-        uint16_t ignored[4];
-        long double fpregs[8];
-    } float_env16;
-    double dtab[8];
-    double rtab[8];
-    int i;
-
-    for(i=0;i<8;i++)
-        dtab[i] = i + 1;
-
-    TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv");
-    TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor");
-    TEST_ENV(&float_env32, "fnstenv", "fldenv");
-    TEST_ENV(&float_env32, "fnsave", "frstor");
-
-    /* test for ffree */
-    for(i=0;i<5;i++)
-        asm volatile ("fldl %0" : : "m" (dtab[i]));
-    asm volatile("ffree %st(2)");
-    asm volatile ("fnstenv %0\n" : : "m" (float_env32));
-    asm volatile ("fninit");
-    printf("fptag=%04x\n", float_env32.fptag);
-}
-
-
-#define TEST_FCMOV(a, b, eflags, CC)\
-{\
-    double res;\
-    asm("push %3\n"\
-        "popf\n"\
-        "fcmov" CC " %2, %0\n"\
-        : "=t" (res)\
-        : "0" (a), "u" (b), "g" (eflags));\
-    printf("fcmov%s eflags=0x%04lx-> %f\n", \
-           CC, (long)eflags, res);\
-}
-
-void test_fcmov(void)
-{
-    double a, b;
-    long eflags, i;
-
-    a = 1.0;
-    b = 2.0;
-    for(i = 0; i < 4; i++) {
-        eflags = 0;
-        if (i & 1)
-            eflags |= CC_C;
-        if (i & 2)
-            eflags |= CC_Z;
-        TEST_FCMOV(a, b, eflags, "b");
-        TEST_FCMOV(a, b, eflags, "e");
-        TEST_FCMOV(a, b, eflags, "be");
-        TEST_FCMOV(a, b, eflags, "nb");
-        TEST_FCMOV(a, b, eflags, "ne");
-        TEST_FCMOV(a, b, eflags, "nbe");
-    }
-    TEST_FCMOV(a, b, 0, "u");
-    TEST_FCMOV(a, b, CC_P, "u");
-    TEST_FCMOV(a, b, 0, "nu");
-    TEST_FCMOV(a, b, CC_P, "nu");
-}
-
-void test_floats(void)
-{
-    test_fops(2, 3);
-    test_fops(1.4, -5);
-    test_fcmp(2, -1);
-    test_fcmp(2, 2);
-    test_fcmp(2, 3);
-    test_fcmp(2, q_nan.d);
-    test_fcmp(q_nan.d, -1);
-    test_fcmp(-1.0/0.0, -1);
-    test_fcmp(1.0/0.0, -1);
-    test_fcvt(0.5);
-    test_fcvt(-0.5);
-    test_fcvt(1.0/7.0);
-    test_fcvt(-1.0/9.0);
-    test_fcvt(32768);
-    test_fcvt(-1e20);
-    test_fcvt(-1.0/0.0);
-    test_fcvt(1.0/0.0);
-    test_fcvt(q_nan.d);
-    test_fconst();
-    test_fbcd(1234567890123456.0);
-    test_fbcd(-123451234567890.0);
-    test_fenv();
-    if (TEST_CMOV) {
-        test_fcmov();
-    }
-}
-
-/**********************************************/
-#if !defined(__x86_64__)
-
-#define TEST_BCD(op, op0, cc_in, cc_mask)\
-{\
-    int res, flags;\
-    res = op0;\
-    flags = cc_in;\
-    asm ("push %3\n\t"\
-         "popf\n\t"\
-         #op "\n\t"\
-         "pushf\n\t"\
-         "pop %1\n\t"\
-        : "=a" (res), "=g" (flags)\
-        : "0" (res), "1" (flags));\
-    printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\
-           #op, op0, res, cc_in, flags & cc_mask);\
-}
-
-void test_bcd(void)
-{
-    TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-
-    TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-    TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
-
-    TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A));
-    TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A));
-    TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A));
-    TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A));
-    TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A));
-    TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A));
-    TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A));
-    TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A));
-
-    TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A));
-    TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A));
-    TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A));
-    TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A));
-    TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A));
-    TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A));
-    TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A));
-    TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A));
-
-    TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
-    TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
-}
-#endif
-
-#define TEST_XCHG(op, size, opconst)\
-{\
-    long op0, op1;\
-    op0 = i2l(0x12345678);\
-    op1 = i2l(0xfbca7654);\
-    asm(#op " %" size "0, %" size "1" \
-        : "=q" (op0), opconst (op1) \
-        : "0" (op0));\
-    printf("%-10s A=" FMTLX " B=" FMTLX "\n",\
-           #op, op0, op1);\
-}
-
-#define TEST_CMPXCHG(op, size, opconst, eax)\
-{\
-    long op0, op1, op2;\
-    op0 = i2l(0x12345678);\
-    op1 = i2l(0xfbca7654);\
-    op2 = i2l(eax);\
-    asm(#op " %" size "0, %" size "1" \
-        : "=q" (op0), opconst (op1) \
-        : "0" (op0), "a" (op2));\
-    printf("%-10s EAX=" FMTLX " A=" FMTLX " C=" FMTLX "\n",\
-           #op, op2, op0, op1);\
-}
-
-void test_xchg(void)
-{
-#if defined(__x86_64__)
-    TEST_XCHG(xchgq, "", "+q");
-#endif
-    TEST_XCHG(xchgl, "k", "+q");
-    TEST_XCHG(xchgw, "w", "+q");
-    TEST_XCHG(xchgb, "b", "+q");
-
-#if defined(__x86_64__)
-    TEST_XCHG(xchgq, "", "=m");
-#endif
-    TEST_XCHG(xchgl, "k", "+m");
-    TEST_XCHG(xchgw, "w", "+m");
-    TEST_XCHG(xchgb, "b", "+m");
-
-#if defined(__x86_64__)
-    TEST_XCHG(xaddq, "", "+q");
-#endif
-    TEST_XCHG(xaddl, "k", "+q");
-    TEST_XCHG(xaddw, "w", "+q");
-    TEST_XCHG(xaddb, "b", "+q");
-
-    {
-        int res;
-        res = 0x12345678;
-        asm("xaddl %1, %0" : "=r" (res) : "0" (res));
-        printf("xaddl same res=%08x\n", res);
-    }
-
-#if defined(__x86_64__)
-    TEST_XCHG(xaddq, "", "+m");
-#endif
-    TEST_XCHG(xaddl, "k", "+m");
-    TEST_XCHG(xaddw, "w", "+m");
-    TEST_XCHG(xaddb, "b", "+m");
-
-#if defined(__x86_64__)
-    TEST_CMPXCHG(cmpxchgq, "", "+q", 0xfbca7654);
-#endif
-    TEST_CMPXCHG(cmpxchgl, "k", "+q", 0xfbca7654);
-    TEST_CMPXCHG(cmpxchgw, "w", "+q", 0xfbca7654);
-    TEST_CMPXCHG(cmpxchgb, "b", "+q", 0xfbca7654);
-
-#if defined(__x86_64__)
-    TEST_CMPXCHG(cmpxchgq, "", "+q", 0xfffefdfc);
-#endif
-    TEST_CMPXCHG(cmpxchgl, "k", "+q", 0xfffefdfc);
-    TEST_CMPXCHG(cmpxchgw, "w", "+q", 0xfffefdfc);
-    TEST_CMPXCHG(cmpxchgb, "b", "+q", 0xfffefdfc);
-
-#if defined(__x86_64__)
-    TEST_CMPXCHG(cmpxchgq, "", "+m", 0xfbca7654);
-#endif
-    TEST_CMPXCHG(cmpxchgl, "k", "+m", 0xfbca7654);
-    TEST_CMPXCHG(cmpxchgw, "w", "+m", 0xfbca7654);
-    TEST_CMPXCHG(cmpxchgb, "b", "+m", 0xfbca7654);
-
-#if defined(__x86_64__)
-    TEST_CMPXCHG(cmpxchgq, "", "+m", 0xfffefdfc);
-#endif
-    TEST_CMPXCHG(cmpxchgl, "k", "+m", 0xfffefdfc);
-    TEST_CMPXCHG(cmpxchgw, "w", "+m", 0xfffefdfc);
-    TEST_CMPXCHG(cmpxchgb, "b", "+m", 0xfffefdfc);
-
-    {
-        uint64_t op0, op1, op2;
-        long eax, edx;
-        long i, eflags;
-
-        for(i = 0; i < 2; i++) {
-            op0 = 0x123456789abcdLL;
-            eax = i2l(op0 & 0xffffffff);
-            edx = i2l(op0 >> 32);
-            if (i == 0)
-                op1 = 0xfbca765423456LL;
-            else
-                op1 = op0;
-            op2 = 0x6532432432434LL;
-            asm("cmpxchg8b %2\n"
-                "pushf\n"
-                "pop %3\n"
-                : "=a" (eax), "=d" (edx), "=m" (op1), "=g" (eflags)
-                : "0" (eax), "1" (edx), "m" (op1), "b" ((int)op2), "c" ((int)(op2 >> 32)));
-            printf("cmpxchg8b: eax=" FMTLX " edx=" FMTLX " op1=" FMT64X " CC=%02lx\n",
-                   eax, edx, op1, eflags & CC_Z);
-        }
-    }
-}
-
-#ifdef TEST_SEGS
-/**********************************************/
-/* segmentation tests */
-
-#include <sys/syscall.h>
-#include <unistd.h>
-#include <asm/ldt.h>
-#include <linux/version.h>
-
-static inline int modify_ldt(int func, void * ptr, unsigned long bytecount)
-{
-    return syscall(__NR_modify_ldt, func, ptr, bytecount);
-}
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
-#define modify_ldt_ldt_s user_desc
-#endif
-
-#define MK_SEL(n) (((n) << 3) | 7)
-
-uint8_t seg_data1[4096];
-uint8_t seg_data2[4096];
-
-#define TEST_LR(op, size, seg, mask)\
-{\
-    int res, res2;\
-    uint16_t mseg = seg;\
-    res = 0x12345678;\
-    asm (op " %" size "2, %" size "0\n" \
-         "movl $0, %1\n"\
-         "jnz 1f\n"\
-         "movl $1, %1\n"\
-         "1:\n"\
-         : "=r" (res), "=r" (res2) : "m" (mseg), "0" (res));\
-    printf(op ": Z=%d %08x\n", res2, res & ~(mask));\
-}
-
-#define TEST_ARPL(op, size, op1, op2)\
-{\
-    long a, b, c;                               \
-    a = (op1);                                  \
-    b = (op2);                                  \
-    asm volatile(op " %" size "3, %" size "0\n"\
-                 "movl $0,%1\n"\
-                 "jnz 1f\n"\
-                 "movl $1,%1\n"\
-                 "1:\n"\
-                 : "=r" (a), "=r" (c) : "0" (a), "r" (b));    \
-    printf(op size " A=" FMTLX " B=" FMTLX " R=" FMTLX " z=%ld\n",\
-           (long)(op1), (long)(op2), a, c);\
-}
-
-/* NOTE: we use Linux modify_ldt syscall */
-void test_segs(void)
-{
-    struct modify_ldt_ldt_s ldt;
-    long long ldt_table[3];
-    int res, res2;
-    char tmp;
-    struct {
-        uint32_t offset;
-        uint16_t seg;
-    } QEMU_PACKED segoff;
-
-    ldt.entry_number = 1;
-    ldt.base_addr = (unsigned long)&seg_data1;
-    ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
-    ldt.seg_32bit = 1;
-    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
-    ldt.read_exec_only = 0;
-    ldt.limit_in_pages = 1;
-    ldt.seg_not_present = 0;
-    ldt.useable = 1;
-    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
-
-    ldt.entry_number = 2;
-    ldt.base_addr = (unsigned long)&seg_data2;
-    ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12;
-    ldt.seg_32bit = 1;
-    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
-    ldt.read_exec_only = 0;
-    ldt.limit_in_pages = 1;
-    ldt.seg_not_present = 0;
-    ldt.useable = 1;
-    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
-
-    modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */
-#if 0
-    {
-        int i;
-        for(i=0;i<3;i++)
-            printf("%d: %016Lx\n", i, ldt_table[i]);
-    }
-#endif
-    /* do some tests with fs or gs */
-    asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
-
-    seg_data1[1] = 0xaa;
-    seg_data2[1] = 0x55;
-
-    asm volatile ("fs movzbl 0x1, %0" : "=r" (res));
-    printf("FS[1] = %02x\n", res);
-
-    asm volatile ("pushl %%gs\n"
-                  "movl %1, %%gs\n"
-                  "gs movzbl 0x1, %0\n"
-                  "popl %%gs\n"
-                  : "=r" (res)
-                  : "r" (MK_SEL(2)));
-    printf("GS[1] = %02x\n", res);
-
-    /* tests with ds/ss (implicit segment case) */
-    tmp = 0xa5;
-    asm volatile ("pushl %%ebp\n\t"
-                  "pushl %%ds\n\t"
-                  "movl %2, %%ds\n\t"
-                  "movl %3, %%ebp\n\t"
-                  "movzbl 0x1, %0\n\t"
-                  "movzbl (%%ebp), %1\n\t"
-                  "popl %%ds\n\t"
-                  "popl %%ebp\n\t"
-                  : "=r" (res), "=r" (res2)
-                  : "r" (MK_SEL(1)), "r" (&tmp));
-    printf("DS[1] = %02x\n", res);
-    printf("SS[tmp] = %02x\n", res2);
-
-    segoff.seg = MK_SEL(2);
-    segoff.offset = 0xabcdef12;
-    asm volatile("lfs %2, %0\n\t"
-                 "movl %%fs, %1\n\t"
-                 : "=r" (res), "=g" (res2)
-                 : "m" (segoff));
-    printf("FS:reg = %04x:%08x\n", res2, res);
-
-    TEST_LR("larw", "w", MK_SEL(2), 0x0100);
-    TEST_LR("larl", "", MK_SEL(2), 0x0100);
-    TEST_LR("lslw", "w", MK_SEL(2), 0);
-    TEST_LR("lsll", "", MK_SEL(2), 0);
-
-    TEST_LR("larw", "w", 0xfff8, 0);
-    TEST_LR("larl", "", 0xfff8, 0);
-    TEST_LR("lslw", "w", 0xfff8, 0);
-    TEST_LR("lsll", "", 0xfff8, 0);
-
-    TEST_ARPL("arpl", "w", 0x12345678 | 3, 0x762123c | 1);
-    TEST_ARPL("arpl", "w", 0x12345678 | 1, 0x762123c | 3);
-    TEST_ARPL("arpl", "w", 0x12345678 | 1, 0x762123c | 1);
-}
-
-/* 16 bit code test */
-extern char code16_start, code16_end;
-extern char code16_func1;
-extern char code16_func2;
-extern char code16_func3;
-
-void test_code16(void)
-{
-    struct modify_ldt_ldt_s ldt;
-    int res, res2;
-
-    /* build a code segment */
-    ldt.entry_number = 1;
-    ldt.base_addr = (unsigned long)&code16_start;
-    ldt.limit = &code16_end - &code16_start;
-    ldt.seg_32bit = 0;
-    ldt.contents = MODIFY_LDT_CONTENTS_CODE;
-    ldt.read_exec_only = 0;
-    ldt.limit_in_pages = 0;
-    ldt.seg_not_present = 0;
-    ldt.useable = 1;
-    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
-
-    /* call the first function */
-    asm volatile ("lcall %1, %2"
-                  : "=a" (res)
-                  : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc");
-    printf("func1() = 0x%08x\n", res);
-    asm volatile ("lcall %2, %3"
-                  : "=a" (res), "=c" (res2)
-                  : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc");
-    printf("func2() = 0x%08x spdec=%d\n", res, res2);
-    asm volatile ("lcall %1, %2"
-                  : "=a" (res)
-                  : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc");
-    printf("func3() = 0x%08x\n", res);
-}
-#endif
-
-#if defined(__x86_64__)
-asm(".globl func_lret\n"
-    "func_lret:\n"
-    "movl $0x87654641, %eax\n"
-    "lretq\n");
-#else
-asm(".globl func_lret\n"
-    "func_lret:\n"
-    "movl $0x87654321, %eax\n"
-    "lret\n"
-
-    ".globl func_iret\n"
-    "func_iret:\n"
-    "movl $0xabcd4321, %eax\n"
-    "iret\n");
-#endif
-
-extern char func_lret;
-extern char func_iret;
-
-void test_misc(void)
-{
-    char table[256];
-    long res, i;
-
-    for(i=0;i<256;i++) table[i] = 256 - i;
-    res = 0x12345678;
-    asm ("xlat" : "=a" (res) : "b" (table), "0" (res));
-    printf("xlat: EAX=" FMTLX "\n", res);
-
-#if defined(__x86_64__)
-#if 0
-    {
-        /* XXX: see if Intel Core2 and AMD64 behavior really
-           differ. Here we implemented the Intel way which is not
-           compatible yet with QEMU. */
-        static struct QEMU_PACKED {
-            uint64_t offset;
-            uint16_t seg;
-        } desc;
-        long cs_sel;
-
-        asm volatile ("mov %%cs, %0" : "=r" (cs_sel));
-
-        asm volatile ("push %1\n"
-                      "call func_lret\n"
-                      : "=a" (res)
-                      : "r" (cs_sel) : "memory", "cc");
-        printf("func_lret=" FMTLX "\n", res);
-
-        desc.offset = (long)&func_lret;
-        desc.seg = cs_sel;
-
-        asm volatile ("xor %%rax, %%rax\n"
-                      "rex64 lcall *(%%rcx)\n"
-                      : "=a" (res)
-                      : "c" (&desc)
-                      : "memory", "cc");
-        printf("func_lret2=" FMTLX "\n", res);
-
-        asm volatile ("push %2\n"
-                      "mov $ 1f, %%rax\n"
-                      "push %%rax\n"
-                      "rex64 ljmp *(%%rcx)\n"
-                      "1:\n"
-                      : "=a" (res)
-                      : "c" (&desc), "b" (cs_sel)
-                      : "memory", "cc");
-        printf("func_lret3=" FMTLX "\n", res);
-    }
-#endif
-#else
-    asm volatile ("push %%cs ; call %1"
-                  : "=a" (res)
-                  : "m" (func_lret): "memory", "cc");
-    printf("func_lret=" FMTLX "\n", res);
-
-    asm volatile ("pushf ; push %%cs ; call %1"
-                  : "=a" (res)
-                  : "m" (func_iret): "memory", "cc");
-    printf("func_iret=" FMTLX "\n", res);
-#endif
-
-#if defined(__x86_64__)
-    /* specific popl test */
-    asm volatile ("push $12345432 ; push $0x9abcdef ; pop (%%rsp) ; pop %0"
-                  : "=g" (res));
-    printf("popl esp=" FMTLX "\n", res);
-#else
-    /* specific popl test */
-    asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popl (%%esp) ; popl %0"
-                  : "=g" (res));
-    printf("popl esp=" FMTLX "\n", res);
-
-    /* specific popw test */
-    asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popw (%%esp) ; addl $2, %%esp ; popl %0"
-                  : "=g" (res));
-    printf("popw esp=" FMTLX "\n", res);
-#endif
-}
-
-uint8_t str_buffer[4096];
-
-#define TEST_STRING1(OP, size, DF, REP)\
-{\
-    long esi, edi, eax, ecx, eflags;\
-\
-    esi = (long)(str_buffer + sizeof(str_buffer) / 2);\
-    edi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\
-    eax = i2l(0x12345678);\
-    ecx = 17;\
-\
-    asm volatile ("push $0\n\t"\
-                  "popf\n\t"\
-                  DF "\n\t"\
-                  REP #OP size "\n\t"\
-                  "cld\n\t"\
-                  "pushf\n\t"\
-                  "pop %4\n\t"\
-                  : "=S" (esi), "=D" (edi), "=a" (eax), "=c" (ecx), "=g" (eflags)\
-                  : "0" (esi), "1" (edi), "2" (eax), "3" (ecx));\
-    printf("%-10s ESI=" FMTLX " EDI=" FMTLX " EAX=" FMTLX " ECX=" FMTLX " EFL=%04x\n",\
-           REP #OP size, esi, edi, eax, ecx,\
-           (int)(eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)));\
-}
-
-#define TEST_STRING(OP, REP)\
-    TEST_STRING1(OP, "b", "", REP);\
-    TEST_STRING1(OP, "w", "", REP);\
-    TEST_STRING1(OP, "l", "", REP);\
-    X86_64_ONLY(TEST_STRING1(OP, "q", "", REP));\
-    TEST_STRING1(OP, "b", "std", REP);\
-    TEST_STRING1(OP, "w", "std", REP);\
-    TEST_STRING1(OP, "l", "std", REP);\
-    X86_64_ONLY(TEST_STRING1(OP, "q", "std", REP))
-
-void test_string(void)
-{
-    int i;
-    for(i = 0;i < sizeof(str_buffer); i++)
-        str_buffer[i] = i + 0x56;
-   TEST_STRING(stos, "");
-   TEST_STRING(stos, "rep ");
-   TEST_STRING(lods, ""); /* to verify stos */
-   TEST_STRING(lods, "rep ");
-   TEST_STRING(movs, "");
-   TEST_STRING(movs, "rep ");
-   TEST_STRING(lods, ""); /* to verify stos */
-
-   /* XXX: better tests */
-   TEST_STRING(scas, "");
-   TEST_STRING(scas, "repz ");
-   TEST_STRING(scas, "repnz ");
-   TEST_STRING(cmps, "");
-   TEST_STRING(cmps, "repz ");
-   TEST_STRING(cmps, "repnz ");
-}
-
-#ifdef TEST_VM86
-/* VM86 test */
-
-static inline void set_bit(uint8_t *a, unsigned int bit)
-{
-    a[bit / 8] |= (1 << (bit % 8));
-}
-
-static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
-{
-    return (uint8_t *)((seg << 4) + (reg & 0xffff));
-}
-
-static inline void pushw(struct vm86_regs *r, int val)
-{
-    r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
-    *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
-}
-
-static inline int vm86(int func, struct vm86plus_struct *v86)
-{
-    return syscall(__NR_vm86, func, v86);
-}
-
-extern char vm86_code_start;
-extern char vm86_code_end;
-
-#define VM86_CODE_CS 0x100
-#define VM86_CODE_IP 0x100
-
-void test_vm86(void)
-{
-    struct vm86plus_struct ctx;
-    struct vm86_regs *r;
-    uint8_t *vm86_mem;
-    int seg, ret;
-
-    vm86_mem = mmap((void *)0x00000000, 0x110000,
-                    PROT_WRITE | PROT_READ | PROT_EXEC,
-                    MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
-    if (vm86_mem == MAP_FAILED) {
-        printf("ERROR: could not map vm86 memory");
-        return;
-    }
-    memset(&ctx, 0, sizeof(ctx));
-
-    /* init basic registers */
-    r = &ctx.regs;
-    r->eip = VM86_CODE_IP;
-    r->esp = 0xfffe;
-    seg = VM86_CODE_CS;
-    r->cs = seg;
-    r->ss = seg;
-    r->ds = seg;
-    r->es = seg;
-    r->fs = seg;
-    r->gs = seg;
-    r->eflags = VIF_MASK;
-
-    /* move code to proper address. We use the same layout as a .com
-       dos program. */
-    memcpy(vm86_mem + (VM86_CODE_CS << 4) + VM86_CODE_IP,
-           &vm86_code_start, &vm86_code_end - &vm86_code_start);
-
-    /* mark int 0x21 as being emulated */
-    set_bit((uint8_t *)&ctx.int_revectored, 0x21);
-
-    for(;;) {
-        ret = vm86(VM86_ENTER, &ctx);
-        switch(VM86_TYPE(ret)) {
-        case VM86_INTx:
-            {
-                int int_num, ah, v;
-
-                int_num = VM86_ARG(ret);
-                if (int_num != 0x21)
-                    goto unknown_int;
-                ah = (r->eax >> 8) & 0xff;
-                switch(ah) {
-                case 0x00: /* exit */
-                    goto the_end;
-                case 0x02: /* write char */
-                    {
-                        uint8_t c = r->edx;
-                        putchar(c);
-                    }
-                    break;
-                case 0x09: /* write string */
-                    {
-                        uint8_t c, *ptr;
-                        ptr = seg_to_linear(r->ds, r->edx);
-                        for(;;) {
-                            c = *ptr++;
-                            if (c == '$')
-                                break;
-                            putchar(c);
-                        }
-                        r->eax = (r->eax & ~0xff) | '$';
-                    }
-                    break;
-                case 0xff: /* extension: write eflags number in edx */
-                    v = (int)r->edx;
-#ifndef LINUX_VM86_IOPL_FIX
-                    v &= ~0x3000;
-#endif
-                    printf("%08x\n", v);
-                    break;
-                default:
-                unknown_int:
-                    printf("unsupported int 0x%02x\n", int_num);
-                    goto the_end;
-                }
-            }
-            break;
-        case VM86_SIGNAL:
-            /* a signal came, we just ignore that */
-            break;
-        case VM86_STI:
-            break;
-        default:
-            printf("ERROR: unhandled vm86 return code (0x%x)\n", ret);
-            goto the_end;
-        }
-    }
- the_end:
-    printf("VM86 end\n");
-    munmap(vm86_mem, 0x110000);
-}
-#endif
-
-/* exception tests */
-#if defined(__i386__) && !defined(REG_EAX)
-#define REG_EAX EAX
-#define REG_EBX EBX
-#define REG_ECX ECX
-#define REG_EDX EDX
-#define REG_ESI ESI
-#define REG_EDI EDI
-#define REG_EBP EBP
-#define REG_ESP ESP
-#define REG_EIP EIP
-#define REG_EFL EFL
-#define REG_TRAPNO TRAPNO
-#define REG_ERR ERR
-#endif
-
-#if defined(__x86_64__)
-#define REG_EIP REG_RIP
-#endif
-
-jmp_buf jmp_env;
-int v1;
-int tab[2];
-
-void sig_handler(int sig, siginfo_t *info, void *puc)
-{
-    struct ucontext *uc = puc;
-
-    printf("si_signo=%d si_errno=%d si_code=%d",
-           info->si_signo, info->si_errno, info->si_code);
-    printf(" si_addr=0x%08lx",
-           (unsigned long)info->si_addr);
-    printf("\n");
-
-    printf("trapno=" FMTLX " err=" FMTLX,
-           (long)uc->uc_mcontext.gregs[REG_TRAPNO],
-           (long)uc->uc_mcontext.gregs[REG_ERR]);
-    printf(" EIP=" FMTLX, (long)uc->uc_mcontext.gregs[REG_EIP]);
-    printf("\n");
-    longjmp(jmp_env, 1);
-}
-
-void test_exceptions(void)
-{
-    struct sigaction act;
-    volatile int val;
-
-    act.sa_sigaction = sig_handler;
-    sigemptyset(&act.sa_mask);
-    act.sa_flags = SA_SIGINFO | SA_NODEFER;
-    sigaction(SIGFPE, &act, NULL);
-    sigaction(SIGILL, &act, NULL);
-    sigaction(SIGSEGV, &act, NULL);
-    sigaction(SIGBUS, &act, NULL);
-    sigaction(SIGTRAP, &act, NULL);
-
-    /* test division by zero reporting */
-    printf("DIVZ exception:\n");
-    if (setjmp(jmp_env) == 0) {
-        /* now divide by zero */
-        v1 = 0;
-        v1 = 2 / v1;
-    }
-
-#if !defined(__x86_64__)
-    printf("BOUND exception:\n");
-    if (setjmp(jmp_env) == 0) {
-        /* bound exception */
-        tab[0] = 1;
-        tab[1] = 10;
-        asm volatile ("bound %0, %1" : : "r" (11), "m" (tab[0]));
-    }
-#endif
-
-#ifdef TEST_SEGS
-    printf("segment exceptions:\n");
-    if (setjmp(jmp_env) == 0) {
-        /* load an invalid segment */
-        asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 1));
-    }
-    if (setjmp(jmp_env) == 0) {
-        /* null data segment is valid */
-        asm volatile ("movl %0, %%fs" : : "r" (3));
-        /* null stack segment */
-        asm volatile ("movl %0, %%ss" : : "r" (3));
-    }
-
-    {
-        struct modify_ldt_ldt_s ldt;
-        ldt.entry_number = 1;
-        ldt.base_addr = (unsigned long)&seg_data1;
-        ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
-        ldt.seg_32bit = 1;
-        ldt.contents = MODIFY_LDT_CONTENTS_DATA;
-        ldt.read_exec_only = 0;
-        ldt.limit_in_pages = 1;
-        ldt.seg_not_present = 1;
-        ldt.useable = 1;
-        modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
-
-        if (setjmp(jmp_env) == 0) {
-            /* segment not present */
-            asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
-        }
-    }
-#endif
-
-    /* test SEGV reporting */
-    printf("PF exception:\n");
-    if (setjmp(jmp_env) == 0) {
-        val = 1;
-        /* we add a nop to test a weird PC retrieval case */
-        asm volatile ("nop");
-        /* now store in an invalid address */
-        *(char *)0x1234 = 1;
-    }
-
-    /* test SEGV reporting */
-    printf("PF exception:\n");
-    if (setjmp(jmp_env) == 0) {
-        val = 1;
-        /* read from an invalid address */
-        v1 = *(char *)0x1234;
-    }
-
-    /* test illegal instruction reporting */
-    printf("UD2 exception:\n");
-    if (setjmp(jmp_env) == 0) {
-        /* now execute an invalid instruction */
-        asm volatile("ud2");
-    }
-    printf("lock nop exception:\n");
-    if (setjmp(jmp_env) == 0) {
-        /* now execute an invalid instruction */
-        asm volatile("lock nop");
-    }
-
-    printf("INT exception:\n");
-    if (setjmp(jmp_env) == 0) {
-        asm volatile ("int $0xfd");
-    }
-    if (setjmp(jmp_env) == 0) {
-        asm volatile ("int $0x01");
-    }
-    if (setjmp(jmp_env) == 0) {
-        asm volatile (".byte 0xcd, 0x03");
-    }
-    if (setjmp(jmp_env) == 0) {
-        asm volatile ("int $0x04");
-    }
-    if (setjmp(jmp_env) == 0) {
-        asm volatile ("int $0x05");
-    }
-
-    printf("INT3 exception:\n");
-    if (setjmp(jmp_env) == 0) {
-        asm volatile ("int3");
-    }
-
-    printf("CLI exception:\n");
-    if (setjmp(jmp_env) == 0) {
-        asm volatile ("cli");
-    }
-
-    printf("STI exception:\n");
-    if (setjmp(jmp_env) == 0) {
-        asm volatile ("cli");
-    }
-
-#if !defined(__x86_64__)
-    printf("INTO exception:\n");
-    if (setjmp(jmp_env) == 0) {
-        /* overflow exception */
-        asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff));
-    }
-#endif
-
-    printf("OUTB exception:\n");
-    if (setjmp(jmp_env) == 0) {
-        asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0));
-    }
-
-    printf("INB exception:\n");
-    if (setjmp(jmp_env) == 0) {
-        asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321));
-    }
-
-    printf("REP OUTSB exception:\n");
-    if (setjmp(jmp_env) == 0) {
-        asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1));
-    }
-
-    printf("REP INSB exception:\n");
-    if (setjmp(jmp_env) == 0) {
-        asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1));
-    }
-
-    printf("HLT exception:\n");
-    if (setjmp(jmp_env) == 0) {
-        asm volatile ("hlt");
-    }
-
-    printf("single step exception:\n");
-    val = 0;
-    if (setjmp(jmp_env) == 0) {
-        asm volatile ("pushf\n"
-                      "orl $0x00100, (%%esp)\n"
-                      "popf\n"
-                      "movl $0xabcd, %0\n"
-                      "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory");
-    }
-    printf("val=0x%x\n", val);
-}
-
-#if !defined(__x86_64__)
-/* specific precise single step test */
-void sig_trap_handler(int sig, siginfo_t *info, void *puc)
-{
-    struct ucontext *uc = puc;
-    printf("EIP=" FMTLX "\n", (long)uc->uc_mcontext.gregs[REG_EIP]);
-}
-
-const uint8_t sstep_buf1[4] = { 1, 2, 3, 4};
-uint8_t sstep_buf2[4];
-
-void test_single_step(void)
-{
-    struct sigaction act;
-    volatile int val;
-    int i;
-
-    val = 0;
-    act.sa_sigaction = sig_trap_handler;
-    sigemptyset(&act.sa_mask);
-    act.sa_flags = SA_SIGINFO;
-    sigaction(SIGTRAP, &act, NULL);
-    asm volatile ("pushf\n"
-                  "orl $0x00100, (%%esp)\n"
-                  "popf\n"
-                  "movl $0xabcd, %0\n"
-
-                  /* jmp test */
-                  "movl $3, %%ecx\n"
-                  "1:\n"
-                  "addl $1, %0\n"
-                  "decl %%ecx\n"
-                  "jnz 1b\n"
-
-                  /* movsb: the single step should stop at each movsb iteration */
-                  "movl $sstep_buf1, %%esi\n"
-                  "movl $sstep_buf2, %%edi\n"
-                  "movl $0, %%ecx\n"
-                  "rep movsb\n"
-                  "movl $3, %%ecx\n"
-                  "rep movsb\n"
-                  "movl $1, %%ecx\n"
-                  "rep movsb\n"
-
-                  /* cmpsb: the single step should stop at each cmpsb iteration */
-                  "movl $sstep_buf1, %%esi\n"
-                  "movl $sstep_buf2, %%edi\n"
-                  "movl $0, %%ecx\n"
-                  "rep cmpsb\n"
-                  "movl $4, %%ecx\n"
-                  "rep cmpsb\n"
-
-                  /* getpid() syscall: single step should skip one
-                     instruction */
-                  "movl $20, %%eax\n"
-                  "int $0x80\n"
-                  "movl $0, %%eax\n"
-
-                  /* when modifying SS, trace is not done on the next
-                     instruction */
-                  "movl %%ss, %%ecx\n"
-                  "movl %%ecx, %%ss\n"
-                  "addl $1, %0\n"
-                  "movl $1, %%eax\n"
-                  "movl %%ecx, %%ss\n"
-                  "jmp 1f\n"
-                  "addl $1, %0\n"
-                  "1:\n"
-                  "movl $1, %%eax\n"
-                  "pushl %%ecx\n"
-                  "popl %%ss\n"
-                  "addl $1, %0\n"
-                  "movl $1, %%eax\n"
-
-                  "pushf\n"
-                  "andl $~0x00100, (%%esp)\n"
-                  "popf\n"
-                  : "=m" (val)
-                  :
-                  : "cc", "memory", "eax", "ecx", "esi", "edi");
-    printf("val=%d\n", val);
-    for(i = 0; i < 4; i++)
-        printf("sstep_buf2[%d] = %d\n", i, sstep_buf2[i]);
-}
-
-/* self modifying code test */
-uint8_t code[] = {
-    0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */
-    0xc3, /* ret */
-};
-
-asm(".section \".data\"\n"
-    "smc_code2:\n"
-    "movl 4(%esp), %eax\n"
-    "movl %eax, smc_patch_addr2 + 1\n"
-    "nop\n"
-    "nop\n"
-    "nop\n"
-    "nop\n"
-    "nop\n"
-    "nop\n"
-    "nop\n"
-    "nop\n"
-    "smc_patch_addr2:\n"
-    "movl $1, %eax\n"
-    "ret\n"
-    ".previous\n"
-    );
-
-typedef int FuncType(void);
-extern int smc_code2(int);
-void test_self_modifying_code(void)
-{
-    int i;
-    printf("self modifying code:\n");
-    printf("func1 = 0x%x\n", ((FuncType *)code)());
-    for(i = 2; i <= 4; i++) {
-        code[1] = i;
-        printf("func%d = 0x%x\n", i, ((FuncType *)code)());
-    }
-
-    /* more difficult test : the modified code is just after the
-       modifying instruction. It is forbidden in Intel specs, but it
-       is used by old DOS programs */
-    for(i = 2; i <= 4; i++) {
-        printf("smc_code2(%d) = %d\n", i, smc_code2(i));
-    }
-}
-#endif
-
-long enter_stack[4096];
-
-#if defined(__x86_64__)
-#define RSP "%%rsp"
-#define RBP "%%rbp"
-#else
-#define RSP "%%esp"
-#define RBP "%%ebp"
-#endif
-
-#if !defined(__x86_64__)
-/* causes an infinite loop, disable it for now.  */
-#define TEST_ENTER(size, stack_type, level)
-#else
-#define TEST_ENTER(size, stack_type, level)\
-{\
-    long esp_save, esp_val, ebp_val, ebp_save, i;\
-    stack_type *ptr, *stack_end, *stack_ptr;\
-    memset(enter_stack, 0, sizeof(enter_stack));\
-    stack_end = stack_ptr = (stack_type *)(enter_stack + 4096);\
-    ebp_val = (long)stack_ptr;\
-    for(i=1;i<=32;i++)\
-       *--stack_ptr = i;\
-    esp_val = (long)stack_ptr;\
-    asm("mov " RSP ", %[esp_save]\n"\
-        "mov " RBP ", %[ebp_save]\n"\
-        "mov %[esp_val], " RSP "\n"\
-        "mov %[ebp_val], " RBP "\n"\
-        "enter" size " $8, $" #level "\n"\
-        "mov " RSP ", %[esp_val]\n"\
-        "mov " RBP ", %[ebp_val]\n"\
-        "mov %[esp_save], " RSP "\n"\
-        "mov %[ebp_save], " RBP "\n"\
-        : [esp_save] "=r" (esp_save),\
-        [ebp_save] "=r" (ebp_save),\
-        [esp_val] "=r" (esp_val),\
-        [ebp_val] "=r" (ebp_val)\
-        :  "[esp_val]" (esp_val),\
-        "[ebp_val]" (ebp_val));\
-    printf("level=%d:\n", level);\
-    printf("esp_val=" FMTLX "\n", esp_val - (long)stack_end);\
-    printf("ebp_val=" FMTLX "\n", ebp_val - (long)stack_end);\
-    for(ptr = (stack_type *)esp_val; ptr < stack_end; ptr++)\
-        printf(FMTLX "\n", (long)ptr[0]);\
-}
-#endif
-
-static void test_enter(void)
-{
-#if defined(__x86_64__)
-    TEST_ENTER("q", uint64_t, 0);
-    TEST_ENTER("q", uint64_t, 1);
-    TEST_ENTER("q", uint64_t, 2);
-    TEST_ENTER("q", uint64_t, 31);
-#else
-    TEST_ENTER("l", uint32_t, 0);
-    TEST_ENTER("l", uint32_t, 1);
-    TEST_ENTER("l", uint32_t, 2);
-    TEST_ENTER("l", uint32_t, 31);
-#endif
-
-    TEST_ENTER("w", uint16_t, 0);
-    TEST_ENTER("w", uint16_t, 1);
-    TEST_ENTER("w", uint16_t, 2);
-    TEST_ENTER("w", uint16_t, 31);
-}
-
-#ifdef TEST_SSE
-
-typedef int __m64 __attribute__ ((__mode__ (__V2SI__)));
-typedef float __m128 __attribute__ ((__mode__(__V4SF__)));
-
-typedef union {
-    double d[2];
-    float s[4];
-    uint32_t l[4];
-    uint64_t q[2];
-    __m128 dq;
-} XMMReg;
-
-static uint64_t __attribute__((aligned(16))) test_values[4][2] = {
-    { 0x456723c698694873, 0xdc515cff944a58ec },
-    { 0x1f297ccd58bad7ab, 0x41f21efba9e3e146 },
-    { 0x007c62c2085427f8, 0x231be9e8cde7438d },
-    { 0x0f76255a085427f8, 0xc233e9e8c4c9439a },
-};
-
-#define SSE_OP(op)\
-{\
-    asm volatile (#op " %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
-    printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           b.q[1], b.q[0],\
-           r.q[1], r.q[0]);\
-}
-
-#define SSE_OP2(op)\
-{\
-    int i;\
-    for(i=0;i<2;i++) {\
-    a.q[0] = test_values[2*i][0];\
-    a.q[1] = test_values[2*i][1];\
-    b.q[0] = test_values[2*i+1][0];\
-    b.q[1] = test_values[2*i+1][1];\
-    SSE_OP(op);\
-    }\
-}
-
-#define MMX_OP2(op)\
-{\
-    int i;\
-    for(i=0;i<2;i++) {\
-    a.q[0] = test_values[2*i][0];\
-    b.q[0] = test_values[2*i+1][0];\
-    asm volatile (#op " %2, %0" : "=y" (r.q[0]) : "0" (a.q[0]), "y" (b.q[0]));\
-    printf("%-9s: a=" FMT64X " b=" FMT64X " r=" FMT64X "\n",\
-           #op,\
-           a.q[0],\
-           b.q[0],\
-           r.q[0]);\
-    }\
-    SSE_OP2(op);\
-}
-
-#define SHUF_OP(op, ib)\
-{\
-    a.q[0] = test_values[0][0];\
-    a.q[1] = test_values[0][1];\
-    b.q[0] = test_values[1][0];\
-    b.q[1] = test_values[1][1];\
-    asm volatile (#op " $" #ib ", %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
-    printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           b.q[1], b.q[0],\
-           ib,\
-           r.q[1], r.q[0]);\
-}
-
-#define PSHUF_OP(op, ib)\
-{\
-    int i;\
-    for(i=0;i<2;i++) {\
-    a.q[0] = test_values[2*i][0];\
-    a.q[1] = test_values[2*i][1];\
-    asm volatile (#op " $" #ib ", %1, %0" : "=x" (r.dq) : "x" (a.dq));\
-    printf("%-9s: a=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           ib,\
-           r.q[1], r.q[0]);\
-    }\
-}
-
-#define SHIFT_IM(op, ib)\
-{\
-    int i;\
-    for(i=0;i<2;i++) {\
-    a.q[0] = test_values[2*i][0];\
-    a.q[1] = test_values[2*i][1];\
-    asm volatile (#op " $" #ib ", %0" : "=x" (r.dq) : "0" (a.dq));\
-    printf("%-9s: a=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           ib,\
-           r.q[1], r.q[0]);\
-    }\
-}
-
-#define SHIFT_OP(op, ib)\
-{\
-    int i;\
-    SHIFT_IM(op, ib);\
-    for(i=0;i<2;i++) {\
-    a.q[0] = test_values[2*i][0];\
-    a.q[1] = test_values[2*i][1];\
-    b.q[0] = ib;\
-    b.q[1] = 0;\
-    asm volatile (#op " %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
-    printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           b.q[1], b.q[0],\
-           r.q[1], r.q[0]);\
-    }\
-}
-
-#define MOVMSK(op)\
-{\
-    int i, reg;\
-    for(i=0;i<2;i++) {\
-    a.q[0] = test_values[2*i][0];\
-    a.q[1] = test_values[2*i][1];\
-    asm volatile (#op " %1, %0" : "=r" (reg) : "x" (a.dq));\
-    printf("%-9s: a=" FMT64X "" FMT64X " r=%08x\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           reg);\
-    }\
-}
-
-#define SSE_OPS(a) \
-SSE_OP(a ## ps);\
-SSE_OP(a ## ss);
-
-#define SSE_OPD(a) \
-SSE_OP(a ## pd);\
-SSE_OP(a ## sd);
-
-#define SSE_COMI(op, field)\
-{\
-    unsigned int eflags;\
-    XMMReg a, b;\
-    a.field[0] = a1;\
-    b.field[0] = b1;\
-    asm volatile (#op " %2, %1\n"\
-        "pushf\n"\
-        "pop %0\n"\
-        : "=m" (eflags)\
-        : "x" (a.dq), "x" (b.dq));\
-    printf("%-9s: a=%f b=%f cc=%04x\n",\
-           #op, a1, b1,\
-           eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\
-}
-
-void test_sse_comi(double a1, double b1)
-{
-    SSE_COMI(ucomiss, s);
-    SSE_COMI(ucomisd, d);
-    SSE_COMI(comiss, s);
-    SSE_COMI(comisd, d);
-}
-
-#define CVT_OP_XMM(op)\
-{\
-    asm volatile (#op " %1, %0" : "=x" (r.dq) : "x" (a.dq));\
-    printf("%-9s: a=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           r.q[1], r.q[0]);\
-}
-
-/* Force %xmm0 usage to avoid the case where both register index are 0
-   to test instruction decoding more extensively */
-#define CVT_OP_XMM2MMX(op)\
-{\
-    asm volatile (#op " %1, %0" : "=y" (r.q[0]) : "x" (a.dq) \
-                  : "%xmm0"); \
-    asm volatile("emms\n"); \
-    printf("%-9s: a=" FMT64X "" FMT64X " r=" FMT64X "\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           r.q[0]);\
-}
-
-#define CVT_OP_MMX2XMM(op)\
-{\
-    asm volatile (#op " %1, %0" : "=x" (r.dq) : "y" (a.q[0]));\
-    asm volatile("emms\n"); \
-    printf("%-9s: a=" FMT64X " r=" FMT64X "" FMT64X "\n",\
-           #op,\
-           a.q[0],\
-           r.q[1], r.q[0]);\
-}
-
-#define CVT_OP_REG2XMM(op)\
-{\
-    asm volatile (#op " %1, %0" : "=x" (r.dq) : "r" (a.l[0]));\
-    printf("%-9s: a=%08x r=" FMT64X "" FMT64X "\n",\
-           #op,\
-           a.l[0],\
-           r.q[1], r.q[0]);\
-}
-
-#define CVT_OP_XMM2REG(op)\
-{\
-    asm volatile (#op " %1, %0" : "=r" (r.l[0]) : "x" (a.dq));\
-    printf("%-9s: a=" FMT64X "" FMT64X " r=%08x\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           r.l[0]);\
-}
-
-struct fpxstate {
-    uint16_t fpuc;
-    uint16_t fpus;
-    uint16_t fptag;
-    uint16_t fop;
-    uint32_t fpuip;
-    uint16_t cs_sel;
-    uint16_t dummy0;
-    uint32_t fpudp;
-    uint16_t ds_sel;
-    uint16_t dummy1;
-    uint32_t mxcsr;
-    uint32_t mxcsr_mask;
-    uint8_t fpregs1[8 * 16];
-    uint8_t xmm_regs[8 * 16];
-    uint8_t dummy2[224];
-};
-
-static struct fpxstate fpx_state __attribute__((aligned(16)));
-static struct fpxstate fpx_state2 __attribute__((aligned(16)));
-
-void test_fxsave(void)
-{
-    struct fpxstate *fp = &fpx_state;
-    struct fpxstate *fp2 = &fpx_state2;
-    int i, nb_xmm;
-    XMMReg a, b;
-    a.q[0] = test_values[0][0];
-    a.q[1] = test_values[0][1];
-    b.q[0] = test_values[1][0];
-    b.q[1] = test_values[1][1];
-
-    asm("movdqa %2, %%xmm0\n"
-        "movdqa %3, %%xmm7\n"
-#if defined(__x86_64__)
-        "movdqa %2, %%xmm15\n"
-#endif
-        " fld1\n"
-        " fldpi\n"
-        " fldln2\n"
-        " fxsave %0\n"
-        " fxrstor %0\n"
-        " fxsave %1\n"
-        " fninit\n"
-        : "=m" (*(uint32_t *)fp2), "=m" (*(uint32_t *)fp)
-        : "m" (a), "m" (b));
-    printf("fpuc=%04x\n", fp->fpuc);
-    printf("fpus=%04x\n", fp->fpus);
-    printf("fptag=%04x\n", fp->fptag);
-    for(i = 0; i < 3; i++) {
-        printf("ST%d: " FMT64X " %04x\n",
-               i,
-               *(uint64_t *)&fp->fpregs1[i * 16],
-               *(uint16_t *)&fp->fpregs1[i * 16 + 8]);
-    }
-    printf("mxcsr=%08x\n", fp->mxcsr & 0x1f80);
-#if defined(__x86_64__)
-    nb_xmm = 16;
-#else
-    nb_xmm = 8;
-#endif
-    for(i = 0; i < nb_xmm; i++) {
-        printf("xmm%d: " FMT64X "" FMT64X "\n",
-               i,
-               *(uint64_t *)&fp->xmm_regs[i * 16],
-               *(uint64_t *)&fp->xmm_regs[i * 16 + 8]);
-    }
-}
-
-void test_sse(void)
-{
-    XMMReg r, a, b;
-    int i;
-
-    MMX_OP2(punpcklbw);
-    MMX_OP2(punpcklwd);
-    MMX_OP2(punpckldq);
-    MMX_OP2(packsswb);
-    MMX_OP2(pcmpgtb);
-    MMX_OP2(pcmpgtw);
-    MMX_OP2(pcmpgtd);
-    MMX_OP2(packuswb);
-    MMX_OP2(punpckhbw);
-    MMX_OP2(punpckhwd);
-    MMX_OP2(punpckhdq);
-    MMX_OP2(packssdw);
-    MMX_OP2(pcmpeqb);
-    MMX_OP2(pcmpeqw);
-    MMX_OP2(pcmpeqd);
-
-    MMX_OP2(paddq);
-    MMX_OP2(pmullw);
-    MMX_OP2(psubusb);
-    MMX_OP2(psubusw);
-    MMX_OP2(pminub);
-    MMX_OP2(pand);
-    MMX_OP2(paddusb);
-    MMX_OP2(paddusw);
-    MMX_OP2(pmaxub);
-    MMX_OP2(pandn);
-
-    MMX_OP2(pmulhuw);
-    MMX_OP2(pmulhw);
-
-    MMX_OP2(psubsb);
-    MMX_OP2(psubsw);
-    MMX_OP2(pminsw);
-    MMX_OP2(por);
-    MMX_OP2(paddsb);
-    MMX_OP2(paddsw);
-    MMX_OP2(pmaxsw);
-    MMX_OP2(pxor);
-    MMX_OP2(pmuludq);
-    MMX_OP2(pmaddwd);
-    MMX_OP2(psadbw);
-    MMX_OP2(psubb);
-    MMX_OP2(psubw);
-    MMX_OP2(psubd);
-    MMX_OP2(psubq);
-    MMX_OP2(paddb);
-    MMX_OP2(paddw);
-    MMX_OP2(paddd);
-
-    MMX_OP2(pavgb);
-    MMX_OP2(pavgw);
-
-    asm volatile ("pinsrw $1, %1, %0" : "=y" (r.q[0]) : "r" (0x12345678));
-    printf("%-9s: r=" FMT64X "\n", "pinsrw", r.q[0]);
-
-    asm volatile ("pinsrw $5, %1, %0" : "=x" (r.dq) : "r" (0x12345678));
-    printf("%-9s: r=" FMT64X "" FMT64X "\n", "pinsrw", r.q[1], r.q[0]);
-
-    a.q[0] = test_values[0][0];
-    a.q[1] = test_values[0][1];
-    asm volatile ("pextrw $1, %1, %0" : "=r" (r.l[0]) : "y" (a.q[0]));
-    printf("%-9s: r=%08x\n", "pextrw", r.l[0]);
-
-    asm volatile ("pextrw $5, %1, %0" : "=r" (r.l[0]) : "x" (a.dq));
-    printf("%-9s: r=%08x\n", "pextrw", r.l[0]);
-
-    asm volatile ("pmovmskb %1, %0" : "=r" (r.l[0]) : "y" (a.q[0]));
-    printf("%-9s: r=%08x\n", "pmovmskb", r.l[0]);
-
-    asm volatile ("pmovmskb %1, %0" : "=r" (r.l[0]) : "x" (a.dq));
-    printf("%-9s: r=%08x\n", "pmovmskb", r.l[0]);
-
-    {
-        r.q[0] = -1;
-        r.q[1] = -1;
-
-        a.q[0] = test_values[0][0];
-        a.q[1] = test_values[0][1];
-        b.q[0] = test_values[1][0];
-        b.q[1] = test_values[1][1];
-        asm volatile("maskmovq %1, %0" :
-                     : "y" (a.q[0]), "y" (b.q[0]), "D" (&r)
-                     : "memory");
-        printf("%-9s: r=" FMT64X " a=" FMT64X " b=" FMT64X "\n",
-               "maskmov",
-               r.q[0],
-               a.q[0],
-               b.q[0]);
-        asm volatile("maskmovdqu %1, %0" :
-                     : "x" (a.dq), "x" (b.dq), "D" (&r)
-                     : "memory");
-        printf("%-9s: r=" FMT64X "" FMT64X " a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X "\n",
-               "maskmov",
-               r.q[1], r.q[0],
-               a.q[1], a.q[0],
-               b.q[1], b.q[0]);
-    }
-
-    asm volatile ("emms");
-
-    SSE_OP2(punpcklqdq);
-    SSE_OP2(punpckhqdq);
-    SSE_OP2(andps);
-    SSE_OP2(andpd);
-    SSE_OP2(andnps);
-    SSE_OP2(andnpd);
-    SSE_OP2(orps);
-    SSE_OP2(orpd);
-    SSE_OP2(xorps);
-    SSE_OP2(xorpd);
-
-    SSE_OP2(unpcklps);
-    SSE_OP2(unpcklpd);
-    SSE_OP2(unpckhps);
-    SSE_OP2(unpckhpd);
-
-    SHUF_OP(shufps, 0x78);
-    SHUF_OP(shufpd, 0x02);
-
-    PSHUF_OP(pshufd, 0x78);
-    PSHUF_OP(pshuflw, 0x78);
-    PSHUF_OP(pshufhw, 0x78);
-
-    SHIFT_OP(psrlw, 7);
-    SHIFT_OP(psrlw, 16);
-    SHIFT_OP(psraw, 7);
-    SHIFT_OP(psraw, 16);
-    SHIFT_OP(psllw, 7);
-    SHIFT_OP(psllw, 16);
-
-    SHIFT_OP(psrld, 7);
-    SHIFT_OP(psrld, 32);
-    SHIFT_OP(psrad, 7);
-    SHIFT_OP(psrad, 32);
-    SHIFT_OP(pslld, 7);
-    SHIFT_OP(pslld, 32);
-
-    SHIFT_OP(psrlq, 7);
-    SHIFT_OP(psrlq, 32);
-    SHIFT_OP(psllq, 7);
-    SHIFT_OP(psllq, 32);
-
-    SHIFT_IM(psrldq, 16);
-    SHIFT_IM(psrldq, 7);
-    SHIFT_IM(pslldq, 16);
-    SHIFT_IM(pslldq, 7);
-
-    MOVMSK(movmskps);
-    MOVMSK(movmskpd);
-
-    /* FPU specific ops */
-
-    {
-        uint32_t mxcsr;
-        asm volatile("stmxcsr %0" : "=m" (mxcsr));
-        printf("mxcsr=%08x\n", mxcsr & 0x1f80);
-        asm volatile("ldmxcsr %0" : : "m" (mxcsr));
-    }
-
-    test_sse_comi(2, -1);
-    test_sse_comi(2, 2);
-    test_sse_comi(2, 3);
-    test_sse_comi(2, q_nan.d);
-    test_sse_comi(q_nan.d, -1);
-
-    for(i = 0; i < 2; i++) {
-        a.s[0] = 2.7;
-        a.s[1] = 3.4;
-        a.s[2] = 4;
-        a.s[3] = -6.3;
-        b.s[0] = 45.7;
-        b.s[1] = 353.4;
-        b.s[2] = 4;
-        b.s[3] = 56.3;
-        if (i == 1) {
-            a.s[0] = q_nan.d;
-            b.s[3] = q_nan.d;
-        }
-
-        SSE_OPS(add);
-        SSE_OPS(mul);
-        SSE_OPS(sub);
-        SSE_OPS(min);
-        SSE_OPS(div);
-        SSE_OPS(max);
-        SSE_OPS(sqrt);
-        SSE_OPS(cmpeq);
-        SSE_OPS(cmplt);
-        SSE_OPS(cmple);
-        SSE_OPS(cmpunord);
-        SSE_OPS(cmpneq);
-        SSE_OPS(cmpnlt);
-        SSE_OPS(cmpnle);
-        SSE_OPS(cmpord);
-
-
-        a.d[0] = 2.7;
-        a.d[1] = -3.4;
-        b.d[0] = 45.7;
-        b.d[1] = -53.4;
-        if (i == 1) {
-            a.d[0] = q_nan.d;
-            b.d[1] = q_nan.d;
-        }
-        SSE_OPD(add);
-        SSE_OPD(mul);
-        SSE_OPD(sub);
-        SSE_OPD(min);
-        SSE_OPD(div);
-        SSE_OPD(max);
-        SSE_OPD(sqrt);
-        SSE_OPD(cmpeq);
-        SSE_OPD(cmplt);
-        SSE_OPD(cmple);
-        SSE_OPD(cmpunord);
-        SSE_OPD(cmpneq);
-        SSE_OPD(cmpnlt);
-        SSE_OPD(cmpnle);
-        SSE_OPD(cmpord);
-    }
-
-    /* float to float/int */
-    a.s[0] = 2.7;
-    a.s[1] = 3.4;
-    a.s[2] = 4;
-    a.s[3] = -6.3;
-    CVT_OP_XMM(cvtps2pd);
-    CVT_OP_XMM(cvtss2sd);
-    CVT_OP_XMM2MMX(cvtps2pi);
-    CVT_OP_XMM2MMX(cvttps2pi);
-    CVT_OP_XMM2REG(cvtss2si);
-    CVT_OP_XMM2REG(cvttss2si);
-    CVT_OP_XMM(cvtps2dq);
-    CVT_OP_XMM(cvttps2dq);
-
-    a.d[0] = 2.6;
-    a.d[1] = -3.4;
-    CVT_OP_XMM(cvtpd2ps);
-    CVT_OP_XMM(cvtsd2ss);
-    CVT_OP_XMM2MMX(cvtpd2pi);
-    CVT_OP_XMM2MMX(cvttpd2pi);
-    CVT_OP_XMM2REG(cvtsd2si);
-    CVT_OP_XMM2REG(cvttsd2si);
-    CVT_OP_XMM(cvtpd2dq);
-    CVT_OP_XMM(cvttpd2dq);
-
-    /* sse/mmx moves */
-    CVT_OP_XMM2MMX(movdq2q);
-    CVT_OP_MMX2XMM(movq2dq);
-
-    /* int to float */
-    a.l[0] = -6;
-    a.l[1] = 2;
-    a.l[2] = 100;
-    a.l[3] = -60000;
-    CVT_OP_MMX2XMM(cvtpi2ps);
-    CVT_OP_MMX2XMM(cvtpi2pd);
-    CVT_OP_REG2XMM(cvtsi2ss);
-    CVT_OP_REG2XMM(cvtsi2sd);
-    CVT_OP_XMM(cvtdq2ps);
-    CVT_OP_XMM(cvtdq2pd);
-
-    /* XXX: test PNI insns */
-#if 0
-    SSE_OP2(movshdup);
-#endif
-    asm volatile ("emms");
-}
-
-#endif
-
-#define TEST_CONV_RAX(op)\
-{\
-    unsigned long a, r;\
-    a = i2l(0x8234a6f8);\
-    r = a;\
-    asm volatile(#op : "=a" (r) : "0" (r));\
-    printf("%-10s A=" FMTLX " R=" FMTLX "\n", #op, a, r);\
-}
-
-#define TEST_CONV_RAX_RDX(op)\
-{\
-    unsigned long a, d, r, rh;                   \
-    a = i2l(0x8234a6f8);\
-    d = i2l(0x8345a1f2);\
-    r = a;\
-    rh = d;\
-    asm volatile(#op : "=a" (r), "=d" (rh) : "0" (r), "1" (rh));   \
-    printf("%-10s A=" FMTLX " R=" FMTLX ":" FMTLX "\n", #op, a, r, rh);  \
-}
-
-void test_conv(void)
-{
-    TEST_CONV_RAX(cbw);
-    TEST_CONV_RAX(cwde);
-#if defined(__x86_64__)
-    TEST_CONV_RAX(cdqe);
-#endif
-
-    TEST_CONV_RAX_RDX(cwd);
-    TEST_CONV_RAX_RDX(cdq);
-#if defined(__x86_64__)
-    TEST_CONV_RAX_RDX(cqo);
-#endif
-
-    {
-        unsigned long a, r;
-        a = i2l(0x12345678);
-        asm volatile("bswapl %k0" : "=r" (r) : "0" (a));
-        printf("%-10s: A=" FMTLX " R=" FMTLX "\n", "bswapl", a, r);
-    }
-#if defined(__x86_64__)
-    {
-        unsigned long a, r;
-        a = i2l(0x12345678);
-        asm volatile("bswapq %0" : "=r" (r) : "0" (a));
-        printf("%-10s: A=" FMTLX " R=" FMTLX "\n", "bswapq", a, r);
-    }
-#endif
-}
-
-extern void *__start_initcall;
-extern void *__stop_initcall;
-
-
-int main(int argc, char **argv)
-{
-    void **ptr;
-    void (*func)(void);
-
-    ptr = &__start_initcall;
-    while (ptr != &__stop_initcall) {
-        func = *ptr++;
-        func();
-    }
-    test_bsx();
-    test_mul();
-    test_jcc();
-    test_loop();
-    test_floats();
-#if !defined(__x86_64__)
-    test_bcd();
-#endif
-    test_xchg();
-    test_string();
-    test_misc();
-    test_lea();
-#ifdef TEST_SEGS
-    test_segs();
-    test_code16();
-#endif
-#ifdef TEST_VM86
-    test_vm86();
-#endif
-#if !defined(__x86_64__)
-    test_exceptions();
-    test_self_modifying_code();
-    test_single_step();
-#endif
-    test_enter();
-    test_conv();
-#ifdef TEST_SSE
-    test_sse();
-    test_fxsave();
-#endif
-    return 0;
-}
diff --git a/tests/test-i386.h b/tests/test-i386.h
deleted file mode 100644
index 75106b8..0000000
--- a/tests/test-i386.h
+++ /dev/null
@@ -1,152 +0,0 @@
-
-#define exec_op glue(exec_, OP)
-#define exec_opq glue(glue(exec_, OP), q)
-#define exec_opl glue(glue(exec_, OP), l)
-#define exec_opw glue(glue(exec_, OP), w)
-#define exec_opb glue(glue(exec_, OP), b)
-
-#define EXECOP2(size, rsize, res, s1, flags) \
-    asm ("push %4\n\t"\
-         "popf\n\t"\
-         stringify(OP) size " %" rsize "2, %" rsize "0\n\t" \
-         "pushf\n\t"\
-         "pop %1\n\t"\
-         : "=q" (res), "=g" (flags)\
-         : "q" (s1), "0" (res), "1" (flags)); \
-    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n", \
-           stringify(OP) size, s0, s1, res, iflags, flags & CC_MASK);
-
-#define EXECOP1(size, rsize, res, flags) \
-    asm ("push %3\n\t"\
-         "popf\n\t"\
-         stringify(OP) size " %" rsize "0\n\t" \
-         "pushf\n\t"\
-         "pop %1\n\t"\
-         : "=q" (res), "=g" (flags)\
-         : "0" (res), "1" (flags)); \
-    printf("%-10s A=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n", \
-           stringify(OP) size, s0, res, iflags, flags & CC_MASK);
-
-#ifdef OP1
-#if defined(__x86_64__)
-void exec_opq(long s0, long s1, long iflags)
-{
-    long res, flags;
-    res = s0;
-    flags = iflags;
-    EXECOP1("q", "", res, flags);
-}
-#endif
-
-void exec_opl(long s0, long s1, long iflags)
-{
-    long res, flags;
-    res = s0;
-    flags = iflags;
-    EXECOP1("l", "k", res, flags);
-}
-
-void exec_opw(long s0, long s1, long iflags)
-{
-    long res, flags;
-    res = s0;
-    flags = iflags;
-    EXECOP1("w", "w", res, flags);
-}
-
-void exec_opb(long s0, long s1, long iflags)
-{
-    long res, flags;
-    res = s0;
-    flags = iflags;
-    EXECOP1("b", "b", res, flags);
-}
-#else
-#if defined(__x86_64__)
-void exec_opq(long s0, long s1, long iflags)
-{
-    long res, flags;
-    res = s0;
-    flags = iflags;
-    EXECOP2("q", "", res, s1, flags);
-}
-#endif
-
-void exec_opl(long s0, long s1, long iflags)
-{
-    long res, flags;
-    res = s0;
-    flags = iflags;
-    EXECOP2("l", "k", res, s1, flags);
-}
-
-void exec_opw(long s0, long s1, long iflags)
-{
-    long res, flags;
-    res = s0;
-    flags = iflags;
-    EXECOP2("w", "w", res, s1, flags);
-}
-
-void exec_opb(long s0, long s1, long iflags)
-{
-    long res, flags;
-    res = s0;
-    flags = iflags;
-    EXECOP2("b", "b", res, s1, flags);
-}
-#endif
-
-void exec_op(long s0, long s1)
-{
-    s0 = i2l(s0);
-    s1 = i2l(s1);
-#if defined(__x86_64__)
-    exec_opq(s0, s1, 0);
-#endif
-    exec_opl(s0, s1, 0);
-    exec_opw(s0, s1, 0);
-    exec_opb(s0, s1, 0);
-#ifdef OP_CC
-#if defined(__x86_64__)
-    exec_opq(s0, s1, CC_C);
-#endif
-    exec_opl(s0, s1, CC_C);
-    exec_opw(s0, s1, CC_C);
-    exec_opb(s0, s1, CC_C);
-#endif
-}
-
-void glue(test_, OP)(void)
-{
-    exec_op(0x12345678, 0x812FADA);
-    exec_op(0x12341, 0x12341);
-    exec_op(0x12341, -0x12341);
-    exec_op(0xffffffff, 0);
-    exec_op(0xffffffff, -1);
-    exec_op(0xffffffff, 1);
-    exec_op(0xffffffff, 2);
-    exec_op(0x7fffffff, 0);
-    exec_op(0x7fffffff, 1);
-    exec_op(0x7fffffff, -1);
-    exec_op(0x80000000, -1);
-    exec_op(0x80000000, 1);
-    exec_op(0x80000000, -2);
-    exec_op(0x12347fff, 0);
-    exec_op(0x12347fff, 1);
-    exec_op(0x12347fff, -1);
-    exec_op(0x12348000, -1);
-    exec_op(0x12348000, 1);
-    exec_op(0x12348000, -2);
-    exec_op(0x12347f7f, 0);
-    exec_op(0x12347f7f, 1);
-    exec_op(0x12347f7f, -1);
-    exec_op(0x12348080, -1);
-    exec_op(0x12348080, 1);
-    exec_op(0x12348080, -2);
-}
-
-void *glue(_test_, OP) __init_call = glue(test_, OP);
-
-#undef OP
-#undef OP_CC
diff --git a/tests/test-mmap.c b/tests/test-mmap.c
deleted file mode 100644
index c67174a..0000000
--- a/tests/test-mmap.c
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * Small test program to verify simulated mmap behaviour.
- *
- * When running qemu-linux-user with the -p flag, you may need to tell
- * this test program about the pagesize because getpagesize() will not reflect
- * the -p choice. Simply pass one argument beeing the pagesize.
- *
- * Copyright (c) 2007 AXIS Communications AB
- * Written by Edgar E. Iglesias.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sys/mman.h>
-
-#define D(x)
-
-#define fail_unless(x)                                         \
-do                                                             \
-{                                                              \
-  if (!(x)) {                                                  \
-    fprintf (stderr, "FAILED at %s:%d\n", __FILE__, __LINE__); \
-    exit (EXIT_FAILURE);                                       \
-  }                                                            \
-} while (0);
-
-unsigned char *dummybuf;
-static unsigned int pagesize;
-static unsigned int pagemask;
-int test_fd;
-size_t test_fsize;
-
-void check_aligned_anonymous_unfixed_mmaps(void)
-{
-	void *p1;
-	void *p2;
-	void *p3;
-	void *p4;
-	void *p5;
-	uintptr_t p;
-	int i;
-
-	fprintf (stderr, "%s", __func__);
-	for (i = 0; i < 0x1fff; i++)
-	{
-		size_t len;
-
-		len = pagesize + (pagesize * i & 7);
-		p1 = mmap(NULL, len, PROT_READ, 
-			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-		p2 = mmap(NULL, len, PROT_READ, 
-			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-		p3 = mmap(NULL, len, PROT_READ, 
-			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-		p4 = mmap(NULL, len, PROT_READ, 
-			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-		p5 = mmap(NULL, len, PROT_READ, 
-			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-
-		/* Make sure we get pages aligned with the pagesize. The
-		   target expects this.  */
-		fail_unless (p1 != MAP_FAILED);
-		fail_unless (p2 != MAP_FAILED);
-		fail_unless (p3 != MAP_FAILED);
-		fail_unless (p4 != MAP_FAILED);
-		fail_unless (p5 != MAP_FAILED);
-		p = (uintptr_t) p1;
-		D(printf ("p=%x\n", p));
-		fail_unless ((p & pagemask) == 0);
-		p = (uintptr_t) p2;
-		fail_unless ((p & pagemask) == 0);
-		p = (uintptr_t) p3;
-		fail_unless ((p & pagemask) == 0);
-		p = (uintptr_t) p4;
-		fail_unless ((p & pagemask) == 0);
-		p = (uintptr_t) p5;
-		fail_unless ((p & pagemask) == 0);
-
-		/* Make sure we can read from the entire area.  */
-		memcpy (dummybuf, p1, pagesize);
-		memcpy (dummybuf, p2, pagesize);
-		memcpy (dummybuf, p3, pagesize);
-		memcpy (dummybuf, p4, pagesize);
-		memcpy (dummybuf, p5, pagesize);
-
-		munmap (p1, len);
-		munmap (p2, len);
-		munmap (p3, len);
-		munmap (p4, len);
-		munmap (p5, len);
-	}
-	fprintf (stderr, " passed\n");
-}
-
-void check_large_anonymous_unfixed_mmap(void)
-{
-	void *p1;
-	uintptr_t p;
-	size_t len;
-
-	fprintf (stderr, "%s", __func__);
-
-	len = 0x02000000;
-	p1 = mmap(NULL, len, PROT_READ, 
-		  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-
-	/* Make sure we get pages aligned with the pagesize. The
-	   target expects this.  */
-	fail_unless (p1 != MAP_FAILED);
-	p = (uintptr_t) p1;
-	fail_unless ((p & pagemask) == 0);
-	
-	/* Make sure we can read from the entire area.  */
-	memcpy (dummybuf, p1, pagesize);
-	munmap (p1, len);
-	fprintf (stderr, " passed\n");
-}
-
-void check_aligned_anonymous_unfixed_colliding_mmaps(void)
-{
-	char *p1;
-	char *p2;
-	char *p3;
-	uintptr_t p;
-	int i;
-
-	fprintf (stderr, "%s", __func__);
-	for (i = 0; i < 0x2fff; i++)
-	{
-		int nlen;
-		p1 = mmap(NULL, pagesize, PROT_READ, 
-			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-		fail_unless (p1 != MAP_FAILED);
-		p = (uintptr_t) p1;
-		fail_unless ((p & pagemask) == 0);
-		memcpy (dummybuf, p1, pagesize);
-
-		p2 = mmap(NULL, pagesize, PROT_READ, 
-			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-		fail_unless (p2 != MAP_FAILED);
-		p = (uintptr_t) p2;
-		fail_unless ((p & pagemask) == 0);
-		memcpy (dummybuf, p2, pagesize);
-
-
-		munmap (p1, pagesize);
-		nlen = pagesize * 8;
-		p3 = mmap(NULL, nlen, PROT_READ, 
-			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-		fail_unless (p3 != MAP_FAILED);
-
-		/* Check if the mmaped areas collide.  */
-		if (p3 < p2 
-		    && (p3 + nlen) > p2)
-			fail_unless (0);
-
-		memcpy (dummybuf, p3, pagesize);
-
-		/* Make sure we get pages aligned with the pagesize. The
-		   target expects this.  */
-		p = (uintptr_t) p3;
-		fail_unless ((p & pagemask) == 0);
-		munmap (p2, pagesize);
-		munmap (p3, nlen);
-	}
-	fprintf (stderr, " passed\n");
-}
-
-void check_aligned_anonymous_fixed_mmaps(void)
-{
-	char *addr;
-	void *p1;
-	uintptr_t p;
-	int i;
-
-	/* Find a suitable address to start with.  */
-	addr = mmap(NULL, pagesize * 40, PROT_READ | PROT_WRITE, 
-		    MAP_PRIVATE | MAP_ANONYMOUS,
-		    -1, 0);
-	fprintf (stderr, "%s addr=%p", __func__, addr);
-	fail_unless (addr != MAP_FAILED);
-
-	for (i = 0; i < 40; i++)
-	{
-		/* Create submaps within our unfixed map.  */
-		p1 = mmap(addr, pagesize, PROT_READ, 
-			  MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
-			  -1, 0);
-		/* Make sure we get pages aligned with the pagesize. 
-		   The target expects this.  */
-		p = (uintptr_t) p1;
-		fail_unless (p1 == addr);
-		fail_unless ((p & pagemask) == 0);		
-		memcpy (dummybuf, p1, pagesize);
-		munmap (p1, pagesize);
-		addr += pagesize;
-	}
-	fprintf (stderr, " passed\n");
-}
-
-void check_aligned_anonymous_fixed_mmaps_collide_with_host(void)
-{
-	char *addr;
-	void *p1;
-	uintptr_t p;
-	int i;
-
-	/* Find a suitable address to start with.  Right were the x86 hosts
-	 stack is.  */
-	addr = ((void *)0x80000000);
-	fprintf (stderr, "%s addr=%p", __func__, addr);
-	fprintf (stderr, "FIXME: QEMU fails to track pages used by the host.");
-
-	for (i = 0; i < 20; i++)
-	{
-		/* Create submaps within our unfixed map.  */
-		p1 = mmap(addr, pagesize, PROT_READ | PROT_WRITE, 
-			  MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
-			  -1, 0);
-		/* Make sure we get pages aligned with the pagesize. 
-		   The target expects this.  */
-		p = (uintptr_t) p1;
-		fail_unless (p1 == addr);
-		fail_unless ((p & pagemask) == 0);		
-		memcpy (p1, dummybuf, pagesize);
-		munmap (p1, pagesize);
-		addr += pagesize;
-	}
-	fprintf (stderr, " passed\n");
-}
-
-void check_file_unfixed_mmaps(void)
-{
-	unsigned int *p1, *p2, *p3;
-	uintptr_t p;
-	int i;
-
-	fprintf (stderr, "%s", __func__);
-	for (i = 0; i < 0x10; i++)
-	{
-		size_t len;
-
-		len = pagesize;
-		p1 = mmap(NULL, len, PROT_READ, 
-			  MAP_PRIVATE, 
-			  test_fd, 0);
-		p2 = mmap(NULL, len, PROT_READ, 
-			  MAP_PRIVATE, 
-			  test_fd, pagesize);
-		p3 = mmap(NULL, len, PROT_READ, 
-			  MAP_PRIVATE, 
-			  test_fd, pagesize * 2);
-
-		fail_unless (p1 != MAP_FAILED);
-		fail_unless (p2 != MAP_FAILED);
-		fail_unless (p3 != MAP_FAILED);
-
-		/* Make sure we get pages aligned with the pagesize. The
-		   target expects this.  */
-		p = (uintptr_t) p1;
-		fail_unless ((p & pagemask) == 0);
-		p = (uintptr_t) p2;
-		fail_unless ((p & pagemask) == 0);
-		p = (uintptr_t) p3;
-		fail_unless ((p & pagemask) == 0);
-
-		/* Verify that the file maps was made correctly.  */
-		D(printf ("p1=%d p2=%d p3=%d\n", *p1, *p2, *p3));
-		fail_unless (*p1 == 0);
-		fail_unless (*p2 == (pagesize / sizeof *p2));
-		fail_unless (*p3 == ((pagesize * 2) / sizeof *p3));
-
-		memcpy (dummybuf, p1, pagesize);
-		memcpy (dummybuf, p2, pagesize);
-		memcpy (dummybuf, p3, pagesize);
-		munmap (p1, len);
-		munmap (p2, len);
-		munmap (p3, len);
-	}
-	fprintf (stderr, " passed\n");
-}
-
-void check_file_unfixed_eof_mmaps(void)
-{
-	char *cp;
-	unsigned int *p1;
-	uintptr_t p;
-	int i;
-
-	fprintf (stderr, "%s", __func__);
-	for (i = 0; i < 0x10; i++)
-	{
-		p1 = mmap(NULL, pagesize, PROT_READ, 
-			  MAP_PRIVATE, 
-			  test_fd, 
-			  (test_fsize - sizeof *p1) & ~pagemask);
-
-		fail_unless (p1 != MAP_FAILED);
-
-		/* Make sure we get pages aligned with the pagesize. The
-		   target expects this.  */
-		p = (uintptr_t) p1;
-		fail_unless ((p & pagemask) == 0);
-		/* Verify that the file maps was made correctly.  */
-		fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1]
-			     == ((test_fsize - sizeof *p1) / sizeof *p1));
-
-		/* Verify that the end of page is accessible and zeroed.  */
-		cp = (void *) p1;
-		fail_unless (cp[pagesize - 4] == 0);
-		munmap (p1, pagesize);
-	}
-	fprintf (stderr, " passed\n");
-}
-
-void check_file_fixed_eof_mmaps(void)
-{
-	char *addr;
-	char *cp;
-	unsigned int *p1;
-	uintptr_t p;
-	int i;
-
-	/* Find a suitable address to start with.  */
-	addr = mmap(NULL, pagesize * 44, PROT_READ, 
-		    MAP_PRIVATE | MAP_ANONYMOUS,
-		    -1, 0);
-
-	fprintf (stderr, "%s addr=%p", __func__, (void *)addr);
-	fail_unless (addr != MAP_FAILED);
-
-	for (i = 0; i < 0x10; i++)
-	{
-		/* Create submaps within our unfixed map.  */
-		p1 = mmap(addr, pagesize, PROT_READ, 
-			  MAP_PRIVATE | MAP_FIXED, 
-			  test_fd, 
-			  (test_fsize - sizeof *p1) & ~pagemask);
-
-		fail_unless (p1 != MAP_FAILED);
-
-		/* Make sure we get pages aligned with the pagesize. The
-		   target expects this.  */
-		p = (uintptr_t) p1;
-		fail_unless ((p & pagemask) == 0);
-
-		/* Verify that the file maps was made correctly.  */
-		fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1]
-			     == ((test_fsize - sizeof *p1) / sizeof *p1));
-
-		/* Verify that the end of page is accessible and zeroed.  */
-		cp = (void *)p1;
-		fail_unless (cp[pagesize - 4] == 0);
-		munmap (p1, pagesize);
-		addr += pagesize;
-	}
-	fprintf (stderr, " passed\n");
-}
-
-void check_file_fixed_mmaps(void)
-{
-	unsigned char *addr;
-	unsigned int *p1, *p2, *p3, *p4;
-	int i;
-
-	/* Find a suitable address to start with.  */
-	addr = mmap(NULL, pagesize * 40 * 4, PROT_READ, 
-		    MAP_PRIVATE | MAP_ANONYMOUS,
-		    -1, 0);
-	fprintf (stderr, "%s addr=%p", __func__, (void *)addr);
-	fail_unless (addr != MAP_FAILED);
-
-	for (i = 0; i < 40; i++)
-	{
-		p1 = mmap(addr, pagesize, PROT_READ, 
-			  MAP_PRIVATE | MAP_FIXED,
-			  test_fd, 0);
-		p2 = mmap(addr + pagesize, pagesize, PROT_READ, 
-			  MAP_PRIVATE | MAP_FIXED,
-			  test_fd, pagesize);
-		p3 = mmap(addr + pagesize * 2, pagesize, PROT_READ, 
-			  MAP_PRIVATE | MAP_FIXED,
-			  test_fd, pagesize * 2);
-		p4 = mmap(addr + pagesize * 3, pagesize, PROT_READ, 
-			  MAP_PRIVATE | MAP_FIXED,
-			  test_fd, pagesize * 3);
-
-		/* Make sure we get pages aligned with the pagesize. 
-		   The target expects this.  */
-		fail_unless (p1 == (void *)addr);
-		fail_unless (p2 == (void *)addr + pagesize);
-		fail_unless (p3 == (void *)addr + pagesize * 2);
-		fail_unless (p4 == (void *)addr + pagesize * 3);
-
-		/* Verify that the file maps was made correctly.  */
-		fail_unless (*p1 == 0);
-		fail_unless (*p2 == (pagesize / sizeof *p2));
-		fail_unless (*p3 == ((pagesize * 2) / sizeof *p3));
-		fail_unless (*p4 == ((pagesize * 3) / sizeof *p4));
-
-		memcpy (dummybuf, p1, pagesize);
-		memcpy (dummybuf, p2, pagesize);
-		memcpy (dummybuf, p3, pagesize);
-		memcpy (dummybuf, p4, pagesize);
-
-		munmap (p1, pagesize);
-		munmap (p2, pagesize);
-		munmap (p3, pagesize);
-		munmap (p4, pagesize);
-		addr += pagesize * 4;
-	}
-	fprintf (stderr, " passed\n");
-}
-
-int main(int argc, char **argv)
-{
-	char tempname[] = "/tmp/.cmmapXXXXXX";
-	unsigned int i;
-
-	/* Trust the first argument, otherwise probe the system for our
-	   pagesize.  */
-	if (argc > 1)
-		pagesize = strtoul(argv[1], NULL, 0);
-	else
-		pagesize = sysconf(_SC_PAGESIZE);
-
-	/* Assume pagesize is a power of two.  */
-	pagemask = pagesize - 1;
-	dummybuf = malloc (pagesize);
-	printf ("pagesize=%u pagemask=%x\n", pagesize, pagemask);
-
-	test_fd = mkstemp(tempname);
-	unlink(tempname);
-
-	/* Fill the file with int's counting from zero and up.  */
-	for (i = 0; i < (pagesize * 4) / sizeof i; i++)
-		write (test_fd, &i, sizeof i);
-	/* Append a few extra writes to make the file end at non 
-	   page boundary.  */
-	write (test_fd, &i, sizeof i); i++;
-	write (test_fd, &i, sizeof i); i++;
-	write (test_fd, &i, sizeof i); i++;
-
-	test_fsize = lseek(test_fd, 0, SEEK_CUR);
-
-	/* Run the tests.  */
-	check_aligned_anonymous_unfixed_mmaps();
-	check_aligned_anonymous_unfixed_colliding_mmaps();
-	check_aligned_anonymous_fixed_mmaps();
-	check_file_unfixed_mmaps();
-	check_file_fixed_mmaps();
-	check_file_fixed_eof_mmaps();
-	check_file_unfixed_eof_mmaps();
-
-	/* Fails at the moment.  */
-	/* check_aligned_anonymous_fixed_mmaps_collide_with_host(); */
-
-	return EXIT_SUCCESS;
-}
diff --git a/tests/test_path.c b/tests/test_path.c
deleted file mode 100644
index 7265a94..0000000
--- a/tests/test_path.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/* Test path override code */
-#include "../config-host.h"
-#include "../qemu-malloc.c"
-#include "../cutils.c"
-#include "../path.c"
-#include "../trace.c"
-#ifdef CONFIG_TRACE_SIMPLE
-#include "../simpletrace.c"
-#endif
-
-#include <stdarg.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-void qemu_log(const char *fmt, ...);
-
-/* Any log message kills the test. */
-void qemu_log(const char *fmt, ...)
-{
-    va_list ap;
-
-    fprintf(stderr, "FATAL: ");
-    va_start(ap, fmt);
-    vfprintf(stderr, fmt, ap);
-    va_end(ap);
-    exit(1);
-}
-
-#define NO_CHANGE(_path)						\
-	do {								\
-	    if (strcmp(path(_path), _path) != 0) return __LINE__;	\
-	} while(0)
-
-#define CHANGE_TO(_path, _newpath)					\
-	do {								\
-	    if (strcmp(path(_path), _newpath) != 0) return __LINE__;	\
-	} while(0)
-
-static void cleanup(void)
-{
-    unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE");
-    unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE2");
-    unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE3");
-    unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE4");
-    unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE5");
-    rmdir("/tmp/qemu-test_path/DIR1/DIR2");
-    rmdir("/tmp/qemu-test_path/DIR1/DIR3");
-    rmdir("/tmp/qemu-test_path/DIR1");
-    rmdir("/tmp/qemu-test_path");
-}
-
-static unsigned int do_test(void)
-{
-    if (mkdir("/tmp/qemu-test_path", 0700) != 0)
-	return __LINE__;
-
-    if (mkdir("/tmp/qemu-test_path/DIR1", 0700) != 0)
-	return __LINE__;
-
-    if (mkdir("/tmp/qemu-test_path/DIR1/DIR2", 0700) != 0)
-	return __LINE__;
-
-    if (mkdir("/tmp/qemu-test_path/DIR1/DIR3", 0700) != 0)
-	return __LINE__;
-
-    if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE", 0600)) != 0)
-	return __LINE__;
-
-    if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE2", 0600)) != 0)
-	return __LINE__;
-
-    if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE3", 0600)) != 0)
-	return __LINE__;
-
-    if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE4", 0600)) != 0)
-	return __LINE__;
-
-    if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE5", 0600)) != 0)
-	return __LINE__;
-
-    init_paths("/tmp/qemu-test_path");
-
-    NO_CHANGE("/tmp");
-    NO_CHANGE("/tmp/");
-    NO_CHANGE("/tmp/qemu-test_path");
-    NO_CHANGE("/tmp/qemu-test_path/");
-    NO_CHANGE("/tmp/qemu-test_path/D");
-    NO_CHANGE("/tmp/qemu-test_path/DI");
-    NO_CHANGE("/tmp/qemu-test_path/DIR");
-    NO_CHANGE("/tmp/qemu-test_path/DIR1");
-    NO_CHANGE("/tmp/qemu-test_path/DIR1/");
-
-    NO_CHANGE("/D");
-    NO_CHANGE("/DI");
-    NO_CHANGE("/DIR");
-    NO_CHANGE("/DIR2");
-    NO_CHANGE("/DIR1.");
-
-    CHANGE_TO("/DIR1", "/tmp/qemu-test_path/DIR1");
-    CHANGE_TO("/DIR1/", "/tmp/qemu-test_path/DIR1");
-
-    NO_CHANGE("/DIR1/D");
-    NO_CHANGE("/DIR1/DI");
-    NO_CHANGE("/DIR1/DIR");
-    NO_CHANGE("/DIR1/DIR1");
-
-    CHANGE_TO("/DIR1/DIR2", "/tmp/qemu-test_path/DIR1/DIR2");
-    CHANGE_TO("/DIR1/DIR2/", "/tmp/qemu-test_path/DIR1/DIR2");
-
-    CHANGE_TO("/DIR1/DIR3", "/tmp/qemu-test_path/DIR1/DIR3");
-    CHANGE_TO("/DIR1/DIR3/", "/tmp/qemu-test_path/DIR1/DIR3");
-
-    NO_CHANGE("/DIR1/DIR2/F");
-    NO_CHANGE("/DIR1/DIR2/FI");
-    NO_CHANGE("/DIR1/DIR2/FIL");
-    NO_CHANGE("/DIR1/DIR2/FIL.");
-
-    CHANGE_TO("/DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
-    CHANGE_TO("/DIR1/DIR2/FILE2", "/tmp/qemu-test_path/DIR1/DIR2/FILE2");
-    CHANGE_TO("/DIR1/DIR2/FILE3", "/tmp/qemu-test_path/DIR1/DIR2/FILE3");
-    CHANGE_TO("/DIR1/DIR2/FILE4", "/tmp/qemu-test_path/DIR1/DIR2/FILE4");
-    CHANGE_TO("/DIR1/DIR2/FILE5", "/tmp/qemu-test_path/DIR1/DIR2/FILE5");
-
-    NO_CHANGE("/DIR1/DIR2/FILE6");
-    NO_CHANGE("/DIR1/DIR2/FILE/X");
-
-    CHANGE_TO("/DIR1/../DIR1", "/tmp/qemu-test_path/DIR1");
-    CHANGE_TO("/DIR1/../DIR1/", "/tmp/qemu-test_path/DIR1");
-    CHANGE_TO("/../DIR1", "/tmp/qemu-test_path/DIR1");
-    CHANGE_TO("/../DIR1/", "/tmp/qemu-test_path/DIR1");
-    CHANGE_TO("/DIR1/DIR2/../DIR2", "/tmp/qemu-test_path/DIR1/DIR2");
-    CHANGE_TO("/DIR1/DIR2/../DIR2/../../DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
-    CHANGE_TO("/DIR1/DIR2/../DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
-
-    NO_CHANGE("/DIR1/DIR2/../DIR1");
-    NO_CHANGE("/DIR1/DIR2/../FILE");
-
-    CHANGE_TO("/./DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
-    CHANGE_TO("/././DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
-    CHANGE_TO("/DIR1/./DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
-    CHANGE_TO("/DIR1/././DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
-    CHANGE_TO("/DIR1/DIR2/./FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
-    CHANGE_TO("/DIR1/DIR2/././FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
-    CHANGE_TO("/./DIR1/./DIR2/./FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
-
-    return 0;
-}
-
-int main(int argc, char *argv[])
-{
-    int ret;
-
-    ret = do_test();
-    cleanup();
-    if (ret) {
-	fprintf(stderr, "test_path: failed on line %i\n", ret);
-	return 1;
-    }
-    return 0;
-}
diff --git a/tests/testthread.c b/tests/testthread.c
deleted file mode 100644
index 27e4825..0000000
--- a/tests/testthread.c
+++ /dev/null
@@ -1,51 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <sys/wait.h>
-#include <sched.h>
-
-void *thread1_func(void *arg)
-{
-    int i;
-    char buf[512];
-
-    for(i=0;i<10;i++) {
-        snprintf(buf, sizeof(buf), "thread1: %d %s\n", i, (char *)arg);
-        write(1, buf, strlen(buf));
-        usleep(100 * 1000);
-    }
-    return NULL;
-}
-
-void *thread2_func(void *arg)
-{
-    int i;
-    char buf[512];
-    for(i=0;i<20;i++) {
-        snprintf(buf, sizeof(buf), "thread2: %d %s\n", i, (char *)arg);
-        write(1, buf, strlen(buf));
-        usleep(150 * 1000);
-    }
-    return NULL;
-}
-
-void test_pthread(void)
-{
-    pthread_t tid1, tid2;
-
-    pthread_create(&tid1, NULL, thread1_func, "hello1");
-    pthread_create(&tid2, NULL, thread2_func, "hello2");
-    pthread_join(tid1, NULL);
-    pthread_join(tid2, NULL);
-    printf("End of pthread test.\n");
-}
-
-int main(int argc, char **argv)
-{
-    test_pthread();
-    return 0;
-}
diff --git a/tests/xtensa/Makefile b/tests/xtensa/Makefile
deleted file mode 100644
index 8713af1..0000000
--- a/tests/xtensa/Makefile
+++ /dev/null
@@ -1,75 +0,0 @@
--include ../../config-host.mak
-
-CROSS=xtensa-dc232b-elf-
-
-ifndef XT
-SIM = qemu-system-xtensa
-SIMFLAGS = -M sim -cpu dc232b -nographic -semihosting $(EXTFLAGS) -kernel
-SIMDEBUG = -s -S
-else
-SIM = xt-run
-SIMFLAGS = --xtensa-core=DC_B_232L --exit_with_target_code $(EXTFLAGS)
-SIMDEBUG = --gdbserve=0
-endif
-
-CC      = $(CROSS)gcc
-AS      = $(CROSS)gcc -x assembler
-LD      = $(CROSS)ld
-
-LDFLAGS = -Tlinker.ld
-
-CRT        = crt.o vectors.o
-
-TESTCASES += test_b.tst
-TESTCASES += test_bi.tst
-#TESTCASES += test_boolean.tst
-TESTCASES += test_bz.tst
-TESTCASES += test_clamps.tst
-TESTCASES += test_fail.tst
-TESTCASES += test_interrupt.tst
-TESTCASES += test_loop.tst
-TESTCASES += test_mac16.tst
-TESTCASES += test_max.tst
-TESTCASES += test_min.tst
-TESTCASES += test_mmu.tst
-TESTCASES += test_mul16.tst
-TESTCASES += test_mul32.tst
-TESTCASES += test_nsa.tst
-ifdef XT
-TESTCASES += test_pipeline.tst
-endif
-TESTCASES += test_quo.tst
-TESTCASES += test_rem.tst
-TESTCASES += test_rst0.tst
-TESTCASES += test_sar.tst
-TESTCASES += test_sext.tst
-TESTCASES += test_shift.tst
-TESTCASES += test_timer.tst
-TESTCASES += test_windowed.tst
-
-all: build
-
-%.o: $(SRC_PATH)/tests/xtensa/%.c
-	$(CC) $(CFLAGS) -c $< -o $@
-
-%.o: $(SRC_PATH)/tests/xtensa/%.S
-	$(AS) $(ASFLAGS) -c $< -o $@
-
-%.tst: %.o macros.inc $(CRT) Makefile
-	$(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $< -o $@
-
-build: $(TESTCASES)
-
-check: $(addprefix run-, $(TESTCASES))
-
-run-%.tst: %.tst
-	$(SIM) $(SIMFLAGS) ./$<
-
-run-test_fail.tst: test_fail.tst
-	! $(SIM) $(SIMFLAGS) ./$<
-
-debug-%.tst: %.tst
-	$(SIM) $(SIMDEBUG) $(SIMFLAGS) ./$<
-
-clean:
-	$(RM) -fr $(TESTCASES) $(CRT)
diff --git a/tests/xtensa/crt.S b/tests/xtensa/crt.S
deleted file mode 100644
index d9846ac..0000000
--- a/tests/xtensa/crt.S
+++ /dev/null
@@ -1,24 +0,0 @@
-.section .init
-    j       1f
-.section .init.text
-1:
-    movi    a2, _start
-    jx      a2
-
-.text
-.global _start
-_start:
-    movi    a2, 1
-    wsr     a2, windowstart
-    movi    a2, 0
-    wsr     a2, windowbase
-    movi    a1, _fstack
-    movi    a2, 0x4000f
-    wsr     a2, ps
-    isync
-
-    call0   main
-
-    mov     a3, a2
-    movi    a2, 1
-    simcall
diff --git a/tests/xtensa/linker.ld b/tests/xtensa/linker.ld
deleted file mode 100644
index 4d0b307..0000000
--- a/tests/xtensa/linker.ld
+++ /dev/null
@@ -1,112 +0,0 @@
-OUTPUT_FORMAT("elf32-xtensa-le")
-ENTRY(_start)
-
-__DYNAMIC = 0;
-
-MEMORY {
-	ram : ORIGIN = 0xd0000000, LENGTH = 0x08000000  /* 128M */
-	rom : ORIGIN = 0xfe000000, LENGTH = 0x00001000  /* 4k */
-}
-
-SECTIONS
-{
-    .init :
-    {
-        *(.init)
-		*(.init.*)
-    } > rom
-
-    .vector :
-    {
-    . = 0x00000000;
-        *(.vector.window_overflow_4)
-        *(.vector.window_overflow_4.*)
-    . = 0x00000040;
-        *(.vector.window_underflow_4)
-        *(.vector.window_underflow_4.*)
-    . = 0x00000080;
-        *(.vector.window_overflow_8)
-        *(.vector.window_overflow_8.*)
-    . = 0x000000c0;
-        *(.vector.window_underflow_8)
-        *(.vector.window_underflow_8.*)
-    . = 0x00000100;
-        *(.vector.window_overflow_12)
-        *(.vector.window_overflow_12.*)
-    . = 0x00000140;
-        *(.vector.window_underflow_12)
-        *(.vector.window_underflow_12.*)
-
-    . = 0x00000180;
-        *(.vector.level2)
-        *(.vector.level2.*)
-    . = 0x000001c0;
-        *(.vector.level3)
-        *(.vector.level3.*)
-    . = 0x00000200;
-        *(.vector.level4)
-        *(.vector.level4.*)
-    . = 0x00000240;
-        *(.vector.level5)
-        *(.vector.level5.*)
-    . = 0x00000280;
-        *(.vector.level6)
-        *(.vector.level6.*)
-    . = 0x000002c0;
-        *(.vector.level7)
-        *(.vector.level7.*)
-
-    . = 0x00000300;
-        *(.vector.kernel)
-        *(.vector.kernel.*)
-    . = 0x00000340;
-        *(.vector.user)
-        *(.vector.user.*)
-    . = 0x000003c0;
-        *(.vector.double)
-        *(.vector.double.*)
-    } > ram
-
-	.text :
-	{
-		_ftext = .;
-		*(.text .stub .text.* .gnu.linkonce.t.* .literal .literal.*)
-		_etext = .;
-	} > ram
-
-	.rodata :
-	{
-		. = ALIGN(4);
-		_frodata = .;
-		*(.rodata .rodata.* .gnu.linkonce.r.*)
-		*(.rodata1)
-		_erodata = .;
-	} > ram
-
-	.data :
-	{
-		. = ALIGN(4);
-		_fdata = .;
-		*(.data .data.* .gnu.linkonce.d.*)
-		*(.data1)
-		_gp = ALIGN(16);
-		*(.sdata .sdata.* .gnu.linkonce.s.*)
-		_edata = .;
-	} > ram
-
-	.bss :
-	{
-		. = ALIGN(4);
-		_fbss = .;
-		*(.dynsbss)
-		*(.sbss .sbss.* .gnu.linkonce.sb.*)
-		*(.scommon)
-		*(.dynbss)
-		*(.bss .bss.* .gnu.linkonce.b.*)
-		*(COMMON)
-		_ebss = .;
-		_end = .;
-	} > ram
-}
-
-PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4);
diff --git a/tests/xtensa/macros.inc b/tests/xtensa/macros.inc
deleted file mode 100644
index 2d4515e..0000000
--- a/tests/xtensa/macros.inc
+++ /dev/null
@@ -1,68 +0,0 @@
-.macro test_suite name
-.data
-status: .word result
-result: .space 20
-.text
-.global main
-.align 4
-main:
-.endm
-
-.macro reset_ps
-    movi    a2, 0x4000f
-    wsr     a2, ps
-    isync
-.endm
-
-.macro test_suite_end
-    reset_ps
-    movi    a0, status
-    l32i    a2, a0, 0
-    movi    a0, result
-    sub     a2, a2, a0
-    movi    a3, 0
-    loopnez a2, 1f
-    l8ui    a2, a0, 0
-    or      a3, a3, a2
-    addi    a0, a0, 1
-1:
-    exit
-.endm
-
-.macro test name
-.endm
-
-.macro test_end
-99:
-    reset_ps
-    movi    a2, status
-    l32i    a3, a2, 0
-    addi    a3, a3, 1
-    s32i    a3, a2, 0
-.endm
-
-.macro exit
-    movi    a2, 1
-    simcall
-.endm
-
-.macro test_fail
-    movi    a2, status
-    l32i    a2, a2, 0
-    movi    a3, 1
-    s8i     a3, a2, 0
-    j       99f
-.endm
-
-.macro assert cond, arg1, arg2
-    b\cond  \arg1, \arg2, 90f
-    test_fail
-90:
-    nop
-.endm
-
-.macro set_vector vector, addr
-    movi    a2, handler_\vector
-    movi    a3, \addr
-    s32i    a3, a2, 0
-.endm
diff --git a/tests/xtensa/test_b.S b/tests/xtensa/test_b.S
deleted file mode 100644
index 6cbe5f1..0000000
--- a/tests/xtensa/test_b.S
+++ /dev/null
@@ -1,221 +0,0 @@
-.include "macros.inc"
-
-test_suite b
-
-test bnone
-    movi    a2, 0xa5a5ff00
-    movi    a3, 0x5a5a00ff
-    bnone   a2, a3, 1f
-    test_fail
-1:
-    movi    a2, 0xa5a5ff01
-    bnone   a2, a3, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test beq
-    movi    a2, 0
-    movi    a3, 0
-    beq     a2, a3, 1f
-    test_fail
-1:
-    movi    a2, 1
-    beq     a2, a3, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test blt
-    movi    a2, 6
-    movi    a3, 7
-    blt     a2, a3, 1f
-    test_fail
-1:
-    movi    a2, 0xffffffff
-    blt     a2, a3, 1f
-    test_fail
-1:
-    movi    a2, 7
-    blt     a2, a3, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test bltu
-    movi    a2, 6
-    movi    a3, 7
-    bltu    a2, a3, 1f
-    test_fail
-1:
-    movi    a2, 7
-    bltu    a2, a3, 1f
-    j       2f
-1:
-    test_fail
-2:
-    movi    a2, 0xffffffff
-    bltu    a2, a3, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test ball
-    movi    a2, 0xa5a5ffa5
-    movi    a3, 0xa5a5ff00
-    ball    a2, a3, 1f
-    test_fail
-1:
-    movi    a2, 0xa5a5a5a5
-    ball    a2, a3, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test bbc
-    movi    a2, 0xfffffffd
-    movi    a3, 0xffffff01
-    bbc     a2, a3, 1f
-    test_fail
-1:
-    movi    a2, 8
-    movi    a3, 0xffffff03
-    bbc     a2, a3, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test bbci
-    movi    a2, 0xfffdffff
-    bbci    a2, 17, 1f
-    test_fail
-1:
-    movi    a2, 0x00020000
-    bbci    a2, 17, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test bany
-    movi    a2, 0xa5a5ff01
-    movi    a3, 0x5a5a00ff
-    bany    a2, a3, 1f
-    test_fail
-1:
-    movi    a2, 0xa5a5ff00
-    bany    a2, a3, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test bne
-    movi    a2, 1
-    movi    a3, 0
-    bne     a2, a3, 1f
-    test_fail
-1:
-    movi    a2, 0
-    bne     a2, a3, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test bge
-    movi    a2, 7
-    movi    a3, 7
-    bge     a2, a3, 1f
-    test_fail
-1:
-    movi    a2, 6
-    bge     a2, a3, 1f
-    j       2f
-1:
-    test_fail
-2:
-    movi    a2, 0xffffffff
-    bge     a2, a3, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test bgeu
-    movi    a2, 7
-    movi    a3, 7
-    bgeu    a2, a3, 1f
-    test_fail
-1:
-    movi    a2, 0xffffffff
-    bgeu    a2, a3, 1f
-    test_fail
-1:
-    movi    a2, 6
-    bgeu    a2, a3, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test bnall
-    movi    a2, 0xa5a5a5a5
-    movi    a3, 0xa5a5ff00
-    bnall   a2, a3, 1f
-    test_fail
-1:
-    movi    a2, 0xa5a5ffa5
-    bnall   a2, a3, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test bbs
-    movi    a2, 8
-    movi    a3, 0xffffff03
-    bbs     a2, a3, 1f
-    test_fail
-1:
-    movi    a2, 0xfffffffd
-    movi    a3, 0xffffff01
-    bbs     a2, a3, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test bbsi
-    movi    a2, 0x00020000
-    bbsi    a2, 17, 1f
-    test_fail
-1:
-    movi    a2, 0xfffdffff
-    bbsi    a2, 17, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_bi.S b/tests/xtensa/test_bi.S
deleted file mode 100644
index 6a5f1df..0000000
--- a/tests/xtensa/test_bi.S
+++ /dev/null
@@ -1,103 +0,0 @@
-.include "macros.inc"
-
-test_suite bi
-
-test beqi
-    movi    a2, 7
-    beqi    a2, 7, 1f
-    test_fail
-1:
-    movi    a2, 1
-    beqi    a2, 7, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test bnei
-    movi    a2, 1
-    bnei    a2, 7, 1f
-    test_fail
-1:
-    movi    a2, 7
-    bnei    a2, 7, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test blti
-    movi    a2, 6
-    blti    a2, 7, 1f
-    test_fail
-1:
-    movi    a2, 0xffffffff
-    blti    a2, 7, 1f
-    test_fail
-1:
-    movi    a2, 7
-    blti    a2, 7, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test bgei
-    movi    a2, 7
-    bgei    a2, 7, 1f
-    test_fail
-1:
-    movi    a2, 6
-    bgei    a2, 7, 1f
-    j       2f
-1:
-    test_fail
-2:
-    movi    a2, 0xffffffff
-    bgei    a2, 7, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test bltui
-    movi    a2, 6
-    bltui   a2, 7, 1f
-    test_fail
-1:
-    movi    a2, 7
-    bltui   a2, 7, 1f
-    j       2f
-1:
-    test_fail
-2:
-    movi    a2, 0xffffffff
-    bltui   a2, 7, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test bgeui
-    movi    a2, 7
-    bgeui   a2, 7, 1f
-    test_fail
-1:
-    movi    a2, 0xffffffff
-    bgeui   a2, 7, 1f
-    test_fail
-1:
-    movi    a2, 6
-    bgeui   a2, 7, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_boolean.S b/tests/xtensa/test_boolean.S
deleted file mode 100644
index 50e6d2c..0000000
--- a/tests/xtensa/test_boolean.S
+++ /dev/null
@@ -1,23 +0,0 @@
-.include "macros.inc"
-
-test_suite boolean
-
-test all4
-    movi    a2, 0xfec0
-    wsr     a2, br
-    all4    b0, b0
-    rsr     a3, br
-    assert  eq, a2, a3
-    all4    b0, b4
-    rsr     a3, br
-    assert  eq, a2, a3
-    all4    b0, b8
-    rsr     a3, br
-    assert  eq, a2, a3
-    all4    b0, b12
-    rsr     a3, br
-    addi    a2, a2, 1
-    assert  eq, a2, a3
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_bz.S b/tests/xtensa/test_bz.S
deleted file mode 100644
index f9ba6e2..0000000
--- a/tests/xtensa/test_bz.S
+++ /dev/null
@@ -1,57 +0,0 @@
-.include "macros.inc"
-
-test_suite bz
-
-test beqz
-    movi    a2, 0
-    _beqz   a2, 1f
-    test_fail
-1:
-    movi    a2, 1
-    _beqz   a2, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test bnez
-    movi    a2, 1
-    _bnez   a2, 1f
-    test_fail
-1:
-    movi    a2, 0
-    _bnez   a2, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test bltz
-    movi    a2, 0xffffffff
-    bltz    a2, 1f
-    test_fail
-1:
-    movi    a2, 0
-    bltz    a2, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test bgez
-    movi    a2, 0
-    bgez    a2, 1f
-    test_fail
-1:
-    movi    a2, 0xffffffff
-    bgez    a2, 1f
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_clamps.S b/tests/xtensa/test_clamps.S
deleted file mode 100644
index c186cc9..0000000
--- a/tests/xtensa/test_clamps.S
+++ /dev/null
@@ -1,42 +0,0 @@
-.include "macros.inc"
-
-test_suite clamps
-
-test clamps
-    movi    a2, 0
-    movi    a3, 0
-    clamps  a4, a2, 7
-    assert  eq, a3, a4
-
-    movi    a2, 0x7f
-    movi    a3, 0x7f
-    clamps  a4, a2, 7
-    assert  eq, a3, a4
-
-    movi    a2, 0xffffff80
-    movi    a3, 0xffffff80
-    clamps  a4, a2, 7
-    assert  eq, a3, a4
-
-    movi    a2, 0x80
-    movi    a3, 0x7f
-    clamps  a2, a2, 7
-    assert  eq, a3, a2
-
-    movi    a2, 0xffffff7f
-    movi    a3, 0xffffff80
-    clamps  a2, a2, 7
-    assert  eq, a3, a2
-
-    movi    a2, 0x7fffffff
-    movi    a3, 0x7f
-    clamps  a2, a2, 7
-    assert  eq, a3, a2
-
-    movi    a2, 0x80000000
-    movi    a3, 0xffffff80
-    clamps  a2, a2, 7
-    assert  eq, a3, a2
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_fail.S b/tests/xtensa/test_fail.S
deleted file mode 100644
index e8d1b42..0000000
--- a/tests/xtensa/test_fail.S
+++ /dev/null
@@ -1,9 +0,0 @@
-.include "macros.inc"
-
-test_suite fail
-
-test fail
-    test_fail
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_interrupt.S b/tests/xtensa/test_interrupt.S
deleted file mode 100644
index 68b3ee1..0000000
--- a/tests/xtensa/test_interrupt.S
+++ /dev/null
@@ -1,194 +0,0 @@
-.include "macros.inc"
-
-test_suite interrupt
-
-.macro clear_interrupts
-    movi    a2, 0
-    wsr     a2, intenable
-    wsr     a2, ccompare0
-    wsr     a2, ccompare1
-    wsr     a2, ccompare2
-    esync
-    rsr     a2, interrupt
-    wsr     a2, intclear
-
-    esync
-    rsr     a2, interrupt
-    assert  eqi, a2, 0
-.endm
-
-.macro check_l1
-    rsr     a2, ps
-    movi    a3, 0x1f        /* EXCM | INTMASK */
-    and     a2, a2, a3
-    assert  eqi, a2, 0x10   /* only EXCM is set for level-1 interrupt */
-    rsr     a2, exccause
-    assert  eqi, a2, 4
-.endm
-
-test rsil
-    clear_interrupts
-
-    rsr     a2, ps
-    rsil    a3, 7
-    rsr     a4, ps
-    assert  eq, a2, a3
-    movi    a2, 0xf
-    and     a2, a4, a2
-    assert  eqi, a2, 7
-    xor     a3, a3, a4
-    movi    a2, 0xfffffff0
-    and     a2, a3, a2
-    assert  eqi, a2, 0
-test_end
-
-test soft_disabled
-    set_vector kernel, 1f
-    clear_interrupts
-
-    movi    a2, 0x80
-    wsr     a2, intset
-    esync
-    rsr     a3, interrupt
-    assert  eq, a2, a3
-    wsr     a2, intclear
-    esync
-    rsr     a3, interrupt
-    assert  eqi, a3, 0
-    j       2f
-1:
-    test_fail
-2:
-test_end
-
-test soft_intenable
-    set_vector kernel, 1f
-    clear_interrupts
-
-    movi    a2, 0x80
-    wsr     a2, intset
-    esync
-    rsr     a3, interrupt
-    assert  eq, a2, a3
-    rsil    a3, 0
-    wsr     a2, intenable
-    esync
-    test_fail
-1:
-    check_l1
-test_end
-
-test soft_rsil
-    set_vector kernel, 1f
-    clear_interrupts
-
-    movi    a2, 0x80
-    wsr     a2, intset
-    esync
-    rsr     a3, interrupt
-    assert  eq, a2, a3
-    wsr     a2, intenable
-    rsil    a3, 0
-    esync
-    test_fail
-1:
-    check_l1
-test_end
-
-test soft_waiti
-    set_vector kernel, 1f
-    clear_interrupts
-
-    movi    a2, 0x80
-    wsr     a2, intset
-    esync
-    rsr     a3, interrupt
-    assert  eq, a2, a3
-    wsr     a2, intenable
-    waiti   0
-    test_fail
-1:
-    check_l1
-test_end
-
-test soft_user
-    set_vector kernel, 1f
-    set_vector user, 2f
-    clear_interrupts
-
-    movi    a2, 0x80
-    wsr     a2, intset
-    esync
-    rsr     a3, interrupt
-    assert  eq, a2, a3
-    wsr     a2, intenable
-
-    rsr     a2, ps
-    movi    a3, 0x20
-    or      a2, a2, a3
-    wsr     a2, ps
-    waiti   0
-1:
-    test_fail
-2:
-    check_l1
-test_end
-
-test soft_priority
-    set_vector kernel, 1f
-    set_vector level3, 2f
-    clear_interrupts
-
-    movi    a2, 0x880
-    wsr     a2, intenable
-    rsil    a3, 0
-    esync
-    wsr     a2, intset
-    esync
-1:
-    test_fail
-2:
-    rsr     a2, ps
-    movi    a3, 0x1f        /* EXCM | INTMASK */
-    and     a2, a2, a3
-    movi    a3, 0x13
-    assert  eq, a2, a3      /* EXCM and INTMASK are set
-                               for high-priority interrupt */
-test_end
-
-test eps_epc_rfi
-    set_vector level3, 3f
-    clear_interrupts
-    reset_ps
-
-    movi    a2, 0x880
-    wsr     a2, intenable
-    rsil    a3, 0
-    rsr     a3, ps
-    esync
-    wsr     a2, intset
-1:
-    esync
-2:
-    test_fail
-3:
-    rsr     a2, eps3
-    assert  eq, a2, a3
-    rsr     a2, epc3
-    movi    a3, 1b
-    assert  ge, a2, a3
-    movi    a3, 2b
-    assert  ge, a3, a2
-    movi    a2, 4f
-    wsr     a2, epc3
-    movi    a2, 0x40003
-    wsr     a2, eps3
-    rfi     3
-    test_fail
-4:
-    rsr     a2, ps
-    movi    a3, 0x40003
-    assert  eq, a2, a3
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_loop.S b/tests/xtensa/test_loop.S
deleted file mode 100644
index a5ea933..0000000
--- a/tests/xtensa/test_loop.S
+++ /dev/null
@@ -1,77 +0,0 @@
-.include "macros.inc"
-
-test_suite loop
-
-test loop
-    movi    a2, 0
-    movi    a3, 5
-    loop    a3, 1f
-    addi    a2, a2, 1
-1:
-    assert  eqi, a2, 5
-test_end
-
-test loop0
-    movi    a2, 0
-    loop    a2, 1f
-    rsr     a2, lcount
-    assert  eqi, a2, -1
-    j       1f
-1:
-test_end
-
-test loop_jump
-    movi    a2, 0
-    movi    a3, 5
-    loop    a3, 1f
-    addi    a2, a2, 1
-    j       1f
-1:
-    assert  eqi, a2, 1
-test_end
-
-test loop_branch
-    movi    a2, 0
-    movi    a3, 5
-    loop    a3, 1f
-    addi    a2, a2, 1
-    beqi    a2, 3, 1f
-1:
-    assert  eqi, a2, 3
-test_end
-
-test loop_manual
-    movi    a2, 0
-    movi    a3, 5
-    movi    a4, 1f
-    movi    a5, 2f
-    wsr     a3, lcount
-    wsr     a4, lbeg
-    wsr     a5, lend
-    isync
-    j       1f
-.align 4
-1:
-    addi    a2, a2, 1
-2:
-    assert  eqi, a2, 6
-test_end
-
-test loop_excm
-    movi    a2, 0
-    movi    a3, 5
-    rsr     a4, ps
-    movi    a5, 0x10
-    or      a4, a4, a5
-    wsr     a4, ps
-    isync
-    loop    a3, 1f
-    addi    a2, a2, 1
-1:
-    xor     a4, a4, a5
-    isync
-    wsr     a4, ps
-    assert  eqi, a2, 1
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_mac16.S b/tests/xtensa/test_mac16.S
deleted file mode 100644
index 5ddd160..0000000
--- a/tests/xtensa/test_mac16.S
+++ /dev/null
@@ -1,243 +0,0 @@
-.include "macros.inc"
-
-test_suite mac16
-
-#define ext16(v) (((v) & 0xffff) | (((v) & 0x8000) * 0x1ffffffe))
-#define mul16(a, b) ((ext16(a) * ext16(b)))
-
-.macro assert_acc_value v
-    rsr     a4, ACCLO
-    movi    a5, (\v) & 0xffffffff
-    assert  eq, a4, a5
-    rsr     a4, ACCHI
-    movi    a5, (\v) >> 32
-    sext    a5, a5, 7
-    assert  eq, a4, a5
-.endm
-
-.macro init_reg sr, reg, val
-    .if (\sr)
-    movi    a4, \val
-    wsr     a4, \reg
-    .else
-    movi    \reg, \val
-    .endif
-.endm
-
-.macro test_mulxx mulop, comb, s, t, a, b
-    init_reg \comb & 2, \s, \a
-    init_reg \comb & 1, \t, \b
-
-    \mulop\().ll \s, \t
-    assert_acc_value mul16(\a, \b)
-
-    \mulop\().lh \s, \t
-    assert_acc_value mul16(\a, (\b >> 16))
-
-    \mulop\().hl \s, \t
-    assert_acc_value mul16((\a >> 16), \b)
-
-    \mulop\().hh \s, \t
-    assert_acc_value mul16((\a >> 16), (\b >> 16))
-.endm
-
-test mul_aa
-    test_mulxx mul.aa, 0, a2, a3, 0xf7315a5a, 0xa5a5137f
-test_end
-
-test mul_ad
-    test_mulxx mul.ad, 1, a2, m2, 0xf7315a5a, 0xa5a5137f
-test_end
-
-test mul_da
-    test_mulxx mul.da, 2, m1, a3, 0xf7315a5a, 0xa5a5137f
-test_end
-
-test mul_dd
-    test_mulxx mul.dd, 3, m0, m3, 0xf7315a5a, 0xa5a5137f
-test_end
-
-
-.macro init_acc iv
-    movi    a4, (\iv) & 0xffffffff
-    wsr     a4, ACCLO
-    movi    a4, (\iv) >> 32
-    wsr     a4, ACCHI
-.endm
-
-.macro test_mulxxx mulop, comb, s, t, a, b, iv, op
-    init_reg \comb & 2, \s, \a
-    init_reg \comb & 1, \t, \b
-
-    init_acc \iv
-    \mulop\().ll \s, \t
-    assert_acc_value (\iv \op mul16(\a, \b))
-
-    init_acc \iv
-    \mulop\().lh \s, \t
-    assert_acc_value (\iv \op mul16(\a, (\b >> 16)))
-
-    init_acc \iv
-    \mulop\().hl \s, \t
-    assert_acc_value (\iv \op mul16((\a >> 16), \b))
-
-    init_acc \iv
-    \mulop\().hh \s, \t
-    assert_acc_value (\iv \op mul16((\a >> 16), (\b >> 16)))
-.endm
-
-
-test mula_aa
-    test_mulxxx mula.aa, 0, a2, a3, 0xf7315a5a, 0xa5a5137f, 0xfff73155aa, +
-test_end
-
-test mula_ad
-    test_mulxxx mula.ad, 1, a2, m2, 0xf7315a5a, 0xa5a5137f, 0xfff73155aa, +
-test_end
-
-test mula_da
-    test_mulxxx mula.da, 2, m1, a3, 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
-test_end
-
-test mula_dd
-    test_mulxxx mula.dd, 3, m0, m3, 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
-test_end
-
-
-test muls_aa
-    test_mulxxx muls.aa, 0, a2, a3, 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, -
-test_end
-
-test muls_ad
-    test_mulxxx muls.ad, 1, a2, m2, 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, -
-test_end
-
-test muls_da
-    test_mulxxx muls.da, 2, m1, a3, 0xf7315a5a, 0xa5a5137f, 0xfff73155aa, -
-test_end
-
-test muls_dd
-    test_mulxxx muls.dd, 3, m0, m3, 0xf7315a5a, 0xa5a5137f, 0xfff73155aa, -
-test_end
-
-test ldinc
-    movi    a2, 1f - 4
-    ldinc   m0, a2
-    movi    a3, 1f
-    assert  eq, a2, a3
-    rsr     a3, m0
-    movi    a4, 0x55aa137f
-    assert  eq, a3, a4
-    ldinc   m1, a2
-    movi    a3, 1f + 4
-    assert  eq, a2, a3
-    rsr     a3, m1
-    movi    a4, 0x12345678
-    assert  eq, a3, a4
-
-.data
-1:  .word 0x55aa137f, 0x12345678, 0x137fa5a5
-.text
-test_end
-
-test lddec
-    movi    a2, 1f
-    lddec   m2, a2
-    movi    a3, 1f - 4
-    assert  eq, a2, a3
-    rsr     a3, m2
-    movi    a4, 0x12345678
-    assert  eq, a3, a4
-    lddec   m3, a2
-    movi    a3, 1f - 8
-    assert  eq, a2, a3
-    rsr     a3, m3
-    movi    a4, 0x55aa137f
-    assert  eq, a3, a4
-.data
-    .word 0x55aa137f, 0x12345678
-1:
-.text
-test_end
-
-
-.macro test_mulxxx_ld mulop, ldop, comb, w, x, s, t, a, b, iv, op
-    init_reg \comb & 2, \s, \a
-    init_reg \comb & 1, \t, \b
-
-    init_acc \iv
-    \mulop\().ll.\ldop \w, \x, \s, \t
-    assert_acc_value (\iv \op mul16(\a, \b))
-
-    init_acc \iv
-    \mulop\().lh.\ldop \w, \x, \s, \t
-    assert_acc_value (\iv \op mul16(\a, (\b >> 16)))
-
-    init_acc \iv
-    \mulop\().hl.\ldop \w, \x, \s, \t
-    assert_acc_value (\iv \op mul16((\a >> 16), \b))
-
-    init_acc \iv
-    \mulop\().hh.\ldop \w, \x, \s, \t
-    assert_acc_value (\iv \op mul16((\a >> 16), (\b >> 16)))
-.endm
-
-test mula_da_ldinc
-    movi    a2, 1f - 4
-    test_mulxxx_ld mula.da, ldinc, 2, m1, a2, m1, a3, \
-        0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
-    movi    a3, 1f + 12
-    assert  eq, a2, a3
-    rsr     a2, m1
-    movi    a3, 0x12345678
-    assert  eq, a2, a3
-.data
-1:  .word 0xf7315a5a, 0xf7315a5a, 0xf7315a5a, 0x12345678
-.text
-test_end
-
-test mula_dd_ldinc
-    movi    a2, 1f - 4
-    test_mulxxx_ld mula.dd, ldinc, 3, m2, a2, m1, m2, \
-        0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
-    movi    a3, 1f + 12
-    assert  eq, a2, a3
-    rsr     a2, m2
-    movi    a3, 0x12345678
-    assert  eq, a2, a3
-.data
-1:  .word 0xa5a5137f, 0xa5a5137f, 0xa5a5137f, 0x12345678
-.text
-test_end
-
-test mula_da_lddec
-    movi    a2, 1f
-    test_mulxxx_ld mula.da, lddec, 2, m1, a2, m1, a3, \
-        0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
-    movi    a3, 1f - 16
-    assert  eq, a2, a3
-    rsr     a2, m1
-    movi    a3, 0x12345678
-    assert  eq, a2, a3
-.data
-    .word 0x12345678, 0xf7315a5a, 0xf7315a5a, 0xf7315a5a
-1:
-.text
-test_end
-
-test mula_dd_lddec
-    movi    a2, 1f
-    test_mulxxx_ld mula.dd, lddec, 3, m2, a2, m1, m2, \
-        0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
-    movi    a3, 1f - 16
-    assert  eq, a2, a3
-    rsr     a2, m2
-    movi    a3, 0x12345678
-    assert  eq, a2, a3
-.data
-    .word 0x12345678, 0xa5a5137f, 0xa5a5137f, 0xa5a5137f
-1:
-.text
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_max.S b/tests/xtensa/test_max.S
deleted file mode 100644
index 2534c9d..0000000
--- a/tests/xtensa/test_max.S
+++ /dev/null
@@ -1,81 +0,0 @@
-.include "macros.inc"
-
-test_suite max
-
-test max
-    movi    a2, 0xffffffff
-    movi    a3, 1
-    movi    a4, 1
-    max     a5, a2, a3
-    assert  eq, a5, a4
-
-    movi    a2, 1
-    movi    a3, 0xffffffff
-    movi    a4, 1
-    max     a5, a2, a3
-    assert  eq, a5, a4
-
-    movi    a2, 0xffffffff
-    movi    a3, 1
-    movi    a4, 1
-    max     a2, a2, a3
-    assert  eq, a2, a4
-
-    movi    a2, 0xffffffff
-    movi    a3, 1
-    movi    a4, 1
-    max     a3, a2, a3
-    assert  eq, a3, a4
-
-    movi    a2, 1
-    movi    a3, 0xffffffff
-    movi    a4, 1
-    max     a2, a2, a3
-    assert  eq, a2, a4
-
-    movi    a2, 1
-    movi    a3, 0xffffffff
-    movi    a4, 1
-    max     a3, a2, a3
-    assert  eq, a3, a4
-test_end
-
-test maxu
-    movi    a2, 0xffffffff
-    movi    a3, 1
-    movi    a4, 0xffffffff
-    maxu    a5, a2, a3
-    assert  eq, a5, a4
-
-    movi    a2, 1
-    movi    a3, 0xffffffff
-    movi    a4, 0xffffffff
-    maxu    a5, a2, a3
-    assert  eq, a5, a4
-
-    movi    a2, 0xffffffff
-    movi    a3, 1
-    movi    a4, 0xffffffff
-    maxu    a2, a2, a3
-    assert  eq, a2, a4
-
-    movi    a2, 0xffffffff
-    movi    a3, 1
-    movi    a4, 0xffffffff
-    maxu    a3, a2, a3
-    assert  eq, a3, a4
-
-    movi    a2, 1
-    movi    a3, 0xffffffff
-    movi    a4, 0xffffffff
-    maxu    a2, a2, a3
-    assert  eq, a2, a4
-
-    movi    a2, 1
-    movi    a3, 0xffffffff
-    movi    a4, 0xffffffff
-    maxu    a3, a2, a3
-    assert  eq, a3, a4
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_min.S b/tests/xtensa/test_min.S
deleted file mode 100644
index 6d9ddeb..0000000
--- a/tests/xtensa/test_min.S
+++ /dev/null
@@ -1,81 +0,0 @@
-.include "macros.inc"
-
-test_suite min
-
-test min
-    movi    a2, 0xffffffff
-    movi    a3, 1
-    movi    a4, 0xffffffff
-    min     a5, a2, a3
-    assert  eq, a5, a4
-
-    movi    a2, 1
-    movi    a3, 0xffffffff
-    movi    a4, 0xffffffff
-    min     a5, a2, a3
-    assert  eq, a5, a4
-
-    movi    a2, 0xffffffff
-    movi    a3, 1
-    movi    a4, 0xffffffff
-    min     a2, a2, a3
-    assert  eq, a2, a4
-
-    movi    a2, 0xffffffff
-    movi    a3, 1
-    movi    a4, 0xffffffff
-    min     a3, a2, a3
-    assert  eq, a3, a4
-
-    movi    a2, 1
-    movi    a3, 0xffffffff
-    movi    a4, 0xffffffff
-    min     a2, a2, a3
-    assert  eq, a2, a4
-
-    movi    a2, 1
-    movi    a3, 0xffffffff
-    movi    a4, 0xffffffff
-    min     a3, a2, a3
-    assert  eq, a3, a4
-test_end
-
-test minu
-    movi    a2, 0xffffffff
-    movi    a3, 1
-    movi    a4, 1
-    minu    a5, a2, a3
-    assert  eq, a5, a4
-
-    movi    a2, 1
-    movi    a3, 0xffffffff
-    movi    a4, 1
-    minu    a5, a2, a3
-    assert  eq, a5, a4
-
-    movi    a2, 0xffffffff
-    movi    a3, 1
-    movi    a4, 1
-    minu    a2, a2, a3
-    assert  eq, a2, a4
-
-    movi    a2, 0xffffffff
-    movi    a3, 1
-    movi    a4, 1
-    minu    a3, a2, a3
-    assert  eq, a3, a4
-
-    movi    a2, 1
-    movi    a3, 0xffffffff
-    movi    a4, 1
-    minu    a2, a2, a3
-    assert  eq, a2, a4
-
-    movi    a2, 1
-    movi    a3, 0xffffffff
-    movi    a4, 1
-    minu    a3, a2, a3
-    assert  eq, a3, a4
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_mmu.S b/tests/xtensa/test_mmu.S
deleted file mode 100644
index 52d5774..0000000
--- a/tests/xtensa/test_mmu.S
+++ /dev/null
@@ -1,318 +0,0 @@
-.include "macros.inc"
-
-test_suite mmu
-
-.purgem test
-
-.macro test name
-    movi    a2, 0x00000004
-    idtlb   a2
-    movi    a2, 0x00100004
-    idtlb   a2
-    movi    a2, 0x00200004
-    idtlb   a2
-    movi    a2, 0x00300004
-    idtlb   a2
-    movi    a2, 0x00000007
-    idtlb   a2
-.endm
-
-test tlb_group
-    movi    a2, 0x04000002 /* PPN */
-    movi    a3, 0x01200004 /* VPN */
-    wdtlb   a2, a3
-    witlb   a2, a3
-    movi    a3, 0x00200004
-    rdtlb0  a1, a3
-    ritlb0  a2, a3
-    movi    a3, 0x01000001
-    assert  eq, a1, a3
-    assert  eq, a2, a3
-    movi    a3, 0x00200004
-    rdtlb1  a1, a3
-    ritlb1  a2, a3
-    movi    a3, 0x04000002
-    assert  eq, a1, a3
-    assert  eq, a2, a3
-    movi    a3, 0x01234567
-    pdtlb   a1, a3
-    pitlb   a2, a3
-    movi    a3, 0x01234014
-    assert  eq, a1, a3
-    movi    a3, 0x0123400c
-    assert  eq, a2, a3
-    movi    a3, 0x00200004
-    idtlb   a3
-    iitlb   a3
-    movi    a3, 0x01234567
-    pdtlb   a1, a3
-    pitlb   a2, a3
-    movi    a3, 0x00000010
-    and     a1, a1, a3
-    assert  eqi, a1, 0
-    movi    a3, 0x00000008
-    and     a2, a2, a3
-    assert  eqi, a2, 0
-test_end
-
-test itlb_miss
-    set_vector kernel, 1f
-
-    movi    a3, 0x00100000
-    jx      a3
-    test_fail
-1:
-    rsr     a2, excvaddr
-    assert  eq, a2, a3
-    rsr     a2, exccause
-    movi    a3, 16
-    assert  eq, a2, a3
-test_end
-
-test dtlb_miss
-    set_vector kernel, 1f
-
-    movi    a3, 0x00100000
-    l8ui    a2, a3, 0
-    test_fail
-1:
-    rsr     a2, excvaddr
-    assert  eq, a2, a3
-    rsr     a2, exccause
-    movi    a3, 24
-    assert  eq, a2, a3
-test_end
-
-test itlb_multi_hit
-    set_vector kernel, 1f
-
-    movi    a2, 0x04000002 /* PPN */
-    movi    a3, 0xf0000004 /* VPN */
-    witlb   a2, a3
-    movi    a3, 0xf0000000
-    pitlb   a2, a3
-    test_fail
-1:
-    rsr     a2, exccause
-    movi    a3, 17
-    assert  eq, a2, a3
-test_end
-
-test dtlb_multi_hit
-    set_vector kernel, 1f
-
-    movi    a2, 0x04000002 /* PPN */
-    movi    a3, 0x01200004 /* VPN */
-    wdtlb   a2, a3
-    movi    a3, 0x01200007 /* VPN */
-    wdtlb   a2, a3
-    movi    a3, 0x01200000
-    pdtlb   a2, a3
-    test_fail
-1:
-    rsr     a2, exccause
-    movi    a3, 25
-    assert  eq, a2, a3
-test_end
-
-test inst_fetch_privilege
-    set_vector kernel, 3f
-
-    movi    a2, 0x4004f
-    wsr     a2, ps
-1:
-    isync
-    nop
-2:
-    test_fail
-3:
-    movi    a1, 1b
-    rsr     a2, excvaddr
-    rsr     a3, epc1
-    assert  ge, a2, a1
-    assert  ge, a3, a1
-    movi    a1, 2b
-    assert  lt, a2, a1
-    assert  lt, a3, a1
-    rsr     a2, exccause
-    movi    a3, 18
-    assert  eq, a2, a3
-    rsr     a2, ps
-    movi    a3, 0x4005f
-    assert  eq, a2, a3
-test_end
-
-test load_store_privilege
-    set_vector kernel, 2f
-
-    movi    a3, 10f
-    pitlb   a3, a3
-    ritlb1  a2, a3
-    movi    a1, 0x10
-    or      a2, a2, a1
-    movi    a1, 0x000ff000
-    and     a3, a3, a1
-    movi    a1, 4
-    or      a3, a3, a1
-    witlb   a2, a3
-    movi    a3, 10f
-    movi    a1, 0x000fffff
-    and     a1, a3, a1
-
-    movi    a2, 0x04000003 /* PPN */
-    movi    a3, 0x01200004 /* VPN */
-    wdtlb   a2, a3
-    movi    a3, 0x01200001
-    movi    a2, 0x4004f
-    jx      a1
-10:
-    wsr     a2, ps
-    isync
-1:
-    l8ui    a2, a3, 0
-    test_fail
-2:
-    rsr     a2, excvaddr
-    assert  eq, a2, a3
-    rsr     a2, epc1
-    movi    a3, 1b
-    movi    a1, 0x000fffff
-    and     a3, a3, a1
-    assert  eq, a2, a3
-    rsr     a2, exccause
-    movi    a3, 26
-    assert  eq, a2, a3
-    rsr     a2, ps
-    movi    a3, 0x4005f
-    assert  eq, a2, a3
-test_end
-
-test cring_load_store_privilege
-    set_vector kernel, 0
-    set_vector double, 2f
-
-    movi    a2, 0x04000003 /* PPN */
-    movi    a3, 0x01200004 /* VPN */
-    wdtlb   a2, a3
-    movi    a3, 0x01200004
-    movi    a2, 0x4005f    /* ring 1 + excm => cring == 0 */
-    wsr     a2, ps
-    isync
-    l8ui    a2, a3, 0      /* cring used */
-1:
-    l32e    a2, a3, -4     /* ring used */
-    test_fail
-2:
-    rsr     a2, excvaddr
-    addi    a2, a2, 4
-    assert  eq, a2, a3
-    rsr     a2, depc
-    movi    a3, 1b
-    assert  eq, a2, a3
-    rsr     a2, exccause
-    movi    a3, 26
-    assert  eq, a2, a3
-    rsr     a2, ps
-    movi    a3, 0x4005f
-    assert  eq, a2, a3
-test_end
-
-test inst_fetch_prohibited
-    set_vector kernel, 2f
-
-    movi    a3, 10f
-    pitlb   a3, a3
-    ritlb1  a2, a3
-    movi    a1, 0xfffff000
-    and     a2, a2, a1
-    movi    a1, 0x4
-    or      a2, a2, a1
-    movi    a1, 0x000ff000
-    and     a3, a3, a1
-    movi    a1, 4
-    or      a3, a3, a1
-    witlb   a2, a3
-    movi    a3, 10f
-    movi    a1, 0x000fffff
-    and     a1, a3, a1
-    jx      a1
-    .align  4
-10:
-    nop
-    test_fail
-2:
-    rsr     a2, excvaddr
-    assert  eq, a2, a1
-    rsr     a2, epc1
-    assert  eq, a2, a1
-    rsr     a2, exccause
-    movi    a3, 20
-    assert  eq, a2, a3
-test_end
-
-test load_prohibited
-    set_vector kernel, 2f
-
-    movi    a2, 0x0400000c /* PPN */
-    movi    a3, 0x01200004 /* VPN */
-    wdtlb   a2, a3
-    movi    a3, 0x01200002
-1:
-    l8ui    a2, a3, 0
-    test_fail
-2:
-    rsr     a2, excvaddr
-    assert  eq, a2, a3
-    rsr     a2, epc1
-    movi    a3, 1b
-    assert  eq, a2, a3
-    rsr     a2, exccause
-    movi    a3, 28
-    assert  eq, a2, a3
-test_end
-
-test store_prohibited
-    set_vector kernel, 2f
-
-    movi    a2, 0x04000001 /* PPN */
-    movi    a3, 0x01200004 /* VPN */
-    wdtlb   a2, a3
-    movi    a3, 0x01200003
-    l8ui    a2, a3, 0
-1:
-    s8i     a2, a3, 0
-    test_fail
-2:
-    rsr     a2, excvaddr
-    assert  eq, a2, a3
-    rsr     a2, epc1
-    movi    a3, 1b
-    assert  eq, a2, a3
-    rsr     a2, exccause
-    movi    a3, 29
-    assert  eq, a2, a3
-test_end
-
-test dtlb_autoload
-    set_vector kernel, 0
-
-    movi    a2, 0xd4000000
-    wsr     a2, ptevaddr
-    movi    a3, 0x00001013
-    s32i    a3, a2, 4
-    pdtlb   a2, a3
-    movi    a1, 0x10
-    and     a1, a1, a2
-    assert  eqi, a1, 0
-    l8ui    a1, a3, 0
-    pdtlb   a2, a3
-    movi    a1, 0xfffff010
-    and     a1, a1, a2
-    movi    a3, 0x00001010
-    assert  eq, a1, a3
-    movi    a1, 0xf
-    and     a1, a1, a2
-    assert  lti, a1, 4
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_mul16.S b/tests/xtensa/test_mul16.S
deleted file mode 100644
index bf94376..0000000
--- a/tests/xtensa/test_mul16.S
+++ /dev/null
@@ -1,83 +0,0 @@
-.include "macros.inc"
-
-test_suite mul16
-
-test mul16u_pp
-    movi    a2, 0x137f5a5a
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0x06e180a6
-    mul16u  a5, a2, a4
-    assert  eq, a5, a6
-    mul16u  a2, a2, a4
-    assert  eq, a2, a6
-    mul16u  a3, a4, a3
-    assert  eq, a3, a6
-test_end
-
-test mul16u_np
-    movi    a2, 0x137fa5a5
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0x0c9d6bdb
-    mul16u  a5, a2, a4
-    assert  eq, a5, a6
-    mul16u  a2, a2, a4
-    assert  eq, a2, a6
-    mul16u  a3, a4, a3
-    assert  eq, a3, a6
-test_end
-
-test mul16u_nn
-    movi    a2, 0x137fa5a5
-    mov     a3, a2
-    movi    a4, 0xa5a5f731
-    movi    a6, 0x9ff1e795
-    mul16u  a5, a2, a4
-    assert  eq, a5, a6
-    mul16u  a2, a2, a4
-    assert  eq, a2, a6
-    mul16u  a3, a4, a3
-    assert  eq, a3, a6
-test_end
-
-test mul16s_pp
-    movi    a2, 0x137f5a5a
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0x06e180a6
-    mul16s  a5, a2, a4
-    assert  eq, a5, a6
-    mul16s  a2, a2, a4
-    assert  eq, a2, a6
-    mul16s  a3, a4, a3
-    assert  eq, a3, a6
-test_end
-
-test mul16s_np
-    movi    a2, 0x137fa5a5
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0xf91e6bdb
-    mul16s  a5, a2, a4
-    assert  eq, a5, a6
-    mul16s  a2, a2, a4
-    assert  eq, a2, a6
-    mul16s  a3, a4, a3
-    assert  eq, a3, a6
-test_end
-
-test mul16s_nn
-    movi    a2, 0x137fa5a5
-    mov     a3, a2
-    movi    a4, 0xa5a5f731
-    movi    a6, 0x031be795
-    mul16s  a5, a2, a4
-    assert  eq, a5, a6
-    mul16s  a2, a2, a4
-    assert  eq, a2, a6
-    mul16s  a3, a4, a3
-    assert  eq, a3, a6
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_mul32.S b/tests/xtensa/test_mul32.S
deleted file mode 100644
index fdaf573..0000000
--- a/tests/xtensa/test_mul32.S
+++ /dev/null
@@ -1,20 +0,0 @@
-.include "macros.inc"
-
-test_suite mul32
-
-test mull
-    movi    a2, 0x137f5a5a
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0x5de480a6
-    mull    a5, a2, a4
-    assert  eq, a5, a6
-    mull    a2, a2, a4
-    assert  eq, a2, a6
-    mull    a3, a4, a3
-    assert  eq, a3, a6
-test_end
-
-/* unfortunately dc232b doesn't have muluh/mulsh*/
-
-test_suite_end
diff --git a/tests/xtensa/test_nsa.S b/tests/xtensa/test_nsa.S
deleted file mode 100644
index a5fe5de..0000000
--- a/tests/xtensa/test_nsa.S
+++ /dev/null
@@ -1,59 +0,0 @@
-.include "macros.inc"
-
-test_suite nsa
-
-test nsa
-    movi    a2, 0
-    movi    a3, 31
-    nsa     a4, a2
-    assert  eq, a3, a4
-
-    movi    a2, 0xffffffff
-    movi    a3, 31
-    nsa     a4, a2
-    assert  eq, a3, a4
-
-    movi    a2, 1
-    movi    a3, 30
-    nsa     a2, a2
-    assert  eq, a3, a2
-
-    movi    a2, 0xfffffffe
-    movi    a3, 30
-    nsa     a2, a2
-    assert  eq, a3, a2
-
-    movi    a2, 0x5a5a5a5a
-    movi    a3, 0
-    nsa     a4, a2
-    assert  eq, a3, a4
-
-    movi    a2, 0xa5a5a5a5
-    movi    a3, 0
-    nsa     a4, a2
-    assert  eq, a3, a4
-test_end
-
-test nsau
-    movi    a2, 0
-    movi    a3, 32
-    nsau    a4, a2
-    assert  eq, a3, a4
-
-    movi    a2, 0xffffffff
-    movi    a3, 0
-    nsau    a4, a2
-    assert  eq, a3, a4
-
-    movi    a2, 1
-    movi    a3, 31
-    nsau    a2, a2
-    assert  eq, a3, a2
-
-    movi    a2, 0x5a5a5a5a
-    movi    a3, 1
-    nsau    a2, a2
-    assert  eq, a3, a2
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_pipeline.S b/tests/xtensa/test_pipeline.S
deleted file mode 100644
index 6be6085..0000000
--- a/tests/xtensa/test_pipeline.S
+++ /dev/null
@@ -1,157 +0,0 @@
-.include "macros.inc"
-
-.purgem test
-.macro test name
-    movi    a2, 1f
-    movi    a3, 99f
-0:
-    ipf     a2, 0
-    ipf     a2, 4
-    ipf     a2, 8
-    ipf     a2, 12
-    addi    a2, a2, 16
-    blt     a2, a3, 0b
-    j       1f
-    .align 4
-1:
-.endm
-
-test_suite pipeline
-
-test register_no_stall
-    rsr     a3, ccount
-    add     a5, a6, a6
-    add     a6, a5, a5
-    rsr     a4, ccount
-    sub     a3, a4, a3
-    assert  eqi, a3, 3
-test_end
-
-test register_stall
-    l32i    a5, a1, 0   /* data cache preload */
-    nop
-    rsr     a3, ccount
-    l32i    a5, a1, 0
-    add     a6, a5, a5  /* M-to-E interlock */
-    rsr     a4, ccount
-    sub     a3, a4, a3
-    assert  eqi, a3, 4
-test_end
-
-test j0_stall
-    rsr     a3, ccount
-    j       1f          /* E + 2-cycle penalty */
-1:
-    rsr     a4, ccount  /* E */
-    sub     a3, a4, a3
-    assert  eqi, a3, 4
-test_end
-
-test j1_stall
-    rsr     a3, ccount
-    j       1f
-    nop
-1:
-    rsr     a4, ccount
-    sub     a3, a4, a3
-    assert  eqi, a3, 4
-test_end
-
-test j5_stall
-    rsr     a3, ccount
-    j       1f
-    nop
-    nop
-    nop
-    nop
-    nop
-1:
-    rsr     a4, ccount
-    sub     a3, a4, a3
-    assert  eqi, a3, 4
-test_end
-
-test b_no_stall
-    movi    a5, 1
-    rsr     a3, ccount
-    beqi    a5, 2, 1f
-    rsr     a4, ccount
-    sub     a3, a4, a3
-    assert  eqi, a3, 2
-1:
-test_end
-
-test b1_stall
-    movi    a5, 1
-    rsr     a3, ccount
-    beqi    a5, 1, 1f
-    nop
-1:
-    rsr     a4, ccount
-    sub     a3, a4, a3
-    assert  eqi, a3, 4
-test_end
-
-test b5_stall
-    movi    a5, 1
-    rsr     a3, ccount
-    beqi    a5, 1, 1f
-    nop
-    nop
-    nop
-    nop
-    nop
-1:
-    rsr     a4, ccount
-    sub     a3, a4, a3
-    assert  eqi, a3, 4
-test_end
-
-/* PS *SYNC */
-
-test ps_dsync
-    rsr     a5, ps
-    isync
-    rsr     a3, ccount
-    wsr     a5, ps
-    dsync
-    rsr     a4, ccount
-    sub     a3, a4, a3
-    assert  eqi, a3, 5
-test_end
-
-test ps_esync
-    rsr     a5, ps
-    isync
-    rsr     a3, ccount
-    wsr     a5, ps
-    esync
-    rsr     a4, ccount
-    sub     a3, a4, a3
-    assert  eqi, a3, 5
-test_end
-
-test ps_rsync
-    rsr     a5, ps
-    isync
-    rsr     a3, ccount
-    wsr     a5, ps
-    rsync
-    rsr     a4, ccount
-    sub     a3, a4, a3
-    assert  eqi, a3, 5
-test_end
-
-test ps_isync
-    rsr     a5, ps
-    isync
-    rsr     a3, ccount
-    wsr     a5, ps
-    isync
-    rsr     a4, ccount
-    sub     a3, a4, a3
-    movi    a4, 9
-    assert  eq, a3, a4
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_quo.S b/tests/xtensa/test_quo.S
deleted file mode 100644
index 12debf1..0000000
--- a/tests/xtensa/test_quo.S
+++ /dev/null
@@ -1,147 +0,0 @@
-.include "macros.inc"
-
-test_suite quo
-
-test quou_pp
-    movi    a2, 0x5a5a137f
-    mov     a3, a2
-    movi    a4, 0x137f5a5a
-    movi    a6, 0x4
-    quou    a5, a2, a4
-    assert  eq, a5, a6
-    quou    a2, a2, a4
-    assert  eq, a2, a6
-    quou    a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test quou_np
-    movi    a2, 0xa5a5137f
-    mov     a3, a2
-    movi    a4, 0x137f5a5a
-    movi    a6, 0x8
-    quou    a5, a2, a4
-    assert  eq, a5, a6
-    quou    a2, a2, a4
-    assert  eq, a2, a6
-    quou    a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test quou_pn
-    movi    a2, 0x5a5a137f
-    mov     a3, a2
-    movi    a4, 0xf7315a5a
-    movi    a6, 0
-    quou    a5, a2, a4
-    assert  eq, a5, a6
-    quou    a2, a2, a4
-    assert  eq, a2, a6
-    quou    a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test quou_nn
-    movi    a2, 0xf7315a5a
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0x1
-    quou    a5, a2, a4
-    assert  eq, a5, a6
-    quou    a2, a2, a4
-    assert  eq, a2, a6
-    quou    a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test quou_exc
-    set_vector kernel, 2f
-    movi    a2, 0xf7315a5a
-    movi    a4, 0x00000000
-1:
-    quou    a5, a2, a4
-    test_fail
-2:
-    rsr     a2, exccause
-    assert  eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
-    rsr     a2, epc1
-    movi    a3, 1b
-    assert  eq, a2, a3
-test_end
-
-test quos_pp
-    movi    a2, 0x5a5a137f
-    mov     a3, a2
-    movi    a4, 0x137f5a5a
-    movi    a6, 0x4
-    quos    a5, a2, a4
-    assert  eq, a5, a6
-    quos    a2, a2, a4
-    assert  eq, a2, a6
-    quos    a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test quos_np
-    movi    a2, 0xa5a5137f
-    mov     a3, a2
-    movi    a4, 0x137f5a5a
-    movi    a6, 0xfffffffc
-    quos    a5, a2, a4
-    assert  eq, a5, a6
-    quos    a2, a2, a4
-    assert  eq, a2, a6
-    quos    a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test quos_pn
-    movi    a2, 0x5a5a137f
-    mov     a3, a2
-    movi    a4, 0xf7315a5a
-    movi    a6, 0xfffffff6
-    quos    a5, a2, a4
-    assert  eq, a5, a6
-    quos    a2, a2, a4
-    assert  eq, a2, a6
-    quos    a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test quos_nn
-    movi    a2, 0xf7315a5a
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0
-    quos    a5, a2, a4
-    assert  eq, a5, a6
-    quos    a2, a2, a4
-    assert  eq, a2, a6
-    quos    a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test quos_over
-    movi    a2, 0x80000000
-    movi    a4, 0xffffffff
-    movi    a6, 0x80000000
-    quos    a5, a2, a4
-    assert  eq, a5, a6
-test_end
-
-test quos_exc
-    set_vector kernel, 2f
-    movi    a2, 0xf7315a5a
-    movi    a4, 0x00000000
-1:
-    quos    a5, a2, a4
-    test_fail
-2:
-    rsr     a2, exccause
-    assert  eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
-    rsr     a2, epc1
-    movi    a3, 1b
-    assert  eq, a2, a3
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_rem.S b/tests/xtensa/test_rem.S
deleted file mode 100644
index bb0d5fe..0000000
--- a/tests/xtensa/test_rem.S
+++ /dev/null
@@ -1,147 +0,0 @@
-.include "macros.inc"
-
-test_suite rem
-
-test remu_pp
-    movi    a2, 0x5a5a137f
-    mov     a3, a2
-    movi    a4, 0x137f5a5a
-    movi    a6, 0x0c5caa17
-    remu    a5, a2, a4
-    assert  eq, a5, a6
-    remu    a2, a2, a4
-    assert  eq, a2, a6
-    remu    a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test remu_np
-    movi    a2, 0xa5a5137f
-    mov     a3, a2
-    movi    a4, 0x137f5a5a
-    movi    a6, 0x9aa40af
-    remu    a5, a2, a4
-    assert  eq, a5, a6
-    remu    a2, a2, a4
-    assert  eq, a2, a6
-    remu    a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test remu_pn
-    movi    a2, 0x5a5a137f
-    mov     a3, a2
-    movi    a4, 0xf7315a5a
-    movi    a6, 0x5a5a137f
-    remu    a5, a2, a4
-    assert  eq, a5, a6
-    remu    a2, a2, a4
-    assert  eq, a2, a6
-    remu    a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test remu_nn
-    movi    a2, 0xf7315a5a
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0x518c46db
-    remu    a5, a2, a4
-    assert  eq, a5, a6
-    remu    a2, a2, a4
-    assert  eq, a2, a6
-    remu    a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test remu_exc
-    set_vector kernel, 2f
-    movi    a2, 0xf7315a5a
-    movi    a4, 0x00000000
-1:
-    remu    a5, a2, a4
-    test_fail
-2:
-    rsr     a2, exccause
-    assert  eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
-    rsr     a2, epc1
-    movi    a3, 1b
-    assert  eq, a2, a3
-test_end
-
-test rems_pp
-    movi    a2, 0x5a5a137f
-    mov     a3, a2
-    movi    a4, 0x137f5a5a
-    movi    a6, 0x0c5caa17
-    rems    a5, a2, a4
-    assert  eq, a5, a6
-    rems    a2, a2, a4
-    assert  eq, a2, a6
-    rems    a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test rems_np
-    movi    a2, 0xa5a5137f
-    mov     a3, a2
-    movi    a4, 0x137f5a5a
-    movi    a6, 0xf3a27ce7
-    rems    a5, a2, a4
-    assert  eq, a5, a6
-    rems    a2, a2, a4
-    assert  eq, a2, a6
-    rems    a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test rems_pn
-    movi    a2, 0x5a5a137f
-    mov     a3, a2
-    movi    a4, 0xf7315a5a
-    movi    a6, 0x02479b03
-    rems    a5, a2, a4
-    assert  eq, a5, a6
-    rems    a2, a2, a4
-    assert  eq, a2, a6
-    rems    a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test rems_nn
-    movi    a2, 0xf7315a5a
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0xf7315a5a
-    rems    a5, a2, a4
-    assert  eq, a5, a6
-    rems    a2, a2, a4
-    assert  eq, a2, a6
-    rems    a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test rems_over
-    movi    a2, 0x80000000
-    movi    a4, 0xffffffff
-    movi    a6, 0
-    rems    a5, a2, a4
-    assert  eq, a5, a6
-test_end
-
-test rems_exc
-    set_vector kernel, 2f
-    movi    a2, 0xf7315a5a
-    movi    a4, 0x00000000
-1:
-    rems    a5, a2, a4
-    test_fail
-2:
-    rsr     a2, exccause
-    assert  eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
-    rsr     a2, epc1
-    movi    a3, 1b
-    assert  eq, a2, a3
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_rst0.S b/tests/xtensa/test_rst0.S
deleted file mode 100644
index 3eda565..0000000
--- a/tests/xtensa/test_rst0.S
+++ /dev/null
@@ -1,148 +0,0 @@
-.include "macros.inc"
-
-test_suite rst0
-
-test and
-    movi    a2, 0x137fa5a5
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0x01250125
-    and     a5, a2, a4
-    assert  eq, a5, a6
-    and     a2, a2, a4
-    assert  eq, a2, a6
-    and     a3, a4, a3
-    assert  eq, a3, a6
-test_end
-
-test or
-    movi    a2, 0x137fa5a5
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0xb7ffb7ff
-    or      a5, a2, a4
-    assert  eq, a5, a6
-    or      a2, a2, a4
-    assert  eq, a2, a6
-    or      a3, a4, a3
-    assert  eq, a3, a6
-test_end
-
-test xor
-    movi    a2, 0x137fa5a5
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0xb6dab6da
-    xor     a5, a2, a4
-    assert  eq, a5, a6
-    xor     a2, a2, a4
-    assert  eq, a2, a6
-    xor     a3, a4, a3
-    assert  eq, a3, a6
-test_end
-
-test add
-    movi    a2, 0x137fa5a5
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0xb924b924
-    add     a5, a2, a4
-    assert  eq, a5, a6
-    add     a2, a2, a4
-    assert  eq, a2, a6
-    add     a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test addx2
-    movi    a2, 0x137fa5a5
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0xcca45ec9
-    addx2   a5, a2, a4
-    assert  eq, a5, a6
-    addx2   a2, a2, a4
-    assert  eq, a2, a6
-    addx2   a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test addx4
-    movi    a2, 0x137fa5a5
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0xf3a3aa13
-    addx4   a5, a2, a4
-    assert  eq, a5, a6
-    addx4   a2, a2, a4
-    assert  eq, a2, a6
-    addx4   a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test addx8
-    movi    a2, 0x137fa5a5
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0x41a240a7
-    addx8   a5, a2, a4
-    assert  eq, a5, a6
-    addx8   a2, a2, a4
-    assert  eq, a2, a6
-    addx8   a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test sub
-    movi    a2, 0x137fa5a5
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0x6dda9226
-    sub     a5, a2, a4
-    assert  eq, a5, a6
-    sub     a2, a2, a4
-    assert  eq, a2, a6
-    sub     a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test subx2
-    movi    a2, 0x137fa5a5
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0x815a37cb
-    subx2   a5, a2, a4
-    assert  eq, a5, a6
-    subx2   a2, a2, a4
-    assert  eq, a2, a6
-    subx2   a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test subx4
-    movi    a2, 0x137fa5a5
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0xa8598315
-    subx4   a5, a2, a4
-    assert  eq, a5, a6
-    subx4   a2, a2, a4
-    assert  eq, a2, a6
-    subx4   a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test subx8
-    movi    a2, 0x137fa5a5
-    mov     a3, a2
-    movi    a4, 0xa5a5137f
-    movi    a6, 0xf65819a9
-    subx8   a5, a2, a4
-    assert  eq, a5, a6
-    subx8   a2, a2, a4
-    assert  eq, a2, a6
-    subx8   a4, a3, a4
-    assert  eq, a4, a6
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_sar.S b/tests/xtensa/test_sar.S
deleted file mode 100644
index 40c649f..0000000
--- a/tests/xtensa/test_sar.S
+++ /dev/null
@@ -1,111 +0,0 @@
-.include "macros.inc"
-
-test_suite sar
-
-.macro test_sar prefix, imm
-    \prefix\()_set \imm
-    \prefix\()_ver \imm
-.endm
-
-.macro tests_sar prefix
-    test_sar \prefix, 0
-    test_sar \prefix, 1
-    test_sar \prefix, 2
-    test_sar \prefix, 3
-    test_sar \prefix, 0x1f
-    test_sar \prefix, 0x20
-    test_sar \prefix, 0x3f
-    test_sar \prefix, 0x40
-    test_sar \prefix, 0xfffffffe
-.endm
-
-.macro sar_set imm
-    movi    a2, \imm
-    wsr     a2, sar
-.endm
-
-.macro sar_ver imm
-    rsr     a3, sar
-    movi    a2, \imm & 0x3f
-    assert  eq, a2, a3
-.endm
-
-test sar
-    tests_sar sar
-test_end
-
-.macro ssr_set imm
-    movi    a2, \imm
-    ssr     a2
-.endm
-
-.macro ssr_ver imm
-    rsr     a3, sar
-    movi    a2, \imm & 0x1f
-    assert  eq, a2, a3
-.endm
-
-test ssr
-    tests_sar ssr
-test_end
-
-.macro ssl_set imm
-    movi    a2, \imm
-    ssl     a2
-.endm
-
-.macro ssl_ver imm
-    rsr     a3, sar
-    movi    a2, 32 - (\imm & 0x1f)
-    assert  eq, a2, a3
-.endm
-
-test ssl
-    tests_sar ssl
-test_end
-
-.macro ssa8l_set imm
-    movi    a2, \imm
-    ssa8l   a2
-.endm
-
-.macro ssa8l_ver imm
-    rsr     a3, sar
-    movi    a2, (\imm & 0x3) << 3
-    assert  eq, a2, a3
-.endm
-
-test ssa8l
-    tests_sar ssa8l
-test_end
-
-.macro ssa8b_set imm
-    movi    a2, \imm
-    ssa8b   a2
-.endm
-
-.macro ssa8b_ver imm
-    rsr     a3, sar
-    movi    a2, 32 - ((\imm & 0x3) << 3)
-    assert  eq, a2, a3
-.endm
-
-test ssa8b
-    tests_sar ssa8b
-test_end
-
-.macro ssai_set imm
-    ssai    \imm & 0x1f
-.endm
-
-.macro ssai_ver imm
-    rsr     a3, sar
-    movi    a2, \imm & 0x1f
-    assert  eq, a2, a3
-.endm
-
-test ssai
-    tests_sar ssai
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_sext.S b/tests/xtensa/test_sext.S
deleted file mode 100644
index 04dc650..0000000
--- a/tests/xtensa/test_sext.S
+++ /dev/null
@@ -1,69 +0,0 @@
-.include "macros.inc"
-
-test_suite sext
-
-test sext
-    movi    a2, 0xffffff5a
-    movi    a3, 0x0000005a
-    sext    a4, a2, 7
-    assert  eq, a3, a4
-
-    movi    a2, 0x000000a5
-    movi    a3, 0xffffffa5
-    sext    a4, a2, 7
-    assert  eq, a3, a4
-
-    movi    a2, 0xfffffaa5
-    movi    a3, 0x000000a5
-    sext    a4, a2, 8
-    assert  eq, a3, a4
-
-    movi    a2, 0x0000055a
-    movi    a3, 0xffffff5a
-    sext    a4, a2, 8
-    assert  eq, a3, a4
-
-    movi    a2, 0xffff5a5a
-    movi    a3, 0x00005a5a
-    sext    a4, a2, 15
-    assert  eq, a3, a4
-
-    movi    a2, 0x0000a5a5
-    movi    a3, 0xffffa5a5
-    sext    a4, a2, 15
-    assert  eq, a3, a4
-
-    movi    a2, 0x00055a5a
-    movi    a3, 0xffff5a5a
-    sext    a4, a2, 16
-    assert  eq, a3, a4
-
-    movi    a2, 0x000aa5a5
-    movi    a3, 0x0000a5a5
-    sext    a4, a2, 16
-    assert  eq, a3, a4
-
-    movi    a2, 0x005a5a5a
-    movi    a3, 0xffda5a5a
-    sext    a4, a2, 22
-    assert  eq, a3, a4
-
-    movi    a2, 0xffa5a5a5
-    movi    a3, 0x0025a5a5
-    sext    a4, a2, 22
-    assert  eq, a3, a4
-test_end
-
-test sext_same_rs
-    movi    a2, 0xffffff5a
-    movi    a3, 0x0000005a
-    sext    a2, a2, 7
-    assert  eq, a3, a2
-
-    movi    a2, 0x000000a5
-    movi    a3, 0xffffffa5
-    sext    a2, a2, 7
-    assert  eq, a3, a2
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_shift.S b/tests/xtensa/test_shift.S
deleted file mode 100644
index a8e4364..0000000
--- a/tests/xtensa/test_shift.S
+++ /dev/null
@@ -1,206 +0,0 @@
-.include "macros.inc"
-
-test_suite shift
-
-.macro test_shift prefix, dst, src, v, imm
-    \prefix\()_set \dst, \src, \v, \imm
-    \prefix\()_ver \dst, \v, \imm
-.endm
-
-.macro test_shift_sd prefix, v, imm
-    test_shift \prefix, a3, a2, \v, \imm
-    test_shift \prefix, a2, a2, \v, \imm
-.endm
-
-.macro tests_imm_shift prefix, v
-    test_shift_sd \prefix, \v, 1
-    test_shift_sd \prefix, \v, 2
-    test_shift_sd \prefix, \v, 7
-    test_shift_sd \prefix, \v, 8
-    test_shift_sd \prefix, \v, 15
-    test_shift_sd \prefix, \v, 16
-    test_shift_sd \prefix, \v, 31
-.endm
-
-.macro tests_shift prefix, v
-    test_shift_sd \prefix, \v, 0
-    tests_imm_shift \prefix, \v
-    test_shift_sd \prefix, \v, 32
-.endm
-
-
-.macro slli_set dst, src, v, imm
-    movi    \src, \v
-    slli    \dst, \src, \imm
-.endm
-
-.macro slli_ver dst, v, imm
-    mov     a2, \dst
-    movi    a3, ((\v) << (\imm)) & 0xffffffff
-    assert  eq, a2, a3
-.endm
-
-test slli
-    tests_imm_shift slli, 0xa3c51249
-test_end
-
-
-.macro srai_set dst, src, v, imm
-    movi    \src, \v
-    srai    \dst, \src, \imm
-.endm
-
-.macro srai_ver dst, v, imm
-    mov     a2, \dst
-    .if (\imm)
-    movi    a3, (((\v) >> (\imm)) & 0xffffffff) | \
-                ~((((\v) & 0x80000000) >> ((\imm) - 1)) - 1)
-    .else
-    movi    a3, \v
-    .endif
-    assert  eq, a2, a3
-.endm
-
-test srai
-    tests_imm_shift srai, 0x49a3c512
-    tests_imm_shift srai, 0xa3c51249
-test_end
-
-
-.macro srli_set dst, src, v, imm
-    movi    \src, \v
-    srli    \dst, \src, \imm
-.endm
-
-.macro srli_ver dst, v, imm
-    mov     a2, \dst
-    movi    a3, (((\v) >> (\imm)) & 0xffffffff)
-    assert  eq, a2, a3
-.endm
-
-test srli
-    tests_imm_shift srli, 0x49a3c512
-    tests_imm_shift srli, 0xa3c51249
-test_end
-
-
-.macro sll_set dst, src, v, imm
-    movi    a2, \imm
-    ssl     a2
-    movi    \src, \v
-    sll     \dst, \src
-.endm
-
-.macro sll_sar_set dst, src, v, imm
-    movi    a2, 32 - \imm
-    wsr     a2, sar
-    movi    \src, \v
-    sll     \dst, \src
-.endm
-
-.macro sll_ver dst, v, imm
-    slli_ver \dst, \v, (\imm) & 0x1f
-.endm
-
-.macro sll_sar_ver dst, v, imm
-    slli_ver \dst, \v, \imm
-.endm
-
-test sll
-    tests_shift sll, 0xa3c51249
-    tests_shift sll_sar, 0xa3c51249
-test_end
-
-
-.macro srl_set dst, src, v, imm
-    movi    a2, \imm
-    ssr     a2
-    movi    \src, \v
-    srl     \dst, \src
-.endm
-
-.macro srl_sar_set dst, src, v, imm
-    movi    a2, \imm
-    wsr     a2, sar
-    movi    \src, \v
-    srl     \dst, \src
-.endm
-
-.macro srl_ver dst, v, imm
-    srli_ver \dst, \v, (\imm) & 0x1f
-.endm
-
-.macro srl_sar_ver dst, v, imm
-    srli_ver \dst, \v, \imm
-.endm
-
-test srl
-    tests_shift srl, 0xa3c51249
-    tests_shift srl_sar, 0xa3c51249
-    tests_shift srl, 0x49a3c512
-    tests_shift srl_sar, 0x49a3c512
-test_end
-
-
-.macro sra_set dst, src, v, imm
-    movi    a2, \imm
-    ssr     a2
-    movi    \src, \v
-    sra     \dst, \src
-.endm
-
-.macro sra_sar_set dst, src, v, imm
-    movi    a2, \imm
-    wsr     a2, sar
-    movi    \src, \v
-    sra     \dst, \src
-.endm
-
-.macro sra_ver dst, v, imm
-    srai_ver \dst, \v, (\imm) & 0x1f
-.endm
-
-.macro sra_sar_ver dst, v, imm
-    srai_ver \dst, \v, \imm
-.endm
-
-test sra
-    tests_shift sra, 0xa3c51249
-    tests_shift sra_sar, 0xa3c51249
-    tests_shift sra, 0x49a3c512
-    tests_shift sra_sar, 0x49a3c512
-test_end
-
-
-.macro src_set dst, src, v, imm
-    movi    a2, \imm
-    ssr     a2
-    movi    \src, (\v) & 0xffffffff
-    movi    a4, (\v) >> 32
-    src     \dst, a4, \src
-.endm
-
-.macro src_sar_set dst, src, v, imm
-    movi    a2, \imm
-    wsr     a2, sar
-    movi    \src, (\v) & 0xffffffff
-    movi    a4, (\v) >> 32
-    src     \dst, a4, \src
-.endm
-
-.macro src_ver dst, v, imm
-    src_sar_ver \dst, \v, (\imm) & 0x1f
-.endm
-
-.macro src_sar_ver dst, v, imm
-    mov     a2, \dst
-    movi    a3, ((\v) >> (\imm)) & 0xffffffff
-    assert  eq, a2, a3
-.endm
-
-test src
-    tests_shift src, 0xa3c51249215c3a94
-    tests_shift src_sar, 0xa3c51249215c3a94
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_timer.S b/tests/xtensa/test_timer.S
deleted file mode 100644
index 1041cc6..0000000
--- a/tests/xtensa/test_timer.S
+++ /dev/null
@@ -1,178 +0,0 @@
-.include "macros.inc"
-
-test_suite timer
-
-test ccount
-    rsr     a3, ccount
-    rsr     a4, ccount
-    sub     a3, a4, a3
-    assert  eqi, a3, 1
-test_end
-
-test ccompare
-    movi    a2, 0
-    wsr     a2, intenable
-    rsr     a2, interrupt
-    wsr     a2, intclear
-    movi    a2, 0
-    wsr     a2, ccompare1
-    wsr     a2, ccompare2
-
-    movi    a3, 20
-    rsr     a2, ccount
-    addi    a2, a2, 20
-    wsr     a2, ccompare0
-    rsr     a2, interrupt
-    assert  eqi, a2, 0
-    loop    a3, 1f
-    rsr     a3, interrupt
-    bnez    a3, 2f
-1:
-    test_fail
-2:
-test_end
-
-test ccompare0_interrupt
-    set_vector kernel, 2f
-    movi    a2, 0
-    wsr     a2, intenable
-    rsr     a2, interrupt
-    wsr     a2, intclear
-    movi    a2, 0
-    wsr     a2, ccompare1
-    wsr     a2, ccompare2
-
-    movi    a3, 20
-    rsr     a2, ccount
-    addi    a2, a2, 20
-    wsr     a2, ccompare0
-    rsync
-    rsr     a2, interrupt
-    assert  eqi, a2, 0
-
-    movi    a2, 0x40
-    wsr     a2, intenable
-    rsil    a2, 0
-    loop    a3, 1f
-    nop
-1:
-    test_fail
-2:
-    rsr     a2, exccause
-    assert  eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
-test_end
-
-test ccompare1_interrupt
-    set_vector level3, 2f
-    movi    a2, 0
-    wsr     a2, intenable
-    rsr     a2, interrupt
-    wsr     a2, intclear
-    movi    a2, 0
-    wsr     a2, ccompare0
-    wsr     a2, ccompare2
-
-    movi    a3, 20
-    rsr     a2, ccount
-    addi    a2, a2, 20
-    wsr     a2, ccompare1
-    rsync
-    rsr     a2, interrupt
-    assert  eqi, a2, 0
-    movi    a2, 0x400
-    wsr     a2, intenable
-    rsil    a2, 2
-    loop    a3, 1f
-    nop
-1:
-    test_fail
-2:
-test_end
-
-test ccompare2_interrupt
-    set_vector level5, 2f
-    movi    a2, 0
-    wsr     a2, intenable
-    rsr     a2, interrupt
-    wsr     a2, intclear
-    movi    a2, 0
-    wsr     a2, ccompare0
-    wsr     a2, ccompare1
-
-    movi    a3, 20
-    rsr     a2, ccount
-    addi    a2, a2, 20
-    wsr     a2, ccompare2
-    rsync
-    rsr     a2, interrupt
-    assert  eqi, a2, 0
-    movi    a2, 0x2000
-    wsr     a2, intenable
-    rsil    a2, 4
-    loop    a3, 1f
-    nop
-1:
-    test_fail
-2:
-test_end
-
-test ccompare_interrupt_masked
-    set_vector kernel, 2f
-    movi    a2, 0
-    wsr     a2, intenable
-    rsr     a2, interrupt
-    wsr     a2, intclear
-    movi    a2, 0
-    wsr     a2, ccompare2
-
-    movi    a3, 40
-    rsr     a2, ccount
-    addi    a2, a2, 20
-    wsr     a2, ccompare1
-    addi    a2, a2, 20
-    wsr     a2, ccompare0
-    rsync
-    rsr     a2, interrupt
-    assert  eqi, a2, 0
-
-    movi    a2, 0x40
-    wsr     a2, intenable
-    rsil    a2, 0
-    loop    a3, 1f
-    nop
-1:
-    test_fail
-2:
-    rsr     a2, exccause
-    assert  eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
-test_end
-
-test ccompare_interrupt_masked_waiti
-    set_vector kernel, 2f
-    movi    a2, 0
-    wsr     a2, intenable
-    rsr     a2, interrupt
-    wsr     a2, intclear
-    movi    a2, 0
-    wsr     a2, ccompare2
-
-    movi    a3, 40
-    rsr     a2, ccount
-    addi    a2, a2, 20
-    wsr     a2, ccompare1
-    addi    a2, a2, 20
-    wsr     a2, ccompare0
-    rsync
-    rsr     a2, interrupt
-    assert  eqi, a2, 0
-
-    movi    a2, 0x40
-    wsr     a2, intenable
-    waiti   0
-    test_fail
-2:
-    rsr     a2, exccause
-    assert  eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/test_windowed.S b/tests/xtensa/test_windowed.S
deleted file mode 100644
index cb2d39e..0000000
--- a/tests/xtensa/test_windowed.S
+++ /dev/null
@@ -1,302 +0,0 @@
-.include "macros.inc"
-
-test_suite windowed
-
-.altmacro
-
-.macro reset_window start
-    movi    a2, 0xff
-    wsr     a2, windowstart
-    rsync
-    movi    a2, 0
-    wsr     a2, windowbase
-    rsync
-    movi    a2, \start
-    wsr     a2, windowstart
-    rsync
-.endm
-
-.macro overflow_test shift, window, probe_ok, probe_ex
-    set_vector window_overflow_4, 0
-    set_vector window_overflow_8, 0
-    set_vector window_overflow_12, 0
-
-    movi    a2, 1 | (((1 << ((\window) / 4)) | 1) << ((\shift) / 4))
-    wsr     a2, windowstart
-    reset_ps
-
-    mov     a2, a\probe_ok
-    set_vector window_overflow_\window, 10f
-1:
-    mov     a2, a\probe_ex
-    test_fail
-10:
-    rsr     a2, epc1
-    movi    a3, 1b
-    assert  eq, a2, a3
-    movi    a2, 2f
-    wsr     a2, epc1
-
-    rsr     a2, windowbase
-    movi    a3, (\shift) / 4
-    assert  eq, a2, a3
-    rsr     a2, ps
-    movi    a3, 0x4001f
-    assert  eq, a2, a3
-    rfwo
-    test_fail
-2:
-    rsr     a2, windowbase
-    assert  eqi, a2, 0
-    rsr     a2, windowstart
-    movi    a3, 1 | ((1 << ((\window) / 4)) << ((\shift) / 4))
-    assert  eq, a2, a3
-    rsr     a2, ps
-    movi    a3, 0x4000f
-    assert  eq, a2, a3
-.endm
-
-.macro overflow_tests shift, window, probe
-    .if \probe < 15
-    overflow_test \shift, \window, %((\shift) - 1), \probe
-    overflow_tests \shift, \window, %((\probe) + 1)
-    .endif
-.endm
-
-.macro all_overflow_tests
-    .irp shift, 4, 8, 12
-    .irp window, 4, 8, 12
-    overflow_tests \shift, \window, \shift
-    .endr
-    .endr
-.endm
-
-test overflow
-    all_overflow_tests
-test_end
-
-
-.macro underflow_test window
-    set_vector window_underflow_4, 0
-    set_vector window_underflow_8, 0
-    set_vector window_underflow_12, 0
-
-    set_vector window_underflow_\window, 10f
-
-    reset_window 1
-    reset_ps
-
-    ssai    2
-    movi    a2, 2f
-    slli    a2, a2, 2
-    movi    a3, (\window) / 4
-    src     a0, a3, a2
-1:
-    retw
-    test_fail
-10:
-    rsr     a2, epc1
-    movi    a3, 1b
-    assert  eq, a2, a3
-    movi    a2, 2f
-    wsr     a2, epc1
-
-    rsr     a2, ps
-    movi    a3, 0x4001f
-    assert  eq, a2, a3
-    rsr     a2, windowbase
-    assert  eqi, a2, 8 - ((\window) / 4)
-    rsr     a2, windowstart
-    assert  eqi, a2, 1
-    rfwu
-2:
-    rsr     a2, ps
-    movi    a3, 0x4000f
-    assert  eq, a2, a3
-    rsr     a2, windowbase
-    assert  eqi, a2, 0
-    rsr     a2, windowstart
-    assert  bsi, a2, 0
-    assert  bsi, a2, 8 - ((\window) / 4)
-.endm
-
-test underflow
-    set_vector window_overflow_4, 0
-    set_vector window_overflow_8, 0
-    set_vector window_overflow_12, 0
-
-    underflow_test 4
-    underflow_test 8
-    underflow_test 12
-test_end
-
-
-.macro retw_test window
-    reset_window %(1 | (1 << (8 - (\window) / 4)))
-    reset_ps
-
-    ssai    2
-    movi    a2, 1f
-    slli    a2, a2, 2
-    movi    a3, (\window) / 4
-    src     a0, a3, a2
-    retw
-    test_fail
-1:
-    rsr     a2, ps
-    movi    a3, 0x4000f
-    assert  eq, a2, a3
-    rsr     a2, windowbase
-    assert  eqi, a2, 8 - ((\window) / 4)
-    rsr     a2, windowstart
-    assert  bci, a2, 0
-    assert  bsi, a2, 8 - ((\window) / 4)
-.endm
-
-test retw
-    set_vector window_underflow_4, 0
-    set_vector window_underflow_8, 0
-    set_vector window_underflow_12, 0
-
-    retw_test 4
-    retw_test 8
-    retw_test 12
-test_end
-
-test movsp
-    set_vector kernel, 2f
-
-    reset_window 1
-    reset_ps
-1:
-    movsp   a2, a3
-    test_fail
-2:
-    rsr     a2, exccause
-    assert  eqi, a2, 5
-    rsr     a2, epc1
-    movi    a3, 1b
-    assert  eq, a2, a3
-
-    set_vector kernel, 0
-
-    reset_window 0x81
-    reset_ps
-
-    movsp   a2, a3
-test_end
-
-test rotw
-    reset_window 0x4b
-    reset_ps
-
-    movi    a3, 0x10
-
-    rotw    1
-    rsr     a2, windowbase
-    assert  eqi, a2, 1
-    movi    a3, 0x11
-    movi    a7, 0x12
-
-    rotw    2
-    rsr     a2, windowbase
-    assert  eqi, a2, 3
-    movi    a3, 0x13
-    movi    a7, 0x14
-    movi    a11, 0x15
-
-    rotw    3
-    rsr     a2, windowbase
-    assert  eqi, a2, 6
-    movi    a3, 0x16
-    movi    a7, 0x17
-
-    movi    a2, 0x44
-    wsr     a2, windowstart
-    rsync
-
-    movi    a2, 0x10
-    assert  eq, a2, a11
-    movi    a11, 0x18
-    movi    a2, 0x11
-    assert  eq, a2, a15
-    movi    a15, 0x19
-
-    rotw    4
-    movi    a2, 0x12
-    assert  eq, a2, a3
-    movi    a2, 0x13
-    assert  eq, a2, a7
-    movi    a2, 0x14
-    assert  eq, a2, a11
-    movi    a2, 0x15
-    assert  eq, a2, a15
-
-    movi    a2, 0x5
-    wsr     a2, windowstart
-    rsync
-
-    rotw    -2
-    movi    a2, 0x18
-    assert  eq, a2, a3
-    movi    a2, 0x19
-    assert  eq, a2, a7
-test_end
-
-.macro callw_test window
-    call\window 2f
-1:
-    test_fail
-    .align  4
-2:
-    rsr     a2, windowbase
-    assert  eqi, a2, 0
-    rsr     a2, ps
-    movi    a3, 0x4000f | ((\window) << 14)
-    assert  eq, a2, a3
-    movi    a2, 1b
-    slli    a2, a2, 2
-    ssai    2
-    movi    a3, (\window) / 4
-    src     a2, a3, a2
-    assert  eq, a2, a\window
-.endm
-
-test callw
-    reset_window 0x1
-    reset_ps
-
-    callw_test 4
-    callw_test 8
-    callw_test 12
-test_end
-
-
-.macro entry_test window
-    reset_window 0x1
-    reset_ps
-    movi    a2, 0x4000f | ((\window) << 14)
-    wsr     a2, ps
-    isync
-    movi    a3, 0x12345678
-    j       1f
-    .align  4
-1:
-    entry   a3, 0x5678
-    movi    a2, 0x12340000
-    assert  eq, a2, a3
-    rsr     a2, windowbase
-    assert  eqi, a2, (\window) / 4
-    rsr     a2, windowstart
-    movi    a3, 1 | (1 << ((\window) / 4))
-    assert  eq, a2, a3
-    rotw    -(\window) / 4
-.endm
-
-test entry
-    entry_test 4
-    entry_test 8
-    entry_test 12
-test_end
-
-test_suite_end
diff --git a/tests/xtensa/vectors.S b/tests/xtensa/vectors.S
deleted file mode 100644
index 265a181..0000000
--- a/tests/xtensa/vectors.S
+++ /dev/null
@@ -1,39 +0,0 @@
-.macro vector name
-
-.section .vector.\name
-    j       1f
-.section .vector.\name\().text
-1:
-    wsr     a2, excsave1
-    movi    a2, handler_\name
-    l32i    a2, a2, 0
-    beqz    a2, 1f
-    jx      a2
-1:
-    movi    a3, 1b
-    movi    a2, 1
-    simcall
-
-.align 4
-.global handler_\name
-handler_\name\(): .word 0
-
-.endm
-
-vector window_overflow_4
-vector window_overflow_8
-vector window_overflow_12
-vector window_underflow_4
-vector window_underflow_8
-vector window_underflow_12
-
-vector level2
-vector level3
-vector level4
-vector level5
-vector level6
-vector level7
-
-vector kernel
-vector user
-vector double
commit a0f426109e17d579c2712f5b96a50215e6cc06a4
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jan 3 15:32:57 2012 +0200

    vga: optimize ppm_save() divisions
    
    ppm_save() spends upwards of 50% of its time doing divisions. Replace them
    with shifts.
    
    Reviewed-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/vga.c b/hw/vga.c
index 4878fbc..950f97e 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2373,12 +2373,10 @@ int ppm_save(const char *filename, struct DisplaySurface *ds)
                 v = *(uint32_t *)d;
             else
                 v = (uint32_t) (*(uint16_t *)d);
-            r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 /
-                (ds->pf.rmax + 1);
-            g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 /
-                (ds->pf.gmax + 1);
-            b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
-                (ds->pf.bmax + 1);
+            /* Limited to 8 or fewer bits per channel: */
+            r = ((v >> ds->pf.rshift) & ds->pf.rmax) << (8 - ds->pf.rbits);
+            g = ((v >> ds->pf.gshift) & ds->pf.gmax) << (8 - ds->pf.gbits);
+            b = ((v >> ds->pf.bshift) & ds->pf.bmax) << (8 - ds->pf.bbits);
             *pbuf++ = r;
             *pbuf++ = g;
             *pbuf++ = b;
commit 19bf7c87081835449d5683ecb0858255bf5a0546
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Dec 28 12:26:58 2011 +0200

    Fix qapi code generation fix
    
    The fixes to qapi code generation had multiple bugs:
    - the Null class used to drop output was missing some methods
    - in some scripts it was never instantiated, leading to a None return,
      which is missing even more methods
    - the --source and --header options were swapped
    
    Luckily, all those bugs were hidden by a makefile bug which caused the
    old behaviour (with the race) to be invoked.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index 9ce8768..21f8c76 100644
--- a/Makefile
+++ b/Makefile
@@ -177,7 +177,7 @@ qapi-dir := $(BUILD_DIR)/qapi-generated
 test-qmp-input-visitor.o test-qmp-output-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
 
-gen-out-type = $(subst .,-,$@)
+gen-out-type = $(subst .,-,$(suffix $@))
 
 $(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
 $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index bd7b207..3aabf61 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -399,9 +399,9 @@ for o, a in opts:
     elif o in ("-m", "--middle"):
         middle_mode = True
     elif o in ("-c", "--source"):
-        do_h = True
-    elif o in ("-h", "--header"):
         do_c = True
+    elif o in ("-h", "--header"):
+        do_h = True
 
 if not do_c and not do_h:
     do_c = True
@@ -411,15 +411,11 @@ c_file = output_dir + prefix + c_file
 h_file = output_dir + prefix + h_file
 
 def maybe_open(really, name, opt):
-    class Null(object):
-        def write(self, str):
-            pass
-        def read(self):
-            return ''
     if really:
         return open(name, opt)
     else:
-        return Null()
+        import StringIO
+        return StringIO.StringIO()
 
 try:
     os.makedirs(output_dir)
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index ae644bc..b56225b 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -183,9 +183,9 @@ for o, a in opts:
     elif o in ("-o", "--output-dir"):
         output_dir = a + "/"
     elif o in ("-c", "--source"):
-        do_h = True
-    elif o in ("-h", "--header"):
         do_c = True
+    elif o in ("-h", "--header"):
+        do_h = True
 
 if not do_c and not do_h:
     do_c = True
@@ -201,13 +201,11 @@ except os.error, e:
         raise
 
 def maybe_open(really, name, opt):
-    class Null(object):
-        def write(self, str):
-            pass
-        def read(self):
-            return ''
     if really:
         return open(name, opt)
+    else:
+        import StringIO
+        return StringIO.StringIO()
 
 fdef = maybe_open(do_c, c_file, 'w')
 fdecl = maybe_open(do_h, h_file, 'w')
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index e9d0584..5160d83 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -159,9 +159,9 @@ for o, a in opts:
     elif o in ("-o", "--output-dir"):
         output_dir = a + "/"
     elif o in ("-c", "--source"):
-        do_h = True
-    elif o in ("-h", "--header"):
         do_c = True
+    elif o in ("-h", "--header"):
+        do_h = True
 
 if not do_c and not do_h:
     do_c = True
@@ -177,13 +177,11 @@ except os.error, e:
         raise
 
 def maybe_open(really, name, opt):
-    class Null(object):
-        def write(self, str):
-            pass
-        def read(self):
-            return ''
     if really:
         return open(name, opt)
+    else:
+        import StringIO
+        return StringIO.StringIO()
 
 fdef = maybe_open(do_c, c_file, 'w')
 fdecl = maybe_open(do_h, h_file, 'w')
commit 73a511decc9c87cbc1bac0012d990e4e74a648bf
Author: Lars Persson <larper at axis.com>
Date:   Wed Dec 21 15:11:35 2011 +0100

    etraxfs-dma: Model metadata and eop
    
    - Send EOP flags to the out channels.
    - Send data descriptor metadata to the out channels.
    
    Signed-off-by: Lars Persson <larper at axis.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/etraxfs_dma.c b/hw/etraxfs_dma.c
index d2bd584..332525c 100644
--- a/hw/etraxfs_dma.c
+++ b/hw/etraxfs_dma.c
@@ -401,15 +401,29 @@ static int channel_out_run(struct fs_dma_ctrl *ctrl, int c)
 	uint32_t saved_data_buf;
 	unsigned char buf[2 * 1024];
 
+	struct dma_context_metadata meta;
+	bool send_context = true;
+
 	if (ctrl->channels[c].eol)
 		return 0;
 
 	do {
+		bool out_eop;
 		D(printf("ch=%d buf=%x after=%x\n",
 			 c,
 			 (uint32_t)ctrl->channels[c].current_d.buf,
 			 (uint32_t)ctrl->channels[c].current_d.after));
 
+		if (send_context) {
+			if (ctrl->channels[c].client->client.metadata_push) {
+				meta.metadata = ctrl->channels[c].current_d.md;
+				ctrl->channels[c].client->client.metadata_push(
+					ctrl->channels[c].client->client.opaque,
+					&meta);
+			}
+			send_context = false;
+		}
+
 		channel_load_d(ctrl, c);
 		saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
 		len = (uint32_t)(unsigned long)
@@ -420,13 +434,17 @@ static int channel_out_run(struct fs_dma_ctrl *ctrl, int c)
 			len = sizeof buf;
 		cpu_physical_memory_read (saved_data_buf, buf, len);
 
-		D(printf("channel %d pushes %x %u bytes\n", c, 
-			 saved_data_buf, len));
+		out_eop = ((saved_data_buf + len) ==
+		           ctrl->channels[c].current_d.after) &&
+			ctrl->channels[c].current_d.out_eop;
+
+		D(printf("channel %d pushes %x %u bytes eop=%u\n", c,
+		         saved_data_buf, len, out_eop));
 
 		if (ctrl->channels[c].client->client.push)
 			ctrl->channels[c].client->client.push(
 				ctrl->channels[c].client->client.opaque,
-				buf, len);
+				buf, len, out_eop);
 		else
 			printf("WARNING: DMA ch%d dataloss,"
 			       " no attached client.\n", c);
@@ -437,11 +455,9 @@ static int channel_out_run(struct fs_dma_ctrl *ctrl, int c)
 				ctrl->channels[c].current_d.after) {
 			/* Done. Step to next.  */
 			if (ctrl->channels[c].current_d.out_eop) {
-				/* TODO: signal eop to the client.  */
-				D(printf("signal eop\n"));
+				send_context = true;
 			}
 			if (ctrl->channels[c].current_d.intr) {
-				/* TODO: signal eop to the client.  */
 				/* data intr.  */
 				D(printf("signal intr %d eol=%d\n",
 					len, ctrl->channels[c].current_d.eol));
diff --git a/hw/etraxfs_dma.h b/hw/etraxfs_dma.h
index 96408ab..021c52a 100644
--- a/hw/etraxfs_dma.h
+++ b/hw/etraxfs_dma.h
@@ -1,3 +1,8 @@
+struct dma_context_metadata {
+	/* data descriptor md */
+	uint16_t metadata;
+};
+
 struct etraxfs_dma_client
 {
 	/* DMA controller. */
@@ -5,10 +10,12 @@ struct etraxfs_dma_client
 	void *ctrl;
 
 	/* client.  */
-	struct
-	{
-		int (*push)(void *opaque, unsigned char *buf, int len);
+	struct {
+		int (*push)(void *opaque, unsigned char *buf,
+		            int len, bool eop);
 		void (*pull)(void *opaque);
+		void (*metadata_push)(void *opaque,
+		                      const struct dma_context_metadata *md);
 		void *opaque;
 	} client;
 };
diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c
index b525258..5afa55f 100644
--- a/hw/etraxfs_eth.c
+++ b/hw/etraxfs_eth.c
@@ -540,7 +540,7 @@ static ssize_t eth_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
         return size;
 }
 
-static int eth_tx_push(void *opaque, unsigned char *buf, int len)
+static int eth_tx_push(void *opaque, unsigned char *buf, int len, bool eop)
 {
 	struct fs_eth *eth = opaque;
 
commit 9f6113c7e65a98a88bb95ff5fd8679fbb28f18d6
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Tue Jan 10 10:33:37 2012 +0100

    microblaze: Break the tb at memory barriers
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 180ac84..96ce2ec 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1249,12 +1249,22 @@ static void dec_bcc(DisasContext *dc)
 
 static void dec_br(DisasContext *dc)
 {
-    unsigned int dslot, link, abs;
+    unsigned int dslot, link, abs, mbar;
     int mem_index = cpu_mmu_index(dc->env);
 
     dslot = dc->ir & (1 << 20);
     abs = dc->ir & (1 << 19);
     link = dc->ir & (1 << 18);
+
+    /* Memory barrier.  */
+    mbar = (dc->ir >> 16) & 31;
+    if (mbar == 2 && dc->imm == 4) {
+        LOG_DIS("mbar %d\n", dc->rd);
+        /* Break the TB.  */
+        dc->cpustate_changed = 1;
+        return;
+    }
+
     LOG_DIS("br%s%s%s%s imm=%x\n",
              abs ? "a" : "", link ? "l" : "",
              dc->type_b ? "i" : "", dslot ? "d" : "",
commit 5818dee572deabb1e75a0901b43caa81fb30f419
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Tue Jan 10 10:27:11 2012 +0100

    microblaze: Emulate the hw stackprotector
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 1a307e3..3ecaeee 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -93,6 +93,7 @@ struct CPUMBState;
 #define          ESR_EC_DIVZERO         5
 #define          ESR_EC_FPU             6
 #define          ESR_EC_PRIVINSN        7
+#define          ESR_EC_STACKPROT       7  /* Same as PRIVINSN.  */
 #define          ESR_EC_DATA_STORAGE    8
 #define          ESR_EC_INSN_STORAGE    9
 #define          ESR_EC_DATA_TLB        10
@@ -235,6 +236,8 @@ typedef struct CPUMBState {
     uint32_t regs[33];
     uint32_t sregs[24];
     float_status fp_status;
+    /* Stack protectors. Yes, it's a hw feature.  */
+    uint32_t slr, shr;
 
     /* Internal flags.  */
 #define IMM_FLAG	4
diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h
index a8d75c0..9dcfb0f 100644
--- a/target-microblaze/helper.h
+++ b/target-microblaze/helper.h
@@ -33,6 +33,7 @@ DEF_HELPER_2(mmu_write, void, i32, i32)
 #endif
 
 DEF_HELPER_4(memalign, void, i32, i32, i32, i32)
+DEF_HELPER_1(stackprot, void, i32)
 
 DEF_HELPER_2(get, i32, i32, i32)
 DEF_HELPER_3(put, void, i32, i32, i32)
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index d99c564..7232c71 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -483,6 +483,17 @@ void helper_memalign(uint32_t addr, uint32_t dr, uint32_t wr, uint32_t mask)
     }
 }
 
+void helper_stackprot(uint32_t addr)
+{
+    if (addr < env->slr || addr > env->shr) {
+            qemu_log("Stack protector violation at %x %x %x\n",
+                     addr, env->slr, env->shr);
+            env->sregs[SR_EAR] = addr;
+            env->sregs[SR_ESR] = ESR_EC_STACKPROT;
+            helper_raise_exception(EXCP_HW_EXCP);
+    }
+}
+
 #if !defined(CONFIG_USER_ONLY)
 /* Writes/reads to the MMU's special regs end up here.  */
 uint32_t helper_mmu_read(uint32_t rn)
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index f4e6f30..180ac84 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -526,6 +526,12 @@ static void dec_msr(DisasContext *dc)
             case 0x7:
                 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));
+                break;
+            case 0x802:
+                tcg_gen_st_tl(cpu_R[dc->ra], cpu_env, offsetof(CPUState, shr));
+                break;
             default:
                 cpu_abort(dc->env, "unknown mts reg %x\n", sr);
                 break;
@@ -552,6 +558,12 @@ static void dec_msr(DisasContext *dc)
             case 0xb:
                 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));
+                break;
+            case 0x802:
+                tcg_gen_ld_tl(cpu_R[dc->rd], cpu_env, offsetof(CPUState, shr));
+                break;
             case 0x2000:
             case 0x2001:
             case 0x2002:
@@ -864,6 +876,13 @@ static inline void gen_load(DisasContext *dc, TCGv dst, TCGv addr,
 static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
 {
     unsigned int extimm = dc->tb_flags & IMM_FLAG;
+    /* Should be set to one if r1 is used by loadstores.  */
+    int stackprot = 0;
+
+    /* All load/stores use ra.  */
+    if (dc->ra == 1) {
+        stackprot = 1;
+    }
 
     /* Treat the common cases first.  */
     if (!dc->type_b) {
@@ -874,8 +893,16 @@ static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
             return &cpu_R[dc->ra];
         }
 
+        if (dc->rb == 1) {
+            stackprot = 1;
+        }
+
         *t = tcg_temp_new();
         tcg_gen_add_tl(*t, cpu_R[dc->ra], cpu_R[dc->rb]);
+
+        if (stackprot) {
+            gen_helper_stackprot(*t);
+        }
         return t;
     }
     /* Immediate.  */
@@ -891,6 +918,9 @@ static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
         tcg_gen_add_tl(*t, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
     }
 
+    if (stackprot) {
+        gen_helper_stackprot(*t);
+    }
     return t;
 }
 
@@ -1917,6 +1947,9 @@ void cpu_reset (CPUState *env)
     memset(env, 0, offsetof(CPUMBState, breakpoints));
     tlb_flush(env, 1);
 
+    /* Disable stack protector.  */
+    env->shr = ~0;
+
     env->pvr.regs[0] = PVR0_PVR_FULL_MASK \
                        | PVR0_USE_BARREL_MASK \
                        | PVR0_USE_DIV_MASK \
commit 48b5e96f0f7006f46a7d6c6f0934a6acdda22e3b
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Tue Jan 10 10:17:21 2012 +0100

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

diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h
index b92aa34..a8d75c0 100644
--- a/target-microblaze/helper.h
+++ b/target-microblaze/helper.h
@@ -5,6 +5,7 @@ DEF_HELPER_0(debug, void)
 DEF_HELPER_FLAGS_3(carry, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32)
 DEF_HELPER_2(cmp, i32, i32, i32)
 DEF_HELPER_2(cmpu, i32, i32, i32)
+DEF_HELPER_FLAGS_1(clz, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32)
 
 DEF_HELPER_2(divs, i32, i32, i32)
 DEF_HELPER_2(divu, i32, i32, i32)
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index 7433cec..d99c564 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -165,6 +165,11 @@ uint32_t helper_cmpu(uint32_t a, uint32_t b)
     return t;
 }
 
+uint32_t helper_clz(uint32_t t0)
+{
+    return clz32(t0);
+}
+
 uint32_t helper_carry(uint32_t a, uint32_t b, uint32_t cf)
 {
     uint32_t ncf;
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index d7f513d..f4e6f30 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -809,6 +809,17 @@ static void dec_bit(DisasContext *dc)
                 return;
             }
             break;
+        case 0xe0:
+            if ((dc->tb_flags & MSR_EE_FLAG)
+                && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+                && !((dc->env->pvr.regs[2] & PVR2_USE_PCMP_INSTR))) {
+                tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
+                t_gen_raise_exception(dc, EXCP_HW_EXCP);
+            }
+            if (dc->env->pvr.regs[2] & PVR2_USE_PCMP_INSTR) {
+                gen_helper_clz(cpu_R[dc->rd], cpu_R[dc->ra]);
+            }
+            break;
         default:
             cpu_abort(dc->env, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
                      dc->pc, op, dc->rd, dc->ra, dc->rb);
commit 2355c16e74ffa4d14e7fc2b4a23b055565ac0221
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Jan 7 15:20:12 2012 +0100

    target-i386: fix SSE rounding and flush to zero
    
    SSE rounding and flush to zero control has never been implemented. However
    given that softfloat-native was using a single state for FPU and SSE and
    given that glibc is setting both FPU and SSE state in fesetround(), this
    was working correctly up to the switch to softfloat.
    
    Fix that by adding an update_sse_status() function similar to
    update_fpu_status(), and callin git on write to mxcsr.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/helper.h b/target-i386/helper.h
index 6b518ad..761954e 100644
--- a/target-i386/helper.h
+++ b/target-i386/helper.h
@@ -197,6 +197,7 @@ DEF_HELPER_2(lzcnt, tl, tl, int)
 
 /* MMX/SSE */
 
+DEF_HELPER_1(ldmxcsr, void, i32)
 DEF_HELPER_0(enter_mmx, void)
 DEF_HELPER_0(emms, void)
 DEF_HELPER_2(movq, void, ptr, ptr)
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index c89e4a4..2aea71b 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -52,11 +52,11 @@ static inline target_long lshift(target_long x, int n)
     }
 }
 
-#define RC_MASK         0xc00
-#define RC_NEAR         0x000
-#define RC_DOWN         0x400
-#define RC_UP           0x800
-#define RC_CHOP         0xc00
+#define FPU_RC_MASK         0xc00
+#define FPU_RC_NEAR         0x000
+#define FPU_RC_DOWN         0x400
+#define FPU_RC_UP           0x800
+#define FPU_RC_CHOP         0xc00
 
 #define MAXTAN 9223372036854775808.0
 
@@ -4024,18 +4024,18 @@ static void update_fp_status(void)
     int rnd_type;
 
     /* set rounding mode */
-    switch(env->fpuc & RC_MASK) {
+    switch(env->fpuc & FPU_RC_MASK) {
     default:
-    case RC_NEAR:
+    case FPU_RC_NEAR:
         rnd_type = float_round_nearest_even;
         break;
-    case RC_DOWN:
+    case FPU_RC_DOWN:
         rnd_type = float_round_down;
         break;
-    case RC_UP:
+    case FPU_RC_UP:
         rnd_type = float_round_up;
         break;
-    case RC_CHOP:
+    case FPU_RC_CHOP:
         rnd_type = float_round_to_zero;
         break;
     }
@@ -5629,6 +5629,50 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
 
 /* MMX/SSE */
 /* XXX: optimize by storing fptt and fptags in the static cpu state */
+
+#define SSE_DAZ             0x0040
+#define SSE_RC_MASK         0x6000
+#define SSE_RC_NEAR         0x0000
+#define SSE_RC_DOWN         0x2000
+#define SSE_RC_UP           0x4000
+#define SSE_RC_CHOP         0x6000
+#define SSE_FZ              0x8000
+
+static void update_sse_status(void)
+{
+    int rnd_type;
+
+    /* set rounding mode */
+    switch(env->mxcsr & SSE_RC_MASK) {
+    default:
+    case SSE_RC_NEAR:
+        rnd_type = float_round_nearest_even;
+        break;
+    case SSE_RC_DOWN:
+        rnd_type = float_round_down;
+        break;
+    case SSE_RC_UP:
+        rnd_type = float_round_up;
+        break;
+    case SSE_RC_CHOP:
+        rnd_type = float_round_to_zero;
+        break;
+    }
+    set_float_rounding_mode(rnd_type, &env->sse_status);
+
+    /* set denormals are zero */
+    set_flush_inputs_to_zero((env->mxcsr & SSE_DAZ) ? 1 : 0, &env->sse_status);
+
+    /* set flush to zero */
+    set_flush_to_zero((env->mxcsr & SSE_FZ) ? 1 : 0, &env->fp_status);
+}
+
+void helper_ldmxcsr(uint32_t val)
+{
+    env->mxcsr = val;
+    update_sse_status();
+}
+
 void helper_enter_mmx(void)
 {
     env->fpstt = 0;
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 8321bf3..b9839c5 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7544,7 +7544,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
             if (op == 2) {
                 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
-                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
+                gen_helper_ldmxcsr(cpu_T[0]);
             } else {
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
                 gen_op_st_T0_A0(OT_LONG + s->mem_index);
commit 170d5b4bb9f8382bd98dde09d969d2e85d83db06
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Jan 7 15:20:12 2012 +0100

    target-i386: fix dpps and dppd SSE2 instructions
    
    The helpers implemented dpps and dppd SSE instructions are not passing
    the correct argument types to the softfloat functions. While they do
    work anyway providing a correct behaviour, this patch fixes that.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 6a77295..0d33ca1 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -1775,44 +1775,44 @@ SSE_HELPER_I(helper_pblendw, W, 8, FBLENDP)
 
 void glue(helper_dpps, SUFFIX) (Reg *d, Reg *s, uint32_t mask)
 {
-    float32 iresult = 0 /*float32_zero*/;
+    float32 iresult = float32_zero;
 
     if (mask & (1 << 4))
         iresult = float32_add(iresult,
-                        float32_mul(d->L(0), s->L(0), &env->sse_status),
+                        float32_mul(d->XMM_S(0), s->XMM_S(0), &env->sse_status),
                         &env->sse_status);
     if (mask & (1 << 5))
         iresult = float32_add(iresult,
-                        float32_mul(d->L(1), s->L(1), &env->sse_status),
+                        float32_mul(d->XMM_S(1), s->XMM_S(1), &env->sse_status),
                         &env->sse_status);
     if (mask & (1 << 6))
         iresult = float32_add(iresult,
-                        float32_mul(d->L(2), s->L(2), &env->sse_status),
+                        float32_mul(d->XMM_S(2), s->XMM_S(2), &env->sse_status),
                         &env->sse_status);
     if (mask & (1 << 7))
         iresult = float32_add(iresult,
-                        float32_mul(d->L(3), s->L(3), &env->sse_status),
+                        float32_mul(d->XMM_S(3), s->XMM_S(3), &env->sse_status),
                         &env->sse_status);
-    d->L(0) = (mask & (1 << 0)) ? iresult : 0 /*float32_zero*/;
-    d->L(1) = (mask & (1 << 1)) ? iresult : 0 /*float32_zero*/;
-    d->L(2) = (mask & (1 << 2)) ? iresult : 0 /*float32_zero*/;
-    d->L(3) = (mask & (1 << 3)) ? iresult : 0 /*float32_zero*/;
+    d->XMM_S(0) = (mask & (1 << 0)) ? iresult : float32_zero;
+    d->XMM_S(1) = (mask & (1 << 1)) ? iresult : float32_zero;
+    d->XMM_S(2) = (mask & (1 << 2)) ? iresult : float32_zero;
+    d->XMM_S(3) = (mask & (1 << 3)) ? iresult : float32_zero;
 }
 
 void glue(helper_dppd, SUFFIX) (Reg *d, Reg *s, uint32_t mask)
 {
-    float64 iresult = 0 /*float64_zero*/;
+    float64 iresult = float64_zero;
 
     if (mask & (1 << 4))
         iresult = float64_add(iresult,
-                        float64_mul(d->Q(0), s->Q(0), &env->sse_status),
+                        float64_mul(d->XMM_D(0), s->XMM_D(0), &env->sse_status),
                         &env->sse_status);
     if (mask & (1 << 5))
         iresult = float64_add(iresult,
-                        float64_mul(d->Q(1), s->Q(1), &env->sse_status),
+                        float64_mul(d->XMM_D(1), s->XMM_D(1), &env->sse_status),
                         &env->sse_status);
-    d->Q(0) = (mask & (1 << 0)) ? iresult : 0 /*float64_zero*/;
-    d->Q(1) = (mask & (1 << 1)) ? iresult : 0 /*float64_zero*/;
+    d->XMM_D(0) = (mask & (1 << 0)) ? iresult : float64_zero;
+    d->XMM_D(1) = (mask & (1 << 1)) ? iresult : float64_zero;
 }
 
 void glue(helper_mpsadbw, SUFFIX) (Reg *d, Reg *s, uint32_t offset)
commit adc7166611ed7240434b60b915f4c116c4c70820
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Jan 7 15:20:11 2012 +0100

    target-i386: fix round{pd,ps,sd,ss} SSE2 instructions
    
    roundps and roundss SSE2 instructions have been broken when switching
    target-i386 to softfloat. They use float64_round_to_int to convert a
    float32, and while the implicit conversion from float32 to float64 was
    correct for softfloat-native, it is not for pure softfloat. Fix that by
    using the correct registers and correct functions.
    
    Also fix roundpd and roundsd implementation at the same time, even if
    these functions are behaving correctly.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 8ed231d..6a77295 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -1653,10 +1653,10 @@ void glue(helper_roundps, SUFFIX) (Reg *d, Reg *s, uint32_t mode)
             break;
         }
 
-    d->L(0) = float64_round_to_int(s->L(0), &env->sse_status);
-    d->L(1) = float64_round_to_int(s->L(1), &env->sse_status);
-    d->L(2) = float64_round_to_int(s->L(2), &env->sse_status);
-    d->L(3) = float64_round_to_int(s->L(3), &env->sse_status);
+    d->XMM_S(0) = float32_round_to_int(s->XMM_S(0), &env->sse_status);
+    d->XMM_S(1) = float32_round_to_int(s->XMM_S(1), &env->sse_status);
+    d->XMM_S(2) = float32_round_to_int(s->XMM_S(2), &env->sse_status);
+    d->XMM_S(3) = float32_round_to_int(s->XMM_S(3), &env->sse_status);
 
 #if 0 /* TODO */
     if (mode & (1 << 3))
@@ -1689,8 +1689,8 @@ void glue(helper_roundpd, SUFFIX) (Reg *d, Reg *s, uint32_t mode)
             break;
         }
 
-    d->Q(0) = float64_round_to_int(s->Q(0), &env->sse_status);
-    d->Q(1) = float64_round_to_int(s->Q(1), &env->sse_status);
+    d->XMM_D(0) = float64_round_to_int(s->XMM_D(0), &env->sse_status);
+    d->XMM_D(1) = float64_round_to_int(s->XMM_D(1), &env->sse_status);
 
 #if 0 /* TODO */
     if (mode & (1 << 3))
@@ -1723,7 +1723,7 @@ void glue(helper_roundss, SUFFIX) (Reg *d, Reg *s, uint32_t mode)
             break;
         }
 
-    d->L(0) = float64_round_to_int(s->L(0), &env->sse_status);
+    d->XMM_S(0) = float32_round_to_int(s->XMM_S(0), &env->sse_status);
 
 #if 0 /* TODO */
     if (mode & (1 << 3))
@@ -1756,7 +1756,7 @@ void glue(helper_roundsd, SUFFIX) (Reg *d, Reg *s, uint32_t mode)
             break;
         }
 
-    d->Q(0) = float64_round_to_int(s->Q(0), &env->sse_status);
+    d->XMM_D(0) = float64_round_to_int(s->XMM_D(0), &env->sse_status);
 
 #if 0 /* TODO */
     if (mode & (1 << 3))
commit a4d1f142542935b90d2eb30f3aead4edcf455fe6
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Jan 7 15:20:11 2012 +0100

    target-i386: fix {min,max}{pd,ps,sd,ss} SSE2 instructions
    
    minpd, minps, minsd, minss and maxpd, maxps, maxsd, maxss SSE2
    instructions have been broken when switching target-i386 to softfloat.
    It's not possible to use comparison instructions on float types anymore
    to softfloat, so use the floatXX_lt function instead, as the
    float_XX_min and float_XX_max functions can't be used due to the Intel
    specific behaviour.
    
    As it implements the correct NaNs behaviour, let's remove the
    corresponding entry from the TODO.
    
    It fixes GDM screen display on Debian Lenny.
    
    Thanks to Peter Maydell and Jason Wessel for their analysis of the
    problem.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/TODO b/target-i386/TODO
index c8ada07..a8d69cf 100644
--- a/target-i386/TODO
+++ b/target-i386/TODO
@@ -15,7 +15,6 @@ Correctness issues:
 - DRx register support
 - CR0.AC emulation
 - SSE alignment checks
-- fix SSE min/max with nans
 
 Optimizations/Features:
 
diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 47dde78..8ed231d 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -584,10 +584,15 @@ void helper_ ## name ## sd (Reg *d, Reg *s)\
 #define FPU_SUB(size, a, b) float ## size ## _sub(a, b, &env->sse_status)
 #define FPU_MUL(size, a, b) float ## size ## _mul(a, b, &env->sse_status)
 #define FPU_DIV(size, a, b) float ## size ## _div(a, b, &env->sse_status)
-#define FPU_MIN(size, a, b) (a) < (b) ? (a) : (b)
-#define FPU_MAX(size, a, b) (a) > (b) ? (a) : (b)
 #define FPU_SQRT(size, a, b) float ## size ## _sqrt(b, &env->sse_status)
 
+/* Note that the choice of comparison op here is important to get the
+ * special cases right: for min and max Intel specifies that (-0,0),
+ * (NaN, anything) and (anything, NaN) return the second argument.
+ */
+#define FPU_MIN(size, a, b) float ## size ## _lt(a, b, &env->sse_status) ? (a) : (b)
+#define FPU_MAX(size, a, b) float ## size ## _lt(b, a, &env->sse_status) ? (a) : (b)
+
 SSE_HELPER_S(add, FPU_ADD)
 SSE_HELPER_S(sub, FPU_SUB)
 SSE_HELPER_S(mul, FPU_MUL)
commit 9841aee16f1e68f5a9063589c898c40b44473add
Author: Stefan Weil <sw at weilnetz.de>
Date:   Mon Jan 9 19:32:04 2012 +0100

    wm8750: Fix calculation of number of array elements
    
    Coverity says that the division by sizeof(*s->rate) might be wrong.
    I think that coverity is right.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/wm8750.c b/hw/wm8750.c
index 39383f4..9fbdf3d 100644
--- a/hw/wm8750.c
+++ b/hw/wm8750.c
@@ -563,7 +563,7 @@ static void wm8750_pre_save(void *opaque)
 {
     WM8750State *s = opaque;
 
-    s->rate_vmstate = (s->rate - wm_rate_table) / sizeof(*s->rate);
+    s->rate_vmstate = s->rate - wm_rate_table;
 }
 
 static int wm8750_post_load(void *opaque, int version_id)
commit c7c530cd3e23219a9be10323ba7876f68d54c107
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Jan 5 15:39:39 2012 +0100

    elf: Improve symbol lookup (optimize, fix for bsd-user)
    
    Coverity complained about local variable key which was only partially
    initiated. Only key.st_value was set. As this was also the only part
    of key which was used in function symfind, the code could be optimized
    by directly passing a pointer to orig_addr.
    
    In bsd-user/elfload.c, fix ec822001a2f26eef8701194714f6482b6d852de2
    was missing. This was a simple replacement of > by >= in symfind, so
    I fixed it here without creating an additional patch.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 1288884..55b2136 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -993,12 +993,12 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 
 static int symfind(const void *s0, const void *s1)
 {
-    struct elf_sym *key = (struct elf_sym *)s0;
+    target_ulong addr = *(target_ulong *)s0;
     struct elf_sym *sym = (struct elf_sym *)s1;
     int result = 0;
-    if (key->st_value < sym->st_value) {
+    if (addr < sym->st_value) {
         result = -1;
-    } else if (key->st_value > sym->st_value + sym->st_size) {
+    } else if (addr >= sym->st_value + sym->st_size) {
         result = 1;
     }
     return result;
@@ -1013,12 +1013,9 @@ static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
 #endif
 
     // binary search
-    struct elf_sym key;
     struct elf_sym *sym;
 
-    key.st_value = orig_addr;
-
-    sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), symfind);
+    sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms), symfind);
     if (sym != NULL) {
         return s->disas_strtab + sym->st_name;
     }
diff --git a/hw/elf_ops.h b/hw/elf_ops.h
index 6af357f..fa65ce2 100644
--- a/hw/elf_ops.h
+++ b/hw/elf_ops.h
@@ -62,12 +62,12 @@ static struct elf_shdr *glue(find_section, SZ)(struct elf_shdr *shdr_table,
 
 static int glue(symfind, SZ)(const void *s0, const void *s1)
 {
-    struct elf_sym *key = (struct elf_sym *)s0;
+    target_phys_addr_t addr = *(target_phys_addr_t *)s0;
     struct elf_sym *sym = (struct elf_sym *)s1;
     int result = 0;
-    if (key->st_value < sym->st_value) {
+    if (addr < sym->st_value) {
         result = -1;
-    } else if (key->st_value >= sym->st_value + sym->st_size) {
+    } else if (addr >= sym->st_value + sym->st_size) {
         result = 1;
     }
     return result;
@@ -77,12 +77,10 @@ static const char *glue(lookup_symbol, SZ)(struct syminfo *s,
                                            target_phys_addr_t orig_addr)
 {
     struct elf_sym *syms = glue(s->disas_symtab.elf, SZ);
-    struct elf_sym key;
     struct elf_sym *sym;
 
-    key.st_value = orig_addr;
-
-    sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), glue(symfind, SZ));
+    sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms),
+                  glue(symfind, SZ));
     if (sym != NULL) {
         return s->disas_strtab + sym->st_name;
     }
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index ea61d0d..845be8b 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1683,12 +1683,12 @@ static void load_elf_interp(const char *filename, struct image_info *info,
 
 static int symfind(const void *s0, const void *s1)
 {
-    struct elf_sym *key = (struct elf_sym *)s0;
+    target_ulong addr = *(target_ulong *)s0;
     struct elf_sym *sym = (struct elf_sym *)s1;
     int result = 0;
-    if (key->st_value < sym->st_value) {
+    if (addr < sym->st_value) {
         result = -1;
-    } else if (key->st_value >= sym->st_value + sym->st_size) {
+    } else if (addr >= sym->st_value + sym->st_size) {
         result = 1;
     }
     return result;
@@ -1703,12 +1703,9 @@ static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
 #endif
 
     // binary search
-    struct elf_sym key;
     struct elf_sym *sym;
 
-    key.st_value = orig_addr;
-
-    sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), symfind);
+    sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms), symfind);
     if (sym != NULL) {
         return s->disas_strtab + sym->st_name;
     }
commit 563c2bf35cf4a20b504dd371c395d987f67e16d4
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jan 6 18:58:28 2012 +0000

    hw/integratorcp: Simplify flash remap code
    
    Use the new memory mutator API to simplify the flash remap code;
    this allows us to drop the flash_mapped flag.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index d9d8da3..e5712fc 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -21,7 +21,6 @@ typedef struct {
     MemoryRegion iomem;
     uint32_t memsz;
     MemoryRegion flash;
-    bool flash_mapped;
     uint32_t cm_osc;
     uint32_t cm_ctrl;
     uint32_t cm_lock;
@@ -110,20 +109,12 @@ static uint64_t integratorcm_read(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static void integratorcm_do_remap(integratorcm_state *s, int flash)
+static void integratorcm_do_remap(integratorcm_state *s)
 {
-    if (!flash) {
-        if (s->flash_mapped) {
-            sysbus_del_memory(&s->busdev, &s->flash);
-            s->flash_mapped = false;
-        }
-    } else {
-        if (!s->flash_mapped) {
-            sysbus_add_memory_overlap(&s->busdev, 0, &s->flash, 1);
-            s->flash_mapped = true;
-        }
-    }
-    //??? tlb_flush (cpu_single_env, 1);
+    /* Sync memory region state with CM_CTRL REMAP bit:
+     * bit 0 => flash at address 0; bit 1 => RAM
+     */
+    memory_region_set_enabled(&s->flash, !(s->cm_ctrl & 4));
 }
 
 static void integratorcm_set_ctrl(integratorcm_state *s, uint32_t value)
@@ -131,9 +122,6 @@ static void integratorcm_set_ctrl(integratorcm_state *s, uint32_t value)
     if (value & 8) {
         qemu_system_reset_request();
     }
-    if ((s->cm_ctrl ^ value) & 4) {
-        integratorcm_do_remap(s, (value & 4) == 0);
-    }
     if ((s->cm_ctrl ^ value) & 1) {
         /* (value & 1) != 0 means the green "MISC LED" is lit.
          * We don't have any nice place to display LEDs. printf is a bad
@@ -143,6 +131,7 @@ static void integratorcm_set_ctrl(integratorcm_state *s, uint32_t value)
     }
     /* Note that the RESET bit [3] always reads as zero */
     s->cm_ctrl = (s->cm_ctrl & ~5) | (value & 5);
+    integratorcm_do_remap(s);
 }
 
 static void integratorcm_update(integratorcm_state *s)
@@ -263,13 +252,12 @@ static int integratorcm_init(SysBusDevice *dev)
     s->cm_init = 0x00000112;
     memory_region_init_ram(&s->flash, "integrator.flash", 0x100000);
     vmstate_register_ram_global(&s->flash);
-    s->flash_mapped = false;
 
     memory_region_init_io(&s->iomem, &integratorcm_ops, s,
                           "integratorcm", 0x00800000);
     sysbus_init_mmio(dev, &s->iomem);
 
-    integratorcm_do_remap(s, 1);
+    integratorcm_do_remap(s);
     /* ??? Save/restore.  */
     return 0;
 }
commit 4753dea8c1311d05781cb66c45e540f94cdabd54
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jan 6 18:58:27 2012 +0000

    hw/integratorcp: Fix sense of REMAP bit
    
    Fix the sense of the REMAP bit: 0 should mean "map flash",
    1 should mean "map RAM".
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index c8f3955..d9d8da3 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -112,7 +112,7 @@ static uint64_t integratorcm_read(void *opaque, target_phys_addr_t offset,
 
 static void integratorcm_do_remap(integratorcm_state *s, int flash)
 {
-    if (flash) {
+    if (!flash) {
         if (s->flash_mapped) {
             sysbus_del_memory(&s->busdev, &s->flash);
             s->flash_mapped = false;
commit 14763ec87340322eba5fe4be35a2c8790c0d1b94
Merge: 665a04a... 93116ac...
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Jan 10 18:24:11 2012 +0100

    Merge branch 's390-next' of git://repo.or.cz/qemu/agraf
    
    * 's390-next' of git://repo.or.cz/qemu/agraf:
      s390: fix cpu hotplug / cpu activity on interrupts
      s390x: add TR function for EXECUTE
      Expose drive_add on all architectures
      Add generic drive hotplugging
      Compile device-hotplug on all targets
      [S390] Add hotplug support

commit 665a04ae1cbfa8004a38cf0fe99ba799c978a1fe
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Dec 12 22:36:01 2011 +0100

    PPC: Fix linker scripts on ppc hosts
    
    When compiling qemu statically with multilib on PPC, we hit the
    same issue that commit 845f2c2812d9ed24b36c02a3d06ee83aeafe8b49
    is fixing. Do the same here.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/ppc.ld b/ppc.ld
index 69aa3f2..2a0dcad 100644
--- a/ppc.ld
+++ b/ppc.ld
@@ -49,8 +49,20 @@ SECTIONS
   .rela.sbss2     : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) }
   .rel.bss        : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
   .rela.bss       : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
-  .rel.plt        : { *(.rel.plt) }
-  .rela.plt       : { *(.rela.plt) }
+  .rel.plt      :
+  {
+    *(.rel.plt)
+    PROVIDE (__rel_iplt_start = .);
+    *(.rel.iplt)
+    PROVIDE (__rel_iplt_end = .);
+  }
+  .rela.plt       :
+  {
+    *(.rela.plt)
+    PROVIDE (__rela_iplt_start = .);
+    *(.rela.iplt)
+    PROVIDE (__rela_iplt_end = .);
+  }
   .init           :
   {
     KEEP (*(.init))
diff --git a/ppc64.ld b/ppc64.ld
index 0a7c0dd..e2dafa0 100644
--- a/ppc64.ld
+++ b/ppc64.ld
@@ -54,8 +54,20 @@ SECTIONS
       *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
       *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
     }
-  .rel.plt        : { *(.rel.plt) }
-  .rela.plt       : { *(.rela.plt) }
+  .rel.plt      :
+  {
+    *(.rel.plt)
+    PROVIDE (__rel_iplt_start = .);
+    *(.rel.iplt)
+    PROVIDE (__rel_iplt_end = .);
+  }
+  .rela.plt       :
+  {
+    *(.rela.plt)
+    PROVIDE (__rela_iplt_start = .);
+    *(.rela.iplt)
+    PROVIDE (__rela_iplt_end = .);
+  }
   .rela.tocbss	  : { *(.rela.tocbss) }
   .init           :
   {
commit 0cdb95549fedc73e13c147ab9dcabcc303426a07
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Jan 7 15:20:12 2012 +0100

    target-sh4: ignore ocbp and ocbwb instructions
    
    ocbp and ocbwb controls the writeback of a cache line to memory. They
    are supposed to do nothing in case of a cache miss. Given QEMU only
    partially emulate caches, it is safe to ignore these instructions.
    
    This fixes a kernel oops when trying to access an rtl8139 NIC with
    recent versions.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 2ecb236..aacf96d 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -1652,18 +1652,10 @@ static void _decode_opc(DisasContext * ctx)
 	}
 	return;
     case 0x00a3:		/* ocbp @Rn */
-	{
-	    TCGv dummy = tcg_temp_new();
-	    tcg_gen_qemu_ld32s(dummy, REG(B11_8), ctx->memidx);
-	    tcg_temp_free(dummy);
-	}
-	return;
     case 0x00b3:		/* ocbwb @Rn */
-	{
-	    TCGv dummy = tcg_temp_new();
-	    tcg_gen_qemu_ld32s(dummy, REG(B11_8), ctx->memidx);
-	    tcg_temp_free(dummy);
-	}
+        /* These instructions are supposed to do nothing in case of
+           a cache miss. Given that we only partially emulate caches
+           it is safe to simply ignore them. */
 	return;
     case 0x0083:		/* pref @Rn */
 	return;
commit 05b922dd0a1919c265361ca62902d6cdaea4cc36
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Dec 26 00:02:18 2011 +0000

    tcg/arm: Use r6 as TCG_AREG0 to avoid clash with Thumb framepointer
    
    On ARM, in Thumb mode r7 is used for the framepointer; this meant
    that we would fail to compile in debug mode because we were using r7
    for TCG_AREG0. Shift to r6 instead to avoid this clash.
    (Bug reported as LP:870990.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/dyngen-exec.h b/dyngen-exec.h
index 3544372..09be9ea 100644
--- a/dyngen-exec.h
+++ b/dyngen-exec.h
@@ -31,7 +31,7 @@
 #elif defined(_ARCH_PPC)
 #define AREG0 "r27"
 #elif defined(__arm__)
-#define AREG0 "r7"
+#define AREG0 "r6"
 #elif defined(__hppa__)
 #define AREG0 "r17"
 #elif defined(__mips__)
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 48586c3..0035b47 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -78,7 +78,7 @@ typedef enum {
 
 enum {
     /* Note: must be synced with dyngen-exec.h */
-    TCG_AREG0 = TCG_REG_R7,
+    TCG_AREG0 = TCG_REG_R6,
 };
 
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
commit 520a02f8b844152929817b686113aed27229d3a9
Author: Stefan Weil <sw at weilnetz.de>
Date:   Mon Jan 9 19:23:42 2012 +0100

    cris-dis: Clean memory allocation
    
    The old code used sizeof(const struct cris_opcode **) where it should
    have used sizeof(const struct cris_opcode *). As both sizes give the
    same value, the resulting binary was ok, but static code analyzers
    like coverity and clang complained.
    
    This is fixed here, and the code is also simplified by using g_new0.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/cris-dis.c b/cris-dis.c
index 5b8e90b..1d174ba 100644
--- a/cris-dis.c
+++ b/cris-dis.c
@@ -1396,34 +1396,12 @@ get_opcode_entry (unsigned int insn,
   /* Allocate and clear the opcode-table.  */
   if (opc_table == NULL)
     {
-      opc_table = g_malloc (65536 * sizeof (opc_table[0]));
-
-      memset (opc_table, 0, 65536 * sizeof (const struct cris_opcode *));
-
-      dip_prefixes
-	= g_malloc (65536 * sizeof (const struct cris_opcode **));
-
-      memset (dip_prefixes, 0, 65536 * sizeof (dip_prefixes[0]));
-
-      bdapq_m1_prefixes
-	= g_malloc (65536 * sizeof (const struct cris_opcode **));
-
-      memset (bdapq_m1_prefixes, 0, 65536 * sizeof (bdapq_m1_prefixes[0]));
-
-      bdapq_m2_prefixes
-	= g_malloc (65536 * sizeof (const struct cris_opcode **));
-
-      memset (bdapq_m2_prefixes, 0, 65536 * sizeof (bdapq_m2_prefixes[0]));
-
-      bdapq_m4_prefixes
-	= g_malloc (65536 * sizeof (const struct cris_opcode **));
-
-      memset (bdapq_m4_prefixes, 0, 65536 * sizeof (bdapq_m4_prefixes[0]));
-
-      rest_prefixes
-	= g_malloc (65536 * sizeof (const struct cris_opcode **));
-
-      memset (rest_prefixes, 0, 65536 * sizeof (rest_prefixes[0]));
+      opc_table = g_new0(const struct cris_opcode *, 65536);
+      dip_prefixes = g_new0(const struct cris_opcode *, 65536);
+      bdapq_m1_prefixes = g_new0(const struct cris_opcode *, 65536);
+      bdapq_m2_prefixes = g_new0(const struct cris_opcode *, 65536);
+      bdapq_m4_prefixes = g_new0(const struct cris_opcode *, 65536);
+      rest_prefixes = g_new0(const struct cris_opcode *, 65536);
     }
 
   /* Get the right table if this is a prefix.
commit cd9244e48a6643752fccecd344d85d1c4de5cbad
Merge: 1ddde08... c49450b...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Jan 9 08:54:04 2012 -0600

    Merge remote-tracking branch 'qemu-kvm/fix-vhost-after-memory-listener' into staging
    
    * qemu-kvm/fix-vhost-after-memory-listener:
      vhost: improve region filtering
      vhost: fix mem_sections memory corruption
      vhost: fix incorrect userspace address

commit c49450b98f7b9edd6690f34ae6ff15fe4a6131b9
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Jan 9 14:01:39 2012 +0200

    vhost: improve region filtering
    
    vhost memory management doesn't care about non-memory (e.g. PIO) or non-RAM
    regions.  Adjust the filtering to reflect that, and move it earlier so it
    applies to mem_sections too.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Acked-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/vhost.c b/hw/vhost.c
index d924fb0..19a7b5c 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -15,6 +15,7 @@
 #include "hw/hw.h"
 #include "range.h"
 #include <linux/vhost.h>
+#include "exec-memory.h"
 
 static void vhost_dev_sync_region(struct vhost_dev *dev,
                                   MemoryRegionSection *section,
@@ -365,10 +366,6 @@ static void vhost_set_memory(MemoryListener *listener,
     int r;
     void *ram;
 
-    if (!memory_region_is_ram(section->mr)) {
-        return;
-    }
-
     dev->mem = g_realloc(dev->mem, s);
 
     if (log_dirty) {
@@ -430,12 +427,22 @@ static void vhost_set_memory(MemoryListener *listener,
     }
 }
 
+static bool vhost_section(MemoryRegionSection *section)
+{
+    return section->address_space == get_system_memory()
+        && memory_region_is_ram(section->mr);
+}
+
 static void vhost_region_add(MemoryListener *listener,
                              MemoryRegionSection *section)
 {
     struct vhost_dev *dev = container_of(listener, struct vhost_dev,
                                          memory_listener);
 
+    if (!vhost_section(section)) {
+        return;
+    }
+
     ++dev->n_mem_sections;
     dev->mem_sections = g_renew(MemoryRegionSection, dev->mem_sections,
                                 dev->n_mem_sections);
@@ -450,6 +457,10 @@ static void vhost_region_del(MemoryListener *listener,
                                          memory_listener);
     int i;
 
+    if (!vhost_section(section)) {
+        return;
+    }
+
     vhost_set_memory(listener, section, false);
     for (i = 0; i < dev->n_mem_sections; ++i) {
         if (dev->mem_sections[i].offset_within_address_space
commit 637f7a6a01e09bc39f7b3a24257a9cd6ea396ca0
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Jan 9 13:59:50 2012 +0200

    vhost: fix mem_sections memory corruption
    
    A memset() used to delete an entry in an array did not take into account
    the array element's size.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Acked-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/vhost.c b/hw/vhost.c
index 541c716..d924fb0 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -456,7 +456,7 @@ static void vhost_region_del(MemoryListener *listener,
             == section->offset_within_address_space) {
             --dev->n_mem_sections;
             memmove(&dev->mem_sections[i], &dev->mem_sections[i+1],
-                    dev->n_mem_sections - i);
+                    (dev->n_mem_sections - i) * sizeof(*dev->mem_sections));
             break;
         }
     }
commit d743c382861eaa1e13f503b05aba5a382a7e7f7c
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Jan 9 13:09:40 2012 +0200

    vhost: fix incorrect userspace address
    
    MemoryListener::region_add() gives us a slice of a MemoryRegion, not a
    region.  Adjust the userspace address to reflect that.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Acked-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/vhost.c b/hw/vhost.c
index cd56e75..541c716 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -378,7 +378,7 @@ static void vhost_set_memory(MemoryListener *listener,
     assert(size);
 
     /* Optimize no-change case. At least cirrus_vga does this a lot at this time. */
-    ram = memory_region_get_ram_ptr(section->mr);
+    ram = memory_region_get_ram_ptr(section->mr) + section->offset_within_region;
     if (add) {
         if (!vhost_dev_cmp_memory(dev, start_addr, size, (uintptr_t)ram)) {
             /* Region exists with same address. Nothing to do. */
commit 1ddde08780f6862a98505f9fb9ea10305638783f
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Jan 8 13:18:19 2012 +0200

    Fix vmstate_register_ram() for rom/device regions
    
    rom/device regions have a ram_addr that is composed of both an I/O handler
    (low bits) and RAM region (high bits); but qemu_ram_set_idstr() expects just
    a RAM region.  Mask the I/O handler to make it happy.
    
    Tested-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/savevm.c b/savevm.c
index 88c4bd8..80be1ff 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2284,7 +2284,7 @@ void do_info_snapshots(Monitor *mon)
 
 void vmstate_register_ram(MemoryRegion *mr, DeviceState *dev)
 {
-    qemu_ram_set_idstr(memory_region_get_ram_addr(mr),
+    qemu_ram_set_idstr(memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK,
                        memory_region_name(mr), dev);
 }
 
commit 1470a0cdca63d2592b3eab8fd22c9b18d38ce800
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Jan 7 09:45:15 2012 +0100

    memory: Fix adjust_endianness()
    
    Commit a621f38de85598a13d8d8524d1a94fc6a1818215 (Direct dispatch
    through MemoryRegion) moved byte swaps to a central function.
    
    Add a missing break, so that long-sized byte swaps don't abort.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/memory.c b/memory.c
index 5e55a90..5ab2112 100644
--- a/memory.c
+++ b/memory.c
@@ -942,6 +942,7 @@ static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size)
             break;
         case 4:
             *data = bswap32(*data);
+            break;
         default:
             abort();
         }
commit 2c3579ab07408b353fe7083bae9469e1485fc8fc
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Jan 7 09:45:14 2012 +0100

    memory: Fix memory_region_wrong_endianness()
    
    Since commit be675c972088eba210e18dc125613e9f205a6bfb (memory: move
    endianness compensation to memory core) it was checking for
    TARGET_BIG_ENDIAN instead of TARGET_WORDS_BIGENDIAN, thereby not
    swapping correctly for Big Endian targets.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/memory.c b/memory.c
index 394cbab..5e55a90 100644
--- a/memory.c
+++ b/memory.c
@@ -843,7 +843,7 @@ static void memory_region_destructor_rom_device(MemoryRegion *mr)
 
 static bool memory_region_wrong_endianness(MemoryRegion *mr)
 {
-#ifdef TARGET_BIG_ENDIAN
+#ifdef TARGET_WORDS_BIGENDIAN
     return mr->ops->endianness == DEVICE_LITTLE_ENDIAN;
 #else
     return mr->ops->endianness == DEVICE_BIG_ENDIAN;
commit 6148b23d69444a300710db0c53f6c53b7f3c8067
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Jan 5 12:30:31 2012 +0200

    kvm: fix build error in ppc kvm due to memory_region_init_ram_ptr() change
    
    Commit c5705a772 ("vmstate, memory: decouple vmstate from memory API") changed
    the signature of memory_region_init_ram_ptr() but did not update a caller in
    the ppc kvm module.  Fix.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 9b2e605..ce8ac5b 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -822,7 +822,8 @@ off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
     };
 
     rma_region = g_new(MemoryRegion, 1);
-    memory_region_init_ram_ptr(rma_region, NULL, name, size, rma);
+    memory_region_init_ram_ptr(rma_region, name, size, rma);
+    vmstate_register_ram_global(rma_region);
     memory_region_add_subregion(sysmem, 0, rma_region);
 
     return size;
commit e7f929028cc11a439ee7bbdf40724d87016361fa
Merge: 15f43cc... 7da362d...
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Jan 7 22:19:14 2012 +0100

    Merge branch 'target-arm.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm
    
    * 'target-arm.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm:
      arm: add dummy A9-specific cp15 registers
      target-arm: Ignore attempts to set invalid modes in CPSR
      target-arm: Don't use cpu_single_env in bank_number()

commit 15f43ccda1bd1353276c7239f8e371966dd656d9
Merge: c278086... f7aa558...
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Jan 7 22:01:57 2012 +0100

    Merge branch 'ppc-next' of git://repo.or.cz/qemu/agraf
    
    * 'ppc-next' of git://repo.or.cz/qemu/agraf:
      PPC: Add description for the Freescale e500mc core.
      pseries: Check for duplicate addresses on the spapr-vio bus
      pseries: Populate "/chosen/linux,stdout-path" in the FDT
      pseries: Add a routine to find a stable "default" vty and use it
      pseries: Emit device tree nodes in reg order
      pseries: FDT NUMA extensions to support multi-node guests
      pseries: Remove hcalls callback
      kvm-ppc: halt secondary cpus when guest reset
      console: Fix segfault on screendump without VGA adapter
      PPC: monitor: add ability to dump SLB entries

commit c27808657bd633fade6fe3e5f193504aab713b07
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Jan 4 22:50:09 2012 +0100

    sm501: Fix size of color_reg
    
    color_reg is expected to hold 32 bit values, so it was too small.
    
    This bug was reported by coverity:
    
    hw/sm501.c:624:
    result_independent_of_operands:
    color_reg >> 16 is 0 regardless of the values of its operands.
    This occurs as the bitwise first operand of '&'.
    
    Cc: Shin-ichiro Kawasaki <kawasaki at juno.dti.ne.jp>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/sm501.c b/hw/sm501.c
index 326531c..09c5894 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -593,7 +593,7 @@ static inline uint32_t get_hwc_x(SM501State *state, int crt)
  */
 static inline uint16_t get_hwc_color(SM501State *state, int crt, int index)
 {
-    uint16_t color_reg = 0;
+    uint32_t color_reg = 0;
     uint16_t color_565 = 0;
 
     if (index == 0) {
commit f840fa995f88bc2bea7311f003e8de5ceb8ab276
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Jan 5 13:11:48 2012 +0100

    target-sh4: Fix operands for fipr, ftrv instructions
    
    Coverity complained about right shifts of opcode (16, 18) which were
    larger than the size of opcode (16 bit).
    
    Using the correct shift values fixes this.
    
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index bad3577..2ecb236 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -1864,8 +1864,8 @@ static void _decode_opc(DisasContext * ctx)
         CHECK_FPU_ENABLED
         if ((ctx->fpscr & FPSCR_PR) == 0) {
             TCGv m, n;
-            m = tcg_const_i32((ctx->opcode >> 16) & 3);
-            n = tcg_const_i32((ctx->opcode >> 18) & 3);
+            m = tcg_const_i32((ctx->opcode >> 8) & 3);
+            n = tcg_const_i32((ctx->opcode >> 10) & 3);
             gen_helper_fipr(m, n);
             tcg_temp_free(m);
             tcg_temp_free(n);
@@ -1877,7 +1877,7 @@ static void _decode_opc(DisasContext * ctx)
         if ((ctx->opcode & 0x0300) == 0x0100 &&
             (ctx->fpscr & FPSCR_PR) == 0) {
             TCGv n;
-            n = tcg_const_i32((ctx->opcode >> 18) & 3);
+            n = tcg_const_i32((ctx->opcode >> 10) & 3);
             gen_helper_ftrv(n);
             tcg_temp_free(n);
             return;
commit e9b40fd34ceb23461083d505a444a389c094455b
Author: Stefan Weil <sw at weilnetz.de>
Date:   Tue Nov 29 06:34:48 2011 +0100

    malta: Fix regression (i8259 interrupts did not work)
    
    Commit 5632ae46d5bda798e971dae48ebb318ac2c3686a passes the address
    of i8259 to qemu_irq_proxy. i8259 is an auto variable with undefined
    value outside of mips_malta_init.
    
    This made the interrupt proxy unusable: either QEMU crashes, or
    the interrupt handler was not called.
    
    Ethernet for example no longer worked with MIPS Malta.
    
    v2:
    While v1 used a static variable for i8259, this patch introduces
    a qdev for the malta machine. i8259 is now part of the device status.
    This is a minimal qdev implementation to keep the patch small.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 6b72cf2..e625ec3 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -47,6 +47,7 @@
 #include "mc146818rtc.h"
 #include "blockdev.h"
 #include "exec-memory.h"
+#include "sysbus.h"             /* SysBusDevice */
 
 //#define DEBUG_BOARD_INIT
 
@@ -72,6 +73,11 @@ typedef struct {
     SerialState *uart;
 } MaltaFPGAState;
 
+typedef struct {
+    SysBusDevice busdev;
+    qemu_irq *i8259;
+} MaltaState;
+
 static ISADevice *pit;
 
 static struct _loaderparams {
@@ -776,7 +782,7 @@ void mips_malta_init (ram_addr_t ram_size,
     PCIBus *pci_bus;
     ISABus *isa_bus;
     CPUState *env;
-    qemu_irq *i8259 = NULL, *isa_irq;
+    qemu_irq *isa_irq;
     qemu_irq *cpu_exit_irq;
     int piix4_devfn;
     i2c_bus *smbus;
@@ -788,6 +794,11 @@ void mips_malta_init (ram_addr_t ram_size,
     int fl_sectors = 0;
     int be;
 
+    DeviceState *dev = qdev_create(NULL, "mips-malta");
+    MaltaState *s = DO_UPCAST(MaltaState, busdev.qdev, dev);
+
+    qdev_init_nofail(dev);
+
     /* Make sure the first 3 serial ports are associated with a device. */
     for(i = 0; i < 3; i++) {
         if (!serial_hds[i]) {
@@ -937,7 +948,7 @@ void mips_malta_init (ram_addr_t ram_size,
      * qemu_irq_proxy() adds an extra bit of indirection, allowing us
      * to resolve the isa_irq -> i8259 dependency after i8259 is initialized.
      */
-    isa_irq = qemu_irq_proxy(&i8259, 16);
+    isa_irq = qemu_irq_proxy(&s->i8259, 16);
 
     /* Northbridge */
     pci_bus = gt64120_register(isa_irq);
@@ -949,9 +960,9 @@ void mips_malta_init (ram_addr_t ram_size,
 
     /* Interrupt controller */
     /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
-    i8259 = i8259_init(isa_bus, env->irq[2]);
+    s->i8259 = i8259_init(isa_bus, env->irq[2]);
 
-    isa_bus_irqs(isa_bus, i8259);
+    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);
     smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
@@ -995,6 +1006,20 @@ void mips_malta_init (ram_addr_t ram_size,
     }
 }
 
+static int mips_malta_sysbus_device_init(SysBusDevice *sysbusdev)
+{
+    return 0;
+}
+
+static SysBusDeviceInfo mips_malta_device = {
+    .init = mips_malta_sysbus_device_init,
+    .qdev.name  = "mips-malta",
+    .qdev.size  = sizeof(MaltaState),
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
 static QEMUMachine mips_malta_machine = {
     .name = "malta",
     .desc = "MIPS Malta Core LV",
@@ -1003,9 +1028,15 @@ static QEMUMachine mips_malta_machine = {
     .is_default = 1,
 };
 
+static void mips_malta_device_init(void)
+{
+    sysbus_register_withprop(&mips_malta_device);
+}
+
 static void mips_malta_machine_init(void)
 {
     qemu_register_machine(&mips_malta_machine);
 }
 
+device_init(mips_malta_device_init);
 machine_init(mips_malta_machine_init);
commit a2e4d53ec5cc1983a615d87b251726f17358be9a
Merge: 2afee49... dc10e8b...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jan 6 12:51:21 2012 -0600

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging
    
    * stefanha/trivial-patches:
      qemu-nbd: drop loop which can never loop
      Make python mandatory
      net/socket.c: Fix fd leak in net_socket_listen_init() error paths
      gdbstub: Fix fd leak in gdbserver_open() error path
      configure: Fix test for supported host CPU type
      configure: CONFIG_QEMU_INTERP_PREFIX only for user mode
      scsi virtio-blk usb-msd: Clean up device init error messages
      Strip trailing '\n' from error_report()'s first argument (again)
      qemu-options.hx: fix tls-channel help text

commit 2afee49fc4a366ab740899ec9e79079ec335e0fb
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jan 6 18:47:21 2012 +0000

    virtio-9p-proxy: Fix typo causing compile failure on 32 bit hosts
    
    Fix a compile failure on 32 bit hosts (integer constant is too large
    for 'unsigned long' type) by correcting a typo where the mask used
    for filling in the second f_fsid word had too many 'F's in it.
    Also drop the 'L' suffix that allowed this typo to go undetected on
    64 bit hosts.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 44f5fc4..d5ad208 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -112,8 +112,8 @@ static void prstatfs_to_statfs(struct statfs *stfs, ProxyStatFS *prstfs)
     stfs->f_bavail = prstfs->f_bavail;
     stfs->f_files = prstfs->f_files;
     stfs->f_ffree = prstfs->f_ffree;
-    stfs->f_fsid.__val[0] = prstfs->f_fsid[0] & 0xFFFFFFFFUL;
-    stfs->f_fsid.__val[1] = prstfs->f_fsid[1] >> 32 & 0xFFFFFFFFFUL;
+    stfs->f_fsid.__val[0] = prstfs->f_fsid[0] & 0xFFFFFFFFU;
+    stfs->f_fsid.__val[1] = prstfs->f_fsid[1] >> 32 & 0xFFFFFFFFU;
     stfs->f_namelen = prstfs->f_namelen;
     stfs->f_frsize = prstfs->f_frsize;
 }
commit dc10e8b3c556b582eb7919c92d0997b5f9a9d136
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Thu Jan 5 13:16:07 2012 +0000

    qemu-nbd: drop loop which can never loop
    
    For some reason nbd_client_thread() has a do..while loop which can never
    loop, the condition is bogus because we would take a goto instead.  Drop
    the loop.
    
    Reported-by: Dr David Alan Gilbert <davidagilbert at uk.ibm.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/qemu-nbd.c b/qemu-nbd.c
index 155b058..eb61c33 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -202,12 +202,10 @@ static void *nbd_client_thread(void *arg)
     int ret;
     pthread_t show_parts_thread;
 
-    do {
-        sock = unix_socket_outgoing(sockpath);
-        if (sock == -1) {
-            goto out;
-        }
-    } while (sock == -1);
+    sock = unix_socket_outgoing(sockpath);
+    if (sock == -1) {
+        goto out;
+    }
 
     ret = nbd_receive_negotiate(sock, NULL, &nbdflags,
                                 &size, &blocksize);
commit 7a3fc891ae3256e4fbf03b6ab6d3ced0dfaaaa27
Author: Sebastian Herbszt <herbszt at gmx.de>
Date:   Sat Dec 31 12:14:47 2011 +0100

    Make python mandatory
    
    The QEMU build depends on Python so make it an explicit requirement.
    
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Sebastian Herbszt <herbszt at gmx.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/configure b/configure
index a1394eb..d88e3ea 100755
--- a/configure
+++ b/configure
@@ -1197,13 +1197,9 @@ if test "$solaris" = "yes" ; then
   fi
 fi
 
-if test "$guest_agent" != "no" ; then
-  if has $python; then
-    :
-  else
-    echo "Python not found. Use --python=/path/to/python"
-    exit 1
-  fi
+if ! has $python; then
+  echo "Python not found. Use --python=/path/to/python"
+  exit 1
 fi
 
 if test -z "$target_list" ; then
commit a46667ea29218565473e430ceae62e2838f6ce3f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sat Dec 24 23:47:11 2011 +0000

    net/socket.c: Fix fd leak in net_socket_listen_init() error paths
    
    Fix a leak of a file descriptor due to missing closesocket() calls
    in error paths in net_socket_listen_init().
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/net/socket.c b/net/socket.c
index aaf9be4..c9d70d3 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -427,12 +427,14 @@ static int net_socket_listen_init(VLANState *vlan,
     if (ret < 0) {
         perror("bind");
         g_free(s);
+        closesocket(fd);
         return -1;
     }
     ret = listen(fd, 0);
     if (ret < 0) {
         perror("listen");
         g_free(s);
+        closesocket(fd);
         return -1;
     }
     s->vlan = vlan;
commit bb16172c52ac18742f3df156912c169904e92147
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sat Dec 24 23:37:24 2011 +0000

    gdbstub: Fix fd leak in gdbserver_open() error path
    
    Fix a leak of a file descriptor in error exit paths in
    gdbserver_open().
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/gdbstub.c b/gdbstub.c
index a5806ef..7d470b6 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2762,11 +2762,13 @@ static int gdbserver_open(int port)
     ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
     if (ret < 0) {
         perror("bind");
+        close(fd);
         return -1;
     }
     ret = listen(fd, 0);
     if (ret < 0) {
         perror("listen");
+        close(fd);
         return -1;
     }
     return fd;
commit 359bc95d3e604e22fe07be62f5099148a2bb4e6f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sat Dec 24 13:07:25 2011 +0000

    configure: Fix test for supported host CPU type
    
    The test for whether the host CPU is supported had several problems:
     * the attempt to fall back to TCI was done as a duplicate
       test, very late (so "--cpu foo" would fail early but "--cpu unicore32"
       would fail late, differently, and after configure had already
       printed a lot of output)
     * a number of CPUs only supported as guests were included in the
       list of CPUs we would accept as valid hosts, which would result
       in a late compile failure on those systems rather than a
       configure failure or fallback to TCI
     * bailing out for an unsupported CPU happened before the main
       option parsing, so "configure --help" wouldn't work
    
    Fix these by folding the setting of ARCH into the first test for
    supported host CPU, removing spurious guest-only CPU names from it,
    and moving the "fall back to TCI" code earlier.
    
    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 af19391..a1394eb 100755
--- a/configure
+++ b/configure
@@ -300,8 +300,11 @@ else
   cpu=`uname -m`
 fi
 
+ARCH=
+# Normalise host CPU name and set ARCH.
+# Note that this case should only have supported host CPUs, not guests.
 case "$cpu" in
-  alpha|cris|ia64|lm32|m68k|microblaze|ppc|ppc64|sparc64|unicore32)
+  ia64|ppc|ppc64|s390|s390x|sparc64)
     cpu="$cpu"
   ;;
   i386|i486|i586|i686|i86pc|BePC)
@@ -319,20 +322,17 @@ case "$cpu" in
   mips*)
     cpu="mips"
   ;;
-  s390)
-    cpu="s390"
-  ;;
-  s390x)
-    cpu="s390x"
-  ;;
   sparc|sun4[cdmuv])
     cpu="sparc"
   ;;
   *)
-    echo "Unsupported CPU = $cpu"
-    exit 1
+    # This will result in either an error or falling back to TCI later
+    ARCH=unknown
   ;;
 esac
+if test -z "$ARCH"; then
+  ARCH="$cpu"
+fi
 
 # OS specific
 if check_define __linux__ ; then
@@ -1080,6 +1080,18 @@ echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
 fi
 
+# Now we have handled --enable-tcg-interpreter and know we're not just
+# printing the help message, bail out if the host CPU isn't supported.
+if test "$ARCH" = "unknown"; then
+    if test "$tcg_interpreter" = "yes" ; then
+        echo "Unsupported CPU = $cpu, will use TCG with TCI (experimental)"
+        ARCH=tci
+    else
+        echo "Unsupported CPU = $cpu, try --enable-tcg-interpreter"
+        exit 1
+    fi
+fi
+
 # check that the C compiler works.
 cat > $TMPC <<EOF
 int main(void) { return 0; }
@@ -2903,20 +2915,6 @@ echo "sysconfdir=$sysconfdir" >> $config_host_mak
 echo "docdir=$docdir" >> $config_host_mak
 echo "confdir=$confdir" >> $config_host_mak
 
-case "$cpu" in
-  i386|x86_64|alpha|arm|cris|hppa|ia64|lm32|m68k|microblaze|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64|unicore32)
-    ARCH=$cpu
-  ;;
-  *)
-    if test "$tcg_interpreter" = "yes" ; then
-        echo "Unsupported CPU = $cpu, will use TCG with TCI (experimental)"
-        ARCH=tci
-    else
-        echo "Unsupported CPU = $cpu, try --enable-tcg-interpreter"
-        exit 1
-    fi
-  ;;
-esac
 echo "ARCH=$ARCH" >> $config_host_mak
 if test "$debug_tcg" = "yes" ; then
   echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
commit a2c80be948eef747d91ad135574a3277698712b9
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Dec 22 11:26:10 2011 +0100

    configure: CONFIG_QEMU_INTERP_PREFIX only for user mode
    
    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 640e815..af19391 100755
--- a/configure
+++ b/configure
@@ -3395,7 +3395,6 @@ echo "# Automatically generated by configure - do not modify" > $config_target_m
 bflt="no"
 target_nptl="no"
 interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_arch2/g"`
-echo "CONFIG_QEMU_INTERP_PREFIX=\"$interp_prefix1\"" >> $config_target_mak
 gdb_xml_files=""
 target_short_alignment=2
 target_int_alignment=4
@@ -3601,6 +3600,7 @@ if test "$target_softmmu" = "yes" ; then
 fi
 if test "$target_user_only" = "yes" ; then
   echo "CONFIG_USER_ONLY=y" >> $config_target_mak
+  echo "CONFIG_QEMU_INTERP_PREFIX=\"$interp_prefix1\"" >> $config_target_mak
 fi
 if test "$target_linux_user" = "yes" ; then
   echo "CONFIG_LINUX_USER=y" >> $config_target_mak
commit 6a84cb1f2822e494839b93dd8c7f7f8fa6c261a9
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Dec 21 11:37:57 2011 +0100

    scsi virtio-blk usb-msd: Clean up device init error messages
    
    Replace
    
        error_report("DEVICE-NAME: MESSAGE");
    
    by just
    
        error_report("MESSAGE");
    
    in block device init functions.
    
    DEVICE-NAME is bogus in some cases: it's "scsi-disk" for device
    scsi-hd and scsi-cd, "virtio-blk-pci" for virtio-blk-s390, and
    "usb-msd" for usb-storage.
    
    There is no real need to put a device name in the message, because
    error_report() points to the offending command line option already:
    
    $ qemu-system-x86_64 --nodefaults --enable-kvm -vnc :0 -S -monitor stdio -usb -device virtio-blk-pci
    upstream-qemu: -device virtio-blk-pci: virtio-blk-pci: drive property not set
    upstream-qemu: -device virtio-blk-pci: Device 'virtio-blk-pci' could not be initialized
    
    And for a monitor command, it's obvious anyway:
    
    $ qemu-system-x86_64 --nodefaults --enable-kvm -vnc :0 -S -monitor stdio -usb
    (qemu) device_add virtio-blk-pci
    virtio-blk-pci: drive property not set
    Device 'virtio-blk-pci' could not be initialized
    
    Reported-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 505accd..5d8bf53 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1515,7 +1515,7 @@ static int scsi_initfn(SCSIDevice *dev)
     DriveInfo *dinfo;
 
     if (!s->qdev.conf.bs) {
-        error_report("scsi-disk: drive property not set");
+        error_report("drive property not set");
         return -1;
     }
 
@@ -1537,7 +1537,7 @@ static int scsi_initfn(SCSIDevice *dev)
     }
 
     if (bdrv_is_sg(s->qdev.conf.bs)) {
-        error_report("scsi-disk: unwanted /dev/sg*");
+        error_report("unwanted /dev/sg*");
         return -1;
     }
 
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 6f7d3db..0aebcdd 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -374,13 +374,13 @@ static int scsi_generic_initfn(SCSIDevice *s)
     struct sg_scsi_id scsiid;
 
     if (!s->conf.bs) {
-        error_report("scsi-generic: drive property not set");
+        error_report("drive property not set");
         return -1;
     }
 
     /* check we are really using a /dev/sg* file */
     if (!bdrv_is_sg(s->conf.bs)) {
-        error_report("scsi-generic: not /dev/sg*");
+        error_report("not /dev/sg*");
         return -1;
     }
 
@@ -396,13 +396,13 @@ static int scsi_generic_initfn(SCSIDevice *s)
     /* check we are using a driver managing SG_IO (version 3 and after */
     if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
         sg_version < 30000) {
-        error_report("scsi-generic: scsi generic interface too old");
+        error_report("scsi generic interface too old");
         return -1;
     }
 
     /* get LUN of the /dev/sg? */
     if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) {
-        error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
+        error_report("SG_GET_SCSI_ID ioctl failed");
         return -1;
     }
 
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 4c06950..b87b929 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -517,7 +517,7 @@ static int usb_msd_initfn(USBDevice *dev)
     DriveInfo *dinfo;
 
     if (!bs) {
-        error_report("usb-msd: drive property not set");
+        error_report("drive property not set");
         return -1;
     }
 
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index ef27421..5e81f53 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -569,7 +569,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
     DriveInfo *dinfo;
 
     if (!conf->bs) {
-        error_report("virtio-blk-pci: drive property not set");
+        error_report("drive property not set");
         return NULL;
     }
     if (!bdrv_is_inserted(conf->bs)) {
commit be62a2ebab29eef7dc66c112d60271890ebbbee2
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Dec 20 18:13:08 2011 +0100

    Strip trailing '\n' from error_report()'s first argument (again)
    
    Commit 6daf194d got rid of them, but Hans and Gerd added some more
    lately.  Tracked down with this Coccinelle semantic patch:
    
    @r@
        expression fmt;
        position p;
    @@
        error_report(fmt, ...)@p
    @script:python@
        fmt << r.fmt;
        p << r.p;
    @@
    if "\\n" in str(fmt):
        print "%s:%s:%s:%s" % (p[0].file, p[0].line, p[0].column, fmt)
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>

diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 8203390..bd4afa7 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -137,7 +137,7 @@ USBDevice *usb_create(USBBus *bus, const char *name)
         bus = usb_bus_find(-1);
         if (!bus)
             return NULL;
-        error_report("%s: no bus specified, using \"%s\" for \"%s\"\n",
+        error_report("%s: no bus specified, using \"%s\" for \"%s\"",
                 __FUNCTION__, bus->qbus.name, name);
     }
 #endif
@@ -152,12 +152,12 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name)
     int rc;
 
     if (!dev) {
-        error_report("Failed to create USB device '%s'\n", name);
+        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'\n", name);
+        error_report("Failed to initialize USB device '%s'", name);
         return NULL;
     }
     return dev;
@@ -244,7 +244,7 @@ int usb_claim_port(USBDevice *dev)
             }
         }
         if (port == NULL) {
-            error_report("Error: usb port %s (bus %s) not found (in use?)\n",
+            error_report("Error: usb port %s (bus %s) not found (in use?)",
                          dev->port_path, bus->qbus.name);
             return -1;
         }
@@ -255,7 +255,7 @@ int usb_claim_port(USBDevice *dev)
         }
         if (bus->nfree == 0) {
             error_report("Error: tried to attach usb device %s to a bus "
-                         "with no free ports\n", dev->product_desc);
+                         "with no free ports", dev->product_desc);
             return -1;
         }
         port = QTAILQ_FIRST(&bus->free);
@@ -302,7 +302,7 @@ int usb_device_attach(USBDevice *dev)
 
     if (!(port->speedmask & dev->speedmask)) {
         error_report("Warning: speed mismatch trying to attach "
-                     "usb device %s to bus %s\n",
+                     "usb device %s to bus %s",
                      dev->product_desc, bus->qbus.name);
         return -1;
     }
diff --git a/usb-redir.c b/usb-redir.c
index a36f2a7..2b53cf3 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -174,7 +174,7 @@ static void usbredir_log(void *priv, int level, const char *msg)
         return;
     }
 
-    error_report("%s\n", msg);
+    error_report("%s", msg);
 }
 
 static void usbredir_log_data(USBRedirDevice *dev, const char *desc,
@@ -193,7 +193,7 @@ static void usbredir_log_data(USBRedirDevice *dev, const char *desc,
         for (j = 0; j < 8 && i + j < len; j++) {
             n += sprintf(buf + n, " %02X", data[i + j]);
         }
-        error_report("%s\n", buf);
+        error_report("%s", buf);
     }
 }
 
commit d70d6b31091ab522ce793a52559e3dd9f9913b32
Author: Alon Levy <alevy at redhat.com>
Date:   Tue Dec 20 13:05:18 2011 +0200

    qemu-options.hx: fix tls-channel help text
    
    Remove the default compiled out tunnel channel, add the always available
    cursor channel. Optimally the man page would depend on compiled in
    options, but that's harder to do.
    
    RHBZ: 688586
    
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index a60191f..3c3bda8 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -857,8 +857,8 @@ The x509 file names can also be configured individually.
 @item tls-ciphers=<list>
 Specify which ciphers to use.
 
- at item tls-channel=[main|display|inputs|record|playback|tunnel]
- at item plaintext-channel=[main|display|inputs|record|playback|tunnel]
+ at item tls-channel=[main|display|cursor|inputs|record|playback]
+ at item plaintext-channel=[main|display|cursor|inputs|record|playback]
 Force specific channel to be used with or without TLS encryption.  The
 options can be specified multiple times to configure multiple
 channels.  The special name "default" can be used to set the default
commit f40b7d113d73d5ca1cdcbe6a4acc1be340a3751d
Merge: 74b728e... ed8e5a8...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jan 6 08:15:39 2012 -0600

    Merge remote-tracking branch 'amit/master' into staging
    
    * amit/master:
      virtio-console: Fix failure on unconnected pty

commit 74b728e4f3a4be43c71a58e4c8102b6d700a0018
Merge: 40aceb9... 84a87cc...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jan 6 08:14:28 2012 -0600

    Merge remote-tracking branch 'aneesh/for-upstream' into staging
    
    * aneesh/for-upstream:
      hw/9pfs: Add support to use named socket for proxy FS
      hw/9pfs: man page for proxy helper
      hw/9pfs: Documentation changes related to proxy fs
      hw/9pfs: Proxy getversion
      hw/9pfs: xattr interfaces in proxy filesystem driver
      hw/9pfs: File ownership and others
      hw/9pfs: Add stat/readlink/statfs for proxy FS
      hw/9pfs: Create other filesystem objects
      hw/9pfs: Open and create files
      hw/9pfs: File system helper process for qemu 9p proxy FS
      hw/9pfs: Add new proxy filesystem driver
      hw/9pfs: Add validation to {un}marshal code
      hw/9pfs: Move pdu_marshal/unmarshal code to a seperate file
      hw/9pfs: Move opt validation to FsDriver callback

commit 40aceb98f31aefbbc1588d1aa060775b89937e30
Merge: f3e8275... b18620c...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jan 6 08:12:23 2012 -0600

    Merge remote-tracking branch 'sstabellini/xen_mem_fix' into staging
    
    * sstabellini/xen_mem_fix:
      xen: Fix after recent change in dirty bitmap tracking.

commit f3e8275f491ca3dd082e1238c62ca2a0ec740d69
Merge: c47f322... fd891c9...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jan 6 08:11:41 2012 -0600

    Merge remote-tracking branch 'kraxel/usb.33' into staging
    
    * kraxel/usb.33:
      usb-ohci: td.cbp incorrectly updated near page end
      usb-host: properly release port on unplug & exit
      usb-storage: cancel I/O on reset
      Fix parse of usb device description with multiple configurations

commit fd891c9318b112462e54ee1b3b16b074b8bec5b1
Author: Andriy Gapon <avg at FreeBSD.org>
Date:   Thu Dec 22 11:34:30 2011 +0200

    usb-ohci: td.cbp incorrectly updated near page end
    
    The current code that updates the cbp value after a transfer looks like this:
    td.cbp += ret;
    if ((td.cbp & 0xfff) + ret > 0xfff) {
    	<handle page overflow>
    because the 'ret' value is effectively added twice the check may fire too early
    when the overflow hasn't happened yet.
    
    Below is one of the possible changes that correct the behavior:
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index e68be70..81488c4 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1025,10 +1025,10 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
         if (ret == len) {
             td.cbp = 0;
         } else {
-            td.cbp += ret;
             if ((td.cbp & 0xfff) + ret > 0xfff) {
-                td.cbp &= 0xfff;
-                td.cbp |= td.be & ~0xfff;
+                td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff);
+            } else {
+                td.cbp += ret;
             }
         }
         td.flags |= OHCI_TD_T1;
commit c75fead66e25b35b867b661ee92087dc245a48c9
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Jan 5 15:49:18 2012 +0100

    usb-host: properly release port on unplug & exit
    
    Factor out port release into a separate function.  Call release function
    in exit notifier too.  Add explicit call the USBDEVFS_RELEASE_PORT
    ioctl, just closing the hub file handle seems not to be enougth.  Make
    sure we release the port before resetting the device, otherwise host
    drivers will not re-attach.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/usb-linux.c b/usb-linux.c
index ed14bb1..749ce71 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -116,6 +116,7 @@ typedef struct USBHostDevice {
     USBDevice dev;
     int       fd;
     int       hub_fd;
+    int       hub_port;
 
     uint8_t   descr[8192];
     int       descr_len;
@@ -434,7 +435,7 @@ static int usb_host_claim_port(USBHostDevice *s)
 {
 #ifdef USBDEVFS_CLAIM_PORT
     char *h, hub_name[64], line[1024];
-    int hub_addr, portnr, ret;
+    int hub_addr, ret;
 
     snprintf(hub_name, sizeof(hub_name), "%d-%s",
              s->match.bus_num, s->match.port);
@@ -442,13 +443,13 @@ static int usb_host_claim_port(USBHostDevice *s)
     /* try strip off last ".$portnr" to get hub */
     h = strrchr(hub_name, '.');
     if (h != NULL) {
-        portnr = atoi(h+1);
+        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);
-        portnr = atoi(s->match.port);
+        s->hub_port = atoi(s->match.port);
     }
 
     if (!usb_host_read_file(line, sizeof(line), "devnum",
@@ -469,20 +470,32 @@ static int usb_host_claim_port(USBHostDevice *s)
         return -1;
     }
 
-    ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &portnr);
+    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, portnr);
+    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 */
@@ -635,10 +648,8 @@ static void usb_host_handle_destroy(USBDevice *dev)
 {
     USBHostDevice *s = (USBHostDevice *)dev;
 
+    usb_host_release_port(s);
     usb_host_close(s);
-    if (s->hub_fd != -1) {
-        close(s->hub_fd);
-    }
     QTAILQ_REMOVE(&hostdevs, s, next);
     qemu_remove_exit_notifier(&s->exit);
 }
@@ -1402,6 +1413,7 @@ 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);;
     }
commit 24a5bbe1c8cd6f5e90100b42eac29f41c33939de
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jan 4 18:13:54 2012 +0100

    usb-storage: cancel I/O on reset
    
    When resetting the usb-storage device we'll have to carefully cancel
    and clear any requests which might be in flight, otherwise we'll confuse
    the state machine.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 4c06950..3147131 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -278,6 +278,18 @@ 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;
 }
 
commit 7da362d01644fca96c7cb4b72dbf2510020061f2
Author: Mark Langsdorf <mark.langsdorf at calxeda.com>
Date:   Thu Jan 5 15:49:06 2012 +0000

    arm: add dummy A9-specific cp15 registers
    
    Add dummy register support for the cp15, CRn=c15 registers.
    
    config_base_register and power_control_register currently
    default to 0, but may have improved support after the QOM
    CPU patches are finished.
    
    Signed-off-by: Mark Langsdorf <mark.langsdorf at calxeda.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index c4d742f..26b4981 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -149,6 +149,10 @@ typedef struct CPUARMState {
         uint32_t c15_i_max; /* Maximum D-cache dirty line index.  */
         uint32_t c15_i_min; /* Minimum D-cache dirty line index.  */
         uint32_t c15_threadid; /* TI debugger thread-ID.  */
+        uint32_t c15_config_base_address; /* SCU base address.  */
+        uint32_t c15_diagnostic; /* diagnostic register */
+        uint32_t c15_power_diagnostic;
+        uint32_t c15_power_control; /* power control */
     } cp15;
 
     struct {
@@ -448,7 +452,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 #define cpu_signal_handler cpu_arm_signal_handler
 #define cpu_list arm_cpu_list
 
-#define CPU_SAVE_VERSION 4
+#define CPU_SAVE_VERSION 5
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 261d547..fa42c64 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1796,6 +1796,20 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
                 goto bad_reg;
             }
         }
+        if (ARM_CPUID(env) == ARM_CPUID_CORTEXA9) {
+            switch (crm) {
+            case 0:
+                if ((op1 == 0) && (op2 == 0)) {
+                    env->cp15.c15_power_control = val;
+                } else if ((op1 == 0) && (op2 == 1)) {
+                    env->cp15.c15_diagnostic = val;
+                } else if ((op1 == 0) && (op2 == 2)) {
+                    env->cp15.c15_power_diagnostic = val;
+                }
+            default:
+                break;
+            }
+        }
         break;
     }
     return;
@@ -2139,6 +2153,40 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
              * 0x200 << ($rn & 0xfff), when MMU is off.  */
             goto bad_reg;
         }
+        if (ARM_CPUID(env) == ARM_CPUID_CORTEXA9) {
+            switch (crm) {
+            case 0:
+                if ((op1 == 4) && (op2 == 0)) {
+                    /* The config_base_address should hold the value of
+                     * the peripheral base. ARM should get this from a CPU
+                     * object property, but that support isn't available in
+                     * December 2011. Default to 0 for now and board models
+                     * that care can set it by a private hook */
+                    return env->cp15.c15_config_base_address;
+                } else if ((op1 == 0) && (op2 == 0)) {
+                    /* power_control should be set to maximum latency. Again,
+                       default to 0 and set by private hook */
+                    return env->cp15.c15_power_control;
+                } else if ((op1 == 0) && (op2 == 1)) {
+                    return env->cp15.c15_diagnostic;
+                } else if ((op1 == 0) && (op2 == 2)) {
+                    return env->cp15.c15_power_diagnostic;
+                }
+                break;
+            case 1: /* NEON Busy */
+                return 0;
+            case 5: /* tlb lockdown */
+            case 6:
+            case 7:
+                if ((op1 == 5) && (op2 == 2)) {
+                    return 0;
+                }
+                break;
+            default:
+                break;
+            }
+            goto bad_reg;
+        }
         return 0;
     }
 bad_reg:
diff --git a/target-arm/machine.c b/target-arm/machine.c
index aaee9b9..8984775 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -56,6 +56,9 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_be32(f, env->cp15.c13_tls2);
     qemu_put_be32(f, env->cp15.c13_tls3);
     qemu_put_be32(f, env->cp15.c15_cpar);
+    qemu_put_be32(f, env->cp15.c15_power_control);
+    qemu_put_be32(f, env->cp15.c15_diagnostic);
+    qemu_put_be32(f, env->cp15.c15_power_diagnostic);
 
     qemu_put_be32(f, env->features);
 
@@ -170,6 +173,9 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     env->cp15.c13_tls2 = qemu_get_be32(f);
     env->cp15.c13_tls3 = qemu_get_be32(f);
     env->cp15.c15_cpar = qemu_get_be32(f);
+    env->cp15.c15_power_control = qemu_get_be32(f);
+    env->cp15.c15_diagnostic = qemu_get_be32(f);
+    env->cp15.c15_power_diagnostic = qemu_get_be32(f);
 
     env->features = qemu_get_be32(f);
 
commit 37064a8b6f9075e18b05bfc6d5264b138a224713
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Jan 5 15:49:06 2012 +0000

    target-arm: Ignore attempts to set invalid modes in CPSR
    
    Ignore attempts to set the CPSR mode field to an invalid value.
    This is UNPREDICTABLE, but we should not cpu_abort() for things
    a malicious guest (or a confused user on the gdbstub interface)
    can provoke.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 5b994d5..261d547 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -463,6 +463,26 @@ void cpu_arm_close(CPUARMState *env)
     g_free(env);
 }
 
+static int bad_mode_switch(CPUState *env, int mode)
+{
+    /* Return true if it is not valid for us to switch to
+     * this CPU mode (ie all the UNPREDICTABLE cases in
+     * the ARM ARM CPSRWriteByInstr pseudocode).
+     */
+    switch (mode) {
+    case ARM_CPU_MODE_USR:
+    case ARM_CPU_MODE_SYS:
+    case ARM_CPU_MODE_SVC:
+    case ARM_CPU_MODE_ABT:
+    case ARM_CPU_MODE_UND:
+    case ARM_CPU_MODE_IRQ:
+    case ARM_CPU_MODE_FIQ:
+        return 0;
+    default:
+        return 1;
+    }
+}
+
 uint32_t cpsr_read(CPUARMState *env)
 {
     int ZF;
@@ -499,7 +519,15 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
     }
 
     if ((env->uncached_cpsr ^ val) & mask & CPSR_M) {
-        switch_mode(env, val & CPSR_M);
+        if (bad_mode_switch(env, val & CPSR_M)) {
+            /* Attempt to switch to an invalid mode: this is UNPREDICTABLE.
+             * We choose to ignore the attempt and leave the CPSR M field
+             * untouched.
+             */
+            mask &= ~CPSR_M;
+        } else {
+            switch_mode(env, val & CPSR_M);
+        }
     }
     mask &= ~CACHED_CPSR_BITS;
     env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask);
commit 1b9e01c1109189951a5f28b90ca037e12d61511c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Jan 5 15:49:06 2012 +0000

    target-arm: Don't use cpu_single_env in bank_number()
    
    Avoid using cpu_single_env in bank_number() -- if we were
    called via the gdb stub reading or writing the CPSR then
    it is NULL and we will segfault if we take the cpu_abort().
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 65f4fbf..5b994d5 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -642,7 +642,7 @@ uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
 extern int semihosting_enabled;
 
 /* Map CPU modes onto saved register banks.  */
-static inline int bank_number (int mode)
+static inline int bank_number(CPUState *env, int mode)
 {
     switch (mode) {
     case ARM_CPU_MODE_USR:
@@ -659,7 +659,7 @@ static inline int bank_number (int mode)
     case ARM_CPU_MODE_FIQ:
         return 5;
     }
-    cpu_abort(cpu_single_env, "Bad mode %x\n", mode);
+    cpu_abort(env, "Bad mode %x\n", mode);
     return -1;
 }
 
@@ -680,12 +680,12 @@ void switch_mode(CPUState *env, int mode)
         memcpy (env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
     }
 
-    i = bank_number(old_mode);
+    i = bank_number(env, old_mode);
     env->banked_r13[i] = env->regs[13];
     env->banked_r14[i] = env->regs[14];
     env->banked_spsr[i] = env->spsr;
 
-    i = bank_number(mode);
+    i = bank_number(env, mode);
     env->regs[13] = env->banked_r13[i];
     env->regs[14] = env->banked_r14[i];
     env->spsr = env->banked_spsr[i];
@@ -2125,7 +2125,7 @@ void HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val)
     if ((env->uncached_cpsr & CPSR_M) == mode) {
         env->regs[13] = val;
     } else {
-        env->banked_r13[bank_number(mode)] = val;
+        env->banked_r13[bank_number(env, mode)] = val;
     }
 }
 
@@ -2134,7 +2134,7 @@ uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
     if ((env->uncached_cpsr & CPSR_M) == mode) {
         return env->regs[13];
     } else {
-        return env->banked_r13[bank_number(mode)];
+        return env->banked_r13[bank_number(env, mode)];
     }
 }
 
commit b18620cf760d283b044543c831db5c88e2c66dcd
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Thu Jan 5 12:47:08 2012 +0000

    xen: Fix after recent change in dirty bitmap tracking.
    
    A recent patch set from Avi break the dirty bitmap support of Xen. But
    this is because xen_sync_dirty_bitmap will return an error for an
    unhandled memory range (a0000 - bffff). However this is not a fatal
    error, so we should just continue instead of aborting.
    
    There is now an error printed when the Xen call failed.
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Acked-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/xen-all.c b/xen-all.c
index d58d461..c86ebf4 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -404,9 +404,9 @@ static void xen_region_del(MemoryListener *listener,
     xen_set_memory(listener, section, false);
 }
 
-static int xen_sync_dirty_bitmap(XenIOState *state,
-                                 target_phys_addr_t start_addr,
-                                 ram_addr_t size)
+static void xen_sync_dirty_bitmap(XenIOState *state,
+                                  target_phys_addr_t start_addr,
+                                  ram_addr_t size)
 {
     target_phys_addr_t npages = size >> TARGET_PAGE_BITS;
     const int width = sizeof(unsigned long) * 8;
@@ -417,20 +417,26 @@ static int xen_sync_dirty_bitmap(XenIOState *state,
     physmap = get_physmapping(state, start_addr, size);
     if (physmap == NULL) {
         /* not handled */
-        return -1;
+        return;
     }
 
     if (state->log_for_dirtybit == NULL) {
         state->log_for_dirtybit = physmap;
     } else if (state->log_for_dirtybit != physmap) {
-        return -1;
+        /* Only one range for dirty bitmap can be tracked. */
+        return;
     }
 
     rc = xc_hvm_track_dirty_vram(xen_xc, xen_domid,
                                  start_addr >> TARGET_PAGE_BITS, npages,
                                  bitmap);
-    if (rc) {
-        return rc;
+    if (rc < 0) {
+        if (rc != -ENODATA) {
+            fprintf(stderr, "xen: track_dirty_vram failed (0x" TARGET_FMT_plx
+                    ", 0x" TARGET_FMT_plx "): %s\n",
+                    start_addr, start_addr + size, strerror(-rc));
+        }
+        return;
     }
 
     for (i = 0; i < ARRAY_SIZE(bitmap); i++) {
@@ -442,40 +448,32 @@ static int xen_sync_dirty_bitmap(XenIOState *state,
                                     (i * width + j) * TARGET_PAGE_SIZE);
         };
     }
-
-    return 0;
 }
 
 static void xen_log_start(MemoryListener *listener,
                           MemoryRegionSection *section)
 {
     XenIOState *state = container_of(listener, XenIOState, memory_listener);
-    int r;
 
-    r = xen_sync_dirty_bitmap(state, section->offset_within_address_space,
-                              section->size);
-    assert(r >= 0);
+    xen_sync_dirty_bitmap(state, section->offset_within_address_space,
+                          section->size);
 }
 
 static void xen_log_stop(MemoryListener *listener, MemoryRegionSection *section)
 {
     XenIOState *state = container_of(listener, XenIOState, memory_listener);
-    int r;
 
     state->log_for_dirtybit = NULL;
     /* Disable dirty bit tracking */
-    r = xc_hvm_track_dirty_vram(xen_xc, xen_domid, 0, 0, NULL);
-    assert(r >= 0);
+    xc_hvm_track_dirty_vram(xen_xc, xen_domid, 0, 0, NULL);
 }
 
 static void xen_log_sync(MemoryListener *listener, MemoryRegionSection *section)
 {
     XenIOState *state = container_of(listener, XenIOState, memory_listener);
-    int r;
 
-    r = xen_sync_dirty_bitmap(state, section->offset_within_address_space,
-                              section->size);
-    assert(r >= 0);
+    xen_sync_dirty_bitmap(state, section->offset_within_address_space,
+                          section->size);
 }
 
 static void xen_log_global_start(MemoryListener *listener)
commit c47f3223658119219bbe0b8d09da733d1c06e76f
Merge: 11c7ef0... b2123a4...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Jan 4 10:06:25 2012 -0600

    Merge remote-tracking branch 'pmaydell/arm-devs.for-upstream' into staging
    
    * pmaydell/arm-devs.for-upstream:
      add L2x0/PL310 cache controller device
      arm: add dummy gic security registers
      arm: Set frequencies for arm_timer
      arm: add missing scu registers
      hw/omap_gpmc: Fix region map/unmap when configuring prefetch engine
      hw/omap1.c: Drop unused includes
      hw/omap1.c: Separate dpll_ctl from omap_mpu_state
      hw/omap1.c: Separate PWT from omap_mpu_state
      hw/omap1.c: Separate PWL from omap_mpu_state
      hw/omap1.c: omap_mpuio_init() need not be public
      hw/pl110.c: Add post-load hook to invalidate display
      hw/pl181.c: Add save/load support

commit 84a87cc4cc77f9e6829e20726f00646afe12deed
Author: M. Mohan Kumar <mohan at in.ibm.com>
Date:   Wed Dec 14 13:58:47 2011 +0530

    hw/9pfs: Add support to use named socket for proxy FS
    
    Add option to use named socket for communicating between proxy helper
    and qemu proxy FS. Access to socket can be given by using command line
    options -u and -g.
    
    Signed-off-by: M. Mohan Kumar <mohan at in.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 7ef14af..1e96c8b 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -57,6 +57,8 @@ typedef struct extended_ops {
  */
 #define V9FS_SM_NONE                0x00000010
 #define V9FS_RDONLY                 0x00000020
+#define V9FS_PROXY_SOCK_FD          0x00000040
+#define V9FS_PROXY_SOCK_NAME        0x00000080
 
 #define V9FS_SEC_MASK               0x0000001C
 
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 52d748d..7f8def5 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -57,6 +57,9 @@ static struct option helper_opts[] = {
     {"fd", required_argument, NULL, 'f'},
     {"path", required_argument, NULL, 'p'},
     {"nodaemon", no_argument, NULL, 'n'},
+    {"socket", required_argument, NULL, 's'},
+    {"uid", required_argument, NULL, 'u'},
+    {"gid", required_argument, NULL, 'g'},
 };
 
 static bool is_daemon;
@@ -695,11 +698,61 @@ err_out:
     return ret;
 }
 
+/* create unix domain socket and return the descriptor */
+static int proxy_socket(const char *path, uid_t uid, gid_t gid)
+{
+    int sock, client;
+    struct sockaddr_un proxy, qemu;
+    socklen_t size;
+
+    /* requested socket already exists, refuse to start */
+    if (!access(path, F_OK)) {
+        do_log(LOG_CRIT, "socket already exists\n");
+        return -1;
+    }
+
+    sock = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sock < 0) {
+        do_perror("socket");
+        return -1;
+    }
+
+    /* mask other part of mode bits */
+    umask(7);
+
+    proxy.sun_family = AF_UNIX;
+    strcpy(proxy.sun_path, path);
+    if (bind(sock, (struct sockaddr *)&proxy,
+            sizeof(struct sockaddr_un)) < 0) {
+        do_perror("bind");
+        return -1;
+    }
+    if (chown(proxy.sun_path, uid, gid) < 0) {
+        do_perror("chown");
+        return -1;
+    }
+    if (listen(sock, 1) < 0) {
+        do_perror("listen");
+        return -1;
+    }
+
+    client = accept(sock, (struct sockaddr *)&qemu, &size);
+    if (client < 0) {
+        do_perror("accept");
+        return -1;
+    }
+    return client;
+}
+
 static void usage(char *prog)
 {
     fprintf(stderr, "usage: %s\n"
             " -p|--path <path> 9p path to export\n"
             " {-f|--fd <socket-descriptor>} socket file descriptor to be used\n"
+            " {-s|--socket <socketname> socket file used for communication\n"
+            " \t-u|--uid <uid> -g|--gid <gid>} - uid:gid combination to give "
+            " access to this socket\n"
+            " \tNote: -s & -f can not be used together\n"
             " [-n|--nodaemon] Run as a normal program\n",
             basename(prog));
 }
@@ -939,7 +992,10 @@ err_out:
 int main(int argc, char **argv)
 {
     int sock;
+    uid_t own_u;
+    gid_t own_g;
     char *rpath = NULL;
+    char *sock_name = NULL;
     struct stat stbuf;
     int c, option_index;
 #ifdef FS_IOC_GETVERSION
@@ -949,9 +1005,10 @@ int main(int argc, char **argv)
 
     is_daemon = true;
     sock = -1;
+    own_u = own_g = -1;
     while (1) {
         option_index = 0;
-        c = getopt_long(argc, argv, "p:nh?f:", helper_opts,
+        c = getopt_long(argc, argv, "p:nh?f:s:u:g:", helper_opts,
                         &option_index);
         if (c == -1) {
             break;
@@ -966,6 +1023,15 @@ int main(int argc, char **argv)
         case 'f':
             sock = atoi(optarg);
             break;
+        case 's':
+            sock_name = strdup(optarg);
+            break;
+        case 'u':
+            own_u = atoi(optarg);
+            break;
+        case 'g':
+            own_g = atoi(optarg);
+            break;
         case '?':
         case 'h':
         default:
@@ -975,8 +1041,16 @@ int main(int argc, char **argv)
     }
 
     /* Parameter validation */
-    if (sock == -1 || rpath == NULL) {
-        fprintf(stderr, "socket descriptor or path not specified\n");
+    if ((sock_name == NULL && sock == -1) || rpath == NULL) {
+        fprintf(stderr, "socket, socket descriptor or path not specified\n");
+        usage(argv[0]);
+        return -1;
+    }
+
+    if (*sock_name && (own_u == -1 || own_g == -1)) {
+        fprintf(stderr, "owner uid:gid not specified, ");
+        fprintf(stderr,
+                "owner uid:gid specifies who can access the socket file\n");
         usage(argv[0]);
         exit(EXIT_FAILURE);
     }
@@ -1001,6 +1075,12 @@ int main(int argc, char **argv)
     }
 
     do_log(LOG_INFO, "Started\n");
+    if (*sock_name) {
+        sock = proxy_socket(sock_name, own_u, own_g);
+        if (sock < 0) {
+            goto error;
+        }
+    }
 
     get_version = false;
 #ifdef FS_IOC_GETVERSION
diff --git a/fsdev/virtfs-proxy-helper.texi b/fsdev/virtfs-proxy-helper.texi
index 3816382..faa0434 100644
--- a/fsdev/virtfs-proxy-helper.texi
+++ b/fsdev/virtfs-proxy-helper.texi
@@ -46,6 +46,10 @@ Path to export for proxy filesystem driver
 Use given file descriptor as socket descriptor for communicating with
 qemu proxy fs drier. Usually a helper like libvirt will create
 socketpair and pass one of the fds as parameter to -f|--fd
+ at item -s|--socket socket-file
+Creates named socket file for communicating with qemu proxy fs driver
+ at item -u|--uid uid -g|--gid gid
+uid:gid combination to give access to named socket file
 @item -n|--nodaemon
 Run as a normal program. By default program will run in daemon mode
 @end table
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 415bd21..44f5fc4 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -1095,15 +1095,49 @@ static int proxy_ioc_getversion(FsContext *fs_ctx, V9fsPath *path,
     return err;
 }
 
+static int connect_namedsocket(const char *path)
+{
+    int sockfd, size;
+    struct sockaddr_un helper;
+
+    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sockfd < 0) {
+        fprintf(stderr, "socket %s\n", strerror(errno));
+        return -1;
+    }
+    strcpy(helper.sun_path, path);
+    helper.sun_family = AF_UNIX;
+    size = strlen(helper.sun_path) + sizeof(helper.sun_family);
+    if (connect(sockfd, (struct sockaddr *)&helper, size) < 0) {
+        fprintf(stderr, "socket error\n");
+        return -1;
+    }
+
+    /* remove the socket for security reasons */
+    unlink(path);
+    return sockfd;
+}
+
 static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs)
 {
+    const char *socket = qemu_opt_get(opts, "socket");
     const char *sock_fd = qemu_opt_get(opts, "sock_fd");
 
-    if (sock_fd) {
-        fprintf(stderr, "sock_fd option not specified\n");
+    if (!socket && !sock_fd) {
+        fprintf(stderr, "socket and sock_fd none of the option specified\n");
+        return -1;
+    }
+    if (socket && sock_fd) {
+        fprintf(stderr, "Both socket and sock_fd options specified\n");
         return -1;
     }
-    fs->path = g_strdup(sock_fd);
+    if (socket) {
+        fs->path = g_strdup(socket);
+        fs->export_flags = V9FS_PROXY_SOCK_NAME;
+    } else {
+        fs->path = g_strdup(sock_fd);
+        fs->export_flags = V9FS_PROXY_SOCK_FD;
+    }
     return 0;
 }
 
@@ -1112,10 +1146,14 @@ static int proxy_init(FsContext *ctx)
     V9fsProxy *proxy = g_malloc(sizeof(V9fsProxy));
     int sock_id;
 
-    sock_id = atoi(ctx->fs_root);
-    if (sock_id < 0) {
-        fprintf(stderr, "socket descriptor not initialized\n");
-        return -1;
+    if (ctx->export_flags & V9FS_PROXY_SOCK_NAME) {
+        sock_id = connect_namedsocket(ctx->fs_root);
+    } else {
+        sock_id = atoi(ctx->fs_root);
+        if (sock_id < 0) {
+            fprintf(stderr, "socket descriptor not initialized\n");
+            return -1;
+        }
     }
     g_free(ctx->fs_root);
 
diff --git a/qemu-config.c b/qemu-config.c
index 1bdc01c..ecc88e8 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -211,6 +211,10 @@ QemuOptsList qemu_fsdev_opts = {
         }, {
             .name = "readonly",
             .type = QEMU_OPT_BOOL,
+
+        }, {
+            .name = "socket",
+            .type = QEMU_OPT_STRING,
         }, {
             .name = "sock_fd",
             .type = QEMU_OPT_NUMBER,
@@ -244,6 +248,9 @@ QemuOptsList qemu_virtfs_opts = {
             .name = "readonly",
             .type = QEMU_OPT_BOOL,
         }, {
+            .name = "socket",
+            .type = QEMU_OPT_STRING,
+        }, {
             .name = "sock_fd",
             .type = QEMU_OPT_NUMBER,
         },
diff --git a/qemu-options.hx b/qemu-options.hx
index 904d751..b38e672 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -552,12 +552,12 @@ DEFHEADING(File system options:)
 
 DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
     "-fsdev fsdriver,id=id[,path=path,][security_model={mapped|passthrough|none}]\n"
-    " [,writeout=immediate][,readonly][,sock_fd=sock_fd]\n",
+    " [,writeout=immediate][,readonly][,socket=socket|sock_fd=sock_fd]\n",
     QEMU_ARCH_ALL)
 
 STEXI
 
- at item -fsdev @var{fsdriver},id=@var{id},path=@var{path},[security_model=@var{security_model}][,writeout=@var{writeout}][,readonly][,sock_fd=@var{sock_fd}]
+ at item -fsdev @var{fsdriver},id=@var{id},path=@var{path},[security_model=@var{security_model}][,writeout=@var{writeout}][,readonly][,socket=@var{socket}|sock_fd=@var{sock_fd}]
 @findex -fsdev
 Define a new file system device. Valid options are:
 @table @option
@@ -590,6 +590,9 @@ reported as written by the storage subsystem.
 @item readonly
 Enables exporting 9p share as a readonly mount for guests. By default
 read-write access is given.
+ at item socket=@var{socket}
+Enables proxy filesystem driver to use passed socket file for communicating
+with virtfs-proxy-helper
 @item sock_fd=@var{sock_fd}
 Enables proxy filesystem driver to use passed socket descriptor for
 communicating with virtfs-proxy-helper. Usually a helper like libvirt
@@ -614,12 +617,12 @@ DEFHEADING(Virtual File system pass-through options:)
 
 DEF("virtfs", HAS_ARG, QEMU_OPTION_virtfs,
     "-virtfs local,path=path,mount_tag=tag,security_model=[mapped|passthrough|none]\n"
-    "        [,writeout=immediate][,readonly][,sock_fd=sock_fd]\n",
+    "        [,writeout=immediate][,readonly][,socket=socket|sock_fd=sock_fd]\n",
     QEMU_ARCH_ALL)
 
 STEXI
 
- at item -virtfs @var{fsdriver}[,path=@var{path}],mount_tag=@var{mount_tag}[,security_model=@var{security_model}][,writeout=@var{writeout}][,readonly][,sock_fd=@var{sock_fd}]
+ at item -virtfs @var{fsdriver}[,path=@var{path}],mount_tag=@var{mount_tag}[,security_model=@var{security_model}][,writeout=@var{writeout}][,readonly][,socket=@var{socket}|sock_fd=@var{sock_fd}]
 @findex -virtfs
 
 The general form of a Virtual File system pass-through options are:
@@ -653,6 +656,10 @@ reported as written by the storage subsystem.
 @item readonly
 Enables exporting 9p share as a readonly mount for guests. By default
 read-write access is given.
+ at item socket=@var{socket}
+Enables proxy filesystem driver to use passed socket file for
+communicating with virtfs-proxy-helper. Usually a helper like libvirt
+will create socketpair and pass one of the fds as sock_fd
 @item sock_fd
 Enables proxy filesystem driver to use passed 'sock_fd' as the socket
 descriptor for interfacing with virtfs-proxy-helper
diff --git a/vl.c b/vl.c
index aaa2b93..ba55b35 100644
--- a/vl.c
+++ b/vl.c
@@ -2661,7 +2661,7 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_virtfs: {
                 QemuOpts *fsdev;
                 QemuOpts *device;
-                const char *writeout, *sock_fd;
+                const char *writeout, *sock_fd, *socket;
 
                 olist = qemu_find_opts("virtfs");
                 if (!olist) {
@@ -2701,6 +2701,10 @@ int main(int argc, char **argv, char **envp)
                 qemu_opt_set(fsdev, "path", qemu_opt_get(opts, "path"));
                 qemu_opt_set(fsdev, "security_model",
                              qemu_opt_get(opts, "security_model"));
+                socket = qemu_opt_get(opts, "socket");
+                if (socket) {
+                    qemu_opt_set(fsdev, "socket", socket);
+                }
                 sock_fd = qemu_opt_get(opts, "sock_fd");
                 if (sock_fd) {
                     qemu_opt_set(fsdev, "sock_fd", sock_fd);
commit a2d8f1beb11004e76aec5cd05ecb62f2b1037598
Author: M. Mohan Kumar <mohan at in.ibm.com>
Date:   Wed Dec 14 13:58:47 2011 +0530

    hw/9pfs: man page for proxy helper
    
    Signed-off-by: M. Mohan Kumar <mohan at in.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/Makefile b/Makefile
index c665b72..9ce8768 100644
--- a/Makefile
+++ b/Makefile
@@ -38,6 +38,7 @@ LIBS+=-lz $(LIBS_TOOLS)
 
 ifdef BUILD_DOCS
 DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 QMP/qmp-commands.txt
+DOCS+=fsdev/virtfs-proxy-helper.1
 else
 DOCS=
 endif
@@ -289,7 +290,10 @@ ifdef CONFIG_POSIX
 	$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man8"
 	$(INSTALL_DATA) qemu-nbd.8 "$(DESTDIR)$(mandir)/man8"
 endif
-
+ifdef CONFIG_VIRTFS
+	$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
+	$(INSTALL_DATA) fsdev/virtfs-proxy-helper.1 "$(DESTDIR)$(mandir)/man1"
+endif
 install-sysconfig:
 	$(INSTALL_DIR) "$(DESTDIR)$(sysconfdir)/qemu"
 	$(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/target-x86_64.conf "$(DESTDIR)$(sysconfdir)/qemu"
@@ -373,6 +377,12 @@ qemu-img.1: qemu-img.texi qemu-img-cmds.texi
 	  pod2man --section=1 --center=" " --release=" " qemu-img.pod > $@, \
 	  "  GEN   $@")
 
+fsdev/virtfs-proxy-helper.1: fsdev/virtfs-proxy-helper.texi
+	$(call quiet-command, \
+	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< fsdev/virtfs-proxy-helper.pod && \
+	  pod2man --section=1 --center=" " --release=" " fsdev/virtfs-proxy-helper.pod > $@, \
+	  "  GEN   $@")
+
 qemu-nbd.8: qemu-nbd.texi
 	$(call quiet-command, \
 	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu-nbd.pod && \
diff --git a/fsdev/virtfs-proxy-helper.texi b/fsdev/virtfs-proxy-helper.texi
new file mode 100644
index 0000000..3816382
--- /dev/null
+++ b/fsdev/virtfs-proxy-helper.texi
@@ -0,0 +1,59 @@
+ at example
+ at c man begin SYNOPSIS
+usage: virtfs-proxy-helper options
+ at c man end
+ at end example
+
+ at c man begin DESCRIPTION
+ at table @description
+Pass-through security model in QEMU 9p server needs root privilege to do
+few file operations (like chown, chmod to any mode/uid:gid).  There are two
+issues in pass-through security model
+
+1) TOCTTOU vulnerability: Following symbolic links in the server could
+provide access to files beyond 9p export path.
+
+2) Running QEMU with root privilege could be a security issue.
+
+To overcome above issues, following approach is used: A new filesytem
+type 'proxy' is introduced. Proxy FS uses chroot + socket combination
+for securing the vulnerability known with following symbolic links.
+Intention of adding a new filesystem type is to allow qemu to run
+in non-root mode, but doing privileged operations using socket IO.
+
+Proxy helper(a stand alone binary part of qemu) is invoked with
+root privileges. Proxy helper chroots into 9p export path and creates
+a socket pair or a named socket based on the command line parameter.
+Qemu and proxy helper communicate using this socket. QEMU proxy fs
+driver sends filesystem request to proxy helper and receives the
+response from it.
+
+Proxy helper is designed so that it can drop the root privilege with
+retaining capbilities needed for doing filesystem operations only.
+
+ at end table
+ at c man end
+
+ at c man begin OPTIONS
+The following options are supported:
+ at table @option
+ at item -h
+ at findex -h
+Display help and exit
+ at item -p|--path path
+Path to export for proxy filesystem driver
+ at item -f|--fd socket-id
+Use given file descriptor as socket descriptor for communicating with
+qemu proxy fs drier. Usually a helper like libvirt will create
+socketpair and pass one of the fds as parameter to -f|--fd
+ at item -n|--nodaemon
+Run as a normal program. By default program will run in daemon mode
+ at end table
+ at c man end
+
+ at setfilename virtfs-proxy-helper
+ at settitle QEMU 9p virtfs proxy filesystem helper
+
+ at c man begin AUTHOR
+M. Mohan Kumar
+ at c man end
commit f67e3ffd34ff8380a3e6d5fca0f6df440478c2ed
Author: M. Mohan Kumar <mohan at in.ibm.com>
Date:   Wed Dec 14 13:58:46 2011 +0530

    hw/9pfs: Documentation changes related to proxy fs
    
    Signed-off-by: M. Mohan Kumar <mohan at in.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index a60191f..904d751 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -551,19 +551,19 @@ DEFHEADING()
 DEFHEADING(File system options:)
 
 DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
-    "-fsdev fsdriver,id=id,path=path,[security_model={mapped|passthrough|none}]\n"
-    "       [,writeout=immediate][,readonly]\n",
+    "-fsdev fsdriver,id=id[,path=path,][security_model={mapped|passthrough|none}]\n"
+    " [,writeout=immediate][,readonly][,sock_fd=sock_fd]\n",
     QEMU_ARCH_ALL)
 
 STEXI
 
- at item -fsdev @var{fsdriver},id=@var{id},path=@var{path},[security_model=@var{security_model}][,writeout=@var{writeout}][,readonly]
+ at item -fsdev @var{fsdriver},id=@var{id},path=@var{path},[security_model=@var{security_model}][,writeout=@var{writeout}][,readonly][,sock_fd=@var{sock_fd}]
 @findex -fsdev
 Define a new file system device. Valid options are:
 @table @option
 @item @var{fsdriver}
 This option specifies the fs driver backend to use.
-Currently "local" and "handle" file system drivers are supported.
+Currently "local", "handle" and "proxy" file system drivers are supported.
 @item id=@var{id}
 Specifies identifier for this device
 @item path=@var{path}
@@ -580,7 +580,7 @@ file attributes. Directories exported by this security model cannot
 interact with other unix tools. "none" security model is same as
 passthrough except the sever won't report failures if it fails to
 set file attributes like ownership. Security model is mandatory
-only for local fsdriver. Other fsdrivers (like handle) don't take
+only for local fsdriver. Other fsdrivers (like handle, proxy) don't take
 security model as a parameter.
 @item writeout=@var{writeout}
 This is an optional argument. The only supported value is "immediate".
@@ -590,6 +590,10 @@ reported as written by the storage subsystem.
 @item readonly
 Enables exporting 9p share as a readonly mount for guests. By default
 read-write access is given.
+ at item sock_fd=@var{sock_fd}
+Enables proxy filesystem driver to use passed socket descriptor for
+communicating with virtfs-proxy-helper. Usually a helper like libvirt
+will create socketpair and pass one of the fds as sock_fd
 @end table
 
 -fsdev option is used along with -device driver "virtio-9p-pci".
@@ -610,19 +614,19 @@ DEFHEADING(Virtual File system pass-through options:)
 
 DEF("virtfs", HAS_ARG, QEMU_OPTION_virtfs,
     "-virtfs local,path=path,mount_tag=tag,security_model=[mapped|passthrough|none]\n"
-    "        [,writeout=immediate][,readonly]\n",
+    "        [,writeout=immediate][,readonly][,sock_fd=sock_fd]\n",
     QEMU_ARCH_ALL)
 
 STEXI
 
- at item -virtfs @var{fsdriver},path=@var{path},mount_tag=@var{mount_tag},security_model=@var{security_model}[,writeout=@var{writeout}][,readonly]
+ at item -virtfs @var{fsdriver}[,path=@var{path}],mount_tag=@var{mount_tag}[,security_model=@var{security_model}][,writeout=@var{writeout}][,readonly][,sock_fd=@var{sock_fd}]
 @findex -virtfs
 
 The general form of a Virtual File system pass-through options are:
 @table @option
 @item @var{fsdriver}
 This option specifies the fs driver backend to use.
-Currently "local" and "handle" file system drivers are supported.
+Currently "local", "handle" and "proxy" file system drivers are supported.
 @item id=@var{id}
 Specifies identifier for this device
 @item path=@var{path}
@@ -639,7 +643,7 @@ file attributes. Directories exported by this security model cannot
 interact with other unix tools. "none" security model is same as
 passthrough except the sever won't report failures if it fails to
 set file attributes like ownership. Security model is mandatory only
-for local fsdriver. Other fsdrivers (like handle) don't take security
+for local fsdriver. Other fsdrivers (like handle, proxy) don't take security
 model as a parameter.
 @item writeout=@var{writeout}
 This is an optional argument. The only supported value is "immediate".
@@ -649,6 +653,9 @@ reported as written by the storage subsystem.
 @item readonly
 Enables exporting 9p share as a readonly mount for guests. By default
 read-write access is given.
+ at item sock_fd
+Enables proxy filesystem driver to use passed 'sock_fd' as the socket
+descriptor for interfacing with virtfs-proxy-helper
 @end table
 ETEXI
 
commit d090e452d4a0e30b59f983dfc5cde190b6088899
Author: M. Mohan Kumar <mohan at in.ibm.com>
Date:   Wed Dec 14 13:58:46 2011 +0530

    hw/9pfs: Proxy getversion
    
    Add proxy getversion to get generation number
    
    Signed-off-by: M. Mohan Kumar <mohan at in.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 703ac85..52d748d 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -28,6 +28,11 @@
 #include <sys/vfs.h>
 #include <sys/stat.h>
 #include <attr/xattr.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#ifdef CONFIG_LINUX_MAGIC_H
+#include <linux/magic.h>
+#endif
 #include "qemu-common.h"
 #include "virtio-9p-marshal.h"
 #include "hw/9pfs/virtio-9p-proxy.h"
@@ -35,6 +40,19 @@
 
 #define PROGNAME "virtfs-proxy-helper"
 
+#ifndef XFS_SUPER_MAGIC
+#define XFS_SUPER_MAGIC  0x58465342
+#endif
+#ifndef EXT2_SUPER_MAGIC
+#define EXT2_SUPER_MAGIC 0xEF53
+#endif
+#ifndef REISERFS_SUPER_MAGIC
+#define REISERFS_SUPER_MAGIC 0x52654973
+#endif
+#ifndef BTRFS_SUPER_MAGIC
+#define BTRFS_SUPER_MAGIC 0x9123683E
+#endif
+
 static struct option helper_opts[] = {
     {"fd", required_argument, NULL, 'f'},
     {"path", required_argument, NULL, 'p'},
@@ -42,6 +60,7 @@ static struct option helper_opts[] = {
 };
 
 static bool is_daemon;
+static bool get_version; /* IOC getversion IOCTL supported */
 
 static void do_log(int loglevel, const char *format, ...)
 {
@@ -330,6 +349,49 @@ static int send_response(int sock, struct iovec *iovec, int size)
     return 0;
 }
 
+/*
+ * gets generation number
+ * returns -errno on failure and sizeof(generation number) on success
+ */
+static int do_getversion(struct iovec *iovec, struct iovec *out_iovec)
+{
+    uint64_t version;
+    int retval = -ENOTTY;
+#ifdef FS_IOC_GETVERSION
+    int fd;
+    V9fsString path;
+#endif
+
+
+    /* no need to issue ioctl */
+    if (!get_version) {
+        version = 0;
+        retval = proxy_marshal(out_iovec, PROXY_HDR_SZ, "q", version);
+        return retval;
+    }
+#ifdef FS_IOC_GETVERSION
+    retval = proxy_unmarshal(iovec, PROXY_HDR_SZ, "s", &path);
+    if (retval < 0) {
+        return retval;
+    }
+
+    fd = open(path.data, O_RDONLY);
+    if (fd < 0) {
+        retval = -errno;
+        goto err_out;
+    }
+    if (ioctl(fd, FS_IOC_GETVERSION, &version) < 0) {
+        retval = -errno;
+    } else {
+        retval = proxy_marshal(out_iovec, PROXY_HDR_SZ, "q", version);
+    }
+    close(fd);
+err_out:
+    v9fs_string_free(&path);
+#endif
+    return retval;
+}
+
 static int do_getxattr(int type, struct iovec *iovec, struct iovec *out_iovec)
 {
     int size = 0, offset, retval;
@@ -673,6 +735,7 @@ static int process_reply(int sock, int type,
     case T_READLINK:
     case T_LGETXATTR:
     case T_LLISTXATTR:
+    case T_GETVERSION:
         if (send_response(sock, out_iovec, retval) < 0) {
             return -1;
         }
@@ -855,6 +918,9 @@ static int process_requests(int sock)
             v9fs_string_free(&path);
             v9fs_string_free(&name);
             break;
+        case T_GETVERSION:
+            retval = do_getversion(&in_iovec, &out_iovec);
+            break;
         default:
             goto err_out;
             break;
@@ -876,6 +942,10 @@ int main(int argc, char **argv)
     char *rpath = NULL;
     struct stat stbuf;
     int c, option_index;
+#ifdef FS_IOC_GETVERSION
+    int retval;
+    struct statfs st_fs;
+#endif
 
     is_daemon = true;
     sock = -1;
@@ -932,6 +1002,22 @@ int main(int argc, char **argv)
 
     do_log(LOG_INFO, "Started\n");
 
+    get_version = false;
+#ifdef FS_IOC_GETVERSION
+    /* check whether underlying FS support IOC_GETVERSION */
+    retval = statfs(rpath, &st_fs);
+    if (!retval) {
+        switch (st_fs.f_type) {
+        case EXT2_SUPER_MAGIC:
+        case BTRFS_SUPER_MAGIC:
+        case REISERFS_SUPER_MAGIC:
+        case XFS_SUPER_MAGIC:
+            get_version = true;
+            break;
+        }
+    }
+#endif
+
     if (chdir("/") < 0) {
         do_perror("chdir");
         goto error;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 22e9b68..415bd21 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -243,6 +243,9 @@ static int v9fs_receive_response(V9fsProxy *proxy, int type,
         v9fs_string_free(&xattr);
         break;
     }
+    case T_GETVERSION:
+        proxy_unmarshal(reply, PROXY_HDR_SZ, "q", response);
+        break;
     default:
         return -1;
     }
@@ -509,6 +512,14 @@ static int v9fs_request(V9fsProxy *proxy, int type,
             header.type = T_LREMOVEXATTR;
         }
         break;
+    case T_GETVERSION:
+        path = va_arg(ap, V9fsString *);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_GETVERSION;
+        }
+        break;
     default:
         error_report("Invalid type %d\n", type);
         retval = -EINVAL;
@@ -559,6 +570,7 @@ static int v9fs_request(V9fsProxy *proxy, int type,
     case T_LSTAT:
     case T_READLINK:
     case T_STATFS:
+    case T_GETVERSION:
         if (v9fs_receive_response(proxy, type, &retval, response) < 0) {
             goto close_error;
         }
@@ -1064,6 +1076,25 @@ static int proxy_unlinkat(FsContext *ctx, V9fsPath *dir,
     return ret;
 }
 
+static int proxy_ioc_getversion(FsContext *fs_ctx, V9fsPath *path,
+                                mode_t st_mode, uint64_t *st_gen)
+{
+    int err;
+
+    /* Do not try to open special files like device nodes, fifos etc
+     * we can get fd for regular files and directories only
+     */
+    if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) {
+        return 0;
+    }
+    err = v9fs_request(fs_ctx->private, T_GETVERSION, st_gen, "s", path);
+    if (err < 0) {
+        errno = -err;
+        err = -1;
+    }
+    return err;
+}
+
 static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs)
 {
     const char *sock_fd = qemu_opt_get(opts, "sock_fd");
@@ -1098,6 +1129,7 @@ static int proxy_init(FsContext *ctx)
     qemu_mutex_init(&proxy->mutex);
 
     ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
+    ctx->exops.get_st_gen = proxy_ioc_getversion;
     return 0;
 }
 
diff --git a/hw/9pfs/virtio-9p-proxy.h b/hw/9pfs/virtio-9p-proxy.h
index 7b3b0a9..005c1ad 100644
--- a/hw/9pfs/virtio-9p-proxy.h
+++ b/hw/9pfs/virtio-9p-proxy.h
@@ -58,6 +58,7 @@ enum {
     T_LLISTXATTR,
     T_LSETXATTR,
     T_LREMOVEXATTR,
+    T_GETVERSION,
 };
 
 typedef struct {
commit d52b09e475317a723273e1a236e6d5e27613c634
Author: M. Mohan Kumar <mohan at in.ibm.com>
Date:   Wed Dec 14 13:58:46 2011 +0530

    hw/9pfs: xattr interfaces in proxy filesystem driver
    
    Add xattr support for proxy FS
    
    Signed-off-by: M. Mohan Kumar <mohan at in.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 204bb4a..703ac85 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -27,6 +27,7 @@
 #include <stdbool.h>
 #include <sys/vfs.h>
 #include <sys/stat.h>
+#include <attr/xattr.h>
 #include "qemu-common.h"
 #include "virtio-9p-marshal.h"
 #include "hw/9pfs/virtio-9p-proxy.h"
@@ -329,6 +330,62 @@ static int send_response(int sock, struct iovec *iovec, int size)
     return 0;
 }
 
+static int do_getxattr(int type, struct iovec *iovec, struct iovec *out_iovec)
+{
+    int size = 0, offset, retval;
+    V9fsString path, name, xattr;
+
+    v9fs_string_init(&xattr);
+    v9fs_string_init(&path);
+    retval = proxy_unmarshal(iovec, PROXY_HDR_SZ, "ds", &size, &path);
+    if (retval < 0) {
+        return retval;
+    }
+    offset = PROXY_HDR_SZ + retval;
+
+    if (size) {
+        xattr.data = g_malloc(size);
+        xattr.size = size;
+    }
+    switch (type) {
+    case T_LGETXATTR:
+        v9fs_string_init(&name);
+        retval = proxy_unmarshal(iovec, offset, "s", &name);
+        if (retval > 0) {
+            retval = lgetxattr(path.data, name.data, xattr.data, size);
+            if (retval < 0) {
+                retval = -errno;
+            } else {
+                xattr.size = retval;
+            }
+        }
+        v9fs_string_free(&name);
+        break;
+    case T_LLISTXATTR:
+        retval = llistxattr(path.data, xattr.data, size);
+        if (retval < 0) {
+            retval = -errno;
+        } else {
+            xattr.size = retval;
+        }
+        break;
+    }
+    if (retval < 0) {
+        goto err_out;
+    }
+
+    if (!size) {
+        proxy_marshal(out_iovec, PROXY_HDR_SZ, "d", retval);
+        retval = sizeof(retval);
+    } else {
+        retval = proxy_marshal(out_iovec, PROXY_HDR_SZ, "s", &xattr);
+    }
+err_out:
+    v9fs_string_free(&xattr);
+    v9fs_string_free(&path);
+    return retval;
+}
+
 static void stat_to_prstat(ProxyStat *pr_stat, struct stat *stat)
 {
     memset(pr_stat, 0, sizeof(*pr_stat));
@@ -605,6 +662,8 @@ static int process_reply(int sock, int type,
     case T_UTIME:
     case T_RENAME:
     case T_REMOVE:
+    case T_LSETXATTR:
+    case T_LREMOVEXATTR:
         if (send_status(sock, out_iovec, retval) < 0) {
             return -1;
         }
@@ -612,6 +671,8 @@ static int process_reply(int sock, int type,
     case T_LSTAT:
     case T_STATFS:
     case T_READLINK:
+    case T_LGETXATTR:
+    case T_LLISTXATTR:
         if (send_response(sock, out_iovec, retval) < 0) {
             return -1;
         }
@@ -625,10 +686,13 @@ static int process_reply(int sock, int type,
 
 static int process_requests(int sock)
 {
+    int flags;
+    int size = 0;
     int retval = 0;
     uint64_t offset;
     ProxyHeader header;
     int mode, uid, gid;
+    V9fsString name, value;
     struct timespec spec[2];
     V9fsString oldpath, path;
     struct iovec in_iovec, out_iovec;
@@ -756,6 +820,41 @@ static int process_requests(int sock)
             }
             v9fs_string_free(&path);
             break;
+        case T_LGETXATTR:
+        case T_LLISTXATTR:
+            retval = do_getxattr(header.type, &in_iovec, &out_iovec);
+            break;
+        case T_LSETXATTR:
+            v9fs_string_init(&path);
+            v9fs_string_init(&name);
+            v9fs_string_init(&value);
+            retval = proxy_unmarshal(&in_iovec, PROXY_HDR_SZ, "sssdd", &path,
+                                     &name, &value, &size, &flags);
+            if (retval > 0) {
+                retval = lsetxattr(path.data,
+                                   name.data, value.data, size, flags);
+                if (retval < 0) {
+                    retval = -errno;
+                }
+            }
+            v9fs_string_free(&path);
+            v9fs_string_free(&name);
+            v9fs_string_free(&value);
+            break;
+        case T_LREMOVEXATTR:
+            v9fs_string_init(&path);
+            v9fs_string_init(&name);
+            retval = proxy_unmarshal(&in_iovec,
+                                     PROXY_HDR_SZ, "ss", &path, &name);
+            if (retval > 0) {
+                retval = lremovexattr(path.data, name.data);
+                if (retval < 0) {
+                    retval = -errno;
+                }
+            }
+            v9fs_string_free(&path);
+            v9fs_string_free(&name);
+            break;
         default:
             goto err_out;
             break;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index ef118ff..22e9b68 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -234,6 +234,15 @@ static int v9fs_receive_response(V9fsProxy *proxy, int type,
         v9fs_string_free(&target);
         break;
     }
+    case T_LGETXATTR:
+    case T_LLISTXATTR: {
+        V9fsString xattr;
+        v9fs_string_init(&xattr);
+        retval = proxy_unmarshal(reply, PROXY_HDR_SZ, "s", &xattr);
+        memcpy(response, xattr.data, xattr.size);
+        v9fs_string_free(&xattr);
+        break;
+    }
     default:
         return -1;
     }
@@ -291,6 +300,7 @@ static int v9fs_request(V9fsProxy *proxy, int type,
     ProxyHeader header = { 0, 0};
     struct timespec spec[2];
     int flags, mode, uid, gid;
+    V9fsString *name, *value;
     V9fsString *path, *oldpath;
     struct iovec *iovec = NULL, *reply = NULL;
 
@@ -457,6 +467,48 @@ static int v9fs_request(V9fsProxy *proxy, int type,
             header.type = T_REMOVE;
         }
         break;
+    case T_LGETXATTR:
+        size = va_arg(ap, int);
+        path = va_arg(ap, V9fsString *);
+        name = va_arg(ap, V9fsString *);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ,
+                                    "dss", size, path, name);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_LGETXATTR;
+        }
+        break;
+    case T_LLISTXATTR:
+        size = va_arg(ap, int);
+        path = va_arg(ap, V9fsString *);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ds", size, path);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_LLISTXATTR;
+        }
+        break;
+    case T_LSETXATTR:
+        path = va_arg(ap, V9fsString *);
+        name = va_arg(ap, V9fsString *);
+        value = va_arg(ap, V9fsString *);
+        size = va_arg(ap, int);
+        flags = va_arg(ap, int);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sssdd",
+                                    path, name, value, size, flags);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_LSETXATTR;
+        }
+        break;
+    case T_LREMOVEXATTR:
+        path = va_arg(ap, V9fsString *);
+        name = va_arg(ap, V9fsString *);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ss", path, name);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_LREMOVEXATTR;
+        }
+        break;
     default:
         error_report("Invalid type %d\n", type);
         retval = -EINVAL;
@@ -498,6 +550,8 @@ static int v9fs_request(V9fsProxy *proxy, int type,
     case T_TRUNCATE:
     case T_UTIME:
     case T_REMOVE:
+    case T_LSETXATTR:
+    case T_LREMOVEXATTR:
         if (v9fs_receive_status(proxy, reply, &retval) < 0) {
             goto close_error;
         }
@@ -509,6 +563,18 @@ static int v9fs_request(V9fsProxy *proxy, int type,
             goto close_error;
         }
         break;
+    case T_LGETXATTR:
+    case T_LLISTXATTR:
+        if (!size) {
+            if (v9fs_receive_status(proxy, reply, &retval) < 0) {
+                goto close_error;
+            }
+        } else {
+            if (v9fs_receive_response(proxy, type, &retval, response) < 0) {
+                goto close_error;
+            }
+        }
+        break;
     }
 
 err_out:
@@ -884,29 +950,71 @@ static int proxy_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
 static ssize_t proxy_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
                                const char *name, void *value, size_t size)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    V9fsString xname;
+
+    v9fs_string_init(&xname);
+    v9fs_string_sprintf(&xname, "%s", name);
+    retval = v9fs_request(ctx->private, T_LGETXATTR, value, "dss", size,
+                          fs_path, &xname);
+    v9fs_string_free(&xname);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static ssize_t proxy_llistxattr(FsContext *ctx, V9fsPath *fs_path,
                                 void *value, size_t size)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    retval = v9fs_request(ctx->private, T_LLISTXATTR, value, "ds", size,
+                        fs_path);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static int proxy_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
                            void *value, size_t size, int flags)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    V9fsString xname, xvalue;
+
+    v9fs_string_init(&xname);
+    v9fs_string_sprintf(&xname, "%s", name);
+
+    v9fs_string_init(&xvalue);
+    xvalue.size = size;
+    xvalue.data = g_malloc(size);
+    memcpy(xvalue.data, value, size);
+
+    retval = v9fs_request(ctx->private, T_LSETXATTR, value, "sssdd",
+                          fs_path, &xname, &xvalue, size, flags);
+    v9fs_string_free(&xname);
+    v9fs_string_free(&xvalue);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static int proxy_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
                               const char *name)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    V9fsString xname;
+
+    v9fs_string_init(&xname);
+    v9fs_string_sprintf(&xname, "%s", name);
+    retval = v9fs_request(ctx->private, T_LREMOVEXATTR, NULL, "ss",
+                          fs_path, &xname);
+    v9fs_string_free(&xname);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static int proxy_name_to_path(FsContext *ctx, V9fsPath *dir_path,
diff --git a/hw/9pfs/virtio-9p-proxy.h b/hw/9pfs/virtio-9p-proxy.h
index bc5ba73..7b3b0a9 100644
--- a/hw/9pfs/virtio-9p-proxy.h
+++ b/hw/9pfs/virtio-9p-proxy.h
@@ -54,6 +54,10 @@ enum {
     T_UTIME,
     T_RENAME,
     T_REMOVE,
+    T_LGETXATTR,
+    T_LLISTXATTR,
+    T_LSETXATTR,
+    T_LREMOVEXATTR,
 };
 
 typedef struct {
commit ea75fc4ec581ab4dd072ab208f9689fa86ab73f3
Author: M. Mohan Kumar <mohan at in.ibm.com>
Date:   Wed Dec 14 13:58:45 2011 +0530

    hw/9pfs: File ownership and others
    
    Add file ownership interfaces like chmod/chown, utime update, rename,
    remove and truncating files for proxy FS
    
    Signed-off-by: M. Mohan Kumar <mohan at in.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/Makefile b/Makefile
index 51591c3..c665b72 100644
--- a/Makefile
+++ b/Makefile
@@ -155,7 +155,7 @@ qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
 qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
 qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
 
-fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o
+fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o oslib-posix.o $(trace-obj-y)
 fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
 
 qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 9b3c833..204bb4a 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -599,6 +599,12 @@ static int process_reply(int sock, int type,
     case T_MKDIR:
     case T_SYMLINK:
     case T_LINK:
+    case T_CHMOD:
+    case T_CHOWN:
+    case T_TRUNCATE:
+    case T_UTIME:
+    case T_RENAME:
+    case T_REMOVE:
         if (send_status(sock, out_iovec, retval) < 0) {
             return -1;
         }
@@ -620,7 +626,10 @@ static int process_reply(int sock, int type,
 static int process_requests(int sock)
 {
     int retval = 0;
+    uint64_t offset;
     ProxyHeader header;
+    int mode, uid, gid;
+    struct timespec spec[2];
     V9fsString oldpath, path;
     struct iovec in_iovec, out_iovec;
 
@@ -673,6 +682,80 @@ static int process_requests(int sock)
         case T_READLINK:
             retval = do_readlink(&in_iovec, &out_iovec);
             break;
+        case T_CHMOD:
+            v9fs_string_init(&path);
+            retval = proxy_unmarshal(&in_iovec, PROXY_HDR_SZ,
+                                     "sd", &path, &mode);
+            if (retval > 0) {
+                retval = chmod(path.data, mode);
+                if (retval < 0) {
+                    retval = -errno;
+                }
+            }
+            v9fs_string_free(&path);
+            break;
+        case T_CHOWN:
+            v9fs_string_init(&path);
+            retval = proxy_unmarshal(&in_iovec, PROXY_HDR_SZ, "sdd", &path,
+                                     &uid, &gid);
+            if (retval > 0) {
+                retval = lchown(path.data, uid, gid);
+                if (retval < 0) {
+                    retval = -errno;
+                }
+            }
+            v9fs_string_free(&path);
+            break;
+        case T_TRUNCATE:
+            v9fs_string_init(&path);
+            retval = proxy_unmarshal(&in_iovec, PROXY_HDR_SZ, "sq",
+                                     &path, &offset);
+            if (retval > 0) {
+                retval = truncate(path.data, offset);
+                if (retval < 0) {
+                    retval = -errno;
+                }
+            }
+            v9fs_string_free(&path);
+            break;
+        case T_UTIME:
+            v9fs_string_init(&path);
+            retval = proxy_unmarshal(&in_iovec, PROXY_HDR_SZ, "sqqqq", &path,
+                                     &spec[0].tv_sec, &spec[0].tv_nsec,
+                                     &spec[1].tv_sec, &spec[1].tv_nsec);
+            if (retval > 0) {
+                retval = qemu_utimens(path.data, spec);
+                if (retval < 0) {
+                    retval = -errno;
+                }
+            }
+            v9fs_string_free(&path);
+            break;
+        case T_RENAME:
+            v9fs_string_init(&path);
+            v9fs_string_init(&oldpath);
+            retval = proxy_unmarshal(&in_iovec, PROXY_HDR_SZ,
+                                     "ss", &oldpath, &path);
+            if (retval > 0) {
+                retval = rename(oldpath.data, path.data);
+                if (retval < 0) {
+                    retval = -errno;
+                }
+            }
+            v9fs_string_free(&oldpath);
+            v9fs_string_free(&path);
+            break;
+        case T_REMOVE:
+            v9fs_string_init(&path);
+            retval = proxy_unmarshal(&in_iovec, PROXY_HDR_SZ, "s", &path);
+            if (retval > 0) {
+                retval = remove(path.data);
+                if (retval < 0) {
+                    retval = -errno;
+                }
+            }
+            v9fs_string_free(&path);
+            break;
         default:
             goto err_out;
             break;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 10e2c59..ef118ff 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -287,7 +287,9 @@ static int v9fs_request(V9fsProxy *proxy, int type,
     va_list ap;
     int size = 0;
     int retval = 0;
+    uint64_t offset;
     ProxyHeader header = { 0, 0};
+    struct timespec spec[2];
     int flags, mode, uid, gid;
     V9fsString *path, *oldpath;
     struct iovec *iovec = NULL, *reply = NULL;
@@ -396,6 +398,65 @@ static int v9fs_request(V9fsProxy *proxy, int type,
             header.type = T_STATFS;
         }
         break;
+    case T_CHMOD:
+        path = va_arg(ap, V9fsString *);
+        mode = va_arg(ap, int);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sd", path, mode);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_CHMOD;
+        }
+        break;
+    case T_CHOWN:
+        path = va_arg(ap, V9fsString *);
+        uid = va_arg(ap, int);
+        gid = va_arg(ap, int);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sdd", path, uid, gid);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_CHOWN;
+        }
+        break;
+    case T_TRUNCATE:
+        path = va_arg(ap, V9fsString *);
+        offset = va_arg(ap, uint64_t);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sq", path, offset);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_TRUNCATE;
+        }
+        break;
+    case T_UTIME:
+        path = va_arg(ap, V9fsString *);
+        spec[0].tv_sec = va_arg(ap, long);
+        spec[0].tv_nsec = va_arg(ap, long);
+        spec[1].tv_sec = va_arg(ap, long);
+        spec[1].tv_nsec = va_arg(ap, long);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sqqqq", path,
+                                    spec[0].tv_sec, spec[1].tv_nsec,
+                                    spec[1].tv_sec, spec[1].tv_nsec);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_UTIME;
+        }
+        break;
+    case T_RENAME:
+        oldpath = va_arg(ap, V9fsString *);
+        path = va_arg(ap, V9fsString *);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ss", oldpath, path);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_RENAME;
+        }
+        break;
+    case T_REMOVE:
+        path = va_arg(ap, V9fsString *);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_REMOVE;
+        }
+        break;
     default:
         error_report("Invalid type %d\n", type);
         retval = -EINVAL;
@@ -431,6 +492,12 @@ static int v9fs_request(V9fsProxy *proxy, int type,
     case T_MKDIR:
     case T_SYMLINK:
     case T_LINK:
+    case T_CHMOD:
+    case T_CHOWN:
+    case T_RENAME:
+    case T_TRUNCATE:
+    case T_UTIME:
+    case T_REMOVE:
         if (v9fs_receive_status(proxy, reply, &retval) < 0) {
             goto close_error;
         }
@@ -591,8 +658,13 @@ static ssize_t proxy_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
 
 static int proxy_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    retval = v9fs_request(fs_ctx->private, T_CHMOD, NULL, "sd",
+                          fs_path, credp->fc_mode);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static int proxy_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
@@ -710,34 +782,74 @@ static int proxy_link(FsContext *ctx, V9fsPath *oldpath,
 
 static int proxy_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+
+    retval = v9fs_request(ctx->private, T_TRUNCATE, NULL, "sq", fs_path, size);
+    if (retval < 0) {
+        errno = -retval;
+        return -1;
+    }
+    return 0;
 }
 
 static int proxy_rename(FsContext *ctx, const char *oldpath,
                         const char *newpath)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    V9fsString oldname, newname;
+
+    v9fs_string_init(&oldname);
+    v9fs_string_init(&newname);
+
+    v9fs_string_sprintf(&oldname, "%s", oldpath);
+    v9fs_string_sprintf(&newname, "%s", newpath);
+    retval = v9fs_request(ctx->private, T_RENAME, NULL, "ss",
+                          &oldname, &newname);
+    v9fs_string_free(&oldname);
+    v9fs_string_free(&newname);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static int proxy_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    retval = v9fs_request(fs_ctx->private, T_CHOWN, NULL, "sdd",
+                          fs_path, credp->fc_uid, credp->fc_gid);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static int proxy_utimensat(FsContext *s, V9fsPath *fs_path,
                            const struct timespec *buf)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    retval = v9fs_request(s->private, T_UTIME, NULL, "sqqqq",
+                          fs_path,
+                          buf[0].tv_sec, buf[0].tv_nsec,
+                          buf[1].tv_sec, buf[1].tv_nsec);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static int proxy_remove(FsContext *ctx, const char *path)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    V9fsString name;
+    v9fs_string_init(&name);
+    v9fs_string_sprintf(&name, "%s", path);
+    retval = v9fs_request(ctx->private, T_REMOVE, NULL, "s", &name);
+    v9fs_string_free(&name);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static int proxy_fsync(FsContext *ctx, int fid_type,
diff --git a/hw/9pfs/virtio-9p-proxy.h b/hw/9pfs/virtio-9p-proxy.h
index da03341..bc5ba73 100644
--- a/hw/9pfs/virtio-9p-proxy.h
+++ b/hw/9pfs/virtio-9p-proxy.h
@@ -48,6 +48,12 @@ enum {
     T_LSTAT,
     T_READLINK,
     T_STATFS,
+    T_CHMOD,
+    T_CHOWN,
+    T_TRUNCATE,
+    T_UTIME,
+    T_RENAME,
+    T_REMOVE,
 };
 
 typedef struct {
commit b178adc3e78fa1ad274f8d78e43443c39f862143
Author: M. Mohan Kumar <mohan at in.ibm.com>
Date:   Wed Dec 14 13:58:45 2011 +0530

    hw/9pfs: Add stat/readlink/statfs for proxy FS
    
    Signed-off-by: M. Mohan Kumar <mohan at in.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 83fbae7..9b3c833 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -25,6 +25,8 @@
 #include <sys/fsuid.h>
 #include <stdarg.h>
 #include <stdbool.h>
+#include <sys/vfs.h>
+#include <sys/stat.h>
 #include "qemu-common.h"
 #include "virtio-9p-marshal.h"
 #include "hw/9pfs/virtio-9p-proxy.h"
@@ -286,6 +288,172 @@ static int setfsugid(int uid, int gid)
 }
 
 /*
+ * send response in two parts
+ * 1) ProxyHeader
+ * 2) Response or error status
+ * This function should be called with marshaled response
+ * send_response constructs header part and error part only.
+ * send response sends {ProxyHeader,Response} if the request was success
+ * otherwise sends {ProxyHeader,error status}
+ */
+static int send_response(int sock, struct iovec *iovec, int size)
+{
+    int retval;
+    ProxyHeader header;
+
+    /*
+     * If response size exceeds available iovec->iov_len,
+     * we return ENOBUFS
+     */
+    if (size > PROXY_MAX_IO_SZ) {
+        size = -ENOBUFS;
+    }
+
+    if (size < 0) {
+        /*
+         * In case of error we would not have got the error encoded
+         * already so encode the error here.
+         */
+        header.type = T_ERROR;
+        header.size = sizeof(size);
+        proxy_marshal(iovec, PROXY_HDR_SZ, "d", size);
+    } else {
+        header.type = T_SUCCESS;
+        header.size = size;
+    }
+    proxy_marshal(iovec, 0, "dd", header.type, header.size);
+    retval = socket_write(sock, iovec->iov_base, header.size + PROXY_HDR_SZ);
+    if (retval < 0) {
+        return retval;;
+    }
+    return 0;
+}
+
+static void stat_to_prstat(ProxyStat *pr_stat, struct stat *stat)
+{
+    memset(pr_stat, 0, sizeof(*pr_stat));
+    pr_stat->st_dev = stat->st_dev;
+    pr_stat->st_ino = stat->st_ino;
+    pr_stat->st_nlink = stat->st_nlink;
+    pr_stat->st_mode = stat->st_mode;
+    pr_stat->st_uid = stat->st_uid;
+    pr_stat->st_gid = stat->st_gid;
+    pr_stat->st_rdev = stat->st_rdev;
+    pr_stat->st_size = stat->st_size;
+    pr_stat->st_blksize = stat->st_blksize;
+    pr_stat->st_blocks = stat->st_blocks;
+    pr_stat->st_atim_sec = stat->st_atim.tv_sec;
+    pr_stat->st_atim_nsec = stat->st_atim.tv_nsec;
+    pr_stat->st_mtim_sec = stat->st_mtim.tv_sec;
+    pr_stat->st_mtim_nsec = stat->st_mtim.tv_nsec;
+    pr_stat->st_ctim_sec = stat->st_ctim.tv_sec;
+    pr_stat->st_ctim_nsec = stat->st_ctim.tv_nsec;
+}
+
+static void statfs_to_prstatfs(ProxyStatFS *pr_stfs, struct statfs *stfs)
+{
+    memset(pr_stfs, 0, sizeof(*pr_stfs));
+    pr_stfs->f_type = stfs->f_type;
+    pr_stfs->f_bsize = stfs->f_bsize;
+    pr_stfs->f_blocks = stfs->f_blocks;
+    pr_stfs->f_bfree = stfs->f_bfree;
+    pr_stfs->f_bavail = stfs->f_bavail;
+    pr_stfs->f_files = stfs->f_files;
+    pr_stfs->f_ffree = stfs->f_ffree;
+    pr_stfs->f_fsid[0] = stfs->f_fsid.__val[0];
+    pr_stfs->f_fsid[1] = stfs->f_fsid.__val[1];
+    pr_stfs->f_namelen = stfs->f_namelen;
+    pr_stfs->f_frsize = stfs->f_frsize;
+}
+
+/*
+ * Gets stat/statfs information and packs in out_iovec structure
+ * on success returns number of bytes packed in out_iovec struture
+ * otherwise returns -errno
+ */
+static int do_stat(int type, struct iovec *iovec, struct iovec *out_iovec)
+{
+    int retval;
+    V9fsString path;
+    ProxyStat pr_stat;
+    ProxyStatFS pr_stfs;
+    struct stat st_buf;
+    struct statfs stfs_buf;
+
+    v9fs_string_init(&path);
+    retval = proxy_unmarshal(iovec, PROXY_HDR_SZ, "s", &path);
+    if (retval < 0) {
+        return retval;
+    }
+
+    switch (type) {
+    case T_LSTAT:
+        retval = lstat(path.data, &st_buf);
+        if (retval < 0) {
+            retval = -errno;
+        } else {
+            stat_to_prstat(&pr_stat, &st_buf);
+            retval = proxy_marshal(out_iovec, PROXY_HDR_SZ,
+                                   "qqqdddqqqqqqqqqq", pr_stat.st_dev,
+                                   pr_stat.st_ino, pr_stat.st_nlink,
+                                   pr_stat.st_mode, pr_stat.st_uid,
+                                   pr_stat.st_gid, pr_stat.st_rdev,
+                                   pr_stat.st_size, pr_stat.st_blksize,
+                                   pr_stat.st_blocks,
+                                   pr_stat.st_atim_sec, pr_stat.st_atim_nsec,
+                                   pr_stat.st_mtim_sec, pr_stat.st_mtim_nsec,
+                                   pr_stat.st_ctim_sec, pr_stat.st_ctim_nsec);
+        }
+        break;
+    case T_STATFS:
+        retval = statfs(path.data, &stfs_buf);
+        if (retval < 0) {
+            retval = -errno;
+        } else {
+            statfs_to_prstatfs(&pr_stfs, &stfs_buf);
+            retval = proxy_marshal(out_iovec, PROXY_HDR_SZ,
+                                   "qqqqqqqqqqq", pr_stfs.f_type,
+                                   pr_stfs.f_bsize, pr_stfs.f_blocks,
+                                   pr_stfs.f_bfree, pr_stfs.f_bavail,
+                                   pr_stfs.f_files, pr_stfs.f_ffree,
+                                   pr_stfs.f_fsid[0], pr_stfs.f_fsid[1],
+                                   pr_stfs.f_namelen, pr_stfs.f_frsize);
+        }
+        break;
+    }
+    v9fs_string_free(&path);
+    return retval;
+}
+
+static int do_readlink(struct iovec *iovec, struct iovec *out_iovec)
+{
+    char *buffer;
+    int size, retval;
+    V9fsString target, path;
+
+    v9fs_string_init(&path);
+    retval = proxy_unmarshal(iovec, PROXY_HDR_SZ, "sd", &path, &size);
+    if (retval < 0) {
+        v9fs_string_free(&path);
+        return retval;
+    }
+    buffer = g_malloc(size);
+    v9fs_string_init(&target);
+    retval = readlink(path.data, buffer, size);
+    if (retval > 0) {
+        buffer[retval] = '\0';
+        v9fs_string_sprintf(&target, "%s", buffer);
+        retval = proxy_marshal(out_iovec, PROXY_HDR_SZ, "s", &target);
+    } else {
+        retval = -errno;
+    }
+    g_free(buffer);
+    v9fs_string_free(&target);
+    v9fs_string_free(&path);
+    return retval;
+}
+
+/*
  * create other filesystem objects and send 0 on success
  * return -errno on error
  */
@@ -435,6 +603,13 @@ static int process_reply(int sock, int type,
             return -1;
         }
         break;
+    case T_LSTAT:
+    case T_STATFS:
+    case T_READLINK:
+        if (send_response(sock, out_iovec, retval) < 0) {
+            return -1;
+        }
+        break;
     default:
         return -1;
         break;
@@ -491,6 +666,13 @@ static int process_requests(int sock)
             v9fs_string_free(&oldpath);
             v9fs_string_free(&path);
             break;
+        case T_LSTAT:
+        case T_STATFS:
+            retval = do_stat(header.type, &in_iovec, &out_iovec);
+            break;
+        case T_READLINK:
+            retval = do_readlink(&in_iovec, &out_iovec);
+            break;
         default:
             goto err_out;
             break;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 6904a1d..10e2c59 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -101,6 +101,148 @@ static ssize_t socket_read(int sockfd, void *buff, size_t size)
     return total;
 }
 
+/* Converts proxy_statfs to VFS statfs structure */
+static void prstatfs_to_statfs(struct statfs *stfs, ProxyStatFS *prstfs)
+{
+    memset(stfs, 0, sizeof(*stfs));
+    stfs->f_type = prstfs->f_type;
+    stfs->f_bsize = prstfs->f_bsize;
+    stfs->f_blocks = prstfs->f_blocks;
+    stfs->f_bfree = prstfs->f_bfree;
+    stfs->f_bavail = prstfs->f_bavail;
+    stfs->f_files = prstfs->f_files;
+    stfs->f_ffree = prstfs->f_ffree;
+    stfs->f_fsid.__val[0] = prstfs->f_fsid[0] & 0xFFFFFFFFUL;
+    stfs->f_fsid.__val[1] = prstfs->f_fsid[1] >> 32 & 0xFFFFFFFFFUL;
+    stfs->f_namelen = prstfs->f_namelen;
+    stfs->f_frsize = prstfs->f_frsize;
+}
+
+/* Converts proxy_stat structure to VFS stat structure */
+static void prstat_to_stat(struct stat *stbuf, ProxyStat *prstat)
+{
+   memset(stbuf, 0, sizeof(*stbuf));
+   stbuf->st_dev = prstat->st_dev;
+   stbuf->st_ino = prstat->st_ino;
+   stbuf->st_nlink = prstat->st_nlink;
+   stbuf->st_mode = prstat->st_mode;
+   stbuf->st_uid = prstat->st_uid;
+   stbuf->st_gid = prstat->st_gid;
+   stbuf->st_rdev = prstat->st_rdev;
+   stbuf->st_size = prstat->st_size;
+   stbuf->st_blksize = prstat->st_blksize;
+   stbuf->st_blocks = prstat->st_blocks;
+   stbuf->st_atim.tv_sec = prstat->st_atim_sec;
+   stbuf->st_atim.tv_nsec = prstat->st_atim_nsec;
+   stbuf->st_mtime = prstat->st_mtim_sec;
+   stbuf->st_mtim.tv_nsec = prstat->st_mtim_nsec;
+   stbuf->st_ctime = prstat->st_ctim_sec;
+   stbuf->st_ctim.tv_nsec = prstat->st_ctim_nsec;
+}
+
+/*
+ * Response contains two parts
+ * {header, data}
+ * header.type == T_ERROR, data -> -errno
+ * header.type == T_SUCCESS, data -> response
+ * size of errno/response is given by header.size
+ * returns < 0, on transport error. response is
+ * valid only if status >= 0.
+ */
+static int v9fs_receive_response(V9fsProxy *proxy, int type,
+                                 int *status, void *response)
+{
+    int retval;
+    ProxyHeader header;
+    struct iovec *reply = &proxy->in_iovec;
+
+    *status = 0;
+    reply->iov_len = 0;
+    retval = socket_read(proxy->sockfd, reply->iov_base, PROXY_HDR_SZ);
+    if (retval < 0) {
+        return retval;
+    }
+    reply->iov_len = PROXY_HDR_SZ;
+    proxy_unmarshal(reply, 0, "dd", &header.type, &header.size);
+    /*
+     * if response size > PROXY_MAX_IO_SZ, read the response but ignore it and
+     * return -ENOBUFS
+     */
+    if (header.size > PROXY_MAX_IO_SZ) {
+        int count;
+        while (header.size > 0) {
+            count = MIN(PROXY_MAX_IO_SZ, header.size);
+            count = socket_read(proxy->sockfd, reply->iov_base, count);
+            if (count < 0) {
+                return count;
+            }
+            header.size -= count;
+        }
+        *status = -ENOBUFS;
+        return 0;
+    }
+
+    retval = socket_read(proxy->sockfd,
+                         reply->iov_base + PROXY_HDR_SZ, header.size);
+    if (retval < 0) {
+        return retval;
+    }
+    reply->iov_len += header.size;
+    /* there was an error during processing request */
+    if (header.type == T_ERROR) {
+        int ret;
+        ret = proxy_unmarshal(reply, PROXY_HDR_SZ, "d", status);
+        if (ret < 0) {
+            *status = ret;
+        }
+        return 0;
+    }
+
+    switch (type) {
+    case T_LSTAT: {
+        ProxyStat prstat;
+        retval = proxy_unmarshal(reply, PROXY_HDR_SZ,
+                                 "qqqdddqqqqqqqqqq", &prstat.st_dev,
+                                 &prstat.st_ino, &prstat.st_nlink,
+                                 &prstat.st_mode, &prstat.st_uid,
+                                 &prstat.st_gid, &prstat.st_rdev,
+                                 &prstat.st_size, &prstat.st_blksize,
+                                 &prstat.st_blocks,
+                                 &prstat.st_atim_sec, &prstat.st_atim_nsec,
+                                 &prstat.st_mtim_sec, &prstat.st_mtim_nsec,
+                                 &prstat.st_ctim_sec, &prstat.st_ctim_nsec);
+        prstat_to_stat(response, &prstat);
+        break;
+    }
+    case T_STATFS: {
+        ProxyStatFS prstfs;
+        retval = proxy_unmarshal(reply, PROXY_HDR_SZ,
+                                 "qqqqqqqqqqq", &prstfs.f_type,
+                                 &prstfs.f_bsize, &prstfs.f_blocks,
+                                 &prstfs.f_bfree, &prstfs.f_bavail,
+                                 &prstfs.f_files, &prstfs.f_ffree,
+                                 &prstfs.f_fsid[0], &prstfs.f_fsid[1],
+                                 &prstfs.f_namelen, &prstfs.f_frsize);
+        prstatfs_to_statfs(response, &prstfs);
+        break;
+    }
+    case T_READLINK: {
+        V9fsString target;
+        v9fs_string_init(&target);
+        retval = proxy_unmarshal(reply, PROXY_HDR_SZ, "s", &target);
+        strcpy(response, target.data);
+        v9fs_string_free(&target);
+        break;
+    }
+    default:
+        return -1;
+    }
+    if (retval < 0) {
+        *status  = retval;
+    }
+    return 0;
+}
+
 /*
  * return < 0 on transport error.
  * *status is valid only if return >= 0
@@ -143,6 +285,7 @@ static int v9fs_request(V9fsProxy *proxy, int type,
 {
     dev_t rdev;
     va_list ap;
+    int size = 0;
     int retval = 0;
     ProxyHeader header = { 0, 0};
     int flags, mode, uid, gid;
@@ -228,6 +371,31 @@ static int v9fs_request(V9fsProxy *proxy, int type,
             header.type = T_LINK;
         }
         break;
+    case T_LSTAT:
+        path = va_arg(ap, V9fsString *);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_LSTAT;
+        }
+        break;
+    case T_READLINK:
+        path = va_arg(ap, V9fsString *);
+        size = va_arg(ap, int);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sd", path, size);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_READLINK;
+        }
+        break;
+    case T_STATFS:
+        path = va_arg(ap, V9fsString *);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_STATFS;
+        }
+        break;
     default:
         error_report("Invalid type %d\n", type);
         retval = -EINVAL;
@@ -267,6 +435,13 @@ static int v9fs_request(V9fsProxy *proxy, int type,
             goto close_error;
         }
         break;
+    case T_LSTAT:
+    case T_READLINK:
+    case T_STATFS:
+        if (v9fs_receive_response(proxy, type, &retval, response) < 0) {
+            goto close_error;
+        }
+        break;
     }
 
 err_out:
@@ -282,15 +457,26 @@ close_error:
 
 static int proxy_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    retval = v9fs_request(fs_ctx->private, T_LSTAT, stbuf, "s", fs_path);
+    if (retval < 0) {
+        errno = -retval;
+        return -1;
+    }
+    return retval;
 }
 
 static ssize_t proxy_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
                               char *buf, size_t bufsz)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    retval = v9fs_request(fs_ctx->private, T_READLINK, buf, "sd",
+                          fs_path, bufsz);
+    if (retval < 0) {
+        errno = -retval;
+        return -1;
+    }
+    return strlen(buf);
 }
 
 static int proxy_close(FsContext *ctx, V9fsFidOpenState *fs)
@@ -513,8 +699,7 @@ static int proxy_link(FsContext *ctx, V9fsPath *oldpath,
     v9fs_string_init(&newpath);
     v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name);
 
-    retval = v9fs_request(ctx->private, T_LINK, NULL, "ss",
-                          oldpath, &newpath);
+    retval = v9fs_request(ctx->private, T_LINK, NULL, "ss", oldpath, &newpath);
     v9fs_string_free(&newpath);
     if (retval < 0) {
         errno = -retval;
@@ -575,8 +760,13 @@ static int proxy_fsync(FsContext *ctx, int fid_type,
 
 static int proxy_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    retval = v9fs_request(s->private, T_STATFS, stbuf, "s", fs_path);
+    if (retval < 0) {
+        errno = -retval;
+        return -1;
+    }
+    return retval;
 }
 
 static ssize_t proxy_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
diff --git a/hw/9pfs/virtio-9p-proxy.h b/hw/9pfs/virtio-9p-proxy.h
index 675218c..da03341 100644
--- a/hw/9pfs/virtio-9p-proxy.h
+++ b/hw/9pfs/virtio-9p-proxy.h
@@ -45,6 +45,40 @@ enum {
     T_MKDIR,
     T_SYMLINK,
     T_LINK,
+    T_LSTAT,
+    T_READLINK,
+    T_STATFS,
 };
 
+typedef struct {
+    uint64_t st_dev;
+    uint64_t st_ino;
+    uint64_t st_nlink;
+    uint32_t st_mode;
+    uint32_t st_uid;
+    uint32_t st_gid;
+    uint64_t st_rdev;
+    uint64_t st_size;
+    uint64_t st_blksize;
+    uint64_t st_blocks;
+    uint64_t st_atim_sec;
+    uint64_t st_atim_nsec;
+    uint64_t st_mtim_sec;
+    uint64_t st_mtim_nsec;
+    uint64_t st_ctim_sec;
+    uint64_t st_ctim_nsec;
+} ProxyStat;
+
+typedef struct {
+    uint64_t f_type;
+    uint64_t f_bsize;
+    uint64_t f_blocks;
+    uint64_t f_bfree;
+    uint64_t f_bavail;
+    uint64_t f_files;
+    uint64_t f_ffree;
+    uint64_t f_fsid[2];
+    uint64_t f_namelen;
+    uint64_t f_frsize;
+} ProxyStatFS;
 #endif
commit 39f8c32c3f4ed54d5d5dfb7cc0f2eb3b244e511a
Author: M. Mohan Kumar <mohan at in.ibm.com>
Date:   Wed Dec 14 13:58:45 2011 +0530

    hw/9pfs: Create other filesystem objects
    
    Add interfaces to create filesystem objects like directory,
    device nodes, symbolic links, links for proxy filesytem driver
    
    Signed-off-by: M. Mohan Kumar <mohan at in.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index e0af257..83fbae7 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -231,6 +231,30 @@ static int send_fd(int sockfd, int fd)
     return 0;
 }
 
+static int send_status(int sockfd, struct iovec *iovec, int status)
+{
+    ProxyHeader header;
+    int retval, msg_size;;
+
+    if (status < 0) {
+        header.type = T_ERROR;
+    } else {
+        header.type = T_SUCCESS;
+    }
+    header.size = sizeof(status);
+    /*
+     * marshal the return status. We don't check error.
+     * because we are sure we have enough space for the status
+     */
+    msg_size = proxy_marshal(iovec, 0, "ddd", header.type,
+                             header.size, status);
+    retval = socket_write(sockfd, iovec->iov_base, msg_size);
+    if (retval < 0) {
+        return retval;
+    }
+    return 0;
+}
+
 /*
  * from man 7 capabilities, section
  * Effect of User ID Changes on Capabilities:
@@ -262,6 +286,67 @@ static int setfsugid(int uid, int gid)
 }
 
 /*
+ * create other filesystem objects and send 0 on success
+ * return -errno on error
+ */
+static int do_create_others(int type, struct iovec *iovec)
+{
+    dev_t rdev;
+    int retval = 0;
+    int offset = PROXY_HDR_SZ;
+    V9fsString oldpath, path;
+    int mode, uid, gid, cur_uid, cur_gid;
+
+    v9fs_string_init(&path);
+    v9fs_string_init(&oldpath);
+    cur_uid = geteuid();
+    cur_gid = getegid();
+
+    retval = proxy_unmarshal(iovec, offset, "dd", &uid, &gid);
+    if (retval < 0) {
+        return retval;
+    }
+    offset += retval;
+    retval = setfsugid(uid, gid);
+    if (retval < 0) {
+        retval = -errno;
+        goto err_out;
+    }
+    switch (type) {
+    case T_MKNOD:
+        retval = proxy_unmarshal(iovec, offset, "sdq", &path, &mode, &rdev);
+        if (retval < 0) {
+            goto err_out;
+        }
+        retval = mknod(path.data, mode, rdev);
+        break;
+    case T_MKDIR:
+        retval = proxy_unmarshal(iovec, offset, "sd", &path, &mode);
+        if (retval < 0) {
+            goto err_out;
+        }
+        retval = mkdir(path.data, mode);
+        break;
+    case T_SYMLINK:
+        retval = proxy_unmarshal(iovec, offset, "ss", &oldpath, &path);
+        if (retval < 0) {
+            goto err_out;
+        }
+        retval = symlink(oldpath.data, path.data);
+        break;
+    }
+    if (retval < 0) {
+        retval = -errno;
+    }
+
+err_out:
+    v9fs_string_free(&path);
+    v9fs_string_free(&oldpath);
+    setfsugid(cur_uid, cur_gid);
+    return retval;
+}
+
+/*
  * create a file and send fd on success
  * return -errno on error
  */
@@ -332,7 +417,8 @@ static void usage(char *prog)
             basename(prog));
 }
 
-static int process_reply(int sock, int type, int retval)
+static int process_reply(int sock, int type,
+                         struct iovec *out_iovec, int retval)
 {
     switch (type) {
     case T_OPEN:
@@ -341,6 +427,14 @@ static int process_reply(int sock, int type, int retval)
             return -1;
         }
         break;
+    case T_MKNOD:
+    case T_MKDIR:
+    case T_SYMLINK:
+    case T_LINK:
+        if (send_status(sock, out_iovec, retval) < 0) {
+            return -1;
+        }
+        break;
     default:
         return -1;
         break;
@@ -352,10 +446,14 @@ static int process_requests(int sock)
 {
     int retval = 0;
     ProxyHeader header;
-    struct iovec in_iovec;
+    V9fsString oldpath, path;
+    struct iovec in_iovec, out_iovec;
+
+    in_iovec.iov_base  = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
+    in_iovec.iov_len   = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
+    out_iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
+    out_iovec.iov_len  = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
 
-    in_iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
-    in_iovec.iov_len  = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
     while (1) {
         /*
          * initialize the header type, so that we send
@@ -374,18 +472,37 @@ static int process_requests(int sock)
         case T_CREATE:
             retval = do_create(&in_iovec);
             break;
+        case T_MKNOD:
+        case T_MKDIR:
+        case T_SYMLINK:
+            retval = do_create_others(header.type, &in_iovec);
+            break;
+        case T_LINK:
+            v9fs_string_init(&path);
+            v9fs_string_init(&oldpath);
+            retval = proxy_unmarshal(&in_iovec, PROXY_HDR_SZ,
+                                     "ss", &oldpath, &path);
+            if (retval > 0) {
+                retval = link(oldpath.data, path.data);
+                if (retval < 0) {
+                    retval = -errno;
+                }
+            }
+            v9fs_string_free(&oldpath);
+            v9fs_string_free(&path);
+            break;
         default:
             goto err_out;
             break;
         }
 
-        if (process_reply(sock, header.type, retval) < 0) {
+        if (process_reply(sock, header.type, &out_iovec, retval) < 0) {
             goto err_out;
         }
     }
-    (void)socket_write;
 err_out:
     g_free(in_iovec.iov_base);
+    g_free(out_iovec.iov_base);
     return -1;
 }
 
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 9399c66..6904a1d 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -19,7 +19,8 @@
 typedef struct V9fsProxy {
     int sockfd;
     QemuMutex mutex;
-    struct iovec iovec;
+    struct iovec in_iovec;
+    struct iovec out_iovec;
 } V9fsProxy;
 
 /*
@@ -78,6 +79,60 @@ static int v9fs_receivefd(int sockfd, int *status)
     return 0;
 }
 
+static ssize_t socket_read(int sockfd, void *buff, size_t size)
+{
+    ssize_t retval, total = 0;
+
+    while (size) {
+        retval = read(sockfd, buff, size);
+        if (retval == 0) {
+            return -EIO;
+        }
+        if (retval < 0) {
+            if (errno == EINTR) {
+                continue;
+            }
+            return -errno;
+        }
+        size -= retval;
+        buff += retval;
+        total += retval;
+    }
+    return total;
+}
+
+/*
+ * return < 0 on transport error.
+ * *status is valid only if return >= 0
+ */
+static int v9fs_receive_status(V9fsProxy *proxy,
+                               struct iovec *reply, int *status)
+{
+    int retval;
+    ProxyHeader header;
+
+    *status = 0;
+    reply->iov_len = 0;
+    retval = socket_read(proxy->sockfd, reply->iov_base, PROXY_HDR_SZ);
+    if (retval < 0) {
+        return retval;
+    }
+    reply->iov_len = PROXY_HDR_SZ;
+    proxy_unmarshal(reply, 0, "dd", &header.type, &header.size);
+    if (header.size != sizeof(int)) {
+        *status = -ENOBUFS;
+        return 0;
+    }
+    retval = socket_read(proxy->sockfd,
+                         reply->iov_base + PROXY_HDR_SZ, header.size);
+    if (retval < 0) {
+        return retval;
+    }
+    reply->iov_len += header.size;
+    proxy_unmarshal(reply, PROXY_HDR_SZ, "d", status);
+    return 0;
+}
+
 /*
  * Proxy->header and proxy->request written to socket by QEMU process.
  * This request read by proxy helper process
@@ -86,12 +141,13 @@ static int v9fs_receivefd(int sockfd, int *status)
 static int v9fs_request(V9fsProxy *proxy, int type,
                         void *response, const char *fmt, ...)
 {
+    dev_t rdev;
     va_list ap;
     int retval = 0;
-    V9fsString *path;
     ProxyHeader header = { 0, 0};
-    struct iovec *iovec = NULL;
     int flags, mode, uid, gid;
+    V9fsString *path, *oldpath;
+    struct iovec *iovec = NULL, *reply = NULL;
 
     qemu_mutex_lock(&proxy->mutex);
 
@@ -99,8 +155,8 @@ static int v9fs_request(V9fsProxy *proxy, int type,
         retval = -EIO;
         goto err_out;
     }
-    iovec = &proxy->iovec;
-
+    iovec = &proxy->out_iovec;
+    reply = &proxy->in_iovec;
     va_start(ap, fmt);
     switch (type) {
     case T_OPEN:
@@ -125,6 +181,53 @@ static int v9fs_request(V9fsProxy *proxy, int type,
             header.type = T_CREATE;
         }
         break;
+    case T_MKNOD:
+        path = va_arg(ap, V9fsString *);
+        mode = va_arg(ap, int);
+        rdev = va_arg(ap, long int);
+        uid = va_arg(ap, int);
+        gid = va_arg(ap, int);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddsdq",
+                                    uid, gid, path, mode, rdev);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_MKNOD;
+        }
+        break;
+    case T_MKDIR:
+        path = va_arg(ap, V9fsString *);
+        mode = va_arg(ap, int);
+        uid = va_arg(ap, int);
+        gid = va_arg(ap, int);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddsd",
+                                    uid, gid, path, mode);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_MKDIR;
+        }
+        break;
+    case T_SYMLINK:
+        oldpath = va_arg(ap, V9fsString *);
+        path = va_arg(ap, V9fsString *);
+        uid = va_arg(ap, int);
+        gid = va_arg(ap, int);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddss",
+                                    uid, gid, oldpath, path);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_SYMLINK;
+        }
+        break;
+    case T_LINK:
+        oldpath = va_arg(ap, V9fsString *);
+        path = va_arg(ap, V9fsString *);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ss",
+                                    oldpath, path);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_LINK;
+        }
+        break;
     default:
         error_report("Invalid type %d\n", type);
         retval = -EINVAL;
@@ -156,6 +259,14 @@ static int v9fs_request(V9fsProxy *proxy, int type,
             goto close_error;
         }
         break;
+    case T_MKNOD:
+    case T_MKDIR:
+    case T_SYMLINK:
+    case T_LINK:
+        if (v9fs_receive_status(proxy, reply, &retval) < 0) {
+            goto close_error;
+        }
+        break;
     }
 
 err_out:
@@ -301,15 +412,41 @@ static int proxy_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
 static int proxy_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
                        const char *name, FsCred *credp)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    V9fsString fullname;
+
+    v9fs_string_init(&fullname);
+    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+
+    retval = v9fs_request(fs_ctx->private, T_MKNOD, NULL, "sdqdd",
+                          &fullname, credp->fc_mode, credp->fc_rdev,
+                          credp->fc_uid, credp->fc_gid);
+    v9fs_string_free(&fullname);
+    if (retval < 0) {
+        errno = -retval;
+        retval = -1;
+    }
+    return retval;
 }
 
 static int proxy_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
                        const char *name, FsCred *credp)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    V9fsString fullname;
+
+    v9fs_string_init(&fullname);
+    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+
+    retval = v9fs_request(fs_ctx->private, T_MKDIR, NULL, "sddd", &fullname,
+                          credp->fc_mode, credp->fc_uid, credp->fc_gid);
+    v9fs_string_free(&fullname);
+    if (retval < 0) {
+        errno = -retval;
+        retval = -1;
+    }
+    v9fs_string_free(&fullname);
+    return retval;
 }
 
 static int proxy_fstat(FsContext *fs_ctx, int fid_type,
@@ -344,19 +481,46 @@ static int proxy_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
     return fs->fd;
 }
 
-
 static int proxy_symlink(FsContext *fs_ctx, const char *oldpath,
                          V9fsPath *dir_path, const char *name, FsCred *credp)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    V9fsString fullname, target;
+
+    v9fs_string_init(&fullname);
+    v9fs_string_init(&target);
+
+    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+    v9fs_string_sprintf(&target, "%s", oldpath);
+
+    retval = v9fs_request(fs_ctx->private, T_SYMLINK, NULL, "ssdd",
+                          &target, &fullname, credp->fc_uid, credp->fc_gid);
+    v9fs_string_free(&fullname);
+    v9fs_string_free(&target);
+    if (retval < 0) {
+        errno = -retval;
+        retval = -1;
+    }
+    return retval;
 }
 
 static int proxy_link(FsContext *ctx, V9fsPath *oldpath,
                       V9fsPath *dirpath, const char *name)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    V9fsString newpath;
+
+    v9fs_string_init(&newpath);
+    v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name);
+
+    retval = v9fs_request(ctx->private, T_LINK, NULL, "ss",
+                          oldpath, &newpath);
+    v9fs_string_free(&newpath);
+    if (retval < 0) {
+        errno = -retval;
+        retval = -1;
+    }
+    return retval;
 }
 
 static int proxy_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
@@ -514,8 +678,11 @@ static int proxy_init(FsContext *ctx)
     }
     g_free(ctx->fs_root);
 
-    proxy->iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
-    proxy->iovec.iov_len = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
+    proxy->in_iovec.iov_base  = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
+    proxy->in_iovec.iov_len   = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
+    proxy->out_iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
+    proxy->out_iovec.iov_len  = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
+
     ctx->private = proxy;
     proxy->sockfd = sock_id;
     qemu_mutex_init(&proxy->mutex);
diff --git a/hw/9pfs/virtio-9p-proxy.h b/hw/9pfs/virtio-9p-proxy.h
index 6172e5f..675218c 100644
--- a/hw/9pfs/virtio-9p-proxy.h
+++ b/hw/9pfs/virtio-9p-proxy.h
@@ -37,8 +37,14 @@ typedef struct {
 #define PROXY_HDR_SZ (sizeof(ProxyHeader))
 
 enum {
-    T_OPEN = 1,
+    T_SUCCESS = 0,
+    T_ERROR,
+    T_OPEN,
     T_CREATE,
+    T_MKNOD,
+    T_MKDIR,
+    T_SYMLINK,
+    T_LINK,
 };
 
 #endif
commit daf0b9aca9f67323266af1a92e8ea06f9d7bf408
Author: M. Mohan Kumar <mohan at in.ibm.com>
Date:   Wed Dec 14 13:58:44 2011 +0530

    hw/9pfs: Open and create files
    
    Add interfaces to open and create files for proxy file system driver.
    
    Signed-off-by: M. Mohan Kumar <mohan at in.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 5fc2fc4..e0af257 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -9,6 +9,7 @@
  * the COPYING file in the top-level directory.
  */
 #include <stdio.h>
+#include <sys/socket.h>
 #include <string.h>
 #include <sys/un.h>
 #include <limits.h>
@@ -27,6 +28,7 @@
 #include "qemu-common.h"
 #include "virtio-9p-marshal.h"
 #include "hw/9pfs/virtio-9p-proxy.h"
+#include "fsdev/virtio-9p-marshal.h"
 
 #define PROGNAME "virtfs-proxy-helper"
 
@@ -187,6 +189,140 @@ static int read_request(int sockfd, struct iovec *iovec, ProxyHeader *header)
     return 0;
 }
 
+static int send_fd(int sockfd, int fd)
+{
+    struct msghdr msg;
+    struct iovec iov;
+    int retval, data;
+    struct cmsghdr *cmsg;
+    union MsgControl msg_control;
+
+    iov.iov_base = &data;
+    iov.iov_len = sizeof(data);
+
+    memset(&msg, 0, sizeof(msg));
+    msg.msg_iov = &iov;
+    msg.msg_iovlen = 1;
+    /* No ancillary data on error */
+    if (fd < 0) {
+        /* fd is really negative errno if the request failed  */
+        data = fd;
+    } else {
+        data = V9FS_FD_VALID;
+        msg.msg_control = &msg_control;
+        msg.msg_controllen = sizeof(msg_control);
+
+        cmsg = &msg_control.cmsg;
+        cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+        cmsg->cmsg_level = SOL_SOCKET;
+        cmsg->cmsg_type = SCM_RIGHTS;
+        memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+    }
+
+    do {
+        retval = sendmsg(sockfd, &msg, 0);
+    } while (retval < 0 && errno == EINTR);
+    if (fd >= 0) {
+        close(fd);
+    }
+    if (retval < 0) {
+        return retval;
+    }
+    return 0;
+}
+
+/*
+ * from man 7 capabilities, section
+ * Effect of User ID Changes on Capabilities:
+ * 4. If the file system user ID is changed from 0 to nonzero (see setfsuid(2))
+ * then the following capabilities are cleared from the effective set:
+ * CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH,  CAP_FOWNER, CAP_FSETID,
+ * CAP_LINUX_IMMUTABLE  (since  Linux 2.2.30), CAP_MAC_OVERRIDE, and CAP_MKNOD
+ * (since Linux 2.2.30). If the file system UID is changed from nonzero to 0,
+ * then any of these capabilities that are enabled in the permitted set
+ * are enabled in the effective set.
+ */
+static int setfsugid(int uid, int gid)
+{
+    /*
+     * We still need DAC_OVERRIDE because  we don't change
+     * supplementary group ids, and hence may be subjected DAC rules
+     */
+    cap_value_t cap_list[] = {
+        CAP_DAC_OVERRIDE,
+    };
+
+    setfsgid(gid);
+    setfsuid(uid);
+
+    if (uid != 0 || gid != 0) {
+        return do_cap_set(cap_list, ARRAY_SIZE(cap_list), 0);
+    }
+    return 0;
+}
+
+/*
+ * create a file and send fd on success
+ * return -errno on error
+ */
+static int do_create(struct iovec *iovec)
+{
+    int ret;
+    V9fsString path;
+    int flags, mode, uid, gid, cur_uid, cur_gid;
+
+    v9fs_string_init(&path);
+    ret = proxy_unmarshal(iovec, PROXY_HDR_SZ, "sdddd",
+                          &path, &flags, &mode, &uid, &gid);
+    if (ret < 0) {
+        goto unmarshal_err_out;
+    }
+    cur_uid = geteuid();
+    cur_gid = getegid();
+    ret = setfsugid(uid, gid);
+    if (ret < 0) {
+        /*
+         * On failure reset back to the
+         * old uid/gid
+         */
+        ret = -errno;
+        goto err_out;
+    }
+    ret = open(path.data, flags, mode);
+    if (ret < 0) {
+        ret = -errno;
+    }
+
+err_out:
+    setfsugid(cur_uid, cur_gid);
+unmarshal_err_out:
+    v9fs_string_free(&path);
+    return ret;
+}
+
+/*
+ * open a file and send fd on success
+ * return -errno on error
+ */
+static int do_open(struct iovec *iovec)
+{
+    int flags, ret;
+    V9fsString path;
+
+    v9fs_string_init(&path);
+    ret = proxy_unmarshal(iovec, PROXY_HDR_SZ, "sd", &path, &flags);
+    if (ret < 0) {
+        goto err_out;
+    }
+    ret = open(path.data, flags);
+    if (ret < 0) {
+        ret = -errno;
+    }
+err_out:
+    v9fs_string_free(&path);
+    return ret;
+}
+
 static void usage(char *prog)
 {
     fprintf(stderr, "usage: %s\n"
@@ -196,22 +332,59 @@ static void usage(char *prog)
             basename(prog));
 }
 
+static int process_reply(int sock, int type, int retval)
+{
+    switch (type) {
+    case T_OPEN:
+    case T_CREATE:
+        if (send_fd(sock, retval) < 0) {
+            return -1;
+        }
+        break;
+    default:
+        return -1;
+        break;
+    }
+    return 0;
+}
+
 static int process_requests(int sock)
 {
-    int retval;
+    int retval = 0;
     ProxyHeader header;
     struct iovec in_iovec;
 
     in_iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
     in_iovec.iov_len  = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
     while (1) {
+        /*
+         * initialize the header type, so that we send
+         * response to proper request type.
+         */
+        header.type = 0;
         retval = read_request(sock, &in_iovec, &header);
         if (retval < 0) {
-            goto error;
+            goto err_out;
+        }
+
+        switch (header.type) {
+        case T_OPEN:
+            retval = do_open(&in_iovec);
+            break;
+        case T_CREATE:
+            retval = do_create(&in_iovec);
+            break;
+        default:
+            goto err_out;
+            break;
+        }
+
+        if (process_reply(sock, header.type, retval) < 0) {
+            goto err_out;
         }
     }
     (void)socket_write;
-error:
+err_out:
     g_free(in_iovec.iov_base);
     return -1;
 }
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 3e4dc68..9399c66 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -22,6 +22,153 @@ typedef struct V9fsProxy {
     struct iovec iovec;
 } V9fsProxy;
 
+/*
+ * Return received file descriptor on success in *status.
+ * errno is also returned on *status (which will be < 0)
+ * return < 0 on transport error.
+ */
+static int v9fs_receivefd(int sockfd, int *status)
+{
+    struct iovec iov;
+    struct msghdr msg;
+    struct cmsghdr *cmsg;
+    int retval, data, fd;
+    union MsgControl msg_control;
+
+    iov.iov_base = &data;
+    iov.iov_len = sizeof(data);
+
+    memset(&msg, 0, sizeof(msg));
+    msg.msg_iov = &iov;
+    msg.msg_iovlen = 1;
+    msg.msg_control = &msg_control;
+    msg.msg_controllen = sizeof(msg_control);
+
+    do {
+        retval = recvmsg(sockfd, &msg, 0);
+    } while (retval < 0 && errno == EINTR);
+    if (retval <= 0) {
+        return retval;
+    }
+    /*
+     * data is set to V9FS_FD_VALID, if ancillary data is sent.  If this
+     * request doesn't need ancillary data (fd) or an error occurred,
+     * data is set to negative errno value.
+     */
+    if (data != V9FS_FD_VALID) {
+        *status = data;
+        return 0;
+    }
+    /*
+     * File descriptor (fd) is sent in the ancillary data. Check if we
+     * indeed received it. One of the reasons to fail to receive it is if
+     * we exceeded the maximum number of file descriptors!
+     */
+    for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+        if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
+            cmsg->cmsg_level != SOL_SOCKET ||
+            cmsg->cmsg_type != SCM_RIGHTS) {
+            continue;
+        }
+        fd = *((int *)CMSG_DATA(cmsg));
+        *status = fd;
+        return 0;
+    }
+    *status = -ENFILE;  /* Ancillary data sent but not received */
+    return 0;
+}
+
+/*
+ * Proxy->header and proxy->request written to socket by QEMU process.
+ * This request read by proxy helper process
+ * returns 0 on success and -errno on error
+ */
+static int v9fs_request(V9fsProxy *proxy, int type,
+                        void *response, const char *fmt, ...)
+{
+    va_list ap;
+    int retval = 0;
+    V9fsString *path;
+    ProxyHeader header = { 0, 0};
+    struct iovec *iovec = NULL;
+    int flags, mode, uid, gid;
+
+    qemu_mutex_lock(&proxy->mutex);
+
+    if (proxy->sockfd == -1) {
+        retval = -EIO;
+        goto err_out;
+    }
+    iovec = &proxy->iovec;
+
+    va_start(ap, fmt);
+    switch (type) {
+    case T_OPEN:
+        path = va_arg(ap, V9fsString *);
+        flags = va_arg(ap, int);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sd", path, flags);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_OPEN;
+        }
+        break;
+    case T_CREATE:
+        path = va_arg(ap, V9fsString *);
+        flags = va_arg(ap, int);
+        mode = va_arg(ap, int);
+        uid = va_arg(ap, int);
+        gid = va_arg(ap, int);
+        retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sdddd", path,
+                                    flags, mode, uid, gid);
+        if (retval > 0) {
+            header.size = retval;
+            header.type = T_CREATE;
+        }
+        break;
+    default:
+        error_report("Invalid type %d\n", type);
+        retval = -EINVAL;
+        break;
+    }
+    va_end(ap);
+
+    if (retval < 0) {
+        goto err_out;
+    }
+
+    /* marshal the header details */
+    proxy_marshal(iovec, 0, "dd", header.type, header.size);
+    header.size += PROXY_HDR_SZ;
+
+    retval = qemu_write_full(proxy->sockfd, iovec->iov_base, header.size);
+    if (retval != header.size) {
+        goto close_error;
+    }
+
+    switch (type) {
+    case T_OPEN:
+    case T_CREATE:
+        /*
+         * A file descriptor is returned as response for
+         * T_OPEN,T_CREATE on success
+         */
+        if (v9fs_receivefd(proxy->sockfd, &retval) < 0) {
+            goto close_error;
+        }
+        break;
+    }
+
+err_out:
+    qemu_mutex_unlock(&proxy->mutex);
+    return retval;
+
+close_error:
+    close(proxy->sockfd);
+    proxy->sockfd = -1;
+    qemu_mutex_unlock(&proxy->mutex);
+    return -EIO;
+}
+
 static int proxy_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
 {
     errno = EOPNOTSUPP;
@@ -48,16 +195,33 @@ static int proxy_closedir(FsContext *ctx, V9fsFidOpenState *fs)
 static int proxy_open(FsContext *ctx, V9fsPath *fs_path,
                       int flags, V9fsFidOpenState *fs)
 {
-    fs->fd = -1;
+    fs->fd = v9fs_request(ctx->private, T_OPEN, NULL, "sd", fs_path, flags);
+    if (fs->fd < 0) {
+        errno = -fs->fd;
+        fs->fd = -1;
+    }
     return fs->fd;
 }
 
 static int proxy_opendir(FsContext *ctx,
                          V9fsPath *fs_path, V9fsFidOpenState *fs)
 {
+    int serrno, fd;
+
     fs->dir = NULL;
-    errno = EOPNOTSUPP;
-    return -1;
+    fd = v9fs_request(ctx->private, T_OPEN, NULL, "sd", fs_path, O_DIRECTORY);
+    if (fd < 0) {
+        errno = -fd;
+        return -1;
+    }
+    fs->dir = fdopendir(fd);
+    if (!fs->dir) {
+        serrno = errno;
+        close(fd);
+        errno = serrno;
+        return -1;
+    }
+    return 0;
 }
 
 static void proxy_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
@@ -164,9 +328,20 @@ static int proxy_fstat(FsContext *fs_ctx, int fid_type,
 static int proxy_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
                        int flags, FsCred *credp, V9fsFidOpenState *fs)
 {
-    fs->fd = -1;
-    errno = EOPNOTSUPP;
-    return -1;
+    V9fsString fullname;
+
+    v9fs_string_init(&fullname);
+    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+
+    fs->fd = v9fs_request(fs_ctx->private, T_CREATE, NULL, "sdddd",
+                          &fullname, flags, credp->fc_mode,
+                          credp->fc_uid, credp->fc_gid);
+    v9fs_string_free(&fullname);
+    if (fs->fd < 0) {
+        errno = -fs->fd;
+        fs->fd = -1;
+    }
+    return fs->fd;
 }
 
 
diff --git a/hw/9pfs/virtio-9p-proxy.h b/hw/9pfs/virtio-9p-proxy.h
index 97c5574..6172e5f 100644
--- a/hw/9pfs/virtio-9p-proxy.h
+++ b/hw/9pfs/virtio-9p-proxy.h
@@ -13,6 +13,7 @@
 #define _QEMU_VIRTIO_9P_PROXY_H
 
 #define PROXY_MAX_IO_SZ (64 * 1024)
+#define V9FS_FD_VALID INT_MAX
 
 /*
  * proxy iovec only support one element and
@@ -23,6 +24,11 @@
 #define proxy_marshal(out_sg, offset, fmt, args...) \
     v9fs_marshal(out_sg, 1, offset, 0, fmt, ##args)
 
+union MsgControl {
+    struct cmsghdr cmsg;
+    char control[CMSG_SPACE(sizeof(int))];
+};
+
 typedef struct {
     uint32_t type;
     uint32_t size;
@@ -30,4 +36,9 @@ typedef struct {
 
 #define PROXY_HDR_SZ (sizeof(ProxyHeader))
 
+enum {
+    T_OPEN = 1,
+    T_CREATE,
+};
+
 #endif
commit 17bff52b6225419931703aa04cc454c16cf5adad
Author: M. Mohan Kumar <mohan at in.ibm.com>
Date:   Wed Dec 14 13:58:42 2011 +0530

    hw/9pfs: File system helper process for qemu 9p proxy FS
    
    Provide root privilege access to QEMU 9p proxy filesystem using socket
    communication.
    
    Proxy helper is started by root user as:
    ~ # virtfs-proxy-helper -f|--fd <socket descriptor> -p|--path <path-to-share>
    
    Signed-off-by: M. Mohan Kumar <mohan at in.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/Makefile b/Makefile
index 0838bc4..51591c3 100644
--- a/Makefile
+++ b/Makefile
@@ -155,6 +155,9 @@ qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
 qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
 qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
 
+fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o
+fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
+
 qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $@")
 
diff --git a/configure b/configure
index 640e815..c136f12 100755
--- a/configure
+++ b/configure
@@ -1967,6 +1967,22 @@ else
 fi
 
 ##########################################
+# libcap probe
+
+if test "$cap" != "no" ; then
+  cat > $TMPC <<EOF
+#include <stdio.h>
+#include <sys/capability.h>
+int main(void) { cap_t caps; caps = cap_init(); }
+EOF
+  if compile_prog "" "-lcap" ; then
+    cap=yes
+  else
+    cap=no
+  fi
+fi
+
+##########################################
 # pthread probe
 PTHREADLIBS_LIST="-pthread -lpthread -lpthreadGC2"
 
@@ -2767,6 +2783,9 @@ 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)"
+  fi
   if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
       tools="qemu-nbd\$(EXESUF) $tools"
     if [ "$guest_agent" = "yes" ]; then
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
new file mode 100644
index 0000000..5fc2fc4
--- /dev/null
+++ b/fsdev/virtfs-proxy-helper.c
@@ -0,0 +1,300 @@
+/*
+ * Helper for QEMU Proxy FS Driver
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * M. Mohan Kumar <mohan at in.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <sys/un.h>
+#include <limits.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <sys/capability.h>
+#include <sys/fsuid.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include "qemu-common.h"
+#include "virtio-9p-marshal.h"
+#include "hw/9pfs/virtio-9p-proxy.h"
+
+#define PROGNAME "virtfs-proxy-helper"
+
+static struct option helper_opts[] = {
+    {"fd", required_argument, NULL, 'f'},
+    {"path", required_argument, NULL, 'p'},
+    {"nodaemon", no_argument, NULL, 'n'},
+};
+
+static bool is_daemon;
+
+static void do_log(int loglevel, const char *format, ...)
+{
+    va_list ap;
+
+    va_start(ap, format);
+    if (is_daemon) {
+        vsyslog(LOG_CRIT, format, ap);
+    } else {
+        vfprintf(stderr, format, ap);
+    }
+    va_end(ap);
+}
+
+static void do_perror(const char *string)
+{
+    if (is_daemon) {
+        syslog(LOG_CRIT, "%s:%s", string, strerror(errno));
+    } else {
+        fprintf(stderr, "%s:%s\n", string, strerror(errno));
+    }
+}
+
+static int do_cap_set(cap_value_t *cap_value, int size, int reset)
+{
+    cap_t caps;
+    if (reset) {
+        /*
+         * Start with an empty set and set permitted and effective
+         */
+        caps = cap_init();
+        if (caps == NULL) {
+            do_perror("cap_init");
+            return -1;
+        }
+        if (cap_set_flag(caps, CAP_PERMITTED, size, cap_value, CAP_SET) < 0) {
+            do_perror("cap_set_flag");
+            goto error;
+        }
+    } else {
+        caps = cap_get_proc();
+        if (!caps) {
+            do_perror("cap_get_proc");
+            return -1;
+        }
+    }
+    if (cap_set_flag(caps, CAP_EFFECTIVE, size, cap_value, CAP_SET) < 0) {
+        do_perror("cap_set_flag");
+        goto error;
+    }
+    if (cap_set_proc(caps) < 0) {
+        do_perror("cap_set_proc");
+        goto error;
+    }
+    cap_free(caps);
+    return 0;
+
+error:
+    cap_free(caps);
+    return -1;
+}
+
+static int init_capabilities(void)
+{
+    /* helper needs following capbabilities only */
+    cap_value_t cap_list[] = {
+        CAP_CHOWN,
+        CAP_DAC_OVERRIDE,
+        CAP_FOWNER,
+        CAP_FSETID,
+        CAP_SETGID,
+        CAP_MKNOD,
+        CAP_SETUID,
+    };
+    return do_cap_set(cap_list, ARRAY_SIZE(cap_list), 1);
+}
+
+static int socket_read(int sockfd, void *buff, ssize_t size)
+{
+    ssize_t retval, total = 0;
+
+    while (size) {
+        retval = read(sockfd, buff, size);
+        if (retval == 0) {
+            return -EIO;
+        }
+        if (retval < 0) {
+            if (errno == EINTR) {
+                continue;
+            }
+            return -errno;
+        }
+        size -= retval;
+        buff += retval;
+        total += retval;
+    }
+    return total;
+}
+
+static int socket_write(int sockfd, void *buff, ssize_t size)
+{
+    ssize_t retval, total = 0;
+
+    while (size) {
+        retval = write(sockfd, buff, size);
+        if (retval < 0) {
+            if (errno == EINTR) {
+                continue;
+            }
+            return -errno;
+        }
+        size -= retval;
+        buff += retval;
+        total += retval;
+    }
+    return total;
+}
+
+static int read_request(int sockfd, struct iovec *iovec, ProxyHeader *header)
+{
+    int retval;
+
+    /*
+     * read the request header.
+     */
+    iovec->iov_len = 0;
+    retval = socket_read(sockfd, iovec->iov_base, PROXY_HDR_SZ);
+    if (retval < 0) {
+        return retval;
+    }
+    iovec->iov_len = PROXY_HDR_SZ;
+    retval = proxy_unmarshal(iovec, 0, "dd", &header->type, &header->size);
+    if (retval < 0) {
+        return retval;
+    }
+    /*
+     * We can't process message.size > PROXY_MAX_IO_SZ.
+     * Treat it as fatal error
+     */
+    if (header->size > PROXY_MAX_IO_SZ) {
+        return -ENOBUFS;
+    }
+    retval = socket_read(sockfd, iovec->iov_base + PROXY_HDR_SZ, header->size);
+    if (retval < 0) {
+        return retval;
+    }
+    iovec->iov_len += header->size;
+    return 0;
+}
+
+static void usage(char *prog)
+{
+    fprintf(stderr, "usage: %s\n"
+            " -p|--path <path> 9p path to export\n"
+            " {-f|--fd <socket-descriptor>} socket file descriptor to be used\n"
+            " [-n|--nodaemon] Run as a normal program\n",
+            basename(prog));
+}
+
+static int process_requests(int sock)
+{
+    int retval;
+    ProxyHeader header;
+    struct iovec in_iovec;
+
+    in_iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
+    in_iovec.iov_len  = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
+    while (1) {
+        retval = read_request(sock, &in_iovec, &header);
+        if (retval < 0) {
+            goto error;
+        }
+    }
+    (void)socket_write;
+error:
+    g_free(in_iovec.iov_base);
+    return -1;
+}
+
+int main(int argc, char **argv)
+{
+    int sock;
+    char *rpath = NULL;
+    struct stat stbuf;
+    int c, option_index;
+
+    is_daemon = true;
+    sock = -1;
+    while (1) {
+        option_index = 0;
+        c = getopt_long(argc, argv, "p:nh?f:", helper_opts,
+                        &option_index);
+        if (c == -1) {
+            break;
+        }
+        switch (c) {
+        case 'p':
+            rpath = strdup(optarg);
+            break;
+        case 'n':
+            is_daemon = false;
+            break;
+        case 'f':
+            sock = atoi(optarg);
+            break;
+        case '?':
+        case 'h':
+        default:
+            usage(argv[0]);
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    /* Parameter validation */
+    if (sock == -1 || rpath == NULL) {
+        fprintf(stderr, "socket descriptor or path not specified\n");
+        usage(argv[0]);
+        exit(EXIT_FAILURE);
+    }
+
+    if (lstat(rpath, &stbuf) < 0) {
+        fprintf(stderr, "invalid path \"%s\" specified, %s\n",
+                rpath, strerror(errno));
+        exit(EXIT_FAILURE);
+    }
+
+    if (!S_ISDIR(stbuf.st_mode)) {
+        fprintf(stderr, "specified path \"%s\" is not directory\n", rpath);
+        exit(EXIT_FAILURE);
+    }
+
+    if (is_daemon) {
+        if (daemon(0, 0) < 0) {
+            fprintf(stderr, "daemon call failed\n");
+            exit(EXIT_FAILURE);
+        }
+        openlog(PROGNAME, LOG_PID, LOG_DAEMON);
+    }
+
+    do_log(LOG_INFO, "Started\n");
+
+    if (chdir("/") < 0) {
+        do_perror("chdir");
+        goto error;
+    }
+    if (chroot(rpath) < 0) {
+        do_perror("chroot");
+        goto error;
+    }
+    umask(0);
+
+    if (init_capabilities() < 0) {
+        goto error;
+    }
+
+    process_requests(sock);
+error:
+    do_log(LOG_INFO, "Done\n");
+    closelog();
+    return 0;
+}
diff --git a/hw/9pfs/virtio-9p-proxy.h b/hw/9pfs/virtio-9p-proxy.h
index 2d60b0e..97c5574 100644
--- a/hw/9pfs/virtio-9p-proxy.h
+++ b/hw/9pfs/virtio-9p-proxy.h
@@ -14,6 +14,15 @@
 
 #define PROXY_MAX_IO_SZ (64 * 1024)
 
+/*
+ * proxy iovec only support one element and
+ * marsha/unmarshal doesn't do little endian conversion.
+ */
+#define proxy_unmarshal(in_sg, offset, fmt, args...) \
+    v9fs_unmarshal(in_sg, 1, offset, 0, fmt, ##args)
+#define proxy_marshal(out_sg, offset, fmt, args...) \
+    v9fs_marshal(out_sg, 1, offset, 0, fmt, ##args)
+
 typedef struct {
     uint32_t type;
     uint32_t size;
commit 4c793dda22213a7aba8e4d9a814e8f368a5f8bf7
Author: M. Mohan Kumar <mohan at in.ibm.com>
Date:   Wed Dec 14 13:49:28 2011 +0530

    hw/9pfs: Add new proxy filesystem driver
    
    Add new proxy filesystem driver to add root privilege to qemu process.
    It needs a helper process to be started by root user.
    
    Following command line can be used to utilize proxy filesystem driver
    -virtfs proxy,id=<id>,mount_tag=<tag>,socket_fd=<socket-fd>
    
    Signed-off-by: M. Mohan Kumar <mohan at in.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/Makefile.objs b/Makefile.objs
index 35cd645..19d1459 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -311,6 +311,7 @@ hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o cofs.o codir.o cofile.o
 9pfs-nested-$(CONFIG_VIRTFS) += coxattr.o virtio-9p-synth.o
 9pfs-nested-$(CONFIG_OPEN_BY_HANDLE) +=  virtio-9p-handle.o
+9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-proxy.o
 
 hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y))
 $(addprefix 9pfs/, $(9pfs-nested-y)): QEMU_CFLAGS+=$(GLIB_CFLAGS)
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
index 00f48ab..e20202a 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -27,6 +27,7 @@ static FsDriverTable FsDrivers[] = {
     { .name = "handle", .ops = &handle_ops},
 #endif
     { .name = "synth", .ops = &synth_ops},
+    { .name = "proxy", .ops = &proxy_ops},
 };
 
 int qemu_fsdev_add(QemuOpts *opts)
diff --git a/fsdev/qemu-fsdev.h b/fsdev/qemu-fsdev.h
index 921452d..1af1f54 100644
--- a/fsdev/qemu-fsdev.h
+++ b/fsdev/qemu-fsdev.h
@@ -44,4 +44,5 @@ FsDriverEntry *get_fsdev_fsentry(char *id);
 extern FileOperations local_ops;
 extern FileOperations handle_ops;
 extern FileOperations synth_ops;
+extern FileOperations proxy_ops;
 #endif
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
new file mode 100644
index 0000000..3e4dc68
--- /dev/null
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -0,0 +1,388 @@
+/*
+ * Virtio 9p Proxy callback
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * M. Mohan Kumar <mohan at in.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+#include <sys/socket.h>
+#include <sys/un.h>
+#include "hw/virtio.h"
+#include "virtio-9p.h"
+#include "fsdev/qemu-fsdev.h"
+#include "virtio-9p-proxy.h"
+
+typedef struct V9fsProxy {
+    int sockfd;
+    QemuMutex mutex;
+    struct iovec iovec;
+} V9fsProxy;
+
+static int proxy_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static ssize_t proxy_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
+                              char *buf, size_t bufsz)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_close(FsContext *ctx, V9fsFidOpenState *fs)
+{
+    return close(fs->fd);
+}
+
+static int proxy_closedir(FsContext *ctx, V9fsFidOpenState *fs)
+{
+    return closedir(fs->dir);
+}
+
+static int proxy_open(FsContext *ctx, V9fsPath *fs_path,
+                      int flags, V9fsFidOpenState *fs)
+{
+    fs->fd = -1;
+    return fs->fd;
+}
+
+static int proxy_opendir(FsContext *ctx,
+                         V9fsPath *fs_path, V9fsFidOpenState *fs)
+{
+    fs->dir = NULL;
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static void proxy_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
+{
+    return rewinddir(fs->dir);
+}
+
+static off_t proxy_telldir(FsContext *ctx, V9fsFidOpenState *fs)
+{
+    return telldir(fs->dir);
+}
+
+static int proxy_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
+                           struct dirent *entry,
+                           struct dirent **result)
+{
+    return readdir_r(fs->dir, entry, result);
+}
+
+static void proxy_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
+{
+    return seekdir(fs->dir, off);
+}
+
+static ssize_t proxy_preadv(FsContext *ctx, V9fsFidOpenState *fs,
+                            const struct iovec *iov,
+                            int iovcnt, off_t offset)
+{
+#ifdef CONFIG_PREADV
+    return preadv(fs->fd, iov, iovcnt, offset);
+#else
+    int err = lseek(fs->fd, offset, SEEK_SET);
+    if (err == -1) {
+        return err;
+    } else {
+        return readv(fs->fd, iov, iovcnt);
+    }
+#endif
+}
+
+static ssize_t proxy_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
+                             const struct iovec *iov,
+                             int iovcnt, off_t offset)
+{
+    ssize_t ret;
+
+#ifdef CONFIG_PREADV
+    ret = pwritev(fs->fd, iov, iovcnt, offset);
+#else
+    int err = lseek(fs->fd, offset, SEEK_SET);
+    if (err == -1) {
+        return err;
+    } else {
+        ret = writev(fs->fd, iov, iovcnt);
+    }
+#endif
+#ifdef CONFIG_SYNC_FILE_RANGE
+    if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) {
+        /*
+         * Initiate a writeback. This is not a data integrity sync.
+         * We want to ensure that we don't leave dirty pages in the cache
+         * after write when writeout=immediate is sepcified.
+         */
+        sync_file_range(fs->fd, offset, ret,
+                        SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE);
+    }
+#endif
+    return ret;
+}
+
+static int proxy_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
+                       const char *name, FsCred *credp)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
+                       const char *name, FsCred *credp)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_fstat(FsContext *fs_ctx, int fid_type,
+                       V9fsFidOpenState *fs, struct stat *stbuf)
+{
+    int fd;
+
+    if (fid_type == P9_FID_DIR) {
+        fd = dirfd(fs->dir);
+    } else {
+        fd = fs->fd;
+    }
+    return fstat(fd, stbuf);
+}
+
+static int proxy_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
+                       int flags, FsCred *credp, V9fsFidOpenState *fs)
+{
+    fs->fd = -1;
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+
+static int proxy_symlink(FsContext *fs_ctx, const char *oldpath,
+                         V9fsPath *dir_path, const char *name, FsCred *credp)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_link(FsContext *ctx, V9fsPath *oldpath,
+                      V9fsPath *dirpath, const char *name)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_rename(FsContext *ctx, const char *oldpath,
+                        const char *newpath)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_utimensat(FsContext *s, V9fsPath *fs_path,
+                           const struct timespec *buf)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_remove(FsContext *ctx, const char *path)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_fsync(FsContext *ctx, int fid_type,
+                       V9fsFidOpenState *fs, int datasync)
+{
+    int fd;
+
+    if (fid_type == P9_FID_DIR) {
+        fd = dirfd(fs->dir);
+    } else {
+        fd = fs->fd;
+    }
+
+    if (datasync) {
+        return qemu_fdatasync(fd);
+    } else {
+        return fsync(fd);
+    }
+}
+
+static int proxy_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static ssize_t proxy_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
+                               const char *name, void *value, size_t size)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static ssize_t proxy_llistxattr(FsContext *ctx, V9fsPath *fs_path,
+                                void *value, size_t size)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
+                           void *value, size_t size, int flags)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
+                              const char *name)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static int proxy_name_to_path(FsContext *ctx, V9fsPath *dir_path,
+                              const char *name, V9fsPath *target)
+{
+    if (dir_path) {
+        v9fs_string_sprintf((V9fsString *)target, "%s/%s",
+                            dir_path->data, name);
+    } else {
+        v9fs_string_sprintf((V9fsString *)target, "%s", name);
+    }
+    /* Bump the size for including terminating NULL */
+    target->size++;
+    return 0;
+}
+
+static int proxy_renameat(FsContext *ctx, V9fsPath *olddir,
+                          const char *old_name, V9fsPath *newdir,
+                          const char *new_name)
+{
+    int ret;
+    V9fsString old_full_name, new_full_name;
+
+    v9fs_string_init(&old_full_name);
+    v9fs_string_init(&new_full_name);
+
+    v9fs_string_sprintf(&old_full_name, "%s/%s", olddir->data, old_name);
+    v9fs_string_sprintf(&new_full_name, "%s/%s", newdir->data, new_name);
+
+    ret = proxy_rename(ctx, old_full_name.data, new_full_name.data);
+    v9fs_string_free(&old_full_name);
+    v9fs_string_free(&new_full_name);
+    return ret;
+}
+
+static int proxy_unlinkat(FsContext *ctx, V9fsPath *dir,
+                          const char *name, int flags)
+{
+    int ret;
+    V9fsString fullname;
+    v9fs_string_init(&fullname);
+
+    v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name);
+    ret = proxy_remove(ctx, fullname.data);
+    v9fs_string_free(&fullname);
+
+    return ret;
+}
+
+static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs)
+{
+    const char *sock_fd = qemu_opt_get(opts, "sock_fd");
+
+    if (sock_fd) {
+        fprintf(stderr, "sock_fd option not specified\n");
+        return -1;
+    }
+    fs->path = g_strdup(sock_fd);
+    return 0;
+}
+
+static int proxy_init(FsContext *ctx)
+{
+    V9fsProxy *proxy = g_malloc(sizeof(V9fsProxy));
+    int sock_id;
+
+    sock_id = atoi(ctx->fs_root);
+    if (sock_id < 0) {
+        fprintf(stderr, "socket descriptor not initialized\n");
+        return -1;
+    }
+    g_free(ctx->fs_root);
+
+    proxy->iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
+    proxy->iovec.iov_len = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
+    ctx->private = proxy;
+    proxy->sockfd = sock_id;
+    qemu_mutex_init(&proxy->mutex);
+
+    ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
+    return 0;
+}
+
+FileOperations proxy_ops = {
+    .parse_opts   = proxy_parse_opts,
+    .init         = proxy_init,
+    .lstat        = proxy_lstat,
+    .readlink     = proxy_readlink,
+    .close        = proxy_close,
+    .closedir     = proxy_closedir,
+    .open         = proxy_open,
+    .opendir      = proxy_opendir,
+    .rewinddir    = proxy_rewinddir,
+    .telldir      = proxy_telldir,
+    .readdir_r    = proxy_readdir_r,
+    .seekdir      = proxy_seekdir,
+    .preadv       = proxy_preadv,
+    .pwritev      = proxy_pwritev,
+    .chmod        = proxy_chmod,
+    .mknod        = proxy_mknod,
+    .mkdir        = proxy_mkdir,
+    .fstat        = proxy_fstat,
+    .open2        = proxy_open2,
+    .symlink      = proxy_symlink,
+    .link         = proxy_link,
+    .truncate     = proxy_truncate,
+    .rename       = proxy_rename,
+    .chown        = proxy_chown,
+    .utimensat    = proxy_utimensat,
+    .remove       = proxy_remove,
+    .fsync        = proxy_fsync,
+    .statfs       = proxy_statfs,
+    .lgetxattr    = proxy_lgetxattr,
+    .llistxattr   = proxy_llistxattr,
+    .lsetxattr    = proxy_lsetxattr,
+    .lremovexattr = proxy_lremovexattr,
+    .name_to_path = proxy_name_to_path,
+    .renameat     = proxy_renameat,
+    .unlinkat     = proxy_unlinkat,
+};
diff --git a/hw/9pfs/virtio-9p-proxy.h b/hw/9pfs/virtio-9p-proxy.h
new file mode 100644
index 0000000..2d60b0e
--- /dev/null
+++ b/hw/9pfs/virtio-9p-proxy.h
@@ -0,0 +1,24 @@
+/*
+ * Virtio 9p Proxy callback
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * M. Mohan Kumar <mohan at in.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+#ifndef _QEMU_VIRTIO_9P_PROXY_H
+#define _QEMU_VIRTIO_9P_PROXY_H
+
+#define PROXY_MAX_IO_SZ (64 * 1024)
+
+typedef struct {
+    uint32_t type;
+    uint32_t size;
+} ProxyHeader;
+
+#define PROXY_HDR_SZ (sizeof(ProxyHeader))
+
+#endif
diff --git a/qemu-config.c b/qemu-config.c
index 18f3020..1bdc01c 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -211,6 +211,9 @@ QemuOptsList qemu_fsdev_opts = {
         }, {
             .name = "readonly",
             .type = QEMU_OPT_BOOL,
+        }, {
+            .name = "sock_fd",
+            .type = QEMU_OPT_NUMBER,
         },
 
         { /*End of list */ }
@@ -240,6 +243,9 @@ QemuOptsList qemu_virtfs_opts = {
         }, {
             .name = "readonly",
             .type = QEMU_OPT_BOOL,
+        }, {
+            .name = "sock_fd",
+            .type = QEMU_OPT_NUMBER,
         },
 
         { /*End of list */ }
diff --git a/vl.c b/vl.c
index 47a8b09..aaa2b93 100644
--- a/vl.c
+++ b/vl.c
@@ -2661,7 +2661,7 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_virtfs: {
                 QemuOpts *fsdev;
                 QemuOpts *device;
-                const char *writeout;
+                const char *writeout, *sock_fd;
 
                 olist = qemu_find_opts("virtfs");
                 if (!olist) {
@@ -2701,6 +2701,10 @@ int main(int argc, char **argv, char **envp)
                 qemu_opt_set(fsdev, "path", qemu_opt_get(opts, "path"));
                 qemu_opt_set(fsdev, "security_model",
                              qemu_opt_get(opts, "security_model"));
+                sock_fd = qemu_opt_get(opts, "sock_fd");
+                if (sock_fd) {
+                    qemu_opt_set(fsdev, "sock_fd", sock_fd);
+                }
 
                 qemu_opt_set_bool(fsdev, "readonly",
                                 qemu_opt_get_bool(opts, "readonly", 0));
commit ddca7f86ac022289840e0200fd4050b2b58e9176
Author: M. Mohan Kumar <mohan at in.ibm.com>
Date:   Wed Dec 14 13:49:13 2011 +0530

    hw/9pfs: Add validation to {un}marshal code
    
    Signed-off-by: M. Mohan Kumar <mohan at in.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/fsdev/virtio-9p-marshal.c b/fsdev/virtio-9p-marshal.c
index 38fb99e..bf980bf 100644
--- a/fsdev/virtio-9p-marshal.c
+++ b/fsdev/virtio-9p-marshal.c
@@ -20,17 +20,12 @@
 #include <sys/uio.h>
 #include <string.h>
 #include <stdint.h>
+#include <errno.h>
 
 #include "compiler.h"
 #include "virtio-9p-marshal.h"
 #include "bswap.h"
 
-void v9fs_string_init(V9fsString *str)
-{
-    str->data = NULL;
-    str->size = 0;
-}
-
 void v9fs_string_free(V9fsString *str)
 {
     g_free(str->data);
@@ -62,11 +57,13 @@ void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
 }
 
 
-static size_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count,
-                              size_t offset, size_t size, int pack)
+static ssize_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count,
+                               size_t offset, size_t size, int pack)
 {
     int i = 0;
     size_t copied = 0;
+    size_t req_size = size;
+
 
     for (i = 0; size && i < sg_count; i++) {
         size_t len;
@@ -90,27 +87,33 @@ static size_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count,
             }
         }
     }
-
+    if (copied < req_size) {
+        /*
+         * We copied less that requested size. error out
+         */
+        return -ENOBUFS;
+    }
     return copied;
 }
 
-static size_t v9fs_unpack(void *dst, struct iovec *out_sg, int out_num,
-                          size_t offset, size_t size)
+static ssize_t v9fs_unpack(void *dst, struct iovec *out_sg, int out_num,
+                           size_t offset, size_t size)
 {
     return v9fs_packunpack(dst, out_sg, out_num, offset, size, 0);
 }
 
-size_t v9fs_pack(struct iovec *in_sg, int in_num, size_t offset,
-                const void *src, size_t size)
+ssize_t v9fs_pack(struct iovec *in_sg, int in_num, size_t offset,
+                  const void *src, size_t size)
 {
     return v9fs_packunpack((void *)src, in_sg, in_num, offset, size, 1);
 }
 
-size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
-                      int bswap, const char *fmt, ...)
+ssize_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
+                       int bswap, const char *fmt, ...)
 {
     int i;
     va_list ap;
+    ssize_t copied = 0;
     size_t old_offset = offset;
 
     va_start(ap, fmt);
@@ -118,13 +121,13 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
         switch (fmt[i]) {
         case 'b': {
             uint8_t *valp = va_arg(ap, uint8_t *);
-            offset += v9fs_unpack(valp, out_sg, out_num, offset, sizeof(*valp));
+            copied = v9fs_unpack(valp, out_sg, out_num, offset, sizeof(*valp));
             break;
         }
         case 'w': {
             uint16_t val, *valp;
             valp = va_arg(ap, uint16_t *);
-            offset += v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
+            copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
             if (bswap) {
                 *valp = le16_to_cpu(val);
             } else {
@@ -135,7 +138,7 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
         case 'd': {
             uint32_t val, *valp;
             valp = va_arg(ap, uint32_t *);
-            offset += v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
+            copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
             if (bswap) {
                 *valp = le32_to_cpu(val);
             } else {
@@ -146,7 +149,7 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
         case 'q': {
             uint64_t val, *valp;
             valp = va_arg(ap, uint64_t *);
-            offset += v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
+            copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
             if (bswap) {
                 *valp = le64_to_cpu(val);
             } else {
@@ -156,59 +159,70 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
         }
         case 's': {
             V9fsString *str = va_arg(ap, V9fsString *);
-            offset += v9fs_unmarshal(out_sg, out_num, offset, bswap,
-                            "w", &str->size);
-            /* FIXME: sanity check str->size */
-            str->data = g_malloc(str->size + 1);
-            offset += v9fs_unpack(str->data, out_sg, out_num, offset,
-                            str->size);
-            str->data[str->size] = 0;
+            copied = v9fs_unmarshal(out_sg, out_num, offset, bswap,
+                                    "w", &str->size);
+            if (copied > 0) {
+                offset += copied;
+                str->data = g_malloc(str->size + 1);
+                copied = v9fs_unpack(str->data, out_sg, out_num, offset,
+                                     str->size);
+                if (copied > 0) {
+                    str->data[str->size] = 0;
+                } else {
+                    v9fs_string_free(str);
+                }
+            }
             break;
         }
         case 'Q': {
             V9fsQID *qidp = va_arg(ap, V9fsQID *);
-            offset += v9fs_unmarshal(out_sg, out_num, offset, bswap, "bdq",
-                                     &qidp->type, &qidp->version, &qidp->path);
+            copied = v9fs_unmarshal(out_sg, out_num, offset, bswap, "bdq",
+                                    &qidp->type, &qidp->version, &qidp->path);
             break;
         }
         case 'S': {
             V9fsStat *statp = va_arg(ap, V9fsStat *);
-            offset += v9fs_unmarshal(out_sg, out_num, offset, bswap,
+            copied = v9fs_unmarshal(out_sg, out_num, offset, bswap,
                                     "wwdQdddqsssssddd",
-                                     &statp->size, &statp->type, &statp->dev,
-                                     &statp->qid, &statp->mode, &statp->atime,
-                                     &statp->mtime, &statp->length,
-                                     &statp->name, &statp->uid, &statp->gid,
-                                     &statp->muid, &statp->extension,
-                                     &statp->n_uid, &statp->n_gid,
-                                     &statp->n_muid);
+                                    &statp->size, &statp->type, &statp->dev,
+                                    &statp->qid, &statp->mode, &statp->atime,
+                                    &statp->mtime, &statp->length,
+                                    &statp->name, &statp->uid, &statp->gid,
+                                    &statp->muid, &statp->extension,
+                                    &statp->n_uid, &statp->n_gid,
+                                    &statp->n_muid);
             break;
         }
         case 'I': {
             V9fsIattr *iattr = va_arg(ap, V9fsIattr *);
-            offset += v9fs_unmarshal(out_sg, out_num, offset, bswap,
-                                     "ddddqqqqq",
-                                     &iattr->valid, &iattr->mode,
-                                     &iattr->uid, &iattr->gid, &iattr->size,
-                                     &iattr->atime_sec, &iattr->atime_nsec,
-                                     &iattr->mtime_sec, &iattr->mtime_nsec);
+            copied = v9fs_unmarshal(out_sg, out_num, offset, bswap,
+                                    "ddddqqqqq",
+                                    &iattr->valid, &iattr->mode,
+                                    &iattr->uid, &iattr->gid, &iattr->size,
+                                    &iattr->atime_sec, &iattr->atime_nsec,
+                                    &iattr->mtime_sec, &iattr->mtime_nsec);
             break;
         }
         default:
             break;
         }
+        if (copied < 0) {
+            va_end(ap);
+            return copied;
+        }
+        offset += copied;
     }
-
     va_end(ap);
 
     return offset - old_offset;
 }
 
-size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset,
-                    int bswap, const char *fmt, ...)
+ssize_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset,
+                     int bswap, const char *fmt, ...)
 {
     int i;
     va_list ap;
+    ssize_t copied = 0;
     size_t old_offset = offset;
 
     va_start(ap, fmt);
@@ -216,7 +230,7 @@ size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset,
         switch (fmt[i]) {
         case 'b': {
             uint8_t val = va_arg(ap, int);
-            offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
+            copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
             break;
         }
         case 'w': {
@@ -226,7 +240,7 @@ size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset,
             } else {
                 val =  va_arg(ap, int);
             }
-            offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
+            copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
             break;
         }
         case 'd': {
@@ -236,7 +250,7 @@ size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset,
             } else {
                 val =  va_arg(ap, uint32_t);
             }
-            offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
+            copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
             break;
         }
         case 'q': {
@@ -246,37 +260,40 @@ size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset,
             } else {
                 val =  va_arg(ap, uint64_t);
             }
-            offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
+            copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
             break;
         }
         case 's': {
             V9fsString *str = va_arg(ap, V9fsString *);
-            offset += v9fs_marshal(in_sg, in_num, offset, bswap,
-                            "w", str->size);
-            offset += v9fs_pack(in_sg, in_num, offset, str->data, str->size);
+            copied = v9fs_marshal(in_sg, in_num, offset, bswap,
+                                  "w", str->size);
+            if (copied > 0) {
+                offset += copied;
+                copied = v9fs_pack(in_sg, in_num, offset, str->data, str->size);
+            }
             break;
         }
         case 'Q': {
             V9fsQID *qidp = va_arg(ap, V9fsQID *);
-            offset += v9fs_marshal(in_sg, in_num, offset, bswap, "bdq",
-                                   qidp->type, qidp->version, qidp->path);
+            copied = v9fs_marshal(in_sg, in_num, offset, bswap, "bdq",
+                                  qidp->type, qidp->version, qidp->path);
             break;
         }
         case 'S': {
             V9fsStat *statp = va_arg(ap, V9fsStat *);
-            offset += v9fs_marshal(in_sg, in_num, offset, bswap,
-                                   "wwdQdddqsssssddd",
-                                   statp->size, statp->type, statp->dev,
-                                   &statp->qid, statp->mode, statp->atime,
-                                   statp->mtime, statp->length, &statp->name,
-                                   &statp->uid, &statp->gid, &statp->muid,
-                                   &statp->extension, statp->n_uid,
-                                   statp->n_gid, statp->n_muid);
+            copied = v9fs_marshal(in_sg, in_num, offset, bswap,
+                                  "wwdQdddqsssssddd",
+                                  statp->size, statp->type, statp->dev,
+                                  &statp->qid, statp->mode, statp->atime,
+                                  statp->mtime, statp->length, &statp->name,
+                                  &statp->uid, &statp->gid, &statp->muid,
+                                  &statp->extension, statp->n_uid,
+                                  statp->n_gid, statp->n_muid);
             break;
         }
         case 'A': {
             V9fsStatDotl *statp = va_arg(ap, V9fsStatDotl *);
-            offset += v9fs_marshal(in_sg, in_num, offset, bswap,
+            copied = v9fs_marshal(in_sg, in_num, offset, bswap,
                                    "qQdddqqqqqqqqqqqqqqq",
                                    statp->st_result_mask,
                                    &statp->qid, statp->st_mode,
@@ -294,6 +311,11 @@ size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset,
         default:
             break;
         }
+        if (copied < 0) {
+            va_end(ap);
+            return copied;
+        }
+        offset += copied;
     }
     va_end(ap);
 
diff --git a/fsdev/virtio-9p-marshal.h b/fsdev/virtio-9p-marshal.h
index f441400..5df65a8 100644
--- a/fsdev/virtio-9p-marshal.h
+++ b/fsdev/virtio-9p-marshal.h
@@ -71,17 +71,20 @@ typedef struct V9fsStatDotl {
     uint64_t st_data_version;
 } V9fsStatDotl;
 
-extern void v9fs_string_init(V9fsString *str);
+static inline void v9fs_string_init(V9fsString *str)
+{
+    str->data = NULL;
+    str->size = 0;
+}
 extern void v9fs_string_free(V9fsString *str);
 extern void v9fs_string_null(V9fsString *str);
 extern void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...);
 extern void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs);
 
-size_t v9fs_pack(struct iovec *in_sg, int in_num, size_t offset,
-                 const void *src, size_t size);
-size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
-                      int bswap, const char *fmt, ...);
-size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset,
-                    int bswap, const char *fmt, ...);
-
+ssize_t v9fs_pack(struct iovec *in_sg, int in_num, size_t offset,
+                  const void *src, size_t size);
+ssize_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
+                       int bswap, const char *fmt, ...);
+ssize_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset,
+                     int bswap, const char *fmt, ...);
 #endif
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 4bfee6c..e6ba6ba 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -590,6 +590,11 @@ static void free_pdu(V9fsState *s, V9fsPDU *pdu)
     }
 }
 
+/*
+ * We don't do error checking for pdu_marshal/unmarshal here
+ * because we always expect to have enough space to encode
+ * error details
+ */
 static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len)
 {
     int8_t id = pdu->id + 1; /* Response */
@@ -702,6 +707,15 @@ static int donttouch_stat(V9fsStat *stat)
     return 0;
 }
 
+static void v9fs_stat_init(V9fsStat *stat)
+{
+    v9fs_string_init(&stat->name);
+    v9fs_string_init(&stat->uid);
+    v9fs_string_init(&stat->gid);
+    v9fs_string_init(&stat->muid);
+    v9fs_string_init(&stat->extension);
+}
+
 static void v9fs_stat_free(V9fsStat *stat)
 {
     v9fs_string_free(&stat->name);
@@ -886,12 +900,18 @@ static inline bool is_ro_export(FsContext *ctx)
 
 static void v9fs_version(void *opaque)
 {
+    ssize_t err;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
     V9fsString version;
     size_t offset = 7;
 
-    pdu_unmarshal(pdu, offset, "ds", &s->msize, &version);
+    v9fs_string_init(&version);
+    err = pdu_unmarshal(pdu, offset, "ds", &s->msize, &version);
+    if (err < 0) {
+        offset = err;
+        goto out;
+    }
     trace_v9fs_version(pdu->tag, pdu->id, s->msize, version.data);
 
     virtfs_reset(pdu);
@@ -904,11 +924,15 @@ static void v9fs_version(void *opaque)
         v9fs_string_sprintf(&version, "unknown");
     }
 
-    offset += pdu_marshal(pdu, offset, "ds", s->msize, &version);
+    err = pdu_marshal(pdu, offset, "ds", s->msize, &version);
+    if (err < 0) {
+        offset = err;
+        goto out;
+    }
+    offset += err;
     trace_v9fs_version_return(pdu->tag, pdu->id, s->msize, version.data);
-
+out:
     complete_pdu(s, pdu, offset);
-
     v9fs_string_free(&version);
     return;
 }
@@ -924,7 +948,13 @@ static void v9fs_attach(void *opaque)
     V9fsQID qid;
     ssize_t err;
 
-    pdu_unmarshal(pdu, offset, "ddssd", &fid, &afid, &uname, &aname, &n_uname);
+    v9fs_string_init(&uname);
+    v9fs_string_init(&aname);
+    err = pdu_unmarshal(pdu, offset, "ddssd", &fid,
+                        &afid, &uname, &aname, &n_uname);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_attach(pdu->tag, pdu->id, fid, afid, uname.data, aname.data);
 
     fidp = alloc_fid(s, fid);
@@ -945,8 +975,12 @@ static void v9fs_attach(void *opaque)
         clunk_fid(s, fid);
         goto out;
     }
-    offset += pdu_marshal(pdu, offset, "Q", &qid);
-    err = offset;
+    err = pdu_marshal(pdu, offset, "Q", &qid);
+    if (err < 0) {
+        clunk_fid(s, fid);
+        goto out;
+    }
+    err += offset;
     trace_v9fs_attach_return(pdu->tag, pdu->id,
                              qid.type, qid.version, qid.path);
     s->root_fid = fid;
@@ -973,7 +1007,10 @@ static void v9fs_stat(void *opaque)
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
-    pdu_unmarshal(pdu, offset, "d", &fid);
+    err = pdu_unmarshal(pdu, offset, "d", &fid);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_stat(pdu->tag, pdu->id, fid);
 
     fidp = get_fid(pdu, fid);
@@ -989,10 +1026,14 @@ static void v9fs_stat(void *opaque)
     if (err < 0) {
         goto out;
     }
-    offset += pdu_marshal(pdu, offset, "wS", 0, &v9stat);
-    err = offset;
+    err = pdu_marshal(pdu, offset, "wS", 0, &v9stat);
+    if (err < 0) {
+        v9fs_stat_free(&v9stat);
+        goto out;
+    }
     trace_v9fs_stat_return(pdu->tag, pdu->id, v9stat.mode,
                            v9stat.atime, v9stat.mtime, v9stat.length);
+    err += offset;
     v9fs_stat_free(&v9stat);
 out:
     put_fid(pdu, fidp);
@@ -1012,7 +1053,10 @@ static void v9fs_getattr(void *opaque)
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
-    pdu_unmarshal(pdu, offset, "dq", &fid, &request_mask);
+    retval = pdu_unmarshal(pdu, offset, "dq", &fid, &request_mask);
+    if (retval < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_getattr(pdu->tag, pdu->id, fid, request_mask);
 
     fidp = get_fid(pdu, fid);
@@ -1038,8 +1082,11 @@ static void v9fs_getattr(void *opaque)
         }
         v9stat_dotl.st_result_mask |= P9_STATS_GEN;
     }
-    retval = offset;
-    retval += pdu_marshal(pdu, offset, "A", &v9stat_dotl);
+    retval = pdu_marshal(pdu, offset, "A", &v9stat_dotl);
+    if (retval < 0) {
+        goto out;
+    }
+    retval += offset;
     trace_v9fs_getattr_return(pdu->tag, pdu->id, v9stat_dotl.st_result_mask,
                               v9stat_dotl.st_mode, v9stat_dotl.st_uid,
                               v9stat_dotl.st_gid);
@@ -1072,7 +1119,10 @@ static void v9fs_setattr(void *opaque)
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
-    pdu_unmarshal(pdu, offset, "dI", &fid, &v9iattr);
+    err = pdu_unmarshal(pdu, offset, "dI", &fid, &v9iattr);
+    if (err < 0) {
+        goto out_nofid;
+    }
 
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
@@ -1147,10 +1197,20 @@ out_nofid:
 static int v9fs_walk_marshal(V9fsPDU *pdu, uint16_t nwnames, V9fsQID *qids)
 {
     int i;
+    ssize_t err;
     size_t offset = 7;
-    offset += pdu_marshal(pdu, offset, "w", nwnames);
+
+    err = pdu_marshal(pdu, offset, "w", nwnames);
+    if (err < 0) {
+        return err;
+    }
+    offset += err;
     for (i = 0; i < nwnames; i++) {
-        offset += pdu_marshal(pdu, offset, "Q", &qids[i]);
+        err = pdu_marshal(pdu, offset, "Q", &qids[i]);
+        if (err < 0) {
+            return err;
+        }
+        offset += err;
     }
     return offset;
 }
@@ -1171,8 +1231,12 @@ static void v9fs_walk(void *opaque)
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
-    offset += pdu_unmarshal(pdu, offset, "ddw", &fid,
-                            &newfid, &nwnames);
+    err = pdu_unmarshal(pdu, offset, "ddw", &fid, &newfid, &nwnames);
+    if (err < 0) {
+        complete_pdu(s, pdu, err);
+        return ;
+    }
+    offset += err;
 
     trace_v9fs_walk(pdu->tag, pdu->id, fid, newfid, nwnames);
 
@@ -1180,7 +1244,11 @@ static void v9fs_walk(void *opaque)
         wnames = g_malloc0(sizeof(wnames[0]) * nwnames);
         qids   = g_malloc0(sizeof(qids[0]) * nwnames);
         for (i = 0; i < nwnames; i++) {
-            offset += pdu_unmarshal(pdu, offset, "s", &wnames[i]);
+            err = pdu_unmarshal(pdu, offset, "s", &wnames[i]);
+            if (err < 0) {
+                goto out_nofid;
+            }
+            offset += err;
         }
     } else if (nwnames > P9_MAXWELEM) {
         err = -EINVAL;
@@ -1279,9 +1347,12 @@ static void v9fs_open(void *opaque)
     V9fsState *s = pdu->s;
 
     if (s->proto_version == V9FS_PROTO_2000L) {
-        pdu_unmarshal(pdu, offset, "dd", &fid, &mode);
+        err = pdu_unmarshal(pdu, offset, "dd", &fid, &mode);
     } else {
-        pdu_unmarshal(pdu, offset, "db", &fid, &mode);
+        err = pdu_unmarshal(pdu, offset, "db", &fid, &mode);
+    }
+    if (err < 0) {
+        goto out_nofid;
     }
     trace_v9fs_open(pdu->tag, pdu->id, fid, mode);
 
@@ -1303,8 +1374,11 @@ static void v9fs_open(void *opaque)
             goto out;
         }
         fidp->fid_type = P9_FID_DIR;
-        offset += pdu_marshal(pdu, offset, "Qd", &qid, 0);
-        err = offset;
+        err = pdu_marshal(pdu, offset, "Qd", &qid, 0);
+        if (err < 0) {
+            goto out;
+        }
+        err += offset;
     } else {
         if (s->proto_version == V9FS_PROTO_2000L) {
             flags = get_dotl_openflags(s, mode);
@@ -1333,8 +1407,11 @@ static void v9fs_open(void *opaque)
             fidp->flags |= FID_NON_RECLAIMABLE;
         }
         iounit = get_iounit(pdu, &fidp->path);
-        offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
-        err = offset;
+        err = pdu_marshal(pdu, offset, "Qd", &qid, iounit);
+        if (err < 0) {
+            goto out;
+        }
+        err += offset;
     }
     trace_v9fs_open_return(pdu->tag, pdu->id,
                            qid.type, qid.version, qid.path, iounit);
@@ -1357,8 +1434,12 @@ static void v9fs_lcreate(void *opaque)
     int32_t iounit;
     V9fsPDU *pdu = opaque;
 
-    pdu_unmarshal(pdu, offset, "dsddd", &dfid, &name, &flags,
-                  &mode, &gid);
+    v9fs_string_init(&name);
+    err = pdu_unmarshal(pdu, offset, "dsddd", &dfid,
+                        &name, &flags, &mode, &gid);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_lcreate(pdu->tag, pdu->id, dfid, flags, mode, gid);
 
     fidp = get_fid(pdu, dfid);
@@ -1384,8 +1465,11 @@ static void v9fs_lcreate(void *opaque)
     }
     iounit =  get_iounit(pdu, &fidp->path);
     stat_to_qid(&stbuf, &qid);
-    offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
-    err = offset;
+    err = pdu_marshal(pdu, offset, "Qd", &qid, iounit);
+    if (err < 0) {
+        goto out;
+    }
+    err += offset;
     trace_v9fs_lcreate_return(pdu->tag, pdu->id,
                               qid.type, qid.version, qid.path, iounit);
 out:
@@ -1405,7 +1489,10 @@ static void v9fs_fsync(void *opaque)
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
-    pdu_unmarshal(pdu, offset, "dd", &fid, &datasync);
+    err = pdu_unmarshal(pdu, offset, "dd", &fid, &datasync);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_fsync(pdu->tag, pdu->id, fid, datasync);
 
     fidp = get_fid(pdu, fid);
@@ -1431,7 +1518,10 @@ static void v9fs_clunk(void *opaque)
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
-    pdu_unmarshal(pdu, offset, "d", &fid);
+    err = pdu_unmarshal(pdu, offset, "d", &fid);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_clunk(pdu->tag, pdu->id, fid);
 
     fidp = clunk_fid(s, fid);
@@ -1454,6 +1544,7 @@ out_nofid:
 static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
                            uint64_t off, uint32_t max_count)
 {
+    ssize_t err;
     size_t offset = 7;
     int read_count;
     int64_t xattr_len;
@@ -1468,11 +1559,18 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
          */
         read_count = 0;
     }
-    offset += pdu_marshal(pdu, offset, "d", read_count);
-    offset += v9fs_pack(pdu->elem.in_sg, pdu->elem.in_num, offset,
-                        ((char *)fidp->fs.xattr.value) + off,
-                        read_count);
-
+    err = pdu_marshal(pdu, offset, "d", read_count);
+    if (err < 0) {
+        return err;
+    }
+    offset += err;
+    err = v9fs_pack(pdu->elem.in_sg, pdu->elem.in_num, offset,
+                    ((char *)fidp->fs.xattr.value) + off,
+                    read_count);
+    if (err < 0) {
+        return err;
+    }
+    offset += err;
     return offset;
 }
 
@@ -1581,7 +1679,10 @@ static void v9fs_read(void *opaque)
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
-    pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &max_count);
+    err = pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &max_count);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_read(pdu->tag, pdu->id, fid, off, max_count);
 
     fidp = get_fid(pdu, fid);
@@ -1599,9 +1700,11 @@ static void v9fs_read(void *opaque)
             err = count;
             goto out;
         }
-        err = offset;
-        err += pdu_marshal(pdu, offset, "d", count);
-        err += count;
+        err = pdu_marshal(pdu, offset, "d", count);
+        if (err < 0) {
+            goto out;
+        }
+        err += offset + count;
     } else if (fidp->fid_type == P9_FID_FILE) {
         QEMUIOVector qiov_full;
         QEMUIOVector qiov;
@@ -1629,9 +1732,11 @@ static void v9fs_read(void *opaque)
                 goto out;
             }
         } while (count < max_count && len > 0);
-        err = offset;
-        err += pdu_marshal(pdu, offset, "d", count);
-        err += count;
+        err = pdu_marshal(pdu, offset, "d", count);
+        if (err < 0) {
+            goto out;
+        }
+        err += offset + count;
         qemu_iovec_destroy(&qiov);
         qemu_iovec_destroy(&qiov_full);
     } else if (fidp->fid_type == P9_FID_XATTR) {
@@ -1703,6 +1808,12 @@ static int v9fs_do_readdir(V9fsPDU *pdu,
         len = pdu_marshal(pdu, 11 + count, "Qqbs",
                           &qid, dent->d_off,
                           dent->d_type, &name);
+        if (len < 0) {
+            v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
+            v9fs_string_free(&name);
+            g_free(dent);
+            return len;
+        }
         count += len;
         v9fs_string_free(&name);
         saved_dir_pos = dent->d_off;
@@ -1726,8 +1837,11 @@ static void v9fs_readdir(void *opaque)
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
-    pdu_unmarshal(pdu, offset, "dqd", &fid, &initial_offset, &max_count);
-
+    retval = pdu_unmarshal(pdu, offset, "dqd", &fid,
+                           &initial_offset, &max_count);
+    if (retval < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_readdir(pdu->tag, pdu->id, fid, initial_offset, max_count);
 
     fidp = get_fid(pdu, fid);
@@ -1749,9 +1863,11 @@ static void v9fs_readdir(void *opaque)
         retval = count;
         goto out;
     }
-    retval = offset;
-    retval += pdu_marshal(pdu, offset, "d", count);
-    retval += count;
+    retval = pdu_marshal(pdu, offset, "d", count);
+    if (retval < 0) {
+        goto out;
+    }
+    retval += count + offset;
     trace_v9fs_readdir_return(pdu->tag, pdu->id, count, retval);
 out:
     put_fid(pdu, fidp);
@@ -1782,8 +1898,11 @@ static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
         err = -ENOSPC;
         goto out;
     }
-    offset += pdu_marshal(pdu, offset, "d", write_count);
-    err = offset;
+    err = pdu_marshal(pdu, offset, "d", write_count);
+    if (err < 0) {
+        return err;
+    }
+    err += offset;
     fidp->fs.xattr.copied_len += write_count;
     /*
      * Now copy the content from sg list
@@ -1818,7 +1937,11 @@ static void v9fs_write(void *opaque)
     QEMUIOVector qiov_full;
     QEMUIOVector qiov;
 
-    offset += pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &count);
+    err = pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &count);
+    if (err < 0) {
+        return complete_pdu(s, pdu, err);
+    }
+    offset += err;
     v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset, count, true);
     trace_v9fs_write(pdu->tag, pdu->id, fid, off, count, qiov_full.niov);
 
@@ -1866,8 +1989,11 @@ static void v9fs_write(void *opaque)
     } while (total < count && len > 0);
 
     offset = 7;
-    offset += pdu_marshal(pdu, offset, "d", total);
-    err = offset;
+    err = pdu_marshal(pdu, offset, "d", total);
+    if (err < 0) {
+        goto out;
+    }
+    err += offset;
     trace_v9fs_write_return(pdu->tag, pdu->id, total, err);
 out_qiov:
     qemu_iovec_destroy(&qiov);
@@ -1895,10 +2021,13 @@ static void v9fs_create(void *opaque)
     V9fsPDU *pdu = opaque;
 
     v9fs_path_init(&path);
-
-    pdu_unmarshal(pdu, offset, "dsdbs", &fid, &name,
-                  &perm, &mode, &extension);
-
+    v9fs_string_init(&name);
+    v9fs_string_init(&extension);
+    err = pdu_unmarshal(pdu, offset, "dsdbs", &fid, &name,
+                        &perm, &mode, &extension);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_create(pdu->tag, pdu->id, fid, name.data, perm, mode);
 
     fidp = get_fid(pdu, fid);
@@ -2029,8 +2158,11 @@ static void v9fs_create(void *opaque)
     }
     iounit = get_iounit(pdu, &fidp->path);
     stat_to_qid(&stbuf, &qid);
-    offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
-    err = offset;
+    err = pdu_marshal(pdu, offset, "Qd", &qid, iounit);
+    if (err < 0) {
+        goto out;
+    }
+    err += offset;
     trace_v9fs_create_return(pdu->tag, pdu->id,
                              qid.type, qid.version, qid.path, iounit);
 out:
@@ -2055,7 +2187,12 @@ static void v9fs_symlink(void *opaque)
     gid_t gid;
     size_t offset = 7;
 
-    pdu_unmarshal(pdu, offset, "dssd", &dfid, &name, &symname, &gid);
+    v9fs_string_init(&name);
+    v9fs_string_init(&symname);
+    err = pdu_unmarshal(pdu, offset, "dssd", &dfid, &name, &symname, &gid);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_symlink(pdu->tag, pdu->id, dfid, name.data, symname.data, gid);
 
     dfidp = get_fid(pdu, dfid);
@@ -2068,8 +2205,11 @@ static void v9fs_symlink(void *opaque)
         goto out;
     }
     stat_to_qid(&stbuf, &qid);
-    offset += pdu_marshal(pdu, offset, "Q", &qid);
-    err = offset;
+    err =  pdu_marshal(pdu, offset, "Q", &qid);
+    if (err < 0) {
+        goto out;
+    }
+    err += offset;
     trace_v9fs_symlink_return(pdu->tag, pdu->id,
                               qid.type, qid.version, qid.path);
 out:
@@ -2082,13 +2222,18 @@ out_nofid:
 
 static void v9fs_flush(void *opaque)
 {
+    ssize_t err;
     int16_t tag;
     size_t offset = 7;
     V9fsPDU *cancel_pdu;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
-    pdu_unmarshal(pdu, offset, "w", &tag);
+    err = pdu_unmarshal(pdu, offset, "w", &tag);
+    if (err < 0) {
+        complete_pdu(s, pdu, err);
+        return;
+    }
     trace_v9fs_flush(pdu->tag, pdu->id, tag);
 
     QLIST_FOREACH(cancel_pdu, &s->active_list, next) {
@@ -2119,7 +2264,11 @@ static void v9fs_link(void *opaque)
     size_t offset = 7;
     int err = 0;
 
-    pdu_unmarshal(pdu, offset, "dds", &dfid, &oldfid, &name);
+    v9fs_string_init(&name);
+    err = pdu_unmarshal(pdu, offset, "dds", &dfid, &oldfid, &name);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_link(pdu->tag, pdu->id, dfid, oldfid, name.data);
 
     dfidp = get_fid(pdu, dfid);
@@ -2153,7 +2302,10 @@ static void v9fs_remove(void *opaque)
     V9fsFidState *fidp;
     V9fsPDU *pdu = opaque;
 
-    pdu_unmarshal(pdu, offset, "d", &fid);
+    err = pdu_unmarshal(pdu, offset, "d", &fid);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_remove(pdu->tag, pdu->id, fid);
 
     fidp = get_fid(pdu, fid);
@@ -2196,8 +2348,11 @@ static void v9fs_unlinkat(void *opaque)
     V9fsFidState *dfidp;
     V9fsPDU *pdu = opaque;
 
-    pdu_unmarshal(pdu, offset, "dsd", &dfid, &name, &flags);
-
+    v9fs_string_init(&name);
+    err = pdu_unmarshal(pdu, offset, "dsd", &dfid, &name, &flags);
+    if (err < 0) {
+        goto out_nofid;
+    }
     dfidp = get_fid(pdu, dfid);
     if (dfidp == NULL) {
         err = -EINVAL;
@@ -2299,8 +2454,11 @@ static void v9fs_rename(void *opaque)
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
-    pdu_unmarshal(pdu, offset, "dds", &fid, &newdirfid, &name);
-
+    v9fs_string_init(&name);
+    err = pdu_unmarshal(pdu, offset, "dds", &fid, &newdirfid, &name);
+    if (err < 0) {
+        goto out_nofid;
+    }
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
         err = -ENOENT;
@@ -2405,8 +2563,13 @@ static void v9fs_renameat(void *opaque)
     int32_t olddirfid, newdirfid;
     V9fsString old_name, new_name;
 
-    pdu_unmarshal(pdu, offset, "dsds", &olddirfid,
-                  &old_name, &newdirfid, &new_name);
+    v9fs_string_init(&old_name);
+    v9fs_string_init(&new_name);
+    err = pdu_unmarshal(pdu, offset, "dsds", &olddirfid,
+                        &old_name, &newdirfid, &new_name);
+    if (err < 0) {
+        goto out_err;
+    }
 
     v9fs_path_write_lock(s);
     err = v9fs_complete_renameat(pdu, olddirfid,
@@ -2415,6 +2578,8 @@ static void v9fs_renameat(void *opaque)
     if (!err) {
         err = offset;
     }
+
+out_err:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&old_name);
     v9fs_string_free(&new_name);
@@ -2432,7 +2597,11 @@ static void v9fs_wstat(void *opaque)
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
-    pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat);
+    v9fs_stat_init(&v9stat);
+    err = pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_wstat(pdu->tag, pdu->id, fid,
                      v9stat.mode, v9stat.atime, v9stat.mtime);
 
@@ -2566,7 +2735,10 @@ static void v9fs_statfs(void *opaque)
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
-    pdu_unmarshal(pdu, offset, "d", &fid);
+    retval = pdu_unmarshal(pdu, offset, "d", &fid);
+    if (retval < 0) {
+        goto out_nofid;
+    }
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
         retval = -ENOENT;
@@ -2576,8 +2748,11 @@ static void v9fs_statfs(void *opaque)
     if (retval < 0) {
         goto out;
     }
-    retval = offset;
-    retval += v9fs_fill_statfs(s, pdu, &stbuf);
+    retval = v9fs_fill_statfs(s, pdu, &stbuf);
+    if (retval < 0) {
+        goto out;
+    }
+    retval += offset;
 out:
     put_fid(pdu, fidp);
 out_nofid:
@@ -2601,8 +2776,12 @@ static void v9fs_mknod(void *opaque)
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
-    pdu_unmarshal(pdu, offset, "dsdddd", &fid, &name, &mode,
-                  &major, &minor, &gid);
+    v9fs_string_init(&name);
+    err = pdu_unmarshal(pdu, offset, "dsdddd", &fid, &name, &mode,
+                        &major, &minor, &gid);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_mknod(pdu->tag, pdu->id, fid, mode, major, minor);
 
     fidp = get_fid(pdu, fid);
@@ -2616,8 +2795,11 @@ static void v9fs_mknod(void *opaque)
         goto out;
     }
     stat_to_qid(&stbuf, &qid);
-    err = offset;
-    err += pdu_marshal(pdu, offset, "Q", &qid);
+    err = pdu_marshal(pdu, offset, "Q", &qid);
+    if (err < 0) {
+        goto out;
+    }
+    err += offset;
     trace_v9fs_mknod_return(pdu->tag, pdu->id,
                             qid.type, qid.version, qid.path);
 out:
@@ -2638,7 +2820,7 @@ out_nofid:
 static void v9fs_lock(void *opaque)
 {
     int8_t status;
-    V9fsFlock *flock;
+    V9fsFlock flock;
     size_t offset = 7;
     struct stat stbuf;
     V9fsFidState *fidp;
@@ -2646,18 +2828,20 @@ static void v9fs_lock(void *opaque)
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
-    flock = g_malloc(sizeof(*flock));
-    pdu_unmarshal(pdu, offset, "dbdqqds", &fid, &flock->type,
-                  &flock->flags, &flock->start, &flock->length,
-                  &flock->proc_id, &flock->client_id);
-
+    status = P9_LOCK_ERROR;
+    v9fs_string_init(&flock.client_id);
+    err = pdu_unmarshal(pdu, offset, "dbdqqds", &fid, &flock.type,
+                        &flock.flags, &flock.start, &flock.length,
+                        &flock.proc_id, &flock.client_id);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_lock(pdu->tag, pdu->id, fid,
-                    flock->type, flock->start, flock->length);
+                    flock.type, flock.start, flock.length);
 
-    status = P9_LOCK_ERROR;
 
     /* We support only block flag now (that too ignored currently) */
-    if (flock->flags & ~P9_LOCK_FLAGS_BLOCK) {
+    if (flock.flags & ~P9_LOCK_FLAGS_BLOCK) {
         err = -EINVAL;
         goto out_nofid;
     }
@@ -2674,12 +2858,13 @@ static void v9fs_lock(void *opaque)
 out:
     put_fid(pdu, fidp);
 out_nofid:
-    err = offset;
-    err += pdu_marshal(pdu, offset, "b", status);
+    err = pdu_marshal(pdu, offset, "b", status);
+    if (err > 0) {
+        err += offset;
+    }
     trace_v9fs_lock_return(pdu->tag, pdu->id, status);
     complete_pdu(s, pdu, err);
-    v9fs_string_free(&flock->client_id);
-    g_free(flock);
+    v9fs_string_free(&flock.client_id);
 }
 
 /*
@@ -2691,18 +2876,20 @@ static void v9fs_getlock(void *opaque)
     size_t offset = 7;
     struct stat stbuf;
     V9fsFidState *fidp;
-    V9fsGetlock *glock;
+    V9fsGetlock glock;
     int32_t fid, err = 0;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
-    glock = g_malloc(sizeof(*glock));
-    pdu_unmarshal(pdu, offset, "dbqqds", &fid, &glock->type,
-                  &glock->start, &glock->length, &glock->proc_id,
-                  &glock->client_id);
-
+    v9fs_string_init(&glock.client_id);
+    err = pdu_unmarshal(pdu, offset, "dbqqds", &fid, &glock.type,
+                        &glock.start, &glock.length, &glock.proc_id,
+                        &glock.client_id);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_getlock(pdu->tag, pdu->id, fid,
-                       glock->type, glock->start, glock->length);
+                       glock.type, glock.start, glock.length);
 
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
@@ -2713,19 +2900,21 @@ static void v9fs_getlock(void *opaque)
     if (err < 0) {
         goto out;
     }
-    glock->type = P9_LOCK_TYPE_UNLCK;
-    offset += pdu_marshal(pdu, offset, "bqqds", glock->type,
-                          glock->start, glock->length, glock->proc_id,
-                          &glock->client_id);
-    err = offset;
-    trace_v9fs_getlock_return(pdu->tag, pdu->id, glock->type, glock->start,
-                              glock->length, glock->proc_id);
+    glock.type = P9_LOCK_TYPE_UNLCK;
+    err = pdu_marshal(pdu, offset, "bqqds", glock.type,
+                          glock.start, glock.length, glock.proc_id,
+                          &glock.client_id);
+    if (err < 0) {
+        goto out;
+    }
+    err += offset;
+    trace_v9fs_getlock_return(pdu->tag, pdu->id, glock.type, glock.start,
+                              glock.length, glock.proc_id);
 out:
     put_fid(pdu, fidp);
 out_nofid:
     complete_pdu(s, pdu, err);
-    v9fs_string_free(&glock->client_id);
-    g_free(glock);
+    v9fs_string_free(&glock.client_id);
 }
 
 static void v9fs_mkdir(void *opaque)
@@ -2741,8 +2930,11 @@ static void v9fs_mkdir(void *opaque)
     int mode;
     int err = 0;
 
-    pdu_unmarshal(pdu, offset, "dsdd", &fid, &name, &mode, &gid);
-
+    v9fs_string_init(&name);
+    err = pdu_unmarshal(pdu, offset, "dsdd", &fid, &name, &mode, &gid);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_mkdir(pdu->tag, pdu->id, fid, name.data, mode, gid);
 
     fidp = get_fid(pdu, fid);
@@ -2755,8 +2947,11 @@ static void v9fs_mkdir(void *opaque)
         goto out;
     }
     stat_to_qid(&stbuf, &qid);
-    offset += pdu_marshal(pdu, offset, "Q", &qid);
-    err = offset;
+    err = pdu_marshal(pdu, offset, "Q", &qid);
+    if (err < 0) {
+        goto out;
+    }
+    err += offset;
     trace_v9fs_mkdir_return(pdu->tag, pdu->id,
                             qid.type, qid.version, qid.path, err);
 out:
@@ -2778,7 +2973,11 @@ static void v9fs_xattrwalk(void *opaque)
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
-    pdu_unmarshal(pdu, offset, "dds", &fid, &newfid, &name);
+    v9fs_string_init(&name);
+    err = pdu_unmarshal(pdu, offset, "dds", &fid, &newfid, &name);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_xattrwalk(pdu->tag, pdu->id, fid, newfid, name.data);
 
     file_fidp = get_fid(pdu, fid);
@@ -2792,7 +2991,7 @@ static void v9fs_xattrwalk(void *opaque)
         goto out;
     }
     v9fs_path_copy(&xattr_fidp->path, &file_fidp->path);
-    if (name.data[0] == 0) {
+    if (name.data == NULL) {
         /*
          * listxattr request. Get the size first
          */
@@ -2818,8 +3017,11 @@ static void v9fs_xattrwalk(void *opaque)
                 goto out;
             }
         }
-        offset += pdu_marshal(pdu, offset, "q", size);
-        err = offset;
+        err = pdu_marshal(pdu, offset, "q", size);
+        if (err < 0) {
+            goto out;
+        }
+        err += offset;
     } else {
         /*
          * specific xattr fid. We check for xattr
@@ -2848,8 +3050,11 @@ static void v9fs_xattrwalk(void *opaque)
                 goto out;
             }
         }
-        offset += pdu_marshal(pdu, offset, "q", size);
-        err = offset;
+        err = pdu_marshal(pdu, offset, "q", size);
+        if (err < 0) {
+            goto out;
+        }
+        err += offset;
     }
     trace_v9fs_xattrwalk_return(pdu->tag, pdu->id, size);
 out:
@@ -2875,8 +3080,11 @@ static void v9fs_xattrcreate(void *opaque)
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
-    pdu_unmarshal(pdu, offset, "dsqd",
-                  &fid, &name, &size, &flags);
+    v9fs_string_init(&name);
+    err = pdu_unmarshal(pdu, offset, "dsqd", &fid, &name, &size, &flags);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_xattrcreate(pdu->tag, pdu->id, fid, name.data, size, flags);
 
     file_fidp = get_fid(pdu, fid);
@@ -2913,7 +3121,10 @@ static void v9fs_readlink(void *opaque)
     int err = 0;
     V9fsFidState *fidp;
 
-    pdu_unmarshal(pdu, offset, "d", &fid);
+    err = pdu_unmarshal(pdu, offset, "d", &fid);
+    if (err < 0) {
+        goto out_nofid;
+    }
     trace_v9fs_readlink(pdu->tag, pdu->id, fid);
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
@@ -2926,8 +3137,12 @@ static void v9fs_readlink(void *opaque)
     if (err < 0) {
         goto out;
     }
-    offset += pdu_marshal(pdu, offset, "s", &target);
-    err = offset;
+    err = pdu_marshal(pdu, offset, "s", &target);
+    if (err < 0) {
+        v9fs_string_free(&target);
+        goto out;
+    }
+    err += offset;
     trace_v9fs_readlink_return(pdu->tag, pdu->id, target.data);
     v9fs_string_free(&target);
 out:
commit 10925bf089024eb5157e78618a5d8864e29f243e
Author: M. Mohan Kumar <mohan at in.ibm.com>
Date:   Wed Dec 14 13:49:06 2011 +0530

    hw/9pfs: Move pdu_marshal/unmarshal code to a seperate file
    
    Move p9 marshaling/unmarshaling code to a separate file so that
    proxy filesytem driver can use these calls. Also made marshaling
    code generic to accept "struct iovec" instead of V9fsPDU.
    
    Signed-off-by: M. Mohan Kumar <mohan at in.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/Makefile.objs b/Makefile.objs
index 8813673..35cd645 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -61,7 +61,7 @@ ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
 # Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
 # only pull in the actual virtio-9p device if we also enabled virtio.
 CONFIG_REALLY_VIRTFS=y
-fsdev-nested-y = qemu-fsdev.o
+fsdev-nested-y = qemu-fsdev.o virtio-9p-marshal.o
 else
 fsdev-nested-y = qemu-fsdev-dummy.o
 endif
diff --git a/fsdev/virtio-9p-marshal.c b/fsdev/virtio-9p-marshal.c
new file mode 100644
index 0000000..38fb99e
--- /dev/null
+++ b/fsdev/virtio-9p-marshal.c
@@ -0,0 +1,301 @@
+/*
+ * Virtio 9p backend
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/time.h>
+#include <utime.h>
+#include <sys/uio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "compiler.h"
+#include "virtio-9p-marshal.h"
+#include "bswap.h"
+
+void v9fs_string_init(V9fsString *str)
+{
+    str->data = NULL;
+    str->size = 0;
+}
+
+void v9fs_string_free(V9fsString *str)
+{
+    g_free(str->data);
+    str->data = NULL;
+    str->size = 0;
+}
+
+void v9fs_string_null(V9fsString *str)
+{
+    v9fs_string_free(str);
+}
+
+void GCC_FMT_ATTR(2, 3)
+v9fs_string_sprintf(V9fsString *str, const char *fmt, ...)
+{
+    va_list ap;
+
+    v9fs_string_free(str);
+
+    va_start(ap, fmt);
+    str->size = g_vasprintf(&str->data, fmt, ap);
+    va_end(ap);
+}
+
+void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
+{
+    v9fs_string_free(lhs);
+    v9fs_string_sprintf(lhs, "%s", rhs->data);
+}
+
+
+static size_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count,
+                              size_t offset, size_t size, int pack)
+{
+    int i = 0;
+    size_t copied = 0;
+
+    for (i = 0; size && i < sg_count; i++) {
+        size_t len;
+        if (offset >= sg[i].iov_len) {
+            /* skip this sg */
+            offset -= sg[i].iov_len;
+            continue;
+        } else {
+            len = MIN(sg[i].iov_len - offset, size);
+            if (pack) {
+                memcpy(sg[i].iov_base + offset, addr, len);
+            } else {
+                memcpy(addr, sg[i].iov_base + offset, len);
+            }
+            size -= len;
+            copied += len;
+            addr += len;
+            if (size) {
+                offset = 0;
+                continue;
+            }
+        }
+    }
+
+    return copied;
+}
+
+static size_t v9fs_unpack(void *dst, struct iovec *out_sg, int out_num,
+                          size_t offset, size_t size)
+{
+    return v9fs_packunpack(dst, out_sg, out_num, offset, size, 0);
+}
+
+size_t v9fs_pack(struct iovec *in_sg, int in_num, size_t offset,
+                const void *src, size_t size)
+{
+    return v9fs_packunpack((void *)src, in_sg, in_num, offset, size, 1);
+}
+
+size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
+                      int bswap, const char *fmt, ...)
+{
+    int i;
+    va_list ap;
+    size_t old_offset = offset;
+
+    va_start(ap, fmt);
+    for (i = 0; fmt[i]; i++) {
+        switch (fmt[i]) {
+        case 'b': {
+            uint8_t *valp = va_arg(ap, uint8_t *);
+            offset += v9fs_unpack(valp, out_sg, out_num, offset, sizeof(*valp));
+            break;
+        }
+        case 'w': {
+            uint16_t val, *valp;
+            valp = va_arg(ap, uint16_t *);
+            offset += v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
+            if (bswap) {
+                *valp = le16_to_cpu(val);
+            } else {
+                *valp = val;
+            }
+            break;
+        }
+        case 'd': {
+            uint32_t val, *valp;
+            valp = va_arg(ap, uint32_t *);
+            offset += v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
+            if (bswap) {
+                *valp = le32_to_cpu(val);
+            } else {
+                *valp = val;
+            }
+            break;
+        }
+        case 'q': {
+            uint64_t val, *valp;
+            valp = va_arg(ap, uint64_t *);
+            offset += v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
+            if (bswap) {
+                *valp = le64_to_cpu(val);
+            } else {
+                *valp = val;
+            }
+            break;
+        }
+        case 's': {
+            V9fsString *str = va_arg(ap, V9fsString *);
+            offset += v9fs_unmarshal(out_sg, out_num, offset, bswap,
+                            "w", &str->size);
+            /* FIXME: sanity check str->size */
+            str->data = g_malloc(str->size + 1);
+            offset += v9fs_unpack(str->data, out_sg, out_num, offset,
+                            str->size);
+            str->data[str->size] = 0;
+            break;
+        }
+        case 'Q': {
+            V9fsQID *qidp = va_arg(ap, V9fsQID *);
+            offset += v9fs_unmarshal(out_sg, out_num, offset, bswap, "bdq",
+                                     &qidp->type, &qidp->version, &qidp->path);
+            break;
+        }
+        case 'S': {
+            V9fsStat *statp = va_arg(ap, V9fsStat *);
+            offset += v9fs_unmarshal(out_sg, out_num, offset, bswap,
+                                    "wwdQdddqsssssddd",
+                                     &statp->size, &statp->type, &statp->dev,
+                                     &statp->qid, &statp->mode, &statp->atime,
+                                     &statp->mtime, &statp->length,
+                                     &statp->name, &statp->uid, &statp->gid,
+                                     &statp->muid, &statp->extension,
+                                     &statp->n_uid, &statp->n_gid,
+                                     &statp->n_muid);
+            break;
+        }
+        case 'I': {
+            V9fsIattr *iattr = va_arg(ap, V9fsIattr *);
+            offset += v9fs_unmarshal(out_sg, out_num, offset, bswap,
+                                     "ddddqqqqq",
+                                     &iattr->valid, &iattr->mode,
+                                     &iattr->uid, &iattr->gid, &iattr->size,
+                                     &iattr->atime_sec, &iattr->atime_nsec,
+                                     &iattr->mtime_sec, &iattr->mtime_nsec);
+            break;
+        }
+        default:
+            break;
+        }
+    }
+
+    va_end(ap);
+
+    return offset - old_offset;
+}
+
+size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset,
+                    int bswap, const char *fmt, ...)
+{
+    int i;
+    va_list ap;
+    size_t old_offset = offset;
+
+    va_start(ap, fmt);
+    for (i = 0; fmt[i]; i++) {
+        switch (fmt[i]) {
+        case 'b': {
+            uint8_t val = va_arg(ap, int);
+            offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
+            break;
+        }
+        case 'w': {
+            uint16_t val;
+            if (bswap) {
+                cpu_to_le16w(&val, va_arg(ap, int));
+            } else {
+                val =  va_arg(ap, int);
+            }
+            offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
+            break;
+        }
+        case 'd': {
+            uint32_t val;
+            if (bswap) {
+                cpu_to_le32w(&val, va_arg(ap, uint32_t));
+            } else {
+                val =  va_arg(ap, uint32_t);
+            }
+            offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
+            break;
+        }
+        case 'q': {
+            uint64_t val;
+            if (bswap) {
+                cpu_to_le64w(&val, va_arg(ap, uint64_t));
+            } else {
+                val =  va_arg(ap, uint64_t);
+            }
+            offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
+            break;
+        }
+        case 's': {
+            V9fsString *str = va_arg(ap, V9fsString *);
+            offset += v9fs_marshal(in_sg, in_num, offset, bswap,
+                            "w", str->size);
+            offset += v9fs_pack(in_sg, in_num, offset, str->data, str->size);
+            break;
+        }
+        case 'Q': {
+            V9fsQID *qidp = va_arg(ap, V9fsQID *);
+            offset += v9fs_marshal(in_sg, in_num, offset, bswap, "bdq",
+                                   qidp->type, qidp->version, qidp->path);
+            break;
+        }
+        case 'S': {
+            V9fsStat *statp = va_arg(ap, V9fsStat *);
+            offset += v9fs_marshal(in_sg, in_num, offset, bswap,
+                                   "wwdQdddqsssssddd",
+                                   statp->size, statp->type, statp->dev,
+                                   &statp->qid, statp->mode, statp->atime,
+                                   statp->mtime, statp->length, &statp->name,
+                                   &statp->uid, &statp->gid, &statp->muid,
+                                   &statp->extension, statp->n_uid,
+                                   statp->n_gid, statp->n_muid);
+            break;
+        }
+        case 'A': {
+            V9fsStatDotl *statp = va_arg(ap, V9fsStatDotl *);
+            offset += v9fs_marshal(in_sg, in_num, offset, bswap,
+                                   "qQdddqqqqqqqqqqqqqqq",
+                                   statp->st_result_mask,
+                                   &statp->qid, statp->st_mode,
+                                   statp->st_uid, statp->st_gid,
+                                   statp->st_nlink, statp->st_rdev,
+                                   statp->st_size, statp->st_blksize,
+                                   statp->st_blocks, statp->st_atime_sec,
+                                   statp->st_atime_nsec, statp->st_mtime_sec,
+                                   statp->st_mtime_nsec, statp->st_ctime_sec,
+                                   statp->st_ctime_nsec, statp->st_btime_sec,
+                                   statp->st_btime_nsec, statp->st_gen,
+                                   statp->st_data_version);
+            break;
+        }
+        default:
+            break;
+        }
+    }
+    va_end(ap);
+
+    return offset - old_offset;
+}
diff --git a/fsdev/virtio-9p-marshal.h b/fsdev/virtio-9p-marshal.h
new file mode 100644
index 0000000..f441400
--- /dev/null
+++ b/fsdev/virtio-9p-marshal.h
@@ -0,0 +1,87 @@
+#ifndef _QEMU_VIRTIO_9P_MARSHAL_H
+#define _QEMU_VIRTIO_9P_MARSHAL_H
+
+typedef struct V9fsString
+{
+    uint16_t size;
+    char *data;
+} V9fsString;
+
+typedef struct V9fsQID
+{
+    int8_t type;
+    int32_t version;
+    int64_t path;
+} V9fsQID;
+
+typedef struct V9fsStat
+{
+    int16_t size;
+    int16_t type;
+    int32_t dev;
+    V9fsQID qid;
+    int32_t mode;
+    int32_t atime;
+    int32_t mtime;
+    int64_t length;
+    V9fsString name;
+    V9fsString uid;
+    V9fsString gid;
+    V9fsString muid;
+    /* 9p2000.u */
+    V9fsString extension;
+   int32_t n_uid;
+    int32_t n_gid;
+    int32_t n_muid;
+} V9fsStat;
+
+typedef struct V9fsIattr
+{
+    int32_t valid;
+    int32_t mode;
+    int32_t uid;
+    int32_t gid;
+    int64_t size;
+    int64_t atime_sec;
+    int64_t atime_nsec;
+    int64_t mtime_sec;
+    int64_t mtime_nsec;
+} V9fsIattr;
+
+typedef struct V9fsStatDotl {
+    uint64_t st_result_mask;
+    V9fsQID qid;
+    uint32_t st_mode;
+    uint32_t st_uid;
+    uint32_t st_gid;
+    uint64_t st_nlink;
+    uint64_t st_rdev;
+    uint64_t st_size;
+    uint64_t st_blksize;
+    uint64_t st_blocks;
+    uint64_t st_atime_sec;
+    uint64_t st_atime_nsec;
+    uint64_t st_mtime_sec;
+    uint64_t st_mtime_nsec;
+    uint64_t st_ctime_sec;
+    uint64_t st_ctime_nsec;
+    uint64_t st_btime_sec;
+    uint64_t st_btime_nsec;
+    uint64_t st_gen;
+    uint64_t st_data_version;
+} V9fsStatDotl;
+
+extern void v9fs_string_init(V9fsString *str);
+extern void v9fs_string_free(V9fsString *str);
+extern void v9fs_string_null(V9fsString *str);
+extern void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...);
+extern void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs);
+
+size_t v9fs_pack(struct iovec *in_sg, int in_num, size_t offset,
+                 const void *src, size_t size);
+size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
+                      int bswap, const char *fmt, ...);
+size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset,
+                    int bswap, const char *fmt, ...);
+
+#endif
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index df0a8e7..4bfee6c 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -11,9 +11,6 @@
  *
  */
 
-#include <glib.h>
-#include <glib/gprintf.h>
-
 #include "hw/virtio.h"
 #include "hw/pc.h"
 #include "qemu_socket.h"
@@ -138,42 +135,6 @@ static int get_dotl_openflags(V9fsState *s, int oflags)
     return flags;
 }
 
-void v9fs_string_init(V9fsString *str)
-{
-    str->data = NULL;
-    str->size = 0;
-}
-
-void v9fs_string_free(V9fsString *str)
-{
-    g_free(str->data);
-    str->data = NULL;
-    str->size = 0;
-}
-
-void v9fs_string_null(V9fsString *str)
-{
-    v9fs_string_free(str);
-}
-
-void GCC_FMT_ATTR(2, 3)
-v9fs_string_sprintf(V9fsString *str, const char *fmt, ...)
-{
-    va_list ap;
-
-    v9fs_string_free(str);
-
-    va_start(ap, fmt);
-    str->size = g_vasprintf(&str->data, fmt, ap);
-    va_end(ap);
-}
-
-void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
-{
-    v9fs_string_free(lhs);
-    v9fs_string_sprintf(lhs, "%s", rhs->data);
-}
-
 void v9fs_path_init(V9fsPath *path)
 {
     path->data = NULL;
@@ -629,211 +590,6 @@ static void free_pdu(V9fsState *s, V9fsPDU *pdu)
     }
 }
 
-size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
-                        size_t offset, size_t size, int pack)
-{
-    int i = 0;
-    size_t copied = 0;
-
-    for (i = 0; size && i < sg_count; i++) {
-        size_t len;
-        if (offset >= sg[i].iov_len) {
-            /* skip this sg */
-            offset -= sg[i].iov_len;
-            continue;
-        } else {
-            len = MIN(sg[i].iov_len - offset, size);
-            if (pack) {
-                memcpy(sg[i].iov_base + offset, addr, len);
-            } else {
-                memcpy(addr, sg[i].iov_base + offset, len);
-            }
-            size -= len;
-            copied += len;
-            addr += len;
-            if (size) {
-                offset = 0;
-                continue;
-            }
-        }
-    }
-
-    return copied;
-}
-
-static size_t pdu_unpack(void *dst, V9fsPDU *pdu, size_t offset, size_t size)
-{
-    return pdu_packunpack(dst, pdu->elem.out_sg, pdu->elem.out_num,
-                         offset, size, 0);
-}
-
-static size_t pdu_pack(V9fsPDU *pdu, size_t offset, const void *src,
-                        size_t size)
-{
-    return pdu_packunpack((void *)src, pdu->elem.in_sg, pdu->elem.in_num,
-                             offset, size, 1);
-}
-
-static size_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
-{
-    size_t old_offset = offset;
-    va_list ap;
-    int i;
-
-    va_start(ap, fmt);
-    for (i = 0; fmt[i]; i++) {
-        switch (fmt[i]) {
-        case 'b': {
-            uint8_t *valp = va_arg(ap, uint8_t *);
-            offset += pdu_unpack(valp, pdu, offset, sizeof(*valp));
-            break;
-        }
-        case 'w': {
-            uint16_t val, *valp;
-            valp = va_arg(ap, uint16_t *);
-            offset += pdu_unpack(&val, pdu, offset, sizeof(val));
-            *valp = le16_to_cpu(val);
-            break;
-        }
-        case 'd': {
-            uint32_t val, *valp;
-            valp = va_arg(ap, uint32_t *);
-            offset += pdu_unpack(&val, pdu, offset, sizeof(val));
-            *valp = le32_to_cpu(val);
-            break;
-        }
-        case 'q': {
-            uint64_t val, *valp;
-            valp = va_arg(ap, uint64_t *);
-            offset += pdu_unpack(&val, pdu, offset, sizeof(val));
-            *valp = le64_to_cpu(val);
-            break;
-        }
-        case 's': {
-            V9fsString *str = va_arg(ap, V9fsString *);
-            offset += pdu_unmarshal(pdu, offset, "w", &str->size);
-            /* FIXME: sanity check str->size */
-            str->data = g_malloc(str->size + 1);
-            offset += pdu_unpack(str->data, pdu, offset, str->size);
-            str->data[str->size] = 0;
-            break;
-        }
-        case 'Q': {
-            V9fsQID *qidp = va_arg(ap, V9fsQID *);
-            offset += pdu_unmarshal(pdu, offset, "bdq",
-                        &qidp->type, &qidp->version, &qidp->path);
-            break;
-        }
-        case 'S': {
-            V9fsStat *statp = va_arg(ap, V9fsStat *);
-            offset += pdu_unmarshal(pdu, offset, "wwdQdddqsssssddd",
-                        &statp->size, &statp->type, &statp->dev,
-                        &statp->qid, &statp->mode, &statp->atime,
-                        &statp->mtime, &statp->length,
-                        &statp->name, &statp->uid, &statp->gid,
-                        &statp->muid, &statp->extension,
-                        &statp->n_uid, &statp->n_gid,
-                        &statp->n_muid);
-            break;
-        }
-        case 'I': {
-            V9fsIattr *iattr = va_arg(ap, V9fsIattr *);
-            offset += pdu_unmarshal(pdu, offset, "ddddqqqqq",
-                        &iattr->valid, &iattr->mode,
-                        &iattr->uid, &iattr->gid, &iattr->size,
-                        &iattr->atime_sec, &iattr->atime_nsec,
-                        &iattr->mtime_sec, &iattr->mtime_nsec);
-            break;
-        }
-        default:
-            break;
-        }
-    }
-
-    va_end(ap);
-
-    return offset - old_offset;
-}
-
-static size_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
-{
-    size_t old_offset = offset;
-    va_list ap;
-    int i;
-
-    va_start(ap, fmt);
-    for (i = 0; fmt[i]; i++) {
-        switch (fmt[i]) {
-        case 'b': {
-            uint8_t val = va_arg(ap, int);
-            offset += pdu_pack(pdu, offset, &val, sizeof(val));
-            break;
-        }
-        case 'w': {
-            uint16_t val;
-            cpu_to_le16w(&val, va_arg(ap, int));
-            offset += pdu_pack(pdu, offset, &val, sizeof(val));
-            break;
-        }
-        case 'd': {
-            uint32_t val;
-            cpu_to_le32w(&val, va_arg(ap, uint32_t));
-            offset += pdu_pack(pdu, offset, &val, sizeof(val));
-            break;
-        }
-        case 'q': {
-            uint64_t val;
-            cpu_to_le64w(&val, va_arg(ap, uint64_t));
-            offset += pdu_pack(pdu, offset, &val, sizeof(val));
-            break;
-        }
-        case 's': {
-            V9fsString *str = va_arg(ap, V9fsString *);
-            offset += pdu_marshal(pdu, offset, "w", str->size);
-            offset += pdu_pack(pdu, offset, str->data, str->size);
-            break;
-        }
-        case 'Q': {
-            V9fsQID *qidp = va_arg(ap, V9fsQID *);
-            offset += pdu_marshal(pdu, offset, "bdq",
-                        qidp->type, qidp->version, qidp->path);
-            break;
-        }
-        case 'S': {
-            V9fsStat *statp = va_arg(ap, V9fsStat *);
-            offset += pdu_marshal(pdu, offset, "wwdQdddqsssssddd",
-                        statp->size, statp->type, statp->dev,
-                        &statp->qid, statp->mode, statp->atime,
-                        statp->mtime, statp->length, &statp->name,
-                        &statp->uid, &statp->gid, &statp->muid,
-                        &statp->extension, statp->n_uid,
-                        statp->n_gid, statp->n_muid);
-            break;
-        }
-        case 'A': {
-            V9fsStatDotl *statp = va_arg(ap, V9fsStatDotl *);
-            offset += pdu_marshal(pdu, offset, "qQdddqqqqqqqqqqqqqqq",
-                        statp->st_result_mask,
-                        &statp->qid, statp->st_mode,
-                        statp->st_uid, statp->st_gid,
-                        statp->st_nlink, statp->st_rdev,
-                        statp->st_size, statp->st_blksize, statp->st_blocks,
-                        statp->st_atime_sec, statp->st_atime_nsec,
-                        statp->st_mtime_sec, statp->st_mtime_nsec,
-                        statp->st_ctime_sec, statp->st_ctime_nsec,
-                        statp->st_btime_sec, statp->st_btime_nsec,
-                        statp->st_gen, statp->st_data_version);
-            break;
-        }
-        default:
-            break;
-        }
-    }
-    va_end(ap);
-
-    return offset - old_offset;
-}
-
 static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len)
 {
     int8_t id = pdu->id + 1; /* Response */
@@ -1713,9 +1469,10 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
         read_count = 0;
     }
     offset += pdu_marshal(pdu, offset, "d", read_count);
-    offset += pdu_pack(pdu, offset,
-                       ((char *)fidp->fs.xattr.value) + off,
-                       read_count);
+    offset += v9fs_pack(pdu->elem.in_sg, pdu->elem.in_num, offset,
+                        ((char *)fidp->fs.xattr.value) + off,
+                        read_count);
+
     return offset;
 }
 
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 19a797b..5797944 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -8,9 +8,11 @@
 #include <sys/resource.h>
 #include "hw/virtio.h"
 #include "fsdev/file-op-9p.h"
+#include "fsdev/virtio-9p-marshal.h"
 #include "qemu-thread.h"
 #include "qemu-coroutine.h"
 
+
 /* The feature bitmap for virtio 9P */
 /* The mount point is specified in a config variable */
 #define VIRTIO_9P_MOUNT_TAG 0
@@ -154,40 +156,6 @@ struct V9fsPDU
 
 typedef struct V9fsFidState V9fsFidState;
 
-typedef struct V9fsString
-{
-    uint16_t size;
-    char *data;
-} V9fsString;
-
-typedef struct V9fsQID
-{
-    int8_t type;
-    int32_t version;
-    int64_t path;
-} V9fsQID;
-
-typedef struct V9fsStat
-{
-    int16_t size;
-    int16_t type;
-    int32_t dev;
-    V9fsQID qid;
-    int32_t mode;
-    int32_t atime;
-    int32_t mtime;
-    int64_t length;
-    V9fsString name;
-    V9fsString uid;
-    V9fsString gid;
-    V9fsString muid;
-    /* 9p2000.u */
-    V9fsString extension;
-   int32_t n_uid;
-    int32_t n_gid;
-    int32_t n_muid;
-} V9fsStat;
-
 enum {
     P9_FID_NONE = 0,
     P9_FID_FILE,
@@ -267,29 +235,6 @@ typedef struct V9fsStatState {
     struct stat stbuf;
 } V9fsStatState;
 
-typedef struct V9fsStatDotl {
-    uint64_t st_result_mask;
-    V9fsQID qid;
-    uint32_t st_mode;
-    uint32_t st_uid;
-    uint32_t st_gid;
-    uint64_t st_nlink;
-    uint64_t st_rdev;
-    uint64_t st_size;
-    uint64_t st_blksize;
-    uint64_t st_blocks;
-    uint64_t st_atime_sec;
-    uint64_t st_atime_nsec;
-    uint64_t st_mtime_sec;
-    uint64_t st_mtime_nsec;
-    uint64_t st_ctime_sec;
-    uint64_t st_ctime_nsec;
-    uint64_t st_btime_sec;
-    uint64_t st_btime_nsec;
-    uint64_t st_gen;
-    uint64_t st_data_version;
-} V9fsStatDotl;
-
 typedef struct V9fsOpenState {
     V9fsPDU *pdu;
     size_t offset;
@@ -332,19 +277,6 @@ typedef struct V9fsWriteState {
     int cnt;
 } V9fsWriteState;
 
-typedef struct V9fsIattr
-{
-    int32_t valid;
-    int32_t mode;
-    int32_t uid;
-    int32_t gid;
-    int64_t size;
-    int64_t atime_sec;
-    int64_t atime_nsec;
-    int64_t mtime_sec;
-    int64_t mtime_nsec;
-} V9fsIattr;
-
 struct virtio_9p_config
 {
     /* number of characters in tag */
@@ -459,14 +391,15 @@ static inline uint8_t v9fs_request_cancelled(V9fsPDU *pdu)
 extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq);
 extern void virtio_9p_set_fd_limit(void);
 extern void v9fs_reclaim_fd(V9fsPDU *pdu);
-extern void v9fs_string_init(V9fsString *str);
-extern void v9fs_string_free(V9fsString *str);
-extern void v9fs_string_null(V9fsString *str);
-extern void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...);
-extern void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs);
 extern void v9fs_path_init(V9fsPath *path);
 extern void v9fs_path_free(V9fsPath *path);
 extern void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs);
 extern int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath,
                              const char *name, V9fsPath *path);
+
+#define pdu_marshal(pdu, offset, fmt, args...)  \
+    v9fs_marshal(pdu->elem.in_sg, pdu->elem.in_num, offset, 1, fmt, ##args)
+#define pdu_unmarshal(pdu, offset, fmt, args...)  \
+    v9fs_unmarshal(pdu->elem.out_sg, pdu->elem.out_num, offset, 1, fmt, ##args)
+
 #endif
commit 99519f0a776797db8fbdbf828240333e5181a612
Author: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
Date:   Wed Dec 14 13:48:59 2011 +0530

    hw/9pfs: Move opt validation to FsDriver callback
    
    This remove all conditional code from common code path and
    make opt validation a FSDriver callback.
    
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index c823fe0..7ef14af 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -61,6 +61,16 @@ typedef struct extended_ops {
 #define V9FS_SEC_MASK               0x0000001C
 
 
+typedef struct FileOperations FileOperations;
+/*
+ * Structure to store the various fsdev's passed through command line.
+ */
+typedef struct FsDriverEntry {
+    char *fsdev_id;
+    char *path;
+    int export_flags;
+    FileOperations *ops;
+} FsDriverEntry;
 
 typedef struct FsContext
 {
@@ -82,8 +92,9 @@ typedef union V9fsFidOpenState V9fsFidOpenState;
 
 void cred_init(FsCred *);
 
-typedef struct FileOperations
+struct FileOperations
 {
+    int (*parse_opts)(QemuOpts *, struct FsDriverEntry *);
     int (*init)(struct FsContext *);
     int (*lstat)(FsContext *, V9fsPath *, struct stat *);
     ssize_t (*readlink)(FsContext *, V9fsPath *, char *, size_t);
@@ -128,6 +139,6 @@ typedef struct FileOperations
                     V9fsPath *newdir, const char *new_name);
     int (*unlinkat)(FsContext *ctx, V9fsPath *dir, const char *name, int flags);
     void *opaque;
-} FileOperations;
+};
 
 #endif
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
index 6684f7e..00f48ab 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -31,12 +31,10 @@ static FsDriverTable FsDrivers[] = {
 
 int qemu_fsdev_add(QemuOpts *opts)
 {
-    struct FsDriverListEntry *fsle;
     int i;
+    struct FsDriverListEntry *fsle;
     const char *fsdev_id = qemu_opts_id(opts);
     const char *fsdriver = qemu_opt_get(opts, "fsdriver");
-    const char *path = qemu_opt_get(opts, "path");
-    const char *sec_model = qemu_opt_get(opts, "security_model");
     const char *writeout = qemu_opt_get(opts, "writeout");
     bool ro = qemu_opt_get_bool(opts, "readonly", 0);
 
@@ -61,29 +59,9 @@ int qemu_fsdev_add(QemuOpts *opts)
         return -1;
     }
 
-    if (!strcmp(fsdriver, "local") && !sec_model) {
-        fprintf(stderr, "security model not specified, "
-                "local fs needs security model\nvalid options are:"
-                "\tsecurity_model=[passthrough|mapped|none]\n");
-        return -1;
-    }
-
-    if (strcmp(fsdriver, "local") && sec_model) {
-        fprintf(stderr, "only local fs driver needs security model\n");
-        return -1;
-    }
-
-    if (!path) {
-        fprintf(stderr, "fsdev: No path specified.\n");
-        return -1;
-    }
-
-    fsle = g_malloc(sizeof(*fsle));
-
+    fsle = g_malloc0(sizeof(*fsle));
     fsle->fse.fsdev_id = g_strdup(fsdev_id);
-    fsle->fse.path = g_strdup(path);
     fsle->fse.ops = FsDrivers[i].ops;
-    fsle->fse.export_flags = 0;
     if (writeout) {
         if (!strcmp(writeout, "immediate")) {
             fsle->fse.export_flags |= V9FS_IMMEDIATE_WRITEOUT;
@@ -95,22 +73,12 @@ int qemu_fsdev_add(QemuOpts *opts)
         fsle->fse.export_flags &= ~V9FS_RDONLY;
     }
 
-    if (strcmp(fsdriver, "local")) {
-        goto done;
+    if (fsle->fse.ops->parse_opts) {
+        if (fsle->fse.ops->parse_opts(opts, &fsle->fse)) {
+            return -1;
+        }
     }
 
-    if (!strcmp(sec_model, "passthrough")) {
-        fsle->fse.export_flags |= V9FS_SM_PASSTHROUGH;
-    } else if (!strcmp(sec_model, "mapped")) {
-        fsle->fse.export_flags |= V9FS_SM_MAPPED;
-    } else if (!strcmp(sec_model, "none")) {
-        fsle->fse.export_flags |= V9FS_SM_NONE;
-    } else {
-        fprintf(stderr, "Invalid security model %s specified, valid options are"
-                "\n\t [passthrough|mapped|none]\n", sec_model);
-        return -1;
-    }
-done:
     QTAILQ_INSERT_TAIL(&fsdriver_entries, fsle, next);
     return 0;
 }
diff --git a/fsdev/qemu-fsdev.h b/fsdev/qemu-fsdev.h
index 8ef8473..921452d 100644
--- a/fsdev/qemu-fsdev.h
+++ b/fsdev/qemu-fsdev.h
@@ -34,16 +34,6 @@ typedef struct FsDriverTable {
     FileOperations *ops;
 } FsDriverTable;
 
-/*
- * Structure to store the various fsdev's passed through command line.
- */
-typedef struct FsDriverEntry {
-    char *fsdev_id;
-    char *path;
-    int export_flags;
-    FileOperations *ops;
-} FsDriverEntry;
-
 typedef struct FsDriverListEntry {
     FsDriverEntry fse;
     QTAILQ_ENTRY(FsDriverListEntry) next;
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index cd343e1..642d5e2 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -77,16 +77,19 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
         exit(1);
     }
 
-    if (!fse->path || !conf->tag) {
-        /* we haven't specified a mount_tag or the path */
-        fprintf(stderr, "fsdev with id %s needs path "
-                "and Virtio-9p device needs mount_tag arguments\n",
+    if (!conf->tag) {
+        /* we haven't specified a mount_tag */
+        fprintf(stderr, "fsdev with id %s needs mount_tag arguments\n",
                 conf->fsdev_id);
         exit(1);
     }
 
     s->ctx.export_flags = fse->export_flags;
-    s->ctx.fs_root = g_strdup(fse->path);
+    if (fse->path) {
+        s->ctx.fs_root = g_strdup(fse->path);
+    } else {
+        s->ctx.fs_root = NULL;
+    }
     s->ctx.exops.get_st_gen = NULL;
 
     if (fse->export_flags & V9FS_SM_PASSTHROUGH) {
diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c
index b556e39..cb012c0 100644
--- a/hw/9pfs/virtio-9p-handle.c
+++ b/hw/9pfs/virtio-9p-handle.c
@@ -641,7 +641,27 @@ out:
     return ret;
 }
 
+static int handle_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
+{
+    const char *sec_model = qemu_opt_get(opts, "security_model");
+    const char *path = qemu_opt_get(opts, "path");
+
+    if (sec_model) {
+        fprintf(stderr, "Invalid argument security_model specified with handle fsdriver\n");
+        return -1;
+    }
+
+    if (!path) {
+        fprintf(stderr, "fsdev: No path specified.\n");
+        return -1;
+    }
+    fse->path = g_strdup(path);
+    return 0;
+
+}
+
 FileOperations handle_ops = {
+    .parse_opts   = handle_parse_opts,
     .init         = handle_init,
     .lstat        = handle_lstat,
     .readlink     = handle_readlink,
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 371a94d..3ae6ef2 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -756,7 +756,41 @@ static int local_init(FsContext *ctx)
     return err;
 }
 
+static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
+{
+    const char *sec_model = qemu_opt_get(opts, "security_model");
+    const char *path = qemu_opt_get(opts, "path");
+
+    if (!sec_model) {
+        fprintf(stderr, "security model not specified, "
+                "local fs needs security model\nvalid options are:"
+                "\tsecurity_model=[passthrough|mapped|none]\n");
+        return -1;
+    }
+
+    if (!strcmp(sec_model, "passthrough")) {
+        fse->export_flags |= V9FS_SM_PASSTHROUGH;
+    } else if (!strcmp(sec_model, "mapped")) {
+        fse->export_flags |= V9FS_SM_MAPPED;
+    } else if (!strcmp(sec_model, "none")) {
+        fse->export_flags |= V9FS_SM_NONE;
+    } else {
+        fprintf(stderr, "Invalid security model %s specified, valid options are"
+                "\n\t [passthrough|mapped|none]\n", sec_model);
+        return -1;
+    }
+
+    if (!path) {
+        fprintf(stderr, "fsdev: No path specified.\n");
+        return -1;
+    }
+    fse->path = g_strdup(path);
+
+    return 0;
+}
+
 FileOperations local_ops = {
+    .parse_opts = local_parse_opts,
     .init  = local_init,
     .lstat = local_lstat,
     .readlink = local_readlink,
diff --git a/vl.c b/vl.c
index d925424..47a8b09 100644
--- a/vl.c
+++ b/vl.c
@@ -2675,11 +2675,8 @@ int main(int argc, char **argv, char **envp)
                 }
 
                 if (qemu_opt_get(opts, "fsdriver") == NULL ||
-                        qemu_opt_get(opts, "mount_tag") == NULL ||
-                        qemu_opt_get(opts, "path") == NULL) {
-                    fprintf(stderr, "Usage: -virtfs fsdriver,path=/share_path/,"
-                            "[security_model={mapped|passthrough|none}],"
-                            "mount_tag=tag.\n");
+                    qemu_opt_get(opts, "mount_tag") == NULL) {
+                    fprintf(stderr, "Usage: -virtfs fsdriver,mount_tag=tag.\n");
                     exit(1);
                 }
                 fsdev = qemu_opts_create(qemu_find_opts("fsdev"),
@@ -2725,7 +2722,6 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
                 qemu_opt_set(fsdev, "fsdriver", "synth");
-                qemu_opt_set(fsdev, "path", "/"); /* ignored */
 
                 device = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
                 qemu_opt_set(device, "driver", "virtio-9p-pci");
commit b2123a48566ab0636b78dda6b9c37c54bff69e6b
Author: Rob Herring <rob.herring at calxeda.com>
Date:   Thu Dec 29 06:19:54 2011 +0000

    add L2x0/PL310 cache controller device
    
    This is just a dummy device for ARM L2 cache controllers, based on the
    pl310. The cache type parameter can be defined by a property value
    and has a meaningful default.
    
    Signed-off-by: Rob Herring <rob.herring at calxeda.com>
    Signed-off-by: Mark Langsdorf <mark.langsdorf at calxeda.com>
    [Peter Maydell: removed stray blank line at end]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/Makefile.target b/Makefile.target
index 3261383..db5e44c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -336,6 +336,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 += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
+obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
 obj-arm-y += pl061.o
diff --git a/hw/arm_l2x0.c b/hw/arm_l2x0.c
new file mode 100644
index 0000000..2faed39
--- /dev/null
+++ b/hw/arm_l2x0.c
@@ -0,0 +1,181 @@
+/*
+ * ARM dummy L210, L220, PL310 cache controller.
+ *
+ * Copyright (c) 2010-2012 Calxeda
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or any later version, as published by the Free Software
+ * Foundation.
+ *
+ * This program is distributed in the hope 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 "sysbus.h"
+
+/* L2C-310 r3p2 */
+#define CACHE_ID 0x410000c8
+
+typedef struct l2x0_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t cache_type;
+    uint32_t ctrl;
+    uint32_t aux_ctrl;
+    uint32_t data_ctrl;
+    uint32_t tag_ctrl;
+    uint32_t filter_start;
+    uint32_t filter_end;
+} l2x0_state;
+
+static const VMStateDescription vmstate_l2x0 = {
+    .name = "l2x0",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(ctrl, l2x0_state),
+        VMSTATE_UINT32(aux_ctrl, l2x0_state),
+        VMSTATE_UINT32(data_ctrl, l2x0_state),
+        VMSTATE_UINT32(tag_ctrl, l2x0_state),
+        VMSTATE_UINT32(filter_start, l2x0_state),
+        VMSTATE_UINT32(filter_end, l2x0_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+
+static uint64_t l2x0_priv_read(void *opaque, target_phys_addr_t offset,
+                               unsigned size)
+{
+    uint32_t cache_data;
+    l2x0_state *s = (l2x0_state *)opaque;
+    offset &= 0xfff;
+    if (offset >= 0x730 && offset < 0x800) {
+        return 0; /* cache ops complete */
+    }
+    switch (offset) {
+    case 0:
+        return CACHE_ID;
+    case 0x4:
+        /* aux_ctrl values affect cache_type values */
+        cache_data = (s->aux_ctrl & (7 << 17)) >> 15;
+        cache_data |= (s->aux_ctrl & (1 << 16)) >> 16;
+        return s->cache_type |= (cache_data << 18) | (cache_data << 6);
+    case 0x100:
+        return s->ctrl;
+    case 0x104:
+        return s->aux_ctrl;
+    case 0x108:
+        return s->tag_ctrl;
+    case 0x10C:
+        return s->data_ctrl;
+    case 0xC00:
+        return s->filter_start;
+    case 0xC04:
+        return s->filter_end;
+    case 0xF40:
+        return 0;
+    case 0xF60:
+        return 0;
+    case 0xF80:
+        return 0;
+    default:
+        fprintf(stderr, "l2x0_priv_read: Bad offset %x\n", (int)offset);
+        break;
+    }
+    return 0;
+}
+
+static void l2x0_priv_write(void *opaque, target_phys_addr_t offset,
+                            uint64_t value, unsigned size)
+{
+    l2x0_state *s = (l2x0_state *)opaque;
+    offset &= 0xfff;
+    if (offset >= 0x730 && offset < 0x800) {
+        /* ignore */
+        return;
+    }
+    switch (offset) {
+    case 0x100:
+        s->ctrl = value & 1;
+        break;
+    case 0x104:
+        s->aux_ctrl = value;
+        break;
+    case 0x108:
+        s->tag_ctrl = value;
+        break;
+    case 0x10C:
+        s->data_ctrl = value;
+        break;
+    case 0xC00:
+        s->filter_start = value;
+        break;
+    case 0xC04:
+        s->filter_end = value;
+        break;
+    case 0xF40:
+        return;
+    case 0xF60:
+        return;
+    case 0xF80:
+        return;
+    default:
+        fprintf(stderr, "l2x0_priv_write: Bad offset %x\n", (int)offset);
+        break;
+    }
+}
+
+static void l2x0_priv_reset(DeviceState *dev)
+{
+    l2x0_state *s = DO_UPCAST(l2x0_state, busdev.qdev, dev);
+
+    s->ctrl = 0;
+    s->aux_ctrl = 0x02020000;
+    s->tag_ctrl = 0;
+    s->data_ctrl = 0;
+    s->filter_start = 0;
+    s->filter_end = 0;
+}
+
+static const MemoryRegionOps l2x0_mem_ops = {
+    .read = l2x0_priv_read,
+    .write = l2x0_priv_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+ };
+
+static int l2x0_priv_init(SysBusDevice *dev)
+{
+    l2x0_state *s = FROM_SYSBUS(l2x0_state, dev);
+
+    memory_region_init_io(&s->iomem, &l2x0_mem_ops, s, "l2x0_cc", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    return 0;
+}
+
+static SysBusDeviceInfo l2x0_info = {
+    .init = l2x0_priv_init,
+    .qdev.name = "l2x0",
+    .qdev.size = sizeof(l2x0_state),
+    .qdev.vmsd = &vmstate_l2x0,
+    .qdev.no_user = 1,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("type", l2x0_state, cache_type, 0x1c100100),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+    .qdev.reset = l2x0_priv_reset,
+};
+
+static void l2x0_register_device(void)
+{
+    sysbus_register_withprop(&l2x0_info);
+}
+
+device_init(l2x0_register_device)
commit b79f22656f47f0f8b4b89f096f5ae67d0cf268eb
Author: Rob Herring <rob.herring at calxeda.com>
Date:   Thu Dec 29 06:19:53 2011 +0000

    arm: add dummy gic security registers
    
    Implement handling for the RAZ/WI gic security registers.
    
    Signed-off-by: Rob Herring <rob.herring at calxeda.com>
    Signed-off-by: Mark Langsdorf <mark.langsdorf at calxeda.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 9b52119..0339cf5 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -282,6 +282,10 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
             return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
         if (offset < 0x08)
             return 0;
+        if (offset >= 0x80) {
+            /* Interrupt Security , RAZ/WI */
+            return 0;
+        }
 #endif
         goto bad_reg;
     } else if (offset < 0x200) {
@@ -413,6 +417,8 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
             DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis");
         } else if (offset < 4) {
             /* ignored.  */
+        } else if (offset >= 0x80) {
+            /* Interrupt Security Registers, RAZ/WI */
         } else {
             goto bad_reg;
         }
commit 104a26a236f92cc62b490ea90c3a8dc8f8e07f48
Author: Mark Langsdorf <mark.langsdorf at calxeda.com>
Date:   Thu Dec 29 06:19:51 2011 +0000

    arm: Set frequencies for arm_timer
    
    Use qdev properties to allow board modelers to set the frequencies
    for the sp804 timer. Each of the sp804's timers can have an
    individual frequency. The timers default to 1MHz.
    
    Signed-off-by: Mark Langsdorf <mark.langsdorf at calxeda.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 0a5b9d2..60e1c63 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -9,6 +9,8 @@
 
 #include "sysbus.h"
 #include "qemu-timer.h"
+#include "qemu-common.h"
+#include "qdev.h"
 
 /* Common timer implementation.  */
 
@@ -178,6 +180,7 @@ typedef struct {
     SysBusDevice busdev;
     MemoryRegion iomem;
     arm_timer_state *timer[2];
+    uint32_t freq0, freq1;
     int level[2];
     qemu_irq irq;
 } sp804_state;
@@ -269,10 +272,11 @@ static int sp804_init(SysBusDevice *dev)
 
     qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
     sysbus_init_irq(dev, &s->irq);
-    /* ??? The timers are actually configurable between 32kHz and 1MHz, but
-       we don't implement that.  */
-    s->timer[0] = arm_timer_init(1000000);
-    s->timer[1] = arm_timer_init(1000000);
+    /* The timers are configurable between 32kHz and 1MHz
+     * defaulting to 1MHz but overrideable as individual properties */
+    s->timer[0] = arm_timer_init(s->freq0);
+    s->timer[1] = arm_timer_init(s->freq1);
+
     s->timer[0]->irq = qi[0];
     s->timer[1]->irq = qi[1];
     memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
@@ -281,6 +285,16 @@ static int sp804_init(SysBusDevice *dev)
     return 0;
 }
 
+static SysBusDeviceInfo sp804_info = {
+    .init = sp804_init,
+    .qdev.name = "sp804",
+    .qdev.size = sizeof(sp804_state),
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("freq0", sp804_state, freq0, 1000000),
+        DEFINE_PROP_UINT32("freq1", sp804_state, freq1, 1000000),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
 
 /* Integrator/CP timer module.  */
 
@@ -349,7 +363,7 @@ static int icp_pit_init(SysBusDevice *dev)
 static void arm_timer_register_devices(void)
 {
     sysbus_register_dev("integrator_pit", sizeof(icp_pit_state), icp_pit_init);
-    sysbus_register_dev("sp804", sizeof(sp804_state), sp804_init);
+    sysbus_register_withprop(&sp804_info);
 }
 
 device_init(arm_timer_register_devices)
commit 78aca8a712d97ef4601aedb502847a958c7cdd3b
Author: Rob Herring <rob.herring at calxeda.com>
Date:   Thu Dec 29 06:19:50 2011 +0000

    arm: add missing scu registers
    
    Add power control register to a9mpcore
    
    Signed-off-by: Rob Herring <rob.herring at calxeda.com>
    Signed-off-by: Mark Langsdorf <mark.langsdorf at calxeda.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index cd2985f..3ef0e13 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -29,6 +29,7 @@ gic_get_current_cpu(void)
 typedef struct a9mp_priv_state {
     gic_state gic;
     uint32_t scu_control;
+    uint32_t scu_status;
     uint32_t old_timer_status[8];
     uint32_t num_cpu;
     qemu_irq *timer_irq;
@@ -48,7 +49,13 @@ static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset,
     case 0x04: /* Configuration */
         return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1);
     case 0x08: /* CPU Power Status */
-        return 0;
+        return s->scu_status;
+    case 0x09: /* CPU status.  */
+        return s->scu_status >> 8;
+    case 0x0a: /* CPU status.  */
+        return s->scu_status >> 16;
+    case 0x0b: /* CPU status.  */
+        return s->scu_status >> 24;
     case 0x0c: /* Invalidate All Registers In Secure State */
         return 0;
     case 0x40: /* Filtering Start Address Register */
@@ -67,12 +74,35 @@ static void a9_scu_write(void *opaque, target_phys_addr_t offset,
                          uint64_t value, unsigned size)
 {
     a9mp_priv_state *s = (a9mp_priv_state *)opaque;
+    uint32_t mask;
+    uint32_t shift;
+    switch (size) {
+    case 1:
+        mask = 0xff;
+        break;
+    case 2:
+        mask = 0xffff;
+        break;
+    case 4:
+        mask = 0xffffffff;
+        break;
+    default:
+        fprintf(stderr, "Invalid size %u in write to a9 scu register %x\n",
+                size, offset);
+        return;
+    }
+
     switch (offset) {
     case 0x00: /* Control */
         s->scu_control = value & 1;
         break;
     case 0x4: /* Configuration: RO */
         break;
+    case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */
+        shift = (offset - 0x8) * 8;
+        s->scu_status &= ~(mask << shift);
+        s->scu_status |= ((value & mask) << shift);
+        break;
     case 0x0c: /* Invalidate All Registers In Secure State */
         /* no-op as we do not implement caches */
         break;
@@ -80,7 +110,6 @@ static void a9_scu_write(void *opaque, target_phys_addr_t offset,
     case 0x44: /* Filtering End Address Register */
         /* RAZ/WI, like an implementation with only one AXI master */
         break;
-    case 0x8: /* CPU Power Status */
     case 0x50: /* SCU Access Control Register */
     case 0x54: /* SCU Non-secure Access Control Register */
         /* unimplemented, fall through */
@@ -169,11 +198,12 @@ static int a9mp_priv_init(SysBusDevice *dev)
 
 static const VMStateDescription vmstate_a9mp_priv = {
     .name = "a9mpcore_priv",
-    .version_id = 1,
+    .version_id = 2,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(scu_control, a9mp_priv_state),
         VMSTATE_UINT32_ARRAY(old_timer_status, a9mp_priv_state, 8),
+        VMSTATE_UINT32_V(scu_status, a9mp_priv_state, 2),
         VMSTATE_END_OF_LIST()
     }
 };
commit 0ec6dc730cbae8c4cdd3d6a2adc306c93219c1f2
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Dec 20 00:21:56 2011 +0000

    hw/omap_gpmc: Fix region map/unmap when configuring prefetch engine
    
    When configuring the prefetch engine (and also when resetting from
    a state where the prefetch engine was enabled) be careful to adhere
    to the "unmap/change config fields/map" ordering, to avoid trying
    to delete the wrong MemoryRegions. This fixes an assertion failure
    in some cases.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reported-by: Alexander Graf <agraf at suse.de>
    Tested-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/omap_gpmc.c b/hw/omap_gpmc.c
index 414f9f5..2fc4137 100644
--- a/hw/omap_gpmc.c
+++ b/hw/omap_gpmc.c
@@ -443,6 +443,12 @@ void omap_gpmc_reset(struct omap_gpmc_s *s)
     s->irqst = 0;
     s->irqen = 0;
     omap_gpmc_int_update(s);
+    for (i = 0; i < 8; i++) {
+        /* This has to happen before we change any of the config
+         * used to determine which memory regions are mapped or unmapped.
+         */
+        omap_gpmc_cs_unmap(s, i);
+    }
     s->timeout = 0;
     s->config = 0xa00;
     s->prefetch.config1 = 0x00004000;
@@ -451,7 +457,6 @@ void omap_gpmc_reset(struct omap_gpmc_s *s)
     s->prefetch.fifopointer = 0;
     s->prefetch.count = 0;
     for (i = 0; i < 8; i ++) {
-        omap_gpmc_cs_unmap(s, i);
         s->cs_file[i].config[1] = 0x101001;
         s->cs_file[i].config[2] = 0x020201;
         s->cs_file[i].config[3] = 0x10031003;
@@ -716,24 +721,31 @@ static void omap_gpmc_write(void *opaque, target_phys_addr_t addr,
 
     case 0x1e0:	/* GPMC_PREFETCH_CONFIG1 */
         if (!s->prefetch.startengine) {
-            uint32_t oldconfig1 = s->prefetch.config1;
+            uint32_t newconfig1 = value & 0x7f8f7fbf;
             uint32_t changed;
-            s->prefetch.config1 = value & 0x7f8f7fbf;
-            changed = oldconfig1 ^ s->prefetch.config1;
+            changed = newconfig1 ^ s->prefetch.config1;
             if (changed & (0x80 | 0x7000000)) {
                 /* Turning the engine on or off, or mapping it somewhere else.
                  * cs_map() and cs_unmap() check the prefetch config and
                  * overall CSVALID bits, so it is sufficient to unmap-and-map
-                 * both the old cs and the new one.
+                 * both the old cs and the new one. Note that we adhere to
+                 * the "unmap/change config/map" order (and not unmap twice
+                 * if newcs == oldcs), otherwise we'll try to delete the wrong
+                 * memory region.
                  */
-                int oldcs = prefetch_cs(oldconfig1);
-                int newcs = prefetch_cs(s->prefetch.config1);
+                int oldcs = prefetch_cs(s->prefetch.config1);
+                int newcs = prefetch_cs(newconfig1);
                 omap_gpmc_cs_unmap(s, oldcs);
-                omap_gpmc_cs_map(s, oldcs);
-                if (newcs != oldcs) {
+                if (oldcs != newcs) {
                     omap_gpmc_cs_unmap(s, newcs);
+                }
+                s->prefetch.config1 = newconfig1;
+                omap_gpmc_cs_map(s, oldcs);
+                if (oldcs != newcs) {
                     omap_gpmc_cs_map(s, newcs);
                 }
+            } else {
+                s->prefetch.config1 = newconfig1;
             }
         }
         break;
commit e023668198b552d7fa3115178d13a0b7c93c662b
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Dec 20 08:11:36 2011 +0000

    hw/omap1.c: Drop unused includes
    
    Drop includes of qemu-timer.h, qemu-char.h and pc.h as they are no
    longer needed.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/omap1.c b/hw/omap1.c
index 6ab9192..976ef71 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -20,11 +20,7 @@
 #include "arm-misc.h"
 #include "omap.h"
 #include "sysemu.h"
-#include "qemu-timer.h"
-#include "qemu-char.h"
 #include "soc_dma.h"
-/* We use pc-style serial ports.  */
-#include "pc.h"
 #include "blockdev.h"
 #include "range.h"
 #include "sysbus.h"
commit b9f7bc40ed2a8746fa90d86459ab81ef55fd3de8
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Tue Dec 20 08:11:34 2011 +0000

    hw/omap1.c: Separate dpll_ctl from omap_mpu_state
    
    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/omap.h b/hw/omap.h
index 2e227b5..60fa34c 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -904,11 +904,7 @@ struct omap_mpu_state_s {
 
     uint32_t tcmi_regs[17];
 
-    struct dpll_ctl_s {
-        MemoryRegion iomem;
-        uint16_t mode;
-        omap_clk dpll;
-    } dpll[3];
+    struct dpll_ctl_s *dpll[3];
 
     omap_clk clks;
     struct {
diff --git a/hw/omap1.c b/hw/omap1.c
index 4635938..6ab9192 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -1344,6 +1344,12 @@ static void omap_tcmi_init(MemoryRegion *memory, target_phys_addr_t base,
 }
 
 /* Digital phase-locked loops control */
+struct dpll_ctl_s {
+    MemoryRegion iomem;
+    uint16_t mode;
+    omap_clk dpll;
+};
+
 static uint64_t omap_dpll_read(void *opaque, target_phys_addr_t addr,
                                unsigned size)
 {
@@ -1409,15 +1415,17 @@ static void omap_dpll_reset(struct dpll_ctl_s *s)
     omap_clk_setrate(s->dpll, 1, 1);
 }
 
-static void omap_dpll_init(MemoryRegion *memory, struct dpll_ctl_s *s,
+static struct dpll_ctl_s  *omap_dpll_init(MemoryRegion *memory,
                            target_phys_addr_t base, omap_clk clk)
 {
+    struct dpll_ctl_s *s = g_malloc0(sizeof(*s));
     memory_region_init_io(&s->iomem, &omap_dpll_ops, s, "omap-dpll", 0x100);
 
     s->dpll = clk;
     omap_dpll_reset(s);
 
     memory_region_add_subregion(memory, base, &s->iomem);
+    return s;
 }
 
 /* MPU Clock/Reset/Power Mode Control */
@@ -3679,9 +3687,9 @@ static void omap1_mpu_reset(void *opaque)
     omap_mpui_reset(mpu);
     omap_tipb_bridge_reset(mpu->private_tipb);
     omap_tipb_bridge_reset(mpu->public_tipb);
-    omap_dpll_reset(&mpu->dpll[0]);
-    omap_dpll_reset(&mpu->dpll[1]);
-    omap_dpll_reset(&mpu->dpll[2]);
+    omap_dpll_reset(mpu->dpll[0]);
+    omap_dpll_reset(mpu->dpll[1]);
+    omap_dpll_reset(mpu->dpll[2]);
     omap_uart_reset(mpu->uart[0]);
     omap_uart_reset(mpu->uart[1]);
     omap_uart_reset(mpu->uart[2]);
@@ -3947,12 +3955,12 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
                     "uart3",
                     serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
 
-    omap_dpll_init(system_memory,
-                   &s->dpll[0], 0xfffecf00, omap_findclk(s, "dpll1"));
-    omap_dpll_init(system_memory,
-                   &s->dpll[1], 0xfffed000, omap_findclk(s, "dpll2"));
-    omap_dpll_init(system_memory,
-                   &s->dpll[2], 0xfffed100, omap_findclk(s, "dpll3"));
+    s->dpll[0] = omap_dpll_init(system_memory, 0xfffecf00,
+                                omap_findclk(s, "dpll1"));
+    s->dpll[1] = omap_dpll_init(system_memory, 0xfffed000,
+                                omap_findclk(s, "dpll2"));
+    s->dpll[2] = omap_dpll_init(system_memory, 0xfffed100,
+                                omap_findclk(s, "dpll3"));
 
     dinfo = drive_get(IF_SD, 0, 0);
     if (!dinfo) {
commit 037595347520eb1e0355831b5cc41530bcbbe8ea
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Tue Dec 20 08:11:33 2011 +0000

    hw/omap1.c: Separate PWT from omap_mpu_state
    
    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/omap.h b/hw/omap.h
index 851ad46..2e227b5 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -829,7 +829,6 @@ struct omap_mpu_state_s {
     MemoryRegion tcmi_iomem;
     MemoryRegion clkm_iomem;
     MemoryRegion clkdsp_iomem;
-    MemoryRegion pwt_iomem;
     MemoryRegion mpui_io_iomem;
     MemoryRegion tap_iomem;
     MemoryRegion imif_ram;
@@ -867,14 +866,7 @@ struct omap_mpu_state_s {
     struct omap_uwire_s *microwire;
 
     struct omap_pwl_s *pwl;
-
-    struct {
-        uint8_t frc;
-        uint8_t vrc;
-        uint8_t gcr;
-        omap_clk clk;
-    } pwt;
-
+    struct omap_pwt_s *pwt;
     struct omap_i2c_s *i2c[2];
 
     struct omap_rtc_s *rtc;
diff --git a/hw/omap1.c b/hw/omap1.c
index ccc6ecf..4635938 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -2392,10 +2392,18 @@ static struct omap_pwl_s *omap_pwl_init(MemoryRegion *system_memory,
 }
 
 /* Pulse-Width Tone module */
+struct omap_pwt_s {
+    MemoryRegion iomem;
+    uint8_t frc;
+    uint8_t vrc;
+    uint8_t gcr;
+    omap_clk clk;
+};
+
 static uint64_t omap_pwt_read(void *opaque, target_phys_addr_t addr,
                               unsigned size)
 {
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    struct omap_pwt_s *s = (struct omap_pwt_s *) opaque;
     int offset = addr & OMAP_MPUI_REG_MASK;
 
     if (size != 1) {
@@ -2404,11 +2412,11 @@ static uint64_t omap_pwt_read(void *opaque, target_phys_addr_t addr,
 
     switch (offset) {
     case 0x00:	/* FRC */
-        return s->pwt.frc;
+        return s->frc;
     case 0x04:	/* VCR */
-        return s->pwt.vrc;
+        return s->vrc;
     case 0x08:	/* GCR */
-        return s->pwt.gcr;
+        return s->gcr;
     }
     OMAP_BAD_REG(addr);
     return 0;
@@ -2417,7 +2425,7 @@ static uint64_t omap_pwt_read(void *opaque, target_phys_addr_t addr,
 static void omap_pwt_write(void *opaque, target_phys_addr_t addr,
                            uint64_t value, unsigned size)
 {
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    struct omap_pwt_s *s = (struct omap_pwt_s *) opaque;
     int offset = addr & OMAP_MPUI_REG_MASK;
 
     if (size != 1) {
@@ -2426,16 +2434,16 @@ static void omap_pwt_write(void *opaque, target_phys_addr_t addr,
 
     switch (offset) {
     case 0x00:	/* FRC */
-        s->pwt.frc = value & 0x3f;
+        s->frc = value & 0x3f;
         break;
     case 0x04:	/* VRC */
-        if ((value ^ s->pwt.vrc) & 1) {
+        if ((value ^ s->vrc) & 1) {
             if (value & 1)
                 printf("%s: %iHz buzz on\n", __FUNCTION__, (int)
                                 /* 1.5 MHz from a 12-MHz or 13-MHz PWT_CLK */
-                                ((omap_clk_getrate(s->pwt.clk) >> 3) /
+                                ((omap_clk_getrate(s->clk) >> 3) /
                                  /* Pre-multiplexer divider */
-                                 ((s->pwt.gcr & 2) ? 1 : 154) /
+                                 ((s->gcr & 2) ? 1 : 154) /
                                  /* Octave multiplexer */
                                  (2 << (value & 3)) *
                                  /* 101/107 divider */
@@ -2450,10 +2458,10 @@ static void omap_pwt_write(void *opaque, target_phys_addr_t addr,
             else
                 printf("%s: silence!\n", __FUNCTION__);
         }
-        s->pwt.vrc = value & 0x7f;
+        s->vrc = value & 0x7f;
         break;
     case 0x08:	/* GCR */
-        s->pwt.gcr = value & 3;
+        s->gcr = value & 3;
         break;
     default:
         OMAP_BAD_REG(addr);
@@ -2467,23 +2475,25 @@ static const MemoryRegionOps omap_pwt_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void omap_pwt_reset(struct omap_mpu_state_s *s)
+static void omap_pwt_reset(struct omap_pwt_s *s)
 {
-    s->pwt.frc = 0;
-    s->pwt.vrc = 0;
-    s->pwt.gcr = 0;
+    s->frc = 0;
+    s->vrc = 0;
+    s->gcr = 0;
 }
 
-static void omap_pwt_init(MemoryRegion *system_memory,
-                target_phys_addr_t base, struct omap_mpu_state_s *s,
-                omap_clk clk)
+static struct omap_pwt_s *omap_pwt_init(MemoryRegion *system_memory,
+                                        target_phys_addr_t base,
+                                        omap_clk clk)
 {
-    s->pwt.clk = clk;
+    struct omap_pwt_s *s = g_malloc0(sizeof(*s));
+    s->clk = clk;
     omap_pwt_reset(s);
 
-    memory_region_init_io(&s->pwt_iomem, &omap_pwt_ops, s,
+    memory_region_init_io(&s->iomem, &omap_pwt_ops, s,
                           "omap-pwt", 0x800);
-    memory_region_add_subregion(system_memory, base, &s->pwt_iomem);
+    memory_region_add_subregion(system_memory, base, &s->iomem);
+    return s;
 }
 
 /* Real-time Clock module */
@@ -3679,7 +3689,7 @@ static void omap1_mpu_reset(void *opaque)
     omap_mpuio_reset(mpu->mpuio);
     omap_uwire_reset(mpu->microwire);
     omap_pwl_reset(mpu->pwl);
-    omap_pwt_reset(mpu);
+    omap_pwt_reset(mpu->pwt);
     omap_i2c_reset(mpu->i2c[0]);
     omap_rtc_reset(mpu->rtc);
     omap_mcbsp_reset(mpu->mcbsp1);
@@ -3974,7 +3984,8 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
 
     s->pwl = omap_pwl_init(system_memory, 0xfffb5800,
                            omap_findclk(s, "armxor_ck"));
-    omap_pwt_init(system_memory, 0xfffb6000, s, omap_findclk(s, "armxor_ck"));
+    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),
commit 11c7ef0c737f37a487f45c6f3aa070ac7e342e3e
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Jan 2 17:21:07 2012 +0200

    Remove IO_MEM_SHIFT
    
    We no longer use any of the lower bits of a ram_addr, so we might as well
    use them for the io table index.  This increases the number of potential
    I/O handlers by a factor of 8.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/cpu-all.h b/cpu-all.h
index 31d5b27..e2c3c49 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -503,7 +503,7 @@ extern int mem_prealloc;
    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  - IO_MEM_SHIFT))
+#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.  */
diff --git a/cpu-common.h b/cpu-common.h
index 0f3a682..a40c57d 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -107,8 +107,6 @@ void stq_phys(target_phys_addr_t addr, uint64_t val);
 void cpu_physical_memory_write_rom(target_phys_addr_t addr,
                                    const uint8_t *buf, int len);
 
-#define IO_MEM_SHIFT       3
-
 extern struct MemoryRegion io_mem_ram;
 extern struct MemoryRegion io_mem_rom;
 extern struct MemoryRegion io_mem_unassigned;
diff --git a/exec.c b/exec.c
index 8916825..b1d6602 100644
--- a/exec.c
+++ b/exec.c
@@ -2096,7 +2096,7 @@ static bool is_romd(ram_addr_t pd)
     MemoryRegion *mr;
 
     pd &= ~TARGET_PAGE_MASK;
-    mr = io_mem_region[pd >> IO_MEM_SHIFT];
+    mr = io_mem_region[pd];
     return mr->rom_device && mr->readable;
 }
 
@@ -2556,8 +2556,7 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section,
             ram_addr_t orig_memory = p->phys_offset;
             target_phys_addr_t start_addr2, end_addr2;
             int need_subpage = 0;
-            MemoryRegion *mr = io_mem_region[(orig_memory & ~TARGET_PAGE_MASK)
-                                             >> IO_MEM_SHIFT];
+            MemoryRegion *mr = io_mem_region[orig_memory & ~TARGET_PAGE_MASK];
 
             CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
                           need_subpage);
@@ -3378,7 +3377,7 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
     if ((memory & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) {
         memory = io_mem_subpage_ram.ram_addr;
     }
-    memory = (memory >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+    memory &= IO_MEM_NB_ENTRIES - 1;
     for (; idx <= eidx; idx++) {
         mmio->sub_io_index[idx] = memory;
         mmio->region_offset[idx] = region_offset;
@@ -3438,14 +3437,13 @@ static int cpu_register_io_memory_fixed(int io_index, MemoryRegion *mr)
         if (io_index == -1)
             return io_index;
     } else {
-        io_index >>= IO_MEM_SHIFT;
         if (io_index >= IO_MEM_NB_ENTRIES)
             return -1;
     }
 
     io_mem_region[io_index] = mr;
 
-    return (io_index << IO_MEM_SHIFT);
+    return io_index;
 }
 
 int cpu_register_io_memory(MemoryRegion *mr)
@@ -3453,10 +3451,8 @@ int cpu_register_io_memory(MemoryRegion *mr)
     return cpu_register_io_memory_fixed(0, mr);
 }
 
-void cpu_unregister_io_memory(int io_table_address)
+void cpu_unregister_io_memory(int io_index)
 {
-    int io_index = io_table_address >> IO_MEM_SHIFT;
-
     io_mem_region[io_index] = NULL;
     io_mem_used[io_index] = 0;
 }
@@ -3568,7 +3564,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
         if (is_write) {
             if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
                 target_phys_addr_t addr1;
-                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+                io_index = pd & (IO_MEM_NB_ENTRIES - 1);
                 addr1 = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
                 /* XXX: could force cpu_single_env to NULL to avoid
                    potential bugs */
@@ -3607,7 +3603,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
             if (!is_ram_rom_romd(pd)) {
                 target_phys_addr_t addr1;
                 /* I/O case */
-                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+                io_index = pd & (IO_MEM_NB_ENTRIES - 1);
                 addr1 = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
                 if (l >= 4 && ((addr1 & 3) == 0)) {
                     /* 32 bit read access */
@@ -3829,7 +3825,7 @@ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr,
 
     if (!is_ram_rom_romd(pd)) {
         /* I/O case */
-        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+        io_index = pd & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
         val = io_mem_read(io_index, addr, 4);
 #if defined(TARGET_WORDS_BIGENDIAN)
@@ -3890,7 +3886,7 @@ static inline uint64_t ldq_phys_internal(target_phys_addr_t addr,
 
     if (!is_ram_rom_romd(pd)) {
         /* I/O case */
-        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+        io_index = pd & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
 
         /* XXX This is broken when device endian != cpu endian.
@@ -3959,7 +3955,7 @@ static inline uint32_t lduw_phys_internal(target_phys_addr_t addr,
 
     if (!is_ram_rom_romd(pd)) {
         /* I/O case */
-        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+        io_index = pd & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
         val = io_mem_read(io_index, addr, 2);
 #if defined(TARGET_WORDS_BIGENDIAN)
@@ -4019,7 +4015,7 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
     pd = p.phys_offset;
 
     if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
-        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+        io_index = pd & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
         io_mem_write(io_index, addr, val, 4);
     } else {
@@ -4050,7 +4046,7 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
     pd = p.phys_offset;
 
     if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
-        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+        io_index = pd & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
 #ifdef TARGET_WORDS_BIGENDIAN
         io_mem_write(io_index, addr, val >> 32, 4);
@@ -4079,7 +4075,7 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val,
     pd = p.phys_offset;
 
     if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
-        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+        io_index = pd & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
@@ -4152,7 +4148,7 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val,
     pd = p.phys_offset;
 
     if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
-        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+        io_index = pd & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
diff --git a/softmmu_template.h b/softmmu_template.h
index f105d0d..97020f8 100644
--- a/softmmu_template.h
+++ b/softmmu_template.h
@@ -63,7 +63,7 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
 {
     DATA_TYPE res;
     int index;
-    index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+    index = physaddr & (IO_MEM_NB_ENTRIES - 1);
     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
@@ -208,7 +208,7 @@ static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
                                           void *retaddr)
 {
     int index;
-    index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+    index = physaddr & (IO_MEM_NB_ENTRIES - 1);
     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
commit 75c578dcaae48f239fc87b545022efa8fa13f455
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Jan 2 15:40:52 2012 +0200

    Drop IO_MEM_ROMD
    
    Unlike ->readonly, ->readable is not inherited from aliase, so we can simply
    query the memory region.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/cpu-common.h b/cpu-common.h
index ffb0a44..0f3a682 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -114,9 +114,6 @@ extern struct MemoryRegion io_mem_rom;
 extern struct MemoryRegion io_mem_unassigned;
 extern struct MemoryRegion io_mem_notdirty;
 
-/* Acts like a ROM when read and like a device when written.  */
-#define IO_MEM_ROMD        (1)
-
 #endif
 
 #endif /* !CPU_COMMON_H */
diff --git a/exec.c b/exec.c
index d5b82aa..8916825 100644
--- a/exec.c
+++ b/exec.c
@@ -2091,9 +2091,18 @@ static bool is_ram_rom(ram_addr_t pd)
     return pd == io_mem_ram.ram_addr || pd == io_mem_rom.ram_addr;
 }
 
+static bool is_romd(ram_addr_t pd)
+{
+    MemoryRegion *mr;
+
+    pd &= ~TARGET_PAGE_MASK;
+    mr = io_mem_region[pd >> IO_MEM_SHIFT];
+    return mr->rom_device && mr->readable;
+}
+
 static bool is_ram_rom_romd(ram_addr_t pd)
 {
-    return is_ram_rom(pd) || (pd & IO_MEM_ROMD);
+    return is_ram_rom(pd) || is_romd(pd);
 }
 
 /* Add a new TLB entry. At most one entry for a given virtual address
@@ -2179,8 +2188,7 @@ 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 ||
-            (pd & IO_MEM_ROMD)) {
+        if ((pd & ~TARGET_PAGE_MASK) == io_mem_rom.ram_addr || is_romd(pd)) {
             /* Write access calls the I/O callback.  */
             te->addr_write = address | TLB_MMIO;
         } else if ((pd & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr &&
@@ -2528,10 +2536,6 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section,
         region_offset = 0;
     }
 
-    if (!readable) {
-        phys_offset &= ~TARGET_PAGE_MASK & ~IO_MEM_ROMD;
-    }
-
     if (readonly) {
         phys_offset |= io_mem_rom.ram_addr;
     }
@@ -4379,7 +4383,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
-        && !(pd & IO_MEM_ROMD)) {
+        && !is_romd(pd)) {
 #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 24b6b6f..394cbab 100644
--- a/memory.c
+++ b/memory.c
@@ -838,7 +838,7 @@ static void memory_region_destructor_iomem(MemoryRegion *mr)
 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 | IO_MEM_ROMD));
+    cpu_unregister_io_memory(mr->ram_addr & ~TARGET_PAGE_MASK);
 }
 
 static bool memory_region_wrong_endianness(MemoryRegion *mr)
@@ -868,6 +868,7 @@ void memory_region_init(MemoryRegion *mr,
     mr->ram = false;
     mr->readable = true;
     mr->readonly = false;
+    mr->rom_device = false;
     mr->destructor = memory_region_destructor_none;
     mr->priority = 0;
     mr->may_overlap = false;
@@ -1039,10 +1040,10 @@ void memory_region_init_rom_device(MemoryRegion *mr,
     mr->ops = ops;
     mr->opaque = opaque;
     mr->terminates = true;
+    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);
-    mr->ram_addr |= IO_MEM_ROMD;
 }
 
 void memory_region_destroy(MemoryRegion *mr)
diff --git a/memory.h b/memory.h
index fbca6f1..70f57fb 100644
--- a/memory.h
+++ b/memory.h
@@ -125,6 +125,7 @@ struct MemoryRegion {
     bool ram;
     bool readonly; /* For RAM regions */
     bool enabled;
+    bool rom_device;
     MemoryRegion *alias;
     target_phys_addr_t alias_offset;
     unsigned priority;
commit b3b00c78d8247cdffc25839d4b8ff0310a889480
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Jan 2 13:20:11 2012 +0200

    Remove IO_MEM_SUBPAGE
    
    Replace with a MemoryRegion flag.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/cpu-common.h b/cpu-common.h
index 98dddfe..ffb0a44 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -116,7 +116,6 @@ extern struct MemoryRegion io_mem_notdirty;
 
 /* Acts like a ROM when read and like a device when written.  */
 #define IO_MEM_ROMD        (1)
-#define IO_MEM_SUBPAGE     (2)
 
 #endif
 
diff --git a/exec.c b/exec.c
index a61a89f..d5b82aa 100644
--- a/exec.c
+++ b/exec.c
@@ -2552,18 +2552,17 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section,
             ram_addr_t orig_memory = p->phys_offset;
             target_phys_addr_t start_addr2, end_addr2;
             int need_subpage = 0;
+            MemoryRegion *mr = io_mem_region[(orig_memory & ~TARGET_PAGE_MASK)
+                                             >> IO_MEM_SHIFT];
 
             CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
                           need_subpage);
             if (need_subpage) {
-                if (!(orig_memory & IO_MEM_SUBPAGE)) {
+                if (!(mr->subpage)) {
                     subpage = subpage_init((addr & TARGET_PAGE_MASK),
                                            &p->phys_offset, orig_memory,
                                            p->region_offset);
                 } else {
-                    MemoryRegion *mr
-                        = io_mem_region[(orig_memory & ~TARGET_PAGE_MASK)
-                                        >> IO_MEM_SHIFT];
                     subpage = container_of(mr, subpage_t, iomem);
                 }
                 subpage_register(subpage, start_addr2, end_addr2, phys_offset,
@@ -3396,12 +3395,13 @@ static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
     mmio->base = base;
     memory_region_init_io(&mmio->iomem, &subpage_ops, mmio,
                           "subpage", TARGET_PAGE_SIZE);
+    mmio->iomem.subpage = true;
     subpage_memory = mmio->iomem.ram_addr;
 #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 | IO_MEM_SUBPAGE;
+    *phys = subpage_memory;
     subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, orig_memory, region_offset);
 
     return mmio;
diff --git a/memory.c b/memory.c
index 25b36ff..24b6b6f 100644
--- a/memory.c
+++ b/memory.c
@@ -862,6 +862,7 @@ void memory_region_init(MemoryRegion *mr,
     }
     mr->addr = 0;
     mr->offset = 0;
+    mr->subpage = false;
     mr->enabled = true;
     mr->terminates = false;
     mr->ram = false;
diff --git a/memory.h b/memory.h
index 77984bb..fbca6f1 100644
--- a/memory.h
+++ b/memory.h
@@ -119,6 +119,7 @@ struct MemoryRegion {
     void (*destructor)(MemoryRegion *mr);
     ram_addr_t ram_addr;
     IORange iorange;
+    bool subpage;
     bool terminates;
     bool readable;
     bool ram;
commit a621f38de85598a13d8d8524d1a94fc6a1818215
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Jan 2 13:12:08 2012 +0200

    Direct dispatch through MemoryRegion
    
    Now that all mmio goes through MemoryRegions, we can convert
    io_mem_opaque to be a MemoryRegion pointer, and remove the thunks
    that convert from old-style CPU{Read,Write}MemoryFunc to MemoryRegionOps.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/exec-all.h b/exec-all.h
index 3d72952..51d01f2 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -302,9 +302,7 @@ extern void *tci_tb_ptr;
 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);
-extern CPUWriteMemoryFunc *_io_mem_write[IO_MEM_NB_ENTRIES][4];
-extern CPUReadMemoryFunc *_io_mem_read[IO_MEM_NB_ENTRIES][4];
-extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
+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 e08e750..f8af27e 100644
--- a/exec-obsolete.h
+++ b/exec-obsolete.h
@@ -31,9 +31,8 @@ ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr);
 void qemu_ram_free(ram_addr_t addr);
 void qemu_ram_free_from_ptr(ram_addr_t addr);
 
-int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
-                           CPUWriteMemoryFunc * const *mem_write,
-                           void *opaque);
+struct MemoryRegion;
+int cpu_register_io_memory(MemoryRegion *mr);
 void cpu_unregister_io_memory(int table_address);
 
 struct MemoryRegionSection;
diff --git a/exec.c b/exec.c
index 2f88032..a61a89f 100644
--- a/exec.c
+++ b/exec.c
@@ -208,9 +208,7 @@ static void io_mem_init(void);
 static void memory_map_init(void);
 
 /* io memory support */
-CPUWriteMemoryFunc *_io_mem_write[IO_MEM_NB_ENTRIES][4];
-CPUReadMemoryFunc *_io_mem_read[IO_MEM_NB_ENTRIES][4];
-void *io_mem_opaque[IO_MEM_NB_ENTRIES];
+MemoryRegion *io_mem_region[IO_MEM_NB_ENTRIES];
 static char io_mem_used[IO_MEM_NB_ENTRIES];
 static MemoryRegion io_mem_watch;
 #endif
@@ -2563,8 +2561,10 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section,
                                            &p->phys_offset, orig_memory,
                                            p->region_offset);
                 } else {
-                    subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
-                                            >> IO_MEM_SHIFT];
+                    MemoryRegion *mr
+                        = io_mem_region[(orig_memory & ~TARGET_PAGE_MASK)
+                                        >> IO_MEM_SHIFT];
+                    subpage = container_of(mr, subpage_t, iomem);
                 }
                 subpage_register(subpage, start_addr2, end_addr2, phys_offset,
                                  region_offset);
@@ -3427,13 +3427,8 @@ static int get_free_io_mem_idx(void)
    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,
-                                        CPUReadMemoryFunc * const *mem_read,
-                                        CPUWriteMemoryFunc * const *mem_write,
-                                        void *opaque)
+static int cpu_register_io_memory_fixed(int io_index, MemoryRegion *mr)
 {
-    int i;
-
     if (io_index <= 0) {
         io_index = get_free_io_mem_idx();
         if (io_index == -1)
@@ -3444,36 +3439,21 @@ static int cpu_register_io_memory_fixed(int io_index,
             return -1;
     }
 
-    for (i = 0; i < 3; ++i) {
-        assert(mem_read[i]);
-        _io_mem_read[io_index][i] = mem_read[i];
-    }
-    for (i = 0; i < 3; ++i) {
-        assert(mem_write[i]);
-        _io_mem_write[io_index][i] = mem_write[i];
-    }
-    io_mem_opaque[io_index] = opaque;
+    io_mem_region[io_index] = mr;
 
     return (io_index << IO_MEM_SHIFT);
 }
 
-int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
-                           CPUWriteMemoryFunc * const *mem_write,
-                           void *opaque)
+int cpu_register_io_memory(MemoryRegion *mr)
 {
-    return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
+    return cpu_register_io_memory_fixed(0, mr);
 }
 
 void cpu_unregister_io_memory(int io_table_address)
 {
-    int i;
     int io_index = io_table_address >> IO_MEM_SHIFT;
 
-    for (i=0;i < 3; i++) {
-        _io_mem_read[io_index][i] = NULL;
-        _io_mem_write[io_index][i] = NULL;
-    }
-    io_mem_opaque[io_index] = NULL;
+    io_mem_region[io_index] = NULL;
     io_mem_used[io_index] = 0;
 }
 
diff --git a/memory.c b/memory.c
index e34bc65..25b36ff 100644
--- a/memory.c
+++ b/memory.c
@@ -906,11 +906,10 @@ static bool memory_region_access_valid(MemoryRegion *mr,
     return true;
 }
 
-static uint32_t memory_region_read_thunk_n(void *_mr,
-                                           target_phys_addr_t addr,
-                                           unsigned size)
+static uint64_t memory_region_dispatch_read1(MemoryRegion *mr,
+                                             target_phys_addr_t addr,
+                                             unsigned size)
 {
-    MemoryRegion *mr = _mr;
     uint64_t data = 0;
 
     if (!memory_region_access_valid(mr, addr, size, false)) {
@@ -930,17 +929,45 @@ static uint32_t memory_region_read_thunk_n(void *_mr,
     return data;
 }
 
-static void memory_region_write_thunk_n(void *_mr,
-                                        target_phys_addr_t addr,
-                                        unsigned size,
-                                        uint64_t data)
+static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size)
 {
-    MemoryRegion *mr = _mr;
+    if (memory_region_wrong_endianness(mr)) {
+        switch (size) {
+        case 1:
+            break;
+        case 2:
+            *data = bswap16(*data);
+            break;
+        case 4:
+            *data = bswap32(*data);
+        default:
+            abort();
+        }
+    }
+}
+
+static uint64_t memory_region_dispatch_read(MemoryRegion *mr,
+                                            target_phys_addr_t addr,
+                                            unsigned size)
+{
+    uint64_t ret;
+
+    ret = memory_region_dispatch_read1(mr, addr, size);
+    adjust_endianness(mr, &ret, size);
+    return ret;
+}
 
+static void memory_region_dispatch_write(MemoryRegion *mr,
+                                         target_phys_addr_t addr,
+                                         uint64_t data,
+                                         unsigned size)
+{
     if (!memory_region_access_valid(mr, addr, size, true)) {
         return; /* FIXME: better signalling */
     }
 
+    adjust_endianness(mr, &data, size);
+
     if (!mr->ops->write) {
         mr->ops->old_mmio.write[bitops_ffsl(size)](mr->opaque, addr, data);
         return;
@@ -953,69 +980,6 @@ static void memory_region_write_thunk_n(void *_mr,
                               memory_region_write_accessor, mr);
 }
 
-static uint32_t memory_region_read_thunk_b(void *mr, target_phys_addr_t addr)
-{
-    return memory_region_read_thunk_n(mr, addr, 1);
-}
-
-static uint32_t memory_region_read_thunk_w(void *mr, target_phys_addr_t addr)
-{
-    uint32_t data;
-
-    data = memory_region_read_thunk_n(mr, addr, 2);
-    if (memory_region_wrong_endianness(mr)) {
-        data = bswap16(data);
-    }
-    return data;
-}
-
-static uint32_t memory_region_read_thunk_l(void *mr, target_phys_addr_t addr)
-{
-    uint32_t data;
-
-    data = memory_region_read_thunk_n(mr, addr, 4);
-    if (memory_region_wrong_endianness(mr)) {
-        data = bswap32(data);
-    }
-    return data;
-}
-
-static void memory_region_write_thunk_b(void *mr, target_phys_addr_t addr,
-                                        uint32_t data)
-{
-    memory_region_write_thunk_n(mr, addr, 1, data);
-}
-
-static void memory_region_write_thunk_w(void *mr, target_phys_addr_t addr,
-                                        uint32_t data)
-{
-    if (memory_region_wrong_endianness(mr)) {
-        data = bswap16(data);
-    }
-    memory_region_write_thunk_n(mr, addr, 2, data);
-}
-
-static void memory_region_write_thunk_l(void *mr, target_phys_addr_t addr,
-                                        uint32_t data)
-{
-    if (memory_region_wrong_endianness(mr)) {
-        data = bswap32(data);
-    }
-    memory_region_write_thunk_n(mr, addr, 4, data);
-}
-
-static CPUReadMemoryFunc * const memory_region_read_thunk[] = {
-    memory_region_read_thunk_b,
-    memory_region_read_thunk_w,
-    memory_region_read_thunk_l,
-};
-
-static CPUWriteMemoryFunc * const memory_region_write_thunk[] = {
-    memory_region_write_thunk_b,
-    memory_region_write_thunk_w,
-    memory_region_write_thunk_l,
-};
-
 void memory_region_init_io(MemoryRegion *mr,
                            const MemoryRegionOps *ops,
                            void *opaque,
@@ -1027,9 +991,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(memory_region_read_thunk,
-                                          memory_region_write_thunk,
-                                          mr);
+    mr->ram_addr = cpu_register_io_memory(mr);
 }
 
 void memory_region_init_ram(MemoryRegion *mr,
@@ -1078,9 +1040,7 @@ void memory_region_init_rom_device(MemoryRegion *mr,
     mr->terminates = true;
     mr->destructor = memory_region_destructor_rom_device;
     mr->ram_addr = qemu_ram_alloc(size, mr);
-    mr->ram_addr |= cpu_register_io_memory(memory_region_read_thunk,
-                                           memory_region_write_thunk,
-                                           mr);
+    mr->ram_addr |= cpu_register_io_memory(mr);
     mr->ram_addr |= IO_MEM_ROMD;
 }
 
@@ -1552,15 +1512,13 @@ void set_system_io_map(MemoryRegion *mr)
 
 uint64_t io_mem_read(int io_index, target_phys_addr_t addr, unsigned size)
 {
-    return _io_mem_read[io_index][bitops_ffsl(size)](io_mem_opaque[io_index],
-                                                     addr);
+    return memory_region_dispatch_read(io_mem_region[io_index], addr, size);
 }
 
 void io_mem_write(int io_index, target_phys_addr_t addr,
                   uint64_t val, unsigned size)
 {
-    _io_mem_write[io_index][bitops_ffsl(size)](io_mem_opaque[io_index],
-                                               addr, val);
+    memory_region_dispatch_write(io_mem_region[io_index], addr, val, size);
 }
 
 typedef struct MemoryRegionList MemoryRegionList;
commit 1ec9b909ff207a44d5ef2609cb4a2e3d449d485f
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Jan 2 12:47:48 2012 +0200

    Convert io_mem_watch to be a MemoryRegion
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/exec.c b/exec.c
index eed5350..2f88032 100644
--- a/exec.c
+++ b/exec.c
@@ -212,7 +212,7 @@ CPUWriteMemoryFunc *_io_mem_write[IO_MEM_NB_ENTRIES][4];
 CPUReadMemoryFunc *_io_mem_read[IO_MEM_NB_ENTRIES][4];
 void *io_mem_opaque[IO_MEM_NB_ENTRIES];
 static char io_mem_used[IO_MEM_NB_ENTRIES];
-static int io_mem_watch;
+static MemoryRegion io_mem_watch;
 #endif
 
 /* log support */
@@ -2158,7 +2158,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 + paddr;
+                iotlb = io_mem_watch.ram_addr + paddr;
                 address |= TLB_MMIO;
                 break;
             }
@@ -3260,55 +3260,34 @@ static void check_watchpoint(int offset, int len_mask, int flags)
 /* Watchpoint access routines.  Watchpoints are inserted using TLB tricks,
    so these check for a hit then pass through to the normal out-of-line
    phys routines.  */
-static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
-{
-    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
-    return ldub_phys(addr);
-}
-
-static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
-{
-    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
-    return lduw_phys(addr);
-}
-
-static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
-{
-    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
-    return ldl_phys(addr);
-}
-
-static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
-                             uint32_t val)
-{
-    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
-    stb_phys(addr, val);
-}
-
-static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
-                             uint32_t val)
+static uint64_t watch_mem_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
-    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
-    stw_phys(addr, val);
+    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~(size - 1), BP_MEM_READ);
+    switch (size) {
+    case 1: return ldub_phys(addr);
+    case 2: return lduw_phys(addr);
+    case 4: return ldl_phys(addr);
+    default: abort();
+    }
 }
 
-static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
-                             uint32_t val)
+static void watch_mem_write(void *opaque, target_phys_addr_t addr,
+                            uint64_t val, unsigned size)
 {
-    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
-    stl_phys(addr, val);
+    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);
+    default: abort();
+    }
 }
 
-static CPUReadMemoryFunc * const watch_mem_read[3] = {
-    watch_mem_readb,
-    watch_mem_readw,
-    watch_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const watch_mem_write[3] = {
-    watch_mem_writeb,
-    watch_mem_writew,
-    watch_mem_writel,
+static const MemoryRegionOps watch_mem_ops = {
+    .read = watch_mem_read,
+    .write = watch_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static uint64_t subpage_read(void *opaque, target_phys_addr_t addr,
@@ -3515,8 +3494,8 @@ static void io_mem_init(void)
     for (i=0; i<5; i++)
         io_mem_used[i] = 1;
 
-    io_mem_watch = cpu_register_io_memory(watch_mem_read,
-                                          watch_mem_write, NULL);
+    memory_region_init_io(&io_mem_watch, &watch_mem_ops, NULL,
+                          "watch", UINT64_MAX);
 }
 
 static void memory_map_init(void)
commit de712f9469d33b134292f461268bca1ed0726812
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Jan 2 12:41:07 2012 +0200

    Convert IO_MEM_SUBPAGE_RAM to be a MemoryRegion
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/cpu-common.h b/cpu-common.h
index fd787b9..98dddfe 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -113,7 +113,6 @@ extern struct MemoryRegion io_mem_ram;
 extern struct MemoryRegion io_mem_rom;
 extern struct MemoryRegion io_mem_unassigned;
 extern struct MemoryRegion io_mem_notdirty;
-#define IO_MEM_SUBPAGE_RAM (4 << IO_MEM_SHIFT)
 
 /* Acts like a ROM when read and like a device when written.  */
 #define IO_MEM_ROMD        (1)
diff --git a/exec.c b/exec.c
index 38ef72b..eed5350 100644
--- a/exec.c
+++ b/exec.c
@@ -119,6 +119,7 @@ static MemoryRegion *system_memory;
 static MemoryRegion *system_io;
 
 MemoryRegion io_mem_ram, io_mem_rom, io_mem_unassigned, io_mem_notdirty;
+static MemoryRegion io_mem_subpage_ram;
 
 #endif
 
@@ -3347,61 +3348,36 @@ static const MemoryRegionOps subpage_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static uint32_t subpage_ram_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t subpage_ram_read(void *opaque, target_phys_addr_t addr,
+                                 unsigned size)
 {
     ram_addr_t raddr = addr;
     void *ptr = qemu_get_ram_ptr(raddr);
-    return ldub_p(ptr);
-}
-
-static void subpage_ram_writeb(void *opaque, target_phys_addr_t addr,
-                               uint32_t value)
-{
-    ram_addr_t raddr = addr;
-    void *ptr = qemu_get_ram_ptr(raddr);
-    stb_p(ptr, value);
-}
-
-static uint32_t subpage_ram_readw(void *opaque, target_phys_addr_t addr)
-{
-    ram_addr_t raddr = addr;
-    void *ptr = qemu_get_ram_ptr(raddr);
-    return lduw_p(ptr);
-}
-
-static void subpage_ram_writew(void *opaque, target_phys_addr_t addr,
-                               uint32_t value)
-{
-    ram_addr_t raddr = addr;
-    void *ptr = qemu_get_ram_ptr(raddr);
-    stw_p(ptr, value);
-}
-
-static uint32_t subpage_ram_readl(void *opaque, target_phys_addr_t addr)
-{
-    ram_addr_t raddr = addr;
-    void *ptr = qemu_get_ram_ptr(raddr);
-    return ldl_p(ptr);
+    switch (size) {
+    case 1: return ldub_p(ptr);
+    case 2: return lduw_p(ptr);
+    case 4: return ldl_p(ptr);
+    default: abort();
+    }
 }
 
-static void subpage_ram_writel(void *opaque, target_phys_addr_t addr,
-                               uint32_t value)
+static void subpage_ram_write(void *opaque, target_phys_addr_t addr,
+                              uint64_t value, unsigned size)
 {
     ram_addr_t raddr = addr;
     void *ptr = qemu_get_ram_ptr(raddr);
-    stl_p(ptr, value);
+    switch (size) {
+    case 1: return stb_p(ptr, value);
+    case 2: return stw_p(ptr, value);
+    case 4: return stl_p(ptr, value);
+    default: abort();
+    }
 }
 
-static CPUReadMemoryFunc * const subpage_ram_read[] = {
-    &subpage_ram_readb,
-    &subpage_ram_readw,
-    &subpage_ram_readl,
-};
-
-static CPUWriteMemoryFunc * const subpage_ram_write[] = {
-    &subpage_ram_writeb,
-    &subpage_ram_writew,
-    &subpage_ram_writel,
+static const MemoryRegionOps subpage_ram_ops = {
+    .read = subpage_ram_read,
+    .write = subpage_ram_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
@@ -3418,7 +3394,7 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
            mmio, start, end, idx, eidx, memory);
 #endif
     if ((memory & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) {
-        memory = IO_MEM_SUBPAGE_RAM;
+        memory = io_mem_subpage_ram.ram_addr;
     }
     memory = (memory >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
     for (; idx <= eidx; idx++) {
@@ -3534,8 +3510,8 @@ static void io_mem_init(void)
                           "unassigned", UINT64_MAX);
     memory_region_init_io(&io_mem_notdirty, &notdirty_mem_ops, NULL,
                           "notdirty", UINT64_MAX);
-    cpu_register_io_memory_fixed(IO_MEM_SUBPAGE_RAM, subpage_ram_read,
-                                 subpage_ram_write, NULL);
+    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;
 
commit 70c68e44bc818698025008d3529a902a37acb831
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Jan 2 12:32:48 2012 +0200

    Convert the subpage wrapper to be a MemoryRegion
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/exec.c b/exec.c
index 389abe7..38ef72b 100644
--- a/exec.c
+++ b/exec.c
@@ -2472,6 +2472,7 @@ static inline void tlb_set_dirty(CPUState *env,
 
 #define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
 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];
@@ -3309,10 +3310,10 @@ static CPUWriteMemoryFunc * const watch_mem_write[3] = {
     watch_mem_writel,
 };
 
-static inline uint32_t subpage_readlen (subpage_t *mmio,
-                                        target_phys_addr_t addr,
-                                        unsigned int len)
+static uint64_t subpage_read(void *opaque, target_phys_addr_t addr,
+                             unsigned len)
 {
+    subpage_t *mmio = opaque;
     unsigned int idx = SUBPAGE_IDX(addr);
 #if defined(DEBUG_SUBPAGE)
     printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
@@ -3321,66 +3322,29 @@ static inline uint32_t subpage_readlen (subpage_t *mmio,
 
     addr += mmio->region_offset[idx];
     idx = mmio->sub_io_index[idx];
-    return io_mem_read(idx, addr, 1 <<len);
+    return io_mem_read(idx, addr, len);
 }
 
-static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
-                                     uint32_t value, unsigned int len)
+static void subpage_write(void *opaque, target_phys_addr_t addr,
+                          uint64_t value, unsigned len)
 {
+    subpage_t *mmio = opaque;
     unsigned int idx = SUBPAGE_IDX(addr);
 #if defined(DEBUG_SUBPAGE)
-    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n",
+    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, 1 << len);
+    io_mem_write(idx, addr, value, len);
 }
 
-static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
-{
-    return subpage_readlen(opaque, addr, 0);
-}
-
-static void subpage_writeb (void *opaque, target_phys_addr_t addr,
-                            uint32_t value)
-{
-    subpage_writelen(opaque, addr, value, 0);
-}
-
-static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr)
-{
-    return subpage_readlen(opaque, addr, 1);
-}
-
-static void subpage_writew (void *opaque, target_phys_addr_t addr,
-                            uint32_t value)
-{
-    subpage_writelen(opaque, addr, value, 1);
-}
-
-static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr)
-{
-    return subpage_readlen(opaque, addr, 2);
-}
-
-static void subpage_writel (void *opaque, target_phys_addr_t addr,
-                            uint32_t value)
-{
-    subpage_writelen(opaque, addr, value, 2);
-}
-
-static CPUReadMemoryFunc * const subpage_read[] = {
-    &subpage_readb,
-    &subpage_readw,
-    &subpage_readl,
-};
-
-static CPUWriteMemoryFunc * const subpage_write[] = {
-    &subpage_writeb,
-    &subpage_writew,
-    &subpage_writel,
+static const MemoryRegionOps subpage_ops = {
+    .read = subpage_read,
+    .write = subpage_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static uint32_t subpage_ram_readb(void *opaque, target_phys_addr_t addr)
@@ -3475,7 +3439,9 @@ static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
     mmio = g_malloc0(sizeof(subpage_t));
 
     mmio->base = base;
-    subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
+    memory_region_init_io(&mmio->iomem, &subpage_ops, mmio,
+                          "subpage", TARGET_PAGE_SIZE);
+    subpage_memory = mmio->iomem.ram_addr;
 #if defined(DEBUG_SUBPAGE)
     printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
            mmio, base, TARGET_PAGE_SIZE, subpage_memory);
commit dd81124bf6d58ac3c5035093a501a55258f825e4
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Jan 2 12:17:03 2012 +0200

    Switch cpu_register_physical_memory_log() to use MemoryRegions
    
    Still internally using ram_addr.
    
    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 79f989c..e08e750 100644
--- a/exec-obsolete.h
+++ b/exec-obsolete.h
@@ -36,27 +36,9 @@ int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
                            void *opaque);
 void cpu_unregister_io_memory(int table_address);
 
-void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
-                                      ram_addr_t size,
-                                      ram_addr_t phys_offset,
-                                      ram_addr_t region_offset,
-                                      bool log_dirty);
-
-static inline void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
-                                                       ram_addr_t size,
-                                                       ram_addr_t phys_offset,
-                                                       ram_addr_t region_offset)
-{
-    cpu_register_physical_memory_log(start_addr, size, phys_offset,
-                                     region_offset, false);
-}
-
-static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
-                                                ram_addr_t size,
-                                                ram_addr_t phys_offset)
-{
-    cpu_register_physical_memory_offset(start_addr, size, phys_offset, 0);
-}
+struct MemoryRegionSection;
+void cpu_register_physical_memory_log(struct MemoryRegionSection *section,
+                                      bool readable, 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 0f5bad8..389abe7 100644
--- a/exec.c
+++ b/exec.c
@@ -2510,18 +2510,32 @@ static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
    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(target_phys_addr_t start_addr,
-                                         ram_addr_t size,
-                                         ram_addr_t phys_offset,
-                                         ram_addr_t region_offset,
-                                         bool log_dirty)
+void cpu_register_physical_memory_log(MemoryRegionSection *section,
+                                      bool readable, bool readonly)
 {
+    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;
     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 (!readable) {
+        phys_offset &= ~TARGET_PAGE_MASK & ~IO_MEM_ROMD;
+    }
+
+    if (readonly) {
+        phys_offset |= io_mem_rom.ram_addr;
+    }
+
     assert(size);
 
     if (phys_offset == io_mem_unassigned.ram_addr) {
diff --git a/memory.c b/memory.c
index a6c37c9..e34bc65 100644
--- a/memory.c
+++ b/memory.c
@@ -305,38 +305,26 @@ static void access_with_adjusted_size(target_phys_addr_t addr,
 
 static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
 {
-    ram_addr_t phys_offset, region_offset;
-
-    phys_offset = fr->mr->ram_addr;
-    region_offset = fr->offset_in_region;
-    /* cpu_register_physical_memory_log() wants region_offset for
-     * mmio, but prefers offseting phys_offset for RAM.  Humour it.
-     */
-    if (memory_region_is_ram(fr->mr)) {
-        phys_offset += region_offset;
-        region_offset = 0;
-    }
-
-    if (!fr->readable) {
-        phys_offset &= ~TARGET_PAGE_MASK & ~IO_MEM_ROMD;
-    }
-
-    if (fr->readonly) {
-        phys_offset |= io_mem_rom.ram_addr;
-    }
+    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),
+    };
 
-    cpu_register_physical_memory_log(int128_get64(fr->addr.start),
-                                     int128_get64(fr->addr.size),
-                                     phys_offset,
-                                     region_offset,
-                                     fr->dirty_log_mask);
+    cpu_register_physical_memory_log(&section, fr->readable, fr->readonly);
 }
 
 static void as_memory_range_del(AddressSpace *as, FlatRange *fr)
 {
-    cpu_register_physical_memory(int128_get64(fr->addr.start),
-                                 int128_get64(fr->addr.size),
-                                 io_mem_unassigned.ram_addr);
+    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),
+    };
+
+    cpu_register_physical_memory_log(&section, true, false);
 }
 
 static void as_memory_log_start(AddressSpace *as, FlatRange *fr)
commit 0e0df1e24de709016c42164d9b22b981a04e4696
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Jan 2 00:32:15 2012 +0200

    Convert IO_MEM_{RAM,ROM,UNASSIGNED,NOTDIRTY} to MemoryRegions
    
    Convert the fixed-address IO_MEM_RAM, IO_MEM_ROM, IO_MEM_UNASSIGNED,
    and IO_MEM_NOTDIRTY io handlers to MemoryRegions.  These aren't real
    regions, since they are never added to the memory hierarchy, but they
    allow reuse of the dispatch functionality.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/cpu-common.h b/cpu-common.h
index 3c0cff0..fd787b9 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -109,10 +109,10 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr,
 
 #define IO_MEM_SHIFT       3
 
-#define IO_MEM_RAM         (0 << IO_MEM_SHIFT) /* hardcoded offset */
-#define IO_MEM_ROM         (1 << IO_MEM_SHIFT) /* hardcoded offset */
-#define IO_MEM_UNASSIGNED  (2 << IO_MEM_SHIFT)
-#define IO_MEM_NOTDIRTY    (3 << IO_MEM_SHIFT)
+extern struct MemoryRegion io_mem_ram;
+extern struct MemoryRegion io_mem_rom;
+extern struct MemoryRegion io_mem_unassigned;
+extern struct MemoryRegion io_mem_notdirty;
 #define IO_MEM_SUBPAGE_RAM (4 << IO_MEM_SHIFT)
 
 /* Acts like a ROM when read and like a device when written.  */
diff --git a/exec.c b/exec.c
index e0d2297..0f5bad8 100644
--- a/exec.c
+++ b/exec.c
@@ -118,6 +118,8 @@ RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list.blocks) };
 static MemoryRegion *system_memory;
 static MemoryRegion *system_io;
 
+MemoryRegion io_mem_ram, io_mem_rom, io_mem_unassigned, io_mem_notdirty;
+
 #endif
 
 CPUState *first_cpu;
@@ -430,7 +432,7 @@ static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
         *lp = pd = g_malloc(sizeof(PhysPageDesc) * L2_SIZE);
 
         for (i = 0; i < L2_SIZE; i++) {
-            pd[i].phys_offset = IO_MEM_UNASSIGNED;
+            pd[i].phys_offset = io_mem_unassigned.ram_addr;
             pd[i].region_offset = (first_index + i) << TARGET_PAGE_BITS;
         }
     }
@@ -446,7 +448,7 @@ static inline PhysPageDesc phys_page_find(target_phys_addr_t index)
         return *p;
     } else {
         return (PhysPageDesc) {
-            .phys_offset = IO_MEM_UNASSIGNED,
+            .phys_offset = io_mem_unassigned.ram_addr,
             .region_offset = index << TARGET_PAGE_BITS,
         };
     }
@@ -1965,7 +1967,7 @@ static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
                                          unsigned long start, unsigned long length)
 {
     unsigned long addr;
-    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
+    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) {
         addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
         if ((addr - start) < length) {
             tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
@@ -2021,7 +2023,7 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
     ram_addr_t ram_addr;
     void *p;
 
-    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
+    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) {
         p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
             + tlb_entry->addend);
         ram_addr = qemu_ram_addr_from_host_nofail(p);
@@ -2087,7 +2089,7 @@ static void tlb_add_large_page(CPUState *env, target_ulong vaddr,
 static bool is_ram_rom(ram_addr_t pd)
 {
     pd &= ~TARGET_PAGE_MASK;
-    return pd == IO_MEM_RAM || pd == IO_MEM_ROM;
+    return pd == io_mem_ram.ram_addr || pd == io_mem_rom.ram_addr;
 }
 
 static bool is_ram_rom_romd(ram_addr_t pd)
@@ -2133,10 +2135,10 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
     if (is_ram_rom(pd)) {
         /* Normal RAM.  */
         iotlb = pd & TARGET_PAGE_MASK;
-        if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
-            iotlb |= IO_MEM_NOTDIRTY;
+        if ((pd & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr)
+            iotlb |= io_mem_notdirty.ram_addr;
         else
-            iotlb |= IO_MEM_ROM;
+            iotlb |= io_mem_rom.ram_addr;
     } else {
         /* IO handlers are currently passed a physical address.
            It would be nice to pass an offset from the base address
@@ -2178,11 +2180,11 @@ 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 ||
+        if ((pd & ~TARGET_PAGE_MASK) == io_mem_rom.ram_addr ||
             (pd & IO_MEM_ROMD)) {
             /* Write access calls the I/O callback.  */
             te->addr_write = address | TLB_MMIO;
-        } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
+        } else if ((pd & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr &&
                    !cpu_physical_memory_is_dirty(pd)) {
             te->addr_write = address | TLB_NOTDIRTY;
         } else {
@@ -2522,7 +2524,7 @@ void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
 
     assert(size);
 
-    if (phys_offset == IO_MEM_UNASSIGNED) {
+    if (phys_offset == io_mem_unassigned.ram_addr) {
         region_offset = start_addr;
     }
     region_offset &= TARGET_PAGE_MASK;
@@ -2532,7 +2534,7 @@ void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
     addr = start_addr;
     do {
         p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 0);
-        if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
+        if (p && p->phys_offset != io_mem_unassigned.ram_addr) {
             ram_addr_t orig_memory = p->phys_offset;
             target_phys_addr_t start_addr2, end_addr2;
             int need_subpage = 0;
@@ -2572,7 +2574,8 @@ void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
 
                 if (need_subpage) {
                     subpage = subpage_init((addr & TARGET_PAGE_MASK),
-                                           &p->phys_offset, IO_MEM_UNASSIGNED,
+                                           &p->phys_offset,
+                                           io_mem_unassigned.ram_addr,
                                            addr & TARGET_PAGE_MASK);
                     subpage_register(subpage, start_addr2, end_addr2,
                                      phys_offset, region_offset);
@@ -3102,133 +3105,83 @@ ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
     return ram_addr;
 }
 
-static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
-{
-#ifdef DEBUG_UNASSIGNED
-    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
-#endif
-#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
-    cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 1);
-#endif
-    return 0;
-}
-
-static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr)
+static uint64_t unassigned_mem_read(void *opaque, target_phys_addr_t addr,
+                                    unsigned size)
 {
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
 #endif
 #if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
-    cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 2);
+    cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size);
 #endif
     return 0;
 }
 
-static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
+static void unassigned_mem_write(void *opaque, target_phys_addr_t addr,
+                                 uint64_t val, unsigned size)
 {
 #ifdef DEBUG_UNASSIGNED
-    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
+    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%"PRIx64"\n", addr, val);
 #endif
 #if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
-    cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 4);
+    cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size);
 #endif
-    return 0;
 }
 
-static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-#ifdef DEBUG_UNASSIGNED
-    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
-#endif
-#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
-    cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 1);
-#endif
-}
+static const MemoryRegionOps unassigned_mem_ops = {
+    .read = unassigned_mem_read,
+    .write = unassigned_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
 
-static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+static uint64_t error_mem_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
-#ifdef DEBUG_UNASSIGNED
-    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
-#endif
-#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
-    cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 2);
-#endif
+    abort();
 }
 
-static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void error_mem_write(void *opaque, target_phys_addr_t addr,
+                            uint64_t value, unsigned size)
 {
-#ifdef DEBUG_UNASSIGNED
-    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
-#endif
-#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
-    cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 4);
-#endif
+    abort();
 }
 
-static CPUReadMemoryFunc * const unassigned_mem_read[3] = {
-    unassigned_mem_readb,
-    unassigned_mem_readw,
-    unassigned_mem_readl,
+static const MemoryRegionOps error_mem_ops = {
+    .read = error_mem_read,
+    .write = error_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const unassigned_mem_write[3] = {
-    unassigned_mem_writeb,
-    unassigned_mem_writew,
-    unassigned_mem_writel,
+static const MemoryRegionOps rom_mem_ops = {
+    .read = error_mem_read,
+    .write = unassigned_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
-                                uint32_t val)
+static void notdirty_mem_write(void *opaque, target_phys_addr_t ram_addr,
+                               uint64_t val, unsigned size)
 {
     int dirty_flags;
     dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
     if (!(dirty_flags & CODE_DIRTY_FLAG)) {
 #if !defined(CONFIG_USER_ONLY)
-        tb_invalidate_phys_page_fast(ram_addr, 1);
+        tb_invalidate_phys_page_fast(ram_addr, size);
         dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
 #endif
     }
-    stb_p(qemu_get_ram_ptr(ram_addr), val);
-    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
-    cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
-    /* we remove the notdirty callback only if the code has been
-       flushed */
-    if (dirty_flags == 0xff)
-        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
-}
-
-static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr,
-                                uint32_t val)
-{
-    int dirty_flags;
-    dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
-    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
-#if !defined(CONFIG_USER_ONLY)
-        tb_invalidate_phys_page_fast(ram_addr, 2);
-        dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
-#endif
-    }
-    stw_p(qemu_get_ram_ptr(ram_addr), val);
-    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
-    cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
-    /* we remove the notdirty callback only if the code has been
-       flushed */
-    if (dirty_flags == 0xff)
-        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
-}
-
-static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr,
-                                uint32_t val)
-{
-    int dirty_flags;
-    dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
-    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
-#if !defined(CONFIG_USER_ONLY)
-        tb_invalidate_phys_page_fast(ram_addr, 4);
-        dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
-#endif
+    switch (size) {
+    case 1:
+        stb_p(qemu_get_ram_ptr(ram_addr), val);
+        break;
+    case 2:
+        stw_p(qemu_get_ram_ptr(ram_addr), val);
+        break;
+    case 4:
+        stl_p(qemu_get_ram_ptr(ram_addr), val);
+        break;
+    default:
+        abort();
     }
-    stl_p(qemu_get_ram_ptr(ram_addr), val);
     dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
     cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
     /* we remove the notdirty callback only if the code has been
@@ -3237,16 +3190,10 @@ static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr,
         tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
 }
 
-static CPUReadMemoryFunc * const error_mem_read[3] = {
-    NULL, /* never used */
-    NULL, /* never used */
-    NULL, /* never used */
-};
-
-static CPUWriteMemoryFunc * const notdirty_mem_write[3] = {
-    notdirty_mem_writeb,
-    notdirty_mem_writew,
-    notdirty_mem_writel,
+static const MemoryRegionOps notdirty_mem_ops = {
+    .read = error_mem_read,
+    .write = notdirty_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 /* Generate a debug exception if a watchpoint has been hit.  */
@@ -3492,7 +3439,7 @@ 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) {
+    if ((memory & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) {
         memory = IO_MEM_SUBPAGE_RAM;
     }
     memory = (memory >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
@@ -3563,12 +3510,12 @@ static int cpu_register_io_memory_fixed(int io_index,
     }
 
     for (i = 0; i < 3; ++i) {
-        _io_mem_read[io_index][i]
-            = (mem_read[i] ? mem_read[i] : unassigned_mem_read[i]);
+        assert(mem_read[i]);
+        _io_mem_read[io_index][i] = mem_read[i];
     }
     for (i = 0; i < 3; ++i) {
-        _io_mem_write[io_index][i]
-            = (mem_write[i] ? mem_write[i] : unassigned_mem_write[i]);
+        assert(mem_write[i]);
+        _io_mem_write[io_index][i] = mem_write[i];
     }
     io_mem_opaque[io_index] = opaque;
 
@@ -3588,8 +3535,8 @@ void cpu_unregister_io_memory(int io_table_address)
     int io_index = io_table_address >> IO_MEM_SHIFT;
 
     for (i=0;i < 3; i++) {
-        _io_mem_read[io_index][i] = unassigned_mem_read[i];
-        _io_mem_write[io_index][i] = unassigned_mem_write[i];
+        _io_mem_read[io_index][i] = NULL;
+        _io_mem_write[io_index][i] = NULL;
     }
     io_mem_opaque[io_index] = NULL;
     io_mem_used[io_index] = 0;
@@ -3599,12 +3546,14 @@ static void io_mem_init(void)
 {
     int i;
 
-    cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read,
-                                 unassigned_mem_write, NULL);
-    cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read,
-                                 unassigned_mem_write, NULL);
-    cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read,
-                                 notdirty_mem_write, NULL);
+    /* 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);
+    memory_region_init_io(&io_mem_notdirty, &notdirty_mem_ops, NULL,
+                          "notdirty", UINT64_MAX);
     cpu_register_io_memory_fixed(IO_MEM_SUBPAGE_RAM, subpage_ram_read,
                                  subpage_ram_write, NULL);
     for (i=0; i<5; i++)
@@ -3698,7 +3647,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
         pd = p.phys_offset;
 
         if (is_write) {
-            if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
+            if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
                 target_phys_addr_t addr1;
                 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
                 addr1 = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
@@ -3879,7 +3828,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
         p = phys_page_find(page >> TARGET_PAGE_BITS);
         pd = p.phys_offset;
 
-        if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
+        if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
             if (todo || bounce.buffer) {
                 break;
             }
@@ -4150,7 +4099,7 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
     p = phys_page_find(addr >> TARGET_PAGE_BITS);
     pd = p.phys_offset;
 
-    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
+    if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
         io_mem_write(io_index, addr, val, 4);
@@ -4181,7 +4130,7 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
     p = phys_page_find(addr >> TARGET_PAGE_BITS);
     pd = p.phys_offset;
 
-    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
+    if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -4210,7 +4159,7 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val,
     p = phys_page_find(addr >> TARGET_PAGE_BITS);
     pd = p.phys_offset;
 
-    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
+    if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
 #if defined(TARGET_WORDS_BIGENDIAN)
@@ -4283,7 +4232,7 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val,
     p = phys_page_find(addr >> TARGET_PAGE_BITS);
     pd = p.phys_offset;
 
-    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
+    if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
 #if defined(TARGET_WORDS_BIGENDIAN)
@@ -4514,7 +4463,8 @@ tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr)
         ldub_code(addr);
     }
     pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK;
-    if (pd != IO_MEM_RAM && pd != IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
+    if (pd != io_mem_ram.ram_addr && pd != io_mem_rom.ram_addr
+        && !(pd & IO_MEM_ROMD)) {
 #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 66accba..a6c37c9 100644
--- a/memory.c
+++ b/memory.c
@@ -312,8 +312,7 @@ static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
     /* cpu_register_physical_memory_log() wants region_offset for
      * mmio, but prefers offseting phys_offset for RAM.  Humour it.
      */
-    if ((phys_offset & ~TARGET_PAGE_MASK) == IO_MEM_RAM
-        || (phys_offset & ~TARGET_PAGE_MASK) == IO_MEM_ROM) {
+    if (memory_region_is_ram(fr->mr)) {
         phys_offset += region_offset;
         region_offset = 0;
     }
@@ -323,7 +322,7 @@ static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
     }
 
     if (fr->readonly) {
-        phys_offset |= IO_MEM_ROM;
+        phys_offset |= io_mem_rom.ram_addr;
     }
 
     cpu_register_physical_memory_log(int128_get64(fr->addr.start),
@@ -337,7 +336,7 @@ static void as_memory_range_del(AddressSpace *as, FlatRange *fr)
 {
     cpu_register_physical_memory(int128_get64(fr->addr.start),
                                  int128_get64(fr->addr.size),
-                                 IO_MEM_UNASSIGNED);
+                                 io_mem_unassigned.ram_addr);
 }
 
 static void as_memory_log_start(AddressSpace *as, FlatRange *fr)
diff --git a/softmmu_template.h b/softmmu_template.h
index 726744c..f105d0d 100644
--- a/softmmu_template.h
+++ b/softmmu_template.h
@@ -22,6 +22,7 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "qemu-timer.h"
+#include "memory.h"
 
 #define DATA_SIZE (1 << SHIFT)
 
@@ -65,8 +66,9 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
     index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
     physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
     env->mem_io_pc = (unsigned long)retaddr;
-    if (index != IO_MEM_RAM && index != IO_MEM_ROM
-        && index != IO_MEM_UNASSIGNED && index != IO_MEM_NOTDIRTY
+    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
             && !can_do_io(env)) {
         cpu_io_recompile(env, retaddr);
     }
@@ -208,8 +210,9 @@ static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
     int index;
     index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
     physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
-    if (index != IO_MEM_RAM && index != IO_MEM_ROM
-        && index != IO_MEM_UNASSIGNED && index != IO_MEM_NOTDIRTY
+    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
             && !can_do_io(env)) {
         cpu_io_recompile(env, retaddr);
     }
commit d39e822265e56af761cc506ac45768ab8af940b4
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Jan 1 23:35:10 2012 +0200

    Uninline get_page_addr_code()
    
    Its use of IO_MEM_ROM and friends will later cause #include loops; and it
    is too large to merit inlining.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/exec-all.h b/exec-all.h
index 7db22fb..3d72952 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -339,31 +339,7 @@ static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong add
     return addr;
 }
 #else
-/* 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 */
-static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr)
-{
-    int mmu_idx, page_index, pd;
-    void *p;
-
-    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-    mmu_idx = cpu_mmu_index(env1);
-    if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code !=
-                 (addr & TARGET_PAGE_MASK))) {
-        ldub_code(addr);
-    }
-    pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK;
-    if (pd != IO_MEM_RAM && pd != IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
-#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)
-        cpu_unassigned_access(env1, addr, 0, 1, 0, 4);
-#else
-        cpu_abort(env1, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
-#endif
-    }
-    p = (void *)((uintptr_t)addr + env1->tlb_table[mmu_idx][page_index].addend);
-    return qemu_ram_addr_from_host_nofail(p);
-}
+tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr);
 #endif
 
 typedef void (CPUDebugExcpHandler)(CPUState *env);
diff --git a/exec.c b/exec.c
index e735c17..e0d2297 100644
--- a/exec.c
+++ b/exec.c
@@ -4499,6 +4499,32 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
     tcg_dump_info(f, 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)
+{
+    int mmu_idx, page_index, pd;
+    void *p;
+
+    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+    mmu_idx = cpu_mmu_index(env1);
+    if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code !=
+                 (addr & TARGET_PAGE_MASK))) {
+        ldub_code(addr);
+    }
+    pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK;
+    if (pd != IO_MEM_RAM && pd != IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
+#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)
+        cpu_unassigned_access(env1, addr, 0, 1, 0, 4);
+#else
+        cpu_abort(env1, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
+#endif
+    }
+    p = (void *)((uintptr_t)addr + env1->tlb_table[mmu_idx][page_index].addend);
+    return qemu_ram_addr_from_host_nofail(p);
+}
+
 #define MMUSUFFIX _cmmu
 #undef GETPC
 #define GETPC() NULL
commit 1d393fa2d1c16021c840e5d37f7ff74341b7c884
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Jan 1 21:15:42 2012 +0200

    Avoid range comparisons on io index types
    
    The code sometimes uses range comparisons on io indexes (e.g.
    index =< IO_MEM_ROM).  Avoid these as they make moving to objects harder.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/exec-all.h b/exec-all.h
index 23c4598..7db22fb 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -354,7 +354,7 @@ static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong add
         ldub_code(addr);
     }
     pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK;
-    if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
+    if (pd != IO_MEM_RAM && pd != IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
 #if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)
         cpu_unassigned_access(env1, addr, 0, 1, 0, 4);
 #else
diff --git a/exec.c b/exec.c
index c366835..e735c17 100644
--- a/exec.c
+++ b/exec.c
@@ -2084,6 +2084,17 @@ 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)
+{
+    pd &= ~TARGET_PAGE_MASK;
+    return pd == IO_MEM_RAM || pd == IO_MEM_ROM;
+}
+
+static bool is_ram_rom_romd(ram_addr_t pd)
+{
+    return is_ram_rom(pd) || (pd & IO_MEM_ROMD);
+}
+
 /* 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.  */
@@ -2114,12 +2125,12 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
 #endif
 
     address = vaddr;
-    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
+    if (!is_ram_rom_romd(pd)) {
         /* IO memory case (romd handled later) */
         address |= TLB_MMIO;
     }
     addend = (unsigned long)qemu_get_ram_ptr(pd & TARGET_PAGE_MASK);
-    if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
+    if (is_ram_rom(pd)) {
         /* Normal RAM.  */
         iotlb = pd & TARGET_PAGE_MASK;
         if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
@@ -2543,16 +2554,14 @@ void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
             } else {
                 p->phys_offset = phys_offset;
                 p->region_offset = region_offset;
-                if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
-                    (phys_offset & IO_MEM_ROMD))
+                if (is_ram_rom_romd(phys_offset))
                     phys_offset += TARGET_PAGE_SIZE;
             }
         } else {
             p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
             p->phys_offset = phys_offset;
             p->region_offset = region_offset;
-            if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
-                (phys_offset & IO_MEM_ROMD)) {
+            if (is_ram_rom_romd(phys_offset)) {
                 phys_offset += TARGET_PAGE_SIZE;
             } else {
                 target_phys_addr_t start_addr2, end_addr2;
@@ -3727,8 +3736,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                 qemu_put_ram_ptr(ptr);
             }
         } else {
-            if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
-                !(pd & IO_MEM_ROMD)) {
+            if (!is_ram_rom_romd(pd)) {
                 target_phys_addr_t addr1;
                 /* I/O case */
                 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
@@ -3780,9 +3788,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr,
         p = phys_page_find(page >> TARGET_PAGE_BITS);
         pd = p.phys_offset;
 
-        if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
-            (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
-            !(pd & IO_MEM_ROMD)) {
+        if (!is_ram_rom_romd(pd)) {
             /* do nothing */
         } else {
             unsigned long addr1;
@@ -3953,8 +3959,7 @@ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr,
     p = phys_page_find(addr >> TARGET_PAGE_BITS);
     pd = p.phys_offset;
 
-    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
-        !(pd & IO_MEM_ROMD)) {
+    if (!is_ram_rom_romd(pd)) {
         /* I/O case */
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
@@ -4015,8 +4020,7 @@ static inline uint64_t ldq_phys_internal(target_phys_addr_t addr,
     p = phys_page_find(addr >> TARGET_PAGE_BITS);
     pd = p.phys_offset;
 
-    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
-        !(pd & IO_MEM_ROMD)) {
+    if (!is_ram_rom_romd(pd)) {
         /* I/O case */
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
@@ -4085,8 +4089,7 @@ static inline uint32_t lduw_phys_internal(target_phys_addr_t addr,
     p = phys_page_find(addr >> TARGET_PAGE_BITS);
     pd = p.phys_offset;
 
-    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
-        !(pd & IO_MEM_ROMD)) {
+    if (!is_ram_rom_romd(pd)) {
         /* I/O case */
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
diff --git a/memory.c b/memory.c
index 63dc3dc..66accba 100644
--- a/memory.c
+++ b/memory.c
@@ -312,7 +312,8 @@ static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
     /* cpu_register_physical_memory_log() wants region_offset for
      * mmio, but prefers offseting phys_offset for RAM.  Humour it.
      */
-    if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
+    if ((phys_offset & ~TARGET_PAGE_MASK) == IO_MEM_RAM
+        || (phys_offset & ~TARGET_PAGE_MASK) == IO_MEM_ROM) {
         phys_offset += region_offset;
         region_offset = 0;
     }
diff --git a/softmmu_template.h b/softmmu_template.h
index a030b5f..726744c 100644
--- a/softmmu_template.h
+++ b/softmmu_template.h
@@ -65,7 +65,8 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
     index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
     physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
     env->mem_io_pc = (unsigned long)retaddr;
-    if (index > (IO_MEM_NOTDIRTY >> IO_MEM_SHIFT)
+    if (index != IO_MEM_RAM && index != IO_MEM_ROM
+        && index != IO_MEM_UNASSIGNED && index != IO_MEM_NOTDIRTY
             && !can_do_io(env)) {
         cpu_io_recompile(env, retaddr);
     }
@@ -207,7 +208,8 @@ static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
     int index;
     index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
     physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
-    if (index > (IO_MEM_NOTDIRTY >> IO_MEM_SHIFT)
+    if (index != IO_MEM_RAM && index != IO_MEM_ROM
+        && index != IO_MEM_UNASSIGNED && index != IO_MEM_NOTDIRTY
             && !can_do_io(env)) {
         cpu_io_recompile(env, retaddr);
     }
commit 2774c6d0ae20d32d75f77e7ed063ddbb854ca4c5
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Jan 1 18:24:24 2012 +0200

    Fix wrong region_offset when overlaying a page with another
    
    cpu_register_physical_memory_log() does not update region_offset
    if a page was previously registered for the same address.  This
    could cause mmio accesses going to the wrong place, by using the
    old region_offset.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Acked-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/exec.c b/exec.c
index 8a3f621..c366835 100644
--- a/exec.c
+++ b/exec.c
@@ -2542,6 +2542,7 @@ void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
                 p->region_offset = 0;
             } else {
                 p->phys_offset = phys_offset;
+                p->region_offset = region_offset;
                 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
                     (phys_offset & IO_MEM_ROMD))
                     phys_offset += TARGET_PAGE_SIZE;
commit 26a83ad0e793465b74a8b06a65f2f6fdc5615413
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Jan 1 18:02:31 2012 +0200

    memory: remove MemoryRegion::backend_registered
    
    backend_registered was used to lazify the process of registering an
    mmio region, since the it is different for the I/O address space and
    the memory address space.  However, it also makes registration dependent
    on the region being visible in the address space.  This is not the case
    for "fake" regions, like watchpoints or IO_MEM_UNASSIGNED.
    
    Remove backend_registered and always initialize the region.  If it turns
    out to be part of the I/O address space, we've wasted an I/O slot, but
    that's not too bad.  In any case this will be optimized later on.
    
    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 5c46833..63dc3dc 100644
--- a/memory.c
+++ b/memory.c
@@ -303,14 +303,10 @@ static void access_with_adjusted_size(target_phys_addr_t addr,
     }
 }
 
-static void memory_region_prepare_ram_addr(MemoryRegion *mr);
-
 static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
 {
     ram_addr_t phys_offset, region_offset;
 
-    memory_region_prepare_ram_addr(fr->mr);
-
     phys_offset = fr->mr->ram_addr;
     region_offset = fr->offset_in_region;
     /* cpu_register_physical_memory_log() wants region_offset for
@@ -1032,19 +1028,6 @@ static CPUWriteMemoryFunc * const memory_region_write_thunk[] = {
     memory_region_write_thunk_l,
 };
 
-static void memory_region_prepare_ram_addr(MemoryRegion *mr)
-{
-    if (mr->backend_registered) {
-        return;
-    }
-
-    mr->destructor = memory_region_destructor_iomem;
-    mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
-                                          memory_region_write_thunk,
-                                          mr);
-    mr->backend_registered = true;
-}
-
 void memory_region_init_io(MemoryRegion *mr,
                            const MemoryRegionOps *ops,
                            void *opaque,
@@ -1055,7 +1038,10 @@ void memory_region_init_io(MemoryRegion *mr,
     mr->ops = ops;
     mr->opaque = opaque;
     mr->terminates = true;
-    mr->backend_registered = false;
+    mr->destructor = memory_region_destructor_iomem;
+    mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
+                                          memory_region_write_thunk,
+                                          mr);
 }
 
 void memory_region_init_ram(MemoryRegion *mr,
@@ -1067,7 +1053,6 @@ void memory_region_init_ram(MemoryRegion *mr,
     mr->terminates = true;
     mr->destructor = memory_region_destructor_ram;
     mr->ram_addr = qemu_ram_alloc(size, mr);
-    mr->backend_registered = true;
 }
 
 void memory_region_init_ram_ptr(MemoryRegion *mr,
@@ -1080,7 +1065,6 @@ void memory_region_init_ram_ptr(MemoryRegion *mr,
     mr->terminates = true;
     mr->destructor = memory_region_destructor_ram_from_ptr;
     mr->ram_addr = qemu_ram_alloc_from_ptr(size, ptr, mr);
-    mr->backend_registered = true;
 }
 
 void memory_region_init_alias(MemoryRegion *mr,
@@ -1110,7 +1094,6 @@ void memory_region_init_rom_device(MemoryRegion *mr,
                                            memory_region_write_thunk,
                                            mr);
     mr->ram_addr |= IO_MEM_ROMD;
-    mr->backend_registered = true;
 }
 
 void memory_region_destroy(MemoryRegion *mr)
@@ -1453,7 +1436,6 @@ void memory_region_set_alias_offset(MemoryRegion *mr, target_phys_addr_t offset)
 
 ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
 {
-    assert(mr->backend_registered);
     return mr->ram_addr;
 }
 
diff --git a/memory.h b/memory.h
index 8041e90..77984bb 100644
--- a/memory.h
+++ b/memory.h
@@ -116,7 +116,6 @@ struct MemoryRegion {
     Int128 size;
     target_phys_addr_t addr;
     target_phys_addr_t offset;
-    bool backend_registered;
     void (*destructor)(MemoryRegion *mr);
     ram_addr_t ram_addr;
     IORange iorange;
commit acbbec5d438dcf04234519bac53e1f5263572d76
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Nov 21 12:27:03 2011 +0200

    memory: move mmio access to functions
    
    Currently mmio access goes directly to the io_mem_{read,write} arrays.
    In preparation for eliminating them, add indirection via a function.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/exec-all.h b/exec-all.h
index c211242..23c4598 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -299,8 +299,11 @@ extern void *tci_tb_ptr;
 
 #if !defined(CONFIG_USER_ONLY)
 
-extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
-extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
+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);
+extern CPUWriteMemoryFunc *_io_mem_write[IO_MEM_NB_ENTRIES][4];
+extern CPUReadMemoryFunc *_io_mem_read[IO_MEM_NB_ENTRIES][4];
 extern void *io_mem_opaque[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 d21413a..8a3f621 100644
--- a/exec.c
+++ b/exec.c
@@ -205,8 +205,8 @@ static void io_mem_init(void);
 static void memory_map_init(void);
 
 /* io memory support */
-CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
-CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
+CPUWriteMemoryFunc *_io_mem_write[IO_MEM_NB_ENTRIES][4];
+CPUReadMemoryFunc *_io_mem_read[IO_MEM_NB_ENTRIES][4];
 void *io_mem_opaque[IO_MEM_NB_ENTRIES];
 static char io_mem_used[IO_MEM_NB_ENTRIES];
 static int io_mem_watch;
@@ -3350,7 +3350,7 @@ static inline uint32_t subpage_readlen (subpage_t *mmio,
 
     addr += mmio->region_offset[idx];
     idx = mmio->sub_io_index[idx];
-    return io_mem_read[idx][len](io_mem_opaque[idx], addr);
+    return io_mem_read(idx, addr, 1 <<len);
 }
 
 static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
@@ -3364,7 +3364,7 @@ static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
 
     addr += mmio->region_offset[idx];
     idx = mmio->sub_io_index[idx];
-    io_mem_write[idx][len](io_mem_opaque[idx], addr, value);
+    io_mem_write(idx, addr, value, 1 << len);
 }
 
 static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
@@ -3553,11 +3553,11 @@ static int cpu_register_io_memory_fixed(int io_index,
     }
 
     for (i = 0; i < 3; ++i) {
-        io_mem_read[io_index][i]
+        _io_mem_read[io_index][i]
             = (mem_read[i] ? mem_read[i] : unassigned_mem_read[i]);
     }
     for (i = 0; i < 3; ++i) {
-        io_mem_write[io_index][i]
+        _io_mem_write[io_index][i]
             = (mem_write[i] ? mem_write[i] : unassigned_mem_write[i]);
     }
     io_mem_opaque[io_index] = opaque;
@@ -3578,8 +3578,8 @@ void cpu_unregister_io_memory(int io_table_address)
     int io_index = io_table_address >> IO_MEM_SHIFT;
 
     for (i=0;i < 3; i++) {
-        io_mem_read[io_index][i] = unassigned_mem_read[i];
-        io_mem_write[io_index][i] = unassigned_mem_write[i];
+        _io_mem_read[io_index][i] = unassigned_mem_read[i];
+        _io_mem_write[io_index][i] = unassigned_mem_write[i];
     }
     io_mem_opaque[io_index] = NULL;
     io_mem_used[io_index] = 0;
@@ -3697,17 +3697,17 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                 if (l >= 4 && ((addr1 & 3) == 0)) {
                     /* 32 bit write access */
                     val = ldl_p(buf);
-                    io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
+                    io_mem_write(io_index, 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][1](io_mem_opaque[io_index], addr1, val);
+                    io_mem_write(io_index, addr1, val, 2);
                     l = 2;
                 } else {
                     /* 8 bit write access */
                     val = ldub_p(buf);
-                    io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
+                    io_mem_write(io_index, addr1, val, 1);
                     l = 1;
                 }
             } else {
@@ -3734,17 +3734,17 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                 addr1 = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
                 if (l >= 4 && ((addr1 & 3) == 0)) {
                     /* 32 bit read access */
-                    val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
+                    val = io_mem_read(io_index, 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][1](io_mem_opaque[io_index], addr1);
+                    val = io_mem_read(io_index, addr1, 2);
                     stw_p(buf, val);
                     l = 2;
                 } else {
                     /* 8 bit read access */
-                    val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
+                    val = io_mem_read(io_index, addr1, 1);
                     stb_p(buf, val);
                     l = 1;
                 }
@@ -3957,7 +3957,7 @@ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr,
         /* I/O case */
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
-        val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
+        val = io_mem_read(io_index, addr, 4);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap32(val);
@@ -4023,11 +4023,11 @@ static inline uint64_t ldq_phys_internal(target_phys_addr_t addr,
         /* XXX This is broken when device endian != cpu endian.
                Fix and add "endian" variable check */
 #ifdef TARGET_WORDS_BIGENDIAN
-        val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
-        val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
+        val = io_mem_read(io_index, addr, 4) << 32;
+        val |= io_mem_read(io_index, addr + 4, 4);
 #else
-        val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
-        val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
+        val = io_mem_read(io_index, addr, 4);
+        val |= io_mem_read(io_index, addr + 4, 4) << 32;
 #endif
     } else {
         /* RAM case */
@@ -4089,7 +4089,7 @@ static inline uint32_t lduw_phys_internal(target_phys_addr_t addr,
         /* I/O case */
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
-        val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
+        val = io_mem_read(io_index, addr, 2);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap16(val);
@@ -4149,7 +4149,7 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
     if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
-        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
+        io_mem_write(io_index, addr, val, 4);
     } else {
         unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
         ptr = qemu_get_ram_ptr(addr1);
@@ -4181,11 +4181,11 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
 #ifdef TARGET_WORDS_BIGENDIAN
-        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
-        io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
+        io_mem_write(io_index, addr, val >> 32, 4);
+        io_mem_write(io_index, addr + 4, (uint32_t)val, 4);
 #else
-        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
-        io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
+        io_mem_write(io_index, addr, (uint32_t)val, 4);
+        io_mem_write(io_index, addr + 4, val >> 32, 4);
 #endif
     } else {
         ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
@@ -4218,7 +4218,7 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val,
             val = bswap32(val);
         }
 #endif
-        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
+        io_mem_write(io_index, addr, val, 4);
     } else {
         unsigned long addr1;
         addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
@@ -4291,7 +4291,7 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val,
             val = bswap16(val);
         }
 #endif
-        io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
+        io_mem_write(io_index, addr, val, 2);
     } else {
         unsigned long addr1;
         addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
diff --git a/memory.c b/memory.c
index 6f9fea1..5c46833 100644
--- a/memory.c
+++ b/memory.c
@@ -1580,6 +1580,19 @@ 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)
+{
+    return _io_mem_read[io_index][bitops_ffsl(size)](io_mem_opaque[io_index],
+                                                     addr);
+}
+
+void io_mem_write(int io_index, target_phys_addr_t addr,
+                  uint64_t val, unsigned size)
+{
+    _io_mem_write[io_index][bitops_ffsl(size)](io_mem_opaque[io_index],
+                                               addr, val);
+}
+
 typedef struct MemoryRegionList MemoryRegionList;
 
 struct MemoryRegionList {
diff --git a/softmmu_template.h b/softmmu_template.h
index 36eb2e8..a030b5f 100644
--- a/softmmu_template.h
+++ b/softmmu_template.h
@@ -72,14 +72,14 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
 
     env->mem_io_vaddr = addr;
 #if SHIFT <= 2
-    res = io_mem_read[index][SHIFT](io_mem_opaque[index], physaddr);
+    res = io_mem_read(index, physaddr, 1 << SHIFT);
 #else
 #ifdef TARGET_WORDS_BIGENDIAN
-    res = (uint64_t)io_mem_read[index][2](io_mem_opaque[index], physaddr) << 32;
-    res |= io_mem_read[index][2](io_mem_opaque[index], physaddr + 4);
+    res = io_mem_read(index, physaddr, 4) << 32;
+    res |= io_mem_read(index, physaddr + 4, 4);
 #else
-    res = io_mem_read[index][2](io_mem_opaque[index], physaddr);
-    res |= (uint64_t)io_mem_read[index][2](io_mem_opaque[index], physaddr + 4) << 32;
+    res = io_mem_read(index, physaddr, 4);
+    res |= io_mem_read(index, physaddr + 4, 4) << 32;
 #endif
 #endif /* SHIFT > 2 */
     return res;
@@ -215,14 +215,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][SHIFT](io_mem_opaque[index], physaddr, val);
+    io_mem_write(index, physaddr, val, 1 << SHIFT);
 #else
 #ifdef TARGET_WORDS_BIGENDIAN
-    io_mem_write[index][2](io_mem_opaque[index], physaddr, val >> 32);
-    io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, val);
+    io_mem_write(index, physaddr, (val >> 32), 4);
+    io_mem_write(index, physaddr + 4, (uint32_t)val, 4);
 #else
-    io_mem_write[index][2](io_mem_opaque[index], physaddr, val);
-    io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, val >> 32);
+    io_mem_write(index, physaddr, (uint32_t)val, 4);
+    io_mem_write(index, physaddr + 4, val >> 32, 4);
 #endif
 #endif /* SHIFT > 2 */
 }
commit f1f6e3b86e0a73e0946f27ecb2b0a86e4665501c
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 20 17:52:22 2011 +0200

    exec: make phys_page_find() return a temporary
    
    Instead of returning a PhysPageDesc pointer, return a temporary.
    This lets us move away from actually storing PhysPageDesc's, and
    instead sythesising them when needed.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/exec.c b/exec.c
index 507d37c..d21413a 100644
--- a/exec.c
+++ b/exec.c
@@ -438,9 +438,18 @@ static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
     return pd + (index & (L2_SIZE - 1));
 }
 
-static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
+static inline PhysPageDesc phys_page_find(target_phys_addr_t index)
 {
-    return phys_page_find_alloc(index, 0);
+    PhysPageDesc *p = phys_page_find_alloc(index, 0);
+
+    if (p) {
+        return *p;
+    } else {
+        return (PhysPageDesc) {
+            .phys_offset = IO_MEM_UNASSIGNED,
+            .region_offset = index << TARGET_PAGE_BITS,
+        };
+    }
 }
 
 static void tlb_protect_code(ram_addr_t ram_addr);
@@ -1402,15 +1411,11 @@ static void breakpoint_invalidate(CPUState *env, target_ulong pc)
     target_phys_addr_t addr;
     target_ulong pd;
     ram_addr_t ram_addr;
-    PhysPageDesc *p;
+    PhysPageDesc p;
 
     addr = cpu_get_phys_page_debug(env, pc);
     p = phys_page_find(addr >> TARGET_PAGE_BITS);
-    if (!p) {
-        pd = IO_MEM_UNASSIGNED;
-    } else {
-        pd = p->phys_offset;
-    }
+    pd = p.phys_offset;
     ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
     tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
 }
@@ -2086,7 +2091,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;
+    PhysPageDesc p;
     unsigned long pd;
     unsigned int index;
     target_ulong address;
@@ -2101,11 +2106,7 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
         tlb_add_large_page(env, vaddr, size);
     }
     p = phys_page_find(paddr >> TARGET_PAGE_BITS);
-    if (!p) {
-        pd = IO_MEM_UNASSIGNED;
-    } else {
-        pd = p->phys_offset;
-    }
+    pd = p.phys_offset;
 #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",
@@ -2133,11 +2134,7 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
            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);
-        if (p) {
-            iotlb += p->region_offset;
-        } else {
-            iotlb += paddr;
-        }
+        iotlb += p.region_offset;
     }
 
     code_address = address;
@@ -2523,7 +2520,7 @@ void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
 
     addr = start_addr;
     do {
-        p = phys_page_find(addr >> TARGET_PAGE_BITS);
+        p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 0);
         if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
             ram_addr_t orig_memory = p->phys_offset;
             target_phys_addr_t start_addr2, end_addr2;
@@ -3680,7 +3677,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
     uint32_t val;
     target_phys_addr_t page;
     ram_addr_t pd;
-    PhysPageDesc *p;
+    PhysPageDesc p;
 
     while (len > 0) {
         page = addr & TARGET_PAGE_MASK;
@@ -3688,18 +3685,13 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
         if (l > len)
             l = len;
         p = phys_page_find(page >> TARGET_PAGE_BITS);
-        if (!p) {
-            pd = IO_MEM_UNASSIGNED;
-        } else {
-            pd = p->phys_offset;
-        }
+        pd = p.phys_offset;
 
         if (is_write) {
             if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
-                target_phys_addr_t addr1 = addr;
+                target_phys_addr_t addr1;
                 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
-                if (p)
-                    addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+                addr1 = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
                 /* XXX: could force cpu_single_env to NULL to avoid
                    potential bugs */
                 if (l >= 4 && ((addr1 & 3) == 0)) {
@@ -3736,11 +3728,10 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
         } else {
             if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
                 !(pd & IO_MEM_ROMD)) {
-                target_phys_addr_t addr1 = addr;
+                target_phys_addr_t addr1;
                 /* I/O case */
                 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
-                if (p)
-                    addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+                addr1 = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
                 if (l >= 4 && ((addr1 & 3) == 0)) {
                     /* 32 bit read access */
                     val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
@@ -3778,7 +3769,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr,
     uint8_t *ptr;
     target_phys_addr_t page;
     unsigned long pd;
-    PhysPageDesc *p;
+    PhysPageDesc p;
 
     while (len > 0) {
         page = addr & TARGET_PAGE_MASK;
@@ -3786,11 +3777,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr,
         if (l > len)
             l = len;
         p = phys_page_find(page >> TARGET_PAGE_BITS);
-        if (!p) {
-            pd = IO_MEM_UNASSIGNED;
-        } else {
-            pd = p->phys_offset;
-        }
+        pd = p.phys_offset;
 
         if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
             (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
@@ -3872,7 +3859,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
     int l;
     target_phys_addr_t page;
     unsigned long pd;
-    PhysPageDesc *p;
+    PhysPageDesc p;
     ram_addr_t raddr = RAM_ADDR_MAX;
     ram_addr_t rlen;
     void *ret;
@@ -3883,11 +3870,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
         if (l > len)
             l = len;
         p = phys_page_find(page >> TARGET_PAGE_BITS);
-        if (!p) {
-            pd = IO_MEM_UNASSIGNED;
-        } else {
-            pd = p->phys_offset;
-        }
+        pd = p.phys_offset;
 
         if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
             if (todo || bounce.buffer) {
@@ -3964,21 +3947,16 @@ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr,
     uint8_t *ptr;
     uint32_t val;
     unsigned long pd;
-    PhysPageDesc *p;
+    PhysPageDesc p;
 
     p = phys_page_find(addr >> TARGET_PAGE_BITS);
-    if (!p) {
-        pd = IO_MEM_UNASSIGNED;
-    } else {
-        pd = p->phys_offset;
-    }
+    pd = p.phys_offset;
 
     if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
         !(pd & IO_MEM_ROMD)) {
         /* I/O case */
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
-        if (p)
-            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+        addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
         val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
@@ -4031,21 +4009,16 @@ static inline uint64_t ldq_phys_internal(target_phys_addr_t addr,
     uint8_t *ptr;
     uint64_t val;
     unsigned long pd;
-    PhysPageDesc *p;
+    PhysPageDesc p;
 
     p = phys_page_find(addr >> TARGET_PAGE_BITS);
-    if (!p) {
-        pd = IO_MEM_UNASSIGNED;
-    } else {
-        pd = p->phys_offset;
-    }
+    pd = p.phys_offset;
 
     if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
         !(pd & IO_MEM_ROMD)) {
         /* I/O case */
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
-        if (p)
-            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+        addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
 
         /* XXX This is broken when device endian != cpu endian.
                Fix and add "endian" variable check */
@@ -4106,21 +4079,16 @@ static inline uint32_t lduw_phys_internal(target_phys_addr_t addr,
     uint8_t *ptr;
     uint64_t val;
     unsigned long pd;
-    PhysPageDesc *p;
+    PhysPageDesc p;
 
     p = phys_page_find(addr >> TARGET_PAGE_BITS);
-    if (!p) {
-        pd = IO_MEM_UNASSIGNED;
-    } else {
-        pd = p->phys_offset;
-    }
+    pd = p.phys_offset;
 
     if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
         !(pd & IO_MEM_ROMD)) {
         /* I/O case */
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
-        if (p)
-            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+        addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
         val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
@@ -4173,19 +4141,14 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
     int io_index;
     uint8_t *ptr;
     unsigned long pd;
-    PhysPageDesc *p;
+    PhysPageDesc p;
 
     p = phys_page_find(addr >> TARGET_PAGE_BITS);
-    if (!p) {
-        pd = IO_MEM_UNASSIGNED;
-    } else {
-        pd = p->phys_offset;
-    }
+    pd = p.phys_offset;
 
     if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
-        if (p)
-            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+        addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
         io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
     } else {
         unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
@@ -4209,19 +4172,14 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
     int io_index;
     uint8_t *ptr;
     unsigned long pd;
-    PhysPageDesc *p;
+    PhysPageDesc p;
 
     p = phys_page_find(addr >> TARGET_PAGE_BITS);
-    if (!p) {
-        pd = IO_MEM_UNASSIGNED;
-    } else {
-        pd = p->phys_offset;
-    }
+    pd = p.phys_offset;
 
     if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
-        if (p)
-            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+        addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
 #ifdef TARGET_WORDS_BIGENDIAN
         io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
         io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
@@ -4243,19 +4201,14 @@ 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;
+    PhysPageDesc p;
 
     p = phys_page_find(addr >> TARGET_PAGE_BITS);
-    if (!p) {
-        pd = IO_MEM_UNASSIGNED;
-    } else {
-        pd = p->phys_offset;
-    }
+    pd = p.phys_offset;
 
     if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
-        if (p)
-            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+        addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap32(val);
@@ -4321,19 +4274,14 @@ 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;
+    PhysPageDesc p;
 
     p = phys_page_find(addr >> TARGET_PAGE_BITS);
-    if (!p) {
-        pd = IO_MEM_UNASSIGNED;
-    } else {
-        pd = p->phys_offset;
-    }
+    pd = p.phys_offset;
 
     if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
-        if (p)
-            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+        addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap16(val);
commit be675c972088eba210e18dc125613e9f205a6bfb
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 20 16:22:55 2011 +0200

    memory: move endianness compensation to memory core
    
    Instead of doing device endianness compensation in cpu_register_io_memory(),
    do it in the memory core.
    
    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 698d7fc..79f989c 100644
--- a/exec-obsolete.h
+++ b/exec-obsolete.h
@@ -33,7 +33,7 @@ void qemu_ram_free_from_ptr(ram_addr_t addr);
 
 int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
                            CPUWriteMemoryFunc * const *mem_write,
-                           void *opaque, enum device_endian endian);
+                           void *opaque);
 void cpu_unregister_io_memory(int table_address);
 
 void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
diff --git a/exec.c b/exec.c
index 28c057c..507d37c 100644
--- a/exec.c
+++ b/exec.c
@@ -3507,8 +3507,7 @@ static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
     mmio = g_malloc0(sizeof(subpage_t));
 
     mmio->base = base;
-    subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio,
-                                            DEVICE_NATIVE_ENDIAN);
+    subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
 #if defined(DEBUG_SUBPAGE)
     printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
            mmio, base, TARGET_PAGE_SIZE, subpage_memory);
@@ -3532,106 +3531,6 @@ static int get_free_io_mem_idx(void)
     return -1;
 }
 
-/*
- * Usually, devices operate in little endian mode. There are devices out
- * there that operate in big endian too. Each device gets byte swapped
- * mmio if plugged onto a CPU that does the other endianness.
- *
- * CPU          Device           swap?
- *
- * little       little           no
- * little       big              yes
- * big          little           yes
- * big          big              no
- */
-
-typedef struct SwapEndianContainer {
-    CPUReadMemoryFunc *read[3];
-    CPUWriteMemoryFunc *write[3];
-    void *opaque;
-} SwapEndianContainer;
-
-static uint32_t swapendian_mem_readb (void *opaque, target_phys_addr_t addr)
-{
-    uint32_t val;
-    SwapEndianContainer *c = opaque;
-    val = c->read[0](c->opaque, addr);
-    return val;
-}
-
-static uint32_t swapendian_mem_readw(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t val;
-    SwapEndianContainer *c = opaque;
-    val = bswap16(c->read[1](c->opaque, addr));
-    return val;
-}
-
-static uint32_t swapendian_mem_readl(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t val;
-    SwapEndianContainer *c = opaque;
-    val = bswap32(c->read[2](c->opaque, addr));
-    return val;
-}
-
-static CPUReadMemoryFunc * const swapendian_readfn[3]={
-    swapendian_mem_readb,
-    swapendian_mem_readw,
-    swapendian_mem_readl
-};
-
-static void swapendian_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                  uint32_t val)
-{
-    SwapEndianContainer *c = opaque;
-    c->write[0](c->opaque, addr, val);
-}
-
-static void swapendian_mem_writew(void *opaque, target_phys_addr_t addr,
-                                  uint32_t val)
-{
-    SwapEndianContainer *c = opaque;
-    c->write[1](c->opaque, addr, bswap16(val));
-}
-
-static void swapendian_mem_writel(void *opaque, target_phys_addr_t addr,
-                                  uint32_t val)
-{
-    SwapEndianContainer *c = opaque;
-    c->write[2](c->opaque, addr, bswap32(val));
-}
-
-static CPUWriteMemoryFunc * const swapendian_writefn[3]={
-    swapendian_mem_writeb,
-    swapendian_mem_writew,
-    swapendian_mem_writel
-};
-
-static void swapendian_init(int io_index)
-{
-    SwapEndianContainer *c = g_malloc(sizeof(SwapEndianContainer));
-    int i;
-
-    /* Swap mmio for big endian targets */
-    c->opaque = io_mem_opaque[io_index];
-    for (i = 0; i < 3; i++) {
-        c->read[i] = io_mem_read[io_index][i];
-        c->write[i] = io_mem_write[io_index][i];
-
-        io_mem_read[io_index][i] = swapendian_readfn[i];
-        io_mem_write[io_index][i] = swapendian_writefn[i];
-    }
-    io_mem_opaque[io_index] = c;
-}
-
-static void swapendian_del(int io_index)
-{
-    if (io_mem_read[io_index][0] == swapendian_readfn[0]) {
-        g_free(io_mem_opaque[io_index]);
-    }
-}
-
 /* 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.
@@ -3642,7 +3541,7 @@ static void swapendian_del(int io_index)
 static int cpu_register_io_memory_fixed(int io_index,
                                         CPUReadMemoryFunc * const *mem_read,
                                         CPUWriteMemoryFunc * const *mem_write,
-                                        void *opaque, enum device_endian endian)
+                                        void *opaque)
 {
     int i;
 
@@ -3666,30 +3565,14 @@ static int cpu_register_io_memory_fixed(int io_index,
     }
     io_mem_opaque[io_index] = opaque;
 
-    switch (endian) {
-    case DEVICE_BIG_ENDIAN:
-#ifndef TARGET_WORDS_BIGENDIAN
-        swapendian_init(io_index);
-#endif
-        break;
-    case DEVICE_LITTLE_ENDIAN:
-#ifdef TARGET_WORDS_BIGENDIAN
-        swapendian_init(io_index);
-#endif
-        break;
-    case DEVICE_NATIVE_ENDIAN:
-    default:
-        break;
-    }
-
     return (io_index << IO_MEM_SHIFT);
 }
 
 int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
                            CPUWriteMemoryFunc * const *mem_write,
-                           void *opaque, enum device_endian endian)
+                           void *opaque)
 {
-    return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque, endian);
+    return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
 }
 
 void cpu_unregister_io_memory(int io_table_address)
@@ -3697,8 +3580,6 @@ void cpu_unregister_io_memory(int io_table_address)
     int i;
     int io_index = io_table_address >> IO_MEM_SHIFT;
 
-    swapendian_del(io_index);
-
     for (i=0;i < 3; i++) {
         io_mem_read[io_index][i] = unassigned_mem_read[i];
         io_mem_write[io_index][i] = unassigned_mem_write[i];
@@ -3712,23 +3593,18 @@ static void io_mem_init(void)
     int i;
 
     cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read,
-                                 unassigned_mem_write, NULL,
-                                 DEVICE_NATIVE_ENDIAN);
+                                 unassigned_mem_write, NULL);
     cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read,
-                                 unassigned_mem_write, NULL,
-                                 DEVICE_NATIVE_ENDIAN);
+                                 unassigned_mem_write, NULL);
     cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read,
-                                 notdirty_mem_write, NULL,
-                                 DEVICE_NATIVE_ENDIAN);
+                                 notdirty_mem_write, NULL);
     cpu_register_io_memory_fixed(IO_MEM_SUBPAGE_RAM, subpage_ram_read,
-                                 subpage_ram_write, NULL,
-                                 DEVICE_NATIVE_ENDIAN);
+                                 subpage_ram_write, NULL);
     for (i=0; i<5; i++)
         io_mem_used[i] = 1;
 
     io_mem_watch = cpu_register_io_memory(watch_mem_read,
-                                          watch_mem_write, NULL,
-                                          DEVICE_NATIVE_ENDIAN);
+                                          watch_mem_write, NULL);
 }
 
 static void memory_map_init(void)
diff --git a/memory.c b/memory.c
index 868ffd0..6f9fea1 100644
--- a/memory.c
+++ b/memory.c
@@ -857,6 +857,15 @@ static void memory_region_destructor_rom_device(MemoryRegion *mr)
     cpu_unregister_io_memory(mr->ram_addr & ~(TARGET_PAGE_MASK | IO_MEM_ROMD));
 }
 
+static bool memory_region_wrong_endianness(MemoryRegion *mr)
+{
+#ifdef TARGET_BIG_ENDIAN
+    return mr->ops->endianness == DEVICE_LITTLE_ENDIAN;
+#else
+    return mr->ops->endianness == DEVICE_BIG_ENDIAN;
+#endif
+}
+
 void memory_region_init(MemoryRegion *mr,
                         const char *name,
                         uint64_t size)
@@ -967,12 +976,24 @@ static uint32_t memory_region_read_thunk_b(void *mr, target_phys_addr_t addr)
 
 static uint32_t memory_region_read_thunk_w(void *mr, target_phys_addr_t addr)
 {
-    return memory_region_read_thunk_n(mr, addr, 2);
+    uint32_t data;
+
+    data = memory_region_read_thunk_n(mr, addr, 2);
+    if (memory_region_wrong_endianness(mr)) {
+        data = bswap16(data);
+    }
+    return data;
 }
 
 static uint32_t memory_region_read_thunk_l(void *mr, target_phys_addr_t addr)
 {
-    return memory_region_read_thunk_n(mr, addr, 4);
+    uint32_t data;
+
+    data = memory_region_read_thunk_n(mr, addr, 4);
+    if (memory_region_wrong_endianness(mr)) {
+        data = bswap32(data);
+    }
+    return data;
 }
 
 static void memory_region_write_thunk_b(void *mr, target_phys_addr_t addr,
@@ -984,12 +1005,18 @@ static void memory_region_write_thunk_b(void *mr, target_phys_addr_t addr,
 static void memory_region_write_thunk_w(void *mr, target_phys_addr_t addr,
                                         uint32_t data)
 {
+    if (memory_region_wrong_endianness(mr)) {
+        data = bswap16(data);
+    }
     memory_region_write_thunk_n(mr, addr, 2, data);
 }
 
 static void memory_region_write_thunk_l(void *mr, target_phys_addr_t addr,
                                         uint32_t data)
 {
+    if (memory_region_wrong_endianness(mr)) {
+        data = bswap32(data);
+    }
     memory_region_write_thunk_n(mr, addr, 4, data);
 }
 
@@ -1014,8 +1041,7 @@ static void memory_region_prepare_ram_addr(MemoryRegion *mr)
     mr->destructor = memory_region_destructor_iomem;
     mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
                                           memory_region_write_thunk,
-                                          mr,
-                                          mr->ops->endianness);
+                                          mr);
     mr->backend_registered = true;
 }
 
@@ -1082,8 +1108,7 @@ void memory_region_init_rom_device(MemoryRegion *mr,
     mr->ram_addr = qemu_ram_alloc(size, mr);
     mr->ram_addr |= cpu_register_io_memory(memory_region_read_thunk,
                                            memory_region_write_thunk,
-                                           mr,
-                                           mr->ops->endianness);
+                                           mr);
     mr->ram_addr |= IO_MEM_ROMD;
     mr->backend_registered = true;
 }
commit 7638e0d220df9dd150492ec59ac9683015e3c8ba
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Dec 21 14:16:38 2011 +0200

    memory: obsolete more dirty memory related functions
    
    No longer used outside memory.c and exec.c.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpu-all.h b/cpu-all.h
index 2fdb856..31d5b27 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -515,55 +515,6 @@ extern int mem_prealloc;
 /* Set if TLB entry is an IO callback.  */
 #define TLB_MMIO        (1 << 5)
 
-#define VGA_DIRTY_FLAG       0x01
-#define CODE_DIRTY_FLAG      0x02
-#define MIGRATION_DIRTY_FLAG 0x08
-
-/* read dirty bit (return 0 or 1) */
-static inline int cpu_physical_memory_is_dirty(ram_addr_t addr)
-{
-    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] == 0xff;
-}
-
-static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr)
-{
-    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS];
-}
-
-static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
-                                                int dirty_flags)
-{
-    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
-}
-
-static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
-{
-    ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
-}
-
-static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr,
-                                                      int dirty_flags)
-{
-    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags;
-}
-
-static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start,
-                                                        int length,
-                                                        int dirty_flags)
-{
-    int i, mask, len;
-    uint8_t *p;
-
-    len = length >> TARGET_PAGE_BITS;
-    mask = ~dirty_flags;
-    p = ram_list.phys_dirty + (start >> TARGET_PAGE_BITS);
-    for (i = 0; i < len; i++) {
-        p[i] &= mask;
-    }
-}
-
-void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
-                                     int dirty_flags);
 void cpu_tlb_update_dirty(CPUState *env);
 
 void dump_exec_info(FILE *f, fprintf_function cpu_fprintf);
diff --git a/exec-obsolete.h b/exec-obsolete.h
index 880105e..698d7fc 100644
--- a/exec-obsolete.h
+++ b/exec-obsolete.h
@@ -63,6 +63,55 @@ void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size);
 
 int cpu_physical_memory_set_dirty_tracking(int enable);
 
+#define VGA_DIRTY_FLAG       0x01
+#define CODE_DIRTY_FLAG      0x02
+#define MIGRATION_DIRTY_FLAG 0x08
+
+/* read dirty bit (return 0 or 1) */
+static inline int cpu_physical_memory_is_dirty(ram_addr_t addr)
+{
+    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] == 0xff;
+}
+
+static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr)
+{
+    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS];
+}
+
+static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
+                                                int dirty_flags)
+{
+    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
+}
+
+static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
+{
+    ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
+}
+
+static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr,
+                                                      int dirty_flags)
+{
+    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags;
+}
+
+static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start,
+                                                        int length,
+                                                        int dirty_flags)
+{
+    int i, mask, len;
+    uint8_t *p;
+
+    len = length >> TARGET_PAGE_BITS;
+    mask = ~dirty_flags;
+    p = ram_list.phys_dirty + (start >> TARGET_PAGE_BITS);
+    for (i = 0; i < len; i++) {
+        p[i] &= mask;
+    }
+}
+
+void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
+                                     int dirty_flags);
 #endif
 
 #endif
commit 5a97065b01222ccc830ddaaaf54c53646748eeb7
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Dec 21 14:21:27 2011 +0200

    xen: convert framebuffer dirty tracking to memory API
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/xen-all.c b/xen-all.c
index 1b8248f..d58d461 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -409,7 +409,6 @@ static int xen_sync_dirty_bitmap(XenIOState *state,
                                  ram_addr_t size)
 {
     target_phys_addr_t npages = size >> TARGET_PAGE_BITS;
-    target_phys_addr_t vram_offset = 0;
     const int width = sizeof(unsigned long) * 8;
     unsigned long bitmap[(npages + width - 1) / width];
     int rc, i, j;
@@ -426,7 +425,6 @@ static int xen_sync_dirty_bitmap(XenIOState *state,
     } else if (state->log_for_dirtybit != physmap) {
         return -1;
     }
-    vram_offset = physmap->phys_offset;
 
     rc = xc_hvm_track_dirty_vram(xen_xc, xen_domid,
                                  start_addr >> TARGET_PAGE_BITS, npages,
@@ -440,7 +438,8 @@ static int xen_sync_dirty_bitmap(XenIOState *state,
         while (map != 0) {
             j = ffsl(map) - 1;
             map &= ~(1ul << j);
-            cpu_physical_memory_set_dirty(vram_offset + (i * width + j) * TARGET_PAGE_SIZE);
+            memory_region_set_dirty(framebuffer,
+                                    (i * width + j) * TARGET_PAGE_SIZE);
         };
     }
 
commit 8f77558f2275f2e3bfabc5badf8fef591cd46dcf
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Dec 21 14:14:07 2011 +0200

    memory: obsolete cpu_physical_memory_[gs]et_dirty_tracking()
    
    The getter is no longer used, so it is completely removed.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index de1886b..66f7a3f 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -251,7 +251,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
     int ret;
 
     if (stage < 0) {
-        cpu_physical_memory_set_dirty_tracking(0);
+        memory_global_dirty_log_stop();
         return 0;
     }
 
@@ -274,8 +274,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
             }
         }
 
-        /* Enable dirty memory tracking */
-        cpu_physical_memory_set_dirty_tracking(1);
+        memory_global_dirty_log_start();
 
         qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
 
@@ -320,7 +319,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
         while ((bytes_sent = ram_save_block(f)) != 0) {
             bytes_transferred += bytes_sent;
         }
-        cpu_physical_memory_set_dirty_tracking(0);
+        memory_global_dirty_log_stop();
     }
 
     qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
diff --git a/cpu-all.h b/cpu-all.h
index 4acaa8b..2fdb856 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -566,10 +566,6 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
                                      int dirty_flags);
 void cpu_tlb_update_dirty(CPUState *env);
 
-int cpu_physical_memory_set_dirty_tracking(int enable);
-
-int cpu_physical_memory_get_dirty_tracking(void);
-
 void dump_exec_info(FILE *f, fprintf_function cpu_fprintf);
 #endif /* !CONFIG_USER_ONLY */
 
diff --git a/exec-obsolete.h b/exec-obsolete.h
index 3a2faae..880105e 100644
--- a/exec-obsolete.h
+++ b/exec-obsolete.h
@@ -61,6 +61,8 @@ static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
 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);
 
+int cpu_physical_memory_set_dirty_tracking(int enable);
+
 #endif
 
 #endif
diff --git a/exec.c b/exec.c
index a4116d9..28c057c 100644
--- a/exec.c
+++ b/exec.c
@@ -2008,19 +2008,9 @@ int cpu_physical_memory_set_dirty_tracking(int enable)
 {
     int ret = 0;
     in_migration = enable;
-    if (enable) {
-        memory_global_dirty_log_start();
-    } else {
-        memory_global_dirty_log_stop();
-    }
     return ret;
 }
 
-int cpu_physical_memory_get_dirty_tracking(void)
-{
-    return in_migration;
-}
-
 static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
 {
     ram_addr_t ram_addr;
diff --git a/memory.c b/memory.c
index f7b3d50..868ffd0 100644
--- a/memory.c
+++ b/memory.c
@@ -1493,6 +1493,7 @@ 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);
@@ -1507,6 +1508,7 @@ void memory_global_dirty_log_stop(void)
     QLIST_FOREACH(listener, &memory_listeners, link) {
         listener->log_global_stop(listener);
     }
+    cpu_physical_memory_set_dirty_tracking(0);
 }
 
 static void listener_add_address_space(MemoryListener *listener,
commit dc94a7ed615391219ef3ebc3705d24b5ed0e2364
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Dec 21 13:54:33 2011 +0200

    Convert ram_load() to the memory API
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index bb2f263..de1886b 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -344,7 +344,7 @@ static inline void *host_from_stream_offset(QEMUFile *f,
             return NULL;
         }
 
-        return block->host + offset;
+        return memory_region_get_ram_ptr(block->mr) + offset;
     }
 
     len = qemu_get_byte(f);
@@ -353,7 +353,7 @@ static inline void *host_from_stream_offset(QEMUFile *f,
 
     QLIST_FOREACH(block, &ram_list.blocks, next) {
         if (!strncmp(id, block->idstr, sizeof(id)))
-            return block->host + offset;
+            return memory_region_get_ram_ptr(block->mr) + offset;
     }
 
     fprintf(stderr, "Can't find block %s!\n", id);
commit f09f2189d51b405bb1e390beeb0ccf155ab2e788
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Dec 21 13:37:56 2011 +0200

    Remove support for version 3 ram_load
    
    Version 3 ram_load depends on ram_addrs, which are not stable.  Version 4
    was introduced in 0.13 (and RHEL 6), so this means live migration from 0.12
    and earlier to 1.1 or later will not work.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 5df8404..bb2f263 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -366,7 +366,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
     int flags;
     int error;
 
-    if (version_id < 3 || version_id > 4) {
+    if (version_id < 4 || version_id > 4) {
         return -EINVAL;
     }
 
@@ -377,11 +377,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
         addr &= TARGET_PAGE_MASK;
 
         if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
-            if (version_id == 3) {
-                if (addr != ram_bytes_total()) {
-                    return -EINVAL;
-                }
-            } else {
+            if (version_id == 4) {
                 /* Synchronize RAM block list */
                 char id[256];
                 ram_addr_t length;
@@ -419,10 +415,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
             void *host;
             uint8_t ch;
 
-            if (version_id == 3)
-                host = qemu_get_ram_ptr(addr);
-            else
-                host = host_from_stream_offset(f, addr, flags);
+            host = host_from_stream_offset(f, addr, flags);
             if (!host) {
                 return -EINVAL;
             }
@@ -438,10 +431,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
         } else if (flags & RAM_SAVE_FLAG_PAGE) {
             void *host;
 
-            if (version_id == 3)
-                host = qemu_get_ram_ptr(addr);
-            else
-                host = host_from_stream_offset(f, addr, flags);
+            host = host_from_stream_offset(f, addr, flags);
 
             qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
         }
commit 8fec98b41b0535ea4823c59ee9bf7d768feac74a
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Dec 21 13:22:16 2011 +0200

    Sort RAMBlocks by ID for migration, not by ram_addr
    
    ram_addr is (a) unstable (b) going away.  Sort by idstr instead.
    
    Commit b2e0a138e initially introduced the sorting for the purpose
    of improving debuggability.  After this patch, the order is still
    stable, but perhaps less usable by a human.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index c73fa1b..5df8404 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -217,12 +217,8 @@ static int block_compar(const void *a, const void *b)
 {
     RAMBlock * const *ablock = a;
     RAMBlock * const *bblock = b;
-    if ((*ablock)->offset < (*bblock)->offset) {
-        return -1;
-    } else if ((*ablock)->offset > (*bblock)->offset) {
-        return 1;
-    }
-    return 0;
+
+    return strcmp((*ablock)->idstr, (*bblock)->idstr);
 }
 
 static void sort_ram_list(void)
commit 71c510e26e4d90690966a70cb14d9c6e7ab5ba4e
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Dec 21 13:11:22 2011 +0200

    Switch ram_save to the memory API
    
    Avoid using ram_addr_t, instead use (MemoryRegion *, offset) pairs.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 847bf4e..c73fa1b 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -117,24 +117,22 @@ static int ram_save_block(QEMUFile *f)
 {
     RAMBlock *block = last_block;
     ram_addr_t offset = last_offset;
-    ram_addr_t current_addr;
     int bytes_sent = 0;
+    MemoryRegion *mr;
 
     if (!block)
         block = QLIST_FIRST(&ram_list.blocks);
 
-    current_addr = block->offset + offset;
-
     do {
-        if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
+        mr = block->mr;
+        if (memory_region_get_dirty(mr, offset, DIRTY_MEMORY_MIGRATION)) {
             uint8_t *p;
             int cont = (block == last_block) ? RAM_SAVE_FLAG_CONTINUE : 0;
 
-            cpu_physical_memory_reset_dirty(current_addr,
-                                            current_addr + TARGET_PAGE_SIZE,
-                                            MIGRATION_DIRTY_FLAG);
+            memory_region_reset_dirty(mr, offset, TARGET_PAGE_SIZE,
+                                      DIRTY_MEMORY_MIGRATION);
 
-            p = block->host + offset;
+            p = memory_region_get_ram_ptr(mr) + offset;
 
             if (is_dup_page(p, *p)) {
                 qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_COMPRESS);
@@ -166,10 +164,7 @@ static int ram_save_block(QEMUFile *f)
             if (!block)
                 block = QLIST_FIRST(&ram_list.blocks);
         }
-
-        current_addr = block->offset + offset;
-
-    } while (current_addr != last_block->offset + last_offset);
+    } while (block != last_block || offset != last_offset);
 
     last_block = block;
     last_offset = offset;
@@ -186,9 +181,9 @@ static ram_addr_t ram_save_remaining(void)
 
     QLIST_FOREACH(block, &ram_list.blocks, next) {
         ram_addr_t addr;
-        for (addr = block->offset; addr < block->offset + block->length;
-             addr += TARGET_PAGE_SIZE) {
-            if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
+        for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) {
+            if (memory_region_get_dirty(block->mr, addr,
+                                        DIRTY_MEMORY_MIGRATION)) {
                 count++;
             }
         }
@@ -275,11 +270,10 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
 
         /* Make sure all dirty bits are set */
         QLIST_FOREACH(block, &ram_list.blocks, next) {
-            for (addr = block->offset; addr < block->offset + block->length;
-                 addr += TARGET_PAGE_SIZE) {
-                if (!cpu_physical_memory_get_dirty(addr,
-                                                   MIGRATION_DIRTY_FLAG)) {
-                    cpu_physical_memory_set_dirty(addr);
+            for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) {
+                if (!memory_region_get_dirty(block->mr, addr,
+                                             DIRTY_MEMORY_MIGRATION)) {
+                    memory_region_set_dirty(block->mr, addr);
                 }
             }
         }
commit 7c63736603640ca7b74b65d71afc54fd0a3492f9
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Dec 21 13:09:49 2011 +0200

    Store MemoryRegion in RAMBlock
    
    As a step in moving live migration from RAMBlocks to MemoryRegions,
    store the MemoryRegion in a RAMBlock.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpu-all.h b/cpu-all.h
index 734833a..4acaa8b 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -476,6 +476,7 @@ extern ram_addr_t ram_size;
 #define RAM_PREALLOC_MASK   (1 << 0)
 
 typedef struct RAMBlock {
+    struct MemoryRegion *mr;
     uint8_t *host;
     ram_addr_t offset;
     ram_addr_t length;
diff --git a/exec.c b/exec.c
index dffceb9..a4116d9 100644
--- a/exec.c
+++ b/exec.c
@@ -2793,6 +2793,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
     size = TARGET_PAGE_ALIGN(size);
     new_block = g_malloc0(sizeof(*new_block));
 
+    new_block->mr = mr;
     new_block->offset = find_ram_offset(size);
     if (host) {
         new_block->host = host;
commit c5705a7728b4a6bc9e4f2d35911adbaf28042b25
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Dec 20 15:59:12 2011 +0200

    vmstate, memory: decouple vmstate from memory API
    
    Currently creating a memory region automatically registers it for
    live migration.  This differs from other state (which is enumerated
    in a VMStateDescription structure) and ties the live migration code
    into the memory core.
    
    Decouple the two by introducing a separate API, vmstate_register_ram(),
    for registering a RAM block for migration.  Currently the same
    implementation is reused, but later it can be moved into a separate list,
    and registrations can be moved to VMStateDescription blocks.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 8813673..47fdc82 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -109,7 +109,7 @@ 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 += buffered_file.o migration.o migration-tcp.o
-common-obj-y += qemu-char.o savevm.o #aio.o
+common-obj-y += qemu-char.o #aio.o
 common-obj-y += msmouse.o ps2.o
 common-obj-y += qdev.o qdev-properties.o
 common-obj-y += block-migration.o iohandler.o
diff --git a/Makefile.target b/Makefile.target
index 3261383..9195223 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -196,7 +196,7 @@ obj-$(CONFIG_VHOST_NET) += vhost.o
 obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
-obj-y += memory.o
+obj-y += memory.o savevm.o
 LIBS+=-lz
 
 QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
diff --git a/cpu-common.h b/cpu-common.h
index 3fe44d2..3c0cff0 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -49,6 +49,7 @@ void qemu_put_ram_ptr(void *addr);
 /* This should not be used by devices.  */
 int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr);
 ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);
+void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev);
 
 void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                             int len, int is_write);
diff --git a/exec-obsolete.h b/exec-obsolete.h
index 34b9fc5..3a2faae 100644
--- a/exec-obsolete.h
+++ b/exec-obsolete.h
@@ -25,11 +25,9 @@
 
 #ifndef CONFIG_USER_ONLY
 
-ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
-                                   ram_addr_t size, void *host,
+ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
                                    MemoryRegion *mr);
-ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size,
-                          MemoryRegion *mr);
+ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr);
 void qemu_ram_free(ram_addr_t addr);
 void qemu_ram_free_from_ptr(ram_addr_t addr);
 
diff --git a/exec.c b/exec.c
index b02199b..dffceb9 100644
--- a/exec.c
+++ b/exec.c
@@ -2753,14 +2753,19 @@ static ram_addr_t last_ram_offset(void)
     return last;
 }
 
-ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
-                                   ram_addr_t size, void *host,
-                                   MemoryRegion *mr)
+void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
 {
     RAMBlock *new_block, *block;
 
-    size = TARGET_PAGE_ALIGN(size);
-    new_block = g_malloc0(sizeof(*new_block));
+    new_block = NULL;
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (block->offset == addr) {
+            new_block = block;
+            break;
+        }
+    }
+    assert(new_block);
+    assert(!new_block->idstr[0]);
 
     if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
         char *id = dev->parent_bus->info->get_dev_path(dev);
@@ -2772,12 +2777,21 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
     pstrcat(new_block->idstr, sizeof(new_block->idstr), name);
 
     QLIST_FOREACH(block, &ram_list.blocks, next) {
-        if (!strcmp(block->idstr, new_block->idstr)) {
+        if (block != new_block && !strcmp(block->idstr, new_block->idstr)) {
             fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
                     new_block->idstr);
             abort();
         }
     }
+}
+
+ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
+                                   MemoryRegion *mr)
+{
+    RAMBlock *new_block;
+
+    size = TARGET_PAGE_ALIGN(size);
+    new_block = g_malloc0(sizeof(*new_block));
 
     new_block->offset = find_ram_offset(size);
     if (host) {
@@ -2834,10 +2848,9 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
     return new_block->offset;
 }
 
-ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size,
-                          MemoryRegion *mr)
+ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr)
 {
-    return qemu_ram_alloc_from_ptr(dev, name, size, NULL, mr);
+    return qemu_ram_alloc_from_ptr(size, NULL, mr);
 }
 
 void qemu_ram_free_from_ptr(ram_addr_t addr)
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index adf7382..7d924a3 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -726,7 +726,8 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
 
     /* Main memory region, 0x00.0000.0000.  Real hardware supports 32GB,
        but the address space hole reserved at this point is 8TB.  */
-    memory_region_init_ram(&s->ram_region, NULL, "ram", ram_size);
+    memory_region_init_ram(&s->ram_region, "ram", ram_size);
+    vmstate_register_ram_global(&s->ram_region);
     memory_region_add_subregion(addr_space, 0, &s->ram_region);
 
     /* TIGbus, 0x801.0000.0000, 1GB.  */
diff --git a/hw/an5206.c b/hw/an5206.c
index 319a40e..d57306d 100644
--- a/hw/an5206.c
+++ b/hw/an5206.c
@@ -46,11 +46,13 @@ static void an5206_init(ram_addr_t ram_size,
     env->rambar0 = AN5206_RAMBAR_ADDR | 1;
 
     /* DRAM at address zero */
-    memory_region_init_ram(ram, NULL, "an5206.ram", ram_size);
+    memory_region_init_ram(ram, "an5206.ram", ram_size);
+    vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space_mem, 0, ram);
 
     /* Internal SRAM.  */
-    memory_region_init_ram(sram, NULL, "an5206.sram", 512);
+    memory_region_init_ram(sram, "an5206.sram", 512);
+    vmstate_register_ram_global(sram);
     memory_region_add_subregion(address_space_mem, AN5206_RAMBAR_ADDR, sram);
 
     mcf5206_init(address_space_mem, AN5206_MBAR_ADDR, env);
diff --git a/hw/armv7m.c b/hw/armv7m.c
index eb8c0d6..5c7a950 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -198,10 +198,12 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
 #endif
 
     /* Flash programming is done via the SCU, so pretend it is ROM.  */
-    memory_region_init_ram(flash, NULL, "armv7m.flash", flash_size);
+    memory_region_init_ram(flash, "armv7m.flash", flash_size);
+    vmstate_register_ram_global(flash);
     memory_region_set_readonly(flash, true);
     memory_region_add_subregion(address_space_mem, 0, flash);
-    memory_region_init_ram(sram, NULL, "armv7m.sram", sram_size);
+    memory_region_init_ram(sram, "armv7m.sram", sram_size);
+    vmstate_register_ram_global(sram);
     memory_region_add_subregion(address_space_mem, 0x20000000, sram);
     armv7m_bitband_init();
 
@@ -235,7 +237,8 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
     /* Hack to map an additional page of ram at the top of the address
        space.  This stops qemu complaining about executing code outside RAM
        when returning from an exception.  */
-    memory_region_init_ram(hack, NULL, "armv7m.hack", 0x1000);
+    memory_region_init_ram(hack, "armv7m.hack", 0x1000);
+    vmstate_register_ram_global(hack);
     memory_region_add_subregion(address_space_mem, 0xfffff000, hack);
 
     qemu_register_reset(armv7m_reset, env);
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index c5405ce..c9301fd 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -266,12 +266,14 @@ void axisdev88_init (ram_addr_t ram_size,
     env = cpu_init(cpu_model);
 
     /* allocate RAM */
-    memory_region_init_ram(phys_ram, NULL, "axisdev88.ram", ram_size);
+    memory_region_init_ram(phys_ram, "axisdev88.ram", ram_size);
+    vmstate_register_ram_global(phys_ram);
     memory_region_add_subregion(address_space_mem, 0x40000000, phys_ram);
 
     /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the 
        internal memory.  */
-    memory_region_init_ram(phys_intmem, NULL, "axisdev88.chipram", INTMEM_SIZE);
+    memory_region_init_ram(phys_intmem, "axisdev88.chipram", INTMEM_SIZE);
+    vmstate_register_ram_global(phys_intmem);
     memory_region_add_subregion(address_space_mem, 0x38000000, phys_intmem);
 
       /* Attach a NAND flash to CS1.  */
diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c
index 30146b9..e3c5740 100644
--- a/hw/dummy_m68k.c
+++ b/hw/dummy_m68k.c
@@ -40,7 +40,8 @@ static void dummy_m68k_init(ram_addr_t ram_size,
     env->vbr = 0;
 
     /* RAM at address zero */
-    memory_region_init_ram(ram, NULL, "dummy_m68k.ram", ram_size);
+    memory_region_init_ram(ram, "dummy_m68k.ram", ram_size);
+    vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space_mem, 0, ram);
 
     /* Load kernel.  */
diff --git a/hw/g364fb.c b/hw/g364fb.c
index 34fb08c..33ec149 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -524,8 +524,9 @@ static void g364fb_init(DeviceState *dev, G364State *s)
                                  g364fb_screen_dump, NULL, s);
 
     memory_region_init_io(&s->mem_ctrl, &g364fb_ctrl_ops, s, "ctrl", 0x180000);
-    memory_region_init_ram_ptr(&s->mem_vram, dev, "vram",
+    memory_region_init_ram_ptr(&s->mem_vram, "vram",
                                s->vram_size, s->vram);
+    vmstate_register_ram(&s->mem_vram, dev);
     memory_region_set_coalescing(&s->mem_vram);
 }
 
diff --git a/hw/hw.h b/hw/hw.h
index efa04d1..932014a 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -949,4 +949,9 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
                                    int required_for_version);
 void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
                         void *opaque);
+struct MemoryRegion;
+void vmstate_register_ram(struct MemoryRegion *memory, DeviceState *dev);
+void vmstate_unregister_ram(struct MemoryRegion *memory, DeviceState *dev);
+void vmstate_register_ram_global(struct MemoryRegion *memory);
+
 #endif
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index 2551236..c8f3955 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -261,7 +261,8 @@ static int integratorcm_init(SysBusDevice *dev)
     }
     memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
     s->cm_init = 0x00000112;
-    memory_region_init_ram(&s->flash, NULL, "integrator.flash", 0x100000);
+    memory_region_init_ram(&s->flash, "integrator.flash", 0x100000);
+    vmstate_register_ram_global(&s->flash);
     s->flash_mapped = false;
 
     memory_region_init_io(&s->iomem, &integratorcm_ops, s,
@@ -471,7 +472,8 @@ static void integratorcp_init(ram_addr_t ram_size,
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    memory_region_init_ram(ram, NULL, "integrator.ram", ram_size);
+    memory_region_init_ram(ram, "integrator.ram", ram_size);
+    vmstate_register_ram_global(ram);
     /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
     /* ??? RAM should repeat to fill physical memory space.  */
     /* SDRAM at address zero*/
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index 7b4dbf6..1aa9e3b 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -335,8 +335,9 @@ static void create_shared_memory_BAR(IVShmemState *s, int fd) {
 
     ptr = mmap(0, s->ivshmem_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
 
-    memory_region_init_ram_ptr(&s->ivshmem, &s->dev.qdev, "ivshmem.bar2",
+    memory_region_init_ram_ptr(&s->ivshmem, "ivshmem.bar2",
                                s->ivshmem_size, ptr);
+    vmstate_register_ram(&s->ivshmem, &s->dev.qdev);
     memory_region_add_subregion(&s->bar, 0, &s->ivshmem);
 
     /* region for shared memory */
@@ -451,8 +452,9 @@ static void ivshmem_read(void *opaque, const uint8_t * buf, int flags)
         /* mmap the region and map into the BAR2 */
         map_ptr = mmap(0, s->ivshmem_size, PROT_READ|PROT_WRITE, MAP_SHARED,
                                                             incoming_fd, 0);
-        memory_region_init_ram_ptr(&s->ivshmem, &s->dev.qdev,
+        memory_region_init_ram_ptr(&s->ivshmem,
                                    "ivshmem.bar2", s->ivshmem_size, map_ptr);
+        vmstate_register_ram(&s->ivshmem, &s->dev.qdev);
 
         IVSHMEM_DPRINTF("guest h/w addr = %" PRIu64 ", size = %" PRIu64 "\n",
                          s->ivshmem_offset, s->ivshmem_size);
@@ -753,6 +755,7 @@ static int pci_ivshmem_uninit(PCIDevice *dev)
 
     memory_region_destroy(&s->ivshmem_mmio);
     memory_region_del_subregion(&s->bar, &s->ivshmem);
+    vmstate_unregister_ram(&s->ivshmem, &s->dev.qdev);
     memory_region_destroy(&s->ivshmem);
     memory_region_destroy(&s->bar);
     unregister_savevm(&dev->qdev, "ivshmem", s);
diff --git a/hw/leon3.c b/hw/leon3.c
index 607ec85..e25bb04 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -142,12 +142,14 @@ static void leon3_generic_hw_init(ram_addr_t  ram_size,
         exit(1);
     }
 
-    memory_region_init_ram(ram, NULL, "leon3.ram", ram_size);
+    memory_region_init_ram(ram, "leon3.ram", ram_size);
+    vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space_mem, 0x40000000, ram);
 
     /* Allocate BIOS */
     prom_size = 8 * 1024 * 1024; /* 8Mb */
-    memory_region_init_ram(prom, NULL, "Leon3.bios", prom_size);
+    memory_region_init_ram(prom, "Leon3.bios", prom_size);
+    vmstate_register_ram_global(prom);
     memory_region_set_readonly(prom, true);
     memory_region_add_subregion(address_space_mem, 0x00000000, prom);
 
diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c
index 97e1c00..3cdf120 100644
--- a/hw/lm32_boards.c
+++ b/hw/lm32_boards.c
@@ -106,7 +106,8 @@ static void lm32_evr_init(ram_addr_t ram_size_not_used,
 
     reset_info->flash_base = flash_base;
 
-    memory_region_init_ram(phys_ram, NULL, "lm32_evr.sdram", ram_size);
+    memory_region_init_ram(phys_ram, "lm32_evr.sdram", ram_size);
+    vmstate_register_ram_global(phys_ram);
     memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
@@ -200,7 +201,8 @@ static void lm32_uclinux_init(ram_addr_t ram_size_not_used,
 
     reset_info->flash_base = flash_base;
 
-    memory_region_init_ram(phys_ram, NULL, "lm32_uclinux.sdram", ram_size);
+    memory_region_init_ram(phys_ram, "lm32_uclinux.sdram", ram_size);
+    vmstate_register_ram_global(phys_ram);
     memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
diff --git a/hw/mainstone.c b/hw/mainstone.c
index 3ed6649..c914a4e 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -111,7 +111,8 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
 
     /* Setup CPU & memory */
     cpu = pxa270_init(address_space_mem, mainstone_binfo.ram_size, cpu_model);
-    memory_region_init_ram(rom, NULL, "mainstone.rom", MAINSTONE_ROM);
+    memory_region_init_ram(rom, "mainstone.rom", MAINSTONE_ROM);
+    vmstate_register_ram_global(rom);
     memory_region_set_readonly(rom, true);
     memory_region_add_subregion(address_space_mem, 0, rom);
 
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index ec608a1..3b0636d 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -213,11 +213,13 @@ static void mcf5208evb_init(ram_addr_t ram_size,
     /* TODO: Configure BARs.  */
 
     /* DRAM at 0x40000000 */
-    memory_region_init_ram(ram, NULL, "mcf5208.ram", ram_size);
+    memory_region_init_ram(ram, "mcf5208.ram", ram_size);
+    vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space_mem, 0x40000000, ram);
 
     /* Internal SRAM.  */
-    memory_region_init_ram(sram, NULL, "mcf5208.sram", 16384);
+    memory_region_init_ram(sram, "mcf5208.sram", 16384);
+    vmstate_register_ram_global(sram);
     memory_region_add_subregion(address_space_mem, 0x80000000, sram);
 
     /* Internal peripherals.  */
diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c
index b5e0dac..7006d29 100644
--- a/hw/milkymist-minimac2.c
+++ b/hw/milkymist-minimac2.c
@@ -468,8 +468,9 @@ static int milkymist_minimac2_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, &s->regs_region);
 
     /* register buffers memory */
-    memory_region_init_ram(&s->buffers, NULL, "milkymist-minimac2.buffers",
+    memory_region_init_ram(&s->buffers, "milkymist-minimac2.buffers",
                            buffers_size);
+    vmstate_register_ram_global(&s->buffers);
     s->rx0_buf = memory_region_get_ram_ptr(&s->buffers);
     s->rx1_buf = s->rx0_buf + MINIMAC2_BUFFER_SIZE;
     s->tx_buf = s->rx1_buf + MINIMAC2_BUFFER_SIZE;
diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c
index 6dd953c..83bd1c4 100644
--- a/hw/milkymist-softusb.c
+++ b/hw/milkymist-softusb.c
@@ -267,11 +267,13 @@ static int milkymist_softusb_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, &s->regs_region);
 
     /* register pmem and dmem */
-    memory_region_init_ram(&s->pmem, NULL, "milkymist-softusb.pmem",
+    memory_region_init_ram(&s->pmem, "milkymist-softusb.pmem",
                            s->pmem_size);
+    vmstate_register_ram_global(&s->pmem);
     sysbus_add_memory(dev, s->pmem_base, &s->pmem);
-    memory_region_init_ram(&s->dmem, NULL, "milkymist-softusb.dmem",
+    memory_region_init_ram(&s->dmem, "milkymist-softusb.dmem",
                            s->dmem_size);
+    vmstate_register_ram_global(&s->dmem);
     sysbus_add_memory(dev, s->dmem_base, &s->dmem);
 
     hid_init(&s->hid_kbd, HID_KEYBOARD, softusb_kbd_hid_datain);
diff --git a/hw/milkymist.c b/hw/milkymist.c
index b7a8c1c..eaef0c2 100644
--- a/hw/milkymist.c
+++ b/hw/milkymist.c
@@ -110,7 +110,8 @@ milkymist_init(ram_addr_t ram_size_not_used,
 
     cpu_lm32_set_phys_msb_ignore(env, 1);
 
-    memory_region_init_ram(phys_sdram, NULL, "milkymist.sdram", sdram_size);
+    memory_region_init_ram(phys_sdram, "milkymist.sdram", sdram_size);
+    vmstate_register_ram_global(phys_sdram);
     memory_region_add_subregion(address_space_mem, sdram_base, phys_sdram);
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index 5e87665..94ef1df 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -291,8 +291,10 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
     bios_size = 1024 * 1024;
 
     /* allocate RAM */
-    memory_region_init_ram(ram, NULL, "fulong2e.ram", ram_size);
-    memory_region_init_ram(bios, NULL, "fulong2e.bios", bios_size);
+    memory_region_init_ram(ram, "fulong2e.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_init_ram(bios, "fulong2e.bios", bios_size);
+    vmstate_register_ram_global(bios);
     memory_region_set_readonly(bios, true);
 
     memory_region_add_subregion(address_space_mem, 0, ram);
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index da04982..63165b9 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -146,10 +146,12 @@ static void mips_jazz_init(MemoryRegion *address_space,
     qemu_register_reset(main_cpu_reset, env);
 
     /* allocate RAM */
-    memory_region_init_ram(ram, NULL, "mips_jazz.ram", ram_size);
+    memory_region_init_ram(ram, "mips_jazz.ram", ram_size);
+    vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space, 0, ram);
 
-    memory_region_init_ram(bios, NULL, "mips_jazz.bios", MAGNUM_BIOS_SIZE);
+    memory_region_init_ram(bios, "mips_jazz.bios", MAGNUM_BIOS_SIZE);
+    vmstate_register_ram_global(bios);
     memory_region_set_readonly(bios, true);
     memory_region_init_alias(bios2, "mips_jazz.bios", bios,
                              0, MAGNUM_BIOS_SIZE);
@@ -208,7 +210,8 @@ static void mips_jazz_init(MemoryRegion *address_space,
         {
             /* Simple ROM, so user doesn't have to provide one */
             MemoryRegion *rom_mr = g_new(MemoryRegion, 1);
-            memory_region_init_ram(rom_mr, NULL, "g364fb.rom", 0x80000);
+            memory_region_init_ram(rom_mr, "g364fb.rom", 0x80000);
+            vmstate_register_ram_global(rom_mr);
             memory_region_set_readonly(rom_mr, true);
             uint8_t *rom = memory_region_get_ram_ptr(rom_mr);
             memory_region_add_subregion(address_space, 0x60000000, rom_mr);
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index d94ad1d..6b72cf2 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -826,7 +826,8 @@ void mips_malta_init (ram_addr_t ram_size,
                 ((unsigned int)ram_size / (1 << 20)));
         exit(1);
     }
-    memory_region_init_ram(ram, NULL, "mips_malta.ram", ram_size);
+    memory_region_init_ram(ram, "mips_malta.ram", ram_size);
+    vmstate_register_ram_global(ram);
     memory_region_add_subregion(system_memory, 0, ram);
 
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -841,7 +842,8 @@ void mips_malta_init (ram_addr_t ram_size,
     if (kernel_filename) {
         /* Write a small bootloader to the flash location. */
         bios = g_new(MemoryRegion, 1);
-        memory_region_init_ram(bios, NULL, "mips_malta.bios", BIOS_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. */
@@ -878,7 +880,8 @@ void mips_malta_init (ram_addr_t ram_size,
            fl_idx++;
         } else {
             bios = g_new(MemoryRegion, 1);
-            memory_region_init_ram(bios, NULL, "mips_malta.bios", BIOS_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);
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index b56cba6..76c95b2 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -163,8 +163,10 @@ mips_mipssim_init (ram_addr_t ram_size,
     qemu_register_reset(main_cpu_reset, reset_info);
 
     /* Allocate RAM. */
-    memory_region_init_ram(ram, NULL, "mips_mipssim.ram", ram_size);
-    memory_region_init_ram(bios, NULL, "mips_mipssim.bios", BIOS_SIZE);
+    memory_region_init_ram(ram, "mips_mipssim.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_init_ram(bios, "mips_mipssim.bios", BIOS_SIZE);
+    vmstate_register_ram_global(bios);
     memory_region_set_readonly(bios, true);
 
     memory_region_add_subregion(address_space_mem, 0, ram);
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index c078078..1c0615c 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -195,7 +195,8 @@ void mips_r4k_init (ram_addr_t ram_size,
                 ((unsigned int)ram_size / (1 << 20)));
         exit(1);
     }
-    memory_region_init_ram(ram, NULL, "mips_r4k.ram", ram_size);
+    memory_region_init_ram(ram, "mips_r4k.ram", ram_size);
+    vmstate_register_ram_global(ram);
 
     memory_region_add_subregion(address_space_mem, 0, ram);
 
@@ -221,7 +222,8 @@ void mips_r4k_init (ram_addr_t ram_size,
 #endif
     if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
         bios = g_new(MemoryRegion, 1);
-        memory_region_init_ram(bios, NULL, "mips_r4k.bios", BIOS_SIZE);
+        memory_region_init_ram(bios, "mips_r4k.bios", BIOS_SIZE);
+        vmstate_register_ram_global(bios);
         memory_region_set_readonly(bios, true);
         memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios);
 
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 3c6cefe..a01e3d2 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1472,10 +1472,12 @@ static void musicpal_init(ram_addr_t ram_size,
     cpu_pic = arm_pic_init_cpu(env);
 
     /* For now we use a fixed - the original - RAM size */
-    memory_region_init_ram(ram, NULL, "musicpal.ram", MP_RAM_DEFAULT_SIZE);
+    memory_region_init_ram(ram, "musicpal.ram", MP_RAM_DEFAULT_SIZE);
+    vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space_mem, 0, ram);
 
-    memory_region_init_ram(sram, NULL, "musicpal.sram", MP_SRAM_SIZE);
+    memory_region_init_ram(sram, "musicpal.sram", MP_SRAM_SIZE);
+    vmstate_register_ram_global(sram);
     memory_region_add_subregion(address_space_mem, MP_SRAM_BASE, sram);
 
     dev = sysbus_create_simple("mv88w8618_pic", MP_PIC_BASE,
diff --git a/hw/omap1.c b/hw/omap1.c
index 53cde76..590ceb5 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -3819,9 +3819,11 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
     omap_clk_init(s);
 
     /* Memory-mapped stuff */
-    memory_region_init_ram(&s->emiff_ram, NULL, "omap1.dram", s->sdram_size);
+    memory_region_init_ram(&s->emiff_ram, "omap1.dram", s->sdram_size);
+    vmstate_register_ram_global(&s->emiff_ram);
     memory_region_add_subregion(system_memory, OMAP_EMIFF_BASE, &s->emiff_ram);
-    memory_region_init_ram(&s->imif_ram, NULL, "omap1.sram", s->sram_size);
+    memory_region_init_ram(&s->imif_ram, "omap1.sram", s->sram_size);
+    vmstate_register_ram_global(&s->imif_ram);
     memory_region_add_subregion(system_memory, OMAP_IMIF_BASE, &s->imif_ram);
 
     omap_clkm_init(system_memory, 0xfffece00, 0xe1008000, s);
diff --git a/hw/omap2.c b/hw/omap2.c
index c09c04a..a6851b0 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -2269,9 +2269,11 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
     omap_clk_init(s);
 
     /* Memory-mapped stuff */
-    memory_region_init_ram(&s->sdram, NULL, "omap2.dram", s->sdram_size);
+    memory_region_init_ram(&s->sdram, "omap2.dram", s->sdram_size);
+    vmstate_register_ram_global(&s->sdram);
     memory_region_add_subregion(sysmem, OMAP2_Q2_BASE, &s->sdram);
-    memory_region_init_ram(&s->sram, NULL, "omap2.sram", s->sram_size);
+    memory_region_init_ram(&s->sram, "omap2.sram", s->sram_size);
+    vmstate_register_ram_global(&s->sram);
     memory_region_add_subregion(sysmem, OMAP2_SRAM_BASE, &s->sram);
 
     s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54);
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index 8e58645..4e8ec4a 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -124,7 +124,8 @@ static void sx1_init(ram_addr_t ram_size,
     cpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, cpu_model);
 
     /* External Flash (EMIFS) */
-    memory_region_init_ram(flash, NULL, "omap_sx1.flash0-0", flash_size);
+    memory_region_init_ram(flash, "omap_sx1.flash0-0", flash_size);
+    vmstate_register_ram_global(flash);
     memory_region_set_readonly(flash, true);
     memory_region_add_subregion(address_space, OMAP_CS0_BASE, flash);
 
@@ -165,7 +166,8 @@ static void sx1_init(ram_addr_t ram_size,
 
     if ((version == 1) &&
             (dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
-        memory_region_init_ram(flash_1, NULL, "omap_sx1.flash1-0", flash1_size);
+        memory_region_init_ram(flash_1, "omap_sx1.flash1-0", flash1_size);
+        vmstate_register_ram_global(flash_1);
         memory_region_set_readonly(flash_1, true);
         memory_region_add_subregion(address_space, OMAP_CS1_BASE, flash_1);
 
diff --git a/hw/onenand.c b/hw/onenand.c
index a9d8d67..33c9718 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -781,7 +781,8 @@ static int onenand_initfn(SysBusDevice *dev)
     }
     s->otp = memset(g_malloc((64 + 2) << PAGE_SHIFT),
                     0xff, (64 + 2) << PAGE_SHIFT);
-    memory_region_init_ram(&s->ram, NULL, "onenand.ram", 0xc000 << s->shift);
+    memory_region_init_ram(&s->ram, "onenand.ram", 0xc000 << s->shift);
+    vmstate_register_ram_global(&s->ram);
     ram = memory_region_get_ram_ptr(&s->ram);
     s->boot[0] = ram + (0x0000 << s->shift);
     s->boot[1] = ram + (0x8000 << s->shift);
diff --git a/hw/palm.c b/hw/palm.c
index 094bfde..b1252ab 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -211,7 +211,8 @@ static void palmte_init(ram_addr_t ram_size,
     cpu = omap310_mpu_init(address_space_mem, sdram_size, cpu_model);
 
     /* External Flash (EMIFS) */
-    memory_region_init_ram(flash, NULL, "palmte.flash", flash_size);
+    memory_region_init_ram(flash, "palmte.flash", flash_size);
+    vmstate_register_ram_global(flash);
     memory_region_set_readonly(flash, true);
     memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE, flash);
 
diff --git a/hw/pc.c b/hw/pc.c
index f51afa8..85304cf 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -987,8 +987,9 @@ void pc_memory_init(MemoryRegion *system_memory,
      * with older qemus that used qemu_ram_alloc().
      */
     ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, NULL, "pc.ram",
+    memory_region_init_ram(ram, "pc.ram",
                            below_4g_mem_size + above_4g_mem_size);
+    vmstate_register_ram_global(ram);
     *ram_memory = ram;
     ram_below_4g = g_malloc(sizeof(*ram_below_4g));
     memory_region_init_alias(ram_below_4g, "ram-below-4g", ram,
@@ -1016,7 +1017,8 @@ void pc_memory_init(MemoryRegion *system_memory,
         goto bios_error;
     }
     bios = g_malloc(sizeof(*bios));
-    memory_region_init_ram(bios, NULL, "pc.bios", bios_size);
+    memory_region_init_ram(bios, "pc.bios", bios_size);
+    vmstate_register_ram_global(bios);
     memory_region_set_readonly(bios, true);
     ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
     if (ret != 0) {
@@ -1041,7 +1043,8 @@ void pc_memory_init(MemoryRegion *system_memory,
     memory_region_set_readonly(isa_bios, true);
 
     option_rom_mr = g_malloc(sizeof(*option_rom_mr));
-    memory_region_init_ram(option_rom_mr, NULL, "pc.rom", PC_ROM_SIZE);
+    memory_region_init_ram(option_rom_mr, "pc.rom", PC_ROM_SIZE);
+    vmstate_register_ram_global(option_rom_mr);
     memory_region_add_subregion_overlap(rom_memory,
                                         PC_ROM_MIN_VGA,
                                         option_rom_mr,
diff --git a/hw/pci.c b/hw/pci.c
index 399227f..c3082bc 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1765,7 +1765,8 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
     else
         snprintf(name, sizeof(name), "%s.rom", pdev->qdev.info->name);
     pdev->has_rom = true;
-    memory_region_init_ram(&pdev->rom, &pdev->qdev, name, size);
+    memory_region_init_ram(&pdev->rom, name, size);
+    vmstate_register_ram(&pdev->rom, &pdev->qdev);
     ptr = memory_region_get_ram_ptr(&pdev->rom);
     load_image(path, ptr);
     g_free(path);
@@ -1787,6 +1788,7 @@ static void pci_del_option_rom(PCIDevice *pdev)
     if (!pdev->has_rom)
         return;
 
+    vmstate_unregister_ram(&pdev->rom, &pdev->qdev);
     memory_region_destroy(&pdev->rom);
     pdev->has_rom = false;
 }
diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c
index fb4ba29..98978f8 100644
--- a/hw/petalogix_ml605_mmu.c
+++ b/hw/petalogix_ml605_mmu.c
@@ -162,11 +162,13 @@ petalogix_ml605_init(ram_addr_t ram_size,
     qemu_register_reset(main_cpu_reset, env);
 
     /* Attach emulated BRAM through the LMB.  */
-    memory_region_init_ram(phys_lmb_bram, NULL, "petalogix_ml605.lmb_bram",
+    memory_region_init_ram(phys_lmb_bram, "petalogix_ml605.lmb_bram",
                            LMB_BRAM_SIZE);
+    vmstate_register_ram_global(phys_lmb_bram);
     memory_region_add_subregion(address_space_mem, 0x00000000, phys_lmb_bram);
 
-    memory_region_init_ram(phys_ram, NULL, "petalogix_ml605.ram", ram_size);
+    memory_region_init_ram(phys_ram, "petalogix_ml605.ram", ram_size);
+    vmstate_register_ram_global(phys_ram);
     memory_region_add_subregion(address_space_mem, ddr_base, phys_ram);
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index 17da2fd..d448a41 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -141,12 +141,13 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     qemu_register_reset(main_cpu_reset, env);
 
     /* Attach emulated BRAM through the LMB.  */
-    memory_region_init_ram(phys_lmb_bram, NULL,
+    memory_region_init_ram(phys_lmb_bram,
                            "petalogix_s3adsp1800.lmb_bram", LMB_BRAM_SIZE);
+    vmstate_register_ram_global(phys_lmb_bram);
     memory_region_add_subregion(sysmem, 0x00000000, phys_lmb_bram);
 
-    memory_region_init_ram(phys_ram, NULL, "petalogix_s3adsp1800.ram",
-                           ram_size);
+    memory_region_init_ram(phys_ram, "petalogix_s3adsp1800.ram", ram_size);
+    vmstate_register_ram_global(phys_ram);
     memory_region_add_subregion(sysmem, ddr_base, phys_ram);
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index 69b8e3d..ee0c3ba 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -589,7 +589,8 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base,
 
     memory_region_init_rom_device(
         &pfl->mem, be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl,
-        qdev, name, size);
+        name, size);
+    vmstate_register_ram(&pfl->mem, qdev);
     pfl->storage = memory_region_get_ram_ptr(&pfl->mem);
     memory_region_add_subregion(get_system_memory(), base, &pfl->mem);
 
@@ -599,6 +600,7 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base,
         ret = bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9);
         if (ret < 0) {
             memory_region_del_subregion(get_system_memory(), &pfl->mem);
+            vmstate_unregister_ram(&pfl->mem, qdev);
             memory_region_destroy(&pfl->mem);
             g_free(pfl);
             return NULL;
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c
index e5a63da..a9e88b9 100644
--- a/hw/pflash_cfi02.c
+++ b/hw/pflash_cfi02.c
@@ -628,7 +628,8 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base,
     pfl = g_malloc0(sizeof(pflash_t));
     memory_region_init_rom_device(
         &pfl->orig_mem, be ? &pflash_cfi02_ops_be : &pflash_cfi02_ops_le, pfl,
-        qdev, name, size);
+        name, size);
+    vmstate_register_ram(&pfl->orig_mem, qdev);
     pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem);
     pfl->base = base;
     pfl->chip_len = chip_len;
diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c
index 672e934..476775d 100644
--- a/hw/ppc405_boards.c
+++ b/hw/ppc405_boards.c
@@ -198,7 +198,8 @@ static void ref405ep_init (ram_addr_t ram_size,
     MemoryRegion *sysmem = get_system_memory();
 
     /* XXX: fix this */
-    memory_region_init_ram(&ram_memories[0], NULL, "ef405ep.ram", 0x08000000);
+    memory_region_init_ram(&ram_memories[0], "ef405ep.ram", 0x08000000);
+    vmstate_register_ram_global(&ram_memories[0]);
     ram_bases[0] = 0;
     ram_sizes[0] = 0x08000000;
     memory_region_init(&ram_memories[1], "ef405ep.ram1", 0);
@@ -212,7 +213,8 @@ static void ref405ep_init (ram_addr_t ram_size,
                         33333333, &pic, kernel_filename == NULL ? 0 : 1);
     /* allocate SRAM */
     sram_size = 512 * 1024;
-    memory_region_init_ram(sram, NULL, "ef405ep.sram", sram_size);
+    memory_region_init_ram(sram, "ef405ep.sram", sram_size);
+    vmstate_register_ram_global(sram);
     memory_region_add_subregion(sysmem, 0xFFF00000, sram);
     /* allocate and load BIOS */
 #ifdef DEBUG_BOARD_INIT
@@ -243,7 +245,8 @@ static void ref405ep_init (ram_addr_t ram_size,
         printf("Load BIOS from file\n");
 #endif
         bios = g_new(MemoryRegion, 1);
-        memory_region_init_ram(bios, NULL, "ef405ep.bios", BIOS_SIZE);
+        memory_region_init_ram(bios, "ef405ep.bios", BIOS_SIZE);
+        vmstate_register_ram_global(bios);
         if (bios_name == NULL)
             bios_name = BIOS_FILENAME;
         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
@@ -513,12 +516,14 @@ static void taihu_405ep_init(ram_addr_t ram_size,
     DriveInfo *dinfo;
 
     /* RAM is soldered to the board so the size cannot be changed */
-    memory_region_init_ram(&ram_memories[0], NULL,
+    memory_region_init_ram(&ram_memories[0],
                            "taihu_405ep.ram-0", 0x04000000);
+    vmstate_register_ram_global(&ram_memories[0]);
     ram_bases[0] = 0;
     ram_sizes[0] = 0x04000000;
-    memory_region_init_ram(&ram_memories[1], NULL,
+    memory_region_init_ram(&ram_memories[1],
                            "taihu_405ep.ram-1", 0x04000000);
+    vmstate_register_ram_global(&ram_memories[1]);
     ram_bases[1] = 0x04000000;
     ram_sizes[1] = 0x04000000;
     ram_size = 0x08000000;
@@ -560,7 +565,8 @@ static void taihu_405ep_init(ram_addr_t ram_size,
         if (bios_name == NULL)
             bios_name = BIOS_FILENAME;
         bios = g_new(MemoryRegion, 1);
-        memory_region_init_ram(bios, NULL, "taihu_405ep.bios", BIOS_SIZE);
+        memory_region_init_ram(bios, "taihu_405ep.bios", BIOS_SIZE);
+        vmstate_register_ram_global(bios);
         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
         if (filename) {
             bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index a6e7431..98079fa 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -966,7 +966,8 @@ static void ppc405_ocm_init(CPUState *env)
 
     ocm = g_malloc0(sizeof(ppc405_ocm_t));
     /* XXX: Size is 4096 or 0x04000000 */
-    memory_region_init_ram(&ocm->isarc_ram, NULL, "ppc405.ocm", 4096);
+    memory_region_init_ram(&ocm->isarc_ram, "ppc405.ocm", 4096);
+    vmstate_register_ram_global(&ocm->isarc_ram);
     memory_region_init_alias(&ocm->dsarc_ram, "ppc405.dsarc", &ocm->isarc_ram,
                              0, 4096);
     qemu_register_reset(&ocm_reset, ocm);
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index d18caa4..26040ac 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -686,7 +686,8 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
             if (bank_size <= size_left) {
                 char name[32];
                 snprintf(name, sizeof(name), "ppc4xx.sdram%d", i);
-                memory_region_init_ram(&ram_memories[i], NULL, name, bank_size);
+                memory_region_init_ram(&ram_memories[i], name, bank_size);
+                vmstate_register_ram_global(&ram_memories[i]);
                 ram_bases[i] = base;
                 ram_sizes[i] = bank_size;
                 base += ram_size;
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 8c84f9e..a746c9c 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -171,11 +171,13 @@ static void ppc_core99_init (ram_addr_t ram_size,
     }
 
     /* allocate RAM */
-    memory_region_init_ram(ram, NULL, "ppc_core99.ram", ram_size);
+    memory_region_init_ram(ram, "ppc_core99.ram", ram_size);
+    vmstate_register_ram_global(ram);
     memory_region_add_subregion(get_system_memory(), 0, ram);
 
     /* allocate and load BIOS */
-    memory_region_init_ram(bios, NULL, "ppc_core99.bios", BIOS_SIZE);
+    memory_region_init_ram(bios, "ppc_core99.bios", BIOS_SIZE);
+    vmstate_register_ram_global(bios);
     if (bios_name == NULL)
         bios_name = PROM_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index aac3526..9295a34 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -116,11 +116,13 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
         exit(1);
     }
 
-    memory_region_init_ram(ram, NULL, "ppc_heathrow.ram", ram_size);
+    memory_region_init_ram(ram, "ppc_heathrow.ram", ram_size);
+    vmstate_register_ram_global(ram);
     memory_region_add_subregion(sysmem, 0, ram);
 
     /* allocate and load BIOS */
-    memory_region_init_ram(bios, NULL, "ppc_heathrow.bios", BIOS_SIZE);
+    memory_region_init_ram(bios, "ppc_heathrow.bios", BIOS_SIZE);
+    vmstate_register_ram_global(bios);
     if (bios_name == NULL)
         bios_name = PROM_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index a7d73bf..47dab3f 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -554,11 +554,13 @@ static void ppc_prep_init (ram_addr_t ram_size,
     }
 
     /* allocate RAM */
-    memory_region_init_ram(ram, NULL, "ppc_prep.ram", ram_size);
+    memory_region_init_ram(ram, "ppc_prep.ram", ram_size);
+    vmstate_register_ram_global(ram);
     memory_region_add_subregion(sysmem, 0, ram);
 
     /* allocate and load BIOS */
-    memory_region_init_ram(bios, NULL, "ppc_prep.bios", BIOS_SIZE);
+    memory_region_init_ram(bios, "ppc_prep.bios", BIOS_SIZE);
+    vmstate_register_ram_global(bios);
     if (bios_name == NULL)
         bios_name = BIOS_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 51b6abd..d69f78c 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -292,7 +292,8 @@ static void mpc8544ds_init(ram_addr_t ram_size,
     ram_size &= ~(RAM_SIZES_ALIGN - 1);
 
     /* Register Memory */
-    memory_region_init_ram(ram, NULL, "mpc8544ds.ram", ram_size);
+    memory_region_init_ram(ram, "mpc8544ds.ram", ram_size);
+    vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space_mem, 0, ram);
 
     /* MPIC */
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index bd177b7..6ddd500 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2046,9 +2046,11 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
     s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
 
     /* SDRAM & Internal Memory Storage */
-    memory_region_init_ram(&s->sdram, NULL, "pxa270.sdram", sdram_size);
+    memory_region_init_ram(&s->sdram, "pxa270.sdram", sdram_size);
+    vmstate_register_ram_global(&s->sdram);
     memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram);
-    memory_region_init_ram(&s->internal, NULL, "pxa270.internal", 0x40000);
+    memory_region_init_ram(&s->internal, "pxa270.internal", 0x40000);
+    vmstate_register_ram_global(&s->internal);
     memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
                                 &s->internal);
 
@@ -2175,10 +2177,12 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
     s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
 
     /* SDRAM & Internal Memory Storage */
-    memory_region_init_ram(&s->sdram, NULL, "pxa255.sdram", sdram_size);
+    memory_region_init_ram(&s->sdram, "pxa255.sdram", sdram_size);
+    vmstate_register_ram_global(&s->sdram);
     memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram);
-    memory_region_init_ram(&s->internal, NULL, "pxa255.internal",
+    memory_region_init_ram(&s->internal, "pxa255.internal",
                            PXA2XX_INTERNAL_SIZE);
+    vmstate_register_ram_global(&s->internal);
     memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
                                 &s->internal);
 
diff --git a/hw/qxl.c b/hw/qxl.c
index 41500e9..ac81927 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1554,8 +1554,8 @@ static int qxl_init_common(PCIQXLDevice *qxl)
     pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
 
     qxl->rom_size = qxl_rom_size();
-    memory_region_init_ram(&qxl->rom_bar, &qxl->pci.qdev, "qxl.vrom",
-                           qxl->rom_size);
+    memory_region_init_ram(&qxl->rom_bar, "qxl.vrom", qxl->rom_size);
+    vmstate_register_ram(&qxl->rom_bar, &qxl->pci.qdev);
     init_qxl_rom(qxl);
     init_qxl_ram(qxl);
 
@@ -1566,8 +1566,8 @@ static int qxl_init_common(PCIQXLDevice *qxl)
         qxl->vram_size = 4096;
     }
     qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
-    memory_region_init_ram(&qxl->vram_bar, &qxl->pci.qdev, "qxl.vram",
-                           qxl->vram_size);
+    memory_region_init_ram(&qxl->vram_bar, "qxl.vram", qxl->vram_size);
+    vmstate_register_ram(&qxl->vram_bar, &qxl->pci.qdev);
 
     io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1);
     if (qxl->revision == 1) {
@@ -1643,8 +1643,8 @@ static int qxl_init_secondary(PCIDevice *dev)
         ram_size = 16 * 1024 * 1024;
     }
     qxl->vga.vram_size = ram_size;
-    memory_region_init_ram(&qxl->vga.vram, &qxl->pci.qdev, "qxl.vgavram",
-                           qxl->vga.vram_size);
+    memory_region_init_ram(&qxl->vga.vram, "qxl.vgavram", qxl->vga.vram_size);
+    vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev);
     qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram);
 
     return qxl_init_common(qxl);
diff --git a/hw/r2d.c b/hw/r2d.c
index 6e1f71c..c80f9e3 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -249,7 +249,8 @@ static void r2d_init(ram_addr_t ram_size,
     qemu_register_reset(main_cpu_reset, reset_info);
 
     /* Allocate memory space */
-    memory_region_init_ram(sdram, NULL, "r2d.sdram", SDRAM_SIZE);
+    memory_region_init_ram(sdram, "r2d.sdram", SDRAM_SIZE);
+    vmstate_register_ram_global(sdram);
     memory_region_add_subregion(address_space_mem, SDRAM_BASE, sdram);
     /* Register peripherals */
     s = sh7750_init(env, address_space_mem);
diff --git a/hw/realview.c b/hw/realview.c
index 750a279..d4191e9 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -183,11 +183,13 @@ static void realview_init(ram_addr_t ram_size,
         /* Core tile RAM.  */
         low_ram_size = ram_size - 0x20000000;
         ram_size = 0x20000000;
-        memory_region_init_ram(ram_lo, NULL, "realview.lowmem", low_ram_size);
+        memory_region_init_ram(ram_lo, "realview.lowmem", low_ram_size);
+        vmstate_register_ram_global(ram_lo);
         memory_region_add_subregion(sysmem, 0x20000000, ram_lo);
     }
 
-    memory_region_init_ram(ram_hi, NULL, "realview.highmem", ram_size);
+    memory_region_init_ram(ram_hi, "realview.highmem", ram_size);
+    vmstate_register_ram_global(ram_hi);
     low_ram_size = ram_size;
     if (low_ram_size > 0x10000000)
       low_ram_size = 0x10000000;
@@ -377,7 +379,8 @@ static void realview_init(ram_addr_t ram_size,
        startup code.  I guess this works on real hardware because the
        BootROM happens to be in ROM/flash or in memory that isn't clobbered
        until after Linux boots the secondary CPUs.  */
-    memory_region_init_ram(ram_hack, NULL, "realview.hack", 0x1000);
+    memory_region_init_ram(ram_hack, "realview.hack", 0x1000);
+    vmstate_register_ram_global(ram_hack);
     memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack);
 
     realview_binfo.ram_size = ram_size;
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 61b67e8..2210b8a 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -184,7 +184,8 @@ static void s390_init(ram_addr_t my_ram_size,
     s390_bus = s390_virtio_bus_init(&my_ram_size);
 
     /* allocate RAM */
-    memory_region_init_ram(ram, NULL, "s390.ram", my_ram_size);
+    memory_region_init_ram(ram, "s390.ram", my_ram_size);
+    vmstate_register_ram_global(ram);
     memory_region_add_subregion(sysmem, 0, ram);
 
     /* clear virtio region */
diff --git a/hw/shix.c b/hw/shix.c
index e0c2200..e259c17 100644
--- a/hw/shix.c
+++ b/hw/shix.c
@@ -57,14 +57,17 @@ static void shix_init(ram_addr_t ram_size,
 
     /* Allocate memory space */
     printf("Allocating ROM\n");
-    memory_region_init_ram(rom, NULL, "shix.rom", 0x4000);
+    memory_region_init_ram(rom, "shix.rom", 0x4000);
+    vmstate_register_ram_global(rom);
     memory_region_set_readonly(rom, true);
     memory_region_add_subregion(sysmem, 0x00000000, rom);
     printf("Allocating SDRAM 1\n");
-    memory_region_init_ram(&sdram[0], NULL, "shix.sdram1", 0x01000000);
+    memory_region_init_ram(&sdram[0], "shix.sdram1", 0x01000000);
+    vmstate_register_ram_global(&sdram[0]);
     memory_region_add_subregion(sysmem, 0x08000000, &sdram[0]);
     printf("Allocating SDRAM 2\n");
-    memory_region_init_ram(&sdram[1], NULL, "shix.sdram2", 0x01000000);
+    memory_region_init_ram(&sdram[1], "shix.sdram2", 0x01000000);
+    vmstate_register_ram_global(&sdram[1]);
     memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]);
 
     /* Load BIOS in 0 (and access it through P2, 0xA0000000) */
diff --git a/hw/sm501.c b/hw/sm501.c
index 297bc9c..326531c 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -1405,8 +1405,9 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
     s->dc_crt_control = 0x00010000;
 
     /* allocate local memory */
-    memory_region_init_ram(&s->local_mem_region, NULL, "sm501.local",
+    memory_region_init_ram(&s->local_mem_region, "sm501.local",
                            local_mem_bytes);
+    vmstate_register_ram_global(&s->local_mem_region);
     s->local_mem = memory_region_get_ram_ptr(&s->local_mem_region);
     memory_region_add_subregion(address_space_mem, base, &s->local_mem_region);
 
diff --git a/hw/spapr.c b/hw/spapr.c
index 2b901f1..161b585 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -457,7 +457,8 @@ static void ppc_spapr_init(ram_addr_t ram_size,
         ram_addr_t nonrma_base = rma_alloc_size;
         ram_addr_t nonrma_size = spapr->ram_limit - rma_alloc_size;
 
-        memory_region_init_ram(ram, NULL, "ppc_spapr.ram", nonrma_size);
+        memory_region_init_ram(ram, "ppc_spapr.ram", nonrma_size);
+        vmstate_register_ram_global(ram);
         memory_region_add_subregion(sysmem, nonrma_base, ram);
     }
 
diff --git a/hw/spitz.c b/hw/spitz.c
index df0e146..82a133d 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -894,7 +894,8 @@ static void spitz_common_init(ram_addr_t ram_size,
 
     sl_flash_register(cpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
 
-    memory_region_init_ram(rom, NULL, "spitz.rom", SPITZ_ROM);
+    memory_region_init_ram(rom, "spitz.rom", SPITZ_ROM);
+    vmstate_register_ram_global(rom);
     memory_region_set_readonly(rom, true);
     memory_region_add_subregion(address_space_mem, 0, rom);
 
diff --git a/hw/strongarm.c b/hw/strongarm.c
index 7c75bb9..69c1179 100644
--- a/hw/strongarm.c
+++ b/hw/strongarm.c
@@ -1511,7 +1511,8 @@ StrongARMState *sa1110_init(MemoryRegion *sysmem,
         exit(1);
     }
 
-    memory_region_init_ram(&s->sdram, NULL, "strongarm.sdram", sdram_size);
+    memory_region_init_ram(&s->sdram, "strongarm.sdram", sdram_size);
+    vmstate_register_ram_global(&s->sdram);
     memory_region_add_subregion(sysmem, SA_SDCS0, &s->sdram);
 
     pic = arm_pic_init_cpu(s->env);
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 3f172ad..941cc98 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -602,7 +602,8 @@ static int idreg_init1(SysBusDevice *dev)
 {
     IDRegState *s = FROM_SYSBUS(IDRegState, dev);
 
-    memory_region_init_ram(&s->mem, NULL, "sun4m.idreg", sizeof(idreg_data));
+    memory_region_init_ram(&s->mem, "sun4m.idreg", sizeof(idreg_data));
+    vmstate_register_ram_global(&s->mem);
     memory_region_set_readonly(&s->mem, true);
     sysbus_init_mmio(dev, &s->mem);
     return 0;
@@ -643,7 +644,8 @@ static int afx_init1(SysBusDevice *dev)
 {
     AFXState *s = FROM_SYSBUS(AFXState, dev);
 
-    memory_region_init_ram(&s->mem, NULL, "sun4m.afx", 4);
+    memory_region_init_ram(&s->mem, "sun4m.afx", 4);
+    vmstate_register_ram_global(&s->mem);
     sysbus_init_mmio(dev, &s->mem);
     return 0;
 }
@@ -711,7 +713,8 @@ static int prom_init1(SysBusDevice *dev)
 {
     PROMState *s = FROM_SYSBUS(PROMState, dev);
 
-    memory_region_init_ram(&s->prom, NULL, "sun4m.prom", PROM_SIZE_MAX);
+    memory_region_init_ram(&s->prom, "sun4m.prom", PROM_SIZE_MAX);
+    vmstate_register_ram_global(&s->prom);
     memory_region_set_readonly(&s->prom, true);
     sysbus_init_mmio(dev, &s->prom);
     return 0;
@@ -745,7 +748,8 @@ static int ram_init1(SysBusDevice *dev)
 {
     RamDevice *d = FROM_SYSBUS(RamDevice, dev);
 
-    memory_region_init_ram(&d->ram, NULL, "sun4m.ram", d->size);
+    memory_region_init_ram(&d->ram, "sun4m.ram", d->size);
+    vmstate_register_ram_global(&d->ram);
     sysbus_init_mmio(dev, &d->ram);
     return 0;
 }
diff --git a/hw/sun4u.c b/hw/sun4u.c
index e3e8dde..2dc3d04 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -629,7 +629,8 @@ static int prom_init1(SysBusDevice *dev)
 {
     PROMState *s = FROM_SYSBUS(PROMState, dev);
 
-    memory_region_init_ram(&s->prom, NULL, "sun4u.prom", PROM_SIZE_MAX);
+    memory_region_init_ram(&s->prom, "sun4u.prom", PROM_SIZE_MAX);
+    vmstate_register_ram_global(&s->prom);
     memory_region_set_readonly(&s->prom, true);
     sysbus_init_mmio(dev, &s->prom);
     return 0;
@@ -664,7 +665,8 @@ static int ram_init1(SysBusDevice *dev)
 {
     RamDevice *d = FROM_SYSBUS(RamDevice, dev);
 
-    memory_region_init_ram(&d->ram, NULL, "sun4u.ram", d->size);
+    memory_region_init_ram(&d->ram, "sun4u.ram", d->size);
+    vmstate_register_ram_global(&d->ram);
     sysbus_init_mmio(dev, &d->ram);
     return 0;
 }
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index c144dcf..b75fa60 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -568,7 +568,8 @@ TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq)
     memory_region_init_io(&s->iomem, &tc6393xb_ops, s, "tc6393xb", 0x10000);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
-    memory_region_init_ram(&s->vram, NULL, "tc6393xb.vram", 0x100000);
+    memory_region_init_ram(&s->vram, "tc6393xb.vram", 0x100000);
+    vmstate_register_ram_global(&s->vram);
     s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
     memory_region_add_subregion(sysmem, base + 0x100000, &s->vram);
     s->scr_width = 480;
diff --git a/hw/tcx.c b/hw/tcx.c
index a987357..75a28f2 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -520,8 +520,9 @@ static int tcx_init1(SysBusDevice *dev)
     int size;
     uint8_t *vram_base;
 
-    memory_region_init_ram(&s->vram_mem, NULL, "tcx.vram",
+    memory_region_init_ram(&s->vram_mem, "tcx.vram",
                            s->vram_size * (1 + 4 + 4));
+    vmstate_register_ram_global(&s->vram_mem);
     vram_base = memory_region_get_ram_ptr(&s->vram_mem);
 
     /* 8-bit plane */
diff --git a/hw/tosa.c b/hw/tosa.c
index 67a71fe..6bbc6dc 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -218,7 +218,8 @@ static void tosa_init(ram_addr_t ram_size,
 
     cpu = pxa255_init(address_space_mem, tosa_binfo.ram_size);
 
-    memory_region_init_ram(rom, NULL, "tosa.rom", TOSA_ROM);
+    memory_region_init_ram(rom, "tosa.rom", TOSA_ROM);
+    vmstate_register_ram_global(rom);
     memory_region_set_readonly(rom, true);
     memory_region_add_subregion(address_space_mem, 0, rom);
 
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index a6315fc..0312b75 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -190,7 +190,8 @@ static void versatile_init(ram_addr_t ram_size,
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    memory_region_init_ram(ram, NULL, "versatile.ram", ram_size);
+    memory_region_init_ram(ram, "versatile.ram", ram_size);
+    vmstate_register_ram_global(ram);
     /* ??? RAM should repeat to fill physical memory space.  */
     /* SDRAM at address zero.  */
     memory_region_add_subregion(sysmem, 0, ram);
diff --git a/hw/vexpress.c b/hw/vexpress.c
index 08c93d5..c9ca43c 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -77,7 +77,8 @@ static void vexpress_a9_init(ram_addr_t ram_size,
         exit(1);
     }
 
-    memory_region_init_ram(ram, NULL, "vexpress.highmem", ram_size);
+    memory_region_init_ram(ram, "vexpress.highmem", ram_size);
+    vmstate_register_ram_global(ram);
     low_ram_size = ram_size;
     if (low_ram_size > 0x4000000) {
         low_ram_size = 0x4000000;
@@ -181,14 +182,16 @@ static void vexpress_a9_init(ram_addr_t ram_size,
     /* CS4: NOR1 flash          : 0x44000000 .. 0x48000000 */
     /* CS2: SRAM                : 0x48000000 .. 0x4a000000 */
     sram_size = 0x2000000;
-    memory_region_init_ram(sram, NULL, "vexpress.sram", sram_size);
+    memory_region_init_ram(sram, "vexpress.sram", sram_size);
+    vmstate_register_ram_global(sram);
     memory_region_add_subregion(sysmem, 0x48000000, sram);
 
     /* CS3: USB, ethernet, VRAM : 0x4c000000 .. 0x50000000 */
 
     /* 0x4c000000 Video RAM */
     vram_size = 0x800000;
-    memory_region_init_ram(vram, NULL, "vexpress.vram", vram_size);
+    memory_region_init_ram(vram, "vexpress.vram", vram_size);
+    vmstate_register_ram_global(vram);
     memory_region_add_subregion(sysmem, 0x4c000000, vram);
 
     /* 0x4e000000 LAN9118 Ethernet */
@@ -202,7 +205,8 @@ static void vexpress_a9_init(ram_addr_t ram_size,
        startup code.  I guess this works on real hardware because the
        BootROM happens to be in ROM/flash or in memory that isn't clobbered
        until after Linux boots the secondary CPUs.  */
-    memory_region_init_ram(hackram, NULL, "vexpress.hack", 0x1000);
+    memory_region_init_ram(hackram, "vexpress.hack", 0x1000);
+    vmstate_register_ram_global(hackram);
     memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, hackram);
 
     vexpress_binfo.ram_size = ram_size;
diff --git a/hw/vga.c b/hw/vga.c
index 7e1dd5a..4878fbc 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2222,7 +2222,8 @@ void vga_common_init(VGACommonState *s, int vga_ram_size)
 #else
     s->is_vbe_vmstate = 0;
 #endif
-    memory_region_init_ram(&s->vram, NULL, "vga.vram", vga_ram_size);
+    memory_region_init_ram(&s->vram, "vga.vram", vga_ram_size);
+    vmstate_register_ram_global(&s->vram);
     xen_register_framebuffer(&s->vram);
     s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
     s->vram_size = vga_ram_size;
diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
index 6ffb896..bd16b97 100644
--- a/hw/virtex_ml507.c
+++ b/hw/virtex_ml507.c
@@ -205,7 +205,8 @@ static void virtex_init(ram_addr_t ram_size,
     env = ppc440_init_xilinx(&ram_size, 1, cpu_model, 400000000);
     qemu_register_reset(main_cpu_reset, env);
 
-    memory_region_init_ram(phys_ram, NULL, "ram", ram_size);
+    memory_region_init_ram(phys_ram, "ram", ram_size);
+    vmstate_register_ram_global(phys_ram);
     memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index af70bde..b1885c3 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1091,7 +1091,8 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size,
 
 
     s->fifo_size = SVGA_FIFO_SIZE;
-    memory_region_init_ram(&s->fifo_ram, NULL, "vmsvga.fifo", s->fifo_size);
+    memory_region_init_ram(&s->fifo_ram, "vmsvga.fifo", s->fifo_size);
+    vmstate_register_ram_global(&s->fifo_ram);
     s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram);
 
     vga_common_init(&s->vga, vga_ram_size);
diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c
index 8947157..26112c3 100644
--- a/hw/xtensa_lx60.c
+++ b/hw/xtensa_lx60.c
@@ -136,7 +136,8 @@ static void lx60_net_init(MemoryRegion *address_space,
             sysbus_mmio_get_region(s, 1));
 
     ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, NULL, "open_eth.ram", 16384);
+    memory_region_init_ram(ram, "open_eth.ram", 16384);
+    vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space, buffers, ram);
 }
 
@@ -186,7 +187,8 @@ static void lx_init(const LxBoardDesc *board,
     }
 
     ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, NULL, "lx60.dram", ram_size);
+    memory_region_init_ram(ram, "lx60.dram", ram_size);
+    vmstate_register_ram_global(ram);
     memory_region_add_subregion(system_memory, 0, ram);
 
     system_io = g_malloc(sizeof(*system_io));
@@ -221,7 +223,8 @@ static void lx_init(const LxBoardDesc *board,
     /* Use presence of kernel file name as 'boot from SRAM' switch. */
     if (kernel_filename) {
         rom = g_malloc(sizeof(*rom));
-        memory_region_init_ram(rom, NULL, "lx60.sram", board->sram_size);
+        memory_region_init_ram(rom, "lx60.sram", board->sram_size);
+        vmstate_register_ram_global(rom);
         memory_region_add_subregion(system_memory, 0xfe000000, rom);
 
         /* Put kernel bootparameters to the end of that SRAM */
diff --git a/hw/xtensa_sim.c b/hw/xtensa_sim.c
index a94e4e5..104e5dc 100644
--- a/hw/xtensa_sim.c
+++ b/hw/xtensa_sim.c
@@ -66,11 +66,13 @@ static void sim_init(ram_addr_t ram_size,
     }
 
     ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, NULL, "xtensa.sram", ram_size);
+    memory_region_init_ram(ram, "xtensa.sram", ram_size);
+    vmstate_register_ram_global(ram);
     memory_region_add_subregion(get_system_memory(), 0, ram);
 
     rom = g_malloc(sizeof(*rom));
-    memory_region_init_ram(rom, NULL, "xtensa.rom", 0x1000);
+    memory_region_init_ram(rom, "xtensa.rom", 0x1000);
+    vmstate_register_ram_global(rom);
     memory_region_add_subregion(get_system_memory(), 0xfe000000, rom);
 
     if (kernel_filename) {
diff --git a/memory.c b/memory.c
index 93f9569..f7b3d50 100644
--- a/memory.c
+++ b/memory.c
@@ -1033,7 +1033,6 @@ void memory_region_init_io(MemoryRegion *mr,
 }
 
 void memory_region_init_ram(MemoryRegion *mr,
-                            DeviceState *dev,
                             const char *name,
                             uint64_t size)
 {
@@ -1041,12 +1040,11 @@ void memory_region_init_ram(MemoryRegion *mr,
     mr->ram = true;
     mr->terminates = true;
     mr->destructor = memory_region_destructor_ram;
-    mr->ram_addr = qemu_ram_alloc(dev, name, size, mr);
+    mr->ram_addr = qemu_ram_alloc(size, mr);
     mr->backend_registered = true;
 }
 
 void memory_region_init_ram_ptr(MemoryRegion *mr,
-                                DeviceState *dev,
                                 const char *name,
                                 uint64_t size,
                                 void *ptr)
@@ -1055,7 +1053,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr,
     mr->ram = true;
     mr->terminates = true;
     mr->destructor = memory_region_destructor_ram_from_ptr;
-    mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr, mr);
+    mr->ram_addr = qemu_ram_alloc_from_ptr(size, ptr, mr);
     mr->backend_registered = true;
 }
 
@@ -1073,7 +1071,6 @@ void memory_region_init_alias(MemoryRegion *mr,
 void memory_region_init_rom_device(MemoryRegion *mr,
                                    const MemoryRegionOps *ops,
                                    void *opaque,
-                                   DeviceState *dev,
                                    const char *name,
                                    uint64_t size)
 {
@@ -1082,7 +1079,7 @@ void memory_region_init_rom_device(MemoryRegion *mr,
     mr->opaque = opaque;
     mr->terminates = true;
     mr->destructor = memory_region_destructor_rom_device;
-    mr->ram_addr = qemu_ram_alloc(dev, name, size, mr);
+    mr->ram_addr = qemu_ram_alloc(size, mr);
     mr->ram_addr |= cpu_register_io_memory(memory_region_read_thunk,
                                            memory_region_write_thunk,
                                            mr,
diff --git a/memory.h b/memory.h
index 55e7830..8041e90 100644
--- a/memory.h
+++ b/memory.h
@@ -224,14 +224,10 @@ void memory_region_init_io(MemoryRegion *mr,
  *                          region will modify memory directly.
  *
  * @mr: the #MemoryRegion to be initialized.
- * @dev: a device associated with the region; may be %NULL.
- * @name: the name of the region; the pair (@dev, @name) must be globally
- *        unique.  The name is part of the save/restore ABI and so cannot be
- *        changed.
+ * @name: the name of the region.
  * @size: size of the region.
  */
 void memory_region_init_ram(MemoryRegion *mr,
-                            DeviceState *dev, /* FIXME: layering violation */
                             const char *name,
                             uint64_t size);
 
@@ -241,15 +237,11 @@ void memory_region_init_ram(MemoryRegion *mr,
  *                          memory directly.
  *
  * @mr: the #MemoryRegion to be initialized.
- * @dev: a device associated with the region; may be %NULL.
- * @name: the name of the region; the pair (@dev, @name) must be globally
- *        unique.  The name is part of the save/restore ABI and so cannot be
- *        changed.
+ * @name: the name of the region.
  * @size: size of the region.
  * @ptr: memory to be mapped; must contain at least @size bytes.
  */
 void memory_region_init_ram_ptr(MemoryRegion *mr,
-                                DeviceState *dev, /* FIXME: layering violation */
                                 const char *name,
                                 uint64_t size,
                                 void *ptr);
@@ -277,16 +269,12 @@ void memory_region_init_alias(MemoryRegion *mr,
  *
  * @mr: the #MemoryRegion to be initialized.
  * @ops: callbacks for write access handling.
- * @dev: a device associated with the region; may be %NULL.
- * @name: the name of the region; the pair (@dev, @name) must be globally
- *        unique.  The name is part of the save/restore ABI and so cannot be
- *        changed.
+ * @name: the name of the region.
  * @size: size of the region.
  */
 void memory_region_init_rom_device(MemoryRegion *mr,
                                    const MemoryRegionOps *ops,
                                    void *opaque,
-                                   DeviceState *dev, /* FIXME: layering violation */
                                    const char *name,
                                    uint64_t size);
 
diff --git a/savevm.c b/savevm.c
index f153c25..88c4bd8 100644
--- a/savevm.c
+++ b/savevm.c
@@ -83,6 +83,7 @@
 #include "qemu-queue.h"
 #include "qemu-timer.h"
 #include "cpus.h"
+#include "memory.h"
 
 #define SELF_ANNOUNCE_ROUNDS 5
 
@@ -2280,3 +2281,19 @@ void do_info_snapshots(Monitor *mon)
     g_free(available_snapshots);
 
 }
+
+void vmstate_register_ram(MemoryRegion *mr, DeviceState *dev)
+{
+    qemu_ram_set_idstr(memory_region_get_ram_addr(mr),
+                       memory_region_name(mr), dev);
+}
+
+void vmstate_unregister_ram(MemoryRegion *mr, DeviceState *dev)
+{
+    /* Nothing do to while the implementation is in RAMBlock */
+}
+
+void vmstate_register_ram_global(MemoryRegion *mr)
+{
+    vmstate_register_ram(mr, NULL);
+}
diff --git a/xen-all.c b/xen-all.c
index dc23265..1b8248f 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -154,7 +154,8 @@ static void xen_ram_init(ram_addr_t ram_size)
          */
         block_len += HVM_BELOW_4G_MMIO_LENGTH;
     }
-    memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len);
+    memory_region_init_ram(&ram_memory, "xen.ram", block_len);
+    vmstate_register_ram_global(&ram_memory);
 
     if (ram_size >= HVM_BELOW_4G_RAM_END) {
         above_4g_mem_size = ram_size - HVM_BELOW_4G_RAM_END;
commit 8991c79b57b75fcdeb290df89b9b0adaccb0303c
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Dec 20 15:53:11 2011 +0200

    memory: introduce memory_region_name()
    
    Trivial accessor for the name attribute.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/memory.c b/memory.c
index a90eefd..93f9569 100644
--- a/memory.c
+++ b/memory.c
@@ -1108,6 +1108,11 @@ uint64_t memory_region_size(MemoryRegion *mr)
     return int128_get64(mr->size);
 }
 
+const char *memory_region_name(MemoryRegion *mr)
+{
+    return mr->name;
+}
+
 bool memory_region_is_ram(MemoryRegion *mr)
 {
     return mr->ram;
diff --git a/memory.h b/memory.h
index a82226a..55e7830 100644
--- a/memory.h
+++ b/memory.h
@@ -316,6 +316,15 @@ uint64_t memory_region_size(MemoryRegion *mr);
 bool memory_region_is_ram(MemoryRegion *mr);
 
 /**
+ * memory_region_name: get a memory region's name
+ *
+ * Returns the string that was used to initialize the memory region.
+ *
+ * @mr: the memory region being queried
+ */
+const char *memory_region_name(MemoryRegion *mr);
+
+/**
  * memory_region_is_logging: return whether a memory region is logging writes
  *
  * Returns %true if the memory region is logging writes
commit 7279a85f37a9cf20b15c86159f0a1f01ce9cead4
Author: Cao,Bing Bu <mars at linux.vnet.ibm.com>
Date:   Tue Dec 13 09:22:20 2011 +0800

    Fix parse of usb device description with multiple configurations
    
    Changed From V1:
    Use DPRINTF instead of fprintf,because it is not an error.
    
    When testing ipod on QEMU by He Jie Xu<xuhj at linux.vnet.ibm.com>,qemu made a assertion.
    We found that the ipod with 2 configurations,and the usb-linux did not parse the descriptor correctly.
    The descr_len returned is the total length of the all configurations,not one configuration.
    The older version will through the other configurations instead of skip,continue parsing the descriptor of interfaces/endpoints in other configurations,then went wrong.
    
    This patch will put the configuration descriptor parse in loop outside and dispel the other configurations not requested.
    
    Signed-off-by: Cao,Bing Bu <mars at linux.vnet.ibm.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/usb-linux.c b/usb-linux.c
index ab4c693..ed14bb1 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -1141,15 +1141,18 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
     length = s->descr_len - 18;
     i = 0;
 
-    if (descriptors[i + 1] != USB_DT_CONFIG ||
-        descriptors[i + 5] != s->configuration) {
-        fprintf(stderr, "invalid descriptor data - configuration %d\n",
-                s->configuration);
-        return 1;
-    }
-    i += descriptors[i];
-
     while (i < length) {
+        if (descriptors[i + 1] != USB_DT_CONFIG) {
+            fprintf(stderr, "invalid descriptor data\n");
+            return 1;
+        } else if (descriptors[i + 5] != s->configuration) {
+            DPRINTF("not requested configuration %d\n", s->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)) {
commit 8717d88ac7f70d5977e3f9b7dc4376f04faaa8b9
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Tue Dec 20 08:11:32 2011 +0000

    hw/omap1.c: Separate PWL from omap_mpu_state
    
    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/omap.h b/hw/omap.h
index 5fe33db..851ad46 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -829,7 +829,6 @@ struct omap_mpu_state_s {
     MemoryRegion tcmi_iomem;
     MemoryRegion clkm_iomem;
     MemoryRegion clkdsp_iomem;
-    MemoryRegion pwl_iomem;
     MemoryRegion pwt_iomem;
     MemoryRegion mpui_io_iomem;
     MemoryRegion tap_iomem;
@@ -867,12 +866,7 @@ struct omap_mpu_state_s {
 
     struct omap_uwire_s *microwire;
 
-    struct {
-        uint8_t output;
-        uint8_t level;
-        uint8_t enable;
-        int clk;
-    } pwl;
+    struct omap_pwl_s *pwl;
 
     struct {
         uint8_t frc;
diff --git a/hw/omap1.c b/hw/omap1.c
index dddac92..ccc6ecf 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -2289,12 +2289,20 @@ void omap_uwire_attach(struct omap_uwire_s *s,
 }
 
 /* Pseudonoise Pulse-Width Light Modulator */
-static void omap_pwl_update(struct omap_mpu_state_s *s)
+struct omap_pwl_s {
+    MemoryRegion iomem;
+    uint8_t output;
+    uint8_t level;
+    uint8_t enable;
+    int clk;
+};
+
+static void omap_pwl_update(struct omap_pwl_s *s)
 {
-    int output = (s->pwl.clk && s->pwl.enable) ? s->pwl.level : 0;
+    int output = (s->clk && s->enable) ? s->level : 0;
 
-    if (output != s->pwl.output) {
-        s->pwl.output = output;
+    if (output != s->output) {
+        s->output = output;
         printf("%s: Backlight now at %i/256\n", __FUNCTION__, output);
     }
 }
@@ -2302,7 +2310,7 @@ static void omap_pwl_update(struct omap_mpu_state_s *s)
 static uint64_t omap_pwl_read(void *opaque, target_phys_addr_t addr,
                               unsigned size)
 {
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
     int offset = addr & OMAP_MPUI_REG_MASK;
 
     if (size != 1) {
@@ -2311,9 +2319,9 @@ static uint64_t omap_pwl_read(void *opaque, target_phys_addr_t addr,
 
     switch (offset) {
     case 0x00:	/* PWL_LEVEL */
-        return s->pwl.level;
+        return s->level;
     case 0x04:	/* PWL_CTRL */
-        return s->pwl.enable;
+        return s->enable;
     }
     OMAP_BAD_REG(addr);
     return 0;
@@ -2322,7 +2330,7 @@ static uint64_t omap_pwl_read(void *opaque, target_phys_addr_t addr,
 static void omap_pwl_write(void *opaque, target_phys_addr_t addr,
                            uint64_t value, unsigned size)
 {
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
     int offset = addr & OMAP_MPUI_REG_MASK;
 
     if (size != 1) {
@@ -2331,11 +2339,11 @@ static void omap_pwl_write(void *opaque, target_phys_addr_t addr,
 
     switch (offset) {
     case 0x00:	/* PWL_LEVEL */
-        s->pwl.level = value;
+        s->level = value;
         omap_pwl_update(s);
         break;
     case 0x04:	/* PWL_CTRL */
-        s->pwl.enable = value & 1;
+        s->enable = value & 1;
         omap_pwl_update(s);
         break;
     default:
@@ -2350,34 +2358,37 @@ static const MemoryRegionOps omap_pwl_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void omap_pwl_reset(struct omap_mpu_state_s *s)
+static void omap_pwl_reset(struct omap_pwl_s *s)
 {
-    s->pwl.output = 0;
-    s->pwl.level = 0;
-    s->pwl.enable = 0;
-    s->pwl.clk = 1;
+    s->output = 0;
+    s->level = 0;
+    s->enable = 0;
+    s->clk = 1;
     omap_pwl_update(s);
 }
 
 static void omap_pwl_clk_update(void *opaque, int line, int on)
 {
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
 
-    s->pwl.clk = on;
+    s->clk = on;
     omap_pwl_update(s);
 }
 
-static void omap_pwl_init(MemoryRegion *system_memory,
-                target_phys_addr_t base, struct omap_mpu_state_s *s,
-                omap_clk clk)
+static struct omap_pwl_s *omap_pwl_init(MemoryRegion *system_memory,
+                                        target_phys_addr_t base,
+                                        omap_clk clk)
 {
+    struct omap_pwl_s *s = g_malloc0(sizeof(*s));
+
     omap_pwl_reset(s);
 
-    memory_region_init_io(&s->pwl_iomem, &omap_pwl_ops, s,
+    memory_region_init_io(&s->iomem, &omap_pwl_ops, s,
                           "omap-pwl", 0x800);
-    memory_region_add_subregion(system_memory, base, &s->pwl_iomem);
+    memory_region_add_subregion(system_memory, base, &s->iomem);
 
     omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]);
+    return s;
 }
 
 /* Pulse-Width Tone module */
@@ -3667,7 +3678,7 @@ static void omap1_mpu_reset(void *opaque)
     omap_mmc_reset(mpu->mmc);
     omap_mpuio_reset(mpu->mpuio);
     omap_uwire_reset(mpu->microwire);
-    omap_pwl_reset(mpu);
+    omap_pwl_reset(mpu->pwl);
     omap_pwt_reset(mpu);
     omap_i2c_reset(mpu->i2c[0]);
     omap_rtc_reset(mpu->rtc);
@@ -3961,7 +3972,8 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
                                    qdev_get_gpio_in(s->ih[1], OMAP_INT_uWireRX),
                     s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
 
-    omap_pwl_init(system_memory, 0xfffb5800, s, omap_findclk(s, "armxor_ck"));
+    s->pwl = omap_pwl_init(system_memory, 0xfffb5800,
+                           omap_findclk(s, "armxor_ck"));
     omap_pwt_init(system_memory, 0xfffb6000, s, omap_findclk(s, "armxor_ck"));
 
     s->i2c[0] = omap_i2c_init(system_memory, 0xfffb3800,
commit 3b204c8129bc6a6843cb9ff555132babf134286c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Dec 20 08:11:31 2011 +0000

    hw/omap1.c: omap_mpuio_init() need not be public
    
    omap_mpuio_init() is only used and defined in omap1.c, so make it static.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/omap.h b/hw/omap.h
index 42eb361..5fe33db 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -672,10 +672,6 @@ void omap_uart_reset(struct omap_uart_s *s);
 void omap_uart_attach(struct omap_uart_s *s, CharDriverState *chr);
 
 struct omap_mpuio_s;
-struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *system_memory,
-                target_phys_addr_t base,
-                qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup,
-                omap_clk clk);
 qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s);
 void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler);
 void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down);
diff --git a/hw/omap1.c b/hw/omap1.c
index 53cde76..dddac92 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -2066,7 +2066,7 @@ static void omap_mpuio_onoff(void *opaque, int line, int on)
         omap_mpuio_kbd_update(s);
 }
 
-struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *memory,
+static struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *memory,
                 target_phys_addr_t base,
                 qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup,
                 omap_clk clk)
commit 128939a954194e37bbe67d1b94abcba599d30d10
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Dec 19 12:01:58 2011 +0000

    hw/pl110.c: Add post-load hook to invalidate display
    
    Add a post-load hook which invalidates the display. In particular, if we
    don't do this and the display size we've just reloaded is larger than
    the default then we will segfault trying to read off the end of the buffer.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/pl110.c b/hw/pl110.c
index 303a9bc..0e1f415 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -60,10 +60,13 @@ typedef struct {
     qemu_irq irq;
 } pl110_state;
 
+static int vmstate_pl110_post_load(void *opaque, int version_id);
+
 static const VMStateDescription vmstate_pl110 = {
     .name = "pl110",
     .version_id = 2,
     .minimum_version_id = 1,
+    .post_load = vmstate_pl110_post_load,
     .fields = (VMStateField[]) {
         VMSTATE_INT32(version, pl110_state),
         VMSTATE_UINT32_ARRAY(timing, pl110_state, 4),
@@ -430,6 +433,14 @@ static void pl110_mux_ctrl_set(void *opaque, int line, int level)
     s->mux_ctrl = level;
 }
 
+static int vmstate_pl110_post_load(void *opaque, int version_id)
+{
+    pl110_state *s = opaque;
+    /* Make sure we redraw, and at the right size */
+    pl110_invalidate_display(s);
+    return 0;
+}
+
 static int pl110_init(SysBusDevice *dev)
 {
     pl110_state *s = FROM_SYSBUS(pl110_state, dev);
commit 624923be11846c3056639986993e0177f931dd44
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Dec 19 12:01:44 2011 +0000

    hw/pl181.c: Add save/load support
    
    Add save/load support to the PL181.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/pl181.c b/hw/pl181.c
index d05bc19..b79aa41 100644
--- a/hw/pl181.c
+++ b/hw/pl181.c
@@ -38,20 +38,45 @@ typedef struct {
     uint32_t datacnt;
     uint32_t status;
     uint32_t mask[2];
-    int fifo_pos;
-    int fifo_len;
+    int32_t fifo_pos;
+    int32_t fifo_len;
     /* The linux 2.6.21 driver is buggy, and misbehaves if new data arrives
        while it is reading the FIFO.  We hack around this be defering
        subsequent transfers until after the driver polls the status word.
        http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=4446/1
      */
-    int linux_hack;
+    int32_t linux_hack;
     uint32_t fifo[PL181_FIFO_LEN];
     qemu_irq irq[2];
     /* GPIO outputs for 'card is readonly' and 'card inserted' */
     qemu_irq cardstatus[2];
 } pl181_state;
 
+static const VMStateDescription vmstate_pl181 = {
+    .name = "pl181",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(clock, pl181_state),
+        VMSTATE_UINT32(power, pl181_state),
+        VMSTATE_UINT32(cmdarg, pl181_state),
+        VMSTATE_UINT32(cmd, pl181_state),
+        VMSTATE_UINT32(datatimer, pl181_state),
+        VMSTATE_UINT32(datalength, pl181_state),
+        VMSTATE_UINT32(respcmd, pl181_state),
+        VMSTATE_UINT32_ARRAY(response, pl181_state, 4),
+        VMSTATE_UINT32(datactrl, pl181_state),
+        VMSTATE_UINT32(datacnt, pl181_state),
+        VMSTATE_UINT32(status, pl181_state),
+        VMSTATE_UINT32_ARRAY(mask, pl181_state, 2),
+        VMSTATE_INT32(fifo_pos, pl181_state),
+        VMSTATE_INT32(fifo_len, pl181_state),
+        VMSTATE_INT32(linux_hack, pl181_state),
+        VMSTATE_UINT32_ARRAY(fifo, pl181_state, PL181_FIFO_LEN),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 #define PL181_CMD_INDEX     0x3f
 #define PL181_CMD_RESPONSE  (1 << 6)
 #define PL181_CMD_LONGRESP  (1 << 7)
@@ -420,9 +445,9 @@ static const MemoryRegionOps pl181_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void pl181_reset(void *opaque)
+static void pl181_reset(DeviceState *d)
 {
-    pl181_state *s = (pl181_state *)opaque;
+    pl181_state *s = DO_UPCAST(pl181_state, busdev.qdev, d);
 
     s->power = 0;
     s->cmdarg = 0;
@@ -459,15 +484,21 @@ static int pl181_init(SysBusDevice *dev)
     qdev_init_gpio_out(&s->busdev.qdev, s->cardstatus, 2);
     dinfo = drive_get_next(IF_SD);
     s->card = sd_init(dinfo ? dinfo->bdrv : NULL, 0);
-    qemu_register_reset(pl181_reset, s);
-    pl181_reset(s);
-    /* ??? Save/restore.  */
     return 0;
 }
 
+static SysBusDeviceInfo pl181_info = {
+    .init = pl181_init,
+    .qdev.name = "pl181",
+    .qdev.size = sizeof(pl181_state),
+    .qdev.vmsd = &vmstate_pl181,
+    .qdev.reset = pl181_reset,
+    .qdev.no_user = 1,
+};
+
 static void pl181_register_devices(void)
 {
-    sysbus_register_dev("pl181", sizeof(pl181_state), pl181_init);
+    sysbus_register_withprop(&pl181_info);
 }
 
 device_init(pl181_register_devices)
commit 93116ac0cf9734e7b28886aedf03848b37d6785e
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Sun Nov 20 23:12:03 2011 +0000

    s390: fix cpu hotplug / cpu activity on interrupts
    
    The add_del/running_cpu code and env->halted are tracking stopped cpus.
    Sleeping cpus (idle and enabled for interrupts) are waiting inside the
    kernel.
    No interrupt besides the restart can move a cpu from stopped to
    operational. This is already handled over there. So lets just remove
    the bogus wakup from the common interrupt delivery, otherwise any
    interrupt will wake up a cpu, even if this cpu is stopped (Thus leading
    to strange hangs on sigp restart)
    
    This fixes
    echo 0 > /sys/devices/system/cpu/cpu0/online
    echo 1 > /sys/devices/system/cpu/cpu0/online
    in the guest
    
    Signed-off-by: Christian Borntraeger<borntraeger at de.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 40b0ab1..b1404bf 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -185,9 +185,6 @@ void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
         return;
     }
 
-    s390_add_running_cpu(env);
-    qemu_cpu_kick(env);
-
     kvmint.type = type;
     kvmint.parm = parm;
     kvmint.parm64 = parm64;
commit 7d77793d6bf5ecb784040aef946ff7b4d52f2d2a
Author: Alexander Graf <agraf at suse.de>
Date:   Fri Nov 18 16:45:54 2011 +0100

    s390x: add TR function for EXECUTE
    
    Newer gcc versions (or glibc?) also generate code that tries to EXECUTE
    the TR opcode. Implement it so that we don't break valid guests.
    
    Reported-by: Andreas Faerber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index b8a1a8a..cf26b29 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -636,6 +636,9 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
         case 0x700:
             cc = helper_xc(l, get_address(0, b1, d1), get_address(0, b2, d2));
             break;
+        case 0xc00:
+            helper_tr(l, get_address(0, b1, d1), get_address(0, b2, d2));
+            break;
         default:
             goto abort;
             break;
commit 971ca4d906958fc09c8c69edde6f3caa4a843766
Author: Alexander Graf <agraf at suse.de>
Date:   Wed Jul 13 14:08:32 2011 +0200

    Expose drive_add on all architectures
    
    All architectures can now use drive_add on the monitor. This of course
    does not mean that there is hotplug support for the specific platform,
    so in order to actually make use of the new drives you still need to
    have a hotplug capable device.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 14838b7..a586498 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -846,7 +846,6 @@ STEXI
 Snapshot device, using snapshot file as target if provided
 ETEXI
 
-#if defined(TARGET_I386)
     {
         .name       = "drive_add",
         .args_type  = "pci_addr:s,opts:s",
@@ -859,7 +858,6 @@ ETEXI
         .help       = "add drive to PCI storage controller",
         .mhandler.cmd = drive_hot_add,
     },
-#endif
 
 STEXI
 @item drive_add
commit dd97aa8adc9a15fa509d5a0196002d309f6d21fd
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Aug 23 23:43:10 2010 +0200

    Add generic drive hotplugging
    
    The monitor command for hotplugging is in i386 specific code. This is just
    plain wrong, as S390 just learned how to do hotplugging too and needs to
    get drives for that.
    
    So let's add a generic copy to generic code that handles drive_add in a
    way that doesn't have pci dependencies. All pci specific code can then
    be handled in a pci specific function.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    
    ---
    
    v1 -> v2:
    
      - align generic drive_add to pci specific one
      - rework to split between generic and pci code
    
    v2 -> v3:
    
      - remove comment

diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
index 8b2ed7a..2bdc615 100644
--- a/hw/device-hotplug.c
+++ b/hw/device-hotplug.c
@@ -26,6 +26,9 @@
 #include "boards.h"
 #include "net.h"
 #include "blockdev.h"
+#include "qemu-config.h"
+#include "sysemu.h"
+#include "monitor.h"
 
 DriveInfo *add_init_drive(const char *optstr)
 {
@@ -44,3 +47,47 @@ DriveInfo *add_init_drive(const char *optstr)
 
     return dinfo;
 }
+
+#if !defined(TARGET_I386)
+int pci_drive_hot_add(Monitor *mon, const QDict *qdict,
+                      DriveInfo *dinfo, int type)
+{
+    /* On non-x86 we don't do PCI hotplug */
+    monitor_printf(mon, "Can't hot-add drive to type %d\n", type);
+    return -1;
+}
+#endif
+
+void drive_hot_add(Monitor *mon, const QDict *qdict)
+{
+    int type;
+    DriveInfo *dinfo = NULL;
+    const char *opts = qdict_get_str(qdict, "opts");
+
+    dinfo = add_init_drive(opts);
+    if (!dinfo) {
+        goto err;
+    }
+    if (dinfo->devaddr) {
+        monitor_printf(mon, "Parameter addr not supported\n");
+        goto err;
+    }
+    type = dinfo->type;
+
+    switch (type) {
+    case IF_NONE:
+        monitor_printf(mon, "OK\n");
+        break;
+    default:
+        if (pci_drive_hot_add(mon, qdict, dinfo, type)) {
+            goto err;
+        }
+    }
+    return;
+
+err:
+    if (dinfo) {
+        drive_put_ref(dinfo);
+    }
+    return;
+}
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 12f61fe..5c6307f 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -104,24 +104,13 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
     return 0;
 }
 
-void drive_hot_add(Monitor *mon, const QDict *qdict)
+int pci_drive_hot_add(Monitor *mon, const QDict *qdict,
+                      DriveInfo *dinfo, int type)
 {
     int dom, pci_bus;
     unsigned slot;
-    int type;
     PCIDevice *dev;
-    DriveInfo *dinfo = NULL;
     const char *pci_addr = qdict_get_str(qdict, "pci_addr");
-    const char *opts = qdict_get_str(qdict, "opts");
-
-    dinfo = add_init_drive(opts);
-    if (!dinfo)
-        goto err;
-    if (dinfo->devaddr) {
-        monitor_printf(mon, "Parameter addr not supported\n");
-        goto err;
-    }
-    type = dinfo->type;
 
     switch (type) {
     case IF_SCSI:
@@ -138,19 +127,14 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
             goto err;
         }
         break;
-    case IF_NONE:
-        monitor_printf(mon, "OK\n");
-        break;
     default:
         monitor_printf(mon, "Can't hot-add drive to type %d\n", type);
         goto err;
     }
-    return;
 
+    return 0;
 err:
-    if (dinfo)
-        drive_put_ref(dinfo);
-    return;
+    return -1;
 }
 
 static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
diff --git a/sysemu.h b/sysemu.h
index 3806901..ddef2bb 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -143,9 +143,13 @@ extern unsigned int nb_prom_envs;
 
 /* pci-hotplug */
 void pci_device_hot_add(Monitor *mon, const QDict *qdict);
-void drive_hot_add(Monitor *mon, const QDict *qdict);
+int pci_drive_hot_add(Monitor *mon, const QDict *qdict,
+                      DriveInfo *dinfo, int type);
 void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict);
 
+/* generic hotplug */
+void drive_hot_add(Monitor *mon, const QDict *qdict);
+
 /* pcie aer error injection */
 void pcie_aer_inject_error_print(Monitor *mon, const QObject *data);
 int do_pcie_aer_inject_error(Monitor *mon,
commit 963d83c85420b39eb4ab6ae1ebdcd7f818221402
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Aug 23 23:40:28 2010 +0200

    Compile device-hotplug on all targets
    
    All guest targets could potentially implement hotplugging. With the next
    patches in this set I will also reflect this in the monitor interface.
    
    So let's always compile it in. It shouldn't hurt.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/Makefile.target b/Makefile.target
index 3261383..d70d911 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -220,12 +220,15 @@ ifeq ($(CONFIG_KVM), y)
 endif
 obj-$(CONFIG_IVSHMEM) += ivshmem.o
 
+# Generic hotplugging
+obj-y += device-hotplug.o
+
 # Hardware support
 obj-i386-y += vga.o
 obj-i386-y += mc146818rtc.o pc.o
 obj-i386-y += cirrus_vga.o sga.o apic.o ioapic.o piix_pci.o
 obj-i386-y += vmport.o
-obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
+obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += debugcon.o multiboot.o
 obj-i386-y += pc_piix.o
 obj-i386-$(CONFIG_KVM) += kvmclock.o
commit 7fa41e536b05865baa9d79c6fd72785f6841576a
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Aug 23 18:58:34 2010 +0200

    [S390] Add hotplug support
    
    I just submitted a few patches that enable the s390 virtio bus to receive
    a hotplug add event. This patch implements the qemu side of it, so that new
    hotplug events can be submitted to the guest.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    
    ---
    
    v1 -> v2:
    
      - make s390 virtio hoplug code emulate-capable

diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index c4b9a99..2efea9f 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -82,12 +82,24 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
     bus->dev_offs = bus->dev_page;
     bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE;
 
+    /* Enable hotplugging */
+    _bus->allow_hotplug = 1;
+
     /* Allocate RAM for VirtIO device pages (descriptors, queues, rings) */
     *ram_size += S390_DEVICE_PAGES * TARGET_PAGE_SIZE;
 
     return bus;
 }
 
+static void s390_virtio_irq(CPUState *env, int config_change, uint64_t token)
+{
+    if (kvm_enabled()) {
+        kvm_s390_virtio_irq(env, config_change, token);
+    } else {
+        cpu_inject_ext(env, VIRTIO_EXT_CODE, config_change, token);
+    }
+}
+
 static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
 {
     VirtIOS390Bus *bus;
@@ -109,6 +121,11 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
     dev->host_features = vdev->get_features(vdev, dev->host_features);
     s390_virtio_device_sync(dev);
 
+    if (dev->qdev.hotplugged) {
+        CPUState *env = s390_cpu_addr2state(0);
+        s390_virtio_irq(env, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
+    }
+
     return 0;
 }
 
@@ -310,11 +327,7 @@ static void virtio_s390_notify(void *opaque, uint16_t vector)
     uint64_t token = s390_virtio_device_vq_token(dev, vector);
     CPUState *env = s390_cpu_addr2state(0);
 
-    if (kvm_enabled()) {
-        kvm_s390_virtio_irq(env, 0, token);
-    } else {
-        cpu_inject_ext(env, VIRTIO_EXT_CODE, 0, token);
-    }
+    s390_virtio_irq(env, 0, token);
 }
 
 static unsigned virtio_s390_get_features(void *opaque)
@@ -382,6 +395,7 @@ static void s390_virtio_bus_register_withprop(VirtIOS390DeviceInfo *info)
 {
     info->qdev.init = s390_virtio_busdev_init;
     info->qdev.bus_info = &s390_virtio_bus_info;
+    info->qdev.unplug = qdev_simple_unplug_cb;
 
     assert(info->qdev.size >= sizeof(VirtIOS390Device));
     qdev_register(&info->qdev);
diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h
index f1bece7..d02a907 100644
--- a/hw/s390-virtio-bus.h
+++ b/hw/s390-virtio-bus.h
@@ -35,6 +35,11 @@
 #define VIRTIO_RING_LEN			(TARGET_PAGE_SIZE * 3)
 #define S390_DEVICE_PAGES		512
 
+#define VIRTIO_PARAM_MASK               0xff
+#define VIRTIO_PARAM_VRING_INTERRUPT    0x0
+#define VIRTIO_PARAM_CONFIG_CHANGED     0x1
+#define VIRTIO_PARAM_DEV_ADD            0x2
+
 typedef struct VirtIOS390Device {
     DeviceState qdev;
     ram_addr_t dev_offs;
commit f3c6a169a39d188e98c17a0a0ebfa7f85e5aafdd
Merge: 8d3bc51... 586c623...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jan 3 14:39:05 2012 -0600

    Merge remote-tracking branch 'qemu-kvm/memory/page_desc' into staging
    
    * qemu-kvm/memory/page_desc: (22 commits)
      Remove cpu_get_physical_page_desc()
      sparc: avoid cpu_get_physical_page_desc()
      virtio-balloon: avoid cpu_get_physical_page_desc()
      vhost: avoid cpu_get_physical_page_desc()
      kvm: avoid cpu_get_physical_page_desc()
      memory: remove CPUPhysMemoryClient
      xen: convert to MemoryListener API
      memory: temporarily add memory_region_get_ram_addr()
      xen, vga: add API for registering the framebuffer
      vhost: convert to MemoryListener API
      kvm: convert to MemoryListener API
      kvm: switch kvm slots to use host virtual address instead of ram_addr_t
      memory: add API for observing updates to the physical memory map
      memory: replace cpu_physical_sync_dirty_bitmap() with a memory API
      framebuffer: drop use of cpu_physical_sync_dirty_bitmap()
      loader: remove calls to cpu_get_physical_page_desc()
      framebuffer: drop use of cpu_get_physical_page_desc()
      memory: introduce memory_region_find()
      memory: add memory_region_is_logging()
      memory: add memory_region_is_rom()
      ...

commit 586c6230c012d1aced38e5a5614d15052ca4ae7a
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Dec 19 16:01:08 2011 +0200

    Remove cpu_get_physical_page_desc()
    
    No longer used.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpu-common.h b/cpu-common.h
index eee2faf..3fe44d2 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -38,7 +38,6 @@ typedef unsigned long ram_addr_t;
 typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
 typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
 
-ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr);
 void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
 /* This should only be used for ram local to a device.  */
 void *qemu_get_ram_ptr(ram_addr_t addr);
diff --git a/exec.c b/exec.c
index e1f7462..b02199b 100644
--- a/exec.c
+++ b/exec.c
@@ -2595,17 +2595,6 @@ void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
     }
 }
 
-/* XXX: temporary until new memory mapping API */
-ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr)
-{
-    PhysPageDesc *p;
-
-    p = phys_page_find(addr >> TARGET_PAGE_BITS);
-    if (!p)
-        return IO_MEM_UNASSIGNED;
-    return p->phys_offset;
-}
-
 void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
 {
     if (kvm_enabled())
commit cc4aa8307c83111a0c804ae3eaf1e63f220c682e
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Dec 19 13:18:13 2011 +0200

    sparc: avoid cpu_get_physical_page_desc()
    
    This reaches into the innards of the memory core, which are being
    changed.  Switch to a memory API version.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/target-sparc/mmu_helper.c b/target-sparc/mmu_helper.c
index 8cdc224..bdff1c3 100644
--- a/target-sparc/mmu_helper.c
+++ b/target-sparc/mmu_helper.c
@@ -19,6 +19,7 @@
 
 #include "cpu.h"
 #include "trace.h"
+#include "exec-memory.h"
 
 /* Sparc MMU emulation */
 
@@ -839,13 +840,15 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
     target_phys_addr_t phys_addr;
     int mmu_idx = cpu_mmu_index(env);
+    MemoryRegionSection section;
 
     if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 2, mmu_idx) != 0) {
         if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 0, mmu_idx) != 0) {
             return -1;
         }
     }
-    if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED) {
+    section = memory_region_find(get_system_memory(), phys_addr, 1);
+    if (!section.size) {
         return -1;
     }
     return phys_addr;
commit b7c28c74af51e07fc457fef47ac4ec6b1e654d2c
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Dec 19 13:18:13 2011 +0200

    virtio-balloon: avoid cpu_get_physical_page_desc()
    
    This reaches into the innards of the memory core, which are being
    changed.  Switch to a memory API version.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index e24a2bf..ce9d2c9 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -21,6 +21,7 @@
 #include "balloon.h"
 #include "virtio-balloon.h"
 #include "kvm.h"
+#include "exec-memory.h"
 
 #if defined(__linux__)
 #include <sys/mman.h>
@@ -70,6 +71,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
 {
     VirtIOBalloon *s = to_virtio_balloon(vdev);
     VirtQueueElement elem;
+    MemoryRegionSection section;
 
     while (virtqueue_pop(vq, &elem)) {
         size_t offset = 0;
@@ -82,13 +84,16 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
             pa = (ram_addr_t)ldl_p(&pfn) << VIRTIO_BALLOON_PFN_SHIFT;
             offset += 4;
 
-            addr = cpu_get_physical_page_desc(pa);
-            if ((addr & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
+            /* FIXME: remove get_system_memory(), but how? */
+            section = memory_region_find(get_system_memory(), pa, 1);
+            if (!section.size || !memory_region_is_ram(section.mr))
                 continue;
 
-            /* Using qemu_get_ram_ptr is bending the rules a bit, but
+            /* Using memory_region_get_ram_ptr is bending the rules a bit, but
                should be OK because we only want a single page.  */
-            balloon_page(qemu_get_ram_ptr(addr), !!(vq == s->dvq));
+            addr = section.offset_within_region;
+            balloon_page(memory_region_get_ram_ptr(section.mr) + addr,
+                         !!(vq == s->dvq));
         }
 
         virtqueue_push(vq, &elem, offset);
commit 2817b260e3ca57ee091fc56403bfafdcc18b6a96
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Dec 19 13:18:13 2011 +0200

    vhost: avoid cpu_get_physical_page_desc()
    
    This reaches into the innards of the memory core, which are being
    changed.  Switch to a memory API version.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/vhost.c b/hw/vhost.c
index a1c5e4c..cd56e75 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -17,6 +17,7 @@
 #include <linux/vhost.h>
 
 static void vhost_dev_sync_region(struct vhost_dev *dev,
+                                  MemoryRegionSection *section,
                                   uint64_t mfirst, uint64_t mlast,
                                   uint64_t rfirst, uint64_t rlast)
 {
@@ -49,8 +50,8 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
                 ffsll(log) : ffs(log))) {
             ram_addr_t ram_addr;
             bit -= 1;
-            ram_addr = cpu_get_physical_page_desc(addr + bit * VHOST_LOG_PAGE);
-            cpu_physical_memory_set_dirty(ram_addr);
+            ram_addr = section->offset_within_region + bit * VHOST_LOG_PAGE;
+            memory_region_set_dirty(section->mr, ram_addr);
             log &= ~(0x1ull << bit);
         }
         addr += VHOST_LOG_CHUNK;
@@ -58,6 +59,7 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
 }
 
 static int vhost_sync_dirty_bitmap(struct vhost_dev *dev,
+                                   MemoryRegionSection *section,
                                    target_phys_addr_t start_addr,
                                    target_phys_addr_t end_addr)
 {
@@ -68,14 +70,14 @@ static int vhost_sync_dirty_bitmap(struct vhost_dev *dev,
     }
     for (i = 0; i < dev->mem->nregions; ++i) {
         struct vhost_memory_region *reg = dev->mem->regions + i;
-        vhost_dev_sync_region(dev, start_addr, end_addr,
+        vhost_dev_sync_region(dev, section, start_addr, end_addr,
                               reg->guest_phys_addr,
                               range_get_last(reg->guest_phys_addr,
                                              reg->memory_size));
     }
     for (i = 0; i < dev->nvqs; ++i) {
         struct vhost_virtqueue *vq = dev->vqs + i;
-        vhost_dev_sync_region(dev, start_addr, end_addr, vq->used_phys,
+        vhost_dev_sync_region(dev, section, start_addr, end_addr, vq->used_phys,
                               range_get_last(vq->used_phys, vq->used_size));
     }
     return 0;
@@ -89,7 +91,7 @@ static void vhost_log_sync(MemoryListener *listener,
     target_phys_addr_t start_addr = section->offset_within_address_space;
     target_phys_addr_t end_addr = start_addr + section->size;
 
-    vhost_sync_dirty_bitmap(dev, start_addr, end_addr);
+    vhost_sync_dirty_bitmap(dev, section, start_addr, end_addr);
 }
 
 /* Assign/unassign. Keep an unsorted array of non-overlapping
@@ -261,7 +263,7 @@ static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size)
 {
     vhost_log_chunk_t *log;
     uint64_t log_base;
-    int r;
+    int r, i;
     if (size) {
         log = g_malloc0(size * sizeof *log);
     } else {
@@ -270,7 +272,10 @@ static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size)
     log_base = (uint64_t)(unsigned long)log;
     r = ioctl(dev->control, VHOST_SET_LOG_BASE, &log_base);
     assert(r >= 0);
-    vhost_sync_dirty_bitmap(dev, 0, (target_phys_addr_t)~0x0ull);
+    for (i = 0; i < dev->n_mem_sections; ++i) {
+        vhost_sync_dirty_bitmap(dev, &dev->mem_sections[i],
+                                0, (target_phys_addr_t)~0x0ull);
+    }
     if (dev->log) {
         g_free(dev->log);
     }
@@ -428,13 +433,33 @@ static void vhost_set_memory(MemoryListener *listener,
 static void vhost_region_add(MemoryListener *listener,
                              MemoryRegionSection *section)
 {
+    struct vhost_dev *dev = container_of(listener, struct vhost_dev,
+                                         memory_listener);
+
+    ++dev->n_mem_sections;
+    dev->mem_sections = g_renew(MemoryRegionSection, dev->mem_sections,
+                                dev->n_mem_sections);
+    dev->mem_sections[dev->n_mem_sections - 1] = *section;
     vhost_set_memory(listener, section, true);
 }
 
 static void vhost_region_del(MemoryListener *listener,
                              MemoryRegionSection *section)
 {
+    struct vhost_dev *dev = container_of(listener, struct vhost_dev,
+                                         memory_listener);
+    int i;
+
     vhost_set_memory(listener, section, false);
+    for (i = 0; i < dev->n_mem_sections; ++i) {
+        if (dev->mem_sections[i].offset_within_address_space
+            == section->offset_within_address_space) {
+            --dev->n_mem_sections;
+            memmove(&dev->mem_sections[i], &dev->mem_sections[i+1],
+                    dev->n_mem_sections - i);
+            break;
+        }
+    }
 }
 
 static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
@@ -714,6 +739,8 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
         .log_global_stop = vhost_log_global_stop,
     };
     hdev->mem = g_malloc0(offsetof(struct vhost_memory, regions));
+    hdev->n_mem_sections = 0;
+    hdev->mem_sections = NULL;
     hdev->log = NULL;
     hdev->log_size = 0;
     hdev->log_enabled = false;
@@ -731,6 +758,7 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
 {
     memory_listener_unregister(&hdev->memory_listener);
     g_free(hdev->mem);
+    g_free(hdev->mem_sections);
     close(hdev->control);
 }
 
@@ -871,7 +899,10 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
                                 hdev->vqs + i,
                                 i);
     }
-    vhost_sync_dirty_bitmap(hdev, 0, (target_phys_addr_t)~0x0ull);
+    for (i = 0; i < hdev->n_mem_sections; ++i) {
+        vhost_sync_dirty_bitmap(hdev, &hdev->mem_sections[i],
+                                0, (target_phys_addr_t)~0x0ull);
+    }
     r = vdev->binding->set_guest_notifiers(vdev->binding_opaque, false);
     if (r < 0) {
         fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r);
diff --git a/hw/vhost.h b/hw/vhost.h
index d1824ec..80e64df 100644
--- a/hw/vhost.h
+++ b/hw/vhost.h
@@ -30,6 +30,8 @@ struct vhost_dev {
     MemoryListener memory_listener;
     int control;
     struct vhost_memory *mem;
+    int n_mem_sections;
+    MemoryRegionSection *mem_sections;
     struct vhost_virtqueue *vqs;
     int nvqs;
     unsigned long long features;
commit ffcde12f6ca9fd9701e238ce9909314a0123f553
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Dec 19 13:18:13 2011 +0200

    kvm: avoid cpu_get_physical_page_desc()
    
    This reaches into the innards of the memory core, which are being
    changed.  Switch to a memory API version.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index e3e4181..3174f42 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -340,16 +340,12 @@ static int kvm_set_migration_log(int enable)
 }
 
 /* get kvm's dirty pages bitmap and update qemu's */
-static int kvm_get_dirty_pages_log_range(unsigned long start_addr,
-                                         unsigned long *bitmap,
-                                         unsigned long offset,
-                                         unsigned long mem_size)
+static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section,
+                                         unsigned long *bitmap)
 {
     unsigned int i, j;
     unsigned long page_number, addr, addr1, c;
-    ram_addr_t ram_addr;
-    unsigned int len = ((mem_size / TARGET_PAGE_SIZE) + HOST_LONG_BITS - 1) /
-        HOST_LONG_BITS;
+    unsigned int len = ((section->size / TARGET_PAGE_SIZE) + HOST_LONG_BITS - 1) / HOST_LONG_BITS;
 
     /*
      * bitmap-traveling is faster than memory-traveling (for addr...)
@@ -363,9 +359,8 @@ static int kvm_get_dirty_pages_log_range(unsigned long start_addr,
                 c &= ~(1ul << j);
                 page_number = i * HOST_LONG_BITS + j;
                 addr1 = page_number * TARGET_PAGE_SIZE;
-                addr = offset + addr1;
-                ram_addr = cpu_get_physical_page_desc(addr);
-                cpu_physical_memory_set_dirty(ram_addr);
+                addr = section->offset_within_region + addr1;
+                memory_region_set_dirty(section->mr, addr);
             } while (c != 0);
         }
     }
@@ -382,14 +377,15 @@ static int kvm_get_dirty_pages_log_range(unsigned long start_addr,
  * @start_add: start of logged region.
  * @end_addr: end of logged region.
  */
-static int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
-                                          target_phys_addr_t end_addr)
+static int kvm_physical_sync_dirty_bitmap(MemoryRegionSection *section)
 {
     KVMState *s = kvm_state;
     unsigned long size, allocated_size = 0;
     KVMDirtyLog d;
     KVMSlot *mem;
     int ret = 0;
+    target_phys_addr_t start_addr = section->offset_within_address_space;
+    target_phys_addr_t end_addr = start_addr + section->size;
 
     d.dirty_bitmap = NULL;
     while (start_addr < end_addr) {
@@ -428,8 +424,7 @@ static int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
             break;
         }
 
-        kvm_get_dirty_pages_log_range(mem->start_addr, d.dirty_bitmap,
-                                      mem->start_addr, mem->memory_size);
+        kvm_get_dirty_pages_log_range(section, d.dirty_bitmap);
         start_addr = mem->start_addr + mem->memory_size;
     }
     g_free(d.dirty_bitmap);
@@ -686,11 +681,9 @@ static void kvm_region_del(MemoryListener *listener,
 static void kvm_log_sync(MemoryListener *listener,
                          MemoryRegionSection *section)
 {
-    target_phys_addr_t start = section->offset_within_address_space;
-    target_phys_addr_t end = start + section->size;
     int r;
 
-    r = kvm_physical_sync_dirty_bitmap(start, end);
+    r = kvm_physical_sync_dirty_bitmap(section);
     if (r < 0) {
         abort();
     }
commit dcd97e33af43ae0bfa7e8c39ce8cebcfe7af6cb4
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Dec 19 12:53:48 2011 +0200

    memory: remove CPUPhysMemoryClient
    
    No longer used.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpu-all.h b/cpu-all.h
index f2c5382..734833a 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -569,12 +569,6 @@ int cpu_physical_memory_set_dirty_tracking(int enable);
 
 int cpu_physical_memory_get_dirty_tracking(void);
 
-int cpu_physical_log_start(target_phys_addr_t start_addr,
-                           ram_addr_t size);
-
-int cpu_physical_log_stop(target_phys_addr_t start_addr,
-                          ram_addr_t size);
-
 void dump_exec_info(FILE *f, fprintf_function cpu_fprintf);
 #endif /* !CONFIG_USER_ONLY */
 
diff --git a/cpu-common.h b/cpu-common.h
index 8295e4f..eee2faf 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -71,29 +71,6 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
 void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque));
 void cpu_unregister_map_client(void *cookie);
 
-struct CPUPhysMemoryClient;
-typedef struct CPUPhysMemoryClient CPUPhysMemoryClient;
-struct CPUPhysMemoryClient {
-    void (*set_memory)(struct CPUPhysMemoryClient *client,
-                       target_phys_addr_t start_addr,
-                       ram_addr_t size,
-                       ram_addr_t phys_offset,
-                       bool log_dirty);
-    int (*sync_dirty_bitmap)(struct CPUPhysMemoryClient *client,
-                             target_phys_addr_t start_addr,
-                             target_phys_addr_t end_addr);
-    int (*migration_log)(struct CPUPhysMemoryClient *client,
-                         int enable);
-    int (*log_start)(struct CPUPhysMemoryClient *client,
-                     target_phys_addr_t phys_addr, ram_addr_t size);
-    int (*log_stop)(struct CPUPhysMemoryClient *client,
-                    target_phys_addr_t phys_addr, ram_addr_t size);
-    QLIST_ENTRY(CPUPhysMemoryClient) list;
-};
-
-void cpu_register_phys_memory_client(CPUPhysMemoryClient *);
-void cpu_unregister_phys_memory_client(CPUPhysMemoryClient *);
-
 /* Coalesced MMIO regions are areas where write operations can be reordered.
  * This usually implies that write operations are side-effect free.  This allows
  * batching which can make a major impact on performance when using
diff --git a/exec-obsolete.h b/exec-obsolete.h
index 5e5c4c6..34b9fc5 100644
--- a/exec-obsolete.h
+++ b/exec-obsolete.h
@@ -63,9 +63,6 @@ static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
 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);
 
-int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
-                                   target_phys_addr_t end_addr);
-
 #endif
 
 #endif
diff --git a/exec.c b/exec.c
index 36b61c9..e1f7462 100644
--- a/exec.c
+++ b/exec.c
@@ -1732,129 +1732,6 @@ const CPULogItem cpu_log_items[] = {
     { 0, NULL, NULL },
 };
 
-#ifndef CONFIG_USER_ONLY
-static QLIST_HEAD(memory_client_list, CPUPhysMemoryClient) memory_client_list
-    = QLIST_HEAD_INITIALIZER(memory_client_list);
-
-static void cpu_notify_set_memory(target_phys_addr_t start_addr,
-                                  ram_addr_t size,
-                                  ram_addr_t phys_offset,
-                                  bool log_dirty)
-{
-    CPUPhysMemoryClient *client;
-    QLIST_FOREACH(client, &memory_client_list, list) {
-        client->set_memory(client, start_addr, size, phys_offset, log_dirty);
-    }
-}
-
-static int cpu_notify_sync_dirty_bitmap(target_phys_addr_t start,
-                                        target_phys_addr_t end)
-{
-    CPUPhysMemoryClient *client;
-    QLIST_FOREACH(client, &memory_client_list, list) {
-        int r = client->sync_dirty_bitmap(client, start, end);
-        if (r < 0)
-            return r;
-    }
-    return 0;
-}
-
-static int cpu_notify_migration_log(int enable)
-{
-    CPUPhysMemoryClient *client;
-    if (enable) {
-        memory_global_dirty_log_start();
-    } else {
-        memory_global_dirty_log_stop();
-    }
-    QLIST_FOREACH(client, &memory_client_list, list) {
-        int r = client->migration_log(client, enable);
-        if (r < 0)
-            return r;
-    }
-    return 0;
-}
-
-struct last_map {
-    target_phys_addr_t start_addr;
-    ram_addr_t size;
-    ram_addr_t phys_offset;
-};
-
-/* The l1_phys_map provides the upper P_L1_BITs of the guest physical
- * address.  Each intermediate table provides the next L2_BITs of guest
- * physical address space.  The number of levels vary based on host and
- * guest configuration, making it efficient to build the final guest
- * physical address by seeding the L1 offset and shifting and adding in
- * each L2 offset as we recurse through them. */
-static void phys_page_for_each_1(CPUPhysMemoryClient *client, int level,
-                                 void **lp, target_phys_addr_t addr,
-                                 struct last_map *map)
-{
-    int i;
-
-    if (*lp == NULL) {
-        return;
-    }
-    if (level == 0) {
-        PhysPageDesc *pd = *lp;
-        addr <<= L2_BITS + TARGET_PAGE_BITS;
-        for (i = 0; i < L2_SIZE; ++i) {
-            if (pd[i].phys_offset != IO_MEM_UNASSIGNED) {
-                target_phys_addr_t start_addr = addr | i << TARGET_PAGE_BITS;
-
-                if (map->size &&
-                    start_addr == map->start_addr + map->size &&
-                    pd[i].phys_offset == map->phys_offset + map->size) {
-
-                    map->size += TARGET_PAGE_SIZE;
-                    continue;
-                } else if (map->size) {
-                    client->set_memory(client, map->start_addr,
-                                       map->size, map->phys_offset, false);
-                }
-
-                map->start_addr = start_addr;
-                map->size = TARGET_PAGE_SIZE;
-                map->phys_offset = pd[i].phys_offset;
-            }
-        }
-    } else {
-        void **pp = *lp;
-        for (i = 0; i < L2_SIZE; ++i) {
-            phys_page_for_each_1(client, level - 1, pp + i,
-                                 (addr << L2_BITS) | i, map);
-        }
-    }
-}
-
-static void phys_page_for_each(CPUPhysMemoryClient *client)
-{
-    int i;
-    struct last_map map = { };
-
-    for (i = 0; i < P_L1_SIZE; ++i) {
-        phys_page_for_each_1(client, P_L1_SHIFT / L2_BITS - 1,
-                             l1_phys_map + i, i, &map);
-    }
-    if (map.size) {
-        client->set_memory(client, map.start_addr, map.size, map.phys_offset,
-                           false);
-    }
-}
-
-void cpu_register_phys_memory_client(CPUPhysMemoryClient *client)
-{
-    QLIST_INSERT_HEAD(&memory_client_list, client, list);
-    phys_page_for_each(client);
-}
-
-void cpu_unregister_phys_memory_client(CPUPhysMemoryClient *client)
-{
-    QLIST_REMOVE(client, list);
-}
-#endif
-
 static int cmp1(const char *s1, int n, const char *s2)
 {
     if (strlen(s2) != n)
@@ -2131,7 +2008,11 @@ int cpu_physical_memory_set_dirty_tracking(int enable)
 {
     int ret = 0;
     in_migration = enable;
-    ret = cpu_notify_migration_log(!!enable);
+    if (enable) {
+        memory_global_dirty_log_start();
+    } else {
+        memory_global_dirty_log_stop();
+    }
     return ret;
 }
 
@@ -2140,45 +2021,6 @@ int cpu_physical_memory_get_dirty_tracking(void)
     return in_migration;
 }
 
-int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
-                                   target_phys_addr_t end_addr)
-{
-    int ret;
-
-    ret = cpu_notify_sync_dirty_bitmap(start_addr, end_addr);
-    return ret;
-}
-
-int cpu_physical_log_start(target_phys_addr_t start_addr,
-                           ram_addr_t size)
-{
-    CPUPhysMemoryClient *client;
-    QLIST_FOREACH(client, &memory_client_list, list) {
-        if (client->log_start) {
-            int r = client->log_start(client, start_addr, size);
-            if (r < 0) {
-                return r;
-            }
-        }
-    }
-    return 0;
-}
-
-int cpu_physical_log_stop(target_phys_addr_t start_addr,
-                          ram_addr_t size)
-{
-    CPUPhysMemoryClient *client;
-    QLIST_FOREACH(client, &memory_client_list, list) {
-        if (client->log_stop) {
-            int r = client->log_stop(client, start_addr, size);
-            if (r < 0) {
-                return r;
-            }
-        }
-    }
-    return 0;
-}
-
 static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
 {
     ram_addr_t ram_addr;
@@ -2681,7 +2523,6 @@ void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
     subpage_t *subpage;
 
     assert(size);
-    cpu_notify_set_memory(start_addr, size, phys_offset, log_dirty);
 
     if (phys_offset == IO_MEM_UNASSIGNED) {
         region_offset = start_addr;
diff --git a/memory.c b/memory.c
index 6a637d4..a90eefd 100644
--- a/memory.c
+++ b/memory.c
@@ -338,11 +338,6 @@ static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
 
 static void as_memory_range_del(AddressSpace *as, FlatRange *fr)
 {
-    if (fr->dirty_log_mask) {
-        Int128 end = addrrange_end(fr->addr);
-        cpu_physical_sync_dirty_bitmap(int128_get64(fr->addr.start),
-                                       int128_get64(end));
-    }
     cpu_register_physical_memory(int128_get64(fr->addr.start),
                                  int128_get64(fr->addr.size),
                                  IO_MEM_UNASSIGNED);
@@ -350,14 +345,10 @@ static void as_memory_range_del(AddressSpace *as, FlatRange *fr)
 
 static void as_memory_log_start(AddressSpace *as, FlatRange *fr)
 {
-    cpu_physical_log_start(int128_get64(fr->addr.start),
-                           int128_get64(fr->addr.size));
 }
 
 static void as_memory_log_stop(AddressSpace *as, FlatRange *fr)
 {
-    cpu_physical_log_stop(int128_get64(fr->addr.start),
-                          int128_get64(fr->addr.size));
 }
 
 static void as_memory_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
@@ -1165,8 +1156,6 @@ 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);
-            cpu_physical_sync_dirty_bitmap(int128_get64(fr->addr.start),
-                                           int128_get64(addrrange_end(fr->addr)));
         }
     }
 }
@@ -1493,7 +1482,6 @@ void memory_global_sync_dirty_bitmap(MemoryRegion *address_space)
     AddressSpace *as = memory_region_to_address_space(address_space);
     FlatRange *fr;
 
-    cpu_physical_sync_dirty_bitmap(0, TARGET_PHYS_ADDR_MAX);
     FOR_EACH_FLAT_RANGE(fr, &as->current_map) {
         MEMORY_LISTENER_UPDATE_REGION(fr, as, log_sync);
     }
commit 20581d207853fe4b1af88b116f077516dfa888cd
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Dec 19 12:07:50 2011 +0200

    xen: convert to MemoryListener API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/trace-events b/trace-events
index 514849a..5781a69 100644
--- a/trace-events
+++ b/trace-events
@@ -462,7 +462,7 @@ mipsnet_irq(uint32_t isr, uint32_t intctl) "set irq to %d (%02x)"
 
 # xen-all.c
 xen_ram_alloc(unsigned long ram_addr, unsigned long size) "requested: %#lx, size %#lx"
-xen_client_set_memory(uint64_t start_addr, unsigned long size, unsigned long phys_offset, bool log_dirty) "%#"PRIx64" size %#lx, offset %#lx, log_dirty %i"
+xen_client_set_memory(uint64_t start_addr, unsigned long size, bool log_dirty) "%#"PRIx64" size %#lx, log_dirty %i"
 
 # xen-mapcache.c
 xen_map_cache(uint64_t phys_addr) "want %#"PRIx64
diff --git a/xen-all.c b/xen-all.c
index 51315ce..dc23265 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -63,6 +63,7 @@ static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
 typedef struct XenPhysmap {
     target_phys_addr_t start_addr;
     ram_addr_t size;
+    MemoryRegion *mr;
     target_phys_addr_t phys_offset;
 
     QLIST_ENTRY(XenPhysmap) list;
@@ -80,8 +81,9 @@ typedef struct XenIOState {
     int send_vcpu;
 
     struct xs_handle *xenstore;
-    CPUPhysMemoryClient client;
+    MemoryListener memory_listener;
     QLIST_HEAD(, XenPhysmap) physmap;
+    target_phys_addr_t free_phys_offset;
     const XenPhysmap *log_for_dirtybit;
 
     Notifier exit;
@@ -226,13 +228,14 @@ static XenPhysmap *get_physmapping(XenIOState *state,
 static int xen_add_to_physmap(XenIOState *state,
                               target_phys_addr_t start_addr,
                               ram_addr_t size,
-                              target_phys_addr_t phys_offset)
+                              MemoryRegion *mr,
+                              target_phys_addr_t offset_within_region)
 {
     unsigned long i = 0;
     int rc = 0;
     XenPhysmap *physmap = NULL;
     target_phys_addr_t pfn, start_gpfn;
-    RAMBlock *block;
+    target_phys_addr_t phys_offset = memory_region_get_ram_addr(mr);
 
     if (get_physmapping(state, start_addr, size)) {
         return 0;
@@ -245,17 +248,13 @@ static int xen_add_to_physmap(XenIOState *state,
      * the linear framebuffer to be that region.
      * Avoid tracking any regions that is not videoram and avoid tracking
      * the legacy vga region. */
-    QLIST_FOREACH(block, &ram_list.blocks, next) {
-        if (!strcmp(block->idstr, "vga.vram") && block->offset == phys_offset
-                && start_addr > 0xbffff) {
-            goto go_physmap;
-        }
+    if (mr == framebuffer && start_addr > 0xbffff) {
+        goto go_physmap;
     }
     return -1;
 
 go_physmap:
-    DPRINTF("mapping vram to %llx - %llx, from %llx\n",
-            start_addr, start_addr + size, phys_offset);
+    DPRINTF("mapping vram to %llx - %llx\n", start_addr, start_addr + size);
 
     pfn = phys_offset >> TARGET_PAGE_BITS;
     start_gpfn = start_addr >> TARGET_PAGE_BITS;
@@ -334,7 +333,8 @@ static int xen_remove_from_physmap(XenIOState *state,
 static int xen_add_to_physmap(XenIOState *state,
                               target_phys_addr_t start_addr,
                               ram_addr_t size,
-                              target_phys_addr_t phys_offset)
+                              MemoryRegion *mr,
+                              target_phys_addr_t offset_within_region)
 {
     return -ENOSYS;
 }
@@ -347,49 +347,62 @@ static int xen_remove_from_physmap(XenIOState *state,
 }
 #endif
 
-static void xen_client_set_memory(struct CPUPhysMemoryClient *client,
-                                  target_phys_addr_t start_addr,
-                                  ram_addr_t size,
-                                  ram_addr_t phys_offset,
-                                  bool log_dirty)
+static void xen_set_memory(struct MemoryListener *listener,
+                           MemoryRegionSection *section,
+                           bool add)
 {
-    XenIOState *state = container_of(client, XenIOState, client);
-    ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
+    XenIOState *state = container_of(listener, XenIOState, memory_listener);
+    target_phys_addr_t start_addr = section->offset_within_address_space;
+    ram_addr_t size = section->size;
+    bool log_dirty = memory_region_is_logging(section->mr);
     hvmmem_type_t mem_type;
 
-    if (!(start_addr != phys_offset
-          && ( (log_dirty && flags < IO_MEM_UNASSIGNED)
-               || (!log_dirty && flags == IO_MEM_UNASSIGNED)))) {
+    if (!memory_region_is_ram(section->mr)) {
         return;
     }
 
-    trace_xen_client_set_memory(start_addr, size, phys_offset, log_dirty);
+    if (!(section->mr != &ram_memory
+          && ( (log_dirty && add) || (!log_dirty && !add)))) {
+        return;
+    }
+
+    trace_xen_client_set_memory(start_addr, size, log_dirty);
 
     start_addr &= TARGET_PAGE_MASK;
     size = TARGET_PAGE_ALIGN(size);
-    phys_offset &= TARGET_PAGE_MASK;
-
-    switch (flags) {
-    case IO_MEM_RAM:
-        xen_add_to_physmap(state, start_addr, size, phys_offset);
-        break;
-    case IO_MEM_ROM:
-        mem_type = HVMMEM_ram_ro;
-        if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type,
-                                start_addr >> TARGET_PAGE_BITS,
-                                size >> TARGET_PAGE_BITS)) {
-            DPRINTF("xc_hvm_set_mem_type error, addr: "TARGET_FMT_plx"\n",
-                    start_addr);
+
+    if (add) {
+        if (!memory_region_is_rom(section->mr)) {
+            xen_add_to_physmap(state, start_addr, size,
+                               section->mr, section->offset_within_region);
+        } else {
+            mem_type = HVMMEM_ram_ro;
+            if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type,
+                                    start_addr >> TARGET_PAGE_BITS,
+                                    size >> TARGET_PAGE_BITS)) {
+                DPRINTF("xc_hvm_set_mem_type error, addr: "TARGET_FMT_plx"\n",
+                        start_addr);
+            }
         }
-        break;
-    case IO_MEM_UNASSIGNED:
+    } else {
         if (xen_remove_from_physmap(state, start_addr, size) < 0) {
             DPRINTF("physmapping does not exist at "TARGET_FMT_plx"\n", start_addr);
         }
-        break;
     }
 }
 
+static void xen_region_add(MemoryListener *listener,
+                           MemoryRegionSection *section)
+{
+    xen_set_memory(listener, section, true);
+}
+
+static void xen_region_del(MemoryListener *listener,
+                           MemoryRegionSection *section)
+{
+    xen_set_memory(listener, section, false);
+}
+
 static int xen_sync_dirty_bitmap(XenIOState *state,
                                  target_phys_addr_t start_addr,
                                  ram_addr_t size)
@@ -433,43 +446,54 @@ static int xen_sync_dirty_bitmap(XenIOState *state,
     return 0;
 }
 
-static int xen_log_start(CPUPhysMemoryClient *client, target_phys_addr_t phys_addr, ram_addr_t size)
+static void xen_log_start(MemoryListener *listener,
+                          MemoryRegionSection *section)
 {
-    XenIOState *state = container_of(client, XenIOState, client);
+    XenIOState *state = container_of(listener, XenIOState, memory_listener);
+    int r;
 
-    return xen_sync_dirty_bitmap(state, phys_addr, size);
+    r = xen_sync_dirty_bitmap(state, section->offset_within_address_space,
+                              section->size);
+    assert(r >= 0);
 }
 
-static int xen_log_stop(CPUPhysMemoryClient *client, target_phys_addr_t phys_addr, ram_addr_t size)
+static void xen_log_stop(MemoryListener *listener, MemoryRegionSection *section)
 {
-    XenIOState *state = container_of(client, XenIOState, client);
+    XenIOState *state = container_of(listener, XenIOState, memory_listener);
+    int r;
 
     state->log_for_dirtybit = NULL;
     /* Disable dirty bit tracking */
-    return xc_hvm_track_dirty_vram(xen_xc, xen_domid, 0, 0, NULL);
+    r = xc_hvm_track_dirty_vram(xen_xc, xen_domid, 0, 0, NULL);
+    assert(r >= 0);
 }
 
-static int xen_client_sync_dirty_bitmap(struct CPUPhysMemoryClient *client,
-                                        target_phys_addr_t start_addr,
-                                        target_phys_addr_t end_addr)
+static void xen_log_sync(MemoryListener *listener, MemoryRegionSection *section)
 {
-    XenIOState *state = container_of(client, XenIOState, client);
+    XenIOState *state = container_of(listener, XenIOState, memory_listener);
+    int r;
 
-    return xen_sync_dirty_bitmap(state, start_addr, end_addr - start_addr);
+    r = xen_sync_dirty_bitmap(state, section->offset_within_address_space,
+                              section->size);
+    assert(r >= 0);
 }
 
-static int xen_client_migration_log(struct CPUPhysMemoryClient *client,
-                                    int enable)
+static void xen_log_global_start(MemoryListener *listener)
+{
+}
+
+static void xen_log_global_stop(MemoryListener *listener)
 {
-    return 0;
 }
 
-static CPUPhysMemoryClient xen_cpu_phys_memory_client = {
-    .set_memory = xen_client_set_memory,
-    .sync_dirty_bitmap = xen_client_sync_dirty_bitmap,
-    .migration_log = xen_client_migration_log,
+static MemoryListener xen_memory_listener = {
+    .region_add = xen_region_add,
+    .region_del = xen_region_del,
     .log_start = xen_log_start,
     .log_stop = xen_log_stop,
+    .log_sync = xen_log_sync,
+    .log_global_start = xen_log_global_start,
+    .log_global_stop = xen_log_global_stop,
 };
 
 /* VCPU Operations, MMIO, IO ring ... */
@@ -947,9 +971,9 @@ int xen_hvm_init(void)
 
     qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
 
-    state->client = xen_cpu_phys_memory_client;
+    state->memory_listener = xen_memory_listener;
     QLIST_INIT(&state->physmap);
-    cpu_register_phys_memory_client(&state->client);
+    memory_listener_register(&state->memory_listener);
     state->log_for_dirtybit = NULL;
 
     /* Initialize backend core & drivers */
commit f7aa558396dd0f6b7a2b22c05cb503c655854102
Author: Varun Sethi <Varun.Sethi at freescale.com>
Date:   Thu Dec 22 12:26:17 2011 +0000

    PPC: Add description for the Freescale e500mc core.
    
    This core is found on chips such as p4080, p3041, p2040, and p5020.
    
    More needs to be done to make this viable for TCG (such as missing SPRs
    and instructions), but this suffices to get KVM running with appropriate
    kernel support.
    
    Signed-off-by: Varun Sethi <Varun.Sethi at freescale.com>
    [scottwood at freescale.com: tweak some flags]
    Signed-off-by: Scott Wood <scottwood at freescale.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 8a7233f..47d73a6 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -2,6 +2,7 @@
  *  PowerPC CPU initialization for qemu.
  *
  *  Copyright (c) 2003-2007 Jocelyn Mayer
+ *  Copyright 2011 Freescale Semiconductor, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -4399,6 +4400,33 @@ static void init_proc_e300 (CPUPPCState *env)
 #define check_pow_e500v2       check_pow_hid0
 #define init_proc_e500v2       init_proc_e500v2
 
+/* e500mc core                                                               */
+#define POWERPC_INSNS_e500mc   (PPC_INSNS_BASE | PPC_ISEL |                 \
+                                PPC_WRTEE | PPC_RFDI | PPC_RFMCI |          \
+                                PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI | \
+                                PPC_CACHE_DCBZ | PPC_CACHE_DCBA |           \
+                                PPC_FLOAT | PPC_FLOAT_FRES |                \
+                                PPC_FLOAT_FRSQRTE | PPC_FLOAT_FSEL |        \
+                                PPC_FLOAT_STFIWX | PPC_WAIT |               \
+                                PPC_MEM_TLBSYNC | PPC_TLBIVAX)
+#define POWERPC_INSNS2_e500mc  (PPC2_BOOKE206)
+#define POWERPC_MSRM_e500mc    (0x000000001402FB36ULL)
+#define POWERPC_MMU_e500mc     (POWERPC_MMU_BOOKE206)
+#define POWERPC_EXCP_e500mc    (POWERPC_EXCP_BOOKE)
+#define POWERPC_INPUT_e500mc   (PPC_FLAGS_INPUT_BookE)
+/* Fixme: figure out the correct flag for e500mc */
+#define POWERPC_BFDM_e500mc    (bfd_mach_ppc_e500)
+#define POWERPC_FLAG_e500mc    (POWERPC_FLAG_CE | POWERPC_FLAG_DE | \
+                                POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
+#define check_pow_e500mc       check_pow_none
+#define init_proc_e500mc       init_proc_e500mc
+
+enum fsl_e500_version {
+    fsl_e500v1,
+    fsl_e500v2,
+    fsl_e500mc,
+};
+
 static void init_proc_e500 (CPUPPCState *env, int version)
 {
     uint32_t tlbncfg[2];
@@ -4430,15 +4458,26 @@ static void init_proc_e500 (CPUPPCState *env, int version)
     env->nb_ways = 2;
     env->id_tlbs = 0;
     switch (version) {
-    case 1:
+    case fsl_e500v1:
         /* e500v1 */
         tlbncfg[0] = gen_tlbncfg(2, 1, 1, 0, 256);
         tlbncfg[1] = gen_tlbncfg(16, 1, 9, TLBnCFG_AVAIL | TLBnCFG_IPROT, 16);
+        env->dcache_line_size = 32;
+        env->icache_line_size = 32;
         break;
-    case 2:
+    case fsl_e500v2:
         /* e500v2 */
         tlbncfg[0] = gen_tlbncfg(4, 1, 1, 0, 512);
         tlbncfg[1] = gen_tlbncfg(16, 1, 12, TLBnCFG_AVAIL | TLBnCFG_IPROT, 16);
+        env->dcache_line_size = 32;
+        env->icache_line_size = 32;
+        break;
+    case fsl_e500mc:
+        /* e500mc */
+        tlbncfg[0] = gen_tlbncfg(4, 1, 1, 0, 512);
+        tlbncfg[1] = gen_tlbncfg(64, 1, 12, TLBnCFG_AVAIL | TLBnCFG_IPROT, 64);
+        env->dcache_line_size = 64;
+        env->icache_line_size = 64;
         break;
     default:
         cpu_abort(env, "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]);
@@ -4522,20 +4561,23 @@ static void init_proc_e500 (CPUPPCState *env, int version)
 #endif
 
     init_excp_e200(env);
-    env->dcache_line_size = 32;
-    env->icache_line_size = 32;
     /* Allocate hardware IRQ controller */
     ppce500_irq_init(env);
 }
 
 static void init_proc_e500v1(CPUPPCState *env)
 {
-    init_proc_e500(env, 1);
+    init_proc_e500(env, fsl_e500v1);
 }
 
 static void init_proc_e500v2(CPUPPCState *env)
 {
-    init_proc_e500(env, 2);
+    init_proc_e500(env, fsl_e500v2);
+}
+
+static void init_proc_e500mc(CPUPPCState *env)
+{
+    init_proc_e500(env, fsl_e500mc);
 }
 
 /* Non-embedded PowerPC                                                      */
@@ -7070,6 +7112,7 @@ enum {
     CPU_POWERPC_e500v2_v21         = 0x80210021,
     CPU_POWERPC_e500v2_v22         = 0x80210022,
     CPU_POWERPC_e500v2_v30         = 0x80210030,
+    CPU_POWERPC_e500mc             = 0x80230020,
     /* MPC85xx microcontrollers */
 #define CPU_POWERPC_MPC8533          CPU_POWERPC_MPC8533_v11
 #define CPU_POWERPC_MPC8533_v10      CPU_POWERPC_e500v2_v21
@@ -8471,6 +8514,7 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("e500v2_v22",    CPU_POWERPC_e500v2_v22,             e500v2),
     /* PowerPC e500v2 v3.0 core                                              */
     POWERPC_DEF("e500v2_v30",    CPU_POWERPC_e500v2_v30,             e500v2),
+    POWERPC_DEF("e500mc",        CPU_POWERPC_e500mc,                 e500mc),
     /* PowerPC e500 microcontrollers                                         */
     /* MPC8533                                                               */
     POWERPC_DEF_SVR("MPC8533",
commit 9fc380d3ed1cfac7d87dbe2a140e465cac58ed7b
Author: Michael Ellerman <michael at ellerman.id.au>
Date:   Mon Dec 12 18:24:35 2011 +0000

    pseries: Check for duplicate addresses on the spapr-vio bus
    
    Check that devices on the spapr vio bus aren't given duplicate
    addresses. Currently we will not run with duplicate devices, the
    fdt code will spot it, but the error reporting is not great. With
    this patch we can report the error nicely in terms of the device
    names given by the user.
    
    Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
    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_vio.c b/hw/spapr_vio.c
index cd03416..7a86dc8 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -621,11 +621,43 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
     rtas_st(rets, 0, 0);
 }
 
+static int spapr_vio_check_reg(VIOsPAPRDevice *sdev, VIOsPAPRDeviceInfo *info)
+{
+    VIOsPAPRDevice *other_sdev;
+    DeviceState *qdev;
+    VIOsPAPRBus *sbus;
+
+    sbus = DO_UPCAST(VIOsPAPRBus, bus, sdev->qdev.parent_bus);
+
+    /*
+     * Check two device aren't given clashing addresses by the user (or some
+     * other mechanism). We have to open code this because we have to check
+     * for matches with devices other than us.
+     */
+    QTAILQ_FOREACH(qdev, &sbus->bus.children, sibling) {
+        other_sdev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
+
+        if (other_sdev != sdev && other_sdev->reg == sdev->reg) {
+            fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n",
+                    info->qdev.name, other_sdev->qdev.info->name, sdev->reg);
+            return -EEXIST;
+        }
+    }
+
+    return 0;
+}
+
 static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
 {
     VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
     VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
     char *id;
+    int ret;
+
+    ret = spapr_vio_check_reg(dev, info);
+    if (ret) {
+        return ret;
+    }
 
     /* Don't overwrite ids assigned on the command line */
     if (!dev->qdev.id) {
commit 68f3a94c64bbaaf8c7f2daa70de1b5d87a432f86
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Dec 13 15:24:34 2011 +1100

    pseries: Populate "/chosen/linux,stdout-path" in the FDT
    
    There is a device tree property "/chosen/linux,stdout-path" which indicates
    which device should be used as stdout - ie. "the console".
    
    Currently we don't specify anything, which means both firmware and Linux
    choose something arbitrarily. Use the routine we added in the last patch
    to pick a default vty and specify it as stdout.
    
    Currently SLOF doesn't use the property, but we are hoping to update it
    to do so.
    
    Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
    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 1883270..6a543de 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -441,6 +441,8 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
         }
     }
 
+    spapr_populate_chosen_stdout(fdt, spapr->vio_bus);
+
     _FDT((fdt_pack(fdt)));
 
     cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 2cce421..cd03416 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -793,4 +793,38 @@ out:
 
     return ret;
 }
+
+int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus)
+{
+    VIOsPAPRDevice *dev;
+    char *name, *path;
+    int ret, offset;
+
+    dev = spapr_vty_get_default(bus);
+    if (!dev)
+        return 0;
+
+    offset = fdt_path_offset(fdt, "/chosen");
+    if (offset < 0) {
+        return offset;
+    }
+
+    name = vio_format_dev_name(dev);
+    if (!name) {
+        return -ENOMEM;
+    }
+
+    if (asprintf(&path, "/vdevice/%s", name) < 0) {
+        path = NULL;
+        ret = -ENOMEM;
+        goto out;
+    }
+
+    ret = fdt_setprop_string(fdt, offset, "linux,stdout-path", path);
+out:
+    free(name);
+    free(path);
+
+    return ret;
+}
 #endif /* CONFIG_FDT */
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index 2430d45..0984d55 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -82,6 +82,7 @@ extern VIOsPAPRBus *spapr_vio_bus_init(void);
 extern VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg);
 extern void spapr_vio_bus_register_withprop(VIOsPAPRDeviceInfo *info);
 extern int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt);
+extern int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus);
 
 extern int spapr_vio_signal(VIOsPAPRDevice *dev, target_ulong mode);
 
@@ -107,6 +108,8 @@ void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev);
 void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd);
 void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg);
 
+VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus);
+
 int spapr_tce_set_bypass(uint32_t unit, uint32_t enable);
 void spapr_vio_quiesce(void);
 
diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
index 2923ca7..c5fb096 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -149,7 +149,7 @@ static VIOsPAPRDeviceInfo spapr_vty = {
     },
 };
 
-static VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
+VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
 {
     VIOsPAPRDevice *sdev, *selected;
     DeviceState *iter;
commit 98331f8ad6a3e2cfbb402d72e6be47eac7706251
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Dec 12 18:24:33 2011 +0000

    pseries: Add a routine to find a stable "default" vty and use it
    
    In vty_lookup() we have a special case for supporting early debug in
    the kernel. This accepts reg == 0 as a special case to mean "any vty".
    
    We implement this by searching the vtys on the bus and returning the
    first we find. This means that the vty we chose depends on the order
    the vtys are specified on the QEMU command line - because that determines
    the order of the vtys on the bus.
    
    We'd rather the command line order was irrelevant, so instead return
    the vty with the lowest reg value. This is still a guess as to what the
    user really means, but it is at least stable WRT command line ordering.
    
    Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>
    
    [agraf] fix braces

diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
index e217314..2923ca7 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -149,24 +149,53 @@ static VIOsPAPRDeviceInfo spapr_vty = {
     },
 };
 
+static VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
+{
+    VIOsPAPRDevice *sdev, *selected;
+    DeviceState *iter;
+
+    /*
+     * To avoid the console bouncing around we want one VTY to be
+     * the "default". We haven't really got anything to go on, so
+     * arbitrarily choose the one with the lowest reg value.
+     */
+
+    selected = NULL;
+    QTAILQ_FOREACH(iter, &bus->bus.children, sibling) {
+        /* Only look at VTY devices */
+        if (iter->info != &spapr_vty.qdev) {
+            continue;
+        }
+
+        sdev = DO_UPCAST(VIOsPAPRDevice, qdev, iter);
+
+        /* First VTY we've found, so it is selected for now */
+        if (!selected) {
+            selected = sdev;
+            continue;
+        }
+
+        /* Choose VTY with lowest reg value */
+        if (sdev->reg < selected->reg) {
+            selected = sdev;
+        }
+    }
+
+    return selected;
+}
+
 static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
 {
     VIOsPAPRDevice *sdev;
 
     sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
     if (!sdev && reg == 0) {
-        DeviceState *qdev;
-
         /* Hack for kernel early debug, which always specifies reg==0.
-         * We search all VIO devices, and grab the first available vty
-         * device.  This attempts to mimic existing PowerVM behaviour
+         * We search all VIO devices, and grab the vty with the lowest
+         * reg.  This attempts to mimic existing PowerVM behaviour
          * (early debug does work there, despite having no vty with
          * reg==0. */
-        QTAILQ_FOREACH(qdev, &spapr->vio_bus->bus.children, sibling) {
-            if (qdev->info == &spapr_vty.qdev) {
-                return DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
-            }
-        }
+        return spapr_vty_get_default(spapr->vio_bus);
     }
 
     return sdev;
commit 05c194384f836240ea4c2da5fa3be43a54bff021
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Dec 12 18:24:32 2011 +0000

    pseries: Emit device tree nodes in reg order
    
    Although in theory the device tree has no inherent ordering, in practice
    the order of nodes in the device tree does effect the order that devices
    are detected by software.
    
    Currently the ordering is determined by the order the devices appear on
    the QEMU command line. Although that does give the user control over the
    ordering, it is fragile, especially when the user does not generate the
    command line manually - eg. when using libvirt etc.
    
    So order the device tree based on the reg value, ie. the address of on
    the VIO bus of the devices. This gives us a sane and stable ordering.
    
    Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>
    
    [agraf] add braces

diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 5a35541..2cce421 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -736,21 +736,61 @@ static void spapr_vio_register_devices(void)
 device_init(spapr_vio_register_devices)
 
 #ifdef CONFIG_FDT
+static int compare_reg(const void *p1, const void *p2)
+{
+    VIOsPAPRDevice const *dev1, *dev2;
+
+    dev1 = (VIOsPAPRDevice *)*(DeviceState **)p1;
+    dev2 = (VIOsPAPRDevice *)*(DeviceState **)p2;
+
+    if (dev1->reg < dev2->reg) {
+        return -1;
+    }
+    if (dev1->reg == dev2->reg) {
+        return 0;
+    }
+
+    /* dev1->reg > dev2->reg */
+    return 1;
+}
+
 int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt)
 {
-    DeviceState *qdev;
-    int ret = 0;
+    DeviceState *qdev, **qdevs;
+    int i, num, ret = 0;
 
+    /* Count qdevs on the bus list */
+    num = 0;
     QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
-        VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
+        num++;
+    }
+
+    /* Copy out into an array of pointers */
+    qdevs = g_malloc(sizeof(qdev) * num);
+    num = 0;
+    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
+        qdevs[num++] = qdev;
+    }
+
+    /* Sort the array */
+    qsort(qdevs, num, sizeof(qdev), compare_reg);
+
+    /* Hack alert. Give the devices to libfdt in reverse order, we happen
+     * to know that will mean they are in forward order in the tree. */
+    for (i = num - 1; i >= 0; i--) {
+        VIOsPAPRDevice *dev = (VIOsPAPRDevice *)(qdevs[i]);
 
         ret = vio_make_devnode(dev, fdt);
 
         if (ret < 0) {
-            return ret;
+            goto out;
         }
     }
 
-    return 0;
+    ret = 0;
+out:
+    free(qdevs);
+
+    return ret;
 }
 #endif /* CONFIG_FDT */
commit 6e806cc38bb1a79ec52d7d86da4aca11cdc302c8
Author: Bharata B Rao <bharata at linux.vnet.ibm.com>
Date:   Mon Dec 12 18:24:30 2011 +0000

    pseries: FDT NUMA extensions to support multi-node guests
    
    Add NUMA specific properties to guest's device tree to boot a multi-node
    guests. This patch adds the following properties:
    
    ibm,associativity
    ibm,architecture-vec-5
    ibm,associativity-reference-points
    
    With this, it becomes possible to use -numa option on pseries targets.
    
    Signed-off-by: Bharata B Rao <bharata 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/hw/spapr.c b/hw/spapr.c
index 2b901f1..1883270 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -97,6 +97,44 @@ qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num)
     return qirq;
 }
 
+static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr)
+{
+    int ret = 0, offset;
+    CPUState *env;
+    char cpu_model[32];
+    int smt = kvmppc_smt_threads();
+
+    assert(spapr->cpu_model);
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        uint32_t associativity[] = {cpu_to_be32(0x5),
+                                    cpu_to_be32(0x0),
+                                    cpu_to_be32(0x0),
+                                    cpu_to_be32(0x0),
+                                    cpu_to_be32(env->numa_node),
+                                    cpu_to_be32(env->cpu_index)};
+
+        if ((env->cpu_index % smt) != 0) {
+            continue;
+        }
+
+        snprintf(cpu_model, 32, "/cpus/%s@%x", spapr->cpu_model,
+                 env->cpu_index);
+
+        offset = fdt_path_offset(fdt, cpu_model);
+        if (offset < 0) {
+            return offset;
+        }
+
+        ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity,
+                          sizeof(associativity));
+        if (ret < 0) {
+            return ret;
+        }
+    }
+    return ret;
+}
+
 static void *spapr_create_fdt_skel(const char *cpu_model,
                                    target_phys_addr_t rma_size,
                                    target_phys_addr_t initrd_base,
@@ -107,9 +145,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
 {
     void *fdt;
     CPUState *env;
-    uint64_t mem_reg_property_rma[] = { 0, cpu_to_be64(rma_size) };
-    uint64_t mem_reg_property_nonrma[] = { cpu_to_be64(rma_size),
-                                           cpu_to_be64(ram_size - rma_size) };
+    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);
     uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
@@ -119,6 +155,13 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
     int i;
     char *modelname;
     int smt = kvmppc_smt_threads();
+    unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
+    uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
+    uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0),
+                                cpu_to_be32(0x0), cpu_to_be32(0x0),
+                                cpu_to_be32(0x0)};
+    char mem_name[32];
+    target_phys_addr_t node0_size, mem_start;
 
 #define _FDT(exp) \
     do { \
@@ -146,6 +189,9 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
     /* /chosen */
     _FDT((fdt_begin_node(fdt, "chosen")));
 
+    /* Set Form1_affinity */
+    _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
+
     _FDT((fdt_property_string(fdt, "bootargs", kernel_cmdline)));
     _FDT((fdt_property(fdt, "linux,initrd-start",
                        &start_prop, sizeof(start_prop))));
@@ -164,24 +210,54 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
     _FDT((fdt_end_node(fdt)));
 
     /* memory node(s) */
-    _FDT((fdt_begin_node(fdt, "memory at 0")));
+    node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size;
+    if (rma_size > node0_size) {
+        rma_size = node0_size;
+    }
 
+    /* RMA */
+    mem_reg_property[0] = 0;
+    mem_reg_property[1] = cpu_to_be64(rma_size);
+    _FDT((fdt_begin_node(fdt, "memory at 0")));
     _FDT((fdt_property_string(fdt, "device_type", "memory")));
-    _FDT((fdt_property(fdt, "reg", mem_reg_property_rma,
-                       sizeof(mem_reg_property_rma))));
+    _FDT((fdt_property(fdt, "reg", mem_reg_property,
+        sizeof(mem_reg_property))));
+    _FDT((fdt_property(fdt, "ibm,associativity", associativity,
+        sizeof(associativity))));
     _FDT((fdt_end_node(fdt)));
 
-    if (ram_size > rma_size) {
-        char mem_name[32];
+    /* RAM: Node 0 */
+    if (node0_size > rma_size) {
+        mem_reg_property[0] = cpu_to_be64(rma_size);
+        mem_reg_property[1] = cpu_to_be64(node0_size - rma_size);
 
-        sprintf(mem_name, "memory@%" PRIx64, (uint64_t)rma_size);
+        sprintf(mem_name, "memory@" TARGET_FMT_lx, rma_size);
         _FDT((fdt_begin_node(fdt, mem_name)));
         _FDT((fdt_property_string(fdt, "device_type", "memory")));
-        _FDT((fdt_property(fdt, "reg", mem_reg_property_nonrma,
-                           sizeof(mem_reg_property_nonrma))));
+        _FDT((fdt_property(fdt, "reg", mem_reg_property,
+                           sizeof(mem_reg_property))));
+        _FDT((fdt_property(fdt, "ibm,associativity", associativity,
+                           sizeof(associativity))));
         _FDT((fdt_end_node(fdt)));
     }
 
+    /* RAM: Node 1 and beyond */
+    mem_start = node0_size;
+    for (i = 1; i < nb_numa_nodes; i++) {
+        mem_reg_property[0] = cpu_to_be64(mem_start);
+        mem_reg_property[1] = cpu_to_be64(node_mem[i]);
+        associativity[3] = associativity[4] = cpu_to_be32(i);
+        sprintf(mem_name, "memory@" TARGET_FMT_lx, mem_start);
+        _FDT((fdt_begin_node(fdt, mem_name)));
+        _FDT((fdt_property_string(fdt, "device_type", "memory")));
+        _FDT((fdt_property(fdt, "reg", mem_reg_property,
+            sizeof(mem_reg_property))));
+        _FDT((fdt_property(fdt, "ibm,associativity", associativity,
+            sizeof(associativity))));
+        _FDT((fdt_end_node(fdt)));
+        mem_start += node_mem[i];
+    }
+
     /* cpus */
     _FDT((fdt_begin_node(fdt, "cpus")));
 
@@ -194,6 +270,9 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
         modelname[i] = toupper(modelname[i]);
     }
 
+    /* This is needed during FDT finalization */
+    spapr->cpu_model = g_strdup(modelname);
+
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         int index = env->cpu_index;
         uint32_t servers_prop[smp_threads];
@@ -280,6 +359,9 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
     _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas_prop,
                        sizeof(hypertas_prop))));
 
+    _FDT((fdt_property(fdt, "ibm,associativity-reference-points",
+        refpoints, sizeof(refpoints))));
+
     _FDT((fdt_end_node(fdt)));
 
     /* interrupt controller */
@@ -351,6 +433,14 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
         fprintf(stderr, "Couldn't set up RTAS device tree properties\n");
     }
 
+    /* Advertise NUMA via ibm,associativity */
+    if (nb_numa_nodes > 1) {
+        ret = spapr_set_associativity(fdt, spapr);
+        if (ret < 0) {
+            fprintf(stderr, "Couldn't set up NUMA device tree properties\n");
+        }
+    }
+
     _FDT((fdt_pack(fdt)));
 
     cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
diff --git a/hw/spapr.h b/hw/spapr.h
index d624841..e946a34 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -21,6 +21,7 @@ typedef struct sPAPREnvironment {
     target_ulong entry_point;
     int next_irq;
     int rtc_offset;
+    char *cpu_model;
 } sPAPREnvironment;
 
 #define H_SUCCESS         0
commit 1fc02533e73ad66f756f07efdf80fa9bef5afbc8
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Dec 12 18:24:28 2011 +0000

    pseries: Remove hcalls callback
    
    For forgotten historical reasons, PAPR hypercalls for specific virtual IO
    devices (oh which there are quite a number) are registered via a callback
    in the VIOsPAPRDeviceInfo structure.
    
    This is kind of ugly, so this patch instead registers hypercalls from
    device_init() functions for each device type.  This works just as well,
    and is cleaner.
    
    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_llan.c b/hw/spapr_llan.c
index abe1297..45674c4 100644
--- a/hw/spapr_llan.c
+++ b/hw/spapr_llan.c
@@ -474,16 +474,6 @@ static target_ulong h_multicast_ctrl(CPUState *env, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
-static void vlan_hcalls(VIOsPAPRBus *bus)
-{
-    spapr_register_hypercall(H_REGISTER_LOGICAL_LAN, h_register_logical_lan);
-    spapr_register_hypercall(H_FREE_LOGICAL_LAN, h_free_logical_lan);
-    spapr_register_hypercall(H_SEND_LOGICAL_LAN, h_send_logical_lan);
-    spapr_register_hypercall(H_ADD_LOGICAL_LAN_BUFFER,
-                             h_add_logical_lan_buffer);
-    spapr_register_hypercall(H_MULTICAST_CTRL, h_multicast_ctrl);
-}
-
 static VIOsPAPRDeviceInfo spapr_vlan = {
     .init = spapr_vlan_init,
     .devnode = spapr_vlan_devnode,
@@ -491,7 +481,6 @@ static VIOsPAPRDeviceInfo spapr_vlan = {
     .dt_type = "network",
     .dt_compatible = "IBM,l-lan",
     .signal_mask = 0x1,
-    .hcalls = vlan_hcalls,
     .qdev.name = "spapr-vlan",
     .qdev.size = sizeof(VIOsPAPRVLANDevice),
     .qdev.props = (Property[]) {
@@ -504,5 +493,11 @@ static VIOsPAPRDeviceInfo spapr_vlan = {
 static void spapr_vlan_register(void)
 {
     spapr_vio_bus_register_withprop(&spapr_vlan);
+    spapr_register_hypercall(H_REGISTER_LOGICAL_LAN, h_register_logical_lan);
+    spapr_register_hypercall(H_FREE_LOGICAL_LAN, h_free_logical_lan);
+    spapr_register_hypercall(H_SEND_LOGICAL_LAN, h_send_logical_lan);
+    spapr_register_hypercall(H_ADD_LOGICAL_LAN_BUFFER,
+                             h_add_logical_lan_buffer);
+    spapr_register_hypercall(H_MULTICAST_CTRL, h_multicast_ctrl);
 }
 device_init(spapr_vlan_register);
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 2dcc036..5a35541 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -684,7 +684,6 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
     VIOsPAPRBus *bus;
     BusState *qbus;
     DeviceState *dev;
-    DeviceInfo *qinfo;
 
     /* Create bridge device */
     dev = qdev_create(NULL, "spapr-vio-bridge");
@@ -711,18 +710,6 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
     spapr_rtas_register("ibm,set-tce-bypass", rtas_set_tce_bypass);
     spapr_rtas_register("quiesce", rtas_quiesce);
 
-    for (qinfo = device_info_list; qinfo; qinfo = qinfo->next) {
-        VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
-
-        if (qinfo->bus_info != &spapr_vio_bus_info) {
-            continue;
-        }
-
-        if (info->hcalls) {
-            info->hcalls(bus);
-        }
-    }
-
     return bus;
 }
 
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index a325a5f..2430d45 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -75,7 +75,6 @@ typedef struct {
     const char *dt_name, *dt_type, *dt_compatible;
     target_ulong signal_mask;
     int (*init)(VIOsPAPRDevice *dev);
-    void (*hcalls)(VIOsPAPRBus *bus);
     int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
 } VIOsPAPRDeviceInfo;
 
diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
index f23cc36..e217314 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -135,18 +135,11 @@ void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev)
     qdev_init_nofail(dev);
 }
 
-static void vty_hcalls(VIOsPAPRBus *bus)
-{
-    spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
-    spapr_register_hypercall(H_GET_TERM_CHAR, h_get_term_char);
-}
-
 static VIOsPAPRDeviceInfo spapr_vty = {
     .init = spapr_vty_init,
     .dt_name = "vty",
     .dt_type = "serial",
     .dt_compatible = "hvterm1",
-    .hcalls = vty_hcalls,
     .qdev.name = "spapr-vty",
     .qdev.size = sizeof(VIOsPAPRVTYDevice),
     .qdev.props = (Property[]) {
@@ -182,5 +175,7 @@ static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
 static void spapr_vty_register(void)
 {
     spapr_vio_bus_register_withprop(&spapr_vty);
+    spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
+    spapr_register_hypercall(H_GET_TERM_CHAR, h_get_term_char);
 }
 device_init(spapr_vty_register);
commit 157feeadbaec09fe4dca539a24f6f6d327d6eeb6
Author: Liu Yu-B13201 <Yu.Liu at freescale.com>
Date:   Mon Nov 28 20:41:18 2011 +0000

    kvm-ppc: halt secondary cpus when guest reset
    
    When guest reset, we need to halt secondary cpus until guest kick them.
    This already works for tcg. The patch add the support for kvm.
    
    Signed-off-by: Liu Yu <yu.liu at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>
    [agraf: remove in-kernel irqchip code]

diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c
index df74953..e7b1453 100644
--- a/hw/ppce500_spin.c
+++ b/hw/ppce500_spin.c
@@ -112,6 +112,7 @@ static void spin_kick(void *data)
 
     env->halted = 0;
     env->exception_index = -1;
+    env->stopped = 0;
     qemu_cpu_kick(env);
 }
 
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 429349f..9b2e605 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -504,7 +504,7 @@ void kvm_arch_post_run(CPUState *env, struct kvm_run *run)
 
 int kvm_arch_process_async_events(CPUState *env)
 {
-    return 0;
+    return env->halted;
 }
 
 static int kvmppc_handle_halt(CPUState *env)
commit 33bcd98c4e9fe0866807bef6253a057c82087539
Author: Alexander Graf <agraf at suse.de>
Date:   Fri Nov 18 16:41:59 2011 +0100

    console: Fix segfault on screendump without VGA adapter
    
    When trying to create a screen dump without having any VGA adapter
    inside the guest, QEMU segfaults.
    
    This is because it's trying to switch back to the "previous" screen
    it was on before dumping the VGA screen. Unfortunately, in my case
    there simply is no previous screen so it accesses a NULL pointer.
    
    Fix it by checking if previous_active_console is actually available.
    
    This is 1.0 material.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/console.c b/console.c
index 223f8fd..135394f 100644
--- a/console.c
+++ b/console.c
@@ -186,7 +186,9 @@ void vga_hw_screen_dump(const char *filename)
         consoles[0]->hw_screen_dump(consoles[0]->hw, filename);
     }
 
-    console_select(previous_active_console->index);
+    if (previous_active_console) {
+        console_select(previous_active_console->index);
+    }
 }
 
 void vga_hw_text_update(console_ch_t *chardata)
commit 4e9200a0a0f89ad2b26f6aa42e1fca16b364a8c8
Author: Nishanth Aravamudan <nacc at us.ibm.com>
Date:   Tue Nov 1 09:57:52 2011 +0000

    PPC: monitor: add ability to dump SLB entries
    
    When run with a PPC Book3S (server) CPU Currently 'info tlb' in the
    qemu monitor reports "dump_mmu: unimplemented".  However, during
    bringup work, it can be quite handy to have the SLB entries, which are
    available in the CPUPPCState.  This patch adds an implementation of
    info tlb for book3s, which dumps the SLB.
    
    Signed-off-by: Nishanth Aravamudan <nacc at us.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/helper.c b/target-ppc/helper.c
index 137a494..5847453 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -1545,12 +1545,40 @@ 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)
+{
+    int i;
+    uint64_t slbe, slbv;
+
+    cpu_synchronize_state(env);
+
+    cpu_fprintf(f, "SLB\tESID\t\t\tVSID\n");
+    for (i = 0; i < env->slb_nr; i++) {
+        slbe = env->slb[i].esid;
+        slbv = env->slb[i].vsid;
+        if (slbe == 0 && slbv == 0) {
+            continue;
+        }
+        cpu_fprintf(f, "%d\t0x%016" PRIx64 "\t0x%016" PRIx64 "\n",
+                    i, slbe, slbv);
+    }
+}
+#endif
+
 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
 {
     switch (env->mmu_model) {
     case POWERPC_MMU_BOOKE206:
         mmubooke206_dump_mmu(f, cpu_fprintf, env);
         break;
+#if defined(TARGET_PPC64)
+    case POWERPC_MMU_64B:
+    case POWERPC_MMU_2_06:
+        mmubooks_dump_mmu(f, cpu_fprintf, env);
+        break;
+#endif
     default:
         cpu_fprintf(f, "%s: unimplemented\n", __func__);
     }
commit ed8e5a85a1741147ce06932b478a509ce3407061
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Thu Dec 29 13:47:43 2011 +0100

    virtio-console: Fix failure on unconnected pty
    
    when I tried qemu with -virtio-console pty the guest hangs and attaching
    on /dev/pts/<x> does not return anything if the attachment is too late.
    
    This results in pty_chr_write() returning 0, which causes the port to
    get throttled. This results in the guest getting frozen as the
    guest->host virtio_console writes don't return until the host releases
    the vq element back to the guest.
    
    For the virtio-serial use case we don't want to lose data but for the
    console case we better drop data instead of "killing" the guest
    console. If we get chardev->frontend notification and a better behaving
    virtio-console we can revert this fix.
    
    Signed-off-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index fe0233f..3a9004a 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -163,7 +163,19 @@ static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
                 abort();
             }
             if (ret == -EAGAIN || (ret >= 0 && ret < buf_size)) {
-                virtio_serial_throttle_port(port, true);
+		/*
+                 * this is a temporary check until chardevs can signal to
+                 * frontends that they are writable again. This prevents
+                 * the console from going into throttled mode (forever)
+                 * if virtio-console is connected to a pty without a
+                 * listener. Otherwise the guest spins forever.
+                 * We can revert this if
+                 * 1: chardevs can notify frondends
+                 * 2: the guest driver does not spin in these cases
+                 */
+                if (!info->is_console) {
+                    virtio_serial_throttle_port(port, true);
+                }
                 port->iov_idx = i;
                 if (ret > 0) {
                     port->iov_offset += ret;
commit 8d3bc5178fbc06cdd89c064ae8f44e77c503e91e
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Dec 27 16:02:16 2011 +0200

    Fix qapi code generation wrt parallel build
    
    Make's multiple output syntax
    
      x.c x.h: x.template
           gen < x.template
    
    actually invokes the command once for x.c and once for x.h (with differing $@
    in each invocation).  During a parallel build, the two commands may be invoked
    in parallel; this opens up a race, where the second invocation trashes a file
    supposedly produced during the first, and now in use by a dependent command.
    
    The various qapi code generators are susceptible to this; fix by making them
    generate just one file per invocation.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index 368eeae..0838bc4 100644
--- a/Makefile
+++ b/Makefile
@@ -173,35 +173,37 @@ qapi-dir := $(BUILD_DIR)/qapi-generated
 test-qmp-input-visitor.o test-qmp-output-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
 
+gen-out-type = $(subst .,-,$@)
+
 $(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
 $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
 $(qapi-dir)/test-qapi-visit.c $(qapi-dir)/test-qapi-visit.h :\
 $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
 $(qapi-dir)/test-qmp-commands.h $(qapi-dir)/test-qmp-marshal.c :\
 $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
-	    $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
+	    $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
 
 $(qapi-dir)/qga-qapi-types.c $(qapi-dir)/qga-qapi-types.h :\
 $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-types.py
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py -o "$(qapi-dir)" -p "qga-" < $<, "  GEN   $@")
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "$(qapi-dir)" -p "qga-" < $<, "  GEN   $@")
 $(qapi-dir)/qga-qapi-visit.c $(qapi-dir)/qga-qapi-visit.h :\
 $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-visit.py
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "qga-" < $<, "  GEN   $@")
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "$(qapi-dir)" -p "qga-" < $<, "  GEN   $@")
 $(qapi-dir)/qga-qmp-commands.h $(qapi-dir)/qga-qmp-marshal.c :\
 $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-commands.py
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "qga-" < $<, "  GEN   $@")
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o "$(qapi-dir)" -p "qga-" < $<, "  GEN   $@")
 
 qapi-types.c qapi-types.h :\
 $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py -o "." < $<, "  GEN   $@")
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "." < $<, "  GEN   $@")
 qapi-visit.c qapi-visit.h :\
 $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py -o "."  < $<, "  GEN   $@")
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "."  < $<, "  GEN   $@")
 qmp-commands.h qmp-marshal.c :\
 $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -m -o "." < $<, "  GEN   $@")
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, "  GEN   $@")
 
 test-qmp-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
 test-qmp-output-visitor: test-qmp-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 54d1f5d..bd7b207 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -372,7 +372,9 @@ def gen_command_def_prologue(prefix="", proxy=False):
 
 
 try:
-    opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:m", ["prefix=", "output-dir=", "type=", "middle"])
+    opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:m",
+                                   ["source", "header", "prefix=",
+                                    "output-dir=", "type=", "middle"])
 except getopt.GetoptError, err:
     print str(err)
     sys.exit(1)
@@ -384,6 +386,9 @@ c_file = 'qmp-marshal.c'
 h_file = 'qmp-commands.h'
 middle_mode = False
 
+do_c = False
+do_h = False
+
 for o, a in opts:
     if o in ("-p", "--prefix"):
         prefix = a
@@ -393,10 +398,29 @@ for o, a in opts:
         dispatch_type = a
     elif o in ("-m", "--middle"):
         middle_mode = True
+    elif o in ("-c", "--source"):
+        do_h = True
+    elif o in ("-h", "--header"):
+        do_c = True
+
+if not do_c and not do_h:
+    do_c = True
+    do_h = True
 
 c_file = output_dir + prefix + c_file
 h_file = output_dir + prefix + h_file
 
+def maybe_open(really, name, opt):
+    class Null(object):
+        def write(self, str):
+            pass
+        def read(self):
+            return ''
+    if really:
+        return open(name, opt)
+    else:
+        return Null()
+
 try:
     os.makedirs(output_dir)
 except os.error, e:
@@ -408,8 +432,8 @@ commands = filter(lambda expr: expr.has_key('command'), exprs)
 commands = filter(lambda expr: not expr.has_key('gen'), commands)
 
 if dispatch_type == "sync":
-    fdecl = open(h_file, 'w')
-    fdef = open(c_file, 'w')
+    fdecl = maybe_open(do_h, h_file, 'w')
+    fdef = maybe_open(do_c, c_file, 'w')
     ret = gen_command_decl_prologue(header=basename(h_file), guard=guardname(h_file), prefix=prefix)
     fdecl.write(ret)
     ret = gen_command_def_prologue(prefix=prefix)
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 267cb49..ae644bc 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -163,7 +163,8 @@ void qapi_free_%(type)s(%(c_type)s obj)
 
 
 try:
-    opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:", ["prefix=", "output-dir="])
+    opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:",
+                                   ["source", "header", "prefix=", "output-dir="])
 except getopt.GetoptError, err:
     print str(err)
     sys.exit(1)
@@ -173,11 +174,22 @@ prefix = ""
 c_file = 'qapi-types.c'
 h_file = 'qapi-types.h'
 
+do_c = False
+do_h = False
+
 for o, a in opts:
     if o in ("-p", "--prefix"):
         prefix = a
     elif o in ("-o", "--output-dir"):
         output_dir = a + "/"
+    elif o in ("-c", "--source"):
+        do_h = True
+    elif o in ("-h", "--header"):
+        do_c = True
+
+if not do_c and not do_h:
+    do_c = True
+    do_h = True
 
 c_file = output_dir + prefix + c_file
 h_file = output_dir + prefix + h_file
@@ -188,8 +200,17 @@ except os.error, e:
     if e.errno != errno.EEXIST:
         raise
 
-fdef = open(c_file, 'w')
-fdecl = open(h_file, 'w')
+def maybe_open(really, name, opt):
+    class Null(object):
+        def write(self, str):
+            pass
+        def read(self):
+            return ''
+    if really:
+        return open(name, opt)
+
+fdef = maybe_open(do_c, c_file, 'w')
+fdecl = maybe_open(do_h, h_file, 'w')
 
 fdef.write(mcgen('''
 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 62de83d..e9d0584 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -139,7 +139,8 @@ void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **e
                 name=name)
 
 try:
-    opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:", ["prefix=", "output-dir="])
+    opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:",
+                                   ["source", "header", "prefix=", "output-dir="])
 except getopt.GetoptError, err:
     print str(err)
     sys.exit(1)
@@ -149,11 +150,22 @@ prefix = ""
 c_file = 'qapi-visit.c'
 h_file = 'qapi-visit.h'
 
+do_c = False
+do_h = False
+
 for o, a in opts:
     if o in ("-p", "--prefix"):
         prefix = a
     elif o in ("-o", "--output-dir"):
         output_dir = a + "/"
+    elif o in ("-c", "--source"):
+        do_h = True
+    elif o in ("-h", "--header"):
+        do_c = True
+
+if not do_c and not do_h:
+    do_c = True
+    do_h = True
 
 c_file = output_dir + prefix + c_file
 h_file = output_dir + prefix + h_file
@@ -164,8 +176,17 @@ except os.error, e:
     if e.errno != errno.EEXIST:
         raise
 
-fdef = open(c_file, 'w')
-fdecl = open(h_file, 'w')
+def maybe_open(really, name, opt):
+    class Null(object):
+        def write(self, str):
+            pass
+        def read(self):
+            return ''
+    if really:
+        return open(name, opt)
+
+fdef = maybe_open(do_c, c_file, 'w')
+fdecl = maybe_open(do_h, h_file, 'w')
 
 fdef.write(mcgen('''
 /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
commit 4e1ea514f9b9f07358b84554dc3d35f533ec3971
Merge: ebdfc3c... 058a96e...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Dec 27 08:53:35 2011 -0600

    Merge remote-tracking branch 'aneesh/for-upstream' into staging
    
    * aneesh/for-upstream:
      scripts/analyse-9p-simpletrace.py:	Add symbolic names for 9p operations.
      hw/9pfs: iattr_valid flags are kernel internal flags map them to 9p values.
      hw/9pfs: Use the correct signed type for different variables
      hw/9pfs: replace iovec manipulation with QEMUIOVector

commit ebdfc3c83cef33f8f619ffcb57d297c6063db59d
Merge: a0fa820... 44f76b2...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Dec 27 08:52:42 2011 -0600

    Merge remote-tracking branch 'bonzini/nbd-for-anthony' into staging
    
    * bonzini/nbd-for-anthony: (26 commits)
      nbd: add myself as maintainer
      qemu-nbd: throttle requests
      qemu-nbd: asynchronous operation
      qemu-nbd: add client pointer to NBDRequest
      qemu-nbd: move client handling to nbd.c
      qemu-nbd: use common main loop
      link the main loop and its dependencies into the tools
      qemu-nbd: introduce NBDRequest
      qemu-nbd: introduce NBDExport
      qemu-nbd: introduce nbd_do_receive_request
      qemu-nbd: more robust handling of invalid requests
      qemu-nbd: introduce nbd_do_send_reply
      qemu-nbd: simplify nbd_trip
      move corking functions to osdep.c
      qemu-nbd: remove data_size argument to nbd_trip
      qemu-nbd: remove offset argument to nbd_trip
      Update ioctl order in nbd_init() to detect EBUSY
      nbd: add support for NBD_CMD_TRIM
      nbd: add support for NBD_CMD_FLUSH
      nbd: add support for NBD_CMD_FLAG_FUA
      ...

commit a0fa82085e175bf8ce6d69a3f83695f81af2a649
Author: Gleb Natapov <gleb at redhat.com>
Date:   Thu Dec 15 12:44:05 2011 +0200

    enable architectural PMU cpuid leaf for kvm
    
    Signed-off-by: Gleb Natapov <gleb at redhat.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 0b3af90..91a104b 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -1180,10 +1180,19 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         break;
     case 0xA:
         /* Architectural Performance Monitoring Leaf */
-        *eax = 0;
-        *ebx = 0;
-        *ecx = 0;
-        *edx = 0;
+        if (kvm_enabled()) {
+            KVMState *s = env->kvm_state;
+
+            *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX);
+            *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX);
+            *ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX);
+            *edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX);
+        } else {
+            *eax = 0;
+            *ebx = 0;
+            *ecx = 0;
+            *edx = 0;
+        }
         break;
     case 0xD:
         /* Processor Extended State */
commit 991dfefdee8f4d1405f4b3cd799e7579f54b6c9f
Author: Vasilis Liaskovitis <vasilis.liaskovitis at profitbricks.com>
Date:   Wed Oct 26 14:19:00 2011 +0200

    Set numa topology for max_cpus
    
    qemu-kvm passes numa/SRAT topology information for smp_cpus to SeaBIOS. However
    SeaBIOS always expects to setup max_cpus number of SRAT cpu entries
    (MaxCountCPUs variable in build_srat function of Seabios). When qemu-kvm runs
    with smp_cpus != max_cpus (e.g. -smp 2,maxcpus=4), Seabios will mistakenly use
    memory SRAT info for setting up CPU SRAT entries for the offline CPUs. Wrong
    SRAT memory entries are also created. This breaks NUMA in a guest.
    Fix by setting up SRAT info for max_cpus in qemu-kvm.
    
    Signed-off-by: Vasilis Liaskovitis <vasilis.liaskovitis at profitbricks.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/hw/pc.c b/hw/pc.c
index 3a71992..f51afa8 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -624,9 +624,9 @@ static void *bochs_bios_init(void)
      * of nodes, one word for each VCPU->node and one word for each node to
      * hold the amount of memory.
      */
-    numa_fw_cfg = g_malloc0((1 + smp_cpus + nb_numa_nodes) * 8);
+    numa_fw_cfg = g_malloc0((1 + max_cpus + nb_numa_nodes) * 8);
     numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes);
-    for (i = 0; i < smp_cpus; i++) {
+    for (i = 0; i < max_cpus; i++) {
         for (j = 0; j < nb_numa_nodes; j++) {
             if (node_cpumask[j] & (1 << i)) {
                 numa_fw_cfg[i + 1] = cpu_to_le64(j);
@@ -635,10 +635,10 @@ static void *bochs_bios_init(void)
         }
     }
     for (i = 0; i < nb_numa_nodes; i++) {
-        numa_fw_cfg[smp_cpus + 1 + i] = cpu_to_le64(node_mem[i]);
+        numa_fw_cfg[max_cpus + 1 + i] = cpu_to_le64(node_mem[i]);
     }
     fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, (uint8_t *)numa_fw_cfg,
-                     (1 + smp_cpus + nb_numa_nodes) * 8);
+                     (1 + max_cpus + nb_numa_nodes) * 8);
 
     return fw_cfg;
 }
diff --git a/vl.c b/vl.c
index c03abb6..d925424 100644
--- a/vl.c
+++ b/vl.c
@@ -3305,7 +3305,7 @@ int main(int argc, char **argv, char **envp)
          * real machines which also use this scheme.
          */
         if (i == nb_numa_nodes) {
-            for (i = 0; i < smp_cpus; i++) {
+            for (i = 0; i < max_cpus; i++) {
                 node_cpumask[i % nb_numa_nodes] |= 1 << i;
             }
         }
commit cce47516cddfb886da9a03cb9db355958b890dce
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Oct 26 13:09:45 2011 +0200

    kvm: x86: Drop redundant apic base and tpr update from kvm_get_sregs
    
    The latter was already commented out, the former is redundant as well.
    We always get the latest changes after return from the guest via
    kvm_arch_post_run.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 06f4401..d206852 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1082,10 +1082,9 @@ static int kvm_get_sregs(CPUState *env)
     env->cr[3] = sregs.cr3;
     env->cr[4] = sregs.cr4;
 
-    cpu_set_apic_base(env->apic_state, sregs.apic_base);
-
     env->efer = sregs.efer;
-    //cpu_set_apic_tpr(env->apic_state, sregs.cr8);
+
+    /* changes to apic base and cr8/tpr are read back via kvm_arch_post_run */
 
 #define HFLAG_COPY_MASK \
     ~( HF_CPL_MASK | HF_PE_MASK | HF_MP_MASK | HF_EM_MASK | \
commit fabacc0f79ccfe9b8b34e6b9ed35ffd17415c918
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Thu Oct 27 19:25:58 2011 +0200

    kvm: x86: Avoid runtime allocation of xsave buffer
    
    Keep a per-VCPU xsave buffer for kvm_put/get_xsave instead of
    continuously allocating and freeing it on state sync.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index a08ce9d..37dde79 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -751,7 +751,8 @@ typedef struct CPUX86State {
     uint32_t cpuid_svm_features;
     bool tsc_valid;
     int tsc_khz;
-    
+    void *kvm_xsave_buf;
+
     /* in order to simplify APIC support, we leave this pointer to the
        user */
     struct DeviceState *apic_state;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index d2f70f9..06f4401 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -516,6 +516,10 @@ int kvm_arch_init_vcpu(CPUState *env)
         }
     }
 
+    if (kvm_has_xsave()) {
+        env->kvm_xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave));
+    }
+
     return 0;
 }
 
@@ -771,15 +775,14 @@ static int kvm_put_fpu(CPUState *env)
 
 static int kvm_put_xsave(CPUState *env)
 {
-    int i, r;
-    struct kvm_xsave* xsave;
+    struct kvm_xsave* xsave = env->kvm_xsave_buf;
     uint16_t cwd, swd, twd;
+    int i, r;
 
     if (!kvm_has_xsave()) {
         return kvm_put_fpu(env);
     }
 
-    xsave = qemu_memalign(4096, sizeof(struct kvm_xsave));
     memset(xsave, 0, sizeof(struct kvm_xsave));
     twd = 0;
     swd = env->fpus & ~(7 << 11);
@@ -801,7 +804,6 @@ static int kvm_put_xsave(CPUState *env)
     memcpy(&xsave->region[XSAVE_YMMH_SPACE], env->ymmh_regs,
             sizeof env->ymmh_regs);
     r = kvm_vcpu_ioctl(env, KVM_SET_XSAVE, xsave);
-    g_free(xsave);
     return r;
 }
 
@@ -978,7 +980,7 @@ static int kvm_get_fpu(CPUState *env)
 
 static int kvm_get_xsave(CPUState *env)
 {
-    struct kvm_xsave* xsave;
+    struct kvm_xsave* xsave = env->kvm_xsave_buf;
     int ret, i;
     uint16_t cwd, swd, twd;
 
@@ -986,10 +988,8 @@ static int kvm_get_xsave(CPUState *env)
         return kvm_get_fpu(env);
     }
 
-    xsave = qemu_memalign(4096, sizeof(struct kvm_xsave));
     ret = kvm_vcpu_ioctl(env, KVM_GET_XSAVE, xsave);
     if (ret < 0) {
-        g_free(xsave);
         return ret;
     }
 
@@ -1013,7 +1013,6 @@ static int kvm_get_xsave(CPUState *env)
     env->xstate_bv = *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV];
     memcpy(env->ymmh_regs, &xsave->region[XSAVE_YMMH_SPACE],
             sizeof env->ymmh_regs);
-    g_free(xsave);
     return 0;
 }
 
commit 6b42494b219a3beb755bc52419c731aa70efe93d
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Thu Oct 27 19:26:02 2011 +0200

    kvm: x86: Use symbols for all xsave field
    
    Field 0 (FCW+FSW) and 1 (FTW+FOP) were hard-coded so far.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 5bfc21f..d2f70f9 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -759,6 +759,8 @@ static int kvm_put_fpu(CPUState *env)
     return kvm_vcpu_ioctl(env, KVM_SET_FPU, &fpu);
 }
 
+#define XSAVE_FCW_FSW     0
+#define XSAVE_FTW_FOP     1
 #define XSAVE_CWD_RIP     2
 #define XSAVE_CWD_RDP     4
 #define XSAVE_MXCSR       6
@@ -786,8 +788,8 @@ static int kvm_put_xsave(CPUState *env)
     for (i = 0; i < 8; ++i) {
         twd |= (!env->fptags[i]) << i;
     }
-    xsave->region[0] = (uint32_t)(swd << 16) + cwd;
-    xsave->region[1] = (uint32_t)(env->fpop << 16) + twd;
+    xsave->region[XSAVE_FCW_FSW] = (uint32_t)(swd << 16) + cwd;
+    xsave->region[XSAVE_FTW_FOP] = (uint32_t)(env->fpop << 16) + twd;
     memcpy(&xsave->region[XSAVE_CWD_RIP], &env->fpip, sizeof(env->fpip));
     memcpy(&xsave->region[XSAVE_CWD_RDP], &env->fpdp, sizeof(env->fpdp));
     memcpy(&xsave->region[XSAVE_ST_SPACE], env->fpregs,
@@ -991,10 +993,10 @@ static int kvm_get_xsave(CPUState *env)
         return ret;
     }
 
-    cwd = (uint16_t)xsave->region[0];
-    swd = (uint16_t)(xsave->region[0] >> 16);
-    twd = (uint16_t)xsave->region[1];
-    env->fpop = (uint16_t)(xsave->region[1] >> 16);
+    cwd = (uint16_t)xsave->region[XSAVE_FCW_FSW];
+    swd = (uint16_t)(xsave->region[XSAVE_FCW_FSW] >> 16);
+    twd = (uint16_t)xsave->region[XSAVE_FTW_FOP];
+    env->fpop = (uint16_t)(xsave->region[XSAVE_FTW_FOP] >> 16);
     env->fpstt = (swd >> 11) & 7;
     env->fpus = swd;
     env->fpuc = cwd;
commit 44f76b289a33399abedfbca2d92d21d910792264
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Dec 22 11:39:19 2011 +0100

    nbd: add myself as maintainer
    
    Not planning to do much else, hence listing it as "Odd Fixes".
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/MAINTAINERS b/MAINTAINERS
index e22bfa1..764c92d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -473,6 +473,13 @@ M: Mark McLoughlin <markmc at redhat.com>
 S: Maintained
 F: net/
 
+Network Block Device (NBD)
+M: Paolo Bonzini <pbonzini at redhat.com>
+S: Odd Fixes
+F: block/nbd.c
+F: nbd.*
+F: qemu-nbd.c
+
 SLIRP
 M: Jan Kiszka <jan.kiszka at siemens.com>
 S: Maintained
commit 41996e3803119541d43bfa59060024a22b803342
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 19 15:25:40 2011 +0200

    qemu-nbd: throttle requests
    
    Limiting the number of in-flight requests is implemented very simply
    with a can_read callback.  It does not require a semaphore, unlike the
    client side in block/nbd.c, because we can throttle directly the creation
    of coroutines.  The client side can have a coroutine created at any time
    when an I/O request is made.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/nbd.c b/nbd.c
index 6d7d1f8..567e94e 100644
--- a/nbd.c
+++ b/nbd.c
@@ -587,6 +587,8 @@ static int nbd_send_reply(int csock, struct nbd_reply *reply)
     return 0;
 }
 
+#define MAX_NBD_REQUESTS 16
+
 typedef struct NBDRequest NBDRequest;
 
 struct NBDRequest {
@@ -614,6 +616,8 @@ struct NBDClient {
 
     CoMutex send_lock;
     Coroutine *send_coroutine;
+
+    int nb_requests;
 };
 
 static void nbd_client_get(NBDClient *client)
@@ -644,6 +648,9 @@ static NBDRequest *nbd_request_get(NBDClient *client)
     NBDRequest *req;
     NBDExport *exp = client->exp;
 
+    assert(client->nb_requests <= MAX_NBD_REQUESTS - 1);
+    client->nb_requests++;
+
     if (QSIMPLEQ_EMPTY(&exp->requests)) {
         req = g_malloc0(sizeof(NBDRequest));
         req->data = qemu_blockalign(exp->bs, NBD_BUFFER_SIZE);
@@ -660,6 +667,9 @@ static void nbd_request_put(NBDRequest *req)
 {
     NBDClient *client = req->client;
     QSIMPLEQ_INSERT_HEAD(&client->exp->requests, req, entry);
+    if (client->nb_requests-- == MAX_NBD_REQUESTS) {
+        qemu_notify_event();
+    }
     nbd_client_put(client);
 }
 
@@ -688,6 +698,7 @@ void nbd_export_close(NBDExport *exp)
     g_free(exp);
 }
 
+static int nbd_can_read(void *opaque);
 static void nbd_read(void *opaque);
 static void nbd_restart_write(void *opaque);
 
@@ -699,7 +710,8 @@ static int nbd_co_send_reply(NBDRequest *req, struct nbd_reply *reply,
     int rc, ret;
 
     qemu_co_mutex_lock(&client->send_lock);
-    qemu_set_fd_handler2(csock, NULL, nbd_read, nbd_restart_write, client);
+    qemu_set_fd_handler2(csock, nbd_can_read, nbd_read,
+                         nbd_restart_write, client);
     client->send_coroutine = qemu_coroutine_self();
 
     if (!len) {
@@ -724,7 +736,7 @@ static int nbd_co_send_reply(NBDRequest *req, struct nbd_reply *reply,
     }
 
     client->send_coroutine = NULL;
-    qemu_set_fd_handler2(csock, NULL, nbd_read, NULL, client);
+    qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, NULL, client);
     qemu_co_mutex_unlock(&client->send_lock);
     return rc;
 }
@@ -900,6 +912,13 @@ out:
     nbd_client_close(client);
 }
 
+static int nbd_can_read(void *opaque)
+{
+    NBDClient *client = opaque;
+
+    return client->recv_coroutine || client->nb_requests < MAX_NBD_REQUESTS;
+}
+
 static void nbd_read(void *opaque)
 {
     NBDClient *client = opaque;
@@ -931,6 +950,6 @@ NBDClient *nbd_client_new(NBDExport *exp, int csock,
     client->sock = csock;
     client->close = close;
     qemu_co_mutex_init(&client->send_lock);
-    qemu_set_fd_handler2(csock, NULL, nbd_read, NULL, client);
+    qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, NULL, client);
     return client;
 }
commit 262db38871b9a2613761cc5f05c4cf697e246a68
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 19 15:19:27 2011 +0200

    qemu-nbd: asynchronous operation
    
    Using coroutines enable asynchronous operation on both the network and
    the block side.  Network can be owned by two coroutines at the same time,
    one writing and one reading.  On the send side, mutual exclusion is
    guaranteed by a CoMutex.  On the receive side, mutual exclusion is
    guaranteed because new coroutines immediately start receiving data,
    and no new coroutines are created as long as the previous one is receiving.
    
    Between receive and send, qemu-nbd can have an arbitrary number of
    in-flight block transfers.  Throttling is implemented by the next
    patch.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/nbd.c b/nbd.c
index ca18c10..6d7d1f8 100644
--- a/nbd.c
+++ b/nbd.c
@@ -20,6 +20,8 @@
 #include "block.h"
 #include "block_int.h"
 
+#include "qemu-coroutine.h"
+
 #include <errno.h>
 #include <string.h>
 #ifndef _WIN32
@@ -607,6 +609,11 @@ struct NBDClient {
 
     NBDExport *exp;
     int sock;
+
+    Coroutine *recv_coroutine;
+
+    CoMutex send_lock;
+    Coroutine *send_coroutine;
 };
 
 static void nbd_client_get(NBDClient *client)
@@ -681,13 +688,20 @@ void nbd_export_close(NBDExport *exp)
     g_free(exp);
 }
 
-static int nbd_do_send_reply(NBDRequest *req, struct nbd_reply *reply,
+static void nbd_read(void *opaque);
+static void nbd_restart_write(void *opaque);
+
+static int nbd_co_send_reply(NBDRequest *req, struct nbd_reply *reply,
                              int len)
 {
     NBDClient *client = req->client;
     int csock = client->sock;
     int rc, ret;
 
+    qemu_co_mutex_lock(&client->send_lock);
+    qemu_set_fd_handler2(csock, NULL, nbd_read, nbd_restart_write, client);
+    client->send_coroutine = qemu_coroutine_self();
+
     if (!len) {
         rc = nbd_send_reply(csock, reply);
         if (rc == -1) {
@@ -697,7 +711,7 @@ static int nbd_do_send_reply(NBDRequest *req, struct nbd_reply *reply,
         socket_set_cork(csock, 1);
         rc = nbd_send_reply(csock, reply);
         if (rc != -1) {
-            ret = write_sync(csock, req->data, len);
+            ret = qemu_co_send(csock, req->data, len);
             if (ret != len) {
                 errno = EIO;
                 rc = -1;
@@ -708,15 +722,20 @@ static int nbd_do_send_reply(NBDRequest *req, struct nbd_reply *reply,
         }
         socket_set_cork(csock, 0);
     }
+
+    client->send_coroutine = NULL;
+    qemu_set_fd_handler2(csock, NULL, nbd_read, NULL, client);
+    qemu_co_mutex_unlock(&client->send_lock);
     return rc;
 }
 
-static int nbd_do_receive_request(NBDRequest *req, struct nbd_request *request)
+static int nbd_co_receive_request(NBDRequest *req, struct nbd_request *request)
 {
     NBDClient *client = req->client;
     int csock = client->sock;
     int rc;
 
+    client->recv_coroutine = qemu_coroutine_self();
     if (nbd_receive_request(csock, request) == -1) {
         rc = -EIO;
         goto out;
@@ -741,7 +760,7 @@ static int nbd_do_receive_request(NBDRequest *req, struct nbd_request *request)
     if ((request->type & NBD_CMD_MASK_COMMAND) == NBD_CMD_WRITE) {
         TRACE("Reading %u byte(s)", request->len);
 
-        if (read_sync(csock, req->data, request->len) != request->len) {
+        if (qemu_co_recv(csock, req->data, request->len) != request->len) {
             LOG("reading from socket failed");
             rc = -EIO;
             goto out;
@@ -750,21 +769,22 @@ static int nbd_do_receive_request(NBDRequest *req, struct nbd_request *request)
     rc = 0;
 
 out:
+    client->recv_coroutine = NULL;
     return rc;
 }
 
-static int nbd_trip(NBDClient *client)
+static void nbd_trip(void *opaque)
 {
+    NBDClient *client = opaque;
     NBDRequest *req = nbd_request_get(client);
     NBDExport *exp = client->exp;
     struct nbd_request request;
     struct nbd_reply reply;
-    int rc = -1;
     int ret;
 
     TRACE("Reading request.");
 
-    ret = nbd_do_receive_request(req, &request);
+    ret = nbd_co_receive_request(req, &request);
     if (ret == -EIO) {
         goto out;
     }
@@ -799,7 +819,7 @@ static int nbd_trip(NBDClient *client)
         }
 
         TRACE("Read %u byte(s)", request.len);
-        if (nbd_do_send_reply(req, &reply, request.len) < 0)
+        if (nbd_co_send_reply(req, &reply, request.len) < 0)
             goto out;
         break;
     case NBD_CMD_WRITE:
@@ -822,7 +842,7 @@ static int nbd_trip(NBDClient *client)
         }
 
         if (request.type & NBD_CMD_FLAG_FUA) {
-            ret = bdrv_flush(exp->bs);
+            ret = bdrv_co_flush(exp->bs);
             if (ret < 0) {
                 LOG("flush failed");
                 reply.error = -ret;
@@ -830,34 +850,34 @@ static int nbd_trip(NBDClient *client)
             }
         }
 
-        if (nbd_do_send_reply(req, &reply, 0) < 0)
+        if (nbd_co_send_reply(req, &reply, 0) < 0)
             goto out;
         break;
     case NBD_CMD_DISC:
         TRACE("Request type is DISCONNECT");
         errno = 0;
-        return 1;
+        goto out;
     case NBD_CMD_FLUSH:
         TRACE("Request type is FLUSH");
 
-        ret = bdrv_flush(exp->bs);
+        ret = bdrv_co_flush(exp->bs);
         if (ret < 0) {
             LOG("flush failed");
             reply.error = -ret;
         }
 
-        if (nbd_do_send_reply(req, &reply, 0) < 0)
+        if (nbd_co_send_reply(req, &reply, 0) < 0)
             goto out;
         break;
     case NBD_CMD_TRIM:
         TRACE("Request type is TRIM");
-        ret = bdrv_discard(exp->bs, (request.from + exp->dev_offset) / 512,
-                           request.len / 512);
+        ret = bdrv_co_discard(exp->bs, (request.from + exp->dev_offset) / 512,
+                              request.len / 512);
         if (ret < 0) {
             LOG("discard failed");
             reply.error = -ret;
         }
-        if (nbd_do_send_reply(req, &reply, 0) < 0)
+        if (nbd_co_send_reply(req, &reply, 0) < 0)
             goto out;
         break;
     default:
@@ -865,28 +885,39 @@ static int nbd_trip(NBDClient *client)
     invalid_request:
         reply.error = -EINVAL;
     error_reply:
-        if (nbd_do_send_reply(req, &reply, 0) == -1)
+        if (nbd_co_send_reply(req, &reply, 0) == -1)
             goto out;
         break;
     }
 
     TRACE("Request/Reply complete");
 
-    rc = 0;
+    nbd_request_put(req);
+    return;
+
 out:
     nbd_request_put(req);
-    return rc;
+    nbd_client_close(client);
 }
 
 static void nbd_read(void *opaque)
 {
     NBDClient *client = opaque;
 
-    if (nbd_trip(client) != 0) {
-        nbd_client_close(client);
+    if (client->recv_coroutine) {
+        qemu_coroutine_enter(client->recv_coroutine, NULL);
+    } else {
+        qemu_coroutine_enter(qemu_coroutine_create(nbd_trip), client);
     }
 }
 
+static void nbd_restart_write(void *opaque)
+{
+    NBDClient *client = opaque;
+
+    qemu_coroutine_enter(client->send_coroutine, NULL);
+}
+
 NBDClient *nbd_client_new(NBDExport *exp, int csock,
                           void (*close)(NBDClient *))
 {
@@ -899,6 +930,7 @@ NBDClient *nbd_client_new(NBDExport *exp, int csock,
     client->exp = exp;
     client->sock = csock;
     client->close = close;
+    qemu_co_mutex_init(&client->send_lock);
     qemu_set_fd_handler2(csock, NULL, nbd_read, NULL, client);
     return client;
 }
commit 72deddc5e61e974fbf561dc704742f102b91de82
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Oct 7 16:47:56 2011 +0200

    qemu-nbd: add client pointer to NBDRequest
    
    By attaching a client to an NBDRequest, we can avoid passing around the
    socket descriptor and data buffer.
    
    Also, we can now manage the reference count for the client in
    nbd_request_get/put request instead of having to do it ourselved in
    nbd_read.  This simplifies things when coroutines are used.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/nbd.c b/nbd.c
index 4822843..ca18c10 100644
--- a/nbd.c
+++ b/nbd.c
@@ -589,6 +589,7 @@ typedef struct NBDRequest NBDRequest;
 
 struct NBDRequest {
     QSIMPLEQ_ENTRY(NBDRequest) entry;
+    NBDClient *client;
     uint8_t *data;
 };
 
@@ -631,9 +632,11 @@ static void nbd_client_close(NBDClient *client)
     nbd_client_put(client);
 }
 
-static NBDRequest *nbd_request_get(NBDExport *exp)
+static NBDRequest *nbd_request_get(NBDClient *client)
 {
     NBDRequest *req;
+    NBDExport *exp = client->exp;
+
     if (QSIMPLEQ_EMPTY(&exp->requests)) {
         req = g_malloc0(sizeof(NBDRequest));
         req->data = qemu_blockalign(exp->bs, NBD_BUFFER_SIZE);
@@ -641,12 +644,16 @@ static NBDRequest *nbd_request_get(NBDExport *exp)
         req = QSIMPLEQ_FIRST(&exp->requests);
         QSIMPLEQ_REMOVE_HEAD(&exp->requests, entry);
     }
+    nbd_client_get(client);
+    req->client = client;
     return req;
 }
 
-static void nbd_request_put(NBDExport *exp, NBDRequest *req)
+static void nbd_request_put(NBDRequest *req)
 {
-    QSIMPLEQ_INSERT_HEAD(&exp->requests, req, entry);
+    NBDClient *client = req->client;
+    QSIMPLEQ_INSERT_HEAD(&client->exp->requests, req, entry);
+    nbd_client_put(client);
 }
 
 NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset,
@@ -674,9 +681,11 @@ void nbd_export_close(NBDExport *exp)
     g_free(exp);
 }
 
-static int nbd_do_send_reply(int csock, struct nbd_reply *reply,
-                             uint8_t *data, int len)
+static int nbd_do_send_reply(NBDRequest *req, struct nbd_reply *reply,
+                             int len)
 {
+    NBDClient *client = req->client;
+    int csock = client->sock;
     int rc, ret;
 
     if (!len) {
@@ -688,7 +697,7 @@ static int nbd_do_send_reply(int csock, struct nbd_reply *reply,
         socket_set_cork(csock, 1);
         rc = nbd_send_reply(csock, reply);
         if (rc != -1) {
-            ret = write_sync(csock, data, len);
+            ret = write_sync(csock, req->data, len);
             if (ret != len) {
                 errno = EIO;
                 rc = -1;
@@ -702,9 +711,10 @@ static int nbd_do_send_reply(int csock, struct nbd_reply *reply,
     return rc;
 }
 
-static int nbd_do_receive_request(int csock, struct nbd_request *request,
-                                  uint8_t *data)
+static int nbd_do_receive_request(NBDRequest *req, struct nbd_request *request)
 {
+    NBDClient *client = req->client;
+    int csock = client->sock;
     int rc;
 
     if (nbd_receive_request(csock, request) == -1) {
@@ -731,7 +741,7 @@ static int nbd_do_receive_request(int csock, struct nbd_request *request,
     if ((request->type & NBD_CMD_MASK_COMMAND) == NBD_CMD_WRITE) {
         TRACE("Reading %u byte(s)", request->len);
 
-        if (read_sync(csock, data, request->len) != request->len) {
+        if (read_sync(csock, req->data, request->len) != request->len) {
             LOG("reading from socket failed");
             rc = -EIO;
             goto out;
@@ -745,9 +755,8 @@ out:
 
 static int nbd_trip(NBDClient *client)
 {
+    NBDRequest *req = nbd_request_get(client);
     NBDExport *exp = client->exp;
-    NBDRequest *req = nbd_request_get(exp);
-    int csock = client->sock;
     struct nbd_request request;
     struct nbd_reply reply;
     int rc = -1;
@@ -755,7 +764,7 @@ static int nbd_trip(NBDClient *client)
 
     TRACE("Reading request.");
 
-    ret = nbd_do_receive_request(csock, &request, req->data);
+    ret = nbd_do_receive_request(req, &request);
     if (ret == -EIO) {
         goto out;
     }
@@ -790,7 +799,7 @@ static int nbd_trip(NBDClient *client)
         }
 
         TRACE("Read %u byte(s)", request.len);
-        if (nbd_do_send_reply(csock, &reply, req->data, request.len) < 0)
+        if (nbd_do_send_reply(req, &reply, request.len) < 0)
             goto out;
         break;
     case NBD_CMD_WRITE:
@@ -821,7 +830,7 @@ static int nbd_trip(NBDClient *client)
             }
         }
 
-        if (nbd_do_send_reply(csock, &reply, NULL, 0) < 0)
+        if (nbd_do_send_reply(req, &reply, 0) < 0)
             goto out;
         break;
     case NBD_CMD_DISC:
@@ -837,7 +846,7 @@ static int nbd_trip(NBDClient *client)
             reply.error = -ret;
         }
 
-        if (nbd_do_send_reply(csock, &reply, NULL, 0) < 0)
+        if (nbd_do_send_reply(req, &reply, 0) < 0)
             goto out;
         break;
     case NBD_CMD_TRIM:
@@ -848,7 +857,7 @@ static int nbd_trip(NBDClient *client)
             LOG("discard failed");
             reply.error = -ret;
         }
-        if (nbd_do_send_reply(csock, &reply, NULL, 0) < 0)
+        if (nbd_do_send_reply(req, &reply, 0) < 0)
             goto out;
         break;
     default:
@@ -856,7 +865,7 @@ static int nbd_trip(NBDClient *client)
     invalid_request:
         reply.error = -EINVAL;
     error_reply:
-        if (nbd_do_send_reply(csock, &reply, NULL, 0) == -1)
+        if (nbd_do_send_reply(req, &reply, 0) == -1)
             goto out;
         break;
     }
@@ -865,7 +874,7 @@ static int nbd_trip(NBDClient *client)
 
     rc = 0;
 out:
-    nbd_request_put(exp, req);
+    nbd_request_put(req);
     return rc;
 }
 
@@ -873,12 +882,9 @@ static void nbd_read(void *opaque)
 {
     NBDClient *client = opaque;
 
-    nbd_client_get(client);
     if (nbd_trip(client) != 0) {
         nbd_client_close(client);
     }
-
-    nbd_client_put(client);
 }
 
 NBDClient *nbd_client_new(NBDExport *exp, int csock,
commit 1743b515860ef645b285908ee367c5e343e0020c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 19 14:33:23 2011 +0200

    qemu-nbd: move client handling to nbd.c
    
    This patch sets up the fd handler in nbd.c instead of qemu-nbd.c.  It
    introduces NBDClient, which wraps the arguments to nbd_trip in a single
    structure, so that we can add a notifier to it.  This way, qemu-nbd can
    know about disconnections.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/nbd.c b/nbd.c
index 82eb98d..4822843 100644
--- a/nbd.c
+++ b/nbd.c
@@ -600,6 +600,37 @@ struct NBDExport {
     QSIMPLEQ_HEAD(, NBDRequest) requests;
 };
 
+struct NBDClient {
+    int refcount;
+    void (*close)(NBDClient *client);
+
+    NBDExport *exp;
+    int sock;
+};
+
+static void nbd_client_get(NBDClient *client)
+{
+    client->refcount++;
+}
+
+static void nbd_client_put(NBDClient *client)
+{
+    if (--client->refcount == 0) {
+        g_free(client);
+    }
+}
+
+static void nbd_client_close(NBDClient *client)
+{
+    qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL);
+    close(client->sock);
+    client->sock = -1;
+    if (client->close) {
+        client->close(client);
+    }
+    nbd_client_put(client);
+}
+
 static NBDRequest *nbd_request_get(NBDExport *exp)
 {
     NBDRequest *req;
@@ -712,9 +743,11 @@ out:
     return rc;
 }
 
-int nbd_trip(NBDExport *exp, int csock)
+static int nbd_trip(NBDClient *client)
 {
+    NBDExport *exp = client->exp;
     NBDRequest *req = nbd_request_get(exp);
+    int csock = client->sock;
     struct nbd_request request;
     struct nbd_reply reply;
     int rc = -1;
@@ -836,7 +869,30 @@ out:
     return rc;
 }
 
-int nbd_negotiate(NBDExport *exp, int csock)
+static void nbd_read(void *opaque)
+{
+    NBDClient *client = opaque;
+
+    nbd_client_get(client);
+    if (nbd_trip(client) != 0) {
+        nbd_client_close(client);
+    }
+
+    nbd_client_put(client);
+}
+
+NBDClient *nbd_client_new(NBDExport *exp, int csock,
+                          void (*close)(NBDClient *))
 {
-    return nbd_send_negotiate(csock, exp->size, exp->nbdflags);
+    NBDClient *client;
+    if (nbd_send_negotiate(csock, exp->size, exp->nbdflags) == -1) {
+        return NULL;
+    }
+    client = g_malloc0(sizeof(NBDClient));
+    client->refcount = 1;
+    client->exp = exp;
+    client->sock = csock;
+    client->close = close;
+    qemu_set_fd_handler2(csock, NULL, nbd_read, NULL, client);
+    return client;
 }
diff --git a/nbd.h b/nbd.h
index c77c2fd..a8382f0 100644
--- a/nbd.h
+++ b/nbd.h
@@ -76,11 +76,12 @@ int nbd_client(int fd);
 int nbd_disconnect(int fd);
 
 typedef struct NBDExport NBDExport;
+typedef struct NBDClient NBDClient;
 
 NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset,
                           off_t size, uint32_t nbdflags);
 void nbd_export_close(NBDExport *exp);
-int nbd_negotiate(NBDExport *exp, int csock);
-int nbd_trip(NBDExport *exp, int csock);
+NBDClient *nbd_client_new(NBDExport *exp, int csock,
+                          void (*close)(NBDClient *));
 
 #endif
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 347c776..155b058 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -249,15 +249,10 @@ static int nbd_can_accept(void *opaque)
     return nb_fds < shared;
 }
 
-static void nbd_read(void *opaque)
+static void nbd_client_closed(NBDClient *client)
 {
-    int fd = (uintptr_t) opaque;
-
-    if (nbd_trip(exp, fd) != 0) {
-        qemu_set_fd_handler2(fd, NULL, NULL, NULL, NULL);
-        close(fd);
-        nb_fds--;
-    }
+    nb_fds--;
+    qemu_notify_event();
 }
 
 static void nbd_accept(void *opaque)
@@ -268,8 +263,7 @@ static void nbd_accept(void *opaque)
 
     int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
     nbd_started = true;
-    if (fd != -1 && nbd_negotiate(exp, fd) != -1) {
-        qemu_set_fd_handler2(fd, NULL, nbd_read, NULL, (void *) (intptr_t) fd);
+    if (fd != -1 && nbd_client_new(exp, fd, nbd_client_closed)) {
         nb_fds++;
     }
 }
commit a61c67828dea7c64edaf226cadb45b4ffcc1d411
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 12 17:28:11 2011 +0200

    qemu-nbd: use common main loop
    
    Using a single main loop for sockets will help yielding from the socket
    coroutine back to the main loop, and later reentering it.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/qemu-nbd.c b/qemu-nbd.c
index d5ac75e..347c776 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -35,12 +35,15 @@
 
 #define SOCKET_PATH    "/var/lock/qemu-nbd-%s"
 
-static int sigterm_wfd;
 static NBDExport *exp;
 static int verbose;
 static char *device;
 static char *srcpath;
 static char *sockpath;
+static bool sigterm_reported;
+static bool nbd_started;
+static int shared = 1;
+static int nb_fds;
 
 static void usage(const char *name)
 {
@@ -169,10 +172,8 @@ static int find_partition(BlockDriverState *bs, int partition,
 
 static void termsig_handler(int signum)
 {
-    static int sigterm_reported;
-    if (!sigterm_reported) {
-        sigterm_reported = (write(sigterm_wfd, "", 1) == 1);
-    }
+    sigterm_reported = true;
+    qemu_notify_event();
 }
 
 static void *show_parts(void *arg)
@@ -243,6 +244,36 @@ out:
     return (void *) EXIT_FAILURE;
 }
 
+static int nbd_can_accept(void *opaque)
+{
+    return nb_fds < shared;
+}
+
+static void nbd_read(void *opaque)
+{
+    int fd = (uintptr_t) opaque;
+
+    if (nbd_trip(exp, fd) != 0) {
+        qemu_set_fd_handler2(fd, NULL, NULL, NULL, NULL);
+        close(fd);
+        nb_fds--;
+    }
+}
+
+static void nbd_accept(void *opaque)
+{
+    int server_fd = (uintptr_t) opaque;
+    struct sockaddr_in addr;
+    socklen_t addr_len = sizeof(addr);
+
+    int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
+    nbd_started = true;
+    if (fd != -1 && nbd_negotiate(exp, fd) != -1) {
+        qemu_set_fd_handler2(fd, NULL, nbd_read, NULL, (void *) (intptr_t) fd);
+        nb_fds++;
+    }
+}
+
 int main(int argc, char **argv)
 {
     BlockDriverState *bs;
@@ -251,8 +282,6 @@ int main(int argc, char **argv)
     bool disconnect = false;
     const char *bindto = "0.0.0.0";
     int port = NBD_DEFAULT_PORT;
-    struct sockaddr_in addr;
-    socklen_t addr_len = sizeof(addr);
     off_t fd_size;
     const char *sopt = "hVb:o:p:rsnP:c:dvk:e:t";
     struct option lopt[] = {
@@ -280,13 +309,7 @@ int main(int argc, char **argv)
     int flags = BDRV_O_RDWR;
     int partition = -1;
     int ret;
-    int shared = 1;
-    fd_set fds;
-    int *sharing_fds;
     int fd;
-    int i;
-    int nb_fds = 0;
-    int max_fd;
     int persistent = 0;
     pthread_t client_thread;
 
@@ -294,12 +317,6 @@ int main(int argc, char **argv)
      * handler ensures that "qemu-nbd -v -c" exits with a nice status code.
      */
     struct sigaction sa_sigterm;
-    int sigterm_fd[2];
-    if (qemu_pipe(sigterm_fd) == -1) {
-        err(EXIT_FAILURE, "Error setting up communication pipe");
-    }
-
-    sigterm_wfd = sigterm_fd[1];
     memset(&sa_sigterm, 0, sizeof(sa_sigterm));
     sa_sigterm.sa_handler = termsig_handler;
     sigaction(SIGTERM, &sa_sigterm, NULL);
@@ -490,16 +507,16 @@ int main(int argc, char **argv)
     }
 
     exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags);
-    sharing_fds = g_malloc((shared + 1) * sizeof(int));
 
     if (sockpath) {
-        sharing_fds[0] = unix_socket_incoming(sockpath);
+        fd = unix_socket_incoming(sockpath);
     } else {
-        sharing_fds[0] = tcp_socket_incoming(bindto, port);
+        fd = tcp_socket_incoming(bindto, port);
     }
 
-    if (sharing_fds[0] == -1)
+    if (fd == -1) {
         return 1;
+    }
 
     if (device) {
         int ret;
@@ -514,54 +531,15 @@ int main(int argc, char **argv)
         memset(&client_thread, 0, sizeof(client_thread));
     }
 
-    max_fd = sharing_fds[0];
-    nb_fds++;
+    qemu_init_main_loop();
+    qemu_set_fd_handler2(fd, nbd_can_accept, nbd_accept, NULL,
+                         (void *)(uintptr_t)fd);
 
     do {
-        FD_ZERO(&fds);
-        FD_SET(sigterm_fd[0], &fds);
-        for (i = 0; i < nb_fds; i++)
-            FD_SET(sharing_fds[i], &fds);
-
-        do {
-            ret = select(max_fd + 1, &fds, NULL, NULL, NULL);
-        } while (ret == -1 && errno == EINTR);
-        if (ret == -1 || FD_ISSET(sigterm_fd[0], &fds)) {
-            break;
-        }
-
-        if (FD_ISSET(sharing_fds[0], &fds))
-            ret--;
-        for (i = 1; i < nb_fds && ret; i++) {
-            if (FD_ISSET(sharing_fds[i], &fds)) {
-                if (nbd_trip(exp, sharing_fds[i]) != 0) {
-                    close(sharing_fds[i]);
-                    nb_fds--;
-                    sharing_fds[i] = sharing_fds[nb_fds];
-                    i--;
-                }
-                ret--;
-            }
-        }
-        /* new connection ? */
-        if (FD_ISSET(sharing_fds[0], &fds)) {
-            if (nb_fds < shared + 1) {
-                sharing_fds[nb_fds] = accept(sharing_fds[0],
-                                             (struct sockaddr *)&addr,
-                                             &addr_len);
-                if (sharing_fds[nb_fds] != -1 &&
-                    nbd_negotiate(exp, sharing_fds[nb_fds]) != -1) {
-                        if (sharing_fds[nb_fds] > max_fd)
-                            max_fd = sharing_fds[nb_fds];
-                        nb_fds++;
-                }
-            }
-        }
-    } while (persistent || nb_fds > 1);
+        main_loop_wait(false);
+    } while (!sigterm_reported && (persistent || !nbd_started || nb_fds > 0));
 
-    close(sharing_fds[0]);
     nbd_export_close(exp);
-    g_free(sharing_fds);
     if (sockpath) {
         unlink(sockpath);
     }
commit cbcfa0418f0c196afa765f5c9837b9344d1adcf3
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 12 16:20:11 2011 +0200

    link the main loop and its dependencies into the tools
    
    Using the main loop code from QEMU enables tools to operate fully
    asynchronously.  Advantages include better Windows portability (for some
    definition of portability) over glib's.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile b/Makefile
index 2c03055..368eeae 100644
--- a/Makefile
+++ b/Makefile
@@ -147,8 +147,9 @@ endif
 qemu-img.o: qemu-img-cmds.h
 qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o cmd.o qemu-ga.o: $(GENERATED_HEADERS)
 
-tools-obj-y = qemu-tool.o $(oslib-obj-y) $(trace-obj-y) \
-	qemu-timer-common.o cutils.o
+tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \
+	qemu-timer-common.o main-loop.o notify.o iohandler.o cutils.o async.o
+tools-obj-$(CONFIG_POSIX) += compatfd.o
 
 qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
 qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
diff --git a/main-loop.h b/main-loop.h
index 876092d..f971013 100644
--- a/main-loop.h
+++ b/main-loop.h
@@ -324,6 +324,9 @@ int qemu_add_child_watch(pid_t pid);
  * by threads other than the main loop thread when calling
  * qemu_bh_new(), qemu_set_fd_handler() and basically all other
  * functions documented in this file.
+ *
+ * NOTE: tools currently are single-threaded and qemu_mutex_lock_iothread
+ * is a no-op there.
  */
 void qemu_mutex_lock_iothread(void);
 
@@ -336,6 +339,9 @@ void qemu_mutex_lock_iothread(void);
  * as soon as possible by threads other than the main loop thread,
  * because it prevents the main loop from processing callbacks,
  * including timers and bottom halves.
+ *
+ * NOTE: tools currently are single-threaded and qemu_mutex_unlock_iothread
+ * is a no-op there.
  */
 void qemu_mutex_unlock_iothread(void);
 
diff --git a/os-posix.c b/os-posix.c
index dc4a6bb..5c437ca 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -42,11 +42,6 @@
 
 #ifdef CONFIG_LINUX
 #include <sys/prctl.h>
-#include <sys/syscall.h>
-#endif
-
-#ifdef CONFIG_EVENTFD
-#include <sys/eventfd.h>
 #endif
 
 static struct passwd *user_pwd;
@@ -333,34 +328,6 @@ void os_set_line_buffering(void)
     setvbuf(stdout, NULL, _IOLBF, 0);
 }
 
-/*
- * Creates an eventfd that looks like a pipe and has EFD_CLOEXEC set.
- */
-int qemu_eventfd(int fds[2])
-{
-#ifdef CONFIG_EVENTFD
-    int ret;
-
-    ret = eventfd(0, 0);
-    if (ret >= 0) {
-        fds[0] = ret;
-        qemu_set_cloexec(ret);
-        if ((fds[1] = dup(ret)) == -1) {
-            close(ret);
-            return -1;
-        }
-        qemu_set_cloexec(fds[1]);
-        return 0;
-    }
-
-    if (errno != ENOSYS) {
-        return -1;
-    }
-#endif
-
-    return qemu_pipe(fds);
-}
-
 int qemu_create_pidfile(const char *filename)
 {
     char buffer[128];
@@ -384,12 +351,3 @@ int qemu_create_pidfile(const char *filename)
     close(fd);
     return 0;
 }
-
-int qemu_get_thread_id(void)
-{
-#if defined (__linux__)
-    return syscall(SYS_gettid);
-#else
-    return getpid();
-#endif
-}
diff --git a/os-win32.c b/os-win32.c
index 8523d8d..ad76370 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -151,8 +151,3 @@ int qemu_create_pidfile(const char *filename)
     }
     return 0;
 }
-
-int qemu_get_thread_id(void)
-{
-    return GetCurrentThreadId();
-}
diff --git a/oslib-posix.c b/oslib-posix.c
index ce75549..b6a3c7f 100644
--- a/oslib-posix.c
+++ b/oslib-posix.c
@@ -55,6 +55,21 @@ static int running_on_valgrind = -1;
 #else
 #  define running_on_valgrind 0
 #endif
+#ifdef CONFIG_LINUX
+#include <sys/syscall.h>
+#endif
+#ifdef CONFIG_EVENTFD
+#include <sys/eventfd.h>
+#endif
+
+int qemu_get_thread_id(void)
+{
+#if defined(__linux__)
+    return syscall(SYS_gettid);
+#else
+    return getpid();
+#endif
+}
 
 int qemu_daemon(int nochdir, int noclose)
 {
@@ -162,6 +177,34 @@ int qemu_pipe(int pipefd[2])
     return ret;
 }
 
+/*
+ * Creates an eventfd that looks like a pipe and has EFD_CLOEXEC set.
+ */
+int qemu_eventfd(int fds[2])
+{
+#ifdef CONFIG_EVENTFD
+    int ret;
+
+    ret = eventfd(0, 0);
+    if (ret >= 0) {
+        fds[0] = ret;
+        fds[1] = dup(ret);
+        if (fds[1] == -1) {
+            close(ret);
+            return -1;
+        }
+        qemu_set_cloexec(ret);
+        qemu_set_cloexec(fds[1]);
+        return 0;
+    }
+    if (errno != ENOSYS) {
+        return -1;
+    }
+#endif
+
+    return qemu_pipe(fds);
+}
+
 int qemu_utimens(const char *path, const struct timespec *times)
 {
     struct timeval tv[2], tv_now;
diff --git a/oslib-win32.c b/oslib-win32.c
index 5e3de7d..ce3021e 100644
--- a/oslib-win32.c
+++ b/oslib-win32.c
@@ -118,3 +118,8 @@ int qemu_gettimeofday(qemu_timeval *tp)
      Do not set errno on error.  */
   return 0;
 }
+
+int qemu_get_thread_id(void)
+{
+    return GetCurrentThreadId();
+}
diff --git a/qemu-tool.c b/qemu-tool.c
index 5df7279..226b6e8 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -16,12 +16,12 @@
 #include "qemu-timer.h"
 #include "qemu-log.h"
 #include "migration.h"
+#include "main-loop.h"
+#include "qemu_socket.h"
+#include "slirp/libslirp.h"
 
 #include <sys/time.h>
 
-QEMUClock *rt_clock;
-QEMUClock *vm_clock;
-
 FILE *logfile;
 
 struct QEMUBH
@@ -57,41 +57,45 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
 {
 }
 
-int qemu_set_fd_handler2(int fd,
-                         IOCanReadHandler *fd_read_poll,
-                         IOHandler *fd_read,
-                         IOHandler *fd_write,
-                         void *opaque)
+int64 cpu_get_clock(void)
 {
-    return 0;
+    abort();
 }
 
-void qemu_notify_event(void)
+int64 cpu_get_icount(void)
 {
+    abort();
 }
 
-QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
-                          QEMUTimerCB *cb, void *opaque)
+void qemu_mutex_lock_iothread(void)
 {
-    return g_malloc(1);
 }
 
-void qemu_free_timer(QEMUTimer *ts)
+void qemu_mutex_unlock_iothread(void)
 {
-    g_free(ts);
 }
 
-void qemu_del_timer(QEMUTimer *ts)
+int use_icount;
+
+void qemu_clock_warp(QEMUClock *clock)
 {
 }
 
-void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
+static void __attribute__((constructor)) init_main_loop(void)
 {
+    init_clocks();
+    init_timer_alarm();
+    qemu_clock_enable(vm_clock, false);
 }
 
-int64_t qemu_get_clock_ns(QEMUClock *clock)
+void slirp_select_fill(int *pnfds, fd_set *readfds,
+                       fd_set *writefds, fd_set *xfds)
+{
+}
+
+void slirp_select_poll(fd_set *readfds, fd_set *writefds,
+                       fd_set *xfds, int select_error)
 {
-    return 0;
 }
 
 void migrate_add_blocker(Error *reason)
commit d9a73806585fd89f75f0c411839151863dac7f61
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 19 14:18:33 2011 +0200

    qemu-nbd: introduce NBDRequest
    
    Move the buffer from NBDExport to a new structure, so that it will be
    possible to have multiple in-flight requests for the same export
    (and for the same client too---we get that for free).
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/nbd.c b/nbd.c
index 8d2a3bc..82eb98d 100644
--- a/nbd.c
+++ b/nbd.c
@@ -36,6 +36,7 @@
 #endif
 
 #include "qemu_socket.h"
+#include "qemu-queue.h"
 
 //#define DEBUG_NBD
 
@@ -584,29 +585,60 @@ static int nbd_send_reply(int csock, struct nbd_reply *reply)
     return 0;
 }
 
+typedef struct NBDRequest NBDRequest;
+
+struct NBDRequest {
+    QSIMPLEQ_ENTRY(NBDRequest) entry;
+    uint8_t *data;
+};
+
 struct NBDExport {
     BlockDriverState *bs;
     off_t dev_offset;
     off_t size;
-    uint8_t *data;
     uint32_t nbdflags;
+    QSIMPLEQ_HEAD(, NBDRequest) requests;
 };
 
+static NBDRequest *nbd_request_get(NBDExport *exp)
+{
+    NBDRequest *req;
+    if (QSIMPLEQ_EMPTY(&exp->requests)) {
+        req = g_malloc0(sizeof(NBDRequest));
+        req->data = qemu_blockalign(exp->bs, NBD_BUFFER_SIZE);
+    } else {
+        req = QSIMPLEQ_FIRST(&exp->requests);
+        QSIMPLEQ_REMOVE_HEAD(&exp->requests, entry);
+    }
+    return req;
+}
+
+static void nbd_request_put(NBDExport *exp, NBDRequest *req)
+{
+    QSIMPLEQ_INSERT_HEAD(&exp->requests, req, entry);
+}
+
 NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset,
                           off_t size, uint32_t nbdflags)
 {
     NBDExport *exp = g_malloc0(sizeof(NBDExport));
+    QSIMPLEQ_INIT(&exp->requests);
     exp->bs = bs;
     exp->dev_offset = dev_offset;
     exp->nbdflags = nbdflags;
     exp->size = size == -1 ? exp->bs->total_sectors * 512 : size;
-    exp->data = qemu_blockalign(exp->bs, NBD_BUFFER_SIZE);
     return exp;
 }
 
 void nbd_export_close(NBDExport *exp)
 {
-    qemu_vfree(exp->data);
+    while (!QSIMPLEQ_EMPTY(&exp->requests)) {
+        NBDRequest *first = QSIMPLEQ_FIRST(&exp->requests);
+        QSIMPLEQ_REMOVE_HEAD(&exp->requests, entry);
+        qemu_vfree(first->data);
+        g_free(first);
+    }
+
     bdrv_close(exp->bs);
     g_free(exp);
 }
@@ -682,15 +714,17 @@ out:
 
 int nbd_trip(NBDExport *exp, int csock)
 {
+    NBDRequest *req = nbd_request_get(exp);
     struct nbd_request request;
     struct nbd_reply reply;
+    int rc = -1;
     int ret;
 
     TRACE("Reading request.");
 
-    ret = nbd_do_receive_request(csock, &request, exp->data);
+    ret = nbd_do_receive_request(csock, &request, req->data);
     if (ret == -EIO) {
-        return -1;
+        goto out;
     }
 
     reply.handle = request.handle;
@@ -715,7 +749,7 @@ int nbd_trip(NBDExport *exp, int csock)
         TRACE("Request type is READ");
 
         ret = bdrv_read(exp->bs, (request.from + exp->dev_offset) / 512,
-                        exp->data, request.len / 512);
+                        req->data, request.len / 512);
         if (ret < 0) {
             LOG("reading from file failed");
             reply.error = -ret;
@@ -723,8 +757,8 @@ int nbd_trip(NBDExport *exp, int csock)
         }
 
         TRACE("Read %u byte(s)", request.len);
-        if (nbd_do_send_reply(csock, &reply, exp->data, request.len) < 0)
-            return -1;
+        if (nbd_do_send_reply(csock, &reply, req->data, request.len) < 0)
+            goto out;
         break;
     case NBD_CMD_WRITE:
         TRACE("Request type is WRITE");
@@ -738,7 +772,7 @@ int nbd_trip(NBDExport *exp, int csock)
         TRACE("Writing to device");
 
         ret = bdrv_write(exp->bs, (request.from + exp->dev_offset) / 512,
-                         exp->data, request.len / 512);
+                         req->data, request.len / 512);
         if (ret < 0) {
             LOG("writing to file failed");
             reply.error = -ret;
@@ -755,7 +789,7 @@ int nbd_trip(NBDExport *exp, int csock)
         }
 
         if (nbd_do_send_reply(csock, &reply, NULL, 0) < 0)
-            return -1;
+            goto out;
         break;
     case NBD_CMD_DISC:
         TRACE("Request type is DISCONNECT");
@@ -771,7 +805,7 @@ int nbd_trip(NBDExport *exp, int csock)
         }
 
         if (nbd_do_send_reply(csock, &reply, NULL, 0) < 0)
-            return -1;
+            goto out;
         break;
     case NBD_CMD_TRIM:
         TRACE("Request type is TRIM");
@@ -782,7 +816,7 @@ int nbd_trip(NBDExport *exp, int csock)
             reply.error = -ret;
         }
         if (nbd_do_send_reply(csock, &reply, NULL, 0) < 0)
-            return -1;
+            goto out;
         break;
     default:
         LOG("invalid request type (%u) received", request.type);
@@ -790,13 +824,16 @@ int nbd_trip(NBDExport *exp, int csock)
         reply.error = -EINVAL;
     error_reply:
         if (nbd_do_send_reply(csock, &reply, NULL, 0) == -1)
-            return -1;
+            goto out;
         break;
     }
 
     TRACE("Request/Reply complete");
 
-    return 0;
+    rc = 0;
+out:
+    nbd_request_put(exp, req);
+    return rc;
 }
 
 int nbd_negotiate(NBDExport *exp, int csock)
commit af49bbbe78b16673cea13fea7f4d7d3433bf2646
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 19 14:03:37 2011 +0200

    qemu-nbd: introduce NBDExport
    
    Wrap the common parameters of nbd_trip and nbd_negotiate in a
    single opaque struct.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/nbd.c b/nbd.c
index 964a732..8d2a3bc 100644
--- a/nbd.c
+++ b/nbd.c
@@ -18,6 +18,7 @@
 
 #include "nbd.h"
 #include "block.h"
+#include "block_int.h"
 
 #include <errno.h>
 #include <string.h>
@@ -186,7 +187,7 @@ int unix_socket_outgoing(const char *path)
                   Request (type == 2)
 */
 
-int nbd_negotiate(int csock, off_t size, uint32_t flags)
+static int nbd_send_negotiate(int csock, off_t size, uint32_t flags)
 {
     char buf[8 + 8 + 8 + 128];
 
@@ -583,6 +584,33 @@ static int nbd_send_reply(int csock, struct nbd_reply *reply)
     return 0;
 }
 
+struct NBDExport {
+    BlockDriverState *bs;
+    off_t dev_offset;
+    off_t size;
+    uint8_t *data;
+    uint32_t nbdflags;
+};
+
+NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset,
+                          off_t size, uint32_t nbdflags)
+{
+    NBDExport *exp = g_malloc0(sizeof(NBDExport));
+    exp->bs = bs;
+    exp->dev_offset = dev_offset;
+    exp->nbdflags = nbdflags;
+    exp->size = size == -1 ? exp->bs->total_sectors * 512 : size;
+    exp->data = qemu_blockalign(exp->bs, NBD_BUFFER_SIZE);
+    return exp;
+}
+
+void nbd_export_close(NBDExport *exp)
+{
+    qemu_vfree(exp->data);
+    bdrv_close(exp->bs);
+    g_free(exp);
+}
+
 static int nbd_do_send_reply(int csock, struct nbd_reply *reply,
                              uint8_t *data, int len)
 {
@@ -652,9 +680,7 @@ out:
     return rc;
 }
 
-int nbd_trip(BlockDriverState *bs, int csock, off_t size,
-             uint64_t dev_offset, uint32_t nbdflags,
-             uint8_t *data)
+int nbd_trip(NBDExport *exp, int csock)
 {
     struct nbd_request request;
     struct nbd_reply reply;
@@ -662,7 +688,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
 
     TRACE("Reading request.");
 
-    ret = nbd_do_receive_request(csock, &request, data);
+    ret = nbd_do_receive_request(csock, &request, exp->data);
     if (ret == -EIO) {
         return -1;
     }
@@ -675,10 +701,11 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
         goto error_reply;
     }
 
-    if ((request.from + request.len) > size) {
+    if ((request.from + request.len) > exp->size) {
             LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
             ", Offset: %" PRIu64 "\n",
-                    request.from, request.len, (uint64_t)size, dev_offset);
+                    request.from, request.len,
+                    (uint64_t)exp->size, exp->dev_offset);
         LOG("requested operation past EOF--bad client?");
         goto invalid_request;
     }
@@ -687,8 +714,8 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
     case NBD_CMD_READ:
         TRACE("Request type is READ");
 
-        ret = bdrv_read(bs, (request.from + dev_offset) / 512,
-                        data, request.len / 512);
+        ret = bdrv_read(exp->bs, (request.from + exp->dev_offset) / 512,
+                        exp->data, request.len / 512);
         if (ret < 0) {
             LOG("reading from file failed");
             reply.error = -ret;
@@ -696,13 +723,13 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
         }
 
         TRACE("Read %u byte(s)", request.len);
-        if (nbd_do_send_reply(csock, &reply, data, request.len) < 0)
+        if (nbd_do_send_reply(csock, &reply, exp->data, request.len) < 0)
             return -1;
         break;
     case NBD_CMD_WRITE:
         TRACE("Request type is WRITE");
 
-        if (nbdflags & NBD_FLAG_READ_ONLY) {
+        if (exp->nbdflags & NBD_FLAG_READ_ONLY) {
             TRACE("Server is read-only, return error");
             reply.error = EROFS;
             goto error_reply;
@@ -710,8 +737,8 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
 
         TRACE("Writing to device");
 
-        ret = bdrv_write(bs, (request.from + dev_offset) / 512,
-                         data, request.len / 512);
+        ret = bdrv_write(exp->bs, (request.from + exp->dev_offset) / 512,
+                         exp->data, request.len / 512);
         if (ret < 0) {
             LOG("writing to file failed");
             reply.error = -ret;
@@ -719,7 +746,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
         }
 
         if (request.type & NBD_CMD_FLAG_FUA) {
-            ret = bdrv_flush(bs);
+            ret = bdrv_flush(exp->bs);
             if (ret < 0) {
                 LOG("flush failed");
                 reply.error = -ret;
@@ -737,7 +764,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
     case NBD_CMD_FLUSH:
         TRACE("Request type is FLUSH");
 
-        ret = bdrv_flush(bs);
+        ret = bdrv_flush(exp->bs);
         if (ret < 0) {
             LOG("flush failed");
             reply.error = -ret;
@@ -748,7 +775,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
         break;
     case NBD_CMD_TRIM:
         TRACE("Request type is TRIM");
-        ret = bdrv_discard(bs, (request.from + dev_offset) / 512,
+        ret = bdrv_discard(exp->bs, (request.from + exp->dev_offset) / 512,
                            request.len / 512);
         if (ret < 0) {
             LOG("discard failed");
@@ -771,3 +798,8 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
 
     return 0;
 }
+
+int nbd_negotiate(NBDExport *exp, int csock)
+{
+    return nbd_send_negotiate(csock, exp->size, exp->nbdflags);
+}
diff --git a/nbd.h b/nbd.h
index dbc4c0d..c77c2fd 100644
--- a/nbd.h
+++ b/nbd.h
@@ -67,15 +67,20 @@ int tcp_socket_incoming_spec(const char *address_and_port);
 int unix_socket_outgoing(const char *path);
 int unix_socket_incoming(const char *path);
 
-int nbd_negotiate(int csock, off_t size, uint32_t flags);
 int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
                           off_t *size, size_t *blocksize);
 int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize);
 int nbd_send_request(int csock, struct nbd_request *request);
 int nbd_receive_reply(int csock, struct nbd_reply *reply);
-int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
-             uint32_t nbdflags, uint8_t *data);
 int nbd_client(int fd);
 int nbd_disconnect(int fd);
 
+typedef struct NBDExport NBDExport;
+
+NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset,
+                          off_t size, uint32_t nbdflags);
+void nbd_export_close(NBDExport *exp);
+int nbd_negotiate(NBDExport *exp, int csock);
+int nbd_trip(NBDExport *exp, int csock);
+
 #endif
diff --git a/qemu-nbd.c b/qemu-nbd.c
index d662268..d5ac75e 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -36,6 +36,7 @@
 #define SOCKET_PATH    "/var/lock/qemu-nbd-%s"
 
 static int sigterm_wfd;
+static NBDExport *exp;
 static int verbose;
 static char *device;
 static char *srcpath;
@@ -280,7 +281,6 @@ int main(int argc, char **argv)
     int partition = -1;
     int ret;
     int shared = 1;
-    uint8_t *data;
     fd_set fds;
     int *sharing_fds;
     int fd;
@@ -489,6 +489,7 @@ int main(int argc, char **argv)
         err(EXIT_FAILURE, "Could not find partition %d", partition);
     }
 
+    exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags);
     sharing_fds = g_malloc((shared + 1) * sizeof(int));
 
     if (sockpath) {
@@ -516,11 +517,6 @@ int main(int argc, char **argv)
     max_fd = sharing_fds[0];
     nb_fds++;
 
-    data = qemu_blockalign(bs, NBD_BUFFER_SIZE);
-    if (data == NULL) {
-        errx(EXIT_FAILURE, "Cannot allocate data buffer");
-    }
-
     do {
         FD_ZERO(&fds);
         FD_SET(sigterm_fd[0], &fds);
@@ -538,8 +534,7 @@ int main(int argc, char **argv)
             ret--;
         for (i = 1; i < nb_fds && ret; i++) {
             if (FD_ISSET(sharing_fds[i], &fds)) {
-                if (nbd_trip(bs, sharing_fds[i], fd_size, dev_offset,
-                             nbdflags, data) != 0) {
+                if (nbd_trip(exp, sharing_fds[i]) != 0) {
                     close(sharing_fds[i]);
                     nb_fds--;
                     sharing_fds[i] = sharing_fds[nb_fds];
@@ -555,7 +550,7 @@ int main(int argc, char **argv)
                                              (struct sockaddr *)&addr,
                                              &addr_len);
                 if (sharing_fds[nb_fds] != -1 &&
-                    nbd_negotiate(sharing_fds[nb_fds], fd_size, nbdflags) != -1) {
+                    nbd_negotiate(exp, sharing_fds[nb_fds]) != -1) {
                         if (sharing_fds[nb_fds] > max_fd)
                             max_fd = sharing_fds[nb_fds];
                         nb_fds++;
@@ -563,9 +558,9 @@ int main(int argc, char **argv)
             }
         }
     } while (persistent || nb_fds > 1);
-    qemu_vfree(data);
 
     close(sharing_fds[0]);
+    nbd_export_close(exp);
     g_free(sharing_fds);
     if (sockpath) {
         unlink(sockpath);
commit a030b347aaa84e2d1b42c9cb2bc9e2d8bec50046
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 19 15:07:54 2011 +0200

    qemu-nbd: introduce nbd_do_receive_request
    
    Group the receiving of a response and the associated data into a new function.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/nbd.c b/nbd.c
index 053ad8d..964a732 100644
--- a/nbd.c
+++ b/nbd.c
@@ -611,6 +611,47 @@ static int nbd_do_send_reply(int csock, struct nbd_reply *reply,
     return rc;
 }
 
+static int nbd_do_receive_request(int csock, struct nbd_request *request,
+                                  uint8_t *data)
+{
+    int rc;
+
+    if (nbd_receive_request(csock, request) == -1) {
+        rc = -EIO;
+        goto out;
+    }
+
+    if (request->len > NBD_BUFFER_SIZE) {
+        LOG("len (%u) is larger than max len (%u)",
+            request->len, NBD_BUFFER_SIZE);
+        rc = -EINVAL;
+        goto out;
+    }
+
+    if ((request->from + request->len) < request->from) {
+        LOG("integer overflow detected! "
+            "you're probably being attacked");
+        rc = -EINVAL;
+        goto out;
+    }
+
+    TRACE("Decoding type");
+
+    if ((request->type & NBD_CMD_MASK_COMMAND) == NBD_CMD_WRITE) {
+        TRACE("Reading %u byte(s)", request->len);
+
+        if (read_sync(csock, data, request->len) != request->len) {
+            LOG("reading from socket failed");
+            rc = -EIO;
+            goto out;
+        }
+    }
+    rc = 0;
+
+out:
+    return rc;
+}
+
 int nbd_trip(BlockDriverState *bs, int csock, off_t size,
              uint64_t dev_offset, uint32_t nbdflags,
              uint8_t *data)
@@ -621,22 +662,17 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
 
     TRACE("Reading request.");
 
-    if (nbd_receive_request(csock, &request) == -1)
+    ret = nbd_do_receive_request(csock, &request, data);
+    if (ret == -EIO) {
         return -1;
+    }
 
     reply.handle = request.handle;
     reply.error = 0;
 
-    if (request.len > NBD_BUFFER_SIZE) {
-        LOG("len (%u) is larger than max len (%u)",
-            request.len, NBD_BUFFER_SIZE);
-        goto invalid_request;
-    }
-
-    if ((request.from + request.len) < request.from) {
-        LOG("integer overflow detected! "
-            "you're probably being attacked");
-        goto invalid_request;
+    if (ret < 0) {
+        reply.error = -ret;
+        goto error_reply;
     }
 
     if ((request.from + request.len) > size) {
@@ -647,8 +683,6 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
         goto invalid_request;
     }
 
-    TRACE("Decoding type");
-
     switch (request.type & NBD_CMD_MASK_COMMAND) {
     case NBD_CMD_READ:
         TRACE("Request type is READ");
@@ -668,14 +702,6 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
     case NBD_CMD_WRITE:
         TRACE("Request type is WRITE");
 
-        TRACE("Reading %u byte(s)", request.len);
-
-        if (read_sync(csock, data, request.len) != request.len) {
-            LOG("reading from socket failed");
-            errno = EINVAL;
-            return -1;
-        }
-
         if (nbdflags & NBD_FLAG_READ_ONLY) {
             TRACE("Server is read-only, return error");
             reply.error = EROFS;
commit fae69416294223d84db425e58e7bbf6a08c45801
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 19 16:04:36 2011 +0200

    qemu-nbd: more robust handling of invalid requests
    
    Fail invalid requests with EINVAL instead of dropping them into
    the void.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/nbd.c b/nbd.c
index 025c5b0..053ad8d 100644
--- a/nbd.c
+++ b/nbd.c
@@ -624,18 +624,19 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
     if (nbd_receive_request(csock, &request) == -1)
         return -1;
 
+    reply.handle = request.handle;
+    reply.error = 0;
+
     if (request.len > NBD_BUFFER_SIZE) {
         LOG("len (%u) is larger than max len (%u)",
             request.len, NBD_BUFFER_SIZE);
-        errno = EINVAL;
-        return -1;
+        goto invalid_request;
     }
 
     if ((request.from + request.len) < request.from) {
         LOG("integer overflow detected! "
             "you're probably being attacked");
-        errno = EINVAL;
-        return -1;
+        goto invalid_request;
     }
 
     if ((request.from + request.len) > size) {
@@ -643,15 +644,11 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
             ", Offset: %" PRIu64 "\n",
                     request.from, request.len, (uint64_t)size, dev_offset);
         LOG("requested operation past EOF--bad client?");
-        errno = EINVAL;
-        return -1;
+        goto invalid_request;
     }
 
     TRACE("Decoding type");
 
-    reply.handle = request.handle;
-    reply.error = 0;
-
     switch (request.type & NBD_CMD_MASK_COMMAND) {
     case NBD_CMD_READ:
         TRACE("Request type is READ");
@@ -661,7 +658,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
         if (ret < 0) {
             LOG("reading from file failed");
             reply.error = -ret;
-            request.len = 0;
+            goto error_reply;
         }
 
         TRACE("Read %u byte(s)", request.len);
@@ -681,24 +678,26 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
 
         if (nbdflags & NBD_FLAG_READ_ONLY) {
             TRACE("Server is read-only, return error");
-            reply.error = 1;
-        } else {
-            TRACE("Writing to device");
+            reply.error = EROFS;
+            goto error_reply;
+        }
+
+        TRACE("Writing to device");
+
+        ret = bdrv_write(bs, (request.from + dev_offset) / 512,
+                         data, request.len / 512);
+        if (ret < 0) {
+            LOG("writing to file failed");
+            reply.error = -ret;
+            goto error_reply;
+        }
 
-            ret = bdrv_write(bs, (request.from + dev_offset) / 512,
-                             data, request.len / 512);
+        if (request.type & NBD_CMD_FLAG_FUA) {
+            ret = bdrv_flush(bs);
             if (ret < 0) {
-                LOG("writing to file failed");
+                LOG("flush failed");
                 reply.error = -ret;
-                request.len = 0;
-            }
-
-            if (request.type & NBD_CMD_FLAG_FUA) {
-                ret = bdrv_flush(bs);
-                if (ret < 0) {
-                    LOG("flush failed");
-                    reply.error = -ret;
-                }
+                goto error_reply;
             }
         }
 
@@ -734,8 +733,12 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
         break;
     default:
         LOG("invalid request type (%u) received", request.type);
-        errno = EINVAL;
-        return -1;
+    invalid_request:
+        reply.error = -EINVAL;
+    error_reply:
+        if (nbd_do_send_reply(csock, &reply, NULL, 0) == -1)
+            return -1;
+        break;
     }
 
     TRACE("Request/Reply complete");
commit 220455920384af77670e84953f3763153e39bcfa
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 19 14:25:30 2011 +0200

    qemu-nbd: introduce nbd_do_send_reply
    
    Group the sending of a reply and the associated data into a new function.
    Without corking, the caller would be forced to leave 12 free bytes at the
    beginning of the data pointer.  Not too ugly, but still ugly. :)
    
    Using nbd_do_send_reply everywhere will help when the routine will set up
    the write handler that re-enters the send coroutine.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/nbd.c b/nbd.c
index d383d85..025c5b0 100644
--- a/nbd.c
+++ b/nbd.c
@@ -583,6 +583,34 @@ static int nbd_send_reply(int csock, struct nbd_reply *reply)
     return 0;
 }
 
+static int nbd_do_send_reply(int csock, struct nbd_reply *reply,
+                             uint8_t *data, int len)
+{
+    int rc, ret;
+
+    if (!len) {
+        rc = nbd_send_reply(csock, reply);
+        if (rc == -1) {
+            rc = -errno;
+        }
+    } else {
+        socket_set_cork(csock, 1);
+        rc = nbd_send_reply(csock, reply);
+        if (rc != -1) {
+            ret = write_sync(csock, data, len);
+            if (ret != len) {
+                errno = EIO;
+                rc = -1;
+            }
+        }
+        if (rc == -1) {
+            rc = -errno;
+        }
+        socket_set_cork(csock, 0);
+    }
+    return rc;
+}
+
 int nbd_trip(BlockDriverState *bs, int csock, off_t size,
              uint64_t dev_offset, uint32_t nbdflags,
              uint8_t *data)
@@ -637,18 +665,8 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
         }
 
         TRACE("Read %u byte(s)", request.len);
-        socket_set_cork(csock, 1);
-        if (nbd_send_reply(csock, &reply) == -1)
+        if (nbd_do_send_reply(csock, &reply, data, request.len) < 0)
             return -1;
-
-        TRACE("Sending data to client");
-
-        if (write_sync(csock, data, request.len) != request.len) {
-            LOG("writing to socket failed");
-            errno = EINVAL;
-            return -1;
-        }
-        socket_set_cork(csock, 0);
         break;
     case NBD_CMD_WRITE:
         TRACE("Request type is WRITE");
@@ -684,7 +702,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
             }
         }
 
-        if (nbd_send_reply(csock, &reply) == -1)
+        if (nbd_do_send_reply(csock, &reply, NULL, 0) < 0)
             return -1;
         break;
     case NBD_CMD_DISC:
@@ -700,7 +718,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
             reply.error = -ret;
         }
 
-        if (nbd_send_reply(csock, &reply) == -1)
+        if (nbd_do_send_reply(csock, &reply, NULL, 0) < 0)
             return -1;
         break;
     case NBD_CMD_TRIM:
@@ -711,7 +729,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
             LOG("discard failed");
             reply.error = -ret;
         }
-        if (nbd_send_reply(csock, &reply) == -1)
+        if (nbd_do_send_reply(csock, &reply, NULL, 0) < 0)
             return -1;
         break;
     default:
commit a478f6e595dab1801931d56d097623d65f5b6d1d
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 19 13:48:43 2011 +0200

    qemu-nbd: simplify nbd_trip
    
    Use TCP_CORK to remove a violation of encapsulation, that would later
    require nbd_trip to know too much about an NBD reply.
    
    We could also switch to sendmsg (qemu_co_sendv) later, it is even
    easier once coroutines are in.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/nbd.c b/nbd.c
index d8cc331..d383d85 100644
--- a/nbd.c
+++ b/nbd.c
@@ -596,9 +596,9 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
     if (nbd_receive_request(csock, &request) == -1)
         return -1;
 
-    if (request.len + NBD_REPLY_SIZE > NBD_BUFFER_SIZE) {
+    if (request.len > NBD_BUFFER_SIZE) {
         LOG("len (%u) is larger than max len (%u)",
-            request.len + NBD_REPLY_SIZE, NBD_BUFFER_SIZE);
+            request.len, NBD_BUFFER_SIZE);
         errno = EINVAL;
         return -1;
     }
@@ -629,8 +629,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
         TRACE("Request type is READ");
 
         ret = bdrv_read(bs, (request.from + dev_offset) / 512,
-                        data + NBD_REPLY_SIZE,
-                        request.len / 512);
+                        data, request.len / 512);
         if (ret < 0) {
             LOG("reading from file failed");
             reply.error = -ret;
@@ -638,26 +637,18 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
         }
 
         TRACE("Read %u byte(s)", request.len);
-
-        /* Reply
-           [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
-           [ 4 ..  7]    error   (0 == no error)
-           [ 7 .. 15]    handle
-         */
-
-        cpu_to_be32w((uint32_t*)data, NBD_REPLY_MAGIC);
-        cpu_to_be32w((uint32_t*)(data + 4), reply.error);
-        cpu_to_be64w((uint64_t*)(data + 8), reply.handle);
+        socket_set_cork(csock, 1);
+        if (nbd_send_reply(csock, &reply) == -1)
+            return -1;
 
         TRACE("Sending data to client");
 
-        if (write_sync(csock, data,
-                   request.len + NBD_REPLY_SIZE) !=
-                   request.len + NBD_REPLY_SIZE) {
+        if (write_sync(csock, data, request.len) != request.len) {
             LOG("writing to socket failed");
             errno = EINVAL;
             return -1;
         }
+        socket_set_cork(csock, 0);
         break;
     case NBD_CMD_WRITE:
         TRACE("Request type is WRITE");
commit 128aa58947637b0989330c2e6a22a824d39e2193
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Sep 21 12:36:48 2011 +0200

    move corking functions to osdep.c
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index 00ea5a0..17a79be 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -702,22 +702,6 @@ static int aio_flush_request(void *opaque)
     return !QLIST_EMPTY(&s->outstanding_aio_head);
 }
 
-#if !defined(SOL_TCP) || !defined(TCP_CORK)
-
-static int set_cork(int fd, int v)
-{
-    return 0;
-}
-
-#else
-
-static int set_cork(int fd, int v)
-{
-    return setsockopt(fd, SOL_TCP, TCP_CORK, &v, sizeof(v));
-}
-
-#endif
-
 static int set_nodelay(int fd)
 {
     int ret, opt;
@@ -923,7 +907,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
     s->co_send = qemu_coroutine_self();
     qemu_aio_set_fd_handler(s->fd, co_read_response, co_write_request,
                             aio_flush_request, NULL, s);
-    set_cork(s->fd, 1);
+    socket_set_cork(s->fd, 1);
 
     /* send a header */
     ret = qemu_co_send(s->fd, &hdr, sizeof(hdr));
@@ -942,7 +926,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
         }
     }
 
-    set_cork(s->fd, 0);
+    socket_set_cork(s->fd, 0);
     qemu_aio_set_fd_handler(s->fd, co_read_response, NULL,
                             aio_flush_request, NULL, s);
     qemu_co_mutex_unlock(&s->lock);
diff --git a/osdep.c b/osdep.c
index 70bad27..3e6bada 100644
--- a/osdep.c
+++ b/osdep.c
@@ -48,6 +48,15 @@ extern int madvise(caddr_t, size_t, int);
 #include "trace.h"
 #include "qemu_socket.h"
 
+int socket_set_cork(int fd, int v)
+{
+#if defined(SOL_TCP) && defined(TCP_CORK)
+    return setsockopt(fd, SOL_TCP, TCP_CORK, &v, sizeof(v));
+#else
+    return 0;
+#endif
+}
+
 int qemu_madvise(void *addr, size_t len, int advice)
 {
     if (advice == QEMU_MADV_INVALID) {
diff --git a/qemu_socket.h b/qemu_socket.h
index 9e32fac..fe4cf6c 100644
--- a/qemu_socket.h
+++ b/qemu_socket.h
@@ -35,6 +35,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
 /* misc helpers */
 int qemu_socket(int domain, int type, int protocol);
 int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+int socket_set_cork(int fd, int v);
 void socket_set_block(int fd);
 void socket_set_nonblock(int fd);
 int send_all(int fd, const void *buf, int len1);
commit 3777b09fd75ba746cf65d0ba30d73a5dd7a02d65
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Oct 7 14:35:58 2011 +0200

    qemu-nbd: remove data_size argument to nbd_trip
    
    The size of the buffer is in practice part of the protocol.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/nbd.c b/nbd.c
index 1df2b91..d8cc331 100644
--- a/nbd.c
+++ b/nbd.c
@@ -585,7 +585,7 @@ static int nbd_send_reply(int csock, struct nbd_reply *reply)
 
 int nbd_trip(BlockDriverState *bs, int csock, off_t size,
              uint64_t dev_offset, uint32_t nbdflags,
-             uint8_t *data, int data_size)
+             uint8_t *data)
 {
     struct nbd_request request;
     struct nbd_reply reply;
@@ -596,9 +596,9 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
     if (nbd_receive_request(csock, &request) == -1)
         return -1;
 
-    if (request.len + NBD_REPLY_SIZE > data_size) {
+    if (request.len + NBD_REPLY_SIZE > NBD_BUFFER_SIZE) {
         LOG("len (%u) is larger than max len (%u)",
-            request.len + NBD_REPLY_SIZE, data_size);
+            request.len + NBD_REPLY_SIZE, NBD_BUFFER_SIZE);
         errno = EINVAL;
         return -1;
     }
diff --git a/nbd.h b/nbd.h
index ebdb2db..dbc4c0d 100644
--- a/nbd.h
+++ b/nbd.h
@@ -57,6 +57,8 @@ enum {
 
 #define NBD_DEFAULT_PORT	10809
 
+#define NBD_BUFFER_SIZE (1024*1024)
+
 size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read);
 int tcp_socket_outgoing(const char *address, uint16_t port);
 int tcp_socket_incoming(const char *address, uint16_t port);
@@ -72,7 +74,7 @@ int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize);
 int nbd_send_request(int csock, struct nbd_request *request);
 int nbd_receive_reply(int csock, struct nbd_reply *reply);
 int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
-             uint32_t nbdflags, uint8_t *data, int data_size);
+             uint32_t nbdflags, uint8_t *data);
 int nbd_client(int fd);
 int nbd_disconnect(int fd);
 
diff --git a/qemu-nbd.c b/qemu-nbd.c
index f9ee9c5..d662268 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -35,8 +35,6 @@
 
 #define SOCKET_PATH    "/var/lock/qemu-nbd-%s"
 
-#define NBD_BUFFER_SIZE (1024*1024)
-
 static int sigterm_wfd;
 static int verbose;
 static char *device;
@@ -541,7 +539,7 @@ int main(int argc, char **argv)
         for (i = 1; i < nb_fds && ret; i++) {
             if (FD_ISSET(sharing_fds[i], &fds)) {
                 if (nbd_trip(bs, sharing_fds[i], fd_size, dev_offset,
-                    nbdflags, data, NBD_BUFFER_SIZE) != 0) {
+                             nbdflags, data) != 0) {
                     close(sharing_fds[i]);
                     nb_fds--;
                     sharing_fds[i] = sharing_fds[nb_fds];
commit 94607e7a775ae7b57219e2078b00ed2930ab98de
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 19 13:50:54 2011 +0200

    qemu-nbd: remove offset argument to nbd_trip
    
    The argument is write-only.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/nbd.c b/nbd.c
index 73fedeb..1df2b91 100644
--- a/nbd.c
+++ b/nbd.c
@@ -583,8 +583,9 @@ static int nbd_send_reply(int csock, struct nbd_reply *reply)
     return 0;
 }
 
-int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
-             off_t *offset, uint32_t nbdflags, uint8_t *data, int data_size)
+int nbd_trip(BlockDriverState *bs, int csock, off_t size,
+             uint64_t dev_offset, uint32_t nbdflags,
+             uint8_t *data, int data_size)
 {
     struct nbd_request request;
     struct nbd_reply reply;
@@ -635,7 +636,6 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
             reply.error = -ret;
             request.len = 0;
         }
-        *offset += request.len;
 
         TRACE("Read %u byte(s)", request.len);
 
@@ -684,8 +684,6 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
                 request.len = 0;
             }
 
-            *offset += request.len;
-
             if (request.type & NBD_CMD_FLAG_FUA) {
                 ret = bdrv_flush(bs);
                 if (ret < 0) {
diff --git a/nbd.h b/nbd.h
index 61553f4..ebdb2db 100644
--- a/nbd.h
+++ b/nbd.h
@@ -72,7 +72,7 @@ int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize);
 int nbd_send_request(int csock, struct nbd_request *request);
 int nbd_receive_reply(int csock, struct nbd_reply *reply);
 int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
-             off_t *offset, uint32_t nbdflags, uint8_t *data, int data_size);
+             uint32_t nbdflags, uint8_t *data, int data_size);
 int nbd_client(int fd);
 int nbd_disconnect(int fd);
 
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 291cba2..f9ee9c5 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -248,7 +248,6 @@ int main(int argc, char **argv)
 {
     BlockDriverState *bs;
     off_t dev_offset = 0;
-    off_t offset = 0;
     uint32_t nbdflags = 0;
     bool disconnect = false;
     const char *bindto = "0.0.0.0";
@@ -542,7 +541,7 @@ int main(int argc, char **argv)
         for (i = 1; i < nb_fds && ret; i++) {
             if (FD_ISSET(sharing_fds[i], &fds)) {
                 if (nbd_trip(bs, sharing_fds[i], fd_size, dev_offset,
-                    &offset, nbdflags, data, NBD_BUFFER_SIZE) != 0) {
+                    nbdflags, data, NBD_BUFFER_SIZE) != 0) {
                     close(sharing_fds[i]);
                     nb_fds--;
                     sharing_fds[i] = sharing_fds[nb_fds];
commit 3e05c785516efa6911504b1ddf936d2386c2e0b6
Author: Chunyan Liu <cyliu at suse.com>
Date:   Fri Dec 2 23:27:54 2011 +0800

    Update ioctl order in nbd_init() to detect EBUSY
    
    Update ioctl(s) in nbd_init() to detect device busy early.
    
    Current nbd_init() issues NBD_CLEAR_SOCKET before NBD_SET_SOCKET, if issuing
    "qemu-nbd -c /dev/nbd0 disk.img" twice, the second time won't detect EBUSY in
    nbd_init(), but in nbd_client will report EBUSY and do clear socket (the 1st
    time command will be affacted too because of no socket any more.)
    
    No change to previous version.
    
    Signed-off-by: Chunyan Liu <cyliu at suse.com>
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/nbd.c b/nbd.c
index 7ab1b1f..73fedeb 100644
--- a/nbd.c
+++ b/nbd.c
@@ -358,6 +358,15 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
 #ifdef __linux__
 int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize)
 {
+    TRACE("Setting NBD socket");
+
+    if (ioctl(fd, NBD_SET_SOCK, csock) == -1) {
+        int serrno = errno;
+        LOG("Failed to set NBD socket");
+        errno = serrno;
+        return -1;
+    }
+
     TRACE("Setting block size to %lu", (unsigned long)blocksize);
 
     if (ioctl(fd, NBD_SET_BLKSIZE, blocksize) == -1) {
@@ -396,24 +405,6 @@ int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize)
         return -1;
     }
 
-    TRACE("Clearing NBD socket");
-
-    if (ioctl(fd, NBD_CLEAR_SOCK) == -1) {
-        int serrno = errno;
-        LOG("Failed clearing NBD socket");
-        errno = serrno;
-        return -1;
-    }
-
-    TRACE("Setting NBD socket");
-
-    if (ioctl(fd, NBD_SET_SOCK, csock) == -1) {
-        int serrno = errno;
-        LOG("Failed to set NBD socket");
-        errno = serrno;
-        return -1;
-    }
-
     TRACE("Negotiation ended");
 
     return 0;
commit 7a706633e9f77a15d12bcfdef5d80f09892fa70c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Oct 21 13:17:14 2011 +0200

    nbd: add support for NBD_CMD_TRIM
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/nbd.c b/block/nbd.c
index 097b418..161b299 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -435,6 +435,30 @@ static int nbd_co_flush(BlockDriverState *bs)
     return -reply.error;
 }
 
+static int nbd_co_discard(BlockDriverState *bs, int64_t sector_num,
+                          int nb_sectors)
+{
+    BDRVNBDState *s = bs->opaque;
+    struct nbd_request request;
+    struct nbd_reply reply;
+
+    if (!(s->nbdflags & NBD_FLAG_SEND_TRIM)) {
+        return 0;
+    }
+    request.type = NBD_CMD_TRIM;
+    request.from = sector_num * 512;;
+    request.len = nb_sectors * 512;
+
+    nbd_coroutine_start(s, &request);
+    if (nbd_co_send_request(s, &request, NULL, 0) == -1) {
+        reply.error = errno;
+    } else {
+        nbd_co_receive_reply(s, &request, &reply, NULL, 0);
+    }
+    nbd_coroutine_end(s, &request);
+    return -reply.error;
+}
+
 static void nbd_close(BlockDriverState *bs)
 {
     BDRVNBDState *s = bs->opaque;
@@ -459,6 +483,7 @@ static BlockDriver bdrv_nbd = {
     .bdrv_co_writev      = nbd_co_writev,
     .bdrv_close          = nbd_close,
     .bdrv_co_flush_to_os = nbd_co_flush,
+    .bdrv_co_discard     = nbd_co_discard,
     .bdrv_getlength      = nbd_getlength,
     .protocol_name       = "nbd",
 };
diff --git a/nbd.c b/nbd.c
index 4fd0f4e..7ab1b1f 100644
--- a/nbd.c
+++ b/nbd.c
@@ -203,8 +203,8 @@ int nbd_negotiate(int csock, off_t size, uint32_t flags)
     cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL);
     cpu_to_be64w((uint64_t*)(buf + 16), size);
     cpu_to_be32w((uint32_t*)(buf + 24),
-                 flags | NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_FLUSH |
-                 NBD_FLAG_SEND_FUA);
+                 flags | NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
+                 NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA);
     memset(buf + 28, 0, 124);
 
     if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
@@ -723,6 +723,17 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
         if (nbd_send_reply(csock, &reply) == -1)
             return -1;
         break;
+    case NBD_CMD_TRIM:
+        TRACE("Request type is TRIM");
+        ret = bdrv_discard(bs, (request.from + dev_offset) / 512,
+                           request.len / 512);
+        if (ret < 0) {
+            LOG("discard failed");
+            reply.error = -ret;
+        }
+        if (nbd_send_reply(csock, &reply) == -1)
+            return -1;
+        break;
     default:
         LOG("invalid request type (%u) received", request.type);
         errno = EINVAL;
commit 1486d04a1b41093e5f97f20ca7397e01df055f49
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Oct 21 13:17:14 2011 +0200

    nbd: add support for NBD_CMD_FLUSH
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/nbd.c b/block/nbd.c
index 2f483cd..097b418 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -407,6 +407,34 @@ static int nbd_co_writev(BlockDriverState *bs, int64_t sector_num,
     return nbd_co_writev_1(bs, sector_num, nb_sectors, qiov, offset);
 }
 
+static int nbd_co_flush(BlockDriverState *bs)
+{
+    BDRVNBDState *s = bs->opaque;
+    struct nbd_request request;
+    struct nbd_reply reply;
+
+    if (!(s->nbdflags & NBD_FLAG_SEND_FLUSH)) {
+        return 0;
+    }
+
+    request.type = NBD_CMD_FLUSH;
+    if (s->nbdflags & NBD_FLAG_SEND_FUA) {
+        request.type |= NBD_CMD_FLAG_FUA;
+    }
+
+    request.from = 0;
+    request.len = 0;
+
+    nbd_coroutine_start(s, &request);
+    if (nbd_co_send_request(s, &request, NULL, 0) == -1) {
+        reply.error = errno;
+    } else {
+        nbd_co_receive_reply(s, &request, &reply, NULL, 0);
+    }
+    nbd_coroutine_end(s, &request);
+    return -reply.error;
+}
+
 static void nbd_close(BlockDriverState *bs)
 {
     BDRVNBDState *s = bs->opaque;
@@ -424,14 +452,15 @@ static int64_t nbd_getlength(BlockDriverState *bs)
 }
 
 static BlockDriver bdrv_nbd = {
-    .format_name	= "nbd",
-    .instance_size	= sizeof(BDRVNBDState),
-    .bdrv_file_open	= nbd_open,
-    .bdrv_co_readv	= nbd_co_readv,
-    .bdrv_co_writev	= nbd_co_writev,
-    .bdrv_close		= nbd_close,
-    .bdrv_getlength	= nbd_getlength,
-    .protocol_name	= "nbd",
+    .format_name         = "nbd",
+    .instance_size       = sizeof(BDRVNBDState),
+    .bdrv_file_open      = nbd_open,
+    .bdrv_co_readv       = nbd_co_readv,
+    .bdrv_co_writev      = nbd_co_writev,
+    .bdrv_close          = nbd_close,
+    .bdrv_co_flush_to_os = nbd_co_flush,
+    .bdrv_getlength      = nbd_getlength,
+    .protocol_name       = "nbd",
 };
 
 static void bdrv_nbd_init(void)
diff --git a/nbd.c b/nbd.c
index c597d47..4fd0f4e 100644
--- a/nbd.c
+++ b/nbd.c
@@ -203,7 +203,8 @@ int nbd_negotiate(int csock, off_t size, uint32_t flags)
     cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL);
     cpu_to_be64w((uint64_t*)(buf + 16), size);
     cpu_to_be32w((uint32_t*)(buf + 24),
-                 flags | NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_FUA);
+                 flags | NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_FLUSH |
+                 NBD_FLAG_SEND_FUA);
     memset(buf + 28, 0, 124);
 
     if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
@@ -710,6 +711,18 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
         TRACE("Request type is DISCONNECT");
         errno = 0;
         return 1;
+    case NBD_CMD_FLUSH:
+        TRACE("Request type is FLUSH");
+
+        ret = bdrv_flush(bs);
+        if (ret < 0) {
+            LOG("flush failed");
+            reply.error = -ret;
+        }
+
+        if (nbd_send_reply(csock, &reply) == -1)
+            return -1;
+        break;
     default:
         LOG("invalid request type (%u) received", request.type);
         errno = EINVAL;
commit 2c7989a9b13a45963548cf4d89535fe90d809cac
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Oct 21 13:16:28 2011 +0200

    nbd: add support for NBD_CMD_FLAG_FUA
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/nbd.c b/block/nbd.c
index 3f693e3..2f483cd 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -352,6 +352,10 @@ static int nbd_co_writev_1(BlockDriverState *bs, int64_t sector_num,
     struct nbd_reply reply;
 
     request.type = NBD_CMD_WRITE;
+    if (!bdrv_enable_write_cache(bs) && (s->nbdflags & NBD_FLAG_SEND_FUA)) {
+        request.type |= NBD_CMD_FLAG_FUA;
+    }
+
     request.from = sector_num * 512;
     request.len = nb_sectors * 512;
 
diff --git a/nbd.c b/nbd.c
index 5b718b5..c597d47 100644
--- a/nbd.c
+++ b/nbd.c
@@ -202,7 +202,8 @@ int nbd_negotiate(int csock, off_t size, uint32_t flags)
     memcpy(buf, "NBDMAGIC", 8);
     cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL);
     cpu_to_be64w((uint64_t*)(buf + 16), size);
-    cpu_to_be32w((uint32_t*)(buf + 24), flags | NBD_FLAG_HAS_FLAGS);
+    cpu_to_be32w((uint32_t*)(buf + 24),
+                 flags | NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_FUA);
     memset(buf + 28, 0, 124);
 
     if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
@@ -630,7 +631,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
     reply.handle = request.handle;
     reply.error = 0;
 
-    switch (request.type) {
+    switch (request.type & NBD_CMD_MASK_COMMAND) {
     case NBD_CMD_READ:
         TRACE("Request type is READ");
 
@@ -692,6 +693,14 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
             }
 
             *offset += request.len;
+
+            if (request.type & NBD_CMD_FLAG_FUA) {
+                ret = bdrv_flush(bs);
+                if (ret < 0) {
+                    LOG("flush failed");
+                    reply.error = -ret;
+                }
+            }
         }
 
         if (nbd_send_reply(csock, &reply) == -1)
commit adcf6302de40e50a8010e7f2c79b3dac2eea6e0c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Sep 13 17:27:45 2011 +0200

    nbd: fix error handling in the server
    
    bdrv_read and bdrv_write return negative errno values, not -1.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/nbd.c b/nbd.c
index ff701d3..5b718b5 100644
--- a/nbd.c
+++ b/nbd.c
@@ -595,6 +595,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
 {
     struct nbd_request request;
     struct nbd_reply reply;
+    int ret;
 
     TRACE("Reading request.");
 
@@ -633,12 +634,13 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
     case NBD_CMD_READ:
         TRACE("Request type is READ");
 
-        if (bdrv_read(bs, (request.from + dev_offset) / 512,
-                  data + NBD_REPLY_SIZE,
-                  request.len / 512) == -1) {
+        ret = bdrv_read(bs, (request.from + dev_offset) / 512,
+                        data + NBD_REPLY_SIZE,
+                        request.len / 512);
+        if (ret < 0) {
             LOG("reading from file failed");
-            errno = EINVAL;
-            return -1;
+            reply.error = -ret;
+            request.len = 0;
         }
         *offset += request.len;
 
@@ -681,11 +683,12 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
         } else {
             TRACE("Writing to device");
 
-            if (bdrv_write(bs, (request.from + dev_offset) / 512,
-                       data, request.len / 512) == -1) {
+            ret = bdrv_write(bs, (request.from + dev_offset) / 512,
+                             data, request.len / 512);
+            if (ret < 0) {
                 LOG("writing to file failed");
-                errno = EINVAL;
-                return -1;
+                reply.error = -ret;
+                request.len = 0;
             }
 
             *offset += request.len;
commit ecda3447d18637c48469296c4ca8823f0a5c6717
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Sep 10 15:06:52 2011 +0200

    nbd: allow multiple in-flight requests
    
    Allow sending up to 16 requests, and drive the replies to the coroutine
    that did the request.  The code is written to be exactly the same as
    before this patch when MAX_NBD_REQUESTS == 1 (modulo the extra mutex
    and state).
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/nbd.c b/block/nbd.c
index 9d661c1..3f693e3 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -46,6 +46,10 @@
 #define logout(fmt, ...) ((void)0)
 #endif
 
+#define MAX_NBD_REQUESTS	16
+#define HANDLE_TO_INDEX(bs, handle) ((handle) ^ ((uint64_t)(intptr_t)bs))
+#define INDEX_TO_HANDLE(bs, index)  ((index)  ^ ((uint64_t)(intptr_t)bs))
+
 typedef struct BDRVNBDState {
     int sock;
     uint32_t nbdflags;
@@ -53,9 +57,12 @@ typedef struct BDRVNBDState {
     size_t blocksize;
     char *export_name; /* An NBD server may export several devices */
 
-    CoMutex mutex;
-    Coroutine *coroutine;
+    CoMutex send_mutex;
+    CoMutex free_sema;
+    Coroutine *send_coroutine;
+    int in_flight;
 
+    Coroutine *recv_coroutine[MAX_NBD_REQUESTS];
     struct nbd_reply reply;
 
     /* If it begins with  '/', this is a UNIX domain socket. Otherwise,
@@ -112,41 +119,68 @@ out:
 
 static void nbd_coroutine_start(BDRVNBDState *s, struct nbd_request *request)
 {
-    qemu_co_mutex_lock(&s->mutex);
-    s->coroutine = qemu_coroutine_self();
-    request->handle = (uint64_t)(intptr_t)s;
+    int i;
+
+    /* Poor man semaphore.  The free_sema is locked when no other request
+     * can be accepted, and unlocked after receiving one reply.  */
+    if (s->in_flight >= MAX_NBD_REQUESTS - 1) {
+        qemu_co_mutex_lock(&s->free_sema);
+        assert(s->in_flight < MAX_NBD_REQUESTS);
+    }
+    s->in_flight++;
+
+    for (i = 0; i < MAX_NBD_REQUESTS; i++) {
+        if (s->recv_coroutine[i] == NULL) {
+            s->recv_coroutine[i] = qemu_coroutine_self();
+            break;
+        }
+    }
+
+    assert(i < MAX_NBD_REQUESTS);
+    request->handle = INDEX_TO_HANDLE(s, i);
 }
 
 static int nbd_have_request(void *opaque)
 {
     BDRVNBDState *s = opaque;
 
-    return !!s->coroutine;
+    return s->in_flight > 0;
 }
 
 static void nbd_reply_ready(void *opaque)
 {
     BDRVNBDState *s = opaque;
+    int i;
 
     if (s->reply.handle == 0) {
         /* No reply already in flight.  Fetch a header.  */
         if (nbd_receive_reply(s->sock, &s->reply) < 0) {
             s->reply.handle = 0;
+            goto fail;
         }
     }
 
     /* There's no need for a mutex on the receive side, because the
      * handler acts as a synchronization point and ensures that only
      * one coroutine is called until the reply finishes.  */
-    if (s->coroutine) {
-        qemu_coroutine_enter(s->coroutine, NULL);
+    i = HANDLE_TO_INDEX(s, s->reply.handle);
+    if (s->recv_coroutine[i]) {
+        qemu_coroutine_enter(s->recv_coroutine[i], NULL);
+        return;
+    }
+
+fail:
+    for (i = 0; i < MAX_NBD_REQUESTS; i++) {
+        if (s->recv_coroutine[i]) {
+            qemu_coroutine_enter(s->recv_coroutine[i], NULL);
+        }
     }
 }
 
 static void nbd_restart_write(void *opaque)
 {
     BDRVNBDState *s = opaque;
-    qemu_coroutine_enter(s->coroutine, NULL);
+    qemu_coroutine_enter(s->send_coroutine, NULL);
 }
 
 static int nbd_co_send_request(BDRVNBDState *s, struct nbd_request *request,
@@ -154,6 +188,8 @@ static int nbd_co_send_request(BDRVNBDState *s, struct nbd_request *request,
 {
     int rc, ret;
 
+    qemu_co_mutex_lock(&s->send_mutex);
+    s->send_coroutine = qemu_coroutine_self();
     qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, nbd_restart_write,
                             nbd_have_request, NULL, s);
     rc = nbd_send_request(s->sock, request);
@@ -166,6 +202,8 @@ static int nbd_co_send_request(BDRVNBDState *s, struct nbd_request *request,
     }
     qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, NULL,
                             nbd_have_request, NULL, s);
+    s->send_coroutine = NULL;
+    qemu_co_mutex_unlock(&s->send_mutex);
     return rc;
 }
 
@@ -175,7 +213,8 @@ static void nbd_co_receive_reply(BDRVNBDState *s, struct nbd_request *request,
 {
     int ret;
 
-    /* Wait until we're woken up by the read handler.  */
+    /* Wait until we're woken up by the read handler.  TODO: perhaps
+     * peek at the next reply and avoid yielding if it's ours?  */
     qemu_coroutine_yield();
     *reply = s->reply;
     if (reply->handle != request->handle) {
@@ -195,8 +234,11 @@ static void nbd_co_receive_reply(BDRVNBDState *s, struct nbd_request *request,
 
 static void nbd_coroutine_end(BDRVNBDState *s, struct nbd_request *request)
 {
-    s->coroutine = NULL;
-    qemu_co_mutex_unlock(&s->mutex);
+    int i = HANDLE_TO_INDEX(s, request->handle);
+    s->recv_coroutine[i] = NULL;
+    if (s->in_flight-- == MAX_NBD_REQUESTS) {
+        qemu_co_mutex_unlock(&s->free_sema);
+    }
 }
 
 static int nbd_establish_connection(BlockDriverState *bs)
@@ -261,7 +303,8 @@ static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
     BDRVNBDState *s = bs->opaque;
     int result;
 
-    qemu_co_mutex_init(&s->mutex);
+    qemu_co_mutex_init(&s->send_mutex);
+    qemu_co_mutex_init(&s->free_sema);
 
     /* Pop the config into our state object. Exit if invalid. */
     result = nbd_config(s, filename, flags);
commit d9b09f13ca581aad92663dc90c2d57a775f3fb9c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Sep 10 15:06:52 2011 +0200

    nbd: split requests
    
    qemu-nbd has a limit of slightly less than 1M per request.  Work
    around this in the nbd block driver.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/nbd.c b/block/nbd.c
index bea7acd..9d661c1 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -277,8 +277,9 @@ static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
     return result;
 }
 
-static int nbd_co_readv(BlockDriverState *bs, int64_t sector_num,
-                        int nb_sectors, QEMUIOVector *qiov)
+static int nbd_co_readv_1(BlockDriverState *bs, int64_t sector_num,
+                          int nb_sectors, QEMUIOVector *qiov,
+                          int offset)
 {
     BDRVNBDState *s = bs->opaque;
     struct nbd_request request;
@@ -292,15 +293,16 @@ static int nbd_co_readv(BlockDriverState *bs, int64_t sector_num,
     if (nbd_co_send_request(s, &request, NULL, 0) == -1) {
         reply.error = errno;
     } else {
-        nbd_co_receive_reply(s, &request, &reply, qiov->iov, 0);
+        nbd_co_receive_reply(s, &request, &reply, qiov->iov, offset);
     }
     nbd_coroutine_end(s, &request);
     return -reply.error;
 
 }
 
-static int nbd_co_writev(BlockDriverState *bs, int64_t sector_num,
-                         int nb_sectors, QEMUIOVector *qiov)
+static int nbd_co_writev_1(BlockDriverState *bs, int64_t sector_num,
+                           int nb_sectors, QEMUIOVector *qiov,
+                           int offset)
 {
     BDRVNBDState *s = bs->opaque;
     struct nbd_request request;
@@ -311,7 +313,7 @@ static int nbd_co_writev(BlockDriverState *bs, int64_t sector_num,
     request.len = nb_sectors * 512;
 
     nbd_coroutine_start(s, &request);
-    if (nbd_co_send_request(s, &request, qiov->iov, 0) == -1) {
+    if (nbd_co_send_request(s, &request, qiov->iov, offset) == -1) {
         reply.error = errno;
     } else {
         nbd_co_receive_reply(s, &request, &reply, NULL, 0);
@@ -320,6 +322,44 @@ static int nbd_co_writev(BlockDriverState *bs, int64_t sector_num,
     return -reply.error;
 }
 
+/* qemu-nbd has a limit of slightly less than 1M per request.  Try to
+ * remain aligned to 4K. */
+#define NBD_MAX_SECTORS 2040
+
+static int nbd_co_readv(BlockDriverState *bs, int64_t sector_num,
+                        int nb_sectors, QEMUIOVector *qiov)
+{
+    int offset = 0;
+    int ret;
+    while (nb_sectors > NBD_MAX_SECTORS) {
+        ret = nbd_co_readv_1(bs, sector_num, NBD_MAX_SECTORS, qiov, offset);
+        if (ret < 0) {
+            return ret;
+        }
+        offset += NBD_MAX_SECTORS * 512;
+        sector_num += NBD_MAX_SECTORS;
+        nb_sectors -= NBD_MAX_SECTORS;
+    }
+    return nbd_co_readv_1(bs, sector_num, nb_sectors, qiov, offset);
+}
+
+static int nbd_co_writev(BlockDriverState *bs, int64_t sector_num,
+                         int nb_sectors, QEMUIOVector *qiov)
+{
+    int offset = 0;
+    int ret;
+    while (nb_sectors > NBD_MAX_SECTORS) {
+        ret = nbd_co_writev_1(bs, sector_num, NBD_MAX_SECTORS, qiov, offset);
+        if (ret < 0) {
+            return ret;
+        }
+        offset += NBD_MAX_SECTORS * 512;
+        sector_num += NBD_MAX_SECTORS;
+        nb_sectors -= NBD_MAX_SECTORS;
+    }
+    return nbd_co_writev_1(bs, sector_num, nb_sectors, qiov, offset);
+}
+
 static void nbd_close(BlockDriverState *bs)
 {
     BDRVNBDState *s = bs->opaque;
commit ae255e523c256cf0708f1c16cb946ff96340a800
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Sep 8 14:28:59 2011 +0200

    nbd: switch to asynchronous operation
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/nbd.c b/block/nbd.c
index 95212da..bea7acd 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -47,13 +47,17 @@
 #endif
 
 typedef struct BDRVNBDState {
-    CoMutex lock;
     int sock;
     uint32_t nbdflags;
     off_t size;
     size_t blocksize;
     char *export_name; /* An NBD server may export several devices */
 
+    CoMutex mutex;
+    Coroutine *coroutine;
+
+    struct nbd_reply reply;
+
     /* If it begins with  '/', this is a UNIX domain socket. Otherwise,
      * it's a string of the form <hostname|ip4|\[ip6\]>:port
      */
@@ -106,6 +110,95 @@ out:
     return err;
 }
 
+static void nbd_coroutine_start(BDRVNBDState *s, struct nbd_request *request)
+{
+    qemu_co_mutex_lock(&s->mutex);
+    s->coroutine = qemu_coroutine_self();
+    request->handle = (uint64_t)(intptr_t)s;
+}
+
+static int nbd_have_request(void *opaque)
+{
+    BDRVNBDState *s = opaque;
+
+    return !!s->coroutine;
+}
+
+static void nbd_reply_ready(void *opaque)
+{
+    BDRVNBDState *s = opaque;
+
+    if (s->reply.handle == 0) {
+        /* No reply already in flight.  Fetch a header.  */
+        if (nbd_receive_reply(s->sock, &s->reply) < 0) {
+            s->reply.handle = 0;
+        }
+    }
+
+    /* There's no need for a mutex on the receive side, because the
+     * handler acts as a synchronization point and ensures that only
+     * one coroutine is called until the reply finishes.  */
+    if (s->coroutine) {
+        qemu_coroutine_enter(s->coroutine, NULL);
+    }
+}
+
+static void nbd_restart_write(void *opaque)
+{
+    BDRVNBDState *s = opaque;
+    qemu_coroutine_enter(s->coroutine, NULL);
+}
+
+static int nbd_co_send_request(BDRVNBDState *s, struct nbd_request *request,
+                               struct iovec *iov, int offset)
+{
+    int rc, ret;
+
+    qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, nbd_restart_write,
+                            nbd_have_request, NULL, s);
+    rc = nbd_send_request(s->sock, request);
+    if (rc != -1 && iov) {
+        ret = qemu_co_sendv(s->sock, iov, request->len, offset);
+        if (ret != request->len) {
+            errno = -EIO;
+            rc = -1;
+        }
+    }
+    qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, NULL,
+                            nbd_have_request, NULL, s);
+    return rc;
+}
+
+static void nbd_co_receive_reply(BDRVNBDState *s, struct nbd_request *request,
+                                 struct nbd_reply *reply,
+                                 struct iovec *iov, int offset)
+{
+    int ret;
+
+    /* Wait until we're woken up by the read handler.  */
+    qemu_coroutine_yield();
+    *reply = s->reply;
+    if (reply->handle != request->handle) {
+        reply->error = EIO;
+    } else {
+        if (iov && reply->error == 0) {
+            ret = qemu_co_recvv(s->sock, iov, request->len, offset);
+            if (ret != request->len) {
+                reply->error = EIO;
+            }
+        }
+
+        /* Tell the read handler to read another header.  */
+        s->reply.handle = 0;
+    }
+}
+
+static void nbd_coroutine_end(BDRVNBDState *s, struct nbd_request *request)
+{
+    s->coroutine = NULL;
+    qemu_co_mutex_unlock(&s->mutex);
+}
+
 static int nbd_establish_connection(BlockDriverState *bs)
 {
     BDRVNBDState *s = bs->opaque;
@@ -135,8 +228,11 @@ static int nbd_establish_connection(BlockDriverState *bs)
         return -errno;
     }
 
-    /* Now that we're connected, set the socket to be non-blocking */
+    /* Now that we're connected, set the socket to be non-blocking and
+     * kick the reply mechanism.  */
     socket_set_nonblock(sock);
+    qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, NULL,
+                            nbd_have_request, NULL, s);
 
     s->sock = sock;
     s->size = size;
@@ -152,11 +248,11 @@ static void nbd_teardown_connection(BlockDriverState *bs)
     struct nbd_request request;
 
     request.type = NBD_CMD_DISC;
-    request.handle = (uint64_t)(intptr_t)bs;
     request.from = 0;
     request.len = 0;
     nbd_send_request(s->sock, &request);
 
+    qemu_aio_set_fd_handler(s->sock, NULL, NULL, NULL, NULL, NULL);
     closesocket(s->sock);
 }
 
@@ -165,6 +261,8 @@ static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
     BDRVNBDState *s = bs->opaque;
     int result;
 
+    qemu_co_mutex_init(&s->mutex);
+
     /* Pop the config into our state object. Exit if invalid. */
     result = nbd_config(s, filename, flags);
     if (result != 0) {
@@ -176,90 +274,50 @@ static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
      */
     result = nbd_establish_connection(bs);
 
-    qemu_co_mutex_init(&s->lock);
     return result;
 }
 
-static int nbd_read(BlockDriverState *bs, int64_t sector_num,
-                    uint8_t *buf, int nb_sectors)
+static int nbd_co_readv(BlockDriverState *bs, int64_t sector_num,
+                        int nb_sectors, QEMUIOVector *qiov)
 {
     BDRVNBDState *s = bs->opaque;
     struct nbd_request request;
     struct nbd_reply reply;
 
     request.type = NBD_CMD_READ;
-    request.handle = (uint64_t)(intptr_t)bs;
     request.from = sector_num * 512;
     request.len = nb_sectors * 512;
 
-    if (nbd_send_request(s->sock, &request) == -1)
-        return -errno;
-
-    if (nbd_receive_reply(s->sock, &reply) == -1)
-        return -errno;
-
-    if (reply.error !=0)
-        return -reply.error;
-
-    if (reply.handle != request.handle)
-        return -EIO;
-
-    if (nbd_wr_sync(s->sock, buf, request.len, 1) != request.len)
-        return -EIO;
+    nbd_coroutine_start(s, &request);
+    if (nbd_co_send_request(s, &request, NULL, 0) == -1) {
+        reply.error = errno;
+    } else {
+        nbd_co_receive_reply(s, &request, &reply, qiov->iov, 0);
+    }
+    nbd_coroutine_end(s, &request);
+    return -reply.error;
 
-    return 0;
 }
 
-static int nbd_write(BlockDriverState *bs, int64_t sector_num,
-                     const uint8_t *buf, int nb_sectors)
+static int nbd_co_writev(BlockDriverState *bs, int64_t sector_num,
+                         int nb_sectors, QEMUIOVector *qiov)
 {
     BDRVNBDState *s = bs->opaque;
     struct nbd_request request;
     struct nbd_reply reply;
 
     request.type = NBD_CMD_WRITE;
-    request.handle = (uint64_t)(intptr_t)bs;
     request.from = sector_num * 512;
     request.len = nb_sectors * 512;
 
-    if (nbd_send_request(s->sock, &request) == -1)
-        return -errno;
-
-    if (nbd_wr_sync(s->sock, (uint8_t*)buf, request.len, 0) != request.len)
-        return -EIO;
-
-    if (nbd_receive_reply(s->sock, &reply) == -1)
-        return -errno;
-
-    if (reply.error !=0)
-        return -reply.error;
-
-    if (reply.handle != request.handle)
-        return -EIO;
-
-    return 0;
-}
-
-static coroutine_fn int nbd_co_read(BlockDriverState *bs, int64_t sector_num,
-                                    uint8_t *buf, int nb_sectors)
-{
-    int ret;
-    BDRVNBDState *s = bs->opaque;
-    qemu_co_mutex_lock(&s->lock);
-    ret = nbd_read(bs, sector_num, buf, nb_sectors);
-    qemu_co_mutex_unlock(&s->lock);
-    return ret;
-}
-
-static coroutine_fn int nbd_co_write(BlockDriverState *bs, int64_t sector_num,
-                                     const uint8_t *buf, int nb_sectors)
-{
-    int ret;
-    BDRVNBDState *s = bs->opaque;
-    qemu_co_mutex_lock(&s->lock);
-    ret = nbd_write(bs, sector_num, buf, nb_sectors);
-    qemu_co_mutex_unlock(&s->lock);
-    return ret;
+    nbd_coroutine_start(s, &request);
+    if (nbd_co_send_request(s, &request, qiov->iov, 0) == -1) {
+        reply.error = errno;
+    } else {
+        nbd_co_receive_reply(s, &request, &reply, NULL, 0);
+    }
+    nbd_coroutine_end(s, &request);
+    return -reply.error;
 }
 
 static void nbd_close(BlockDriverState *bs)
@@ -282,8 +340,8 @@ static BlockDriver bdrv_nbd = {
     .format_name	= "nbd",
     .instance_size	= sizeof(BDRVNBDState),
     .bdrv_file_open	= nbd_open,
-    .bdrv_read          = nbd_co_read,
-    .bdrv_write         = nbd_co_write,
+    .bdrv_co_readv	= nbd_co_readv,
+    .bdrv_co_writev	= nbd_co_writev,
     .bdrv_close		= nbd_close,
     .bdrv_getlength	= nbd_getlength,
     .protocol_name	= "nbd",
diff --git a/nbd.c b/nbd.c
index de880fe..ff701d3 100644
--- a/nbd.c
+++ b/nbd.c
@@ -81,6 +81,14 @@ size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read)
 {
     size_t offset = 0;
 
+    if (qemu_in_coroutine()) {
+        if (do_read) {
+            return qemu_co_recv(fd, buffer, size);
+        } else {
+            return qemu_co_send(fd, buffer, size);
+        }
+    }
+
     while (offset < size) {
         ssize_t len;
 
commit 8c5135f90e2dcf1d5c3d03106e0ac6e371ccb572
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Sep 8 13:46:25 2011 +0200

    sheepdog: move coroutine send/recv function to generic code
    
    Outside coroutines, avoid busy waiting on EAGAIN by temporarily
    making the socket blocking.
    
    The API of qemu_recvv/qemu_sendv is slightly different from
    do_readv/do_writev because they do not handle coroutines.  It
    returns the number of bytes written before encountering an
    EAGAIN.  The specificity of yielding on EAGAIN is entirely in
    qemu-coroutine.c.
    
    Reviewed-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index f753d83..8813673 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -12,7 +12,7 @@ oslib-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o
 
 #######################################################################
 # coroutines
-coroutine-obj-y = qemu-coroutine.o qemu-coroutine-lock.o
+coroutine-obj-y = qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
 ifeq ($(CONFIG_UCONTEXT_COROUTINE),y)
 coroutine-obj-$(CONFIG_POSIX) += coroutine-ucontext.o
 else
diff --git a/block/sheepdog.c b/block/sheepdog.c
index aa9707f..00ea5a0 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -443,129 +443,6 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
     return acb;
 }
 
-#ifdef _WIN32
-
-struct msghdr {
-    struct iovec *msg_iov;
-    size_t        msg_iovlen;
-};
-
-static ssize_t sendmsg(int s, const struct msghdr *msg, int flags)
-{
-    size_t size = 0;
-    char *buf, *p;
-    int i, ret;
-
-    /* count the msg size */
-    for (i = 0; i < msg->msg_iovlen; i++) {
-        size += msg->msg_iov[i].iov_len;
-    }
-    buf = g_malloc(size);
-
-    p = buf;
-    for (i = 0; i < msg->msg_iovlen; i++) {
-        memcpy(p, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
-        p += msg->msg_iov[i].iov_len;
-    }
-
-    ret = send(s, buf, size, flags);
-
-    g_free(buf);
-    return ret;
-}
-
-static ssize_t recvmsg(int s, struct msghdr *msg, int flags)
-{
-    size_t size = 0;
-    char *buf, *p;
-    int i, ret;
-
-    /* count the msg size */
-    for (i = 0; i < msg->msg_iovlen; i++) {
-        size += msg->msg_iov[i].iov_len;
-    }
-    buf = g_malloc(size);
-
-    ret = qemu_recv(s, buf, size, flags);
-    if (ret < 0) {
-        goto out;
-    }
-
-    p = buf;
-    for (i = 0; i < msg->msg_iovlen; i++) {
-        memcpy(msg->msg_iov[i].iov_base, p, msg->msg_iov[i].iov_len);
-        p += msg->msg_iov[i].iov_len;
-    }
-out:
-    g_free(buf);
-    return ret;
-}
-
-#endif
-
-/*
- * Send/recv data with iovec buffers
- *
- * This function send/recv data from/to the iovec buffer directly.
- * The first `offset' bytes in the iovec buffer are skipped and next
- * `len' bytes are used.
- *
- * For example,
- *
- *   do_send_recv(sockfd, iov, len, offset, 1);
- *
- * is equals to
- *
- *   char *buf = malloc(size);
- *   iov_to_buf(iov, iovcnt, buf, offset, size);
- *   send(sockfd, buf, size, 0);
- *   free(buf);
- */
-static int do_send_recv(int sockfd, struct iovec *iov, int len, int offset,
-                        int write)
-{
-    struct msghdr msg;
-    int ret, diff;
-
-    memset(&msg, 0, sizeof(msg));
-    msg.msg_iov = iov;
-    msg.msg_iovlen = 1;
-
-    len += offset;
-
-    while (iov->iov_len < len) {
-        len -= iov->iov_len;
-
-        iov++;
-        msg.msg_iovlen++;
-    }
-
-    diff = iov->iov_len - len;
-    iov->iov_len -= diff;
-
-    while (msg.msg_iov->iov_len <= offset) {
-        offset -= msg.msg_iov->iov_len;
-
-        msg.msg_iov++;
-        msg.msg_iovlen--;
-    }
-
-    msg.msg_iov->iov_base = (char *) msg.msg_iov->iov_base + offset;
-    msg.msg_iov->iov_len -= offset;
-
-    if (write) {
-        ret = sendmsg(sockfd, &msg, 0);
-    } else {
-        ret = recvmsg(sockfd, &msg, 0);
-    }
-
-    msg.msg_iov->iov_base = (char *) msg.msg_iov->iov_base - offset;
-    msg.msg_iov->iov_len += offset;
-
-    iov->iov_len += diff;
-    return ret;
-}
-
 static int connect_to_sdog(const char *addr, const char *port)
 {
     char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
@@ -618,83 +495,19 @@ success:
     return fd;
 }
 
-static int do_readv_writev(int sockfd, struct iovec *iov, int len,
-                           int iov_offset, int write)
-{
-    int ret;
-again:
-    ret = do_send_recv(sockfd, iov, len, iov_offset, write);
-    if (ret < 0) {
-        if (errno == EINTR) {
-            goto again;
-        }
-        if (errno == EAGAIN) {
-            if (qemu_in_coroutine()) {
-                qemu_coroutine_yield();
-            }
-            goto again;
-        }
-        error_report("failed to recv a rsp, %s", strerror(errno));
-        return 1;
-    }
-
-    iov_offset += ret;
-    len -= ret;
-    if (len) {
-        goto again;
-    }
-
-    return 0;
-}
-
-static int do_readv(int sockfd, struct iovec *iov, int len, int iov_offset)
-{
-    return do_readv_writev(sockfd, iov, len, iov_offset, 0);
-}
-
-static int do_writev(int sockfd, struct iovec *iov, int len, int iov_offset)
-{
-    return do_readv_writev(sockfd, iov, len, iov_offset, 1);
-}
-
-static int do_read_write(int sockfd, void *buf, int len, int write)
-{
-    struct iovec iov;
-
-    iov.iov_base = buf;
-    iov.iov_len = len;
-
-    return do_readv_writev(sockfd, &iov, len, 0, write);
-}
-
-static int do_read(int sockfd, void *buf, int len)
-{
-    return do_read_write(sockfd, buf, len, 0);
-}
-
-static int do_write(int sockfd, void *buf, int len)
-{
-    return do_read_write(sockfd, buf, len, 1);
-}
-
 static int send_req(int sockfd, SheepdogReq *hdr, void *data,
                     unsigned int *wlen)
 {
     int ret;
-    struct iovec iov[2];
 
-    iov[0].iov_base = hdr;
-    iov[0].iov_len = sizeof(*hdr);
-
-    if (*wlen) {
-        iov[1].iov_base = data;
-        iov[1].iov_len = *wlen;
+    ret = qemu_send_full(sockfd, hdr, sizeof(*hdr), 0);
+    if (ret < sizeof(*hdr)) {
+        error_report("failed to send a req, %s", strerror(errno));
     }
 
-    ret = do_writev(sockfd, iov, sizeof(*hdr) + *wlen, 0);
-    if (ret) {
+    ret = qemu_send_full(sockfd, data, *wlen, 0);
+    if (ret < *wlen) {
         error_report("failed to send a req, %s", strerror(errno));
-        ret = -1;
     }
 
     return ret;
@@ -705,16 +518,15 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
 {
     int ret;
 
+    socket_set_block(sockfd);
     ret = send_req(sockfd, hdr, data, wlen);
-    if (ret) {
-        ret = -1;
+    if (ret < 0) {
         goto out;
     }
 
-    ret = do_read(sockfd, hdr, sizeof(*hdr));
-    if (ret) {
+    ret = qemu_recv_full(sockfd, hdr, sizeof(*hdr), 0);
+    if (ret < sizeof(*hdr)) {
         error_report("failed to get a rsp, %s", strerror(errno));
-        ret = -1;
         goto out;
     }
 
@@ -723,15 +535,15 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
     }
 
     if (*rlen) {
-        ret = do_read(sockfd, data, *rlen);
-        if (ret) {
+        ret = qemu_recv_full(sockfd, data, *rlen, 0);
+        if (ret < *rlen) {
             error_report("failed to get the data, %s", strerror(errno));
-            ret = -1;
             goto out;
         }
     }
     ret = 0;
 out:
+    socket_set_nonblock(sockfd);
     return ret;
 }
 
@@ -793,8 +605,8 @@ static void coroutine_fn aio_read_response(void *opaque)
     }
 
     /* read a header */
-    ret = do_read(fd, &rsp, sizeof(rsp));
-    if (ret) {
+    ret = qemu_co_recv(fd, &rsp, sizeof(rsp));
+    if (ret < 0) {
         error_report("failed to get the header, %s", strerror(errno));
         goto out;
     }
@@ -839,9 +651,9 @@ static void coroutine_fn aio_read_response(void *opaque)
         }
         break;
     case AIOCB_READ_UDATA:
-        ret = do_readv(fd, acb->qiov->iov, rsp.data_length,
-                       aio_req->iov_offset);
-        if (ret) {
+        ret = qemu_co_recvv(fd, acb->qiov->iov, rsp.data_length,
+                            aio_req->iov_offset);
+        if (ret < 0) {
             error_report("failed to get the data, %s", strerror(errno));
             goto out;
         }
@@ -1114,16 +926,16 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
     set_cork(s->fd, 1);
 
     /* send a header */
-    ret = do_write(s->fd, &hdr, sizeof(hdr));
-    if (ret) {
+    ret = qemu_co_send(s->fd, &hdr, sizeof(hdr));
+    if (ret < 0) {
         qemu_co_mutex_unlock(&s->lock);
         error_report("failed to send a req, %s", strerror(errno));
         return -EIO;
     }
 
     if (wlen) {
-        ret = do_writev(s->fd, iov, wlen, aio_req->iov_offset);
-        if (ret) {
+        ret = qemu_co_sendv(s->fd, iov, wlen, aio_req->iov_offset);
+        if (ret < 0) {
             qemu_co_mutex_unlock(&s->lock);
             error_report("failed to send a data, %s", strerror(errno));
             return -EIO;
diff --git a/cutils.c b/cutils.c
index 24b3fe3..a6ffd46 100644
--- a/cutils.c
+++ b/cutils.c
@@ -25,6 +25,8 @@
 #include "host-utils.h"
 #include <math.h>
 
+#include "qemu_socket.h"
+
 void pstrcpy(char *buf, int buf_size, const char *str)
 {
     int c;
@@ -403,3 +405,112 @@ int qemu_parse_fd(const char *param)
     }
     return fd;
 }
+
+/*
+ * Send/recv data with iovec buffers
+ *
+ * This function send/recv data from/to the iovec buffer directly.
+ * The first `offset' bytes in the iovec buffer are skipped and next
+ * `len' bytes are used.
+ *
+ * For example,
+ *
+ *   do_sendv_recvv(sockfd, iov, len, offset, 1);
+ *
+ * is equal to
+ *
+ *   char *buf = malloc(size);
+ *   iov_to_buf(iov, iovcnt, buf, offset, size);
+ *   send(sockfd, buf, size, 0);
+ *   free(buf);
+ */
+static int do_sendv_recvv(int sockfd, struct iovec *iov, int len, int offset,
+                          int do_sendv)
+{
+    int ret, diff, iovlen;
+    struct iovec *last_iov;
+
+    /* last_iov is inclusive, so count from one.  */
+    iovlen = 1;
+    last_iov = iov;
+    len += offset;
+
+    while (last_iov->iov_len < len) {
+        len -= last_iov->iov_len;
+
+        last_iov++;
+        iovlen++;
+    }
+
+    diff = last_iov->iov_len - len;
+    last_iov->iov_len -= diff;
+
+    while (iov->iov_len <= offset) {
+        offset -= iov->iov_len;
+
+        iov++;
+        iovlen--;
+    }
+
+    iov->iov_base = (char *) iov->iov_base + offset;
+    iov->iov_len -= offset;
+
+    {
+#if defined CONFIG_IOVEC && defined CONFIG_POSIX
+        struct msghdr msg;
+        memset(&msg, 0, sizeof(msg));
+        msg.msg_iov = iov;
+        msg.msg_iovlen = iovlen;
+
+        do {
+            if (do_sendv) {
+                ret = sendmsg(sockfd, &msg, 0);
+            } else {
+                ret = recvmsg(sockfd, &msg, 0);
+            }
+        } while (ret == -1 && errno == EINTR);
+#else
+        struct iovec *p = iov;
+        ret = 0;
+        while (iovlen > 0) {
+            int rc;
+            if (do_sendv) {
+                rc = send(sockfd, p->iov_base, p->iov_len, 0);
+            } else {
+                rc = qemu_recv(sockfd, p->iov_base, p->iov_len, 0);
+            }
+            if (rc == -1) {
+                if (errno == EINTR) {
+                    continue;
+                }
+                if (ret == 0) {
+                    ret = -1;
+                }
+                break;
+            }
+            if (rc == 0) {
+                break;
+            }
+            ret += rc;
+            iovlen--, p++;
+        }
+#endif
+    }
+
+    /* Undo the changes above */
+    iov->iov_base = (char *) iov->iov_base - offset;
+    iov->iov_len += offset;
+    last_iov->iov_len += diff;
+    return ret;
+}
+
+int qemu_recvv(int sockfd, struct iovec *iov, int len, int iov_offset)
+{
+    return do_sendv_recvv(sockfd, iov, len, iov_offset, 0);
+}
+
+int qemu_sendv(int sockfd, struct iovec *iov, int len, int iov_offset)
+{
+    return do_sendv_recvv(sockfd, iov, len, iov_offset, 1);
+}
+
diff --git a/qemu-common.h b/qemu-common.h
index 5c3f3af..6ab7dfb 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -175,7 +175,7 @@ ssize_t qemu_write_full(int fd, const void *buf, size_t count)
     QEMU_WARN_UNUSED_RESULT;
 ssize_t qemu_send_full(int fd, const void *buf, size_t count, int flags)
     QEMU_WARN_UNUSED_RESULT;
-ssize_t qemu_recv_full(int fd, const void *buf, size_t count, int flags)
+ssize_t qemu_recv_full(int fd, void *buf, size_t count, int flags)
     QEMU_WARN_UNUSED_RESULT;
 void qemu_set_cloexec(int fd);
 
@@ -190,6 +190,9 @@ int qemu_pipe(int pipefd[2]);
 #define qemu_recv(sockfd, buf, len, flags) recv(sockfd, buf, len, flags)
 #endif
 
+int qemu_recvv(int sockfd, struct iovec *iov, int len, int iov_offset);
+int qemu_sendv(int sockfd, struct iovec *iov, int len, int iov_offset);
+
 /* Error handling.  */
 
 void QEMU_NORETURN hw_error(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
@@ -276,6 +279,33 @@ struct qemu_work_item {
 void qemu_init_vcpu(void *env);
 #endif
 
+/**
+ * Sends an iovec (or optionally a part of it) down a socket, yielding
+ * when the socket is full.
+ */
+int qemu_co_sendv(int sockfd, struct iovec *iov,
+                  int len, int iov_offset);
+
+/**
+ * Receives data into an iovec (or optionally into a part of it) from
+ * a socket, yielding when there is no data in the socket.
+ */
+int qemu_co_recvv(int sockfd, struct iovec *iov,
+                  int len, int iov_offset);
+
+
+/**
+ * Sends a buffer down a socket, yielding when the socket is full.
+ */
+int qemu_co_send(int sockfd, void *buf, int len);
+
+/**
+ * Receives data into a buffer from a socket, yielding when there
+ * is no data in the socket.
+ */
+int qemu_co_recv(int sockfd, void *buf, int len);
+
+
 typedef struct QEMUIOVector {
     struct iovec *iov;
     int niov;
diff --git a/qemu-coroutine-io.c b/qemu-coroutine-io.c
new file mode 100644
index 0000000..40fd514
--- /dev/null
+++ b/qemu-coroutine-io.c
@@ -0,0 +1,96 @@
+/*
+ * Coroutine-aware I/O functions
+ *
+ * Copyright (C) 2009-2010 Nippon Telegraph and Telephone Corporation.
+ * Copyright (c) 2011, Red Hat, 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 "qemu-common.h"
+#include "qemu_socket.h"
+#include "qemu-coroutine.h"
+
+int coroutine_fn qemu_co_recvv(int sockfd, struct iovec *iov,
+                               int len, int iov_offset)
+{
+    int total = 0;
+    int ret;
+    while (len) {
+        ret = qemu_recvv(sockfd, iov, len, iov_offset + total);
+        if (ret < 0) {
+            if (errno == EAGAIN) {
+                qemu_coroutine_yield();
+                continue;
+            }
+            if (total == 0) {
+                total = -1;
+            }
+            break;
+        }
+        if (ret == 0) {
+            break;
+        }
+        total += ret, len -= ret;
+    }
+
+    return total;
+}
+
+int coroutine_fn qemu_co_sendv(int sockfd, struct iovec *iov,
+                               int len, int iov_offset)
+{
+    int total = 0;
+    int ret;
+    while (len) {
+        ret = qemu_sendv(sockfd, iov, len, iov_offset + total);
+        if (ret < 0) {
+            if (errno == EAGAIN) {
+                qemu_coroutine_yield();
+                continue;
+            }
+            if (total == 0) {
+                total = -1;
+            }
+            break;
+        }
+        total += ret, len -= ret;
+    }
+
+    return total;
+}
+
+int coroutine_fn qemu_co_recv(int sockfd, void *buf, int len)
+{
+    struct iovec iov;
+
+    iov.iov_base = buf;
+    iov.iov_len = len;
+
+    return qemu_co_recvv(sockfd, &iov, len, 0);
+}
+
+int coroutine_fn qemu_co_send(int sockfd, void *buf, int len)
+{
+    struct iovec iov;
+
+    iov.iov_base = buf;
+    iov.iov_len = len;
+
+    return qemu_co_sendv(sockfd, &iov, len, 0);
+}
commit 03ecd2c80a64d030a22fe67cc7a60f24e17ff211
Author: Amit Shah <amit.shah at redhat.com>
Date:   Wed Dec 21 12:28:29 2011 +0530

    virtio-serial-bus: Ports are expected to implement 'have_data' callback
    
    There's no need to check if ports can accept any incoming data from the
    guest each time the guest sends data.  Check if the port implements such
    functionality during port initialisation.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index a4825b9..fe0233f 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -466,13 +466,11 @@ static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
 {
     VirtIOSerial *vser;
     VirtIOSerialPort *port;
-    VirtIOSerialPortInfo *info;
 
     vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
     port = find_port_by_vq(vser, vq);
-    info = port ? DO_UPCAST(VirtIOSerialPortInfo, qdev, port->dev.info) : NULL;
 
-    if (!port || !port->host_connected || !info->have_data) {
+    if (!port || !port->host_connected) {
         discard_vq_data(vq, vdev);
         return;
     }
@@ -746,6 +744,8 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
     port->vser = bus->vser;
     port->bh = qemu_bh_new(flush_queued_data_bh, port);
 
+    assert(info->have_data);
+
     /*
      * Is the first console port we're seeing? If so, put it up at
      * location 0. This is done for backward compatibility (old
commit 05e7af694ce00dafdc464ca70306fa9dd6f78dcd
Author: Amit Shah <amit.shah at redhat.com>
Date:   Wed Dec 21 12:28:28 2011 +0530

    virtio-console: Properly initialise class methods
    
    The earlier code really was a hack: initialising class methods in an
    object init function as noted by Anthony.
    
    The motivation for that was to not have the virtio-serial-bus call into
    the callback functions if there was no chardev backend registered.
    However, that really wasn't a worthwhile optimisation, and definitely
    not one that was well-implemented.  Get rid of it.
    
    Reported-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index dbbea76..73d866a 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -120,9 +120,6 @@ static int virtconsole_initfn(VirtIOSerialPort *port)
     if (vcon->chr) {
         qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
                               vcon);
-        info->have_data = flush_buf;
-        info->guest_open = guest_open;
-        info->guest_close = guest_close;
     }
 
     return 0;
@@ -149,6 +146,9 @@ static VirtIOSerialPortInfo virtconsole_info = {
     .is_console    = true,
     .init          = virtconsole_initfn,
     .exit          = virtconsole_exitfn,
+    .have_data     = flush_buf,
+    .guest_open    = guest_open,
+    .guest_close   = guest_close,
     .qdev.props = (Property[]) {
         DEFINE_PROP_CHR("chardev", VirtConsole, chr),
         DEFINE_PROP_END_OF_LIST(),
@@ -166,6 +166,9 @@ static VirtIOSerialPortInfo virtserialport_info = {
     .qdev.size     = sizeof(VirtConsole),
     .init          = virtconsole_initfn,
     .exit          = virtconsole_exitfn,
+    .have_data     = flush_buf,
+    .guest_open    = guest_open,
+    .guest_close   = guest_close,
     .qdev.props = (Property[]) {
         DEFINE_PROP_CHR("chardev", VirtConsole, chr),
         DEFINE_PROP_END_OF_LIST(),
commit 6640422c172e01d0e191a754d3643a68abca83bc
Author: Amit Shah <amit.shah at redhat.com>
Date:   Wed Dec 21 12:28:27 2011 +0530

    virtio-console: Check if chardev backends available before calling into them
    
    For the callback functions invoked by the virtio-serial-bus code, check
    if we have chardev backends registered before we call into the chardev
    functions.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Reported-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index d3351c8..dbbea76 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -27,6 +27,11 @@ static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
     ssize_t ret;
 
+    if (!vcon->chr) {
+        /* If there's no backend, we can just say we consumed all data. */
+        return len;
+    }
+
     ret = qemu_chr_fe_write(vcon->chr, buf, len);
     trace_virtio_console_flush_buf(port->id, len, ret);
 
@@ -52,6 +57,9 @@ static void guest_open(VirtIOSerialPort *port)
 {
     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
 
+    if (!vcon->chr) {
+        return;
+    }
     qemu_chr_fe_open(vcon->chr);
 }
 
@@ -60,6 +68,9 @@ static void guest_close(VirtIOSerialPort *port)
 {
     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
 
+    if (!vcon->chr) {
+        return;
+    }
     qemu_chr_fe_close(vcon->chr);
 }
 
commit 993295fedc5fefaefee9ac80e057d8bf08026ef4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Sep 17 16:27:59 2011 +0200

    add qemu_send_full and qemu_recv_full
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/osdep.c b/osdep.c
index 56e6963..70bad27 100644
--- a/osdep.c
+++ b/osdep.c
@@ -166,3 +166,70 @@ int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
 
     return ret;
 }
+
+/*
+ * A variant of send(2) which handles partial write.
+ *
+ * Return the number of bytes transferred, which is only
+ * smaller than `count' if there is an error.
+ *
+ * This function won't work with non-blocking fd's.
+ * Any of the possibilities with non-bloking fd's is bad:
+ *   - return a short write (then name is wrong)
+ *   - busy wait adding (errno == EAGAIN) to the loop
+ */
+ssize_t qemu_send_full(int fd, const void *buf, size_t count, int flags)
+{
+    ssize_t ret = 0;
+    ssize_t total = 0;
+
+    while (count) {
+        ret = send(fd, buf, count, flags);
+        if (ret < 0) {
+            if (errno == EINTR) {
+                continue;
+            }
+            break;
+        }
+
+        count -= ret;
+        buf += ret;
+        total += ret;
+    }
+
+    return total;
+}
+
+/*
+ * A variant of recv(2) which handles partial write.
+ *
+ * Return the number of bytes transferred, which is only
+ * smaller than `count' if there is an error.
+ *
+ * This function won't work with non-blocking fd's.
+ * Any of the possibilities with non-bloking fd's is bad:
+ *   - return a short write (then name is wrong)
+ *   - busy wait adding (errno == EAGAIN) to the loop
+ */
+ssize_t qemu_recv_full(int fd, void *buf, size_t count, int flags)
+{
+    ssize_t ret = 0;
+    ssize_t total = 0;
+
+    while (count) {
+        ret = qemu_recv(fd, buf, count, flags);
+        if (ret <= 0) {
+            if (ret < 0 && errno == EINTR) {
+                continue;
+            }
+            break;
+        }
+
+        count -= ret;
+        buf += ret;
+        total += ret;
+    }
+
+    return total;
+}
+
diff --git a/qemu-common.h b/qemu-common.h
index b2de015..5c3f3af 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -173,6 +173,10 @@ void *qemu_oom_check(void *ptr);
 int qemu_open(const char *name, int flags, ...);
 ssize_t qemu_write_full(int fd, const void *buf, size_t count)
     QEMU_WARN_UNUSED_RESULT;
+ssize_t qemu_send_full(int fd, const void *buf, size_t count, int flags)
+    QEMU_WARN_UNUSED_RESULT;
+ssize_t qemu_recv_full(int fd, const void *buf, size_t count, int flags)
+    QEMU_WARN_UNUSED_RESULT;
 void qemu_set_cloexec(int fd);
 
 #ifndef _WIN32
commit 058a96ed506d77714bcce3d69b351e364078c080
Author: Harsh Prateek Bora <harsh at linux.vnet.ibm.com>
Date:   Wed Dec 21 12:37:23 2011 +0530

    scripts/analyse-9p-simpletrace.py:	Add symbolic names for 9p operations.
    
    Currently, we just print the numerical value of 9p operation identifier in
    case of RERROR which is less meaningful for readability. Mapping 9p
    operation ids to symbolic names provides a better tracelog:
    
    	RERROR (tag = 1 , id = TWALK , err = " No such file or directory ")
    	RERROR (tag = 1 , id = TUNLINKAT , err = " Directory not empty ")
    
    This patch provides a dictionary of all possible 9p operation symbols mapped
    to their numerical identifiers which are likely to be used in future at
    various places in this script.
    
    Signed-off-by: Harsh Prateek Bora <harsh at linux.vnet.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/scripts/analyse-9p-simpletrace.py b/scripts/analyse-9p-simpletrace.py
index b6d58fd..3c3dee4 100755
--- a/scripts/analyse-9p-simpletrace.py
+++ b/scripts/analyse-9p-simpletrace.py
@@ -3,15 +3,86 @@
 # Usage: ./analyse-9p-simpletrace <trace-events> <trace-pid>
 #
 # Author: Harsh Prateek Bora
-
+import os
 import simpletrace
 
+symbol_9p = {
+    6   : 'TLERROR',
+    7   : 'RLERROR',
+    8   : 'TSTATFS',
+    9   : 'RSTATFS',
+    12  : 'TLOPEN',
+    13  : 'RLOPEN',
+    14  : 'TLCREATE',
+    15  : 'RLCREATE',
+    16  : 'TSYMLINK',
+    17  : 'RSYMLINK',
+    18  : 'TMKNOD',
+    19  : 'RMKNOD',
+    20  : 'TRENAME',
+    21  : 'RRENAME',
+    22  : 'TREADLINK',
+    23  : 'RREADLINK',
+    24  : 'TGETATTR',
+    25  : 'RGETATTR',
+    26  : 'TSETATTR',
+    27  : 'RSETATTR',
+    30  : 'TXATTRWALK',
+    31  : 'RXATTRWALK',
+    32  : 'TXATTRCREATE',
+    33  : 'RXATTRCREATE',
+    40  : 'TREADDIR',
+    41  : 'RREADDIR',
+    50  : 'TFSYNC',
+    51  : 'RFSYNC',
+    52  : 'TLOCK',
+    53  : 'RLOCK',
+    54  : 'TGETLOCK',
+    55  : 'RGETLOCK',
+    70  : 'TLINK',
+    71  : 'RLINK',
+    72  : 'TMKDIR',
+    73  : 'RMKDIR',
+    74  : 'TRENAMEAT',
+    75  : 'RRENAMEAT',
+    76  : 'TUNLINKAT',
+    77  : 'RUNLINKAT',
+    100 : 'TVERSION',
+    101 : 'RVERSION',
+    102 : 'TAUTH',
+    103 : 'RAUTH',
+    104 : 'TATTACH',
+    105 : 'RATTACH',
+    106 : 'TERROR',
+    107 : 'RERROR',
+    108 : 'TFLUSH',
+    109 : 'RFLUSH',
+    110 : 'TWALK',
+    111 : 'RWALK',
+    112 : 'TOPEN',
+    113 : 'ROPEN',
+    114 : 'TCREATE',
+    115 : 'RCREATE',
+    116 : 'TREAD',
+    117 : 'RREAD',
+    118 : 'TWRITE',
+    119 : 'RWRITE',
+    120 : 'TCLUNK',
+    121 : 'RCLUNK',
+    122 : 'TREMOVE',
+    123 : 'RREMOVE',
+    124 : 'TSTAT',
+    125 : 'RSTAT',
+    126 : 'TWSTAT',
+    127 : 'RWSTAT'
+}
+
 class VirtFSRequestTracker(simpletrace.Analyzer):
         def begin(self):
                 print "Pretty printing 9p simpletrace log ..."
 
         def v9fs_rerror(self, tag, id, err):
-                print "RERROR (tag =", tag, ", id =", id, ",err =", err, ")"
+                print "RERROR (tag =", tag, ", id =", symbol_9p[id], ", err = \"", os.strerror(err), "\")"
 
         def v9fs_version(self, tag, id, msize, version):
                 print "TVERSION (tag =", tag, ", msize =", msize, ", version =", version, ")"
commit e4027caf9373c5797b7769f5120c249e31ab5487
Author: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
Date:   Wed Dec 21 12:37:23 2011 +0530

    hw/9pfs: iattr_valid flags are kernel internal flags map them to 9p values.
    
    Kernel internal values can change, add protocol values for these constant and
    use them.
    
    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 7f1301b..df0a8e7 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -1293,17 +1293,18 @@ out_nofid:
     complete_pdu(s, pdu, retval);
 }
 
-/* From Linux kernel code */
-#define ATTR_MODE    (1 << 0)
-#define ATTR_UID     (1 << 1)
-#define ATTR_GID     (1 << 2)
-#define ATTR_SIZE    (1 << 3)
-#define ATTR_ATIME   (1 << 4)
-#define ATTR_MTIME   (1 << 5)
-#define ATTR_CTIME   (1 << 6)
-#define ATTR_MASK    127
-#define ATTR_ATIME_SET  (1 << 7)
-#define ATTR_MTIME_SET  (1 << 8)
+/* Attribute flags */
+#define P9_ATTR_MODE       (1 << 0)
+#define P9_ATTR_UID        (1 << 1)
+#define P9_ATTR_GID        (1 << 2)
+#define P9_ATTR_SIZE       (1 << 3)
+#define P9_ATTR_ATIME      (1 << 4)
+#define P9_ATTR_MTIME      (1 << 5)
+#define P9_ATTR_CTIME      (1 << 6)
+#define P9_ATTR_ATIME_SET  (1 << 7)
+#define P9_ATTR_MTIME_SET  (1 << 8)
+
+#define P9_ATTR_MASK    127
 
 static void v9fs_setattr(void *opaque)
 {
@@ -1322,16 +1323,16 @@ static void v9fs_setattr(void *opaque)
         err = -EINVAL;
         goto out_nofid;
     }
-    if (v9iattr.valid & ATTR_MODE) {
+    if (v9iattr.valid & P9_ATTR_MODE) {
         err = v9fs_co_chmod(pdu, &fidp->path, v9iattr.mode);
         if (err < 0) {
             goto out;
         }
     }
-    if (v9iattr.valid & (ATTR_ATIME | ATTR_MTIME)) {
+    if (v9iattr.valid & (P9_ATTR_ATIME | P9_ATTR_MTIME)) {
         struct timespec times[2];
-        if (v9iattr.valid & ATTR_ATIME) {
-            if (v9iattr.valid & ATTR_ATIME_SET) {
+        if (v9iattr.valid & P9_ATTR_ATIME) {
+            if (v9iattr.valid & P9_ATTR_ATIME_SET) {
                 times[0].tv_sec = v9iattr.atime_sec;
                 times[0].tv_nsec = v9iattr.atime_nsec;
             } else {
@@ -1340,8 +1341,8 @@ static void v9fs_setattr(void *opaque)
         } else {
             times[0].tv_nsec = UTIME_OMIT;
         }
-        if (v9iattr.valid & ATTR_MTIME) {
-            if (v9iattr.valid & ATTR_MTIME_SET) {
+        if (v9iattr.valid & P9_ATTR_MTIME) {
+            if (v9iattr.valid & P9_ATTR_MTIME_SET) {
                 times[1].tv_sec = v9iattr.mtime_sec;
                 times[1].tv_nsec = v9iattr.mtime_nsec;
             } else {
@@ -1359,13 +1360,13 @@ static void v9fs_setattr(void *opaque)
      * If the only valid entry in iattr is ctime we can call
      * chown(-1,-1) to update the ctime of the file
      */
-    if ((v9iattr.valid & (ATTR_UID | ATTR_GID)) ||
-        ((v9iattr.valid & ATTR_CTIME)
-         && !((v9iattr.valid & ATTR_MASK) & ~ATTR_CTIME))) {
-        if (!(v9iattr.valid & ATTR_UID)) {
+    if ((v9iattr.valid & (P9_ATTR_UID | P9_ATTR_GID)) ||
+        ((v9iattr.valid & P9_ATTR_CTIME)
+         && !((v9iattr.valid & P9_ATTR_MASK) & ~P9_ATTR_CTIME))) {
+        if (!(v9iattr.valid & P9_ATTR_UID)) {
             v9iattr.uid = -1;
         }
-        if (!(v9iattr.valid & ATTR_GID)) {
+        if (!(v9iattr.valid & P9_ATTR_GID)) {
             v9iattr.gid = -1;
         }
         err = v9fs_co_chown(pdu, &fidp->path, v9iattr.uid,
@@ -1374,7 +1375,7 @@ static void v9fs_setattr(void *opaque)
             goto out;
         }
     }
-    if (v9iattr.valid & (ATTR_SIZE)) {
+    if (v9iattr.valid & (P9_ATTR_SIZE)) {
         err = v9fs_co_truncate(pdu, &fidp->path, v9iattr.size);
         if (err < 0) {
             goto out;
commit 2f008a8c97e2549da7337c98c53eae2d31f0d548
Author: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
Date:   Wed Dec 21 12:37:23 2011 +0530

    hw/9pfs: Use the correct signed type for different variables
    
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index a85ecd3..c823fe0 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -74,7 +74,7 @@ typedef struct FsContext
 } FsContext;
 
 typedef struct V9fsPath {
-    int16_t size;
+    uint16_t size;
     char *data;
 } V9fsPath;
 
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 46dc9f7..7f1301b 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -1694,8 +1694,8 @@ out_nofid:
     complete_pdu(s, pdu, err);
 }
 
-static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu,
-                           V9fsFidState *fidp, int64_t off, int32_t max_count)
+static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
+                           uint64_t off, uint32_t max_count)
 {
     size_t offset = 7;
     int read_count;
@@ -1719,7 +1719,7 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu,
 }
 
 static int v9fs_do_readdir_with_stat(V9fsPDU *pdu,
-                                     V9fsFidState *fidp, int32_t max_count)
+                                     V9fsFidState *fidp, uint32_t max_count)
 {
     V9fsPath path;
     V9fsStat v9stat;
@@ -1814,11 +1814,11 @@ static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu,
 static void v9fs_read(void *opaque)
 {
     int32_t fid;
-    int64_t off;
+    uint64_t off;
     ssize_t err = 0;
     int32_t count = 0;
     size_t offset = 7;
-    int32_t max_count;
+    uint32_t max_count;
     V9fsFidState *fidp;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
@@ -1962,8 +1962,9 @@ static void v9fs_readdir(void *opaque)
     V9fsFidState *fidp;
     ssize_t retval = 0;
     size_t offset = 7;
-    int64_t initial_offset;
-    int32_t count, max_count;
+    uint64_t initial_offset;
+    int32_t count;
+    uint32_t max_count;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
@@ -2001,7 +2002,7 @@ out_nofid:
 }
 
 static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
-                            int64_t off, int32_t count,
+                            uint64_t off, uint32_t count,
                             struct iovec *sg, int cnt)
 {
     int i, to_copy;
@@ -2048,8 +2049,8 @@ static void v9fs_write(void *opaque)
 {
     ssize_t err;
     int32_t fid;
-    int64_t off;
-    int32_t count;
+    uint64_t off;
+    uint32_t count;
     int32_t len = 0;
     int32_t total = 0;
     size_t offset = 7;
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 8b612da..19a797b 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -156,7 +156,7 @@ typedef struct V9fsFidState V9fsFidState;
 
 typedef struct V9fsString
 {
-    int16_t size;
+    uint16_t size;
     char *data;
 } V9fsString;
 
diff --git a/trace-events b/trace-events
index 514849a..2918398 100644
--- a/trace-events
+++ b/trace-events
@@ -578,11 +578,11 @@ v9fs_lcreate(uint16_t tag, uint8_t id, int32_t dfid, int32_t flags, int32_t mode
 v9fs_lcreate_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int32_t iounit) "tag %d id %d qid={type %d version %d path %"PRId64"} iounit %d"
 v9fs_fsync(uint16_t tag, uint8_t id, int32_t fid, int datasync) "tag %d id %d fid %d datasync %d"
 v9fs_clunk(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
-v9fs_read(uint16_t tag, uint8_t id, int32_t fid, int64_t off, int32_t max_count) "tag %d id %d fid %d off %"PRId64" max_count %d"
+v9fs_read(uint16_t tag, uint8_t id, int32_t fid, uint64_t off, uint32_t max_count) "tag %d id %d fid %d off %"PRIu64" max_count %u"
 v9fs_read_return(uint16_t tag, uint8_t id, int32_t count, ssize_t err) "tag %d id %d count %d err %zd"
-v9fs_readdir(uint16_t tag, uint8_t id, int32_t fid, int64_t offset, int32_t max_count) "tag %d id %d fid %d offset %"PRId64" max_count %d"
-v9fs_readdir_return(uint16_t tag, uint8_t id, int32_t count, ssize_t retval) "tag %d id %d count %d retval %zd"
-v9fs_write(uint16_t tag, uint8_t id, int32_t fid, int64_t off, int32_t count, int cnt) "tag %d id %d fid %d off %"PRId64" count %d cnt %d"
+v9fs_readdir(uint16_t tag, uint8_t id, int32_t fid, uint64_t offset, uint32_t max_count) "tag %d id %d fid %d offset %"PRIu64" max_count %u"
+v9fs_readdir_return(uint16_t tag, uint8_t id, uint32_t count, ssize_t retval) "tag %d id %d count %u retval %zd"
+v9fs_write(uint16_t tag, uint8_t id, int32_t fid, uint64_t off, uint32_t count, int cnt) "tag %d id %d fid %d off %"PRIu64" count %u cnt %d"
 v9fs_write_return(uint16_t tag, uint8_t id, int32_t total, ssize_t err) "tag %d id %d total %d err %zd"
 v9fs_create(uint16_t tag, uint8_t id, int32_t fid, char* name, int32_t perm, int8_t mode) "tag %d id %d fid %d name %s perm %d mode %d"
 v9fs_create_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int iounit) "tag %d id %d qid={type %d version %d path %"PRId64"} iounit %d"
commit 302a0d3ed721e4c30c6a2a37f64c60b50ffd33b9
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Dec 21 12:37:22 2011 +0530

    hw/9pfs: replace iovec manipulation with QEMUIOVector
    
    The v9fs_read() and v9fs_write() functions rely on iovec[] manipulation
    code should be replaced with QEMUIOVector to avoid duplicating code.
    In the future it may be possible to make the code even more concise by
    using QEMUIOVector consistently across virtio and 9pfs.
    
    The "v" format specifier for pdu_marshal() and pdu_unmarshal() is
    dropped since it does not actually pack/unpack anything.  The specifier
    was also not implemented to update the offset variable and could only be
    used at the end of a format string, another sign that this shouldn't
    really be a format specifier.  Instead, see the new
    v9fs_init_qiov_from_pdu() function.
    
    This change avoids a possible iovec[] buffer overflow when indirect
    vrings are used since the number of vectors is now limited by the
    underlying VirtQueueElement and cannot be out-of-bounds.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    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 36a862f..46dc9f7 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -674,40 +674,6 @@ static size_t pdu_pack(V9fsPDU *pdu, size_t offset, const void *src,
                              offset, size, 1);
 }
 
-static int pdu_copy_sg(V9fsPDU *pdu, size_t offset, int rx, struct iovec *sg)
-{
-    size_t pos = 0;
-    int i, j;
-    struct iovec *src_sg;
-    unsigned int num;
-
-    if (rx) {
-        src_sg = pdu->elem.in_sg;
-        num = pdu->elem.in_num;
-    } else {
-        src_sg = pdu->elem.out_sg;
-        num = pdu->elem.out_num;
-    }
-
-    j = 0;
-    for (i = 0; i < num; i++) {
-        if (offset <= pos) {
-            sg[j].iov_base = src_sg[i].iov_base;
-            sg[j].iov_len = src_sg[i].iov_len;
-            j++;
-        } else if (offset < (src_sg[i].iov_len + pos)) {
-            sg[j].iov_base = src_sg[i].iov_base;
-            sg[j].iov_len = src_sg[i].iov_len;
-            sg[j].iov_base += (offset - pos);
-            sg[j].iov_len -= (offset - pos);
-            j++;
-        }
-        pos += src_sg[i].iov_len;
-    }
-
-    return j;
-}
-
 static size_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
 {
     size_t old_offset = offset;
@@ -743,12 +709,6 @@ static size_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
             *valp = le64_to_cpu(val);
             break;
         }
-        case 'v': {
-            struct iovec *iov = va_arg(ap, struct iovec *);
-            int *iovcnt = va_arg(ap, int *);
-            *iovcnt = pdu_copy_sg(pdu, offset, 0, iov);
-            break;
-        }
         case 's': {
             V9fsString *str = va_arg(ap, V9fsString *);
             offset += pdu_unmarshal(pdu, offset, "w", &str->size);
@@ -827,12 +787,6 @@ static size_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
             offset += pdu_pack(pdu, offset, &val, sizeof(val));
             break;
         }
-        case 'v': {
-            struct iovec *iov = va_arg(ap, struct iovec *);
-            int *iovcnt = va_arg(ap, int *);
-            *iovcnt = pdu_copy_sg(pdu, offset, 1, iov);
-            break;
-        }
         case 's': {
             V9fsString *str = va_arg(ap, V9fsString *);
             offset += pdu_marshal(pdu, offset, "w", str->size);
@@ -1143,42 +1097,6 @@ static void stat_to_v9stat_dotl(V9fsState *s, const struct stat *stbuf,
     stat_to_qid(stbuf, &v9lstat->qid);
 }
 
-static struct iovec *adjust_sg(struct iovec *sg, int len, int *iovcnt)
-{
-    while (len && *iovcnt) {
-        if (len < sg->iov_len) {
-            sg->iov_len -= len;
-            sg->iov_base += len;
-            len = 0;
-        } else {
-            len -= sg->iov_len;
-            sg++;
-            *iovcnt -= 1;
-        }
-    }
-
-    return sg;
-}
-
-static struct iovec *cap_sg(struct iovec *sg, int cap, int *cnt)
-{
-    int i;
-    int total = 0;
-
-    for (i = 0; i < *cnt; i++) {
-        if ((total + sg[i].iov_len) > cap) {
-            sg[i].iov_len -= ((total + sg[i].iov_len) - cap);
-            i++;
-            break;
-        }
-        total += sg[i].iov_len;
-    }
-
-    *cnt = i;
-
-    return sg;
-}
-
 static void print_sg(struct iovec *sg, int cnt)
 {
     int i;
@@ -1861,6 +1779,38 @@ out:
     return count;
 }
 
+/*
+ * Create a QEMUIOVector for a sub-region of PDU iovecs
+ *
+ * @qiov:       uninitialized QEMUIOVector
+ * @skip:       number of bytes to skip from beginning of PDU
+ * @size:       number of bytes to include
+ * @is_write:   true - write, false - read
+ *
+ * The resulting QEMUIOVector has heap-allocated iovecs and must be cleaned up
+ * with qemu_iovec_destroy().
+ */
+static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu,
+                                    uint64_t skip, size_t size,
+                                    bool is_write)
+{
+    QEMUIOVector elem;
+    struct iovec *iov;
+    unsigned int niov;
+
+    if (is_write) {
+        iov = pdu->elem.out_sg;
+        niov = pdu->elem.out_num;
+    } else {
+        iov = pdu->elem.in_sg;
+        niov = pdu->elem.in_num;
+    }
+
+    qemu_iovec_init_external(&elem, iov, niov);
+    qemu_iovec_init(qiov, niov);
+    qemu_iovec_copy(qiov, &elem, skip, size);
+}
+
 static void v9fs_read(void *opaque)
 {
     int32_t fid;
@@ -1895,21 +1845,21 @@ static void v9fs_read(void *opaque)
         err += pdu_marshal(pdu, offset, "d", count);
         err += count;
     } else if (fidp->fid_type == P9_FID_FILE) {
-        int32_t cnt;
+        QEMUIOVector qiov_full;
+        QEMUIOVector qiov;
         int32_t len;
-        struct iovec *sg;
-        struct iovec iov[128]; /* FIXME: bad, bad, bad */
 
-        sg = iov;
-        pdu_marshal(pdu, offset + 4, "v", sg, &cnt);
-        sg = cap_sg(sg, max_count, &cnt);
+        v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset + 4, max_count, false);
+        qemu_iovec_init(&qiov, qiov_full.niov);
         do {
+            qemu_iovec_reset(&qiov);
+            qemu_iovec_copy(&qiov, &qiov_full, count, qiov_full.size - count);
             if (0) {
-                print_sg(sg, cnt);
+                print_sg(qiov.iov, qiov.niov);
             }
             /* Loop in case of EINTR */
             do {
-                len = v9fs_co_preadv(pdu, fidp, sg, cnt, off);
+                len = v9fs_co_preadv(pdu, fidp, qiov.iov, qiov.niov, off);
                 if (len >= 0) {
                     off   += len;
                     count += len;
@@ -1920,11 +1870,12 @@ static void v9fs_read(void *opaque)
                 err = len;
                 goto out;
             }
-            sg = adjust_sg(sg, len, &cnt);
         } while (count < max_count && len > 0);
         err = offset;
         err += pdu_marshal(pdu, offset, "d", count);
         err += count;
+        qemu_iovec_destroy(&qiov);
+        qemu_iovec_destroy(&qiov_full);
     } else if (fidp->fid_type == P9_FID_XATTR) {
         err = v9fs_xattr_read(s, pdu, fidp, off, max_count);
     } else {
@@ -2095,7 +2046,6 @@ out:
 
 static void v9fs_write(void *opaque)
 {
-    int cnt;
     ssize_t err;
     int32_t fid;
     int64_t off;
@@ -2104,13 +2054,14 @@ static void v9fs_write(void *opaque)
     int32_t total = 0;
     size_t offset = 7;
     V9fsFidState *fidp;
-    struct iovec iov[128]; /* FIXME: bad, bad, bad */
-    struct iovec *sg = iov;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
+    QEMUIOVector qiov_full;
+    QEMUIOVector qiov;
 
-    pdu_unmarshal(pdu, offset, "dqdv", &fid, &off, &count, sg, &cnt);
-    trace_v9fs_write(pdu->tag, pdu->id, fid, off, count, cnt);
+    offset += pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &count);
+    v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset, count, true);
+    trace_v9fs_write(pdu->tag, pdu->id, fid, off, count, qiov_full.niov);
 
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
@@ -2126,20 +2077,23 @@ static void v9fs_write(void *opaque)
         /*
          * setxattr operation
          */
-        err = v9fs_xattr_write(s, pdu, fidp, off, count, sg, cnt);
+        err = v9fs_xattr_write(s, pdu, fidp, off, count,
+                               qiov_full.iov, qiov_full.niov);
         goto out;
     } else {
         err = -EINVAL;
         goto out;
     }
-    sg = cap_sg(sg, count, &cnt);
+    qemu_iovec_init(&qiov, qiov_full.niov);
     do {
+        qemu_iovec_reset(&qiov);
+        qemu_iovec_copy(&qiov, &qiov_full, total, qiov_full.size - total);
         if (0) {
-            print_sg(sg, cnt);
+            print_sg(qiov.iov, qiov.niov);
         }
         /* Loop in case of EINTR */
         do {
-            len = v9fs_co_pwritev(pdu, fidp, sg, cnt, off);
+            len = v9fs_co_pwritev(pdu, fidp, qiov.iov, qiov.niov, off);
             if (len >= 0) {
                 off   += len;
                 total += len;
@@ -2148,16 +2102,20 @@ static void v9fs_write(void *opaque)
         if (len < 0) {
             /* IO error return the error */
             err = len;
-            goto out;
+            goto out_qiov;
         }
-        sg = adjust_sg(sg, len, &cnt);
     } while (total < count && len > 0);
+
+    offset = 7;
     offset += pdu_marshal(pdu, offset, "d", total);
     err = offset;
     trace_v9fs_write_return(pdu->tag, pdu->id, total, err);
+out_qiov:
+    qemu_iovec_destroy(&qiov);
 out:
     put_fid(pdu, fidp);
 out_nofid:
+    qemu_iovec_destroy(&qiov_full);
     complete_pdu(s, pdu, err);
 }
 
commit 3799ce4ab64f578eb818689a276e4f0c73d01fb5
Author: Andrzej Zaborowski <andrew.zaborowski at intel.com>
Date:   Wed Dec 21 05:04:21 2011 +0100

    sd: Remember to reset .expecting_acmd on reset.
    
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/sd.c b/hw/sd.c
index 2b8ebe4..07eb263 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -422,6 +422,7 @@ static void sd_reset(SDState *sd, BlockDriverState *bdrv)
     sd->size = size;
     sd->blk_len = 0x200;
     sd->pwd_len = 0;
+    sd->expecting_acmd = 0;
 }
 
 static void sd_cardchange(void *opaque, bool load)
commit fcfa9351c57985ebb54fe6aacd06a270880a561f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Dec 18 21:38:00 2011 +0100

    hw/sd.c: Clear status bits when read via response r6
    
    Response format r6 includes a subset of the status bits;
    clear the clear-on-read bits which are read by an r6 response.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/sd.c b/hw/sd.c
index 6614cbf..2b8ebe4 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -371,6 +371,7 @@ static void sd_response_r6_make(SDState *sd, uint8_t *response)
     status = ((sd->card_status >> 8) & 0xc000) |
              ((sd->card_status >> 6) & 0x2000) |
               (sd->card_status & 0x1fff);
+    sd->card_status &= ~(CARD_STATUS_C & 0xc81fff);
 
     response[0] = (arg >> 8) & 0xff;
     response[1] = arg & 0xff;
commit 1d06cb7ab93f879ac25c9f5ef1d1ac8d97a42dfc
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Dec 18 21:37:59 2011 +0100

    hw/sd.c: Correct handling of APP_CMD status bit
    
    Fix some bugs in our implementation of the APP_CMD status bit:
     * the response to an ACMD should have APP_CMD set, not cleared
     * if an illegal ACMD is sent then the next command should be
       handled as a normal command
    
    This requires that we split "card is expecting an ACMD" from
    the state of the APP_CMD status bit (the latter indicates
    both "expecting ACMD" and "that was an ACMD").
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/sd.c b/hw/sd.c
index e1565b6..6614cbf 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -92,6 +92,10 @@ struct SDState {
 
     int spi;
     int current_cmd;
+    /* True if we will handle the next command as an ACMD. Note that this does
+     * *not* track the APP_CMD status bit!
+     */
+    int expecting_acmd;
     int blk_written;
     uint64_t data_start;
     uint32_t data_offset;
@@ -341,8 +345,8 @@ static int sd_req_crc_validate(SDRequest *req)
 static void sd_response_r1_make(SDState *sd, uint8_t *response)
 {
     uint32_t status = sd->card_status;
-    /* Clear the "clear on read" status bits (except APP_CMD) */
-    sd->card_status &= ~CARD_STATUS_C | APP_CMD;
+    /* Clear the "clear on read" status bits */
+    sd->card_status &= ~CARD_STATUS_C;
 
     response[0] = (status >> 24) & 0xff;
     response[1] = (status >> 16) & 0xff;
@@ -608,6 +612,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
     uint32_t rca = 0x0000;
     uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg;
 
+    /* Not interpreting this as an app command */
+    sd->card_status &= ~APP_CMD;
+
     if (sd_cmd_type[req.cmd] == sd_ac || sd_cmd_type[req.cmd] == sd_adtc)
         rca = req.arg >> 16;
 
@@ -1116,6 +1123,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
         if (sd->rca != rca)
             return sd_r0;
 
+        sd->expecting_acmd = 1;
         sd->card_status |= APP_CMD;
         return sd_r1;
 
@@ -1155,6 +1163,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
                                     SDRequest req)
 {
     DPRINTF("ACMD%d 0x%08x\n", req.cmd, req.arg);
+    sd->card_status |= APP_CMD;
     switch (req.cmd) {
     case 6:	/* ACMD6:  SET_BUS_WIDTH */
         switch (sd->state) {
@@ -1251,7 +1260,6 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 
     default:
         /* Fall back to standard commands.  */
-        sd->card_status &= ~APP_CMD;
         return sd_normal_command(sd, req);
     }
 
@@ -1269,7 +1277,7 @@ static int cmd_valid_while_locked(SDState *sd, SDRequest *req)
      * ACMD41 and ACMD42
      * Anything else provokes an "illegal command" response.
      */
-    if (sd->card_status & APP_CMD) {
+    if (sd->expecting_acmd) {
         return req->cmd == 41 || req->cmd == 42;
     }
     if (req->cmd == 16 || req->cmd == 55) {
@@ -1297,6 +1305,7 @@ int sd_do_command(SDState *sd, SDRequest *req,
     if (sd->card_status & CARD_IS_LOCKED) {
         if (!cmd_valid_while_locked(sd, req)) {
             sd->card_status |= ILLEGAL_COMMAND;
+            sd->expecting_acmd = 0;
             fprintf(stderr, "SD: Card is locked\n");
             rtype = sd_illegal;
             goto send_response;
@@ -1306,11 +1315,12 @@ int sd_do_command(SDState *sd, SDRequest *req,
     last_state = sd->state;
     sd_set_mode(sd);
 
-    if (sd->card_status & APP_CMD) {
+    if (sd->expecting_acmd) {
+        sd->expecting_acmd = 0;
         rtype = sd_app_command(sd, *req);
-        sd->card_status &= ~APP_CMD;
-    } else
+    } else {
         rtype = sd_normal_command(sd, *req);
+    }
 
     if (rtype == sd_illegal) {
         sd->card_status |= ILLEGAL_COMMAND;
commit 10a412dab3f54439ea3d60274eb41668f7d83bd2
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Dec 18 21:37:58 2011 +0100

    hw/sd.c: Correct handling of type B SD status bits
    
    Correct how we handle the type B ("cleared on valid command")
    status bits. In particular, the CURRENT_STATE bits in a response
    should be the state of the card when it received that command,
    not the state when it received the preceding command. (This is
    one of the issues noted in LP:597641.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/sd.c b/hw/sd.c
index 9eebfac..e1565b6 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -104,7 +104,7 @@ struct SDState {
     int enable;
 };
 
-static void sd_set_status(SDState *sd)
+static void sd_set_mode(SDState *sd)
 {
     switch (sd->state) {
     case sd_inactive_state:
@@ -126,9 +126,6 @@ static void sd_set_status(SDState *sd)
         sd->mode = sd_data_transfer_mode;
         break;
     }
-
-    sd->card_status &= ~CURRENT_STATE;
-    sd->card_status |= sd->state << 9;
 }
 
 static const sd_cmd_type_t sd_cmd_type[64] = {
@@ -341,13 +338,10 @@ static int sd_req_crc_validate(SDRequest *req)
     return sd_crc7(buffer, 5) != req->crc;	/* TODO */
 }
 
-static void sd_response_r1_make(SDState *sd,
-                                uint8_t *response, uint32_t last_status)
+static void sd_response_r1_make(SDState *sd, uint8_t *response)
 {
-    uint32_t mask = CARD_STATUS_B ^ ILLEGAL_COMMAND;
-    uint32_t status;
-
-    status = (sd->card_status & ~mask) | (last_status & mask);
+    uint32_t status = sd->card_status;
+    /* Clear the "clear on read" status bits (except APP_CMD) */
     sd->card_status &= ~CARD_STATUS_C | APP_CMD;
 
     response[0] = (status >> 24) & 0xff;
@@ -1286,7 +1280,7 @@ static int cmd_valid_while_locked(SDState *sd, SDRequest *req)
 
 int sd_do_command(SDState *sd, SDRequest *req,
                   uint8_t *response) {
-    uint32_t last_status = sd->card_status;
+    int last_state;
     sd_rsp_type_t rtype;
     int rsplen;
 
@@ -1300,10 +1294,7 @@ int sd_do_command(SDState *sd, SDRequest *req,
         goto send_response;
     }
 
-    sd->card_status &= ~CARD_STATUS_B;
-    sd_set_status(sd);
-
-    if (last_status & CARD_IS_LOCKED) {
+    if (sd->card_status & CARD_IS_LOCKED) {
         if (!cmd_valid_while_locked(sd, req)) {
             sd->card_status |= ILLEGAL_COMMAND;
             fprintf(stderr, "SD: Card is locked\n");
@@ -1312,7 +1303,10 @@ int sd_do_command(SDState *sd, SDRequest *req,
         }
     }
 
-    if (last_status & APP_CMD) {
+    last_state = sd->state;
+    sd_set_mode(sd);
+
+    if (sd->card_status & APP_CMD) {
         rtype = sd_app_command(sd, *req);
         sd->card_status &= ~APP_CMD;
     } else
@@ -1320,15 +1314,20 @@ int sd_do_command(SDState *sd, SDRequest *req,
 
     if (rtype == sd_illegal) {
         sd->card_status |= ILLEGAL_COMMAND;
+    } else {
+        /* Valid command, we can update the 'state before command' bits.
+         * (Do this now so they appear in r1 responses.)
+         */
+        sd->current_cmd = req->cmd;
+        sd->card_status &= ~CURRENT_STATE;
+        sd->card_status |= (last_state << 9);
     }
 
-    sd->current_cmd = req->cmd;
-
 send_response:
     switch (rtype) {
     case sd_r1:
     case sd_r1b:
-        sd_response_r1_make(sd, response, last_status);
+        sd_response_r1_make(sd, response);
         rsplen = 4;
         break;
 
@@ -1364,6 +1363,13 @@ send_response:
         break;
     }
 
+    if (rtype != sd_illegal) {
+        /* Clear the "clear on valid command" status bits now we've
+         * sent any response
+         */
+        sd->card_status &= ~CARD_STATUS_B;
+    }
+
 #ifdef DEBUG_SD
     if (rsplen) {
         int i;
commit 5b08bfe2e94c7b1ce39aa3b196231c7f30a5defd
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Dec 18 21:37:57 2011 +0100

    hw/sd.c: Set ILLEGAL_COMMAND for ACMDs in invalid state
    
    App commands in an invalid state should set ILLEGAL_COMMAND, not
    merely return a zero response.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/sd.c b/hw/sd.c
index 9116f67..9eebfac 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -1262,7 +1262,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
     }
 
     fprintf(stderr, "SD: ACMD%i in a wrong state\n", req.cmd);
-    return sd_r0;
+    return sd_illegal;
 }
 
 static int cmd_valid_while_locked(SDState *sd, SDRequest *req)
commit b1f517ed4311da719d7584d1be36a4f21127b0f1
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Dec 18 21:37:56 2011 +0100

    hw/sd.c: Handle CRC and locked-card errors in normal code path
    
    Handle returning CRC and locked-card errors in the same code path
    we use for other responses. This makes no difference in behaviour
    but means that these error responses will be printed by the debug
    logging code.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/sd.c b/hw/sd.c
index 57925af..9116f67 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -1296,7 +1296,8 @@ int sd_do_command(SDState *sd, SDRequest *req,
 
     if (sd_req_crc_validate(req)) {
         sd->card_status |= COM_CRC_ERROR;
-        return 0;
+        rtype = sd_illegal;
+        goto send_response;
     }
 
     sd->card_status &= ~CARD_STATUS_B;
@@ -1306,7 +1307,8 @@ int sd_do_command(SDState *sd, SDRequest *req,
         if (!cmd_valid_while_locked(sd, req)) {
             sd->card_status |= ILLEGAL_COMMAND;
             fprintf(stderr, "SD: Card is locked\n");
-            return 0;
+            rtype = sd_illegal;
+            goto send_response;
         }
     }
 
@@ -1322,6 +1324,7 @@ int sd_do_command(SDState *sd, SDRequest *req,
 
     sd->current_cmd = req->cmd;
 
+send_response:
     switch (rtype) {
     case sd_r1:
     case sd_r1b:
commit 53bb8cc4855827f2981bf0566076233573a05bd7
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Dec 18 21:37:55 2011 +0100

    hw/sd.c: Handle illegal commands in sd_do_command
    
    Add an extra sd_illegal value to the sd_rsp_type_t enum so that
    sd_app_command() and sd_normal_command() can tell sd_do_command()
    that the command was illegal. This is needed so we can do things
    like reset certain status bits only on receipt of a valid command.
    For the moment, just use it to pull out the setting of the
    ILLEGAL_COMMAND status bit into sd_do_command().
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/sd.c b/hw/sd.c
index dd28061..57925af 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -51,6 +51,7 @@ typedef enum {
     sd_r6 = 6,    /* Published RCA response */
     sd_r7,        /* Operating voltage */
     sd_r1b = -1,
+    sd_illegal = -2,
 } sd_rsp_type_t;
 
 struct SDState {
@@ -679,8 +680,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
         break;
 
     case 5: /* CMD5: reserved for SDIO cards */
-        sd->card_status |= ILLEGAL_COMMAND;
-        return sd_r0;
+        return sd_illegal;
 
     case 6:	/* CMD6:   SWITCH_FUNCTION */
         if (sd->spi)
@@ -1115,8 +1115,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
          * on stderr, as some OSes may use these in their
          * probing for presence of an SDIO card.
          */
-        sd->card_status |= ILLEGAL_COMMAND;
-        return sd_r0;
+        return sd_illegal;
 
     /* Application specific commands (Class 8) */
     case 55:	/* CMD55:  APP_CMD */
@@ -1145,21 +1144,17 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
 
     default:
     bad_cmd:
-        sd->card_status |= ILLEGAL_COMMAND;
-
         fprintf(stderr, "SD: Unknown CMD%i\n", req.cmd);
-        return sd_r0;
+        return sd_illegal;
 
     unimplemented_cmd:
         /* Commands that are recognised but not yet implemented in SPI mode.  */
-        sd->card_status |= ILLEGAL_COMMAND;
         fprintf(stderr, "SD: CMD%i not implemented in SPI mode\n", req.cmd);
-        return sd_r0;
+        return sd_illegal;
     }
 
-    sd->card_status |= ILLEGAL_COMMAND;
     fprintf(stderr, "SD: CMD%i in a wrong state\n", req.cmd);
-    return sd_r0;
+    return sd_illegal;
 }
 
 static sd_rsp_type_t sd_app_command(SDState *sd,
@@ -1321,6 +1316,10 @@ int sd_do_command(SDState *sd, SDRequest *req,
     } else
         rtype = sd_normal_command(sd, *req);
 
+    if (rtype == sd_illegal) {
+        sd->card_status |= ILLEGAL_COMMAND;
+    }
+
     sd->current_cmd = req->cmd;
 
     switch (rtype) {
@@ -1356,14 +1355,12 @@ int sd_do_command(SDState *sd, SDRequest *req,
         break;
 
     case sd_r0:
+    case sd_illegal:
     default:
         rsplen = 0;
         break;
     }
 
-    if (sd->card_status & ILLEGAL_COMMAND)
-        rsplen = 0;
-
 #ifdef DEBUG_SD
     if (rsplen) {
         int i;
commit e30d59388bab90418b414c1f29d5779361d31ffe
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Dec 18 21:37:54 2011 +0100

    hw/sd.c: When setting ADDRESS_ERROR bit, don't clear everything else
    
    Fix a typo that meant that ADDRESS_ERRORs setting or clearing write
    protection would clear every other bit in the status register.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/sd.c b/hw/sd.c
index e57852e..dd28061 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -999,7 +999,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
         switch (sd->state) {
         case sd_transfer_state:
             if (addr >= sd->size) {
-                sd->card_status = ADDRESS_ERROR;
+                sd->card_status |= ADDRESS_ERROR;
                 return sd_r1b;
             }
 
@@ -1019,7 +1019,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
         switch (sd->state) {
         case sd_transfer_state:
             if (addr >= sd->size) {
-                sd->card_status = ADDRESS_ERROR;
+                sd->card_status |= ADDRESS_ERROR;
                 return sd_r1b;
             }
 
commit abda1f37eed86f3501db2e5439c1a7b97171ea22
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Dec 18 21:37:53 2011 +0100

    hw/sd.c: On CRC error, set CRC error status bit rather than clearing it
    
    If we fail to validate the CRC for an SD command we should be setting
    COM_CRC_ERROR, not clearing it. (This bug actually has no effect currently
    because sd_req_crc_validate() always returns success.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/sd.c b/hw/sd.c
index 245b6c3..e57852e 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -1300,7 +1300,7 @@ int sd_do_command(SDState *sd, SDRequest *req,
     }
 
     if (sd_req_crc_validate(req)) {
-        sd->card_status &= ~COM_CRC_ERROR;
+        sd->card_status |= COM_CRC_ERROR;
         return 0;
     }
 
commit b8d334c828f14a341e18bcc123b303ec29f8df76
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Dec 18 21:37:52 2011 +0100

    hw/sd.c: Add comment regarding CARD_STATUS_* defines
    
    Add a clarifying comment about what the CARD_STATUS_[ABC]
    macros are defining.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/sd.c b/hw/sd.c
index a1c98c0..245b6c3 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -309,6 +309,11 @@ static void sd_set_rca(SDState *sd)
     sd->rca += 0x4567;
 }
 
+/* Card status bits, split by clear condition:
+ * A : According to the card current state
+ * B : Always related to the previous command
+ * C : Cleared by read
+ */
 #define CARD_STATUS_A	0x02004100
 #define CARD_STATUS_B	0x00c01e00
 #define CARD_STATUS_C	0xfd39a028
commit 25881d33905798e6fddda3827b4345e867c02b7f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Dec 18 21:37:51 2011 +0100

    hw/sd.c: Fix the set of commands which are failed when card is locked
    
    Fix bugs in the code determining whether to accept a command when the
    SD card is locked. Most notably, we had the condition completely
    reversed, so we would accept all the commands we should refuse and
    refuse all the commands we should accept. Correct this by refactoring
    the enormous if () clause into a separate function.
    We had also missed ACMD42 off the list of commands which are accepted
    in locked state: add it.
    
    This is one of the two problems reported in LP:597641.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/sd.c b/hw/sd.c
index 10e26ad..a1c98c0 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -1265,6 +1265,25 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
     return sd_r0;
 }
 
+static int cmd_valid_while_locked(SDState *sd, SDRequest *req)
+{
+    /* Valid commands in locked state:
+     * basic class (0)
+     * lock card class (7)
+     * CMD16
+     * implicitly, the ACMD prefix CMD55
+     * ACMD41 and ACMD42
+     * Anything else provokes an "illegal command" response.
+     */
+    if (sd->card_status & APP_CMD) {
+        return req->cmd == 41 || req->cmd == 42;
+    }
+    if (req->cmd == 16 || req->cmd == 55) {
+        return 1;
+    }
+    return sd_cmd_class[req->cmd] == 0 || sd_cmd_class[req->cmd] == 7;
+}
+
 int sd_do_command(SDState *sd, SDRequest *req,
                   uint8_t *response) {
     uint32_t last_status = sd->card_status;
@@ -1283,17 +1302,13 @@ int sd_do_command(SDState *sd, SDRequest *req,
     sd->card_status &= ~CARD_STATUS_B;
     sd_set_status(sd);
 
-    if (last_status & CARD_IS_LOCKED)
-        if (((last_status & APP_CMD) &&
-                                 req->cmd == 41) ||
-                        (!(last_status & APP_CMD) &&
-                         (sd_cmd_class[req->cmd] == 0 ||
-                          sd_cmd_class[req->cmd] == 7 ||
-                          req->cmd == 16 || req->cmd == 55))) {
+    if (last_status & CARD_IS_LOCKED) {
+        if (!cmd_valid_while_locked(sd, req)) {
             sd->card_status |= ILLEGAL_COMMAND;
             fprintf(stderr, "SD: Card is locked\n");
             return 0;
         }
+    }
 
     if (last_status & APP_CMD) {
         rtype = sd_app_command(sd, *req);
commit e114fead273e2a7d453c2fb67c74cad58c34581d
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Dec 19 20:33:59 2011 +0000

    hw/sysbus.c: Remove unnecessary conditionals
    
    Now that all sysbus MMIO regions are MemoryRegions, mmio[n].memory
    is never NULL, and we can remove some unnecessary conditionals.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/sysbus.c b/hw/sysbus.c
index 81a57bd..24f619f 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -50,17 +50,12 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)
     }
     if (dev->mmio[n].addr != (target_phys_addr_t)-1) {
         /* Unregister previous mapping.  */
-        if (dev->mmio[n].memory) {
-            memory_region_del_subregion(get_system_memory(),
-                                        dev->mmio[n].memory);
-        }
+        memory_region_del_subregion(get_system_memory(), dev->mmio[n].memory);
     }
     dev->mmio[n].addr = addr;
-    if (dev->mmio[n].memory) {
-        memory_region_add_subregion(get_system_memory(),
-                                    addr,
-                                    dev->mmio[n].memory);
-    }
+    memory_region_add_subregion(get_system_memory(),
+                                addr,
+                                dev->mmio[n].memory);
 }
 
 
@@ -206,10 +201,7 @@ static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
 
     monitor_printf(mon, "%*sirq %d\n", indent, "", s->num_irq);
     for (i = 0; i < s->num_mmio; i++) {
-        size = 0;
-        if (s->mmio[i].memory) {
-            size = memory_region_size(s->mmio[i].memory);
-        }
+        size = memory_region_size(s->mmio[i].memory);
         monitor_printf(mon, "%*smmio " TARGET_FMT_plx "/" TARGET_FMT_plx "\n",
                        indent, "", s->mmio[i].addr, size);
     }
commit 42ed3727536ccf80c87942b3f04e7378fe90f107
Author: Alon Levy <alevy at redhat.com>
Date:   Tue Dec 20 13:41:04 2011 +0200

    g_thread_init users: don't call it if glib >= 2.31
    
    since commit f9b29ca03 included in release 2.31 (docs below say 2.32 but
    that is not correct) and onwards g_thread_init is deprecated and calling
    it is not required:
    
     http://developer.gnome.org/glib/unstable/glib-Deprecated-Thread-APIs.html#g-thread-init
    
     g_thread_init has been deprecated since version 2.32 and should not be
     used in newly-written code. This function is no longer necessary. The
     GLib threading system is automatically initialized at the start of your
     program.
    
    Fixes bulid failure when warnings are treated as errors on fedora 17.
    
    I only tested the change to vl.c, and copy pasted to the two other
    locations (couldn't decide if a wrapper for calling g_thread_init is
    uglier).
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/coroutine-gthread.c b/coroutine-gthread.c
index fdea27a..662801b 100644
--- a/coroutine-gthread.c
+++ b/coroutine-gthread.c
@@ -36,7 +36,12 @@ static GStaticPrivate coroutine_key = G_STATIC_PRIVATE_INIT;
 static void __attribute__((constructor)) coroutine_init(void)
 {
     if (!g_thread_supported()) {
+#if !GLIB_CHECK_VERSION(2, 31, 0)
         g_thread_init(NULL);
+#else
+        fprintf(stderr, "glib threading failed to initialize.\n");
+        exit(1);
+#endif
     }
 
     coroutine_cond = g_cond_new();
diff --git a/trace/simple.c b/trace/simple.c
index 6339152..bbc9930 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -376,7 +376,12 @@ bool trace_backend_init(const char *events, const char *file)
     GThread *thread;
 
     if (!g_thread_supported()) {
+#if !GLIB_CHECK_VERSION(2, 31, 0)
         g_thread_init(NULL);
+#else
+        fprintf(stderr, "glib threading failed to initialize.\n");
+        exit(1);
+#endif
     }
 
     trace_available_cond = g_cond_new();
diff --git a/vl.c b/vl.c
index 78b790c..c03abb6 100644
--- a/vl.c
+++ b/vl.c
@@ -2176,7 +2176,12 @@ int main(int argc, char **argv, char **envp)
 
     g_mem_set_vtable(&mem_trace);
     if (!g_thread_supported()) {
+#if !GLIB_CHECK_VERSION(2, 31, 0)
         g_thread_init(NULL);
+#else
+        fprintf(stderr, "glib threading failed to initialize.\n");
+        exit(1);
+#endif
     }
 
     runstate_init();
commit 4a0f031d5bd2399eec5eea062e44b5271a855faf
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Thu Dec 15 22:10:01 2011 +0100

    audio: remove unused parameter isa_pic
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/arch_init.c b/arch_init.c
index 3bc2a41..d4c92b0 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -473,7 +473,7 @@ struct soundhw {
     int enabled;
     int isa;
     union {
-        int (*init_isa) (ISABus *bus, qemu_irq *pic);
+        int (*init_isa) (ISABus *bus);
         int (*init_pci) (PCIBus *bus);
     } init;
 };
@@ -628,15 +628,15 @@ void select_soundhw(const char *optarg)
     }
 }
 
-void audio_init(ISABus *isa_bus, qemu_irq *isa_pic, PCIBus *pci_bus)
+void audio_init(ISABus *isa_bus, PCIBus *pci_bus)
 {
     struct soundhw *c;
 
     for (c = soundhw; c->name; ++c) {
         if (c->enabled) {
             if (c->isa) {
-                if (isa_pic) {
-                    c->init.init_isa(isa_bus, isa_pic);
+                if (isa_bus) {
+                    c->init.init_isa(isa_bus);
                 }
             } else {
                 if (pci_bus) {
@@ -650,7 +650,7 @@ void audio_init(ISABus *isa_bus, qemu_irq *isa_pic, PCIBus *pci_bus)
 void select_soundhw(const char *optarg)
 {
 }
-void audio_init(ISABus *isa_bus, qemu_irq *isa_pic, PCIBus *pci_bus)
+void audio_init(ISABus *isa_bus, PCIBus *pci_bus)
 {
 }
 #endif
diff --git a/arch_init.h b/arch_init.h
index 074f02a..828256c 100644
--- a/arch_init.h
+++ b/arch_init.h
@@ -27,7 +27,7 @@ void do_acpitable_option(const char *optarg);
 void do_smbios_option(const char *optarg);
 void cpudef_init(void);
 int audio_available(void);
-void audio_init(ISABus *isa_bus, qemu_irq *isa_pic, PCIBus *pci_bus);
+void audio_init(ISABus *isa_bus, PCIBus *pci_bus);
 int tcg_available(void);
 int kvm_available(void);
 int xen_available(void);
diff --git a/hw/adlib.c b/hw/adlib.c
index b5e1564..dd8b188 100644
--- a/hw/adlib.c
+++ b/hw/adlib.c
@@ -275,7 +275,7 @@ static void Adlib_fini (AdlibState *s)
     AUD_remove_card (&s->card);
 }
 
-int Adlib_init (ISABus *bus, qemu_irq *pic)
+int Adlib_init (ISABus *bus)
 {
     AdlibState *s = &glob_adlib;
     struct audsettings as;
diff --git a/hw/audiodev.h b/hw/audiodev.h
index bfa324a..ed2790f 100644
--- a/hw/audiodev.h
+++ b/hw/audiodev.h
@@ -2,19 +2,19 @@
 int es1370_init(PCIBus *bus);
 
 /* sb16.c */
-int SB16_init(ISABus *bus, qemu_irq *pic);
+int SB16_init(ISABus *bus);
 
 /* adlib.c */
-int Adlib_init(ISABus *bus, qemu_irq *pic);
+int Adlib_init(ISABus *bus);
 
 /* gus.c */
-int GUS_init(ISABus *bus, qemu_irq *pic);
+int GUS_init(ISABus *bus);
 
 /* ac97.c */
 int ac97_init(PCIBus *bus);
 
 /* cs4231a.c */
-int cs4231a_init(ISABus *bus, qemu_irq *pic);
+int cs4231a_init(ISABus *bus);
 
 /* intel-hda.c + hda-audio.c */
 int intel_hda_and_codec_init(PCIBus *bus);
diff --git a/hw/cs4231a.c b/hw/cs4231a.c
index 0238829..dc77a3a 100644
--- a/hw/cs4231a.c
+++ b/hw/cs4231a.c
@@ -659,7 +659,7 @@ static int cs4231a_initfn (ISADevice *dev)
     return 0;
 }
 
-int cs4231a_init (ISABus *bus, qemu_irq *pic)
+int cs4231a_init (ISABus *bus)
 {
     isa_create_simple (bus, "cs4231a");
     return 0;
diff --git a/hw/gus.c b/hw/gus.c
index 17cceee..ab872d8 100644
--- a/hw/gus.c
+++ b/hw/gus.c
@@ -293,7 +293,7 @@ static int gus_initfn (ISADevice *dev)
     return 0;
 }
 
-int GUS_init (ISABus *bus, qemu_irq *pic)
+int GUS_init (ISABus *bus)
 {
     isa_create_simple (bus, "gus");
     return 0;
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 8ed66ce..da04982 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -281,7 +281,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
 
     /* Sound card */
     /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */
-    audio_init(isa_bus, i8259, NULL);
+    audio_init(isa_bus, NULL);
 
     /* NVRAM */
     dev = qdev_create(NULL, "ds1225y");
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 330924e..d94ad1d 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -973,7 +973,7 @@ void mips_malta_init (ram_addr_t ram_size,
     fdctrl_init_isa(isa_bus, fd);
 
     /* Sound card */
-    audio_init(isa_bus, NULL, pci_bus);
+    audio_init(isa_bus, pci_bus);
 
     /* Network card */
     network_init();
diff --git a/hw/pc.h b/hw/pc.h
index 17648cc..13e41f1 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -176,7 +176,7 @@ extern int no_hpet;
 
 /* pcspk.c */
 void pcspk_init(ISADevice *pit);
-int pcspk_audio_init(ISABus *bus, qemu_irq *pic);
+int pcspk_audio_init(ISABus *bus);
 
 /* piix_pci.c */
 struct PCII440FXState;
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 77b88b4..b70431f 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -222,7 +222,7 @@ static void pc_init1(MemoryRegion *system_memory,
     qdev_property_add_child(qdev_resolve_path("/i440fx/piix3", NULL),
                             "rtc", (DeviceState *)rtc_state, NULL);
 
-    audio_init(isa_bus, gsi, pci_enabled ? pci_bus : NULL);
+    audio_init(isa_bus, pci_enabled ? pci_bus : NULL);
 
     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
                  floppy, idebus[0], idebus[1], rtc_state);
diff --git a/hw/pcspk.c b/hw/pcspk.c
index 4d949fb..acb0167 100644
--- a/hw/pcspk.c
+++ b/hw/pcspk.c
@@ -96,7 +96,7 @@ static void pcspk_callback(void *opaque, int free)
     }
 }
 
-int pcspk_audio_init(ISABus *bus, qemu_irq *pic)
+int pcspk_audio_init(ISABus *bus)
 {
     PCSpkState *s = &pcspk_state;
     struct audsettings as = {PCSPK_SAMPLE_RATE, 1, AUD_FMT_U8, 0};
diff --git a/hw/sb16.c b/hw/sb16.c
index 88ad8e8..887b32e 100644
--- a/hw/sb16.c
+++ b/hw/sb16.c
@@ -1385,7 +1385,7 @@ static int sb16_initfn (ISADevice *dev)
     return 0;
 }
 
-int SB16_init (ISABus *bus, qemu_irq *pic)
+int SB16_init (ISABus *bus)
 {
     isa_create_simple (bus, "sb16");
     return 0;
commit d3c68e4f45b54c447c9a169533c286cb1be62b59
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Thu Dec 15 22:10:00 2011 +0100

    isa: always use provided ISA bus in isa_bus_irqs()
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index 3207680..5af790b 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -53,8 +53,10 @@ ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space_io)
 
 void isa_bus_irqs(ISABus *bus, qemu_irq *irqs)
 {
-    assert(!bus || bus == isabus);
-    isabus->irqs = irqs;
+    if (!bus) {
+        hw_error("Can't set isa irqs with no isa bus present.");
+    }
+    bus->irqs = irqs;
 }
 
 /*
commit 75782268d682828e1ebbaa1cfaf63ecde50dad54
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Thu Dec 15 22:09:59 2011 +0100

    isa: always use provided ISA bus when creating an isa device
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index 7c94f0b..3207680 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -130,12 +130,11 @@ ISADevice *isa_create(ISABus *bus, const char *name)
 {
     DeviceState *dev;
 
-    assert(!bus || bus == isabus);
-    if (!isabus) {
+    if (!bus) {
         hw_error("Tried to create isa device %s with no isa bus present.",
                  name);
     }
-    dev = qdev_create(&isabus->qbus, name);
+    dev = qdev_create(&bus->qbus, name);
     return DO_UPCAST(ISADevice, qdev, dev);
 }
 
@@ -143,12 +142,11 @@ ISADevice *isa_try_create(ISABus *bus, const char *name)
 {
     DeviceState *dev;
 
-    assert(!bus || bus == isabus);
-    if (!isabus) {
+    if (!bus) {
         hw_error("Tried to create isa device %s with no isa bus present.",
                  name);
     }
-    dev = qdev_try_create(&isabus->qbus, name);
+    dev = qdev_try_create(&bus->qbus, name);
     return DO_UPCAST(ISADevice, qdev, dev);
 }
 
commit 142e9787485d5c58341534b78366ae7ea8e74969
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Thu Dec 15 22:09:58 2011 +0100

    malta: give ISA bus to ISA methods
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 621e661..330924e 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -942,8 +942,7 @@ void mips_malta_init (ram_addr_t ram_size,
     /* Southbridge */
     ide_drive_get(hd, MAX_IDE_BUS);
 
-    piix4_devfn = piix4_init(pci_bus, 80);
-    isa_bus = NULL;
+    piix4_devfn = piix4_init(pci_bus, &isa_bus, 80);
 
     /* Interrupt controller */
     /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
diff --git a/hw/pc.h b/hw/pc.h
index 04e72cc..17648cc 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -196,7 +196,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn,
 
 /* piix4.c */
 extern PCIDevice *piix4_dev;
-int piix4_init(PCIBus *bus, int devfn);
+int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn);
 
 /* vga.c */
 enum vga_retrace_method {
diff --git a/hw/piix4.c b/hw/piix4.c
index 2fd1171..51af459 100644
--- a/hw/piix4.c
+++ b/hw/piix4.c
@@ -93,11 +93,12 @@ static int piix4_initfn(PCIDevice *dev)
     return 0;
 }
 
-int piix4_init(PCIBus *bus, int devfn)
+int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn)
 {
     PCIDevice *d;
 
     d = pci_create_simple_multifunction(bus, devfn, true, "PIIX4");
+    *isa_bus = DO_UPCAST(ISABus, qbus, qdev_get_child_bus(&d->qdev, "isa.0"));
     return d->devfn;
 }
 
commit c9940edb473cbaeac565b3a420fdfcc0b6c31e5d
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Thu Dec 15 22:09:57 2011 +0100

    fulong2e: give ISA bus to ISA methods
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index e6e120c..5e87665 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -264,7 +264,6 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
     int64_t kernel_entry;
     qemu_irq *i8259;
     qemu_irq *cpu_exit_irq;
-    int via_devfn;
     PCIBus *pci_bus;
     ISABus *isa_bus;
     i2c_bus *smbus;
@@ -338,12 +337,11 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
     /* South bridge */
     ide_drive_get(hd, MAX_IDE_BUS);
 
-    via_devfn = vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 0));
-    if (via_devfn < 0) {
+    isa_bus = vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 0));
+    if (!isa_bus) {
         fprintf(stderr, "vt82c686b_init error\n");
         exit(1);
     }
-    isa_bus = NULL;
 
     /* Interrupt controller */
     /* The 8259 -> IP5  */
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 2845959..038128b 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -507,13 +507,13 @@ static int vt82c686b_initfn(PCIDevice *d)
     return 0;
 }
 
-int vt82c686b_init(PCIBus *bus, int devfn)
+ISABus *vt82c686b_init(PCIBus *bus, int devfn)
 {
     PCIDevice *d;
 
     d = pci_create_simple_multifunction(bus, devfn, true, "VT82C686B");
 
-    return d->devfn;
+    return DO_UPCAST(ISABus, qbus, qdev_get_child_bus(&d->qdev, "isa.0"));
 }
 
 static PCIDeviceInfo via_info = {
diff --git a/hw/vt82c686.h b/hw/vt82c686.h
index e3270ca..6ef876d 100644
--- a/hw/vt82c686.h
+++ b/hw/vt82c686.h
@@ -2,7 +2,7 @@
 #define HW_VT82C686_H
 
 /* vt82c686.c */
-int vt82c686b_init(PCIBus * bus, int devfn);
+ISABus *vt82c686b_init(PCIBus * bus, int devfn);
 void vt82c686b_ac97_init(PCIBus *bus, int devfn);
 void vt82c686b_mc97_init(PCIBus *bus, int devfn);
 i2c_bus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
commit ab953e284ad2e701bdbad1685d07c1a930ba8d48
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Thu Dec 15 22:09:56 2011 +0100

    sun4u: give ISA bus to ISA methods
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/sun4u.c b/hw/sun4u.c
index dfb81da..e3e8dde 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -530,10 +530,12 @@ static ISABus *
 pci_ebus_init(PCIBus *bus, int devfn)
 {
     qemu_irq *isa_irq;
+    PCIDevice *pci_dev;
     ISABus *isa_bus;
 
-    pci_create_simple(bus, devfn, "ebus");
-    isa_bus = NULL;
+    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_bus_irqs(isa_bus, isa_irq);
     return isa_bus;
commit 71baa3036fa175f2a5fb08a1a64c541cddb47be4
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Thu Dec 15 22:09:55 2011 +0100

    alpha: give ISA bus to ISA methods
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c
index a07a2ff..876335a 100644
--- a/hw/alpha_dp264.c
+++ b/hw/alpha_dp264.c
@@ -68,8 +68,8 @@ static void clipper_init(ram_addr_t ram_size,
     cpus[0]->trap_arg2 = smp_cpus;
 
     /* Init the chipset.  */
-    pci_bus = typhoon_init(ram_size, &rtc_irq, cpus, clipper_pci_map_irq);
-    isa_bus = NULL;
+    pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus,
+                           clipper_pci_map_irq);
 
     rtc_init(isa_bus, 1980, rtc_irq);
     pit_init(isa_bus, 0x40, 0);
diff --git a/hw/alpha_sys.h b/hw/alpha_sys.h
index 13f0177..d54b18f 100644
--- a/hw/alpha_sys.h
+++ b/hw/alpha_sys.h
@@ -12,7 +12,8 @@
 #include "irq.h"
 
 
-PCIBus *typhoon_init(ram_addr_t, qemu_irq *, CPUState *[4], pci_map_irq_fn);
+PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, CPUState *[4],
+                     pci_map_irq_fn);
 
 /* alpha_pci.c.  */
 extern const MemoryRegionOps alpha_pci_bw_io_ops;
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index 113837d..adf7382 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -691,7 +691,8 @@ static void typhoon_alarm_timer(void *opaque)
     cpu_interrupt(s->cchip.cpu[cpu], CPU_INTERRUPT_TIMER);
 }
 
-PCIBus *typhoon_init(ram_addr_t ram_size, qemu_irq *p_rtc_irq,
+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)
 {
     const uint64_t MB = 1024 * 1024;
@@ -791,12 +792,11 @@ PCIBus *typhoon_init(ram_addr_t ram_size, qemu_irq *p_rtc_irq,
     /* ??? Technically there should be a cy82c693ub pci-isa bridge.  */
     {
         qemu_irq isa_pci_irq, *isa_irqs;
-        ISABus *isa_bus;
 
-        isa_bus = isa_bus_new(NULL, addr_space_io);
+        *isa_bus = isa_bus_new(NULL, addr_space_io);
         isa_pci_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1);
-        isa_irqs = i8259_init(isa_bus, isa_pci_irq);
-        isa_bus_irqs(isa_bus, isa_irqs);
+        isa_irqs = i8259_init(*isa_bus, isa_pci_irq);
+        isa_bus_irqs(*isa_bus, isa_irqs);
     }
 
     return b;
commit 605730793dfa0974a1dfb6a7a29d7eb68c0befbc
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Thu Dec 15 22:09:54 2011 +0100

    pc: give ISA bus to ISA methods
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pc.h b/hw/pc.h
index afb7535..04e72cc 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -183,7 +183,7 @@ struct PCII440FXState;
 typedef struct PCII440FXState PCII440FXState;
 
 PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn,
-                    qemu_irq *pic,
+                    ISABus **isa_bus, qemu_irq *pic,
                     MemoryRegion *address_space_mem,
                     MemoryRegion *address_space_io,
                     ram_addr_t ram_size,
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index b4126b5..77b88b4 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -137,7 +137,7 @@ static void pc_init1(MemoryRegion *system_memory,
     gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
 
     if (pci_enabled) {
-        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, gsi,
+        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
                               system_memory, system_io, ram_size,
                               below_4g_mem_size,
                               0x100000000ULL - below_4g_mem_size,
@@ -146,7 +146,6 @@ static void pc_init1(MemoryRegion *system_memory,
                                ? 0
                                : ((uint64_t)1 << 62)),
                               pci_memory, ram_memory);
-        isa_bus = NULL;
     } else {
         pci_bus = NULL;
         i440fx_state = NULL;
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index e188c7a..3652522 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -252,7 +252,7 @@ static int i440fx_initfn(PCIDevice *dev)
 static PCIBus *i440fx_common_init(const char *device_name,
                                   PCII440FXState **pi440fx_state,
                                   int *piix3_devfn,
-                                  qemu_irq *pic,
+                                  ISABus **isa_bus, qemu_irq *pic,
                                   MemoryRegion *address_space_mem,
                                   MemoryRegion *address_space_io,
                                   ram_addr_t ram_size,
@@ -318,6 +318,8 @@ static PCIBus *i440fx_common_init(const char *device_name,
     }
     qdev_property_add_child(dev, "piix3", &piix3->dev.qdev, NULL);
     piix3->pic = pic;
+    *isa_bus = DO_UPCAST(ISABus, qbus,
+                         qdev_get_child_bus(&piix3->dev.qdev, "isa.0"));
 
     *piix3_devfn = piix3->dev.devfn;
 
@@ -332,7 +334,7 @@ static PCIBus *i440fx_common_init(const char *device_name,
 }
 
 PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
-                    qemu_irq *pic,
+                    ISABus **isa_bus, qemu_irq *pic,
                     MemoryRegion *address_space_mem,
                     MemoryRegion *address_space_io,
                     ram_addr_t ram_size,
@@ -345,7 +347,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
 {
     PCIBus *b;
 
-    b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, pic,
+    b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, isa_bus, pic,
                            address_space_mem, address_space_io, ram_size,
                            pci_hole_start, pci_hole_size,
                            pci_hole64_size, pci_hole64_size,
commit a811f53ccb57911636f7d3d9cb1652d6d49df2c3
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Thu Dec 15 22:09:53 2011 +0100

    i8259: give ISA device to isa_register_ioport()
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/i8259.c b/hw/i8259.c
index 4446339..7331e0e 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -469,9 +469,9 @@ static int pic_initfn(ISADevice *dev)
     memory_region_init_io(&s->base_io, &pic_base_ioport_ops, s, "pic", 2);
     memory_region_init_io(&s->elcr_io, &pic_elcr_ioport_ops, s, "elcr", 1);
 
-    isa_register_ioport(NULL, &s->base_io, s->iobase);
+    isa_register_ioport(dev, &s->base_io, s->iobase);
     if (s->elcr_addr != -1) {
-        isa_register_ioport(NULL, &s->elcr_io, s->elcr_addr);
+        isa_register_ioport(dev, &s->elcr_io, s->elcr_addr);
     }
 
     qdev_init_gpio_out(&dev->qdev, s->int_out, ARRAY_SIZE(s->int_out));
commit d1a1be180c0e0299d7b7c1e3e6ed3b7002bdf8e0
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Thu Dec 15 22:09:52 2011 +0100

    isa: move ISABus structure definition to header file
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index dcbb134..7c94f0b 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -22,11 +22,6 @@
 #include "isa.h"
 #include "exec-memory.h"
 
-struct ISABus {
-    BusState qbus;
-    MemoryRegion *address_space_io;
-    qemu_irq *irqs;
-};
 static ISABus *isabus;
 target_phys_addr_t isa_mem_base = 0;
 
diff --git a/hw/isa.h b/hw/isa.h
index 1e75f87..b11a0be 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -12,6 +12,12 @@
 typedef struct ISADevice ISADevice;
 typedef struct ISADeviceInfo ISADeviceInfo;
 
+struct ISABus {
+    BusState qbus;
+    MemoryRegion *address_space_io;
+    qemu_irq *irqs;
+};
+
 struct ISADevice {
     DeviceState qdev;
     uint32_t isairq[2];
commit 48a18b3c698295e4d891f34e919615e84e20f027
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Thu Dec 15 22:09:51 2011 +0100

    isa: give ISABus/ISADevice to isa_create(), isa_bus_irqs() and isa_get_irq() functions
    
    NULL is a valid bus/device, so there is no change in behaviour.
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/arch_init.c b/arch_init.c
index a411fdf..3bc2a41 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -473,7 +473,7 @@ struct soundhw {
     int enabled;
     int isa;
     union {
-        int (*init_isa) (qemu_irq *pic);
+        int (*init_isa) (ISABus *bus, qemu_irq *pic);
         int (*init_pci) (PCIBus *bus);
     } init;
 };
@@ -628,7 +628,7 @@ void select_soundhw(const char *optarg)
     }
 }
 
-void audio_init(qemu_irq *isa_pic, PCIBus *pci_bus)
+void audio_init(ISABus *isa_bus, qemu_irq *isa_pic, PCIBus *pci_bus)
 {
     struct soundhw *c;
 
@@ -636,7 +636,7 @@ void audio_init(qemu_irq *isa_pic, PCIBus *pci_bus)
         if (c->enabled) {
             if (c->isa) {
                 if (isa_pic) {
-                    c->init.init_isa(isa_pic);
+                    c->init.init_isa(isa_bus, isa_pic);
                 }
             } else {
                 if (pci_bus) {
@@ -650,7 +650,7 @@ void audio_init(qemu_irq *isa_pic, PCIBus *pci_bus)
 void select_soundhw(const char *optarg)
 {
 }
-void audio_init(qemu_irq *isa_pic, PCIBus *pci_bus)
+void audio_init(ISABus *isa_bus, qemu_irq *isa_pic, PCIBus *pci_bus)
 {
 }
 #endif
diff --git a/arch_init.h b/arch_init.h
index a74187a..074f02a 100644
--- a/arch_init.h
+++ b/arch_init.h
@@ -27,7 +27,7 @@ void do_acpitable_option(const char *optarg);
 void do_smbios_option(const char *optarg);
 void cpudef_init(void);
 int audio_available(void);
-void audio_init(qemu_irq *isa_pic, PCIBus *pci_bus);
+void audio_init(ISABus *isa_bus, qemu_irq *isa_pic, PCIBus *pci_bus);
 int tcg_available(void);
 int kvm_available(void);
 int xen_available(void);
diff --git a/hw/adlib.c b/hw/adlib.c
index e4bfcc6..b5e1564 100644
--- a/hw/adlib.c
+++ b/hw/adlib.c
@@ -275,7 +275,7 @@ static void Adlib_fini (AdlibState *s)
     AUD_remove_card (&s->card);
 }
 
-int Adlib_init (qemu_irq *pic)
+int Adlib_init (ISABus *bus, qemu_irq *pic)
 {
     AdlibState *s = &glob_adlib;
     struct audsettings as;
diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c
index 598b830..a07a2ff 100644
--- a/hw/alpha_dp264.c
+++ b/hw/alpha_dp264.c
@@ -50,6 +50,7 @@ static void clipper_init(ram_addr_t ram_size,
 {
     CPUState *cpus[4];
     PCIBus *pci_bus;
+    ISABus *isa_bus;
     qemu_irq rtc_irq;
     long size, i;
     const char *palcode_filename;
@@ -68,10 +69,11 @@ static void clipper_init(ram_addr_t ram_size,
 
     /* Init the chipset.  */
     pci_bus = typhoon_init(ram_size, &rtc_irq, cpus, clipper_pci_map_irq);
+    isa_bus = NULL;
 
-    rtc_init(1980, rtc_irq);
-    pit_init(0x40, 0);
-    isa_create_simple("i8042");
+    rtc_init(isa_bus, 1980, rtc_irq);
+    pit_init(isa_bus, 0x40, 0);
+    isa_create_simple(isa_bus, "i8042");
 
     /* VGA setup.  Don't bother loading the bios.  */
     alpha_pci_vga_setup(pci_bus);
@@ -79,7 +81,7 @@ static void clipper_init(ram_addr_t ram_size,
     /* Serial code setup.  */
     for (i = 0; i < MAX_SERIAL_PORTS; ++i) {
         if (serial_hds[i]) {
-            serial_isa_init(i, serial_hds[i]);
+            serial_isa_init(isa_bus, i, serial_hds[i]);
         }
     }
 
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index c7608bb..113837d 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -791,11 +791,12 @@ PCIBus *typhoon_init(ram_addr_t ram_size, qemu_irq *p_rtc_irq,
     /* ??? Technically there should be a cy82c693ub pci-isa bridge.  */
     {
         qemu_irq isa_pci_irq, *isa_irqs;
+        ISABus *isa_bus;
 
-        isa_bus_new(NULL, addr_space_io);
+        isa_bus = isa_bus_new(NULL, addr_space_io);
         isa_pci_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1);
-        isa_irqs = i8259_init(isa_pci_irq);
-        isa_bus_irqs(isa_irqs);
+        isa_irqs = i8259_init(isa_bus, isa_pci_irq);
+        isa_bus_irqs(isa_bus, isa_irqs);
     }
 
     return b;
diff --git a/hw/audiodev.h b/hw/audiodev.h
index d60c349..bfa324a 100644
--- a/hw/audiodev.h
+++ b/hw/audiodev.h
@@ -2,19 +2,19 @@
 int es1370_init(PCIBus *bus);
 
 /* sb16.c */
-int SB16_init(qemu_irq *pic);
+int SB16_init(ISABus *bus, qemu_irq *pic);
 
 /* adlib.c */
-int Adlib_init(qemu_irq *pic);
+int Adlib_init(ISABus *bus, qemu_irq *pic);
 
 /* gus.c */
-int GUS_init(qemu_irq *pic);
+int GUS_init(ISABus *bus, qemu_irq *pic);
 
 /* ac97.c */
 int ac97_init(PCIBus *bus);
 
 /* cs4231a.c */
-int cs4231a_init(qemu_irq *pic);
+int cs4231a_init(ISABus *bus, qemu_irq *pic);
 
 /* intel-hda.c + hda-audio.c */
 int intel_hda_and_codec_init(PCIBus *bus);
diff --git a/hw/cs4231a.c b/hw/cs4231a.c
index a7e03a3..0238829 100644
--- a/hw/cs4231a.c
+++ b/hw/cs4231a.c
@@ -659,9 +659,9 @@ static int cs4231a_initfn (ISADevice *dev)
     return 0;
 }
 
-int cs4231a_init (qemu_irq *pic)
+int cs4231a_init (ISABus *bus, qemu_irq *pic)
 {
-    isa_create_simple ("cs4231a");
+    isa_create_simple (bus, "cs4231a");
     return 0;
 }
 
diff --git a/hw/fdc.h b/hw/fdc.h
index 506feb6..55a8d73 100644
--- a/hw/fdc.h
+++ b/hw/fdc.h
@@ -7,11 +7,11 @@
 /* fdc.c */
 #define MAX_FD 2
 
-static inline ISADevice *fdctrl_init_isa(DriveInfo **fds)
+static inline ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds)
 {
     ISADevice *dev;
 
-    dev = isa_try_create("isa-fdc");
+    dev = isa_try_create(bus, "isa-fdc");
     if (!dev) {
         return NULL;
     }
diff --git a/hw/gus.c b/hw/gus.c
index b5eb548..17cceee 100644
--- a/hw/gus.c
+++ b/hw/gus.c
@@ -293,9 +293,9 @@ static int gus_initfn (ISADevice *dev)
     return 0;
 }
 
-int GUS_init (qemu_irq *pic)
+int GUS_init (ISABus *bus, qemu_irq *pic)
 {
-    isa_create_simple ("gus");
+    isa_create_simple (bus, "gus");
     return 0;
 }
 
diff --git a/hw/i8254.c b/hw/i8254.c
index 12571ef..cf9ed2f 100644
--- a/hw/i8254.c
+++ b/hw/i8254.c
@@ -525,7 +525,7 @@ static int pit_initfn(ISADevice *dev)
     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);
-    s->irq = isa_get_irq(pit->irq);
+    s->irq = isa_get_irq(dev, pit->irq);
 
     memory_region_init_io(&pit->ioports, &pit_ioport_ops, pit, "pit", 4);
     isa_register_ioport(dev, &pit->ioports, pit->iobase);
diff --git a/hw/i8259.c b/hw/i8259.c
index ab519de..4446339 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -518,7 +518,7 @@ void irq_info(Monitor *mon)
 #endif
 }
 
-qemu_irq *i8259_init(qemu_irq parent_irq)
+qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq)
 {
     qemu_irq *irq_set;
     ISADevice *dev;
@@ -526,7 +526,7 @@ qemu_irq *i8259_init(qemu_irq parent_irq)
 
     irq_set = g_malloc(ISA_NUM_IRQS * sizeof(qemu_irq));
 
-    dev = isa_create("isa-i8259");
+    dev = isa_create(bus, "isa-i8259");
     qdev_prop_set_uint32(&dev->qdev, "iobase", 0x20);
     qdev_prop_set_uint32(&dev->qdev, "elcr_addr", 0x4d0);
     qdev_prop_set_uint8(&dev->qdev, "elcr_mask", 0xf8);
@@ -540,7 +540,7 @@ qemu_irq *i8259_init(qemu_irq parent_irq)
 
     isa_pic = DO_UPCAST(PicState, dev, dev);
 
-    dev = isa_create("isa-i8259");
+    dev = isa_create(bus, "isa-i8259");
     qdev_prop_set_uint32(&dev->qdev, "iobase", 0xa0);
     qdev_prop_set_uint32(&dev->qdev, "elcr_addr", 0x4d1);
     qdev_prop_set_uint8(&dev->qdev, "elcr_mask", 0xde);
diff --git a/hw/ide.h b/hw/ide.h
index f9f6bd8..0b18c90 100644
--- a/hw/ide.h
+++ b/hw/ide.h
@@ -8,7 +8,7 @@
 #define MAX_IDE_DEVS	2
 
 /* ide-isa.c */
-ISADevice *isa_ide_init(int iobase, int iobase2, int isairq,
+ISADevice *isa_ide_init(ISABus *bus, int iobase, int iobase2, int isairq,
                         DriveInfo *hd0, DriveInfo *hd1);
 
 /* ide-pci.c */
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index 01a9e59..219f3a4 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -73,13 +73,13 @@ static int isa_ide_initfn(ISADevice *dev)
     return 0;
 };
 
-ISADevice *isa_ide_init(int iobase, int iobase2, int isairq,
+ISADevice *isa_ide_init(ISABus *bus, int iobase, int iobase2, int isairq,
                         DriveInfo *hd0, DriveInfo *hd1)
 {
     ISADevice *dev;
     ISAIDEState *s;
 
-    dev = isa_create("isa-ide");
+    dev = isa_create(bus, "isa-ide");
     qdev_prop_set_uint32(&dev->qdev, "iobase",  iobase);
     qdev_prop_set_uint32(&dev->qdev, "iobase2", iobase2);
     qdev_prop_set_uint32(&dev->qdev, "irq",     isairq);
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 08cbbe2..3473345 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -136,7 +136,7 @@ static void pci_piix_init_ports(PCIIDEState *d) {
         ide_bus_new(&d->bus[i], &d->dev.qdev, i);
         ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase,
                         port_info[i].iobase2);
-        ide_init2(&d->bus[i], isa_get_irq(port_info[i].isairq));
+        ide_init2(&d->bus[i], isa_get_irq(NULL, port_info[i].isairq));
 
         bmdma_init(&d->bus[i], &d->bmdma[i], d);
         d->bmdma[i].bus = &d->bus[i];
diff --git a/hw/ide/via.c b/hw/ide/via.c
index a57134c..4ea2064 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -160,7 +160,7 @@ static void vt82c686b_init_ports(PCIIDEState *d) {
         ide_bus_new(&d->bus[i], &d->dev.qdev, i);
         ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase,
                         port_info[i].iobase2);
-        ide_init2(&d->bus[i], isa_get_irq(port_info[i].isairq));
+        ide_init2(&d->bus[i], isa_get_irq(NULL, port_info[i].isairq));
 
         bmdma_init(&d->bus[i], &d->bmdma[i], d);
         d->bmdma[i].bus = &d->bus[i];
diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index 7c2c261..dcbb134 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -56,8 +56,9 @@ ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space_io)
     return isabus;
 }
 
-void isa_bus_irqs(qemu_irq *irqs)
+void isa_bus_irqs(ISABus *bus, qemu_irq *irqs)
 {
+    assert(!bus || bus == isabus);
     isabus->irqs = irqs;
 }
 
@@ -67,8 +68,9 @@ void isa_bus_irqs(qemu_irq *irqs)
  * This function is only for special cases such as the 'ferr', and
  * temporary use for normal devices until they are converted to qdev.
  */
-qemu_irq isa_get_irq(int isairq)
+qemu_irq isa_get_irq(ISADevice *dev, int isairq)
 {
+    assert(!dev || DO_UPCAST(ISABus, qbus, dev->qdev.parent_bus) == isabus);
     if (isairq < 0 || isairq > 15) {
         hw_error("isa irq %d invalid", isairq);
     }
@@ -79,7 +81,7 @@ void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq)
 {
     assert(dev->nirqs < ARRAY_SIZE(dev->isairq));
     dev->isairq[dev->nirqs] = isairq;
-    *p = isa_get_irq(isairq);
+    *p = isa_get_irq(dev, isairq);
     dev->nirqs++;
 }
 
@@ -129,10 +131,11 @@ void isa_qdev_register(ISADeviceInfo *info)
     qdev_register(&info->qdev);
 }
 
-ISADevice *isa_create(const char *name)
+ISADevice *isa_create(ISABus *bus, const char *name)
 {
     DeviceState *dev;
 
+    assert(!bus || bus == isabus);
     if (!isabus) {
         hw_error("Tried to create isa device %s with no isa bus present.",
                  name);
@@ -141,10 +144,11 @@ ISADevice *isa_create(const char *name)
     return DO_UPCAST(ISADevice, qdev, dev);
 }
 
-ISADevice *isa_try_create(const char *name)
+ISADevice *isa_try_create(ISABus *bus, const char *name)
 {
     DeviceState *dev;
 
+    assert(!bus || bus == isabus);
     if (!isabus) {
         hw_error("Tried to create isa device %s with no isa bus present.",
                  name);
@@ -153,11 +157,11 @@ ISADevice *isa_try_create(const char *name)
     return DO_UPCAST(ISADevice, qdev, dev);
 }
 
-ISADevice *isa_create_simple(const char *name)
+ISADevice *isa_create_simple(ISABus *bus, const char *name)
 {
     ISADevice *dev;
 
-    dev = isa_create(name);
+    dev = isa_create(bus, name);
     qdev_init_nofail(&dev->qdev);
     return dev;
 }
diff --git a/hw/isa.h b/hw/isa.h
index 5eb9c78..1e75f87 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -9,7 +9,6 @@
 
 #define ISA_NUM_IRQS 16
 
-typedef struct ISABus ISABus;
 typedef struct ISADevice ISADevice;
 typedef struct ISADeviceInfo ISADeviceInfo;
 
@@ -27,14 +26,14 @@ struct ISADeviceInfo {
 };
 
 ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space_io);
-void isa_bus_irqs(qemu_irq *irqs);
-qemu_irq isa_get_irq(int isairq);
+void isa_bus_irqs(ISABus *bus, qemu_irq *irqs);
+qemu_irq isa_get_irq(ISADevice *dev, int isairq);
 void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq);
 void isa_qdev_register(ISADeviceInfo *info);
 MemoryRegion *isa_address_space(ISADevice *dev);
-ISADevice *isa_create(const char *name);
-ISADevice *isa_try_create(const char *name);
-ISADevice *isa_create_simple(const char *name);
+ISADevice *isa_create(ISABus *bus, const char *name);
+ISADevice *isa_try_create(ISABus *bus, const char *name);
+ISADevice *isa_create_simple(ISABus *bus, const char *name);
 
 /**
  * isa_register_ioport: Install an I/O port region on the ISA bus.
diff --git a/hw/m48t59.c b/hw/m48t59.c
index 8d8d495..c043996 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -660,13 +660,14 @@ M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base,
     return state;
 }
 
-M48t59State *m48t59_init_isa(uint32_t io_base, uint16_t size, int type)
+M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
+                             int type)
 {
     M48t59ISAState *d;
     ISADevice *dev;
     M48t59State *s;
 
-    dev = isa_create("m48t59_isa");
+    dev = isa_create(bus, "m48t59_isa");
     qdev_prop_set_uint32(&dev->qdev, "type", type);
     qdev_prop_set_uint32(&dev->qdev, "size", size);
     qdev_prop_set_uint32(&dev->qdev, "io_base", io_base);
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 0c23cb0..9cbd052 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -677,12 +677,12 @@ static int rtc_initfn(ISADevice *dev)
     return 0;
 }
 
-ISADevice *rtc_init(int base_year, qemu_irq intercept_irq)
+ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
 {
     ISADevice *dev;
     RTCState *s;
 
-    dev = isa_create("mc146818rtc");
+    dev = isa_create(bus, "mc146818rtc");
     s = DO_UPCAST(RTCState, dev, dev);
     qdev_prop_set_int32(&dev->qdev, "base_year", base_year);
     qdev_init_nofail(&dev->qdev);
diff --git a/hw/mc146818rtc.h b/hw/mc146818rtc.h
index 575968c..f119930 100644
--- a/hw/mc146818rtc.h
+++ b/hw/mc146818rtc.h
@@ -5,7 +5,7 @@
 
 #define RTC_ISA_IRQ 8
 
-ISADevice *rtc_init(int base_year, qemu_irq intercept_irq);
+ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq);
 void rtc_set_memory(ISADevice *dev, int addr, int val);
 void rtc_set_date(ISADevice *dev, const struct tm *tm);
 
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index 04921c1..e6e120c 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -266,6 +266,7 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
     qemu_irq *cpu_exit_irq;
     int via_devfn;
     PCIBus *pci_bus;
+    ISABus *isa_bus;
     i2c_bus *smbus;
     int i;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
@@ -342,11 +343,12 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
         fprintf(stderr, "vt82c686b_init error\n");
         exit(1);
     }
+    isa_bus = NULL;
 
     /* Interrupt controller */
     /* The 8259 -> IP5  */
-    i8259 = i8259_init(env->irq[5]);
-    isa_bus_irqs(i8259);
+    i8259 = i8259_init(isa_bus, env->irq[5]);
+    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));
@@ -358,23 +360,23 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
     smbus_eeprom_init(smbus, 1, eeprom_spd, sizeof(eeprom_spd));
 
     /* init other devices */
-    pit = pit_init(0x40, 0);
+    pit = pit_init(isa_bus, 0x40, 0);
     cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
     DMA_init(0, cpu_exit_irq);
 
     /* Super I/O */
-    isa_create_simple("i8042");
+    isa_create_simple(isa_bus, "i8042");
 
-    rtc_init(2000, NULL);
+    rtc_init(isa_bus, 2000, NULL);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
-            serial_isa_init(i, serial_hds[i]);
+            serial_isa_init(isa_bus, i, serial_hds[i]);
         }
     }
 
     if (parallel_hds[0]) {
-        parallel_init(0, parallel_hds[0]);
+        parallel_init(isa_bus, 0, parallel_hds[0]);
     }
 
     /* Sound card */
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 358de59..8ed66ce 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -120,6 +120,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
     NICInfo *nd;
     DeviceState *dev;
     SysBusDevice *sysbus;
+    ISABus *isa_bus;
     ISADevice *pit;
     DriveInfo *fds[MAX_FD];
     qemu_irq esp_reset, dma_enable;
@@ -183,12 +184,12 @@ static void mips_jazz_init(MemoryRegion *address_space,
     memory_region_add_subregion(address_space, 0x8000d000, dma_dummy);
 
     /* ISA devices */
-    isa_bus_new(NULL, address_space_io);
-    i8259 = i8259_init(env->irq[4]);
-    isa_bus_irqs(i8259);
+    isa_bus = isa_bus_new(NULL, address_space_io);
+    i8259 = i8259_init(isa_bus, env->irq[4]);
+    isa_bus_irqs(isa_bus, i8259);
     cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
     DMA_init(0, cpu_exit_irq);
-    pit = pit_init(0x40, 0);
+    pit = pit_init(isa_bus, 0x40, 0);
     pcspk_init(pit);
 
     /* ISA IO space at 0x90000000 */
@@ -255,7 +256,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
     fdctrl_init_sysbus(rc4030[1], 0, 0x80003000, fds);
 
     /* Real time clock */
-    rtc_init(1980, NULL);
+    rtc_init(isa_bus, 1980, NULL);
     memory_region_init_io(rtc, &rtc_ops, NULL, "rtc", 0x1000);
     memory_region_add_subregion(address_space, 0x80004000, rtc);
 
@@ -280,7 +281,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
 
     /* Sound card */
     /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */
-    audio_init(i8259, NULL);
+    audio_init(isa_bus, i8259, NULL);
 
     /* NVRAM */
     dev = qdev_create(NULL, "ds1225y");
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index e7dfbd6..621e661 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -774,6 +774,7 @@ void mips_malta_init (ram_addr_t ram_size,
     target_long bios_size;
     int64_t kernel_entry;
     PCIBus *pci_bus;
+    ISABus *isa_bus;
     CPUState *env;
     qemu_irq *i8259 = NULL, *isa_irq;
     qemu_irq *cpu_exit_irq;
@@ -942,37 +943,38 @@ void mips_malta_init (ram_addr_t ram_size,
     ide_drive_get(hd, MAX_IDE_BUS);
 
     piix4_devfn = piix4_init(pci_bus, 80);
+    isa_bus = NULL;
 
     /* Interrupt controller */
     /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
-    i8259 = i8259_init(env->irq[2]);
+    i8259 = i8259_init(isa_bus, env->irq[2]);
 
-    isa_bus_irqs(i8259);
+    isa_bus_irqs(isa_bus, i8259);
     pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
     usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
-    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_get_irq(9),
-                          NULL, NULL, 0);
+    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
+                          isa_get_irq(NULL, 9), NULL, NULL, 0);
     /* TODO: Populate SPD eeprom data.  */
     smbus_eeprom_init(smbus, 8, NULL, 0);
-    pit = pit_init(0x40, 0);
+    pit = pit_init(isa_bus, 0x40, 0);
     cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
     DMA_init(0, cpu_exit_irq);
 
     /* Super I/O */
-    isa_create_simple("i8042");
+    isa_create_simple(isa_bus, "i8042");
 
-    rtc_init(2000, NULL);
-    serial_isa_init(0, serial_hds[0]);
-    serial_isa_init(1, serial_hds[1]);
+    rtc_init(isa_bus, 2000, NULL);
+    serial_isa_init(isa_bus, 0, serial_hds[0]);
+    serial_isa_init(isa_bus, 1, serial_hds[1]);
     if (parallel_hds[0])
-        parallel_init(0, parallel_hds[0]);
+        parallel_init(isa_bus, 0, parallel_hds[0]);
     for(i = 0; i < MAX_FD; i++) {
         fd[i] = drive_get(IF_FLOPPY, 0, i);
     }
-    fdctrl_init_isa(fd);
+    fdctrl_init_isa(isa_bus, fd);
 
     /* Sound card */
-    audio_init(NULL, pci_bus);
+    audio_init(isa_bus, NULL, pci_bus);
 
     /* Network card */
     network_init();
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index d0564d4..c078078 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -165,6 +165,7 @@ void mips_r4k_init (ram_addr_t ram_size,
     ResetData *reset_info;
     int i;
     qemu_irq *i8259;
+    ISABus *isa_bus;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     DriveInfo *dinfo;
     int be;
@@ -256,36 +257,36 @@ void mips_r4k_init (ram_addr_t ram_size,
     cpu_mips_clock_init(env);
 
     /* The PIC is attached to the MIPS CPU INT0 pin */
-    isa_bus_new(NULL, get_system_io());
-    i8259 = i8259_init(env->irq[2]);
-    isa_bus_irqs(i8259);
+    isa_bus = isa_bus_new(NULL, get_system_io());
+    i8259 = i8259_init(isa_bus, env->irq[2]);
+    isa_bus_irqs(isa_bus, i8259);
 
-    rtc_init(2000, NULL);
+    rtc_init(isa_bus, 2000, NULL);
 
     /* Register 64 KB of ISA IO space at 0x14000000 */
     isa_mmio_init(0x14000000, 0x00010000);
     isa_mem_base = 0x10000000;
 
-    pit = pit_init(0x40, 0);
+    pit = pit_init(isa_bus, 0x40, 0);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
-            serial_isa_init(i, serial_hds[i]);
+            serial_isa_init(isa_bus, i, serial_hds[i]);
         }
     }
 
-    isa_vga_init();
+    isa_vga_init(isa_bus);
 
     if (nd_table[0].vlan)
-        isa_ne2000_init(0x300, 9, &nd_table[0]);
+        isa_ne2000_init(isa_bus, 0x300, 9, &nd_table[0]);
 
     ide_drive_get(hd, MAX_IDE_BUS);
     for(i = 0; i < MAX_IDE_BUS; i++)
-        isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+        isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i],
                      hd[MAX_IDE_DEVS * i],
 		     hd[MAX_IDE_DEVS * i + 1]);
 
-    isa_create_simple("i8042");
+    isa_create_simple(isa_bus, "i8042");
 }
 
 static QEMUMachine mips_machine = {
diff --git a/hw/nvram.h b/hw/nvram.h
index 0f55b24..8924da4 100644
--- a/hw/nvram.h
+++ b/hw/nvram.h
@@ -34,7 +34,8 @@ typedef struct M48t59State M48t59State;
 void m48t59_write (void *private, uint32_t addr, uint32_t val);
 uint32_t m48t59_read (void *private, uint32_t addr);
 void m48t59_toggle_lock (void *private, int lock);
-M48t59State *m48t59_init_isa(uint32_t io_base, uint16_t size, int type);
+M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
+                             int type);
 M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base,
                          uint32_t io_base, uint16_t size, int type);
 void m48t59_set_addr (void *opaque, uint32_t addr);
diff --git a/hw/pc.c b/hw/pc.c
index 03466ec..3a71992 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -849,13 +849,13 @@ static const int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
 static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
 static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 
-void pc_init_ne2k_isa(NICInfo *nd)
+void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd)
 {
     static int nb_ne2k = 0;
 
     if (nb_ne2k == NE2000_NB_MAX)
         return;
-    isa_ne2000_init(ne2000_io[nb_ne2k],
+    isa_ne2000_init(bus, ne2000_io[nb_ne2k],
                     ne2000_irq[nb_ne2k], nd);
     nb_ne2k++;
 }
@@ -1069,7 +1069,7 @@ qemu_irq *pc_allocate_cpu_irq(void)
     return qemu_allocate_irqs(pic_irq_request, NULL, 1);
 }
 
-DeviceState *pc_vga_init(PCIBus *pci_bus)
+DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
 {
     DeviceState *dev = NULL;
 
@@ -1102,7 +1102,7 @@ DeviceState *pc_vga_init(PCIBus *pci_bus)
         if (pci_bus) {
             dev = pci_vga_init(pci_bus);
         } else {
-            dev = isa_vga_init();
+            dev = isa_vga_init(isa_bus);
         }
     }
 
@@ -1118,7 +1118,7 @@ static void cpu_request_exit(void *opaque, int irq, int level)
     }
 }
 
-void pc_basic_device_init(qemu_irq *gsi,
+void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
                           ISADevice **rtc_state,
                           ISADevice **floppy,
                           bool no_vmport)
@@ -1144,31 +1144,31 @@ void pc_basic_device_init(qemu_irq *gsi,
             rtc_irq = qdev_get_gpio_in(hpet, 0);
         }
     }
-    *rtc_state = rtc_init(2000, rtc_irq);
+    *rtc_state = rtc_init(isa_bus, 2000, rtc_irq);
 
     qemu_register_boot_set(pc_boot_set, *rtc_state);
 
-    pit = pit_init(0x40, 0);
+    pit = pit_init(isa_bus, 0x40, 0);
     pcspk_init(pit);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
-            serial_isa_init(i, serial_hds[i]);
+            serial_isa_init(isa_bus, i, serial_hds[i]);
         }
     }
 
     for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
         if (parallel_hds[i]) {
-            parallel_init(i, parallel_hds[i]);
+            parallel_init(isa_bus, i, parallel_hds[i]);
         }
     }
 
     a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2);
-    i8042 = isa_create_simple("i8042");
+    i8042 = isa_create_simple(isa_bus, "i8042");
     i8042_setup_a20_line(i8042, &a20_line[0]);
     if (!no_vmport) {
-        vmport_init();
-        vmmouse = isa_try_create("vmmouse");
+        vmport_init(isa_bus);
+        vmmouse = isa_try_create(isa_bus, "vmmouse");
     } else {
         vmmouse = NULL;
     }
@@ -1176,7 +1176,7 @@ void pc_basic_device_init(qemu_irq *gsi,
         qdev_prop_set_ptr(&vmmouse->qdev, "ps2_mouse", i8042);
         qdev_init_nofail(&vmmouse->qdev);
     }
-    port92 = isa_create_simple("port92");
+    port92 = isa_create_simple(isa_bus, "port92");
     port92_init(port92, &a20_line[1]);
 
     cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
@@ -1185,7 +1185,7 @@ void pc_basic_device_init(qemu_irq *gsi,
     for(i = 0; i < MAX_FD; i++) {
         fd[i] = drive_get(IF_FLOPPY, 0, i);
     }
-    *floppy = fdctrl_init_isa(fd);
+    *floppy = fdctrl_init_isa(isa_bus, fd);
 }
 
 void pc_pci_device_init(PCIBus *pci_bus)
diff --git a/hw/pc.h b/hw/pc.h
index b2000e7..afb7535 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -20,11 +20,12 @@ SerialState *serial_mm_init(MemoryRegion *address_space,
                             target_phys_addr_t base, int it_shift,
                             qemu_irq irq, int baudbase,
                             CharDriverState *chr, enum device_endian);
-static inline bool serial_isa_init(int index, CharDriverState *chr)
+static inline bool serial_isa_init(ISABus *bus, int index,
+                                   CharDriverState *chr)
 {
     ISADevice *dev;
 
-    dev = isa_try_create("isa-serial");
+    dev = isa_try_create(bus, "isa-serial");
     if (!dev) {
         return false;
     }
@@ -39,11 +40,11 @@ static inline bool serial_isa_init(int index, CharDriverState *chr)
 void serial_set_frequency(SerialState *s, uint32_t frequency);
 
 /* parallel.c */
-static inline bool parallel_init(int index, CharDriverState *chr)
+static inline bool parallel_init(ISABus *bus, int index, CharDriverState *chr)
 {
     ISADevice *dev;
 
-    dev = isa_try_create("isa-parallel");
+    dev = isa_try_create(bus, "isa-parallel");
     if (!dev) {
         return false;
     }
@@ -63,7 +64,7 @@ bool parallel_mm_init(MemoryRegion *address_space,
 
 typedef struct PicState PicState;
 extern PicState *isa_pic;
-qemu_irq *i8259_init(qemu_irq parent_irq);
+qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq);
 int pic_read_irq(PicState *s);
 int pic_get_output(PicState *s);
 void pic_info(Monitor *mon);
@@ -84,11 +85,11 @@ void gsi_handler(void *opaque, int n, int level);
 
 #define PIT_FREQ 1193182
 
-static inline ISADevice *pit_init(int base, int irq)
+static inline ISADevice *pit_init(ISABus *bus, int base, int irq)
 {
     ISADevice *dev;
 
-    dev = isa_create("isa-pit");
+    dev = isa_create(bus, "isa-pit");
     qdev_prop_set_uint32(&dev->qdev, "iobase", base);
     qdev_prop_set_uint32(&dev->qdev, "irq", irq);
     qdev_init_nofail(&dev->qdev);
@@ -106,9 +107,9 @@ void hpet_pit_disable(void);
 void hpet_pit_enable(void);
 
 /* vmport.c */
-static inline void vmport_init(void)
+static inline void vmport_init(ISABus *bus)
 {
-    isa_create_simple("vmport");
+    isa_create_simple(bus, "vmport");
 }
 void vmport_register(unsigned char command, IOPortReadFunc *func, void *opaque);
 void vmmouse_get_data(uint32_t *data);
@@ -140,12 +141,12 @@ void pc_memory_init(MemoryRegion *system_memory,
                     MemoryRegion *rom_memory,
                     MemoryRegion **ram_memory);
 qemu_irq *pc_allocate_cpu_irq(void);
-DeviceState *pc_vga_init(PCIBus *pci_bus);
-void pc_basic_device_init(qemu_irq *gsi,
+DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus);
+void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
                           ISADevice **rtc_state,
                           ISADevice **floppy,
                           bool no_vmport);
-void pc_init_ne2k_isa(NICInfo *nd);
+void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd);
 void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
                   const char *boot_device,
                   ISADevice *floppy, BusState *ide0, BusState *ide1,
@@ -175,7 +176,7 @@ extern int no_hpet;
 
 /* pcspk.c */
 void pcspk_init(ISADevice *pit);
-int pcspk_audio_init(qemu_irq *pic);
+int pcspk_audio_init(ISABus *bus, qemu_irq *pic);
 
 /* piix_pci.c */
 struct PCII440FXState;
@@ -205,11 +206,11 @@ enum vga_retrace_method {
 
 extern enum vga_retrace_method vga_retrace_method;
 
-static inline DeviceState *isa_vga_init(void)
+static inline DeviceState *isa_vga_init(ISABus *bus)
 {
     ISADevice *dev;
 
-    dev = isa_try_create("isa-vga");
+    dev = isa_try_create(bus, "isa-vga");
     if (!dev) {
         fprintf(stderr, "Warning: isa-vga not available\n");
         return NULL;
@@ -228,13 +229,13 @@ DeviceState *pci_cirrus_vga_init(PCIBus *bus);
 DeviceState *isa_cirrus_vga_init(MemoryRegion *address_space);
 
 /* ne2000.c */
-static inline bool isa_ne2000_init(int base, int irq, NICInfo *nd)
+static inline bool isa_ne2000_init(ISABus *bus, int base, int irq, NICInfo *nd)
 {
     ISADevice *dev;
 
     qemu_check_nic_model(nd, "ne2k_isa");
 
-    dev = isa_try_create("ne2k_isa");
+    dev = isa_try_create(bus, "ne2k_isa");
     if (!dev) {
         return false;
     }
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index b9bb09d..b4126b5 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -84,6 +84,7 @@ static void pc_init1(MemoryRegion *system_memory,
     int i;
     ram_addr_t below_4g_mem_size, above_4g_mem_size;
     PCIBus *pci_bus;
+    ISABus *isa_bus;
     PCII440FXState *i440fx_state;
     int piix3_devfn = -1;
     qemu_irq *cpu_irq;
@@ -145,17 +146,18 @@ static void pc_init1(MemoryRegion *system_memory,
                                ? 0
                                : ((uint64_t)1 << 62)),
                               pci_memory, ram_memory);
+        isa_bus = NULL;
     } else {
         pci_bus = NULL;
         i440fx_state = NULL;
-        isa_bus_new(NULL, system_io);
+        isa_bus = isa_bus_new(NULL, system_io);
         no_hpet = 1;
     }
-    isa_bus_irqs(gsi);
+    isa_bus_irqs(isa_bus, gsi);
 
     if (!xen_enabled()) {
         cpu_irq = pc_allocate_cpu_irq();
-        i8259 = i8259_init(cpu_irq[0]);
+        i8259 = i8259_init(isa_bus, cpu_irq[0]);
     } else {
         i8259 = xen_interrupt_controller_init();
     }
@@ -169,7 +171,7 @@ static void pc_init1(MemoryRegion *system_memory,
 
     pc_register_ferr_irq(gsi[13]);
 
-    dev = pc_vga_init(pci_enabled? pci_bus: NULL);
+    dev = pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
     if (dev) {
         qdev_property_add_child(qdev_get_root(), "vga", dev, NULL);
     }
@@ -179,13 +181,13 @@ static void pc_init1(MemoryRegion *system_memory,
     }
 
     /* init basic PC hardware */
-    pc_basic_device_init(gsi, &rtc_state, &floppy, xen_enabled());
+    pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled());
 
     for(i = 0; i < nb_nics; i++) {
         NICInfo *nd = &nd_table[i];
 
         if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
-            pc_init_ne2k_isa(nd);
+            pc_init_ne2k_isa(isa_bus, nd);
         else
             pci_nic_init_nofail(nd, "e1000", NULL);
     }
@@ -203,7 +205,8 @@ static void pc_init1(MemoryRegion *system_memory,
     } else {
         for(i = 0; i < MAX_IDE_BUS; i++) {
             ISADevice *dev;
-            dev = isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+            dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
+                               ide_irq[i],
                                hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
             idebus[i] = qdev_get_child_bus(&dev->qdev, "ide.0");
         }
@@ -220,7 +223,7 @@ static void pc_init1(MemoryRegion *system_memory,
     qdev_property_add_child(qdev_resolve_path("/i440fx/piix3", NULL),
                             "rtc", (DeviceState *)rtc_state, NULL);
 
-    audio_init(gsi, pci_enabled ? pci_bus : NULL);
+    audio_init(isa_bus, gsi, pci_enabled ? pci_bus : NULL);
 
     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
                  floppy, idebus[0], idebus[1], rtc_state);
diff --git a/hw/pcspk.c b/hw/pcspk.c
index 7fa2d36..4d949fb 100644
--- a/hw/pcspk.c
+++ b/hw/pcspk.c
@@ -96,7 +96,7 @@ static void pcspk_callback(void *opaque, int free)
     }
 }
 
-int pcspk_audio_init(qemu_irq *pic)
+int pcspk_audio_init(ISABus *bus, qemu_irq *pic)
 {
     PCSpkState *s = &pcspk_state;
     struct audsettings as = {PCSPK_SAMPLE_RATE, 1, AUD_FMT_U8, 0};
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index f22d5b9..a7d73bf 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -523,6 +523,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
     uint32_t kernel_base, initrd_base;
     long kernel_size, initrd_size;
     PCIBus *pci_bus;
+    ISABus *isa_bus;
     qemu_irq *i8259;
     qemu_irq *cpu_exit_irq;
     int ppc_boot_device;
@@ -628,10 +629,10 @@ static void ppc_prep_init (ram_addr_t ram_size,
         hw_error("Only 6xx bus is supported on PREP machine\n");
     }
     /* Hmm, prep has no pci-isa bridge ??? */
-    isa_bus_new(NULL, get_system_io());
-    i8259 = i8259_init(first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
+    isa_bus = isa_bus_new(NULL, get_system_io());
+    i8259 = i8259_init(isa_bus, first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
     pci_bus = pci_prep_init(i8259, get_system_memory(), get_system_io());
-    isa_bus_irqs(i8259);
+    isa_bus_irqs(isa_bus, i8259);
     //    pci_bus = i440fx_init();
     /* Register 8 MB of ISA IO space (needed for non-contiguous map) */
     memory_region_init_io(PPC_io_memory, &PPC_prep_io_ops, sysctrl,
@@ -642,10 +643,10 @@ static void ppc_prep_init (ram_addr_t ram_size,
     pci_vga_init(pci_bus);
     //    openpic = openpic_init(0x00000000, 0xF0000000, 1);
     //    pit = pit_init(0x40, 0);
-    rtc_init(2000, NULL);
+    rtc_init(isa_bus, 2000, NULL);
 
     if (serial_hds[0])
-        serial_isa_init(0, serial_hds[0]);
+        serial_isa_init(isa_bus, 0, serial_hds[0]);
     nb_nics1 = nb_nics;
     if (nb_nics1 > NE2000_NB_MAX)
         nb_nics1 = NE2000_NB_MAX;
@@ -654,7 +655,8 @@ static void ppc_prep_init (ram_addr_t ram_size,
 	    nd_table[i].model = g_strdup("ne2k_isa");
         }
         if (strcmp(nd_table[i].model, "ne2k_isa") == 0) {
-            isa_ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]);
+            isa_ne2000_init(isa_bus, ne2000_io[i], ne2000_irq[i],
+                            &nd_table[i]);
         } else {
             pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
         }
@@ -662,11 +664,11 @@ static void ppc_prep_init (ram_addr_t ram_size,
 
     ide_drive_get(hd, MAX_IDE_BUS);
     for(i = 0; i < MAX_IDE_BUS; i++) {
-        isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+        isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i],
                      hd[2 * i],
 		     hd[2 * i + 1]);
     }
-    isa_create_simple("i8042");
+    isa_create_simple(isa_bus, "i8042");
 
     cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
     DMA_init(1, cpu_exit_irq);
@@ -676,7 +678,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
     for(i = 0; i < MAX_FD; i++) {
         fd[i] = drive_get(IF_FLOPPY, 0, i);
     }
-    fdctrl_init_isa(fd);
+    fdctrl_init_isa(isa_bus, fd);
 
     /* Register speaker port */
     register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
diff --git a/hw/sb16.c b/hw/sb16.c
index f0658ac..88ad8e8 100644
--- a/hw/sb16.c
+++ b/hw/sb16.c
@@ -1385,9 +1385,9 @@ static int sb16_initfn (ISADevice *dev)
     return 0;
 }
 
-int SB16_init (qemu_irq *pic)
+int SB16_init (ISABus *bus, qemu_irq *pic)
 {
-    isa_create_simple ("sb16");
+    isa_create_simple (bus, "sb16");
     return 0;
 }
 
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 97600a9..dfb81da 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -526,14 +526,17 @@ static void dummy_isa_irq_handler(void *opaque, int n, int level)
 }
 
 /* EBUS (Eight bit bus) bridge */
-static void
+static ISABus *
 pci_ebus_init(PCIBus *bus, int devfn)
 {
     qemu_irq *isa_irq;
+    ISABus *isa_bus;
 
     pci_create_simple(bus, devfn, "ebus");
+    isa_bus = NULL;
     isa_irq = qemu_allocate_irqs(dummy_isa_irq_handler, NULL, 16);
-    isa_bus_irqs(isa_irq);
+    isa_bus_irqs(isa_bus, isa_irq);
+    return isa_bus;
 }
 
 static int
@@ -744,6 +747,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
     unsigned int i;
     long initrd_size, kernel_size;
     PCIBus *pci_bus, *pci_bus2, *pci_bus3;
+    ISABus *isa_bus;
     qemu_irq *irq;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     DriveInfo *fd[MAX_FD];
@@ -764,7 +768,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
     pci_vga_init(pci_bus);
 
     // XXX Should be pci_bus3
-    pci_ebus_init(pci_bus, -1);
+    isa_bus = pci_ebus_init(pci_bus, -1);
 
     i = 0;
     if (hwdef->console_serial_base) {
@@ -774,13 +778,13 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
     }
     for(; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
-            serial_isa_init(i, serial_hds[i]);
+            serial_isa_init(isa_bus, i, serial_hds[i]);
         }
     }
 
     for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
         if (parallel_hds[i]) {
-            parallel_init(i, parallel_hds[i]);
+            parallel_init(isa_bus, i, parallel_hds[i]);
         }
     }
 
@@ -791,12 +795,12 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 
     pci_cmd646_ide_init(pci_bus, hd, 1);
 
-    isa_create_simple("i8042");
+    isa_create_simple(isa_bus, "i8042");
     for(i = 0; i < MAX_FD; i++) {
         fd[i] = drive_get(IF_FLOPPY, 0, i);
     }
-    fdctrl_init_isa(fd);
-    nvram = m48t59_init_isa(0x0074, NVRAM_SIZE, 59);
+    fdctrl_init_isa(isa_bus, fd);
+    nvram = m48t59_init_isa(isa_bus, 0x0074, NVRAM_SIZE, 59);
 
     initrd_size = 0;
     kernel_size = sun4u_load_kernel(kernel_filename, initrd_filename,
diff --git a/qemu-common.h b/qemu-common.h
index 44870fe..b2de015 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -217,6 +217,7 @@ typedef struct VLANState VLANState;
 typedef struct VLANClientState VLANClientState;
 typedef struct i2c_bus i2c_bus;
 typedef struct i2c_slave i2c_slave;
+typedef struct ISABus ISABus;
 typedef struct SMBusDevice SMBusDevice;
 typedef struct PCIHostState PCIHostState;
 typedef struct PCIExpressHost PCIExpressHost;
commit 0fa29915cdcadb5853515703d3eca8992627dcf2
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Wed Nov 30 21:35:38 2011 +0100

    net: store guest timestamp in dump file instead of time since guest startup
    
    Stored dates are no more 1970-01-01 (+ run time), but have a real meaning.
    If someone wants to have comparable timestamps accross boots, it is
    possible to start qemu with -rtc to give the startup date.
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/net/dump.c b/net/dump.c
index 8132411..4b48d48 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -30,6 +30,7 @@
 
 typedef struct DumpState {
     VLANClientState nc;
+    int64_t start_ts;
     int fd;
     int pcap_caplen;
 } DumpState;
@@ -70,7 +71,7 @@ static ssize_t dump_receive(VLANClientState *nc, const uint8_t *buf, size_t size
     ts = muldiv64(qemu_get_clock_ns(vm_clock), 1000000, get_ticks_per_sec());
     caplen = size > s->pcap_caplen ? s->pcap_caplen : size;
 
-    hdr.ts.tv_sec = ts / 1000000;
+    hdr.ts.tv_sec = ts / 1000000 + s->start_ts;
     hdr.ts.tv_usec = ts % 1000000;
     hdr.caplen = caplen;
     hdr.len = size;
@@ -104,6 +105,7 @@ static int net_dump_init(VLANState *vlan, const char *device,
     struct pcap_file_hdr hdr;
     VLANClientState *nc;
     DumpState *s;
+    struct tm tm;
     int fd;
 
     fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0644);
@@ -136,6 +138,9 @@ static int net_dump_init(VLANState *vlan, const char *device,
     s->fd = fd;
     s->pcap_caplen = len;
 
+    qemu_get_timedate(&tm, 0);
+    s->start_ts = mktime(&tm);
+
     return 0;
 }
 
commit 6514ed528cd6cf752927b4eb38e64bba84c321ff
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Wed Nov 30 21:35:37 2011 +0100

    net: truncate output file when using dump backend
    
    This prevents data of a previous run to be seen in the new dump file.
    
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/net/dump.c b/net/dump.c
index 0d0cbb2..8132411 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -106,7 +106,7 @@ static int net_dump_init(VLANState *vlan, const char *device,
     DumpState *s;
     int fd;
 
-    fd = open(filename, O_CREAT | O_WRONLY | O_BINARY, 0644);
+    fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0644);
     if (fd < 0) {
         error_report("-net dump: can't open %s", filename);
         return -1;
commit bc7c9eccfeb620b0e87b2d0d079d9434c6bef03d
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Dec 20 14:10:36 2011 +0100

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

diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 43c85aa..e188c7a 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -81,7 +81,6 @@ struct PCII440FXState {
     PAMMemoryRegion pam_regions[13];
     MemoryRegion smram_region;
     uint8_t smm_enabled;
-    PIIX3State *piix3;
 };
 
 
@@ -320,8 +319,6 @@ static PCIBus *i440fx_common_init(const char *device_name,
     qdev_property_add_child(dev, "piix3", &piix3->dev.qdev, NULL);
     piix3->pic = pic;
 
-    (*pi440fx_state)->piix3 = piix3;
-
     *piix3_devfn = piix3->dev.devfn;
 
     ram_size = ram_size / 8 / 1024 / 1024;
commit e34911c420c617151fe5bc95a4b6f269cca0483b
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Dec 19 12:06:23 2011 +0200

    memory: temporarily add memory_region_get_ram_addr()
    
    This is a layering violation, but needed while the code contains
    naked calls to qemu_get_ram_ptr() and the like.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/memory.c b/memory.c
index 9e3f87a..6a637d4 100644
--- a/memory.c
+++ b/memory.c
@@ -1435,6 +1435,12 @@ void memory_region_set_alias_offset(MemoryRegion *mr, target_phys_addr_t offset)
     memory_region_update_topology(mr);
 }
 
+ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
+{
+    assert(mr->backend_registered);
+    return mr->ram_addr;
+}
+
 static int cmp_flatrange_addr(const void *addr_, const void *fr_)
 {
     const AddrRange *addr = addr_;
diff --git a/memory.h b/memory.h
index 5ba874e..a82226a 100644
--- a/memory.h
+++ b/memory.h
@@ -558,6 +558,16 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr,
                                          target_phys_addr_t offset,
                                          MemoryRegion *subregion,
                                          unsigned priority);
+
+/**
+ * memory_region_get_ram_addr: Get the ram address associated with a memory
+ *                             region
+ *
+ * DO NOT USE THIS FUCNTION.  This is a temporary workaround while the Xen
+ * code is being reworked.
+ */
+ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr);
+
 /**
  * memory_region_del_subregion: Remove a subregion.
  *
commit c65adf9bcdc9c3212d62696f1b52c8ce0f98dd7f
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Dec 18 16:40:50 2011 +0200

    xen, vga: add API for registering the framebuffer
    
    Xen currently uses the name of a memory region to determine whether it
    is the framebuffer.  Replace with an explicit API.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/vga.c b/hw/vga.c
index ca79aa1..7e1dd5a 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -28,6 +28,7 @@
 #include "vga_int.h"
 #include "pixel_ops.h"
 #include "qemu-timer.h"
+#include "xen.h"
 
 //#define DEBUG_VGA
 //#define DEBUG_VGA_MEM
@@ -2222,6 +2223,7 @@ void vga_common_init(VGACommonState *s, int vga_ram_size)
     s->is_vbe_vmstate = 0;
 #endif
     memory_region_init_ram(&s->vram, NULL, "vga.vram", vga_ram_size);
+    xen_register_framebuffer(&s->vram);
     s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
     s->vram_size = vga_ram_size;
     s->get_bpp = vga_get_bpp;
diff --git a/hw/xen.h b/hw/xen.h
index f9f66e8..b46879c 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -49,6 +49,9 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size,
                    struct MemoryRegion *mr);
 #endif
 
+struct MemoryRegion;
+void xen_register_framebuffer(struct MemoryRegion *mr);
+
 #if defined(CONFIG_XEN) && CONFIG_XEN_CTRL_INTERFACE_VERSION < 400
 #  define HVM_MAX_VCPUS 32
 #endif
diff --git a/xen-all.c b/xen-all.c
index bd89889..51315ce 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -33,6 +33,7 @@
 #endif
 
 static MemoryRegion ram_memory, ram_640k, ram_lo, ram_hi;
+static MemoryRegion *framebuffer;
 
 /* Compatibility with older version */
 #if __XEN_LATEST_INTERFACE_VERSION__ < 0x0003020a
@@ -982,3 +983,8 @@ void destroy_hvm_domain(void)
         xc_interface_close(xc_handle);
     }
 }
+
+void xen_register_framebuffer(MemoryRegion *mr)
+{
+    framebuffer = mr;
+}
diff --git a/xen-stub.c b/xen-stub.c
index 5fa400f..d403d86 100644
--- a/xen-stub.c
+++ b/xen-stub.c
@@ -44,3 +44,7 @@ int xen_init(void)
 {
     return -ENOSYS;
 }
+
+void xen_register_framebuffer(MemoryRegion *mr)
+{
+}
commit 04097f7c5957273c578f72b9bd603ba6b1d69e33
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Dec 18 14:06:05 2011 +0200

    vhost: convert to MemoryListener API
    
    Drop the use of cpu_register_phys_memory_client() in favour of the new
    MemoryListener API.  The new API simplifies the caller, since there is no
    need to deal with splitting and merging slots; however this is not exploited
    in this patch.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/vhost.c b/hw/vhost.c
index 0870cb7..a1c5e4c 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -57,12 +57,12 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
     }
 }
 
-static int vhost_client_sync_dirty_bitmap(CPUPhysMemoryClient *client,
-                                          target_phys_addr_t start_addr,
-                                          target_phys_addr_t end_addr)
+static int vhost_sync_dirty_bitmap(struct vhost_dev *dev,
+                                   target_phys_addr_t start_addr,
+                                   target_phys_addr_t end_addr)
 {
-    struct vhost_dev *dev = container_of(client, struct vhost_dev, client);
     int i;
+
     if (!dev->log_enabled || !dev->started) {
         return 0;
     }
@@ -81,6 +81,17 @@ static int vhost_client_sync_dirty_bitmap(CPUPhysMemoryClient *client,
     return 0;
 }
 
+static void vhost_log_sync(MemoryListener *listener,
+                          MemoryRegionSection *section)
+{
+    struct vhost_dev *dev = container_of(listener, struct vhost_dev,
+                                         memory_listener);
+    target_phys_addr_t start_addr = section->offset_within_address_space;
+    target_phys_addr_t end_addr = start_addr + section->size;
+
+    vhost_sync_dirty_bitmap(dev, start_addr, end_addr);
+}
+
 /* Assign/unassign. Keep an unsorted array of non-overlapping
  * memory regions in dev->mem. */
 static void vhost_dev_unassign_memory(struct vhost_dev *dev,
@@ -259,8 +270,7 @@ static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size)
     log_base = (uint64_t)(unsigned long)log;
     r = ioctl(dev->control, VHOST_SET_LOG_BASE, &log_base);
     assert(r >= 0);
-    vhost_client_sync_dirty_bitmap(&dev->client, 0,
-                                   (target_phys_addr_t)~0x0ull);
+    vhost_sync_dirty_bitmap(dev, 0, (target_phys_addr_t)~0x0ull);
     if (dev->log) {
         g_free(dev->log);
     }
@@ -335,31 +345,37 @@ static bool vhost_dev_cmp_memory(struct vhost_dev *dev,
     return uaddr != reg->userspace_addr + start_addr - reg->guest_phys_addr;
 }
 
-static void vhost_client_set_memory(CPUPhysMemoryClient *client,
-                                    target_phys_addr_t start_addr,
-                                    ram_addr_t size,
-                                    ram_addr_t phys_offset,
-                                    bool log_dirty)
+static void vhost_set_memory(MemoryListener *listener,
+                             MemoryRegionSection *section,
+                             bool add)
 {
-    struct vhost_dev *dev = container_of(client, struct vhost_dev, client);
-    ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
+    struct vhost_dev *dev = container_of(listener, struct vhost_dev,
+                                         memory_listener);
+    target_phys_addr_t start_addr = section->offset_within_address_space;
+    ram_addr_t size = section->size;
+    bool log_dirty = memory_region_is_logging(section->mr);
     int s = offsetof(struct vhost_memory, regions) +
         (dev->mem->nregions + 1) * sizeof dev->mem->regions[0];
     uint64_t log_size;
     int r;
+    void *ram;
+
+    if (!memory_region_is_ram(section->mr)) {
+        return;
+    }
 
     dev->mem = g_realloc(dev->mem, s);
 
     if (log_dirty) {
-        flags = IO_MEM_UNASSIGNED;
+        add = false;
     }
 
     assert(size);
 
     /* Optimize no-change case. At least cirrus_vga does this a lot at this time. */
-    if (flags == IO_MEM_RAM) {
-        if (!vhost_dev_cmp_memory(dev, start_addr, size,
-                                  (uintptr_t)qemu_get_ram_ptr(phys_offset))) {
+    ram = memory_region_get_ram_ptr(section->mr);
+    if (add) {
+        if (!vhost_dev_cmp_memory(dev, start_addr, size, (uintptr_t)ram)) {
             /* Region exists with same address. Nothing to do. */
             return;
         }
@@ -371,10 +387,9 @@ static void vhost_client_set_memory(CPUPhysMemoryClient *client,
     }
 
     vhost_dev_unassign_memory(dev, start_addr, size);
-    if (flags == IO_MEM_RAM) {
+    if (add) {
         /* Add given mapping, merging adjacent regions if any */
-        vhost_dev_assign_memory(dev, start_addr, size,
-                                (uintptr_t)qemu_get_ram_ptr(phys_offset));
+        vhost_dev_assign_memory(dev, start_addr, size, (uintptr_t)ram);
     } else {
         /* Remove old mapping for this memory, if any. */
         vhost_dev_unassign_memory(dev, start_addr, size);
@@ -410,6 +425,18 @@ static void vhost_client_set_memory(CPUPhysMemoryClient *client,
     }
 }
 
+static void vhost_region_add(MemoryListener *listener,
+                             MemoryRegionSection *section)
+{
+    vhost_set_memory(listener, section, true);
+}
+
+static void vhost_region_del(MemoryListener *listener,
+                             MemoryRegionSection *section)
+{
+    vhost_set_memory(listener, section, false);
+}
+
 static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
                                     struct vhost_virtqueue *vq,
                                     unsigned idx, bool enable_log)
@@ -467,10 +494,10 @@ err_features:
     return r;
 }
 
-static int vhost_client_migration_log(CPUPhysMemoryClient *client,
-                                      int enable)
+static int vhost_migration_log(MemoryListener *listener, int enable)
 {
-    struct vhost_dev *dev = container_of(client, struct vhost_dev, client);
+    struct vhost_dev *dev = container_of(listener, struct vhost_dev,
+                                         memory_listener);
     int r;
     if (!!enable == dev->log_enabled) {
         return 0;
@@ -500,6 +527,38 @@ static int vhost_client_migration_log(CPUPhysMemoryClient *client,
     return 0;
 }
 
+static void vhost_log_global_start(MemoryListener *listener)
+{
+    int r;
+
+    r = vhost_migration_log(listener, true);
+    if (r < 0) {
+        abort();
+    }
+}
+
+static void vhost_log_global_stop(MemoryListener *listener)
+{
+    int r;
+
+    r = vhost_migration_log(listener, false);
+    if (r < 0) {
+        abort();
+    }
+}
+
+static void vhost_log_start(MemoryListener *listener,
+                            MemoryRegionSection *section)
+{
+    /* FIXME: implement */
+}
+
+static void vhost_log_stop(MemoryListener *listener,
+                           MemoryRegionSection *section)
+{
+    /* FIXME: implement */
+}
+
 static int vhost_virtqueue_init(struct vhost_dev *dev,
                                 struct VirtIODevice *vdev,
                                 struct vhost_virtqueue *vq,
@@ -645,17 +704,21 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
     }
     hdev->features = features;
 
-    hdev->client.set_memory = vhost_client_set_memory;
-    hdev->client.sync_dirty_bitmap = vhost_client_sync_dirty_bitmap;
-    hdev->client.migration_log = vhost_client_migration_log;
-    hdev->client.log_start = NULL;
-    hdev->client.log_stop = NULL;
+    hdev->memory_listener = (MemoryListener) {
+        .region_add = vhost_region_add,
+        .region_del = vhost_region_del,
+        .log_start = vhost_log_start,
+        .log_stop = vhost_log_stop,
+        .log_sync = vhost_log_sync,
+        .log_global_start = vhost_log_global_start,
+        .log_global_stop = vhost_log_global_stop,
+    };
     hdev->mem = g_malloc0(offsetof(struct vhost_memory, regions));
     hdev->log = NULL;
     hdev->log_size = 0;
     hdev->log_enabled = false;
     hdev->started = false;
-    cpu_register_phys_memory_client(&hdev->client);
+    memory_listener_register(&hdev->memory_listener);
     hdev->force = force;
     return 0;
 fail:
@@ -666,7 +729,7 @@ fail:
 
 void vhost_dev_cleanup(struct vhost_dev *hdev)
 {
-    cpu_unregister_phys_memory_client(&hdev->client);
+    memory_listener_unregister(&hdev->memory_listener);
     g_free(hdev->mem);
     close(hdev->control);
 }
@@ -808,8 +871,7 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
                                 hdev->vqs + i,
                                 i);
     }
-    vhost_client_sync_dirty_bitmap(&hdev->client, 0,
-                                   (target_phys_addr_t)~0x0ull);
+    vhost_sync_dirty_bitmap(hdev, 0, (target_phys_addr_t)~0x0ull);
     r = vdev->binding->set_guest_notifiers(vdev->binding_opaque, false);
     if (r < 0) {
         fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r);
diff --git a/hw/vhost.h b/hw/vhost.h
index c9452f0..d1824ec 100644
--- a/hw/vhost.h
+++ b/hw/vhost.h
@@ -3,6 +3,7 @@
 
 #include "hw/hw.h"
 #include "hw/virtio.h"
+#include "memory.h"
 
 /* Generic structures common for any vhost based device. */
 struct vhost_virtqueue {
@@ -26,7 +27,7 @@ typedef unsigned long vhost_log_chunk_t;
 
 struct vhost_memory;
 struct vhost_dev {
-    CPUPhysMemoryClient client;
+    MemoryListener memory_listener;
     int control;
     struct vhost_memory *mem;
     struct vhost_virtqueue *vqs;
commit a01672d3968cf91208666d371784110bfde9d4f8
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Dec 18 14:06:05 2011 +0200

    kvm: convert to MemoryListener API
    
    Drop the use of cpu_register_phys_memory_client() in favour of the new
    MemoryListener API.  The new API simplifies the caller, since there is no
    need to deal with splitting and merging slots; however this is not exploited
    in this patch.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 8d8f31e..e3e4181 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -27,6 +27,7 @@
 #include "gdbstub.h"
 #include "kvm.h"
 #include "bswap.h"
+#include "memory.h"
 
 /* This check must be after config-host.h is included */
 #ifdef CONFIG_EVENTFD
@@ -289,16 +290,28 @@ static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr,
     return kvm_slot_dirty_pages_log_change(mem, log_dirty);
 }
 
-static int kvm_log_start(CPUPhysMemoryClient *client,
-                         target_phys_addr_t phys_addr, ram_addr_t size)
+static void kvm_log_start(MemoryListener *listener,
+                          MemoryRegionSection *section)
 {
-    return kvm_dirty_pages_log_change(phys_addr, size, true);
+    int r;
+
+    r = kvm_dirty_pages_log_change(section->offset_within_address_space,
+                                   section->size, true);
+    if (r < 0) {
+        abort();
+    }
 }
 
-static int kvm_log_stop(CPUPhysMemoryClient *client,
-                        target_phys_addr_t phys_addr, ram_addr_t size)
+static void kvm_log_stop(MemoryListener *listener,
+                          MemoryRegionSection *section)
 {
-    return kvm_dirty_pages_log_change(phys_addr, size, false);
+    int r;
+
+    r = kvm_dirty_pages_log_change(section->offset_within_address_space,
+                                   section->size, false);
+    if (r < 0) {
+        abort();
+    }
 }
 
 static int kvm_set_migration_log(int enable)
@@ -519,13 +532,15 @@ kvm_check_extension_list(KVMState *s, const KVMCapabilityInfo *list)
     return NULL;
 }
 
-static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
-                             ram_addr_t phys_offset, bool log_dirty)
+static void kvm_set_phys_mem(MemoryRegionSection *section, bool add)
 {
     KVMState *s = kvm_state;
-    ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
     KVMSlot *mem, old;
     int err;
+    MemoryRegion *mr = section->mr;
+    bool log_dirty = memory_region_is_logging(mr);
+    target_phys_addr_t start_addr = section->offset_within_address_space;
+    ram_addr_t size = section->size;
     void *ram = NULL;
 
     /* kvm works in page size chunks, but the function may be called
@@ -533,20 +548,19 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
     size = TARGET_PAGE_ALIGN(size);
     start_addr = TARGET_PAGE_ALIGN(start_addr);
 
-    /* KVM does not support read-only slots */
-    phys_offset &= ~IO_MEM_ROM;
-
-    if ((phys_offset & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
-        ram = qemu_safe_ram_ptr(phys_offset);
+    if (!memory_region_is_ram(mr)) {
+        return;
     }
 
+    ram = memory_region_get_ram_ptr(mr) + section->offset_within_region;
+
     while (1) {
         mem = kvm_lookup_overlapping_slot(s, start_addr, start_addr + size);
         if (!mem) {
             break;
         }
 
-        if (flags < IO_MEM_UNASSIGNED && start_addr >= mem->start_addr &&
+        if (add && start_addr >= mem->start_addr &&
             (start_addr + size <= mem->start_addr + mem->memory_size) &&
             (ram - start_addr == mem->ram - mem->start_addr)) {
             /* The new slot fits into the existing one and comes with
@@ -575,8 +589,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
          * slot comes around later, we will fail (not seen in practice so far)
          * - and actually require a recent KVM version. */
         if (s->broken_set_mem_region &&
-            old.start_addr == start_addr && old.memory_size < size &&
-            flags < IO_MEM_UNASSIGNED) {
+            old.start_addr == start_addr && old.memory_size < size && add) {
             mem = kvm_alloc_slot(s);
             mem->memory_size = old.memory_size;
             mem->start_addr = old.start_addr;
@@ -591,7 +604,6 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
             }
 
             start_addr += old.memory_size;
-            phys_offset += old.memory_size;
             ram += old.memory_size;
             size -= old.memory_size;
             continue;
@@ -642,8 +654,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
     if (!size) {
         return;
     }
-    /* KVM does not need to know about this memory */
-    if (flags >= IO_MEM_UNASSIGNED) {
+    if (!add) {
         return;
     }
     mem = kvm_alloc_slot(s);
@@ -660,33 +671,55 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
     }
 }
 
-static void kvm_client_set_memory(struct CPUPhysMemoryClient *client,
-                                  target_phys_addr_t start_addr,
-                                  ram_addr_t size, ram_addr_t phys_offset,
-                                  bool log_dirty)
+static void kvm_region_add(MemoryListener *listener,
+                           MemoryRegionSection *section)
+{
+    kvm_set_phys_mem(section, true);
+}
+
+static void kvm_region_del(MemoryListener *listener,
+                           MemoryRegionSection *section)
 {
-    kvm_set_phys_mem(start_addr, size, phys_offset, log_dirty);
+    kvm_set_phys_mem(section, false);
+}
+
+static void kvm_log_sync(MemoryListener *listener,
+                         MemoryRegionSection *section)
+{
+    target_phys_addr_t start = section->offset_within_address_space;
+    target_phys_addr_t end = start + section->size;
+    int r;
+
+    r = kvm_physical_sync_dirty_bitmap(start, end);
+    if (r < 0) {
+        abort();
+    }
 }
 
-static int kvm_client_sync_dirty_bitmap(struct CPUPhysMemoryClient *client,
-                                        target_phys_addr_t start_addr,
-                                        target_phys_addr_t end_addr)
+static void kvm_log_global_start(struct MemoryListener *listener)
 {
-    return kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
+    int r;
+
+    r = kvm_set_migration_log(1);
+    assert(r >= 0);
 }
 
-static int kvm_client_migration_log(struct CPUPhysMemoryClient *client,
-                                    int enable)
+static void kvm_log_global_stop(struct MemoryListener *listener)
 {
-    return kvm_set_migration_log(enable);
+    int r;
+
+    r = kvm_set_migration_log(0);
+    assert(r >= 0);
 }
 
-static CPUPhysMemoryClient kvm_cpu_phys_memory_client = {
-    .set_memory = kvm_client_set_memory,
-    .sync_dirty_bitmap = kvm_client_sync_dirty_bitmap,
-    .migration_log = kvm_client_migration_log,
+static MemoryListener kvm_memory_listener = {
+    .region_add = kvm_region_add,
+    .region_del = kvm_region_del,
     .log_start = kvm_log_start,
     .log_stop = kvm_log_stop,
+    .log_sync = kvm_log_sync,
+    .log_global_start = kvm_log_global_start,
+    .log_global_stop = kvm_log_global_stop,
 };
 
 static void kvm_handle_interrupt(CPUState *env, int mask)
@@ -794,7 +827,7 @@ int kvm_init(void)
     }
 
     kvm_state = s;
-    cpu_register_phys_memory_client(&kvm_cpu_phys_memory_client);
+    memory_listener_register(&kvm_memory_listener);
 
     s->many_ioeventfds = kvm_check_many_ioeventfds();
 
commit 9f213ed92c5ccc3d0aa19359bb1783760d01dae9
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Dec 15 19:55:26 2011 +0200

    kvm: switch kvm slots to use host virtual address instead of ram_addr_t
    
    This simplifies a later switch to the memory API in slot management.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index ac048bc..8d8f31e 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -50,7 +50,7 @@ typedef struct KVMSlot
 {
     target_phys_addr_t start_addr;
     ram_addr_t memory_size;
-    ram_addr_t phys_offset;
+    void *ram;
     int slot;
     int flags;
 } KVMSlot;
@@ -146,17 +146,16 @@ static KVMSlot *kvm_lookup_overlapping_slot(KVMState *s,
     return found;
 }
 
-int kvm_physical_memory_addr_from_ram(KVMState *s, ram_addr_t ram_addr,
-                                      target_phys_addr_t *phys_addr)
+int kvm_physical_memory_addr_from_host(KVMState *s, void *ram,
+                                       target_phys_addr_t *phys_addr)
 {
     int i;
 
     for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
         KVMSlot *mem = &s->slots[i];
 
-        if (ram_addr >= mem->phys_offset &&
-            ram_addr < mem->phys_offset + mem->memory_size) {
-            *phys_addr = mem->start_addr + (ram_addr - mem->phys_offset);
+        if (ram >= mem->ram && ram < mem->ram + mem->memory_size) {
+            *phys_addr = mem->start_addr + (ram - mem->ram);
             return 1;
         }
     }
@@ -171,7 +170,7 @@ static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot)
     mem.slot = slot->slot;
     mem.guest_phys_addr = slot->start_addr;
     mem.memory_size = slot->memory_size;
-    mem.userspace_addr = (unsigned long)qemu_safe_ram_ptr(slot->phys_offset);
+    mem.userspace_addr = (unsigned long)slot->ram;
     mem.flags = slot->flags;
     if (s->migration_log) {
         mem.flags |= KVM_MEM_LOG_DIRTY_PAGES;
@@ -527,6 +526,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
     ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
     KVMSlot *mem, old;
     int err;
+    void *ram = NULL;
 
     /* kvm works in page size chunks, but the function may be called
        with sub-page size and unaligned start address. */
@@ -536,6 +536,10 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
     /* KVM does not support read-only slots */
     phys_offset &= ~IO_MEM_ROM;
 
+    if ((phys_offset & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
+        ram = qemu_safe_ram_ptr(phys_offset);
+    }
+
     while (1) {
         mem = kvm_lookup_overlapping_slot(s, start_addr, start_addr + size);
         if (!mem) {
@@ -544,7 +548,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
 
         if (flags < IO_MEM_UNASSIGNED && start_addr >= mem->start_addr &&
             (start_addr + size <= mem->start_addr + mem->memory_size) &&
-            (phys_offset - start_addr == mem->phys_offset - mem->start_addr)) {
+            (ram - start_addr == mem->ram - mem->start_addr)) {
             /* The new slot fits into the existing one and comes with
              * identical parameters - update flags and done. */
             kvm_slot_dirty_pages_log_change(mem, log_dirty);
@@ -576,7 +580,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
             mem = kvm_alloc_slot(s);
             mem->memory_size = old.memory_size;
             mem->start_addr = old.start_addr;
-            mem->phys_offset = old.phys_offset;
+            mem->ram = old.ram;
             mem->flags = kvm_mem_flags(s, log_dirty);
 
             err = kvm_set_user_memory_region(s, mem);
@@ -588,6 +592,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
 
             start_addr += old.memory_size;
             phys_offset += old.memory_size;
+            ram += old.memory_size;
             size -= old.memory_size;
             continue;
         }
@@ -597,7 +602,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
             mem = kvm_alloc_slot(s);
             mem->memory_size = start_addr - old.start_addr;
             mem->start_addr = old.start_addr;
-            mem->phys_offset = old.phys_offset;
+            mem->ram = old.ram;
             mem->flags =  kvm_mem_flags(s, log_dirty);
 
             err = kvm_set_user_memory_region(s, mem);
@@ -621,7 +626,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
             mem->start_addr = start_addr + size;
             size_delta = mem->start_addr - old.start_addr;
             mem->memory_size = old.memory_size - size_delta;
-            mem->phys_offset = old.phys_offset + size_delta;
+            mem->ram = old.ram + size_delta;
             mem->flags = kvm_mem_flags(s, log_dirty);
 
             err = kvm_set_user_memory_region(s, mem);
@@ -644,7 +649,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
     mem = kvm_alloc_slot(s);
     mem->memory_size = size;
     mem->start_addr = start_addr;
-    mem->phys_offset = phys_offset;
+    mem->ram = ram;
     mem->flags = kvm_mem_flags(s, log_dirty);
 
     err = kvm_set_user_memory_region(s, mem);
diff --git a/kvm.h b/kvm.h
index 243b063..c1de81a 100644
--- a/kvm.h
+++ b/kvm.h
@@ -188,8 +188,8 @@ static inline void cpu_synchronize_post_init(CPUState *env)
 
 
 #if !defined(CONFIG_USER_ONLY)
-int kvm_physical_memory_addr_from_ram(KVMState *s, ram_addr_t ram_addr,
-                                      target_phys_addr_t *phys_addr);
+int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
+                                       target_phys_addr_t *phys_addr);
 #endif
 
 #endif
diff --git a/memory.c b/memory.c
index 61e324b..9e3f87a 100644
--- a/memory.c
+++ b/memory.c
@@ -769,11 +769,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(frold, as, log_stop);
+                    MEMORY_LISTENER_UPDATE_REGION(frnew, as, 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(frold, as, log_start);
+                    MEMORY_LISTENER_UPDATE_REGION(frnew, as, log_start);
                 }
             }
 
@@ -784,7 +784,7 @@ static void address_space_update_topology_pass(AddressSpace *as,
 
             if (adding) {
                 as->ops->range_add(as, frnew);
-                MEMORY_LISTENER_UPDATE_REGION(frold, as, region_add);
+                MEMORY_LISTENER_UPDATE_REGION(frnew, as, region_add);
             }
 
             ++inew;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 5bfc21f..74d81ef 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -253,8 +253,7 @@ int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
     if ((env->mcg_cap & MCG_SER_P) && addr
         && (code == BUS_MCEERR_AR || code == BUS_MCEERR_AO)) {
         if (qemu_ram_addr_from_host(addr, &ram_addr) ||
-            !kvm_physical_memory_addr_from_ram(env->kvm_state, ram_addr,
-                                               &paddr)) {
+            !kvm_physical_memory_addr_from_host(env->kvm_state, addr, &paddr)) {
             fprintf(stderr, "Hardware memory error for memory used by "
                     "QEMU itself instead of guest system!\n");
             /* Hope we are lucky for AO MCE */
@@ -286,8 +285,8 @@ int kvm_arch_on_sigbus(int code, void *addr)
 
         /* Hope we are lucky for AO MCE */
         if (qemu_ram_addr_from_host(addr, &ram_addr) ||
-            !kvm_physical_memory_addr_from_ram(first_cpu->kvm_state, ram_addr,
-                                               &paddr)) {
+            !kvm_physical_memory_addr_from_host(first_cpu->kvm_state, addr,
+                                                &paddr)) {
             fprintf(stderr, "Hardware memory error for memory used by "
                     "QEMU itself instead of guest system!: %p\n", addr);
             return 0;
commit 7664e80c84700d8b7e88ae854d1d74806c63f013
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Dec 11 14:47:25 2011 +0200

    memory: add API for observing updates to the physical memory map
    
    Add an API that allows a client to observe changes in the global
    memory map:
     - region added (possibly with logging enabled)
     - region removed (possibly with logging enabled)
     - logging started on a region
     - logging stopped on a region
     - global logging started
     - global logging removed
    
    This API will eventually replace cpu_register_physical_memory_client().
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index 32782b4..36b61c9 100644
--- a/exec.c
+++ b/exec.c
@@ -1762,6 +1762,11 @@ static int cpu_notify_sync_dirty_bitmap(target_phys_addr_t start,
 static int cpu_notify_migration_log(int enable)
 {
     CPUPhysMemoryClient *client;
+    if (enable) {
+        memory_global_dirty_log_start();
+    } else {
+        memory_global_dirty_log_stop();
+    }
     QLIST_FOREACH(client, &memory_client_list, list) {
         int r = client->migration_log(client, enable);
         if (r < 0)
diff --git a/memory.c b/memory.c
index ef5d647..61e324b 100644
--- a/memory.c
+++ b/memory.c
@@ -23,6 +23,10 @@
 
 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);
 
 typedef struct AddrRange AddrRange;
 
@@ -697,6 +701,32 @@ 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))
+
 static void address_space_update_topology_pass(AddressSpace *as,
                                                FlatView old_view,
                                                FlatView new_view,
@@ -729,6 +759,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);
                 as->ops->range_del(as, frold);
             }
 
@@ -738,9 +769,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(frold, as, 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(frold, as, log_start);
                 }
             }
 
@@ -751,6 +784,7 @@ static void address_space_update_topology_pass(AddressSpace *as,
 
             if (adding) {
                 as->ops->range_add(as, frnew);
+                MEMORY_LISTENER_UPDATE_REGION(frold, as, region_add);
             }
 
             ++inew;
@@ -1130,6 +1164,7 @@ 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);
             cpu_physical_sync_dirty_bitmap(int128_get64(fr->addr.start),
                                            int128_get64(addrrange_end(fr->addr)));
         }
@@ -1449,7 +1484,65 @@ MemoryRegionSection memory_region_find(MemoryRegion *address_space,
 
 void memory_global_sync_dirty_bitmap(MemoryRegion *address_space)
 {
+    AddressSpace *as = memory_region_to_address_space(address_space);
+    FlatRange *fr;
+
     cpu_physical_sync_dirty_bitmap(0, TARGET_PHYS_ADDR_MAX);
+    FOR_EACH_FLAT_RANGE(fr, &as->current_map) {
+        MEMORY_LISTENER_UPDATE_REGION(fr, as, log_sync);
+    }
+}
+
+void memory_global_dirty_log_start(void)
+{
+    MemoryListener *listener;
+
+    global_dirty_log = true;
+    QLIST_FOREACH(listener, &memory_listeners, link) {
+        listener->log_global_start(listener);
+    }
+}
+
+void memory_global_dirty_log_stop(void)
+{
+    MemoryListener *listener;
+
+    global_dirty_log = false;
+    QLIST_FOREACH(listener, &memory_listeners, link) {
+        listener->log_global_stop(listener);
+    }
+}
+
+static void listener_add_address_space(MemoryListener *listener,
+                                       AddressSpace *as)
+{
+    FlatRange *fr;
+
+    if (global_dirty_log) {
+        listener->log_global_start(listener);
+    }
+    FOR_EACH_FLAT_RANGE(fr, &as->current_map) {
+        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),
+        };
+        listener->region_add(listener, &section);
+    }
+}
+
+void memory_listener_register(MemoryListener *listener)
+{
+    QLIST_INSERT_HEAD(&memory_listeners, 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);
 }
 
 void set_system_memory_map(MemoryRegion *mr)
diff --git a/memory.h b/memory.h
index 8197b45..5ba874e 100644
--- a/memory.h
+++ b/memory.h
@@ -154,6 +154,7 @@ typedef struct MemoryRegionSection MemoryRegionSection;
  * MemoryRegionSection: describes a fragment of a #MemoryRegion
  *
  * @mr: the region, or %NULL if empty
+ * @address_space: the address space the region is mapped in
  * @offset_within_region: the beginning of the section, relative to @mr's start
  * @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
@@ -161,11 +162,31 @@ typedef struct MemoryRegionSection MemoryRegionSection;
  */
 struct MemoryRegionSection {
     MemoryRegion *mr;
+    MemoryRegion *address_space;
     target_phys_addr_t offset_within_region;
     uint64_t size;
     target_phys_addr_t offset_within_address_space;
 };
 
+typedef struct MemoryListener MemoryListener;
+
+/**
+ * MemoryListener: callbacks structure for updates to the physical memory map
+ *
+ * Allows a component to adjust to changes in the guest-visible memory map.
+ * Use with memory_listener_register() and memory_listener_unregister().
+ */
+struct MemoryListener {
+    void (*region_add)(MemoryListener *listener, MemoryRegionSection *section);
+    void (*region_del)(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);
+    void (*log_global_start)(MemoryListener *listener);
+    void (*log_global_stop)(MemoryListener *listener);
+    QLIST_ENTRY(MemoryListener) link;
+};
+
 /**
  * memory_region_init: Initialize a memory region
  *
@@ -631,6 +652,32 @@ void memory_region_transaction_begin(void);
  */
 void memory_region_transaction_commit(void);
 
+/**
+ * memory_listener_register: register callbacks to be called when memory
+ *                           sections are mapped or unmapped into an address
+ *                           space
+ *
+ * @listener: an object containing the callbacks to be called
+ */
+void memory_listener_register(MemoryListener *listener);
+
+/**
+ * memory_listener_unregister: undo the effect of memory_listener_register()
+ *
+ * @listener: an object containing the callbacks to be removed
+ */
+void memory_listener_unregister(MemoryListener *listener);
+
+/**
+ * memory_global_dirty_log_start: begin dirty logging for all regions
+ */
+void memory_global_dirty_log_start(void);
+
+/**
+ * memory_global_dirty_log_stop: begin dirty logging for all regions
+ */
+void memory_global_dirty_log_stop(void);
+
 void mtree_info(fprintf_function mon_printf, void *f);
 
 #endif
commit 86e775c654b775d3e295e8a33bb03cc03bdab68d
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Dec 15 16:24:49 2011 +0200

    memory: replace cpu_physical_sync_dirty_bitmap() with a memory API
    
    The function is still used as the implementation.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index a411fdf..ceef26e 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -41,6 +41,7 @@
 #include "net.h"
 #include "gdbstub.h"
 #include "hw/smbios.h"
+#include "exec-memory.h"
 
 #ifdef TARGET_SPARC
 int graphic_width = 1024;
@@ -263,10 +264,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
         return 0;
     }
 
-    if (cpu_physical_sync_dirty_bitmap(0, TARGET_PHYS_ADDR_MAX) != 0) {
-        qemu_file_set_error(f, -EINVAL);
-        return -EINVAL;
-    }
+    memory_global_sync_dirty_bitmap(get_system_memory());
 
     if (stage == 1) {
         RAMBlock *block;
diff --git a/cpu-all.h b/cpu-all.h
index 9d78715..f2c5382 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -569,9 +569,6 @@ int cpu_physical_memory_set_dirty_tracking(int enable);
 
 int cpu_physical_memory_get_dirty_tracking(void);
 
-int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
-                                   target_phys_addr_t end_addr);
-
 int cpu_physical_log_start(target_phys_addr_t start_addr,
                            ram_addr_t size);
 
diff --git a/exec-obsolete.h b/exec-obsolete.h
index 34b9fc5..5e5c4c6 100644
--- a/exec-obsolete.h
+++ b/exec-obsolete.h
@@ -63,6 +63,9 @@ static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
 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);
 
+int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
+                                   target_phys_addr_t end_addr);
+
 #endif
 
 #endif
diff --git a/memory.c b/memory.c
index c3e64ba..ef5d647 100644
--- a/memory.c
+++ b/memory.c
@@ -1447,6 +1447,10 @@ MemoryRegionSection memory_region_find(MemoryRegion *address_space,
     return ret;
 }
 
+void memory_global_sync_dirty_bitmap(MemoryRegion *address_space)
+{
+    cpu_physical_sync_dirty_bitmap(0, TARGET_PHYS_ADDR_MAX);
+}
 
 void set_system_memory_map(MemoryRegion *mr)
 {
diff --git a/memory.h b/memory.h
index 4d8f39a..8197b45 100644
--- a/memory.h
+++ b/memory.h
@@ -607,6 +607,16 @@ void memory_region_set_alias_offset(MemoryRegion *mr,
 MemoryRegionSection memory_region_find(MemoryRegion *address_space,
                                        target_phys_addr_t addr, uint64_t size);
 
+
+/**
+ * memory_global_sync_dirty_bitmap: synchronize the dirty log for all memory
+ *
+ * Synchronizes the dirty page log for an entire address space.
+ * @address_space: a top-level (i.e. parentless) region that contains the
+ *       memory being synchronized
+ */
+void memory_global_sync_dirty_bitmap(MemoryRegion *address_space);
+
 /**
  * memory_region_transaction_begin: Start a transaction.
  *
commit c1cd0b2c5131f24504d4513c4160cec73d53b326
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Dec 15 16:07:48 2011 +0200

    framebuffer: drop use of cpu_physical_sync_dirty_bitmap()
    
    Replace with memory API equivalent.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/framebuffer.c b/hw/framebuffer.c
index 3f4e773..b43bcdf 100644
--- a/hw/framebuffer.c
+++ b/hw/framebuffer.c
@@ -50,7 +50,6 @@ void framebuffer_update_display(
     *first_row = -1;
     src_len = src_width * rows;
 
-    cpu_physical_sync_dirty_bitmap(base, base + src_len);
     mem_section = memory_region_find(address_space, base, src_len);
     if (mem_section.size != src_len || !memory_region_is_ram(mem_section.mr)) {
         return;
@@ -59,6 +58,7 @@ void framebuffer_update_display(
     assert(mem);
     assert(mem_section.offset_within_address_space == base);
 
+    memory_region_sync_dirty_bitmap(mem);
     src_base = cpu_physical_memory_map(base, &src_len, 0);
     /* If we can't map the framebuffer then bail.  We could try harder,
        but it's not really worth it as dirty flag tracking will probably
commit dcc5cd33d27ab5612e0212b5399ad6ac0bc4886e
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Dec 8 16:12:18 2011 +0200

    loader: remove calls to cpu_get_physical_page_desc()
    
    cpu_get_physical_page_desc() is tied into the memory core's
    innards, replace it with uses of the API.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/loader.c b/hw/loader.c
index 9bbcddd..446b628 100644
--- a/hw/loader.c
+++ b/hw/loader.c
@@ -49,6 +49,8 @@
 #include "uboot_image.h"
 #include "loader.h"
 #include "fw_cfg.h"
+#include "memory.h"
+#include "exec-memory.h"
 
 #include <zlib.h>
 
@@ -674,7 +676,7 @@ static void rom_reset(void *unused)
 int rom_load_all(void)
 {
     target_phys_addr_t addr = 0;
-    int memtype;
+    MemoryRegionSection section;
     Rom *rom;
 
     QTAILQ_FOREACH(rom, &roms, next) {
@@ -690,9 +692,8 @@ int rom_load_all(void)
         }
         addr  = rom->addr;
         addr += rom->romsize;
-        memtype = cpu_get_physical_page_desc(rom->addr) & (3 << IO_MEM_SHIFT);
-        if (memtype == IO_MEM_ROM)
-            rom->isrom = 1;
+        section = memory_region_find(get_system_memory(), rom->addr, 1);
+        rom->isrom = section.size && memory_region_is_rom(section.mr);
     }
     qemu_register_reset(rom_reset, NULL);
     roms_loaded = 1;
commit 75c9d6c2f88f5713345b545beec10f0444ebd551
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Dec 8 16:00:54 2011 +0200

    framebuffer: drop use of cpu_get_physical_page_desc()
    
    cpu_get_physical_page_desc() is tied into the memory core's
    innards, replace it with uses of the API.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/framebuffer.c b/hw/framebuffer.c
index 56cf16e..3f4e773 100644
--- a/hw/framebuffer.c
+++ b/hw/framebuffer.c
@@ -22,6 +22,7 @@
    
 void framebuffer_update_display(
     DisplayState *ds,
+    MemoryRegion *address_space,
     target_phys_addr_t base,
     int cols, /* Width in pixels.  */
     int rows, /* Leight in pixels.  */
@@ -42,27 +43,21 @@ void framebuffer_update_display(
     int dirty;
     int i;
     ram_addr_t addr;
-    ram_addr_t pd;
-    ram_addr_t pd2;
+    MemoryRegionSection mem_section;
+    MemoryRegion *mem;
 
     i = *first_row;
     *first_row = -1;
     src_len = src_width * rows;
 
     cpu_physical_sync_dirty_bitmap(base, base + src_len);
-    pd = cpu_get_physical_page_desc(base);
-    pd2 = cpu_get_physical_page_desc(base + src_len - 1);
-    /* We should reall check that this is a continuous ram region.
-       Instead we just check that the first and last pages are
-       both ram, and the right distance apart.  */
-    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM
-        || (pd2 & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
-        return;
-    }
-    pd = (pd & TARGET_PAGE_MASK) + (base & ~TARGET_PAGE_MASK);
-    if (((pd + src_len - 1) & TARGET_PAGE_MASK) != (pd2 & TARGET_PAGE_MASK)) {
+    mem_section = memory_region_find(address_space, base, src_len);
+    if (mem_section.size != src_len || !memory_region_is_ram(mem_section.mr)) {
         return;
     }
+    mem = mem_section.mr;
+    assert(mem);
+    assert(mem_section.offset_within_address_space == base);
 
     src_base = cpu_physical_memory_map(base, &src_len, 0);
     /* If we can't map the framebuffer then bail.  We could try harder,
@@ -82,7 +77,7 @@ void framebuffer_update_display(
         dest -= dest_row_pitch * (rows - 1);
     }
     first = -1;
-    addr = pd;
+    addr = mem_section.offset_within_region;
 
     addr += i * src_width;
     src += i * src_width;
@@ -93,8 +88,8 @@ void framebuffer_update_display(
         dirty = 0;
         dirty_offset = 0;
         while (addr + dirty_offset < TARGET_PAGE_ALIGN(addr + src_width)) {
-            dirty |= cpu_physical_memory_get_dirty(addr + dirty_offset,
-                                                   VGA_DIRTY_FLAG);
+            dirty |= memory_region_get_dirty(mem, addr + dirty_offset,
+                                             DIRTY_MEMORY_VGA);
             dirty_offset += TARGET_PAGE_SIZE;
         }
 
@@ -112,7 +107,8 @@ void framebuffer_update_display(
     if (first < 0) {
         return;
     }
-    cpu_physical_memory_reset_dirty(pd, pd + src_len, VGA_DIRTY_FLAG);
+    memory_region_reset_dirty(mem, mem_section.offset_within_region, src_len,
+                              DIRTY_MEMORY_VGA);
     *first_row = first;
     *last_row = last;
     return;
diff --git a/hw/framebuffer.h b/hw/framebuffer.h
index a3a2146..527a6b8 100644
--- a/hw/framebuffer.h
+++ b/hw/framebuffer.h
@@ -1,12 +1,15 @@
 #ifndef QEMU_FRAMEBUFFER_H
 #define QEMU_FRAMEBUFFER_H
 
+#include "memory.h"
+
 /* Framebuffer device helper routines.  */
 
 typedef void (*drawfn)(void *, uint8_t *, const uint8_t *, int, int);
 
 void framebuffer_update_display(
     DisplayState *ds,
+    MemoryRegion *address_space,
     target_phys_addr_t base,
     int cols,
     int rows,
diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c
index 01cd309..108115e 100644
--- a/hw/milkymist-vgafb.c
+++ b/hw/milkymist-vgafb.c
@@ -120,7 +120,7 @@ static void vgafb_update_display(void *opaque)
         break;
     }
 
-    framebuffer_update_display(s->ds,
+    framebuffer_update_display(s->ds, sysbus_address_space(&s->busdev),
                                s->regs[R_BASEADDRESS] + s->fb_offset,
                                s->regs[R_HRES],
                                s->regs[R_VRES],
diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c
index 8484f70..f265306 100644
--- a/hw/omap_lcdc.c
+++ b/hw/omap_lcdc.c
@@ -22,6 +22,7 @@
 #include "framebuffer.h"
 
 struct omap_lcd_panel_s {
+    MemoryRegion *sysmem;
     MemoryRegion iomem;
     qemu_irq irq;
     DisplayState *state;
@@ -211,7 +212,7 @@ static void omap_update_display(void *opaque)
 
     step = width * bpp >> 3;
     linesize = ds_get_linesize(omap_lcd->state);
-    framebuffer_update_display(omap_lcd->state,
+    framebuffer_update_display(omap_lcd->state, omap_lcd->sysmem,
                                frame_base, width, height,
                                step, linesize, 0,
                                omap_lcd->invalidate,
@@ -440,6 +441,7 @@ struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem,
 
     s->irq = irq;
     s->dma = dma;
+    s->sysmem = sysmem;
     omap_lcdc_reset(s);
 
     memory_region_init_io(&s->iomem, &omap_lcdc_ops, s, "omap.lcdc", 0x100);
diff --git a/hw/pl110.c b/hw/pl110.c
index cc1eb6d..303a9bc 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -229,7 +229,7 @@ static void pl110_update_display(void *opaque)
     }
     dest_width *= s->cols;
     first = 0;
-    framebuffer_update_display(s->ds,
+    framebuffer_update_display(s->ds, sysbus_address_space(&s->busdev),
                                s->upbase, s->cols, s->rows,
                                src_width, dest_width, 0,
                                s->invalidate,
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index fd23d63..5dd4ef0 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -30,6 +30,7 @@ struct DMAChannel {
 };
 
 struct PXA2xxLCDState {
+    MemoryRegion *sysmem;
     MemoryRegion iomem;
     qemu_irq irq;
     int irqlevel;
@@ -681,7 +682,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
 
     dest_width = s->xres * s->dest_width;
     *miny = 0;
-    framebuffer_update_display(s->ds,
+    framebuffer_update_display(s->ds, s->sysmem,
                                addr, s->xres, s->yres,
                                src_width, dest_width, s->dest_width,
                                s->invalidated,
@@ -708,7 +709,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
 
     dest_width = s->yres * s->dest_width;
     *miny = 0;
-    framebuffer_update_display(s->ds,
+    framebuffer_update_display(s->ds, s->sysmem,
                                addr, s->xres, s->yres,
                                src_width, s->dest_width, -dest_width,
                                s->invalidated,
@@ -739,7 +740,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
 
     dest_width = s->xres * s->dest_width;
     *miny = 0;
-    framebuffer_update_display(s->ds,
+    framebuffer_update_display(s->ds, s->sysmem,
                                addr, s->xres, s->yres,
                                src_width, -dest_width, -s->dest_width,
                                s->invalidated,
@@ -769,7 +770,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
 
     dest_width = s->yres * s->dest_width;
     *miny = 0;
-    framebuffer_update_display(s->ds,
+    framebuffer_update_display(s->ds, s->sysmem,
                                addr, s->xres, s->yres,
                                src_width, -s->dest_width, dest_width,
                                s->invalidated,
@@ -985,6 +986,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
     s = (PXA2xxLCDState *) g_malloc0(sizeof(PXA2xxLCDState));
     s->invalidated = 1;
     s->irq = irq;
+    s->sysmem = sysmem;
 
     pxa2xx_lcdc_orientation(s, graphic_rotate);
 
commit e2177955a899483b19bd54e547db3b61db95eaf7
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Dec 8 15:00:18 2011 +0200

    memory: introduce memory_region_find()
    
    Given an address space (represented by the top-level memory region),
    returns the memory region that maps a given range.  Useful for implementing
    DMA.
    
    The implementation is a simplistic binary search.  Once we have a tree
    representation this can be optimized.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/memory.c b/memory.c
index 6e61635..c3e64ba 100644
--- a/memory.c
+++ b/memory.c
@@ -515,6 +515,20 @@ static AddressSpace address_space_io = {
     .ops = &address_space_ops_io,
 };
 
+static AddressSpace *memory_region_to_address_space(MemoryRegion *mr)
+{
+    while (mr->parent) {
+        mr = mr->parent;
+    }
+    if (mr == address_space_memory.root) {
+        return &address_space_memory;
+    }
+    if (mr == address_space_io.root) {
+        return &address_space_io;
+    }
+    abort();
+}
+
 /* Render a memory region into the global view.  Ranges in @view obscure
  * ranges in @mr.
  */
@@ -1386,6 +1400,54 @@ void memory_region_set_alias_offset(MemoryRegion *mr, target_phys_addr_t offset)
     memory_region_update_topology(mr);
 }
 
+static int cmp_flatrange_addr(const void *addr_, const void *fr_)
+{
+    const AddrRange *addr = addr_;
+    const FlatRange *fr = fr_;
+
+    if (int128_le(addrrange_end(*addr), fr->addr.start)) {
+        return -1;
+    } else if (int128_ge(addr->start, addrrange_end(fr->addr))) {
+        return 1;
+    }
+    return 0;
+}
+
+static FlatRange *address_space_lookup(AddressSpace *as, AddrRange addr)
+{
+    return bsearch(&addr, as->current_map.ranges, as->current_map.nr,
+                   sizeof(FlatRange), cmp_flatrange_addr);
+}
+
+MemoryRegionSection memory_region_find(MemoryRegion *address_space,
+                                       target_phys_addr_t addr, uint64_t size)
+{
+    AddressSpace *as = memory_region_to_address_space(address_space);
+    AddrRange range = addrrange_make(int128_make64(addr),
+                                     int128_make64(size));
+    FlatRange *fr = address_space_lookup(as, range);
+    MemoryRegionSection ret = { .mr = NULL, .size = 0 };
+
+    if (!fr) {
+        return ret;
+    }
+
+    while (fr > as->current_map.ranges
+           && addrrange_intersects(fr[-1].addr, range)) {
+        --fr;
+    }
+
+    ret.mr = fr->mr;
+    range = addrrange_intersection(range, fr->addr);
+    ret.offset_within_region = fr->offset_in_region;
+    ret.offset_within_region += int128_get64(int128_sub(range.start,
+                                                        fr->addr.start));
+    ret.size = int128_get64(range.size);
+    ret.offset_within_address_space = int128_get64(range.start);
+    return ret;
+}
+
+
 void set_system_memory_map(MemoryRegion *mr)
 {
     address_space_memory.root = mr;
diff --git a/memory.h b/memory.h
index 87fb974..4d8f39a 100644
--- a/memory.h
+++ b/memory.h
@@ -148,6 +148,24 @@ struct MemoryRegionPortio {
 
 #define PORTIO_END_OF_LIST() { }
 
+typedef struct MemoryRegionSection MemoryRegionSection;
+
+/**
+ * MemoryRegionSection: describes a fragment of a #MemoryRegion
+ *
+ * @mr: the region, or %NULL if empty
+ * @offset_within_region: the beginning of the section, relative to @mr's start
+ * @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
+ */
+struct MemoryRegionSection {
+    MemoryRegion *mr;
+    target_phys_addr_t offset_within_region;
+    uint64_t size;
+    target_phys_addr_t offset_within_address_space;
+};
+
 /**
  * memory_region_init: Initialize a memory region
  *
@@ -569,6 +587,27 @@ void memory_region_set_alias_offset(MemoryRegion *mr,
                                     target_phys_addr_t offset);
 
 /**
+ * memory_region_find: locate a MemoryRegion in an address space
+ *
+ * Locates the first #MemoryRegion within an address space given by
+ * @address_space that overlaps the range given by @addr and @size.
+ *
+ * Returns a #MemoryRegionSection that describes a contiguous overlap.
+ * It will have the following characteristics:
+ *    . at offset_within_address_space >= @addr
+ *    . at offset_within_address_space + . at size <= @addr + @size
+ *    . at size = 0 iff no overlap was found
+ *    . at mr is non-%NULL iff an overlap was found
+ *
+ * @address_space: a top-level (i.e. parentless) region that contains
+ *       the region to be found
+ * @addr: start of the area within @address_space to be searched
+ * @size: size of the area to be searched
+ */
+MemoryRegionSection memory_region_find(MemoryRegion *address_space,
+                                       target_phys_addr_t addr, uint64_t size);
+
+/**
  * memory_region_transaction_begin: Start a transaction.
  *
  * During a transaction, changes will be accumulated and made visible
commit 55043ba37ee4b080a4f4f77b0ff672be3cbf8825
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Dec 15 17:20:34 2011 +0200

    memory: add memory_region_is_logging()
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/memory.c b/memory.c
index 01baeac..6e61635 100644
--- a/memory.c
+++ b/memory.c
@@ -1074,6 +1074,11 @@ bool memory_region_is_ram(MemoryRegion *mr)
     return mr->ram;
 }
 
+bool memory_region_is_logging(MemoryRegion *mr)
+{
+    return mr->dirty_log_mask;
+}
+
 bool memory_region_is_rom(MemoryRegion *mr)
 {
     return mr->ram && mr->readonly;
diff --git a/memory.h b/memory.h
index 91d6e8a..87fb974 100644
--- a/memory.h
+++ b/memory.h
@@ -277,6 +277,15 @@ uint64_t memory_region_size(MemoryRegion *mr);
 bool memory_region_is_ram(MemoryRegion *mr);
 
 /**
+ * memory_region_is_logging: return whether a memory region is logging writes
+ *
+ * Returns %true if the memory region is logging writes
+ *
+ * @mr: the memory region being queried
+ */
+bool memory_region_is_logging(MemoryRegion *mr);
+
+/**
  * memory_region_is_rom: check whether a memory region is ROM
  *
  * Returns %true is a memory region is read-only memory.
commit ce7923da4da4e5895ab737fbf2c9b603c764a933
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Dec 8 16:05:11 2011 +0200

    memory: add memory_region_is_rom()
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/memory.c b/memory.c
index 4264b42..01baeac 100644
--- a/memory.c
+++ b/memory.c
@@ -1074,6 +1074,11 @@ bool memory_region_is_ram(MemoryRegion *mr)
     return mr->ram;
 }
 
+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;
diff --git a/memory.h b/memory.h
index dccc900..91d6e8a 100644
--- a/memory.h
+++ b/memory.h
@@ -277,6 +277,15 @@ uint64_t memory_region_size(MemoryRegion *mr);
 bool memory_region_is_ram(MemoryRegion *mr);
 
 /**
+ * memory_region_is_rom: check whether a memory region is ROM
+ *
+ * Returns %true is a memory region is read-only memory.
+ *
+ * @mr: the memory region being queried
+ */
+bool memory_region_is_rom(MemoryRegion *mr);
+
+/**
  * memory_region_get_ram_ptr: Get a pointer into a RAM memory region.
  *
  * Returns a host pointer to a RAM memory region (created with
commit 8ea9252abe08631611effb905fbb4a015ec1514c
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Dec 8 15:58:43 2011 +0200

    memory: add memory_region_is_ram()
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/memory.c b/memory.c
index a7e615a..4264b42 100644
--- a/memory.c
+++ b/memory.c
@@ -832,6 +832,7 @@ void memory_region_init(MemoryRegion *mr,
     mr->offset = 0;
     mr->enabled = true;
     mr->terminates = false;
+    mr->ram = false;
     mr->readable = true;
     mr->readonly = false;
     mr->destructor = memory_region_destructor_none;
@@ -998,6 +999,7 @@ void memory_region_init_ram(MemoryRegion *mr,
                             uint64_t size)
 {
     memory_region_init(mr, name, size);
+    mr->ram = true;
     mr->terminates = true;
     mr->destructor = memory_region_destructor_ram;
     mr->ram_addr = qemu_ram_alloc(dev, name, size, mr);
@@ -1011,6 +1013,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr,
                                 void *ptr)
 {
     memory_region_init(mr, name, size);
+    mr->ram = true;
     mr->terminates = true;
     mr->destructor = memory_region_destructor_ram_from_ptr;
     mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr, mr);
@@ -1066,6 +1069,11 @@ uint64_t memory_region_size(MemoryRegion *mr)
     return int128_get64(mr->size);
 }
 
+bool memory_region_is_ram(MemoryRegion *mr)
+{
+    return mr->ram;
+}
+
 void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset)
 {
     mr->offset = offset;
diff --git a/memory.h b/memory.h
index fe643ff..dccc900 100644
--- a/memory.h
+++ b/memory.h
@@ -122,6 +122,7 @@ struct MemoryRegion {
     IORange iorange;
     bool terminates;
     bool readable;
+    bool ram;
     bool readonly; /* For RAM regions */
     bool enabled;
     MemoryRegion *alias;
@@ -267,6 +268,15 @@ void memory_region_destroy(MemoryRegion *mr);
 uint64_t memory_region_size(MemoryRegion *mr);
 
 /**
+ * memory_region_is_ram: check whether a memory region is random access
+ *
+ * Returns %true is a memory region is random access.
+ *
+ * @mr: the memory region being queried
+ */
+bool memory_region_is_ram(MemoryRegion *mr);
+
+/**
  * memory_region_get_ram_ptr: Get a pointer into a RAM memory region.
  *
  * Returns a host pointer to a RAM memory region (created with
commit 62ec4832ea1093b20a8a0893a016a00ef8145496
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Dec 8 15:57:34 2011 +0200

    sysbus: add sysbus_address_space()
    
    Given a bus device, retrieves the memory address space for its bus.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/sysbus.c b/hw/sysbus.c
index 81a57bd..7016903 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -261,3 +261,8 @@ void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem)
 {
     memory_region_del_subregion(get_system_io(), mem);
 }
+
+MemoryRegion *sysbus_address_space(SysBusDevice *dev)
+{
+    return get_system_memory();
+}
diff --git a/hw/sysbus.h b/hw/sysbus.h
index 2f4025b..899756b 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -57,6 +57,7 @@ void sysbus_del_memory(SysBusDevice *dev, MemoryRegion *mem);
 void sysbus_add_io(SysBusDevice *dev, target_phys_addr_t addr,
                    MemoryRegion *mem);
 void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem);
+MemoryRegion *sysbus_address_space(SysBusDevice *dev);
 
 /* Legacy helper function for creating devices.  */
 DeviceState *sysbus_create_varargs(const char *name,
commit 1de81d2832e210dda43a101e4163a17bc4d9c71d
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 19 16:37:46 2011 -0600

    qdev: fix hotplug when no -device is specified
    
    The peripheral[-anon] containers are initialized lazily but since they sit on
    sysbus, they can not be created after realize.  This was causing an abort() to
    occur during hotplug if no -device option was used.
    
    This was spotted by qemu-test::device-add.sh
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 0465632..d0cf66d 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -1529,3 +1529,9 @@ void qdev_property_add_str(DeviceState *dev, const char *name,
                       qdev_property_release_str,
                       prop, errp);
 }
+
+void qdev_machine_init(void)
+{
+    qdev_get_peripheral_anon();
+    qdev_get_peripheral();
+}
diff --git a/hw/qdev.h b/hw/qdev.h
index d5896be..2abb767 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -616,4 +616,12 @@ void qdev_property_add_str(DeviceState *dev, const char *name,
  */
 char *qdev_get_type(DeviceState *dev, Error **errp);
 
+/**
+ * @qdev_machine_init
+ *
+ * Initialize platform devices before machine init.  This is a hack until full
+ * support for composition is added.
+ */
+void qdev_machine_init(void);
+
 #endif
diff --git a/vl.c b/vl.c
index da69f94..78b790c 100644
--- a/vl.c
+++ b/vl.c
@@ -3335,6 +3335,8 @@ int main(int argc, char **argv, char **envp)
     }
     qemu_add_globals();
 
+    qdev_machine_init();
+
     machine->init(ram_size, boot_devices,
                   kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
 
commit ab0115e10ca2221a7844ac5fd18842976eec3b2b
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Fri Dec 16 23:37:48 2011 +0100

    sysbus: remove sysbus_init_mmio_cb2
    
    This function is not longer in use so remove it.
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/sysbus.c b/hw/sysbus.c
index b315a8c..81a57bd 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -53,8 +53,6 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)
         if (dev->mmio[n].memory) {
             memory_region_del_subregion(get_system_memory(),
                                         dev->mmio[n].memory);
-        } else if (dev->mmio[n].unmap) {
-            dev->mmio[n].unmap(dev, dev->mmio[n].addr);
         }
     }
     dev->mmio[n].addr = addr;
@@ -62,8 +60,6 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)
         memory_region_add_subregion(get_system_memory(),
                                     addr,
                                     dev->mmio[n].memory);
-    } else if (dev->mmio[n].cb) {
-        dev->mmio[n].cb(dev, addr);
     }
 }
 
@@ -89,18 +85,6 @@ void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target)
     }
 }
 
-void sysbus_init_mmio_cb2(SysBusDevice *dev,
-                          mmio_mapfunc cb, mmio_mapfunc unmap)
-{
-    int n;
-
-    assert(dev->num_mmio < QDEV_MAX_MMIO);
-    n = dev->num_mmio++;
-    dev->mmio[n].addr = -1;
-    dev->mmio[n].cb = cb;
-    dev->mmio[n].unmap = unmap;
-}
-
 void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory)
 {
     int n;
diff --git a/hw/sysbus.h b/hw/sysbus.h
index 9bac582..2f4025b 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -11,7 +11,6 @@
 #define QDEV_MAX_IRQ 256
 
 typedef struct SysBusDevice SysBusDevice;
-typedef void (*mmio_mapfunc)(SysBusDevice *dev, target_phys_addr_t addr);
 
 struct SysBusDevice {
     DeviceState qdev;
@@ -21,8 +20,6 @@ struct SysBusDevice {
     int num_mmio;
     struct {
         target_phys_addr_t addr;
-        mmio_mapfunc cb;
-        mmio_mapfunc unmap;
         MemoryRegion *memory;
     } mmio[QDEV_MAX_MMIO];
     int num_pio;
@@ -43,8 +40,6 @@ typedef struct {
 void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init);
 void sysbus_register_withprop(SysBusDeviceInfo *info);
 void *sysbus_new(void);
-void sysbus_init_mmio_cb2(SysBusDevice *dev,
-                          mmio_mapfunc cb, mmio_mapfunc unmap);
 void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory);
 MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n);
 void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p);
commit cb4e15c7ff92859d112221ef57ee4340e5c531d3
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Fri Dec 16 23:37:47 2011 +0100

    ppce500_pci: remove sysbus_init_mmio_cb2 usage
    
    Expose only one container MemoryRegion to sysbus.
    (Peter Maydell's idea)
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 6232af1..b606206 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -79,6 +79,7 @@ struct PPCE500PCIState {
     uint32_t gasket_time;
     qemu_irq irq[4];
     /* mmio maps */
+    MemoryRegion container;
     MemoryRegion iomem;
 };
 
@@ -298,26 +299,6 @@ static const VMStateDescription vmstate_ppce500_pci = {
     }
 };
 
-static void e500_pci_map(SysBusDevice *dev, target_phys_addr_t base)
-{
-    PCIHostState *h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
-    PPCE500PCIState *s = DO_UPCAST(PPCE500PCIState, pci_state, h);
-
-    sysbus_add_memory(dev, base + PCIE500_CFGADDR, &h->conf_mem);
-    sysbus_add_memory(dev, base + PCIE500_CFGDATA, &h->data_mem);
-    sysbus_add_memory(dev, base + PCIE500_REG_BASE, &s->iomem);
-}
-
-static void e500_pci_unmap(SysBusDevice *dev, target_phys_addr_t base)
-{
-    PCIHostState *h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
-    PPCE500PCIState *s = DO_UPCAST(PPCE500PCIState, pci_state, h);
-
-    sysbus_del_memory(dev, &h->conf_mem);
-    sysbus_del_memory(dev, &h->data_mem);
-    sysbus_del_memory(dev, &s->iomem);
-}
-
 #include "exec-memory.h"
 
 static int e500_pcihost_initfn(SysBusDevice *dev)
@@ -343,13 +324,17 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
 
     pci_create_simple(b, 0, "e500-host-bridge");
 
+    memory_region_init(&s->container, "pci-container", PCIE500_ALL_SIZE);
     memory_region_init_io(&h->conf_mem, &pci_host_conf_be_ops, h,
                           "pci-conf-idx", 4);
     memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, h,
                           "pci-conf-data", 4);
     memory_region_init_io(&s->iomem, &e500_pci_reg_ops, s,
                           "pci.reg", PCIE500_REG_SIZE);
-    sysbus_init_mmio_cb2(dev, e500_pci_map, e500_pci_unmap);
+    memory_region_add_subregion(&s->container, PCIE500_CFGADDR, &h->conf_mem);
+    memory_region_add_subregion(&s->container, PCIE500_CFGDATA, &h->data_mem);
+    memory_region_add_subregion(&s->container, PCIE500_REG_BASE, &s->iomem);
+    sysbus_init_mmio(dev, &s->container);
 
     return 0;
 }
commit 8c106233ab179deb6faa8914b6103d3e68431b4b
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Fri Dec 16 23:37:46 2011 +0100

    sh_pci: remove sysbus_init_mmio_cb2 usage
    
    The isa region is not exposed as a sysbus region because the iobr
    register contains its address and use it to remap dynamically
    the region. (Peter Maydell's idea)
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/r2d.c b/hw/r2d.c
index 9b6fcba..6e1f71c 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -231,6 +231,8 @@ static void r2d_init(ram_addr_t ram_size,
     qemu_irq *irq;
     DriveInfo *dinfo;
     int i;
+    DeviceState *dev;
+    SysBusDevice *busdev;
     MemoryRegion *address_space_mem = get_system_memory();
 
     if (!cpu_model)
@@ -252,8 +254,16 @@ static void r2d_init(ram_addr_t ram_size,
     /* Register peripherals */
     s = sh7750_init(env, address_space_mem);
     irq = r2d_fpga_init(address_space_mem, 0x04000000, sh7750_irl(s));
-    sysbus_create_varargs("sh_pci", 0x1e200000, irq[PCI_INTA], irq[PCI_INTB],
-                          irq[PCI_INTC], irq[PCI_INTD], NULL);
+
+    dev = qdev_create(NULL, "sh_pci");
+    busdev = sysbus_from_qdev(dev);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(busdev, 0, P4ADDR(0x1e200000));
+    sysbus_mmio_map(busdev, 1, A7ADDR(0x1e200000));
+    sysbus_connect_irq(busdev, 0, irq[PCI_INTA]);
+    sysbus_connect_irq(busdev, 1, irq[PCI_INTB]);
+    sysbus_connect_irq(busdev, 2, irq[PCI_INTC]);
+    sysbus_connect_irq(busdev, 3, irq[PCI_INTD]);
 
     sm501_init(address_space_mem, 0x10000000, SM501_VRAM_SIZE,
                irq[SM501], serial_hds[2]);
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index 86f468e..d4d028d 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -110,29 +110,6 @@ static void sh_pci_set_irq(void *opaque, int irq_num, int level)
     qemu_set_irq(pic[irq_num], level);
 }
 
-static void sh_pci_map(SysBusDevice *dev, target_phys_addr_t base)
-{
-    SHPCIState *s = FROM_SYSBUS(SHPCIState, dev);
-
-    memory_region_add_subregion(get_system_memory(),
-                                P4ADDR(base),
-                                &s->memconfig_p4);
-    memory_region_add_subregion(get_system_memory(),
-                                A7ADDR(base),
-                                &s->memconfig_a7);
-    s->iobr = 0xfe240000;
-    memory_region_add_subregion(get_system_memory(), s->iobr, &s->isa);
-}
-
-static void sh_pci_unmap(SysBusDevice *dev, target_phys_addr_t base)
-{
-    SHPCIState *s = FROM_SYSBUS(SHPCIState, dev);
-
-    memory_region_del_subregion(get_system_memory(), &s->memconfig_p4);
-    memory_region_del_subregion(get_system_memory(), &s->memconfig_a7);
-    memory_region_del_subregion(get_system_memory(), &s->isa);
-}
-
 static int sh_pci_init_device(SysBusDevice *dev)
 {
     SHPCIState *s;
@@ -153,9 +130,11 @@ static int sh_pci_init_device(SysBusDevice *dev)
     memory_region_init_alias(&s->memconfig_a7, "sh_pci.2", &s->memconfig_p4,
                              0, 0x224);
     isa_mmio_setup(&s->isa, 0x40000);
-    sysbus_init_mmio_cb2(dev, sh_pci_map, sh_pci_unmap);
+    sysbus_init_mmio(dev, &s->memconfig_p4);
     sysbus_init_mmio(dev, &s->memconfig_a7);
-    sysbus_init_mmio(dev, &s->isa);
+    s->iobr = 0xfe240000;
+    memory_region_add_subregion(get_system_memory(), s->iobr, &s->isa);
+
     s->dev = pci_create_simple(s->bus, PCI_DEVFN(0, 0), "sh_pci_host");
     return 0;
 }
commit ca2cc7888846ab85ee6549bb0b68ac0cbf16a4e9
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sun Dec 18 17:05:11 2011 +0100

    qom: register qdev properties also as non-legacy properties
    
    Push legacy properties into a "legacy-..." namespace, and make them
    available with correct types too.
    
    For now, all properties come in both variants.  This need not be the
    case for string properties.  We will revisit this after -device is
    changed to actually use the legacy properties.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index c6fcf4c..0465632 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -80,6 +80,9 @@ static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
     return NULL;
 }
 
+static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
+                                     Error **errp);
+
 static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
 {
     DeviceState *dev;
@@ -104,10 +107,12 @@ static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
 
     for (prop = dev->info->props; prop && prop->name; prop++) {
         qdev_property_add_legacy(dev, prop, NULL);
+        qdev_property_add_static(dev, prop, NULL);
     }
 
     for (prop = dev->info->bus_info->props; prop && prop->name; prop++) {
         qdev_property_add_legacy(dev, prop, NULL);
+        qdev_property_add_static(dev, prop, NULL);
     }
 
     qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
@@ -1172,7 +1177,7 @@ static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
  * @qdev_add_legacy_property - adds a legacy property
  *
  * Do not use this is new code!  Properties added through this interface will
- * be given types in the "legacy<>" type namespace.
+ * be given names and types in the "legacy" namespace.
  *
  * Legacy properties are always processed as strings.  The format of the string
  * depends on the property type.
@@ -1180,18 +1185,35 @@ static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
 void qdev_property_add_legacy(DeviceState *dev, Property *prop,
                               Error **errp)
 {
-    gchar *type;
+    gchar *name, *type;
 
+    name = g_strdup_printf("legacy-%s", prop->name);
     type = g_strdup_printf("legacy<%s>",
                            prop->info->legacy_name ?: prop->info->name);
 
-    qdev_property_add(dev, prop->name, type,
+    qdev_property_add(dev, name, type,
                       prop->info->print ? qdev_get_legacy_property : NULL,
                       prop->info->parse ? qdev_set_legacy_property : NULL,
                       NULL,
                       prop, errp);
 
     g_free(type);
+    g_free(name);
+}
+
+/**
+ * @qdev_property_add_static - add a @Property to a device.
+ *
+ * Static properties access data in a struct.  The actual type of the
+ * property and the field depends on the property type.
+ */
+void qdev_property_add_static(DeviceState *dev, Property *prop,
+                              Error **errp)
+{
+    qdev_property_add(dev, prop->name, prop->info->name,
+                      prop->info->get, prop->info->set,
+                      NULL,
+                      prop, errp);
 }
 
 DeviceState *qdev_get_root(void)
diff --git a/hw/qdev.h b/hw/qdev.h
index 5f23cac..d5896be 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -487,11 +487,10 @@ const char *qdev_property_get_type(DeviceState *dev, const char *name,
                                    Error **errp);
 
 /**
- * @qdev_property_add_legacy - add a legacy @Property to a device
- *
- * DO NOT USE THIS IN NEW CODE!
+ * @qdev_property_add_static - add a @Property to a device referencing a
+ * field in a struct.
  */
-void qdev_property_add_legacy(DeviceState *dev, Property *prop, Error **errp);
+void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp);
 
 /**
  * @qdev_get_root - returns the root device of the composition tree
commit cafe5bdb9a6179f80562e99ef3f29bdf0b5df678
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sun Dec 18 17:05:10 2011 +0100

    qom: distinguish "legacy" property type name from QOM type name
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 41d2165..663c2a0 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -86,7 +86,8 @@ static void set_bit(DeviceState *dev, Visitor *v, void *opaque,
 }
 
 PropertyInfo qdev_prop_bit = {
-    .name  = "on/off",
+    .name  = "boolean",
+    .legacy_name  = "on/off",
     .type  = PROP_TYPE_BIT,
     .size  = sizeof(uint32_t),
     .parse = parse_bit,
@@ -189,7 +190,8 @@ static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
 }
 
 PropertyInfo qdev_prop_hex8 = {
-    .name  = "hex8",
+    .name  = "uint8",
+    .legacy_name  = "hex8",
     .type  = PROP_TYPE_UINT8,
     .size  = sizeof(uint8_t),
     .parse = parse_hex8,
@@ -397,7 +399,8 @@ static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
 }
 
 PropertyInfo qdev_prop_hex32 = {
-    .name  = "hex32",
+    .name  = "uint32",
+    .legacy_name  = "hex32",
     .type  = PROP_TYPE_UINT32,
     .size  = sizeof(uint32_t),
     .parse = parse_hex32,
@@ -485,7 +488,8 @@ static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
 }
 
 PropertyInfo qdev_prop_hex64 = {
-    .name  = "hex64",
+    .name  = "uint64",
+    .legacy_name  = "hex64",
     .type  = PROP_TYPE_UINT64,
     .size  = sizeof(uint64_t),
     .parse = parse_hex64,
diff --git a/hw/qdev.c b/hw/qdev.c
index 2a146f7..c6fcf4c 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -218,13 +218,15 @@ int qdev_device_help(QemuOpts *opts)
         if (!prop->info->parse) {
             continue;           /* no way to set it, don't show */
         }
-        error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
+        error_printf("%s.%s=%s\n", info->name, prop->name,
+                     prop->info->legacy_name ?: prop->info->name);
     }
     for (prop = info->bus_info->props; prop && prop->name; prop++) {
         if (!prop->info->parse) {
             continue;           /* no way to set it, don't show */
         }
-        error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
+        error_printf("%s.%s=%s\n", info->name, prop->name,
+                     prop->info->legacy_name ?: prop->info->name);
     }
     return 1;
 }
@@ -1180,7 +1182,8 @@ void qdev_property_add_legacy(DeviceState *dev, Property *prop,
 {
     gchar *type;
 
-    type = g_strdup_printf("legacy<%s>", prop->info->name);
+    type = g_strdup_printf("legacy<%s>",
+                           prop->info->legacy_name ?: prop->info->name);
 
     qdev_property_add(dev, prop->name, type,
                       prop->info->print ? qdev_get_legacy_property : NULL,
diff --git a/hw/qdev.h b/hw/qdev.h
index 42495ae..5f23cac 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -156,6 +156,7 @@ enum PropertyType {
 
 struct PropertyInfo {
     const char *name;
+    const char *legacy_name;
     size_t size;
     enum PropertyType type;
     int64_t min;
commit 80e555c2418c50e5130fed6245537dfd2ba4bebd
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sun Dec 18 17:05:09 2011 +0100

    qom: introduce get/set methods for Property
    
    This patch adds a visitor interface to Property.  This way, QOM will be
    able to expose Properties that access a fixed field in a struct without
    exposing also the everything-is-a-string "feature" of qdev properties.
    
    Whenever the printed representation in both QOM and qdev (which is
    typically the case for device backends), parse/print code can be reused
    via get_generic/set_generic.  Dually, whenever multiple PropertyInfos
    have the same representation in both the struct and the visitors the
    code can be reused (for example among all of int32/uint32/hex32).
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev-addr.c b/hw/qdev-addr.c
index 305c2d3..5ddda2d 100644
--- a/hw/qdev-addr.c
+++ b/hw/qdev-addr.c
@@ -18,12 +18,53 @@ static int print_taddr(DeviceState *dev, Property *prop, char *dest, size_t len)
     return snprintf(dest, len, "0x" TARGET_FMT_plx, *ptr);
 }
 
+static void get_taddr(DeviceState *dev, Visitor *v, void *opaque,
+                      const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    target_phys_addr_t *ptr = qdev_get_prop_ptr(dev, prop);
+    int64_t value;
+
+    value = *ptr;
+    visit_type_int(v, &value, name, errp);
+}
+
+static void set_taddr(DeviceState *dev, Visitor *v, void *opaque,
+                      const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    target_phys_addr_t *ptr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    int64_t value;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_int(v, &value, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    if ((uint64_t)value <= (uint64_t) ~(target_phys_addr_t)0) {
+        *ptr = value;
+    } else {
+        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
+                  dev->id?:"", name, value, (uint64_t) 0,
+                  (uint64_t) ~(target_phys_addr_t)0);
+    }
+}
+
+
 PropertyInfo qdev_prop_taddr = {
     .name  = "taddr",
     .type  = PROP_TYPE_TADDR,
     .size  = sizeof(target_phys_addr_t),
     .parse = parse_taddr,
     .print = print_taddr,
+    .get   = get_taddr,
+    .set   = set_taddr,
 };
 
 void qdev_prop_set_taddr(DeviceState *dev, const char *name, target_phys_addr_t value)
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index de618f2..41d2165 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -55,12 +55,44 @@ static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
     return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
 }
 
+static void get_bit(DeviceState *dev, Visitor *v, void *opaque,
+                    const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    uint32_t *p = qdev_get_prop_ptr(dev, prop);
+    bool value = (*p & qdev_get_prop_mask(prop)) != 0;
+
+    visit_type_bool(v, &value, name, errp);
+}
+
+static void set_bit(DeviceState *dev, Visitor *v, void *opaque,
+                    const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    Error *local_err = NULL;
+    bool value;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_bool(v, &value, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    bit_prop_set(dev, prop, value);
+}
+
 PropertyInfo qdev_prop_bit = {
     .name  = "on/off",
     .type  = PROP_TYPE_BIT,
     .size  = sizeof(uint32_t),
     .parse = parse_bit,
     .print = print_bit,
+    .get   = get_bit,
+    .set   = set_bit,
 };
 
 /* --- 8bit integer --- */
@@ -85,12 +117,54 @@ static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len)
     return snprintf(dest, len, "%" PRIu8, *ptr);
 }
 
+static void get_int8(DeviceState *dev, Visitor *v, void *opaque,
+                     const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    int8_t *ptr = qdev_get_prop_ptr(dev, prop);
+    int64_t value;
+
+    value = *ptr;
+    visit_type_int(v, &value, name, errp);
+}
+
+static void set_int8(DeviceState *dev, Visitor *v, void *opaque,
+                      const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    int8_t *ptr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    int64_t value;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_int(v, &value, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    if (value > prop->info->min && value <= prop->info->max) {
+        *ptr = value;
+    } else {
+        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
+                  dev->id?:"", name, value, prop->info->min,
+                  prop->info->max);
+    }
+}
+
 PropertyInfo qdev_prop_uint8 = {
     .name  = "uint8",
     .type  = PROP_TYPE_UINT8,
     .size  = sizeof(uint8_t),
     .parse = parse_uint8,
     .print = print_uint8,
+    .get   = get_int8,
+    .set   = set_int8,
+    .min   = 0,
+    .max   = 255,
 };
 
 /* --- 8bit hex value --- */
@@ -120,6 +194,10 @@ PropertyInfo qdev_prop_hex8 = {
     .size  = sizeof(uint8_t),
     .parse = parse_hex8,
     .print = print_hex8,
+    .get   = get_int8,
+    .set   = set_int8,
+    .min   = 0,
+    .max   = 255,
 };
 
 /* --- 16bit integer --- */
@@ -144,12 +222,54 @@ static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len
     return snprintf(dest, len, "%" PRIu16, *ptr);
 }
 
+static void get_int16(DeviceState *dev, Visitor *v, void *opaque,
+                      const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    int16_t *ptr = qdev_get_prop_ptr(dev, prop);
+    int64_t value;
+
+    value = *ptr;
+    visit_type_int(v, &value, name, errp);
+}
+
+static void set_int16(DeviceState *dev, Visitor *v, void *opaque,
+                      const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    int16_t *ptr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    int64_t value;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_int(v, &value, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    if (value > prop->info->min && value <= prop->info->max) {
+        *ptr = value;
+    } else {
+        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
+                  dev->id?:"", name, value, prop->info->min,
+                  prop->info->max);
+    }
+}
+
 PropertyInfo qdev_prop_uint16 = {
     .name  = "uint16",
     .type  = PROP_TYPE_UINT16,
     .size  = sizeof(uint16_t),
     .parse = parse_uint16,
     .print = print_uint16,
+    .get   = get_int16,
+    .set   = set_int16,
+    .min   = 0,
+    .max   = 65535,
 };
 
 /* --- 32bit integer --- */
@@ -174,12 +294,54 @@ static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len
     return snprintf(dest, len, "%" PRIu32, *ptr);
 }
 
+static void get_int32(DeviceState *dev, Visitor *v, void *opaque,
+                      const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
+    int64_t value;
+
+    value = *ptr;
+    visit_type_int(v, &value, name, errp);
+}
+
+static void set_int32(DeviceState *dev, Visitor *v, void *opaque,
+                      const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    int64_t value;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_int(v, &value, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    if (value > prop->info->min && value <= prop->info->max) {
+        *ptr = value;
+    } else {
+        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
+                  dev->id?:"", name, value, prop->info->min,
+                  prop->info->max);
+    }
+}
+
 PropertyInfo qdev_prop_uint32 = {
     .name  = "uint32",
     .type  = PROP_TYPE_UINT32,
     .size  = sizeof(uint32_t),
     .parse = parse_uint32,
     .print = print_uint32,
+    .get   = get_int32,
+    .set   = set_int32,
+    .min   = 0,
+    .max   = 0xFFFFFFFFULL,
 };
 
 static int parse_int32(DeviceState *dev, Property *prop, const char *str)
@@ -207,6 +369,10 @@ PropertyInfo qdev_prop_int32 = {
     .size  = sizeof(int32_t),
     .parse = parse_int32,
     .print = print_int32,
+    .get   = get_int32,
+    .set   = set_int32,
+    .min   = -0x80000000LL,
+    .max   = 0x7FFFFFFFLL,
 };
 
 /* --- 32bit hex value --- */
@@ -236,6 +402,10 @@ PropertyInfo qdev_prop_hex32 = {
     .size  = sizeof(uint32_t),
     .parse = parse_hex32,
     .print = print_hex32,
+    .get   = get_int32,
+    .set   = set_int32,
+    .min   = 0,
+    .max   = 0xFFFFFFFFULL,
 };
 
 /* --- 64bit integer --- */
@@ -260,12 +430,37 @@ static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len
     return snprintf(dest, len, "%" PRIu64, *ptr);
 }
 
+static void get_int64(DeviceState *dev, Visitor *v, void *opaque,
+                      const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    int64_t *ptr = qdev_get_prop_ptr(dev, prop);
+
+    visit_type_int(v, ptr, name, errp);
+}
+
+static void set_int64(DeviceState *dev, Visitor *v, void *opaque,
+                      const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    int64_t *ptr = qdev_get_prop_ptr(dev, prop);
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_int(v, ptr, name, errp);
+}
+
 PropertyInfo qdev_prop_uint64 = {
     .name  = "uint64",
     .type  = PROP_TYPE_UINT64,
     .size  = sizeof(uint64_t),
     .parse = parse_uint64,
     .print = print_uint64,
+    .get   = get_int64,
+    .set   = set_int64,
 };
 
 /* --- 64bit hex value --- */
@@ -295,6 +490,8 @@ PropertyInfo qdev_prop_hex64 = {
     .size  = sizeof(uint64_t),
     .parse = parse_hex64,
     .print = print_hex64,
+    .get   = get_int64,
+    .set   = set_int64,
 };
 
 /* --- string --- */
@@ -322,6 +519,48 @@ static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len
     return snprintf(dest, len, "\"%s\"", *ptr);
 }
 
+static void get_string(DeviceState *dev, Visitor *v, void *opaque,
+                       const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    char **ptr = qdev_get_prop_ptr(dev, prop);
+
+    if (!*ptr) {
+        char *str = (char *)"";
+        visit_type_str(v, &str, name, errp);
+    } else {
+        visit_type_str(v, ptr, name, errp);
+    }
+}
+
+static void set_string(DeviceState *dev, Visitor *v, void *opaque,
+                       const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    char **ptr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    char *str;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_str(v, &str, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    if (!*str) {
+        g_free(str);
+        str = NULL;
+    }
+    if (*ptr) {
+        g_free(*ptr);
+    }
+    *ptr = str;
+}
+
 PropertyInfo qdev_prop_string = {
     .name  = "string",
     .type  = PROP_TYPE_STRING,
@@ -329,6 +568,8 @@ PropertyInfo qdev_prop_string = {
     .parse = parse_string,
     .print = print_string,
     .free  = free_string,
+    .get   = get_string,
+    .set   = set_string,
 };
 
 /* --- drive --- */
@@ -364,12 +605,57 @@ static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len)
                     *ptr ? bdrv_get_device_name(*ptr) : "<null>");
 }
 
+static void get_generic(DeviceState *dev, Visitor *v, void *opaque,
+                       const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    void **ptr = qdev_get_prop_ptr(dev, prop);
+    char buffer[1024];
+    char *p = buffer;
+
+    buffer[0] = 0;
+    if (*ptr) {
+        prop->info->print(dev, prop, buffer, sizeof(buffer));
+    }
+    visit_type_str(v, &p, name, errp);
+}
+
+static void set_generic(DeviceState *dev, Visitor *v, void *opaque,
+                        const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    Error *local_err = NULL;
+    char *str;
+    int ret;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_str(v, &str, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    if (!*str) {
+        g_free(str);
+        error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+        return;
+    }
+    ret = prop->info->parse(dev, prop, str);
+    error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
+    g_free(str);
+}
+
 PropertyInfo qdev_prop_drive = {
     .name  = "drive",
     .type  = PROP_TYPE_DRIVE,
     .size  = sizeof(BlockDriverState *),
     .parse = parse_drive,
     .print = print_drive,
+    .get   = get_generic,
+    .set   = set_generic,
     .free  = free_drive,
 };
 
@@ -407,6 +693,8 @@ PropertyInfo qdev_prop_chr = {
     .size  = sizeof(CharDriverState*),
     .parse = parse_chr,
     .print = print_chr,
+    .get   = get_generic,
+    .set   = set_generic,
 };
 
 /* --- netdev device --- */
@@ -441,6 +729,8 @@ PropertyInfo qdev_prop_netdev = {
     .size  = sizeof(VLANClientState*),
     .parse = parse_netdev,
     .print = print_netdev,
+    .get   = get_generic,
+    .set   = set_generic,
 };
 
 /* --- vlan --- */
@@ -469,12 +759,57 @@ static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
     }
 }
 
+static void get_vlan(DeviceState *dev, Visitor *v, void *opaque,
+                     const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    VLANState **ptr = qdev_get_prop_ptr(dev, prop);
+    int64_t id;
+
+    id = *ptr ? (*ptr)->id : -1;
+    visit_type_int(v, &id, name, errp);
+}
+
+static void set_vlan(DeviceState *dev, Visitor *v, void *opaque,
+                     const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    VLANState **ptr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    int64_t id;
+    VLANState *vlan;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_int(v, &id, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    if (id == -1) {
+        *ptr = NULL;
+        return;
+    }
+    vlan = qemu_find_vlan(id, 1);
+    if (!vlan) {
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE,
+                  name, prop->info->name);
+        return;
+    }
+    *ptr = vlan;
+}
+
 PropertyInfo qdev_prop_vlan = {
     .name  = "vlan",
     .type  = PROP_TYPE_VLAN,
     .size  = sizeof(VLANClientState*),
     .parse = parse_vlan,
     .print = print_vlan,
+    .get   = get_vlan,
+    .set   = set_vlan,
 };
 
 /* --- pointer --- */
@@ -531,6 +866,8 @@ PropertyInfo qdev_prop_macaddr = {
     .size  = sizeof(MACAddr),
     .parse = parse_mac,
     .print = print_mac,
+    .get   = get_generic,
+    .set   = set_generic,
 };
 
 /* --- pci address --- */
@@ -570,12 +907,29 @@ static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t
     }
 }
 
+static void get_pci_devfn(DeviceState *dev, Visitor *v, void *opaque,
+                          const char *name, Error **errp)
+{
+    Property *prop = opaque;
+    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
+    char buffer[32];
+    char *p = buffer;
+
+    buffer[0] = 0;
+    if (*ptr != -1) {
+        snprintf(buffer, sizeof(buffer), "%02x.%x", *ptr >> 3, *ptr & 7);
+    }
+    visit_type_str(v, &p, name, errp);
+}
+
 PropertyInfo qdev_prop_pci_devfn = {
     .name  = "pci-devfn",
     .type  = PROP_TYPE_UINT32,
     .size  = sizeof(uint32_t),
     .parse = parse_pci_devfn,
     .print = print_pci_devfn,
+    .get   = get_pci_devfn,
+    .set   = set_generic,
 };
 
 /* --- public helpers --- */
diff --git a/hw/qdev.h b/hw/qdev.h
index 94f5ce9..42495ae 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -158,9 +158,13 @@ struct PropertyInfo {
     const char *name;
     size_t size;
     enum PropertyType type;
+    int64_t min;
+    int64_t max;
     int (*parse)(DeviceState *dev, Property *prop, const char *str);
     int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
     void (*free)(DeviceState *dev, Property *prop);
+    DevicePropertyAccessor *get;
+    DevicePropertyAccessor *set;
 };
 
 typedef struct GlobalProperty {
commit 6aced82c4f304c47d7affb8371edda093b11c81a
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sun Dec 18 17:05:08 2011 +0100

    qom: introduce QERR_PROPERTY_VALUE_OUT_OF_RANGE
    
    This will be used when reject invalid values for integer fields that
    are less than 64-bits wide.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qerror.c b/qerror.c
index adde8a5..9a75d06 100644
--- a/qerror.c
+++ b/qerror.c
@@ -206,6 +206,11 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Property '%(device).%(property)' can't find value '%(value)'",
     },
     {
+        .error_fmt = QERR_PROPERTY_VALUE_OUT_OF_RANGE,
+        .desc      = "Property '%(device).%(property)' doesn't take "
+                     "value %(value) (minimum: %(min), maximum: %(max)'",
+    },
+    {
         .error_fmt = QERR_QMP_BAD_INPUT_OBJECT,
         .desc      = "Expected '%(expected)' in QMP input",
     },
diff --git a/qerror.h b/qerror.h
index 9190b02..efda232 100644
--- a/qerror.h
+++ b/qerror.h
@@ -171,6 +171,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_PROPERTY_VALUE_NOT_FOUND \
     "{ 'class': 'PropertyValueNotFound', 'data': { 'device': %s, 'property': %s, 'value': %s } }"
 
+#define QERR_PROPERTY_VALUE_OUT_OF_RANGE \
+    "{ 'class': 'PropertyValueOutOfRange', 'data': { 'device': %s, 'property': %s, 'value': %"PRId64", 'min': %"PRId64", 'max': %"PRId64" } }"
+
 #define QERR_QMP_BAD_INPUT_OBJECT \
     "{ 'class': 'QMPBadInputObject', 'data': { 'expected': %s } }"
 
commit 7db4c4e8e53fc6fe9fee3fe6f6e822f7f1549352
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sun Dec 18 17:05:07 2011 +0100

    qom: interpret the return value when setting legacy properties
    
    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 f0b811c..de618f2 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -614,6 +614,28 @@ int qdev_prop_exists(DeviceState *dev, const char *name)
     return qdev_prop_find(dev, name) ? true : false;
 }
 
+void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
+                                    Property *prop, const char *value)
+{
+    switch (ret) {
+    case -EEXIST:
+        error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
+                  dev->info->name, prop->name, value);
+        break;
+    default:
+    case -EINVAL:
+        error_set(errp, QERR_PROPERTY_VALUE_BAD,
+                  dev->info->name, prop->name, value);
+        break;
+    case -ENOENT:
+        error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
+                  dev->info->name, prop->name, value);
+        break;
+    case 0:
+        break;
+    }
+}
+
 int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
 {
     Property *prop;
@@ -632,21 +654,10 @@ int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
     }
     ret = prop->info->parse(dev, prop, value);
     if (ret < 0) {
-        switch (ret) {
-        case -EEXIST:
-            qerror_report(QERR_PROPERTY_VALUE_IN_USE,
-                          dev->info->name, name, value);
-            break;
-        default:
-        case -EINVAL:
-            qerror_report(QERR_PROPERTY_VALUE_BAD,
-                          dev->info->name, name, value);
-            break;
-        case -ENOENT:
-            qerror_report(QERR_PROPERTY_VALUE_NOT_FOUND,
-                          dev->info->name, name, value);
-            break;
-        }
+        Error *err;
+        error_set_from_qdev_prop_error(&err, ret, dev, prop, value);
+        qerror_report_err(err);
+        error_free(err);
         return -1;
     }
     return 0;
diff --git a/hw/qdev.c b/hw/qdev.c
index c020a6f..2a146f7 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -1162,10 +1162,7 @@ static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
     }
 
     ret = prop->info->parse(dev, prop, ptr);
-    if (ret != 0) {
-        error_set(errp, QERR_INVALID_PARAMETER_VALUE,
-                  name, prop->info->name);
-    }
+    error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
     g_free(ptr);
 }
 
diff --git a/hw/qdev.h b/hw/qdev.h
index 6e18427..94f5ce9 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -370,6 +370,8 @@ void qdev_prop_set_defaults(DeviceState *dev, Property *props);
 
 void qdev_prop_register_global_list(GlobalProperty *props);
 void qdev_prop_set_globals(DeviceState *dev);
+void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
+                                    Property *prop, const char *value);
 
 static inline const char *qdev_fw_name(DeviceState *dev)
 {
commit e3cb6ba65d265f2cc1313ee26e879407ff24663c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sun Dec 18 17:05:06 2011 +0100

    qom: push permission checks up into qdev_property_add_legacy
    
    qdev_property_get and qdev_property_set can generate permission
    denied errors themselves.  Do not duplicate this functionality in
    qdev_get/set_legacy_property, and clean up excessive indentation.
    
    Reviewed-by: Anthony Liguori <anthony at codemonkey.ws>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index bda8d6c..c020a6f 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -1135,46 +1135,38 @@ static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
 {
     Property *prop = opaque;
 
-    if (prop->info->print) {
-        char buffer[1024];
-        char *ptr = buffer;
+    char buffer[1024];
+    char *ptr = buffer;
 
-        prop->info->print(dev, prop, buffer, sizeof(buffer));
-        visit_type_str(v, &ptr, name, errp);
-    } else {
-        error_set(errp, QERR_PERMISSION_DENIED);
-    }
+    prop->info->print(dev, prop, buffer, sizeof(buffer));
+    visit_type_str(v, &ptr, name, errp);
 }
 
 static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
                                      const char *name, Error **errp)
 {
     Property *prop = opaque;
+    Error *local_err = NULL;
+    char *ptr = NULL;
+    int ret;
 
     if (dev->state != DEV_STATE_CREATED) {
         error_set(errp, QERR_PERMISSION_DENIED);
         return;
     }
 
-    if (prop->info->parse) {
-        Error *local_err = NULL;
-        char *ptr = NULL;
+    visit_type_str(v, &ptr, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
 
-        visit_type_str(v, &ptr, name, &local_err);
-        if (!local_err) {
-            int ret;
-            ret = prop->info->parse(dev, prop, ptr);
-            if (ret != 0) {
-                error_set(errp, QERR_INVALID_PARAMETER_VALUE,
-                          name, prop->info->name);
-            }
-            g_free(ptr);
-        } else {
-            error_propagate(errp, local_err);
-        }
-    } else {
-        error_set(errp, QERR_PERMISSION_DENIED);
+    ret = prop->info->parse(dev, prop, ptr);
+    if (ret != 0) {
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE,
+                  name, prop->info->name);
     }
+    g_free(ptr);
 }
 
 /**
@@ -1194,8 +1186,8 @@ void qdev_property_add_legacy(DeviceState *dev, Property *prop,
     type = g_strdup_printf("legacy<%s>", prop->info->name);
 
     qdev_property_add(dev, prop->name, type,
-                      qdev_get_legacy_property,
-                      qdev_set_legacy_property,
+                      prop->info->print ? qdev_get_legacy_property : NULL,
+                      prop->info->parse ? qdev_set_legacy_property : NULL,
                       NULL,
                       prop, errp);
 
commit 0d41d9aabbed72750ca41e94ce1fda94dd1919d1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sun Dec 18 17:05:05 2011 +0100

    qom: fix swapped parameters
    
    Reviewed-by: Anthony Liguori <anthony at codemonkey.ws>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 83913c7..bda8d6c 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -1110,7 +1110,7 @@ void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
     if (!prop->set) {
         error_set(errp, QERR_PERMISSION_DENIED);
     } else {
-        prop->set(dev, prop->opaque, v, name, errp);
+        prop->set(dev, v, prop->opaque, name, errp);
     }
 }
 
commit 47c6d3ecdfc3fc354cf996f873a9f854c2325160
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sun Dec 18 17:05:04 2011 +0100

    qapi: protect against NULL QObject in qmp_input_get_object
    
    A NULL qobj can occur when a parameter is fetched via qdict_get, but
    the parameter is not in the command.  By returning NULL, the caller can
    choose whether to raise a missing parameter error, an invalid parameter
    type error, or use a default value.  For example, qom-set could can
    use this to reset a property to its default value, though at this time
    it will fail with "Invalid parameter type".  In any case, anything is
    better than crashing!
    
    Reviewed-by: Anthony Liguori <anthony at codemonkey.ws>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index 8cbc0ab..c78022b 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -49,10 +49,12 @@ static const QObject *qmp_input_get_object(QmpInputVisitor *qiv,
         qobj = qiv->stack[qiv->nb_stack - 1].obj;
     }
 
-    if (name && qobject_type(qobj) == QTYPE_QDICT) {
-        return qdict_get(qobject_to_qdict(qobj), name);
-    } else if (qiv->nb_stack > 0 && qobject_type(qobj) == QTYPE_QLIST) {
-        return qlist_entry_obj(qiv->stack[qiv->nb_stack - 1].entry);
+    if (qobj) {
+        if (name && qobject_type(qobj) == QTYPE_QDICT) {
+            return qdict_get(qobject_to_qdict(qobj), name);
+        } else if (qiv->nb_stack > 0 && qobject_type(qobj) == QTYPE_QLIST) {
+            return qlist_entry_obj(qiv->stack[qiv->nb_stack - 1].entry);
+        }
     }
 
     return qobj;
commit b1746dddfc94f9c98b9b9c1a6f25c064f0f58a5a
Author: Michael Ellerman <michael at ellerman.id.au>
Date:   Mon Dec 19 17:19:32 2011 +1100

    Documentation: Move balloon option out of i386 only section
    
    The balloon option is not i386 only, so move it into the standard
    options section.
    
    Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index 749aee1..a60191f 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -456,6 +456,19 @@ modprobe i810_audio clocking=48000
 @end example
 ETEXI
 
+DEF("balloon", HAS_ARG, QEMU_OPTION_balloon,
+    "-balloon none   disable balloon device\n"
+    "-balloon virtio[,addr=str]\n"
+    "                enable virtio balloon device (default)\n", QEMU_ARCH_ALL)
+STEXI
+ at item -balloon none
+ at findex -balloon
+Disable balloon device.
+ at item -balloon virtio[,addr=@var{addr}]
+Enable virtio balloon device (default), optionally with PCI address
+ at var{addr}.
+ETEXI
+
 STEXI
 @end table
 ETEXI
@@ -1120,19 +1133,6 @@ STEXI
 Disable HPET support.
 ETEXI
 
-DEF("balloon", HAS_ARG, QEMU_OPTION_balloon,
-    "-balloon none   disable balloon device\n"
-    "-balloon virtio[,addr=str]\n"
-    "                enable virtio balloon device (default)\n", QEMU_ARCH_ALL)
-STEXI
- at item -balloon none
- at findex -balloon
-Disable balloon device.
- at item -balloon virtio[,addr=@var{addr}]
-Enable virtio balloon device (default), optionally with PCI address
- at var{addr}.
-ETEXI
-
 DEF("acpitable", HAS_ARG, QEMU_OPTION_acpitable,
     "-acpitable [sig=str][,rev=n][,oem_id=str][,oem_table_id=str][,oem_rev=n][,asl_compiler_id=str][,asl_compiler_rev=n][,{data|file}=file1[:file2]...]\n"
     "                ACPI table description\n", QEMU_ARCH_I386)
commit a3adb7ad3bd9c517d569e7e23b249e7f7d616015
Author: Michael Ellerman <michael at ellerman.id.au>
Date:   Mon Dec 19 17:19:31 2011 +1100

    vl.c: In qemu -h output, only print options for the arch we are running as
    
    Only print options in the help output that are accepted by our arch.
    This is less confusing for users and also for other programs that
    consume the help output.
    
    The options affected are:
    
     -g and -prom-env only displayed on PPC or SPARC
    
     -win2k-hack, -rtc-td-hack, -no-fd-bootchk, -no-acpi, -no-hpet,
     -acpitable, -smbios only displayed on i386
    
     -semihosting only displayed on ARM, M68K or XTENSA
    
     -old-param only displayed on ARM
    
    Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-options-wrapper.h b/qemu-options-wrapper.h
index 202f5af..13bfea0 100644
--- a/qemu-options-wrapper.h
+++ b/qemu-options-wrapper.h
@@ -4,18 +4,26 @@
 #define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)     \
     opt_enum,
 #define DEFHEADING(text)
+#define ARCHHEADING(text, arch_mask)
 
 #elif defined(QEMU_OPTIONS_GENERATE_HELP)
 
-#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)     \
-        opt_help
-#define DEFHEADING(text) stringify(text) "\n"
+#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)    \
+    if ((arch_mask) & arch_type)                               \
+        fputs(opt_help, stdout);
+
+#define ARCHHEADING(text, arch_mask) \
+    if ((arch_mask) & arch_type)    \
+        puts(stringify(text));
+
+#define DEFHEADING(text) ARCHHEADING(text, QEMU_ARCH_ALL)
 
 #elif defined(QEMU_OPTIONS_GENERATE_OPTIONS)
 
 #define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)     \
     { option, opt_arg, opt_enum, arch_mask },
 #define DEFHEADING(text)
+#define ARCHHEADING(text, arch_mask)
 
 #else
 #error "qemu-options-wrapper.h included with no option defined"
@@ -25,6 +33,7 @@
 
 #undef DEF
 #undef DEFHEADING
+#undef ARCHHEADING
 #undef GEN_DOCS
 
 #undef QEMU_OPTIONS_GENERATE_ENUM
diff --git a/qemu-options.hx b/qemu-options.hx
index 087a3b9..749aee1 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1070,9 +1070,9 @@ STEXI
 @end table
 ETEXI
 
-DEFHEADING()
+ARCHHEADING(, QEMU_ARCH_I386)
 
-DEFHEADING(i386 target only:)
+ARCHHEADING(i386 target only:, QEMU_ARCH_I386)
 STEXI
 @table @option
 ETEXI
diff --git a/scripts/hxtool b/scripts/hxtool
index 7ca83ed..995bb7f 100644
--- a/scripts/hxtool
+++ b/scripts/hxtool
@@ -47,6 +47,9 @@ hxtotexi()
             DEFHEADING*)
             echo "$(expr "$str" : "DEFHEADING(\(.*\))")"
             ;;
+            ARCHHEADING*)
+            echo "$(expr "$str" : "ARCHHEADING(\(.*\),.*)")"
+            ;;
             *)
             test $flag -eq 1 && echo "$str"
             ;;
diff --git a/vl.c b/vl.c
index 25ec37b..da69f94 100644
--- a/vl.c
+++ b/vl.c
@@ -1492,24 +1492,21 @@ static void version(void)
 
 static void help(int exitcode)
 {
-    const char *options_help =
+    version();
+    printf("usage: %s [options] [disk_image]\n\n"
+           "'disk_image' is a raw hard disk image for IDE hard disk 0\n\n",
+            error_get_progname());
+
 #define QEMU_OPTIONS_GENERATE_HELP
 #include "qemu-options-wrapper.h"
-        ;
-    version();
-    printf("usage: %s [options] [disk_image]\n"
-           "\n"
-           "'disk_image' is a raw hard disk image for IDE hard disk 0\n"
-           "\n"
-           "%s\n"
-           "During emulation, the following keys are useful:\n"
+
+    printf("\nDuring emulation, the following keys are useful:\n"
            "ctrl-alt-f      toggle full screen\n"
            "ctrl-alt-n      switch to virtual console 'n'\n"
            "ctrl-alt        toggle mouse and keyboard grab\n"
            "\n"
-           "When using -nographic, press 'ctrl-a h' to get some help.\n",
-           error_get_progname(),
-           options_help);
+           "When using -nographic, press 'ctrl-a h' to get some help.\n");
+
     exit(exitcode);
 }
 
commit 77bd1119ba43dbd0e73014037a08f8b49136bf6f
Author: Michael Ellerman <michael at ellerman.id.au>
Date:   Mon Dec 19 17:19:30 2011 +1100

    vl.c: Move option generation logic into a wrapper file
    
    In vl.c and qemu-options.h we define macros and include qemu-options.def
    in order to generate different content. Move the bulk of the def'ing and
    undef'ing into a wrapper, this will make it cleaner when we add another
    macro in the next patch.
    
    AFAICS undefining GEN_DOCS services no purpose, but I've left it for now.
    
    Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-options-wrapper.h b/qemu-options-wrapper.h
new file mode 100644
index 0000000..202f5af
--- /dev/null
+++ b/qemu-options-wrapper.h
@@ -0,0 +1,32 @@
+
+#if defined(QEMU_OPTIONS_GENERATE_ENUM)
+
+#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)     \
+    opt_enum,
+#define DEFHEADING(text)
+
+#elif defined(QEMU_OPTIONS_GENERATE_HELP)
+
+#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)     \
+        opt_help
+#define DEFHEADING(text) stringify(text) "\n"
+
+#elif defined(QEMU_OPTIONS_GENERATE_OPTIONS)
+
+#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)     \
+    { option, opt_arg, opt_enum, arch_mask },
+#define DEFHEADING(text)
+
+#else
+#error "qemu-options-wrapper.h included with no option defined"
+#endif
+
+#include "qemu-options.def"
+
+#undef DEF
+#undef DEFHEADING
+#undef GEN_DOCS
+
+#undef QEMU_OPTIONS_GENERATE_ENUM
+#undef QEMU_OPTIONS_GENERATE_HELP
+#undef QEMU_OPTIONS_GENERATE_OPTIONS
diff --git a/qemu-options.h b/qemu-options.h
index c96f994..89a009e 100644
--- a/qemu-options.h
+++ b/qemu-options.h
@@ -29,13 +29,8 @@
 #define _QEMU_OPTIONS_H_
 
 enum {
-#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)     \
-    opt_enum,
-#define DEFHEADING(text)
-#include "qemu-options.def"
-#undef DEF
-#undef DEFHEADING
-#undef GEN_DOCS
+#define QEMU_OPTIONS_GENERATE_ENUM
+#include "qemu-options-wrapper.h"
 };
 
 #endif
diff --git a/vl.c b/vl.c
index d51ac2e..25ec37b 100644
--- a/vl.c
+++ b/vl.c
@@ -1493,13 +1493,8 @@ static void version(void)
 static void help(int exitcode)
 {
     const char *options_help =
-#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)     \
-        opt_help
-#define DEFHEADING(text) stringify(text) "\n"
-#include "qemu-options.def"
-#undef DEF
-#undef DEFHEADING
-#undef GEN_DOCS
+#define QEMU_OPTIONS_GENERATE_HELP
+#include "qemu-options-wrapper.h"
         ;
     version();
     printf("usage: %s [options] [disk_image]\n"
@@ -1529,13 +1524,8 @@ typedef struct QEMUOption {
 
 static const QEMUOption qemu_options[] = {
     { "h", 0, QEMU_OPTION_h, QEMU_ARCH_ALL },
-#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)     \
-    { option, opt_arg, opt_enum, arch_mask },
-#define DEFHEADING(text)
-#include "qemu-options.def"
-#undef DEF
-#undef DEFHEADING
-#undef GEN_DOCS
+#define QEMU_OPTIONS_GENERATE_OPTIONS
+#include "qemu-options-wrapper.h"
     { NULL },
 };
 static void select_vgahw (const char *p)
commit f76d27b67ca05c7ee875e39b4f6e3d567d3e9292
Merge: 4a1cc68... 67d95c1...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 19 09:45:17 2011 -0600

    Merge remote-tracking branch 'qemu-kvm/memory/exec-obsolete' into staging

diff --cc memory.c
index 37e4f09,cbd6988..a7e615a
--- a/memory.c
+++ b/memory.c
@@@ -18,8 -18,10 +18,11 @@@
  #include "kvm.h"
  #include <assert.h>
  
+ #define WANT_EXEC_OBSOLETE
+ #include "exec-obsolete.h"
+ 
  unsigned memory_region_transaction_depth = 0;
 +static bool memory_region_update_pending = false;
  
  typedef struct AddrRange AddrRange;
  
commit 4a1cc6800a54b154a214e7ecf36c63c8c81f2074
Merge: cde7fc3... ce76b8a...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 19 09:45:12 2011 -0600

    Merge remote-tracking branch 'qemu-kvm/memory/xen' into staging

commit 67d95c153bef55f619615ea71a5c2d689db4fd4e
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Dec 15 15:25:22 2011 +0200

    memory: move obsolete exec.c functions to a private header
    
    This will help avoid accidental usage.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpu-common.h b/cpu-common.h
index 72eb731..8295e4f 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -38,37 +38,7 @@ typedef unsigned long ram_addr_t;
 typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
 typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
 
-void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
-                                      ram_addr_t size,
-                                      ram_addr_t phys_offset,
-                                      ram_addr_t region_offset,
-                                      bool log_dirty);
-
-static inline void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
-                                                       ram_addr_t size,
-                                                       ram_addr_t phys_offset,
-                                                       ram_addr_t region_offset)
-{
-    cpu_register_physical_memory_log(start_addr, size, phys_offset,
-                                     region_offset, false);
-}
-
-static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
-                                                ram_addr_t size,
-                                                ram_addr_t phys_offset)
-{
-    cpu_register_physical_memory_offset(start_addr, size, phys_offset, 0);
-}
-
 ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr);
-struct MemoryRegion;
-ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
-                                   ram_addr_t size, void *host,
-                                   struct MemoryRegion *mr);
-ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size,
-                          struct MemoryRegion *mr);
-void qemu_ram_free(ram_addr_t addr);
-void qemu_ram_free_from_ptr(ram_addr_t addr);
 void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
 /* This should only be used for ram local to a device.  */
 void *qemu_get_ram_ptr(ram_addr_t addr);
@@ -81,11 +51,6 @@ void qemu_put_ram_ptr(void *addr);
 int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr);
 ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);
 
-int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
-                           CPUWriteMemoryFunc * const *mem_write,
-                           void *opaque, enum device_endian endian);
-void cpu_unregister_io_memory(int table_address);
-
 void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                             int len, int is_write);
 static inline void cpu_physical_memory_read(target_phys_addr_t addr,
@@ -134,10 +99,6 @@ void cpu_unregister_phys_memory_client(CPUPhysMemoryClient *);
  * batching which can make a major impact on performance when using
  * virtualization.
  */
-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);
-
 void qemu_flush_coalesced_mmio_buffer(void);
 
 uint32_t ldub_phys(target_phys_addr_t addr);
diff --git a/exec-obsolete.h b/exec-obsolete.h
new file mode 100644
index 0000000..34b9fc5
--- /dev/null
+++ b/exec-obsolete.h
@@ -0,0 +1,68 @@
+/*
+ * Declarations for obsolete exec.c functions
+ *
+ * Copyright 2011 Red Hat, Inc. and/or its affiliates
+ *
+ * Authors:
+ *  Avi Kivity <avi at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+/*
+ * This header is for use by exec.c and memory.c ONLY.  Do not include it.
+ * The functions declared here will be removed soon.
+ */
+
+#ifndef EXEC_OBSOLETE_H
+#define EXEC_OBSOLETE_H
+
+#ifndef WANT_EXEC_OBSOLETE
+#error Do not include exec-obsolete.h
+#endif
+
+#ifndef CONFIG_USER_ONLY
+
+ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
+                                   ram_addr_t size, void *host,
+                                   MemoryRegion *mr);
+ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size,
+                          MemoryRegion *mr);
+void qemu_ram_free(ram_addr_t addr);
+void qemu_ram_free_from_ptr(ram_addr_t addr);
+
+int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
+                           CPUWriteMemoryFunc * const *mem_write,
+                           void *opaque, enum device_endian endian);
+void cpu_unregister_io_memory(int table_address);
+
+void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
+                                      ram_addr_t size,
+                                      ram_addr_t phys_offset,
+                                      ram_addr_t region_offset,
+                                      bool log_dirty);
+
+static inline void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
+                                                       ram_addr_t size,
+                                                       ram_addr_t phys_offset,
+                                                       ram_addr_t region_offset)
+{
+    cpu_register_physical_memory_log(start_addr, size, phys_offset,
+                                     region_offset, false);
+}
+
+static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
+                                                ram_addr_t size,
+                                                ram_addr_t phys_offset)
+{
+    cpu_register_physical_memory_offset(start_addr, size, phys_offset, 0);
+}
+
+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);
+
+#endif
+
+#endif
diff --git a/exec.c b/exec.c
index fbcb1bf..32782b4 100644
--- a/exec.c
+++ b/exec.c
@@ -57,6 +57,9 @@
 #include "trace.h"
 #endif
 
+#define WANT_EXEC_OBSOLETE
+#include "exec-obsolete.h"
+
 //#define DEBUG_TB_INVALIDATE
 //#define DEBUG_FLUSH
 //#define DEBUG_TLB
diff --git a/memory.c b/memory.c
index 1a42cea..cbd6988 100644
--- a/memory.c
+++ b/memory.c
@@ -18,6 +18,9 @@
 #include "kvm.h"
 #include <assert.h>
 
+#define WANT_EXEC_OBSOLETE
+#include "exec-obsolete.h"
+
 unsigned memory_region_transaction_depth = 0;
 
 typedef struct AddrRange AddrRange;
commit 0eeb06b0dd897826b04d3d0d6318b2fb8d271a92
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Dec 15 15:23:03 2011 +0200

    etraxfs_eth: drop bogus cpu_unregister_io_memory()
    
    Leftover call to cpu_unregister_io_memory() can segfault on cleanup.  Remove.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c
index 5ac2d15..b525258 100644
--- a/hw/etraxfs_eth.c
+++ b/hw/etraxfs_eth.c
@@ -323,7 +323,6 @@ struct fs_eth
 	MemoryRegion mmio;
 	NICState *nic;
 	NICConf conf;
-	int ethregs;
 
 	/* Two addrs in the filter.  */
 	uint8_t macaddr[2][6];
@@ -571,8 +570,6 @@ static void eth_cleanup(VLANClientState *nc)
 {
 	struct fs_eth *eth = DO_UPCAST(NICState, nc, nc)->opaque;
 
-        cpu_unregister_io_memory(eth->ethregs);
-
 	/* Disconnect the client.  */
 	eth->dma_out->client.push = NULL;
 	eth->dma_out->client.opaque = NULL;
commit ce76b8a8ab61255f9029b5244b885cb8bef60e97
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Dec 18 16:27:48 2011 +0200

    xen: convert to memory API
    
    Undo the private implementation of qemu_ram_alloc(); use the global one
    (which calls right back into xen_ram_alloc()).
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/xen-all.c b/xen-all.c
index b441fc1..bd89889 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -16,6 +16,7 @@
 #include "range.h"
 #include "xen-mapcache.h"
 #include "trace.h"
+#include "exec-memory.h"
 
 #include <xen/hvm/ioreq.h>
 #include <xen/hvm/params.h>
@@ -31,6 +32,8 @@
     do { } while (0)
 #endif
 
+static MemoryRegion ram_memory, ram_640k, ram_lo, ram_hi;
+
 /* Compatibility with older version */
 #if __XEN_LATEST_INTERFACE_VERSION__ < 0x0003020a
 static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
@@ -137,27 +140,18 @@ qemu_irq *xen_interrupt_controller_init(void)
 
 static void xen_ram_init(ram_addr_t ram_size)
 {
-    RAMBlock *new_block;
+    MemoryRegion *sysmem = get_system_memory();
     ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
+    ram_addr_t block_len;
 
-    new_block = g_malloc0(sizeof (*new_block));
-    pstrcpy(new_block->idstr, sizeof (new_block->idstr), "xen.ram");
-    new_block->host = NULL;
-    new_block->offset = 0;
-    new_block->length = ram_size;
+    block_len = ram_size;
     if (ram_size >= HVM_BELOW_4G_RAM_END) {
         /* Xen does not allocate the memory continuously, and keep a hole at
          * HVM_BELOW_4G_MMIO_START of HVM_BELOW_4G_MMIO_LENGTH
          */
-        new_block->length += HVM_BELOW_4G_MMIO_LENGTH;
+        block_len += HVM_BELOW_4G_MMIO_LENGTH;
     }
-
-    QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
-
-    ram_list.phys_dirty = g_realloc(ram_list.phys_dirty,
-                                       new_block->length >> TARGET_PAGE_BITS);
-    memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
-           0xff, new_block->length >> TARGET_PAGE_BITS);
+    memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len);
 
     if (ram_size >= HVM_BELOW_4G_RAM_END) {
         above_4g_mem_size = ram_size - HVM_BELOW_4G_RAM_END;
@@ -166,18 +160,23 @@ static void xen_ram_init(ram_addr_t ram_size)
         below_4g_mem_size = ram_size;
     }
 
-    cpu_register_physical_memory(0, 0xa0000, 0);
+    memory_region_init_alias(&ram_640k, "xen.ram.640k",
+                             &ram_memory, 0, 0xa0000);
+    memory_region_add_subregion(sysmem, 0, &ram_640k);
     /* Skip of the VGA IO memory space, it will be registered later by the VGA
      * emulated device.
      *
      * The area between 0xc0000 and 0x100000 will be used by SeaBIOS to load
      * the Options ROM, so it is registered here as RAM.
      */
-    cpu_register_physical_memory(0xc0000, below_4g_mem_size - 0xc0000,
-                                 0xc0000);
+    memory_region_init_alias(&ram_lo, "xen.ram.lo",
+                             &ram_memory, 0xc0000, below_4g_mem_size - 0xc0000);
+    memory_region_add_subregion(sysmem, 0xc0000, &ram_lo);
     if (above_4g_mem_size > 0) {
-        cpu_register_physical_memory(0x100000000ULL, above_4g_mem_size,
-                                     0x100000000ULL);
+        memory_region_init_alias(&ram_hi, "xen.ram.hi",
+                                 &ram_memory, 0x100000000ULL,
+                                 above_4g_mem_size);
+        memory_region_add_subregion(sysmem, 0x100000000ULL, &ram_hi);
     }
 }
 
@@ -187,6 +186,10 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
     xen_pfn_t *pfn_list;
     int i;
 
+    if (mr == &ram_memory) {
+        return;
+    }
+
     trace_xen_ram_alloc(ram_addr, size);
 
     nr_pfn = size >> TARGET_PAGE_BITS;
commit fce537d4a741521ac182d54465c568b101b9a71e
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Dec 18 15:48:55 2011 +0200

    memory, xen: pass MemoryRegion to xen_ram_alloc()
    
    Currently xen_ram_alloc() relies on ram_addr, which is going away.
    Give it something else to use as a cookie.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpu-common.h b/cpu-common.h
index 48f4c01..72eb731 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -61,9 +61,12 @@ static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
 }
 
 ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr);
+struct MemoryRegion;
 ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
-                        ram_addr_t size, void *host);
-ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size);
+                                   ram_addr_t size, void *host,
+                                   struct MemoryRegion *mr);
+ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size,
+                          struct MemoryRegion *mr);
 void qemu_ram_free(ram_addr_t addr);
 void qemu_ram_free_from_ptr(ram_addr_t addr);
 void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
diff --git a/exec.c b/exec.c
index 06889bd..fbcb1bf 100644
--- a/exec.c
+++ b/exec.c
@@ -2916,7 +2916,8 @@ static ram_addr_t last_ram_offset(void)
 }
 
 ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
-                                   ram_addr_t size, void *host)
+                                   ram_addr_t size, void *host,
+                                   MemoryRegion *mr)
 {
     RAMBlock *new_block, *block;
 
@@ -2972,7 +2973,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
             }
 #else
             if (xen_enabled()) {
-                xen_ram_alloc(new_block->offset, size);
+                xen_ram_alloc(new_block->offset, size, mr);
             } else {
                 new_block->host = qemu_vmalloc(size);
             }
@@ -2995,9 +2996,10 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
     return new_block->offset;
 }
 
-ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
+ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size,
+                          MemoryRegion *mr)
 {
-    return qemu_ram_alloc_from_ptr(dev, name, size, NULL);
+    return qemu_ram_alloc_from_ptr(dev, name, size, NULL, mr);
 }
 
 void qemu_ram_free_from_ptr(ram_addr_t addr)
diff --git a/hw/xen.h b/hw/xen.h
index 2162111..f9f66e8 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -44,7 +44,9 @@ void xen_vcpu_init(void);
 void xenstore_store_pv_console_info(int i, struct CharDriverState *chr);
 
 #if defined(NEED_CPU_H) && !defined(CONFIG_USER_ONLY)
-void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size);
+struct MemoryRegion;
+void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size,
+                   struct MemoryRegion *mr);
 #endif
 
 #if defined(CONFIG_XEN) && CONFIG_XEN_CTRL_INTERFACE_VERSION < 400
diff --git a/memory.c b/memory.c
index adfdf14..1a42cea 100644
--- a/memory.c
+++ b/memory.c
@@ -982,7 +982,7 @@ void memory_region_init_ram(MemoryRegion *mr,
     memory_region_init(mr, name, size);
     mr->terminates = true;
     mr->destructor = memory_region_destructor_ram;
-    mr->ram_addr = qemu_ram_alloc(dev, name, size);
+    mr->ram_addr = qemu_ram_alloc(dev, name, size, mr);
     mr->backend_registered = true;
 }
 
@@ -995,7 +995,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr,
     memory_region_init(mr, name, size);
     mr->terminates = true;
     mr->destructor = memory_region_destructor_ram_from_ptr;
-    mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr);
+    mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr, mr);
     mr->backend_registered = true;
 }
 
@@ -1022,7 +1022,7 @@ void memory_region_init_rom_device(MemoryRegion *mr,
     mr->opaque = opaque;
     mr->terminates = true;
     mr->destructor = memory_region_destructor_rom_device;
-    mr->ram_addr = qemu_ram_alloc(dev, name, size);
+    mr->ram_addr = qemu_ram_alloc(dev, name, size, mr);
     mr->ram_addr |= cpu_register_io_memory(memory_region_read_thunk,
                                            memory_region_write_thunk,
                                            mr,
diff --git a/xen-all.c b/xen-all.c
index b5e28ab..b441fc1 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -181,7 +181,7 @@ static void xen_ram_init(ram_addr_t ram_size)
     }
 }
 
-void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size)
+void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
 {
     unsigned long nr_pfn;
     xen_pfn_t *pfn_list;
diff --git a/xen-stub.c b/xen-stub.c
index efe2ab5..5fa400f 100644
--- a/xen-stub.c
+++ b/xen-stub.c
@@ -8,6 +8,7 @@
 
 #include "qemu-common.h"
 #include "hw/xen.h"
+#include "memory.h"
 
 void xenstore_store_pv_console_info(int i, CharDriverState *chr)
 {
@@ -30,7 +31,7 @@ void xen_cmos_set_s3_resume(void *opaque, int irq, int level)
 {
 }
 
-void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size)
+void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
 {
 }
 
commit cde7fc31dee7a7bac96779f77a21825b187871d3
Merge: 3cfdd0d... a6c5c07...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 19 09:12:25 2011 -0600

    Merge remote-tracking branch 'qemu-kvm/memory/mutators' into staging
    
    Conflicts:
    	memory.h

diff --cc memory.h
index beae127,c07bcca..fe643ff
--- a/memory.h
+++ b/memory.h
@@@ -501,17 -502,50 +502,55 @@@ void memory_region_add_subregion_overla
  void memory_region_del_subregion(MemoryRegion *mr,
                                   MemoryRegion *subregion);
  
 -
+ /*
+  * memory_region_set_enabled: dynamically enable or disable a region
+  *
+  * Enables or disables a memory region.  A disabled memory region
+  * ignores all accesses to itself and its subregions.  It does not
+  * obscure sibling subregions with lower priority - it simply behaves as
+  * if it was removed from the hierarchy.
+  *
+  * Regions default to being enabled.
+  *
+  * @mr: the region to be updated
+  * @enabled: whether to enable or disable the region
+  */
+ void memory_region_set_enabled(MemoryRegion *mr, bool enabled);
+ 
+ /*
+  * memory_region_set_address: dynamically update the address of a region
+  *
+  * Dynamically updates the address of a region, relative to its parent.
+  * May be used on regions are currently part of a memory hierarchy.
+  *
+  * @mr: the region to be updated
+  * @addr: new address, relative to parent region
+  */
+ void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr);
+ 
+ /*
+  * memory_region_set_alias_offset: dynamically update a memory alias's offset
+  *
+  * Dynamically updates the offset into the target region that an alias points
+  * to, as if the fourth argument to memory_region_init_alias() has changed.
+  *
+  * @mr: the #MemoryRegion to be updated; should be an alias.
+  * @offset: the new offset into the target memory region
+  */
+ void memory_region_set_alias_offset(MemoryRegion *mr,
+                                     target_phys_addr_t offset);
+ 
 -/* Start a transaction; changes will be accumulated and made visible only
 - * when the transaction ends.
 +/**
 + * memory_region_transaction_begin: Start a transaction.
 + *
 + * During a transaction, changes will be accumulated and made visible
 + * only when the transaction ends (is commited).
   */
  void memory_region_transaction_begin(void);
 -/* Commit a transaction and make changes visible to the guest.
 +
 +/**
 + * memory_region_transaction_commit: Commit a transaction and make changes
 + *                                   visible to the guest.
   */
  void memory_region_transaction_commit(void);
  
commit 3cfdd0da7e513e740b759a2abec49db3c086d6e2
Merge: ddf83d0... 50ced5b...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 19 09:10:49 2011 -0600

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging

commit ddf83d0173c6a64a95a6640e4bfcea4cd789cad2
Merge: ea830eb... bd83b36...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 19 08:50:47 2011 -0600

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

commit ea830ebb74461c5ad6d199857fb000d2e0284c69
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Sun Dec 18 13:07:03 2011 -0600

    pc: fix event_idx compatibility for virtio devices
    
    event_idx was introduced in 0.15 and must be disabled for all virtio-pci devices
    (including virtio-balloon-pci).
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 265ccb2..b9bb09d 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -343,6 +343,22 @@ static QEMUMachine pc_machine_v0_14 = {
             .driver   = "qxl-vga",
             .property = "revision",
             .value    = stringify(2),
+        },{
+            .driver   = "virtio-blk-pci",
+            .property = "event_idx",
+            .value    = "off",
+        },{
+            .driver   = "virtio-serial-pci",
+            .property = "event_idx",
+            .value    = "off",
+        },{
+            .driver   = "virtio-net-pci",
+            .property = "event_idx",
+            .value    = "off",
+        },{
+            .driver   = "virtio-balloon-pci",
+            .property = "event_idx",
+            .value    = "off",
         },
         { /* end of list */ }
     },
@@ -383,6 +399,10 @@ static QEMUMachine pc_machine_v0_13 = {
             .property = "event_idx",
             .value    = "off",
         },{
+            .driver   = "virtio-balloon-pci",
+            .property = "event_idx",
+            .value    = "off",
+        },{
             .driver   = "AC97",
             .property = "use_broken_id",
             .value    = stringify(1),
@@ -430,6 +450,10 @@ static QEMUMachine pc_machine_v0_12 = {
             .property = "event_idx",
             .value    = "off",
         },{
+            .driver   = "virtio-balloon-pci",
+            .property = "event_idx",
+            .value    = "off",
+        },{
             .driver   = "AC97",
             .property = "use_broken_id",
             .value    = stringify(1),
@@ -485,6 +509,10 @@ static QEMUMachine pc_machine_v0_11 = {
             .property = "event_idx",
             .value    = "off",
         },{
+            .driver   = "virtio-balloon-pci",
+            .property = "event_idx",
+            .value    = "off",
+        },{
             .driver   = "AC97",
             .property = "use_broken_id",
             .value    = stringify(1),
@@ -552,6 +580,10 @@ static QEMUMachine pc_machine_v0_10 = {
             .property = "event_idx",
             .value    = "off",
         },{
+            .driver   = "virtio-balloon-pci",
+            .property = "event_idx",
+            .value    = "off",
+        },{
             .driver   = "AC97",
             .property = "use_broken_id",
             .value    = stringify(1),
commit 50ced5b3b108aba7f9b2c8e6f7de4e924f30f83b
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 17 09:27:39 2011 +0100

    configure: Improve Xen autodetection for hosts without Xen
    
    With this patch, it only takes one test (instead of four)
    to detect that there is no Xen support at all.
    
    For most build hosts, this will reduce the time configure needs.
    It will also reduce noisy output in config.log.
    
    Build hosts with Xen now need up to five (instead of up to four)
    tests. They get improved diagnostics when Xen support fails.
    
    Cc: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    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 36ee849..640e815 100755
--- a/configure
+++ b/configure
@@ -1317,10 +1317,30 @@ fi
 if test "$xen" != "no" ; then
   xen_libs="-lxenstore -lxenctrl -lxenguest"
 
-  # Xen unstable
+  # First we test whether Xen headers and libraries are available.
+  # If no, we are done and there is no Xen support.
+  # If yes, more tests are run to detect the Xen version.
+
+  # Xen (any)
   cat > $TMPC <<EOF
 #include <xenctrl.h>
 #include <xs.h>
+int main(void) {
+  return 0;
+}
+EOF
+  if ! compile_prog "" "$xen_libs" ; then
+    # Xen not found
+    if test "$xen" = "yes" ; then
+      feature_not_found "xen"
+    fi
+    xen=no
+
+  # Xen unstable
+  elif (
+      cat > $TMPC <<EOF
+#include <xenctrl.h>
+#include <xs.h>
 #include <stdint.h>
 #include <xen/hvm/hvm_info_table.h>
 #if !defined(HVM_MAX_VCPUS)
@@ -1336,7 +1356,8 @@ int main(void) {
   return 0;
 }
 EOF
-  if compile_prog "" "$xen_libs" ; then
+      compile_prog "" "$xen_libs"
+    ) ; then
     xen_ctrl_version=410
     xen=yes
 
@@ -1407,10 +1428,10 @@ EOF
     xen_ctrl_version=330
     xen=yes
 
-  # Xen not found or unsupported
+  # Xen version unsupported
   else
     if test "$xen" = "yes" ; then
-      feature_not_found "xen"
+      feature_not_found "xen (unsupported version)"
     fi
     xen=no
   fi
commit 84972cbb06046ad7b60e9c388509b9b96fa0510d
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 17 09:27:38 2011 +0100

    configure: Fix compiler warnings in config.log (statement without effect)
    
    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 bd6f10f..36ee849 100755
--- a/configure
+++ b/configure
@@ -2074,7 +2074,7 @@ cat > $TMPC <<EOF
 #include <sys/types.h>
 #include <sys/uio.h>
 #include <unistd.h>
-int main(void) { preadv; }
+int main(void) { return preadv == preadv; }
 EOF
 preadv=no
 if compile_prog "" "" ; then
@@ -2107,7 +2107,7 @@ if test "$opengl" != "no" ; then
 #include <X11/Xlib.h>
 #include <GL/gl.h>
 #include <GL/glx.h>
-int main(void) { GL_VERSION; return 0; }
+int main(void) { return GL_VERSION != 0; }
 EOF
   if compile_prog "" "-lGL" ; then
     opengl=yes
@@ -2369,8 +2369,7 @@ int main(void)
      * warning but not an error, and will proceed to fail the
      * qemu compile where we compile with -Werror.)
      */
-    epoll_create1;
-    return 0;
+    return epoll_create1 == epoll_create1;
 }
 EOF
 if compile_prog "$ARCH_CFLAGS" "" ; then
commit 55cc7f3ed228ac52ffb766ba9113c2ed88dfa846
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 17 09:27:37 2011 +0100

    configure: Fix compiler warning in config.log (value was never used)
    
    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 e9725d4..bd6f10f 100755
--- a/configure
+++ b/configure
@@ -2269,8 +2269,7 @@ cat > $TMPC << EOF
 
 int main(void)
 {
-    int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
-    return 0;
+    return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
 }
 EOF
 if compile_prog "" "" ; then
commit ffc41d10b01b9c72a7dd412b271164530c14bdb8
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 17 09:27:36 2011 +0100

    configure: Fix compiler warning in config.log (undefined NULL)
    
    Avoid the warning when probing for xfs.
    
    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 e3713af..e9725d4 100755
--- a/configure
+++ b/configure
@@ -1670,6 +1670,7 @@ fi
 # xfsctl() probe, used for raw-posix
 if test "$xfs" != "no" ; then
   cat > $TMPC << EOF
+#include <stddef.h>  /* NULL */
 #include <xfs/xfs.h>
 int main(void)
 {
commit 66ea0f223b2521a2277839e568144773fecc8429
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 17 09:27:35 2011 +0100

    configure: Fix compiler warnings in config.log (uninitialized variable)
    
    warning: ‘fd’ is used uninitialized in this function
    warning: ‘id’ is used uninitialized in this function
    
    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 eeec8fa..e3713af 100755
--- a/configure
+++ b/configure
@@ -2237,7 +2237,7 @@ cat > $TMPC << EOF
 
 int main(void)
 {
-    int len, fd;
+    int len, fd = 0;
     len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
     splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
     return 0;
@@ -2449,7 +2449,7 @@ fi
 cat > $TMPC <<EOF
 #include <signal.h>
 #include <time.h>
-int main(void) { clockid_t id; return clock_gettime(id, NULL); }
+int main(void) { return clock_gettime(CLOCK_REALTIME, NULL); }
 EOF
 
 if compile_prog "" "" ; then
commit ed054defef32c723c0c467676717c5ddeb8dcd18
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 17 09:27:34 2011 +0100

    configure: Fix compiler warning in config.log (macro redefined)
    
    warning: "_GNU_SOURCE" redefined
    
    The macro is already defined on the command line.
    
    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 f2c2a27..eeec8fa 100755
--- a/configure
+++ b/configure
@@ -2251,7 +2251,6 @@ fi
 # signalfd probe
 signalfd="no"
 cat > $TMPC << EOF
-#define _GNU_SOURCE
 #include <unistd.h>
 #include <sys/syscall.h>
 #include <signal.h>
commit f91f9bee0c614da0dab6208a7a7fa00e3d207408
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 17 09:27:33 2011 +0100

    configure: Fix compiler warning in config.log (unused variable)
    
    warning: unused variable ‘iov’
    
    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 4e596e6..f2c2a27 100755
--- a/configure
+++ b/configure
@@ -2060,7 +2060,7 @@ cat > $TMPC <<EOF
 #include <sys/types.h>
 #include <sys/uio.h>
 #include <unistd.h>
-int main(void) { struct iovec iov; return 0; }
+int main(void) { return sizeof(struct iovec); }
 EOF
 iovec=no
 if compile_prog "" "" ; then
commit 7a42bbe4515168390ce1c3f65b15ebc08db625ce
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 17 09:27:32 2011 +0100

    configure: Fix compiler warnings in config.log (null arguments)
    
    warning: null argument where non-null required (argument 1)
    warning: null argument where non-null required (argument 3)
    
    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 773df6a..4e596e6 100755
--- a/configure
+++ b/configure
@@ -1951,7 +1951,12 @@ PTHREADLIBS_LIST="-pthread -lpthread -lpthreadGC2"
 pthread=no
 cat > $TMPC << EOF
 #include <pthread.h>
-int main(void) { pthread_create(0,0,0,0); return 0; }
+static void *f(void *p) { return NULL; }
+int main(void) {
+  pthread_t thread;
+  pthread_create(&thread, 0, f, 0);
+  return 0;
+}
 EOF
 if compile_prog "" "" ; then
   pthread=yes
commit ef9a252442c84af64216fc3e9c5c2283cbb30995
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 17 17:46:02 2011 +0100

    configure: Fix compiler warning in config.log (integer from pointer)
    
    warning: return makes integer from pointer without a cast
    
    v2: Removed type cast.
    
    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 93c6cbe..773df6a 100755
--- a/configure
+++ b/configure
@@ -1841,7 +1841,11 @@ if test "$curses" != "no" ; then
 #ifdef __OpenBSD__
 #define resize_term resizeterm
 #endif
-int main(void) { resize_term(0, 0); return curses_version(); }
+int main(void) {
+  const char *s = curses_version();
+  resize_term(0, 0);
+  return s != 0;
+}
 EOF
   for curses_lib in $curses_list; do
     if compile_prog "" "$curses_lib" ; then
commit 182eacc0fdd860ac60fa6fcf40429caa15e8328a
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 17 09:27:30 2011 +0100

    configure: Fix compiler warnings in config.log (old-style function definition)
    
    warning: function declaration isn’t a prototype
    In function ‘foo’:
    warning: old-style function definition
    
    The function name was changed, too, to avoid an additional warning.
    
    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 03b8f35..93c6cbe 100755
--- a/configure
+++ b/configure
@@ -1274,11 +1274,11 @@ if test "$nptl" != "no" ; then
   cat > $TMPC <<EOF
 #include <sched.h>
 #include <linux/futex.h>
-void foo()
-{
+int main(void) {
 #if !defined(CLONE_SETTLS) || !defined(FUTEX_WAIT)
 #error bork
 #endif
+  return 0;
 }
 EOF
 
commit 75cafad74d8df3f8ea188ed355127b91c9903290
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 17 09:27:29 2011 +0100

    configure: Fix compiler warnings in config.log (always return a value from main)
    
    Fix several "warning: control reaches end of non-void function".
    
    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 6fd580e..03b8f35 100755
--- a/configure
+++ b/configure
@@ -1082,7 +1082,7 @@ fi
 
 # check that the C compiler works.
 cat > $TMPC <<EOF
-int main(void) {}
+int main(void) { return 0; }
 EOF
 
 if compile_object ; then
@@ -2651,7 +2651,7 @@ ucontext_coroutine=no
 if test "$darwin" != "yes"; then
   cat > $TMPC << EOF
 #include <ucontext.h>
-int main(void) { makecontext(0, 0, 0); }
+int main(void) { makecontext(0, 0, 0); return 0; }
 EOF
   if compile_prog "" "" ; then
       ucontext_coroutine=yes
@@ -2664,7 +2664,7 @@ fi
 open_by_hande_at=no
 cat > $TMPC << EOF
 #include <fcntl.h>
-int main(void) { struct file_handle fh; open_by_handle_at(0, &fh, 0); }
+int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
 EOF
 if compile_prog "" "" ; then
     open_by_handle_at=yes
@@ -2677,6 +2677,7 @@ linux_magic_h=no
 cat > $TMPC << EOF
 #include <linux/magic.h>
 int main(void) {
+  return 0;
 }
 EOF
 if compile_prog "" "" ; then
commit 8ceb49fe4597e643aab5308b38f84de5d13a39b4
Author: Julian Pidancet <julian.pidancet at gmail.com>
Date:   Sun Dec 18 18:08:44 2011 +0000

    Also create piix3 property when Xen is enabled
    
    This recently added line in hw/pc_piix.c is causing a SEGV on a Xen
    setup because the piix3 property is never created:
    
    qdev_property_add_child(qdev_resolve_path("/i440fx/piix3", NULL),
                                "rtc", (DeviceState *)rtc_state, NULL);
    
    Signed-off-by: Julian Pidancet <julian.pidancet at gmail.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index d785d4b..ea156a9 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -324,9 +324,8 @@ static PCIBus *i440fx_common_init(const char *device_name,
                 pci_create_simple_multifunction(b, -1, true, "PIIX3"));
         pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3,
                 PIIX_NUM_PIRQS);
-
-        qdev_property_add_child(dev, "piix3", &piix3->dev.qdev, NULL);
     }
+    qdev_property_add_child(dev, "piix3", &piix3->dev.qdev, NULL);
     piix3->pic = pic;
 
     (*pi440fx_state)->piix3 = piix3;
commit b15ba6c95147e62671b29580c3b9056773cc496e
Author: Geoffrey Thomas <geofft at ldpreload.com>
Date:   Sat Dec 17 04:23:59 2011 -0500

    slirp: Fix typo in net_slirp_hostfwd_remove
    
    Report an error when err is nonzero, not when it is zero.
    
    Signed-off-by: Geoffrey Thomas <geofft at ldpreload.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/net/slirp.c b/net/slirp.c
index 6646ecb..18e07ba 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -351,7 +351,7 @@ void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict)
                                host_addr, host_port);
 
     monitor_printf(mon, "host forwarding rule for %s %s\n", src_str,
-                   err ? "removed" : "not found");
+                   err ? "not found" : "removed");
     return;
 
  fail_syntax:
commit ce01a508e8053350544c88ba68a3f90c44b6bb93
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Sun Dec 18 12:59:12 2011 -0600

    pc: add pc-0.15
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 166c2fc..265ccb2 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -321,6 +321,14 @@ static QEMUMachine pc_machine_v1_0 = {
     .is_default = 1,
 };
 
+static QEMUMachine pc_machine_v0_15 = {
+    .name = "pc-0.15",
+    .desc = "Standard PC",
+    .init = pc_init_pci,
+    .max_cpus = 255,
+    .is_default = 1,
+};
+
 static QEMUMachine pc_machine_v0_14 = {
     .name = "pc-0.14",
     .desc = "Standard PC",
@@ -572,6 +580,7 @@ static QEMUMachine xenfv_machine = {
 static void pc_machine_init(void)
 {
     qemu_register_machine(&pc_machine_v1_0);
+    qemu_register_machine(&pc_machine_v0_15);
     qemu_register_machine(&pc_machine_v0_14);
     qemu_register_machine(&pc_machine_v0_13);
     qemu_register_machine(&pc_machine_v0_12);
commit 7b011fbc050d442a20ed5d2a29724570c1557661
Author: Michael Ellerman <michael at ellerman.id.au>
Date:   Fri Dec 16 11:20:20 2011 +1100

    kvm: Print something before calling abort() if KVM_RUN fails
    
    It's a little unfriendly to call abort() without printing any sort of
    error message. So turn the DPRINTK() into an fprintf(stderr, ...).
    
    Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/kvm-all.c b/kvm-all.c
index 4c466d6..ac048bc 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -977,7 +977,8 @@ int kvm_cpu_exec(CPUState *env)
                 ret = EXCP_INTERRUPT;
                 break;
             }
-            DPRINTF("kvm run failed %s\n", strerror(-run_ret));
+            fprintf(stderr, "error: kvm run failed %s\n",
+                    strerror(-run_ret));
             abort();
         }
 
commit bfc213af97c5f7768ad7549bc95134cb4e218a76
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Dec 15 18:58:26 2011 +0000

    stellaris: Calculate system clock period on reset
    
    Calculate the system clock period on reset; otherwise it remains
    set to the default value of zero and attempting to use it provokes
    a hang. This is one of the issues noted in LP:696094.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/stellaris.c b/hw/stellaris.c
index ce62a98..7a73074 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -621,6 +621,7 @@ static void ssys_reset(void *opaque)
     s->rcgc[0] = 1;
     s->scgc[0] = 1;
     s->dcgc[0] = 1;
+    ssys_calculate_system_clock(s);
 }
 
 static int stellaris_sys_post_load(void *opaque, int version_id)
commit 7fc3574d065d6744afbab73d8a701ffd94206138
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Dec 15 18:28:52 2011 +0000

    Makefile.target: Remove unnecessary dependency rules
    
    Remove some dependency rules which aren't necessary (the automatically
    generated .d files cover all these). These were leftovers from dyngen
    days, when the object files also had a dependency on some generated
    files.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/Makefile.target b/Makefile.target
index 8be9b9a..3261383 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -92,12 +92,6 @@ tci-dis.o: QEMU_CFLAGS += -I$(SRC_PATH)/tcg -I$(SRC_PATH)/tcg/tci
 
 $(libobj-y): $(GENERATED_HEADERS)
 
-translate.o: translate.c cpu.h
-
-translate-all.o: translate-all.c cpu.h
-
-tcg/tcg.o: cpu.h
-
 # 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)
commit b61744b391e9184ac49c52f7eb42722507cc76ee
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Dec 15 15:11:16 2011 +0100

    ide: drop argument to dma_buf_commit
    
    The argument is unused and even wrong when the function is called
    by ide_handle_rw_error.  Drop it.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 49847bd..753c442 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -493,7 +493,7 @@ void ide_sector_read(IDEState *s)
     }
 }
 
-static void dma_buf_commit(IDEState *s, int is_write)
+static void dma_buf_commit(IDEState *s)
 {
     qemu_sglist_destroy(&s->sg);
 }
@@ -532,7 +532,7 @@ static int ide_handle_rw_error(IDEState *s, int error, int op)
         bdrv_iostatus_set_err(s->bs, error);
     } else {
         if (op & BM_STATUS_DMA_RETRY) {
-            dma_buf_commit(s, 0);
+            dma_buf_commit(s);
             ide_dma_error(s);
         } else {
             ide_rw_error(s);
@@ -566,7 +566,7 @@ handle_rw_error:
     n = s->io_buffer_size >> 9;
     sector_num = ide_get_sector(s);
     if (n > 0) {
-        dma_buf_commit(s, ide_cmd_is_read(s));
+        dma_buf_commit(s);
         sector_num += n;
         ide_set_sector(s, sector_num);
         s->nsector -= n;
commit 5ab97b7f81dccccee03a3f1d03a4d09a27f0eeff
Author: Alex Rozenman <Alex_Rozenman at mentor.com>
Date:   Tue Dec 13 12:52:08 2011 +0200

    phys_page_find_alloc: Use correct initial region_offset.
    
    This fixes a common bug with initial region_offset value.
    Usually, the pages are re-assigned afterwards, so the bug
    has a very small effect on regular QEMU use flows.
    
    Signed-off-by: Alex Rozenman <Alex_Rozenman at mentor.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/exec.c b/exec.c
index eef5e2f..06889bd 100644
--- a/exec.c
+++ b/exec.c
@@ -418,6 +418,7 @@ static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
     pd = *lp;
     if (pd == NULL) {
         int i;
+        int first_index = index & ~(L2_SIZE - 1);
 
         if (!alloc) {
             return NULL;
@@ -427,7 +428,7 @@ static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
 
         for (i = 0; i < L2_SIZE; i++) {
             pd[i].phys_offset = IO_MEM_UNASSIGNED;
-            pd[i].region_offset = (index + i) << TARGET_PAGE_BITS;
+            pd[i].region_offset = (first_index + i) << TARGET_PAGE_BITS;
         }
     }
 
commit 885660bd48efbe3742892e06de7a8898703e0bdc
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Wed Dec 7 21:48:07 2011 -0600

    network scripts: don't block SIGCHLD before forking
    
    This patch fixes a bug where child processes of launch_script() can
    misbehave due to SIGCHLD being blocked. In the case of `sudo`, this
    causes a permanent hang.
    
    Previously a SIGCHLD handler was added to reap fork_exec()'d zombie
    processes by calling waitpid(-1, ...). This required other
    fork()/waitpid() callers to temporarilly block SIGCHILD to avoid
    having the final wait status being intercepted by the SIGCHLD
    handler:
    
    7c3370d4fe3fa6cda8655f109e4659afc8ca4269
    
    Since then, the qemu_add_child_watch() interface was added to allow
    registration of such processes and reap only from that specific set
    of PIDs:
    
    4d54ec7898bd951007cb6122d5315584bd41d0c4
    
    As a result, we can now avoid blocking SIGCHLD in launch_script(), so
    drop that behavior.
    
    Reviewed-by: Jan Kiszka <jan.kiszka at siemens.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/net/tap.c b/net/tap.c
index 1f26dc9..6c27a94 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -346,15 +346,10 @@ static TAPState *net_tap_fd_init(VLANState *vlan,
 
 static int launch_script(const char *setup_script, const char *ifname, int fd)
 {
-    sigset_t oldmask, mask;
     int pid, status;
     char *args[3];
     char **parg;
 
-    sigemptyset(&mask);
-    sigaddset(&mask, SIGCHLD);
-    sigprocmask(SIG_BLOCK, &mask, &oldmask);
-
     /* try to launch network script */
     pid = fork();
     if (pid == 0) {
@@ -378,7 +373,6 @@ static int launch_script(const char *setup_script, const char *ifname, int fd)
         while (waitpid(pid, &status, 0) != pid) {
             /* loop */
         }
-        sigprocmask(SIG_SETMASK, &oldmask, NULL);
 
         if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
             return 0;
commit f603a687ff722e9df3e6e4730ca4e267aa2b124e
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Dec 15 13:33:54 2011 +0000

    HACKING: clarify allocation/free recommendations
    
    Clarify the allocation/free recommendations; this is mostly
    just tidying up following the global-search-and-replace done
    with the conversion to the GLib g_malloc and friends.
    
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/HACKING b/HACKING
index 733eab2..471cf1d 100644
--- a/HACKING
+++ b/HACKING
@@ -77,11 +77,13 @@ avoided.
 
 Use of the malloc/free/realloc/calloc/valloc/memalign/posix_memalign
 APIs is not allowed in the QEMU codebase. Instead of these routines,
-use the replacement g_malloc/g_malloc0/g_realloc/g_free or
-qemu_vmalloc/qemu_memalign/qemu_vfree APIs.
+use the GLib memory allocation routines g_malloc/g_malloc0/g_new/
+g_new0/g_realloc/g_free or QEMU's qemu_vmalloc/qemu_memalign/qemu_vfree
+APIs.
 
-Please note that NULL check for the g_malloc result is redundant and
-that g_malloc() call with zero size is not allowed.
+Please note that g_malloc will exit on allocation failure, so there
+is no need to test for failure (as you would have to with malloc).
+Calling g_malloc with a zero size is valid and will return NULL.
 
 Memory allocated by qemu_vmalloc or qemu_memalign must be freed with
 qemu_vfree, since breaking this will cause problems on Win32 and user
commit db3a5ed7e4422491dac1f83264ebb01f6667ffc8
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Thu Dec 15 10:05:18 2011 +0000

    usb: fix usb_qdev_init() error handling again
    
    Commit f462141f18ffdd75847f6459ef83d90b831d12c0 introduced clean up code
    when usb_qdev_init() fails.  Unfortunately it calls .handle_destroy()
    when .init() was never invoked or failed.  This can lead to crashes when
    .handle_destroy() tries to clean up things that were never initialized.
    
    This patch is careful to undo only those steps that completed along the
    usb_qdev_init() code path.  It's not as pretty as the unified error
    handling in f462141f18ffdd75847f6459ef83d90b831d12c0 but it's necessary.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 8cafb76..8203390 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -77,23 +77,21 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
     QLIST_INIT(&dev->strings);
     rc = usb_claim_port(dev);
     if (rc != 0) {
-        goto err;
+        return rc;
     }
     rc = dev->info->init(dev);
     if (rc != 0) {
-        goto err;
+        usb_release_port(dev);
+        return rc;
     }
     if (dev->auto_attach) {
         rc = usb_device_attach(dev);
         if (rc != 0) {
-            goto err;
+            usb_qdev_exit(qdev);
+            return rc;
         }
     }
     return 0;
-
-err:
-    usb_qdev_exit(qdev);
-    return rc;
 }
 
 static int usb_qdev_exit(DeviceState *qdev)
commit 56384e8b1eebac750e6186f5041af710433ddc9e
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Nov 30 16:26:21 2011 +0100

    exec.c: Fix subpage memory access to RAM MemoryRegion
    
    Commit 95c318f5e1f88d7e5bcc6deac17330fd4806a2d3 (Fix segfault in mmio
    subpage handling code.) prevented a segfault by making all subpage
    registrations over an existing memory page perform an unassigned access.
    Symptoms were writes not taking effect and reads returning zero.
    
    Very small page sizes are not currently supported either,
    so subpage memory areas cannot fully be avoided.
    
    Therefore change the previous fix to use a new IO_MEM_SUBPAGE_RAM
    instead of IO_MEM_UNASSIGNED. Suggested by Avi.
    
    Reviewed-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Cc: Avi Kivity <avi at redhat.com>
    Cc: Gleb Natapov <gleb at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/cpu-common.h b/cpu-common.h
index 7c9cef8..48f4c01 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -172,6 +172,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr,
 #define IO_MEM_ROM         (1 << IO_MEM_SHIFT) /* hardcoded offset */
 #define IO_MEM_UNASSIGNED  (2 << IO_MEM_SHIFT)
 #define IO_MEM_NOTDIRTY    (3 << IO_MEM_SHIFT)
+#define IO_MEM_SUBPAGE_RAM (4 << IO_MEM_SHIFT)
 
 /* Acts like a ROM when read and like a device when written.  */
 #define IO_MEM_ROMD        (1)
diff --git a/exec.c b/exec.c
index 4f79cbb..eef5e2f 100644
--- a/exec.c
+++ b/exec.c
@@ -3570,6 +3570,63 @@ static CPUWriteMemoryFunc * const subpage_write[] = {
     &subpage_writel,
 };
 
+static uint32_t subpage_ram_readb(void *opaque, target_phys_addr_t addr)
+{
+    ram_addr_t raddr = addr;
+    void *ptr = qemu_get_ram_ptr(raddr);
+    return ldub_p(ptr);
+}
+
+static void subpage_ram_writeb(void *opaque, target_phys_addr_t addr,
+                               uint32_t value)
+{
+    ram_addr_t raddr = addr;
+    void *ptr = qemu_get_ram_ptr(raddr);
+    stb_p(ptr, value);
+}
+
+static uint32_t subpage_ram_readw(void *opaque, target_phys_addr_t addr)
+{
+    ram_addr_t raddr = addr;
+    void *ptr = qemu_get_ram_ptr(raddr);
+    return lduw_p(ptr);
+}
+
+static void subpage_ram_writew(void *opaque, target_phys_addr_t addr,
+                               uint32_t value)
+{
+    ram_addr_t raddr = addr;
+    void *ptr = qemu_get_ram_ptr(raddr);
+    stw_p(ptr, value);
+}
+
+static uint32_t subpage_ram_readl(void *opaque, target_phys_addr_t addr)
+{
+    ram_addr_t raddr = addr;
+    void *ptr = qemu_get_ram_ptr(raddr);
+    return ldl_p(ptr);
+}
+
+static void subpage_ram_writel(void *opaque, target_phys_addr_t addr,
+                               uint32_t value)
+{
+    ram_addr_t raddr = addr;
+    void *ptr = qemu_get_ram_ptr(raddr);
+    stl_p(ptr, value);
+}
+
+static CPUReadMemoryFunc * const subpage_ram_read[] = {
+    &subpage_ram_readb,
+    &subpage_ram_readw,
+    &subpage_ram_readl,
+};
+
+static CPUWriteMemoryFunc * const subpage_ram_write[] = {
+    &subpage_ram_writeb,
+    &subpage_ram_writew,
+    &subpage_ram_writel,
+};
+
 static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
                              ram_addr_t memory, ram_addr_t region_offset)
 {
@@ -3583,8 +3640,9 @@ 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)
-        memory = IO_MEM_UNASSIGNED;
+    if ((memory & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
+        memory = IO_MEM_SUBPAGE_RAM;
+    }
     memory = (memory >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
     for (; idx <= eidx; idx++) {
         mmio->sub_io_index[idx] = memory;
@@ -3817,6 +3875,9 @@ static void io_mem_init(void)
     cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read,
                                  notdirty_mem_write, NULL,
                                  DEVICE_NATIVE_ENDIAN);
+    cpu_register_io_memory_fixed(IO_MEM_SUBPAGE_RAM, subpage_ram_read,
+                                 subpage_ram_write, NULL,
+                                 DEVICE_NATIVE_ENDIAN);
     for (i=0; i<5; i++)
         io_mem_used[i] = 1;
 
commit 15d37e709fa809f1b64d3ad81965f3d8200e828a
Author: michael at ozlabs.org <michael at ozlabs.org>
Date:   Tue Dec 13 12:22:58 2011 +1100

    vl.c: Print the actual program name in help output
    
    In help() we do what boils down to:
    
      printf("%s", "qemu");
    
    This seems to be an artifact of be995c27640a82c7056b6f53d02ec823570114e5
    ("removed unused code"), which removed some ifdef'ery that used to print
    a different name depending on CONFIG_SOFTMMU.
    
    Instead print the actual program name, originally from argv[0].
    
    Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index 5372a96..d51ac2e 100644
--- a/vl.c
+++ b/vl.c
@@ -1513,7 +1513,7 @@ static void help(int exitcode)
            "ctrl-alt        toggle mouse and keyboard grab\n"
            "\n"
            "When using -nographic, press 'ctrl-a h' to get some help.\n",
-           "qemu",
+           error_get_progname(),
            options_help);
     exit(exitcode);
 }
commit 7636a470a8ccd99cfb2d89eae9b6720be5a203c4
Author: michael at ozlabs.org <michael at ozlabs.org>
Date:   Tue Dec 13 12:22:57 2011 +1100

    error: Add an accessor for progname
    
    We'd like to get the progname for help output, so add an accessor.
    
    Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Reviewed-by: Andreas F=E4rber <afaerber at suse.de>
    Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-error.c b/qemu-error.c
index 4b20d28..7cd5ffe 100644
--- a/qemu-error.c
+++ b/qemu-error.c
@@ -157,6 +157,11 @@ void error_set_progname(const char *argv0)
     progname = p ? p + 1 : argv0;
 }
 
+const char *error_get_progname(void)
+{
+    return progname;
+}
+
 /*
  * Print current location to current monitor if we have one, else to stderr.
  */
diff --git a/qemu-error.h b/qemu-error.h
index 4d5c537..93d74b4 100644
--- a/qemu-error.h
+++ b/qemu-error.h
@@ -36,5 +36,6 @@ void error_printf_unless_qmp(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
 void error_print_loc(void);
 void error_set_progname(const char *argv0);
 void error_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
+const char *error_get_progname(void);
 
 #endif
commit 1ecf47bf0a091700e45f1b7d1f5ad85abc0acd22
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Dec 13 13:43:52 2011 +0100

    fix win32 build
    
    On Windows, cpus.c needs access to the hThread.  Add a Windows-specific
    function to grab it.  This requires changing the CPU threads to
    joinable.  There is no substantial change because the threads run
    in an infinite loop.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/cpu-defs.h b/cpu-defs.h
index db48a7a..57a709b 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -153,6 +153,14 @@ typedef struct CPUWatchpoint {
     QTAILQ_ENTRY(CPUWatchpoint) entry;
 } CPUWatchpoint;
 
+#ifdef _WIN32
+#define CPU_COMMON_THREAD \
+    void *hThread;
+
+#else
+#define CPU_COMMON_THREAD
+#endif
+
 #define CPU_TEMP_BUF_NLONGS 128
 #define CPU_COMMON                                                      \
     struct TranslationBlock *current_tb; /* currently executing TB  */  \
@@ -211,6 +219,7 @@ typedef struct CPUWatchpoint {
     uint32_t stop;   /* Stop request */                                 \
     uint32_t stopped; /* Artificially stopped */                        \
     struct QemuThread *thread;                                          \
+    CPU_COMMON_THREAD                                                   \
     struct QemuCond *halt_cond;                                         \
     int thread_kicked;                                                  \
     struct qemu_work_item *queued_work_first, *queued_work_last;        \
diff --git a/cpus.c b/cpus.c
index a060c60..b421a71 100644
--- a/cpus.c
+++ b/cpus.c
@@ -793,9 +793,9 @@ static void qemu_cpu_kick_thread(CPUState *env)
     }
 #else /* _WIN32 */
     if (!qemu_cpu_is_self(env)) {
-        SuspendThread(env->thread->thread);
+        SuspendThread(env->hThread);
         cpu_signal(0);
-        ResumeThread(env->thread->thread);
+        ResumeThread(env->hThread);
     }
 #endif
 }
@@ -911,7 +911,10 @@ static void qemu_tcg_init_vcpu(void *_env)
         qemu_cond_init(env->halt_cond);
         tcg_halt_cond = env->halt_cond;
         qemu_thread_create(env->thread, qemu_tcg_cpu_thread_fn, env,
-                           QEMU_THREAD_DETACHED);
+                           QEMU_THREAD_JOINABLE);
+#ifdef _WIN32
+        env->hThread = qemu_thread_get_handle(env->thread);
+#endif
         while (env->created == 0) {
             qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
         }
@@ -928,7 +931,7 @@ static void qemu_kvm_start_vcpu(CPUState *env)
     env->halt_cond = g_malloc0(sizeof(QemuCond));
     qemu_cond_init(env->halt_cond);
     qemu_thread_create(env->thread, qemu_kvm_cpu_thread_fn, env,
-                       QEMU_THREAD_DETACHED);
+                       QEMU_THREAD_JOINABLE);
     while (env->created == 0) {
         qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
     }
diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c
index a13ffcc..fe9b931 100644
--- a/qemu-thread-win32.c
+++ b/qemu-thread-win32.c
@@ -252,14 +252,10 @@ void *qemu_thread_join(QemuThread *thread)
      * discard the handle that _beginthreadex gives back, and
      * get another copy of the handle here.
      */
-    EnterCriticalSection(&data->cs);
-    if (!data->exited) {
-        handle = OpenThread(SYNCHRONIZE, FALSE, thread->tid);
-        LeaveCriticalSection(&data->cs);
+    handle = qemu_thread_get_handle(thread);
+    if (handle) {
         WaitForSingleObject(handle, INFINITE);
         CloseHandle(handle);
-    } else {
-        LeaveCriticalSection(&data->cs);
     }
     ret = data->ret;
     DeleteCriticalSection(&data->cs);
@@ -308,6 +304,27 @@ void qemu_thread_get_self(QemuThread *thread)
     thread->tid = GetCurrentThreadId();
 }
 
+HANDLE qemu_thread_get_handle(QemuThread *thread)
+{
+    QemuThreadData *data;
+    HANDLE handle;
+
+    data = thread->data;
+    if (!data) {
+        return NULL;
+    }
+
+    EnterCriticalSection(&data->cs);
+    if (!data->exited) {
+        handle = OpenThread(SYNCHRONIZE | THREAD_SUSPEND_RESUME, FALSE,
+                            thread->tid);
+    } else {
+        handle = NULL;
+    }
+    LeaveCriticalSection(&data->cs);
+    return handle;
+}
+
 int qemu_thread_is_self(QemuThread *thread)
 {
     return GetCurrentThreadId() == thread->tid;
diff --git a/qemu-thread-win32.h b/qemu-thread-win32.h
index 2983490..b9d1be8 100644
--- a/qemu-thread-win32.h
+++ b/qemu-thread-win32.h
@@ -19,4 +19,7 @@ struct QemuThread {
     unsigned tid;
 };
 
+/* Only valid for joinable threads.  */
+HANDLE qemu_thread_get_handle(QemuThread *thread);
+
 #endif
commit cd34d667d448bec91c81f4e46f9e7eb4e4857f6f
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:43 2011 -0600

    qdev: add a qdev_get_type() function and expose as a 'type' property
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 0fc20fc..83913c7 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -110,6 +110,8 @@ static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
         qdev_property_add_legacy(dev, prop, NULL);
     }
 
+    qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
+
     return dev;
 }
 
@@ -1031,6 +1033,11 @@ char* qdev_get_fw_dev_path(DeviceState *dev)
     return strdup(path);
 }
 
+char *qdev_get_type(DeviceState *dev, Error **errp)
+{
+    return g_strdup(dev->info->name);
+}
+
 void qdev_ref(DeviceState *dev)
 {
     dev->ref++;
diff --git a/hw/qdev.h b/hw/qdev.h
index 9faf2ee..6e18427 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -596,4 +596,18 @@ void qdev_property_add_str(DeviceState *dev, const char *name,
                            void (*set)(DeviceState *, const char *, Error **),
                            Error **errp);
 
+/**
+ * @qdev_get_type
+ *
+ * Returns the string representation of the type of this object.
+ *
+ * @dev - the device
+ *
+ * @errp - if an error occurs, a pointer to an area to store the error
+ *
+ * Returns: a string representing the type.  This must be freed by the caller
+ *          with g_free().
+ */
+char *qdev_get_type(DeviceState *dev, Error **errp);
+
 #endif
commit 6a146eba33159cb97d28457d409d81066cbefb09
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:42 2011 -0600

    qom: add string property type
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 4004860..0fc20fc 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -1449,3 +1449,62 @@ DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
     return dev;
 }
 
+typedef struct StringProperty
+{
+    char *(*get)(DeviceState *, Error **);
+    void (*set)(DeviceState *, const char *, Error **);
+} StringProperty;
+
+static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
+                                  const char *name, Error **errp)
+{
+    StringProperty *prop = opaque;
+    char *value;
+
+    value = prop->get(dev, errp);
+    if (value) {
+        visit_type_str(v, &value, name, errp);
+        g_free(value);
+    }
+}
+
+static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
+                                  const char *name, Error **errp)
+{
+    StringProperty *prop = opaque;
+    char *value;
+    Error *local_err = NULL;
+
+    visit_type_str(v, &value, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    prop->set(dev, value, errp);
+    g_free(value);
+}
+
+static void qdev_property_release_str(DeviceState *dev, const char *name,
+                                      void *opaque)
+{
+    StringProperty *prop = opaque;
+    g_free(prop);
+}
+
+void qdev_property_add_str(DeviceState *dev, const char *name,
+                           char *(*get)(DeviceState *, Error **),
+                           void (*set)(DeviceState *, const char *, Error **),
+                           Error **errp)
+{
+    StringProperty *prop = g_malloc0(sizeof(*prop));
+
+    prop->get = get;
+    prop->set = set;
+
+    qdev_property_add(dev, name, "string",
+                      get ? qdev_property_get_str : NULL,
+                      set ? qdev_property_set_str : NULL,
+                      qdev_property_release_str,
+                      prop, errp);
+}
diff --git a/hw/qdev.h b/hw/qdev.h
index fdab848..9faf2ee 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -574,4 +574,26 @@ void qdev_property_add_link(DeviceState *dev, const char *name,
                             const char *type, DeviceState **child,
                             Error **errp);
 
+/**
+ * @qdev_property_add_str
+ *
+ * Add a string property using getters/setters.  This function will add a
+ * property of type 'string'.
+ *
+ * @dev - the device to add a property to
+ *
+ * @name - the name of the property
+ *
+ * @get - the getter or NULL if the property is write-only.  This function must
+ *        return a string to be freed by @g_free().
+ *
+ * @set - the setter or NULL if the property is read-only
+ *
+ * @errp - if an error occurs, a pointer to an area to store the error
+ */
+void qdev_property_add_str(DeviceState *dev, const char *name,
+                           char *(*get)(DeviceState *, Error **),
+                           void (*set)(DeviceState *, const char *, Error **),
+                           Error **errp);
+
 #endif
commit ad6d45fa0837acf3e8cab323ee5b08e05a9410a5
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:41 2011 -0600

    qom: add vga node to the pc composition tree
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 1b216e8..1388a20 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -2899,7 +2899,7 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci,
  *
  ***************************************/
 
-void isa_cirrus_vga_init(MemoryRegion *system_memory)
+DeviceState *isa_cirrus_vga_init(MemoryRegion *system_memory)
 {
     CirrusVGAState *s;
 
@@ -2913,6 +2913,8 @@ void isa_cirrus_vga_init(MemoryRegion *system_memory)
     vmstate_register(NULL, 0, &vmstate_cirrus_vga, s);
     rom_add_vga(VGABIOS_CIRRUS_FILENAME);
     /* XXX ISA-LFB support */
+    /* FIXME not qdev yet */
+    return NULL;
 }
 
 /***************************************
@@ -2955,9 +2957,9 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
      return 0;
 }
 
-void pci_cirrus_vga_init(PCIBus *bus)
+DeviceState *pci_cirrus_vga_init(PCIBus *bus)
 {
-    pci_create_simple(bus, -1, "cirrus-vga");
+    return &pci_create_simple(bus, -1, "cirrus-vga")->qdev;
 }
 
 static PCIDeviceInfo cirrus_vga_info = {
diff --git a/hw/pc.c b/hw/pc.c
index b6dcba2..03466ec 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1069,38 +1069,44 @@ qemu_irq *pc_allocate_cpu_irq(void)
     return qemu_allocate_irqs(pic_irq_request, NULL, 1);
 }
 
-void pc_vga_init(PCIBus *pci_bus)
+DeviceState *pc_vga_init(PCIBus *pci_bus)
 {
+    DeviceState *dev = NULL;
+
     if (cirrus_vga_enabled) {
         if (pci_bus) {
-            pci_cirrus_vga_init(pci_bus);
+            dev = pci_cirrus_vga_init(pci_bus);
         } else {
-            isa_cirrus_vga_init(get_system_memory());
+            dev = isa_cirrus_vga_init(get_system_memory());
         }
     } else if (vmsvga_enabled) {
         if (pci_bus) {
-            if (!pci_vmsvga_init(pci_bus)) {
+            dev = pci_vmsvga_init(pci_bus);
+            if (!dev) {
                 fprintf(stderr, "Warning: vmware_vga not available,"
                         " using standard VGA instead\n");
-                pci_vga_init(pci_bus);
+                dev = pci_vga_init(pci_bus);
             }
         } else {
             fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
         }
 #ifdef CONFIG_SPICE
     } else if (qxl_enabled) {
-        if (pci_bus)
-            pci_create_simple(pci_bus, -1, "qxl-vga");
-        else
+        if (pci_bus) {
+            dev = &pci_create_simple(pci_bus, -1, "qxl-vga")->qdev;
+        } else {
             fprintf(stderr, "%s: qxl: no PCI bus\n", __FUNCTION__);
+        }
 #endif
     } else if (std_vga_enabled) {
         if (pci_bus) {
-            pci_vga_init(pci_bus);
+            dev = pci_vga_init(pci_bus);
         } else {
-            isa_vga_init();
+            dev = isa_vga_init();
         }
     }
+
+    return dev;
 }
 
 static void cpu_request_exit(void *opaque, int irq, int level)
diff --git a/hw/pc.h b/hw/pc.h
index b7b7e40..b2000e7 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -140,7 +140,7 @@ void pc_memory_init(MemoryRegion *system_memory,
                     MemoryRegion *rom_memory,
                     MemoryRegion **ram_memory);
 qemu_irq *pc_allocate_cpu_irq(void);
-void pc_vga_init(PCIBus *pci_bus);
+DeviceState *pc_vga_init(PCIBus *pci_bus);
 void pc_basic_device_init(qemu_irq *gsi,
                           ISADevice **rtc_state,
                           ISADevice **floppy,
@@ -205,27 +205,27 @@ enum vga_retrace_method {
 
 extern enum vga_retrace_method vga_retrace_method;
 
-static inline int isa_vga_init(void)
+static inline DeviceState *isa_vga_init(void)
 {
     ISADevice *dev;
 
     dev = isa_try_create("isa-vga");
     if (!dev) {
         fprintf(stderr, "Warning: isa-vga not available\n");
-        return 0;
+        return NULL;
     }
     qdev_init_nofail(&dev->qdev);
-    return 1;
+    return &dev->qdev;
 }
 
-int pci_vga_init(PCIBus *bus);
+DeviceState *pci_vga_init(PCIBus *bus);
 int isa_vga_mm_init(target_phys_addr_t vram_base,
                     target_phys_addr_t ctrl_base, int it_shift,
                     MemoryRegion *address_space);
 
 /* cirrus_vga.c */
-void pci_cirrus_vga_init(PCIBus *bus);
-void isa_cirrus_vga_init(MemoryRegion *address_space);
+DeviceState *pci_cirrus_vga_init(PCIBus *bus);
+DeviceState *isa_cirrus_vga_init(MemoryRegion *address_space);
 
 /* ne2000.c */
 static inline bool isa_ne2000_init(int base, int irq, NICInfo *nd)
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 2d5ea2c..166c2fc 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -99,6 +99,7 @@ static void pc_init1(MemoryRegion *system_memory,
     MemoryRegion *ram_memory;
     MemoryRegion *pci_memory;
     MemoryRegion *rom_memory;
+    DeviceState *dev;
 
     pc_cpus_init(cpu_model);
 
@@ -168,7 +169,10 @@ static void pc_init1(MemoryRegion *system_memory,
 
     pc_register_ferr_irq(gsi[13]);
 
-    pc_vga_init(pci_enabled? pci_bus: NULL);
+    dev = pc_vga_init(pci_enabled? pci_bus: NULL);
+    if (dev) {
+        qdev_property_add_child(qdev_get_root(), "vga", dev, NULL);
+    }
 
     if (xen_enabled()) {
         pci_create_simple(pci_bus, -1, "xen-platform");
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index 14bfadb..a75dbf3 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -70,10 +70,9 @@ static int pci_vga_initfn(PCIDevice *dev)
      return 0;
 }
 
-int pci_vga_init(PCIBus *bus)
+DeviceState *pci_vga_init(PCIBus *bus)
 {
-    pci_create_simple(bus, -1, "VGA");
-    return 0;
+    return &pci_create_simple(bus, -1, "VGA")->qdev;
 }
 
 static PCIDeviceInfo vga_info = {
diff --git a/hw/vmware_vga.h b/hw/vmware_vga.h
index 5132573..db11cbf 100644
--- a/hw/vmware_vga.h
+++ b/hw/vmware_vga.h
@@ -4,15 +4,15 @@
 #include "qemu-common.h"
 
 /* vmware_vga.c */
-static inline bool pci_vmsvga_init(PCIBus *bus)
+static inline DeviceState *pci_vmsvga_init(PCIBus *bus)
 {
     PCIDevice *dev;
 
     dev = pci_try_create(bus, -1, "vmware-svga");
     if (!dev || qdev_init(&dev->qdev) < 0) {
-        return false;
+        return NULL;
     } else {
-        return true;
+        return &dev->qdev;
     }
 }
 
commit b2b6c39a7915e82cade4ab8689344c91c5e45653
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:40 2011 -0600

    qom: optimize qdev_get_canonical_path using a parent link
    
    The full tree search was a bit unreasonable.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 4d491f1..4004860 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -1229,6 +1229,8 @@ void qdev_property_add_child(DeviceState *dev, const char *name,
                       NULL, NULL, child, errp);
 
     qdev_ref(child);
+    g_assert(child->parent == NULL);
+    child->parent = dev;
 
     g_free(type);
 }
@@ -1307,48 +1309,38 @@ void qdev_property_add_link(DeviceState *dev, const char *name,
     g_free(full_type);
 }
 
-static gchar *qdev_get_path_in(DeviceState *parent, DeviceState *dev)
+gchar *qdev_get_canonical_path(DeviceState *dev)
 {
-    DeviceProperty *prop;
+    DeviceState *root = qdev_get_root();
+    char *newpath = NULL, *path = NULL;
 
-    if (parent == dev) {
-        return g_strdup("");
-    }
+    while (dev != root) {
+        DeviceProperty *prop = NULL;
 
-    QTAILQ_FOREACH(prop, &parent->properties, node) {
-        gchar *subpath;
+        g_assert(dev->parent != NULL);
 
-        if (!strstart(prop->type, "child<", NULL)) {
-            continue;
-        }
+        QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
+            if (!strstart(prop->type, "child<", NULL)) {
+                continue;
+            }
 
-        /* Check to see if the device is one of parent's children */
-        if (prop->opaque == dev) {
-            return g_strdup(prop->name);
+            if (prop->opaque == dev) {
+                if (path) {
+                    newpath = g_strdup_printf("%s/%s", prop->name, path);
+                    g_free(path);
+                    path = newpath;
+                } else {
+                    path = g_strdup(prop->name);
+                }
+                break;
+            }
         }
 
-        /* Check to see if the device is a child of our child */
-        subpath = qdev_get_path_in(prop->opaque, dev);
-        if (subpath) {
-            gchar *path;
+        g_assert(prop != NULL);
 
-            path = g_strdup_printf("%s/%s", prop->name, subpath);
-            g_free(subpath);
-
-            return path;
-        }
+        dev = dev->parent;
     }
 
-    return NULL;
-}
-
-gchar *qdev_get_canonical_path(DeviceState *dev)
-{
-    gchar *path, *newpath;
-
-    path = qdev_get_path_in(qdev_get_root(), dev);
-    g_assert(path != NULL);
-
     newpath = g_strdup_printf("/%s", path);
     g_free(path);
 
diff --git a/hw/qdev.h b/hw/qdev.h
index 4351e2e..fdab848 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -92,6 +92,10 @@ struct DeviceState {
     uint32_t ref;
 
     QTAILQ_HEAD(, DeviceProperty) properties;
+
+    /* Do not, under any circumstance, use this parent link below anywhere
+     * outside of qdev.c.  You have been warned. */
+    DeviceState *parent;
 };
 
 typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent);
commit 182970509bd79635a5b16a06d2e918d3f5187486
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:39 2011 -0600

    rtc: add a dynamic property for retrieving the date
    
    This really shows the power of dynamic object properties compared to qdev
    static properties.
    
    This property represents a complex structure who's format is preserved over the
    wire.  This is enabled by visitors.
    
    It also shows an entirely synthetic property that is not tied to device state.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 2aaca2f..0c23cb0 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -614,6 +614,29 @@ static const MemoryRegionOps cmos_ops = {
     .old_portio = cmos_portio
 };
 
+// FIXME add int32 visitor
+static void visit_type_int32(Visitor *v, int *value, const char *name, Error **errp)
+{
+    int64_t val = *value;
+    visit_type_int(v, &val, name, errp);
+}
+
+static void rtc_get_date(DeviceState *dev, Visitor *v, void *opaque,
+                         const char *name, Error **errp)
+{
+    ISADevice *isa = DO_UPCAST(ISADevice, qdev, dev);
+    RTCState *s = DO_UPCAST(RTCState, dev, isa);
+
+    visit_start_struct(v, NULL, "struct tm", name, 0, errp);
+    visit_type_int32(v, &s->current_tm.tm_year, "tm_year", errp);
+    visit_type_int32(v, &s->current_tm.tm_mon, "tm_mon", errp);
+    visit_type_int32(v, &s->current_tm.tm_mday, "tm_mday", errp);
+    visit_type_int32(v, &s->current_tm.tm_hour, "tm_hour", errp);
+    visit_type_int32(v, &s->current_tm.tm_min, "tm_min", errp);
+    visit_type_int32(v, &s->current_tm.tm_sec, "tm_sec", errp);
+    visit_end_struct(v, errp);
+}
+
 static int rtc_initfn(ISADevice *dev)
 {
     RTCState *s = DO_UPCAST(RTCState, dev, dev);
@@ -647,6 +670,10 @@ static int rtc_initfn(ISADevice *dev)
 
     qdev_set_legacy_instance_id(&dev->qdev, base, 2);
     qemu_register_reset(rtc_reset, s);
+
+    qdev_property_add(&s->dev.qdev, "date", "struct tm",
+                      rtc_get_date, NULL, NULL, s, NULL);
+
     return 0;
 }
 
commit d0c5be58704640850fad02c0ff38135f2e9aa589
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:38 2011 -0600

    rtc: make piix3 set the rtc as a child (v2)
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 970f43c..2d5ea2c 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -205,6 +205,17 @@ static void pc_init1(MemoryRegion *system_memory,
         }
     }
 
+    /* FIXME there's some major spaghetti here.  Somehow we create the devices
+     * on the PIIX before we actually create it.  We create the PIIX3 deep in
+     * the recess of the i440fx creation too and then lose the DeviceState.
+     *
+     * For now, let's "fix" this by making judicious use of paths.  This is not
+     * generally the right way to do this.
+     */
+
+    qdev_property_add_child(qdev_resolve_path("/i440fx/piix3", NULL),
+                            "rtc", (DeviceState *)rtc_state, NULL);
+
     audio_init(gsi, pci_enabled ? pci_bus : NULL);
 
     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index d183443..d785d4b 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -288,6 +288,7 @@ static PCIBus *i440fx_common_init(const char *device_name,
                     address_space_io, 0);
     s->bus = b;
     qdev_init_nofail(dev);
+    qdev_property_add_child(qdev_get_root(), "i440fx", dev, NULL);
 
     d = pci_create_simple(b, 0, device_name);
     *pi440fx_state = DO_UPCAST(PCII440FXState, dev, d);
@@ -323,6 +324,8 @@ static PCIBus *i440fx_common_init(const char *device_name,
                 pci_create_simple_multifunction(b, -1, true, "PIIX3"));
         pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3,
                 PIIX_NUM_PIRQS);
+
+        qdev_property_add_child(dev, "piix3", &piix3->dev.qdev, NULL);
     }
     piix3->pic = pic;
 
commit 8eb02831af6c5534d8712cb8db1104852cac26e9
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:37 2011 -0600

    dev: add an anonymous peripheral container
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index cb3fc6e..4d491f1 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -240,6 +240,19 @@ static DeviceState *qdev_get_peripheral(void)
     return dev;
 }
 
+static DeviceState *qdev_get_peripheral_anon(void)
+{
+    static DeviceState *dev;
+
+    if (dev == NULL) {
+        dev = qdev_create(NULL, "container");
+        qdev_property_add_child(qdev_get_root(), "peripheral-anon", dev, NULL);
+        qdev_init_nofail(dev);
+    }
+
+    return dev;
+}
+
 DeviceState *qdev_device_add(QemuOpts *opts)
 {
     const char *driver, *path, *id;
@@ -292,7 +305,13 @@ DeviceState *qdev_device_add(QemuOpts *opts)
     if (id) {
         qdev->id = id;
         qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
-    }
+    } else {
+        static int anon_count;
+        gchar *name = g_strdup_printf("device[%d]", anon_count++);
+        qdev_property_add_child(qdev_get_peripheral_anon(), name,
+                                qdev, NULL);
+        g_free(name);
+    }        
     if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
         qdev_free(qdev);
         return NULL;
commit 1bdaacb18fc86366cf5a855b72247bbb1014cc21
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:36 2011 -0600

    qdev: add explicitly named devices to the root complex
    
    We first add a 'peripheral' container to the root device that we add user
    created devices to.  This provides all user created devices with a unique and
    isolated namespace.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index d448275..cb3fc6e 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -227,6 +227,19 @@ int qdev_device_help(QemuOpts *opts)
     return 1;
 }
 
+static DeviceState *qdev_get_peripheral(void)
+{
+    static DeviceState *dev;
+
+    if (dev == NULL) {
+        dev = qdev_create(NULL, "container");
+        qdev_property_add_child(qdev_get_root(), "peripheral", dev, NULL);
+        qdev_init_nofail(dev);
+    }
+
+    return dev;
+}
+
 DeviceState *qdev_device_add(QemuOpts *opts)
 {
     const char *driver, *path, *id;
@@ -278,6 +291,7 @@ DeviceState *qdev_device_add(QemuOpts *opts)
     id = qemu_opts_id(opts);
     if (id) {
         qdev->id = id;
+        qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
     }
     if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
         qdev_free(qdev);
commit eb6e8ea5c38b47a3c6cf27f4780abd92bc079caa
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:35 2011 -0600

    qom: qom_{get, set} monitor commands (v2)
    
    This allows clients to read and write device model properties through QMP.  QAPI
    doesn't support Visitor types yet and these commands are special in that they
    don't work with fixed types.
    
    I've added a documentation stub to qapi-schema.json so we can keep consistency
    there.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/monitor.h b/monitor.h
index 052f1cb..cfa2f67 100644
--- a/monitor.h
+++ b/monitor.h
@@ -67,4 +67,8 @@ typedef void (MonitorCompletion)(void *opaque, QObject *ret_data);
 
 void monitor_set_error(Monitor *mon, QError *qerror);
 
+int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret);
+
+int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret);
+
 #endif /* !MONITOR_H */
diff --git a/qapi-schema.json b/qapi-schema.json
index 7c979b2..44cf764 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1216,3 +1216,62 @@
 { 'command': 'qom-list',
   'data': { 'path': 'str' },
   'returns': [ 'DevicePropertyInfo' ] }
+
+##
+# @qom-get:
+#
+# This command will get a property from a device model path and return the
+# value.
+#
+# @path: The path within the device model.  There are two forms of supported
+#        paths--absolute and partial paths.
+#
+#        Absolute paths are derived from the root device and can follow child<>
+#        or link<> properties.  Since they can follow link<> properties, they
+#        can be arbitrarily long.  Absolute paths look like absolute filenames
+#        and are prefixed  with a leading slash.
+#
+#        Partial paths look like relative filenames.  They do not begin
+#        with a prefix.  The matching rules for partial paths are subtle but
+#        designed to make specifying devices easy.  At each level of the
+#        composition tree, the partial path is matched as an absolute path.
+#        The first match is not returned.  At least two matches are searched
+#        for.  A successful result is only returned if only one match is
+#        found.  If more than one match is found, a flag is return to
+#        indicate that the match was ambiguous.
+#
+# @property: The property name to read
+#
+# Returns: The property value.  The type depends on the property type.  legacy<>
+#          properties are returned as #str.  child<> and link<> properties are
+#          returns as #str pathnames.  All integer property types (u8, u16, etc)
+#          are returned as #int.
+#
+# Since: 1.1
+#
+# Notes: This command is experimental and may change syntax in future releases.
+##
+{ 'command': 'qom-get',
+  'data': { 'path': 'str', 'property': 'str' },
+  'returns': 'visitor',
+  'gen': 'no' }
+
+##
+# @qom-set:
+#
+# This command will set a property from a device model path.
+#
+# @path: see @qom-get for a description of this parameter
+#
+# @property: the property name to set
+#
+# @value: a value who's type is appropriate for the property type.  See @qom-get
+#         for a description of type mapping.
+#
+# Since: 1.1
+#
+# Notes: This command is experimental and may change syntax in future releases.
+##
+{ 'command': 'qom-set',
+  'data': { 'path': 'str', 'property': 'str', 'value': 'visitor' },
+  'gen': 'no' }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index c1f0718..7e3f4b9 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2015,3 +2015,15 @@ EQMP
         .args_type  = "path:s",
         .mhandler.cmd_new = qmp_marshal_input_qom_list,
     },
+
+    {
+        .name       = "qom-set",
+	.args_type  = "path:s,property:s,opts:O",
+	.mhandler.cmd_new = qmp_qom_set,
+    },
+
+    {
+        .name       = "qom-get",
+	.args_type  = "path:s,property:s",
+	.mhandler.cmd_new = qmp_qom_get,
+    },
diff --git a/qmp.c b/qmp.c
index 8e9a595..5e09b41 100644
--- a/qmp.c
+++ b/qmp.c
@@ -17,6 +17,8 @@
 #include "kvm.h"
 #include "arch_init.h"
 #include "hw/qdev.h"
+#include "qapi/qmp-input-visitor.h"
+#include "qapi/qmp-output-visitor.h"
 
 NameInfo *qmp_query_name(Error **errp)
 {
@@ -182,3 +184,66 @@ DevicePropertyInfoList *qmp_qom_list(const char *path, Error **errp)
 
     return props;
 }
+
+/* FIXME: teach qapi about how to pass through Visitors */
+int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret)
+{
+    const char *path = qdict_get_str(qdict, "path");
+    const char *property = qdict_get_str(qdict, "property");
+    QObject *value = qdict_get(qdict, "value");
+    Error *local_err = NULL;
+    QmpInputVisitor *mi;
+    DeviceState *dev;
+
+    dev = qdev_resolve_path(path, NULL);
+    if (!dev) {
+        error_set(&local_err, QERR_DEVICE_NOT_FOUND, path);
+        goto out;
+    }
+
+    mi = qmp_input_visitor_new(value);
+    qdev_property_set(dev, qmp_input_get_visitor(mi), property, &local_err);
+
+    qmp_input_visitor_cleanup(mi);
+
+out:
+    if (local_err) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -1;
+    }
+
+    return 0;
+}
+
+int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret)
+{
+    const char *path = qdict_get_str(qdict, "path");
+    const char *property = qdict_get_str(qdict, "property");
+    Error *local_err = NULL;
+    QmpOutputVisitor *mo;
+    DeviceState *dev;
+
+    dev = qdev_resolve_path(path, NULL);
+    if (!dev) {
+        error_set(&local_err, QERR_DEVICE_NOT_FOUND, path);
+        goto out;
+    }
+
+    mo = qmp_output_visitor_new();
+    qdev_property_get(dev, qmp_output_get_visitor(mo), property, &local_err);
+    if (!local_err) {
+        *ret = qmp_output_get_qobject(mo);
+    }
+
+    qmp_output_visitor_cleanup(mo);
+
+out:
+    if (local_err) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -1;
+    }
+
+    return 0;
+}
commit b4b12c6247d89b94e197891fbadb2699fd469ed6
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:34 2011 -0600

    qmp: add qom-list command
    
    This can be used to list properties in the device model.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qapi-schema.json b/qapi-schema.json
index f358b49..7c979b2 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1168,3 +1168,51 @@
 # Since: 0.14.0
 ##
 { 'command': 'migrate_set_speed', 'data': {'value': 'int'} }
+
+##
+# @DevicePropertyInfo:
+#
+# @name: the name of the property
+#
+# @type: the type of the property.  This will typically come in one of four
+#        forms:
+#
+#        1) A primitive type such as 'u8', 'u16', 'bool', 'str', or 'double'.
+#           These types are mapped to the appropriate JSON type.
+#
+#        2) A legacy type in the form 'legacy<subtype>' where subtype is the
+#           legacy qdev typename.  These types are always treated as strings.
+#
+#        3) A child type in the form 'child<subtype>' where subtype is a qdev
+#           device type name.  Child properties create the composition tree.
+#
+#        4) A link type in the form 'link<subtype>' where subtype is a qdev
+#           device type name.  Link properties form the device model graph.
+#
+# Since: 1.1
+#
+# Notes: This type is experimental.  Its syntax may change in future releases.
+##
+{ 'type': 'DevicePropertyInfo',
+  'data': { 'name': 'str', 'type': 'str' } }
+
+##
+# @qom-list:
+#
+# This command will list any properties of a device given a path in the device
+# model.
+#
+# @path: the path within the device model.  See @qom-get for a description of
+#        this parameter.
+#
+# Returns: a list of @DevicePropertyInfo that describe the properties of the
+#          device.
+#
+# Since: 1.1
+#
+# Notes: This command is experimental.  It's syntax may change in future
+#        releases.
+##
+{ 'command': 'qom-list',
+  'data': { 'path': 'str' },
+  'returns': [ 'DevicePropertyInfo' ] }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 002e7e8..c1f0718 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2009,3 +2009,9 @@ EQMP
         .args_type  = "",
         .mhandler.cmd_new = qmp_marshal_input_query_balloon,
     },
+
+    {
+        .name       = "qom-list",
+        .args_type  = "path:s",
+        .mhandler.cmd_new = qmp_marshal_input_qom_list,
+    },
diff --git a/qmp.c b/qmp.c
index d71ceb4..8e9a595 100644
--- a/qmp.c
+++ b/qmp.c
@@ -16,6 +16,7 @@
 #include "qmp-commands.h"
 #include "kvm.h"
 #include "arch_init.h"
+#include "hw/qdev.h"
 
 NameInfo *qmp_query_name(Error **errp)
 {
@@ -154,3 +155,30 @@ void qmp_cont(Error **errp)
 
     vm_start();
 }
+
+DevicePropertyInfoList *qmp_qom_list(const char *path, Error **errp)
+{
+    DeviceState *dev;
+    bool ambiguous = false;
+    DevicePropertyInfoList *props = NULL;
+    DeviceProperty *prop;
+
+    dev = qdev_resolve_path(path, &ambiguous);
+    if (dev == NULL) {
+        error_set(errp, QERR_DEVICE_NOT_FOUND, path);
+        return NULL;
+    }
+
+    QTAILQ_FOREACH(prop, &dev->properties, node) {
+        DevicePropertyInfoList *entry = g_malloc0(sizeof(*entry));
+
+        entry->value = g_malloc0(sizeof(DevicePropertyInfo));
+        entry->next = props;
+        props = entry;
+
+        entry->value->name = g_strdup(prop->name);
+        entry->value->type = g_strdup(prop->type);
+    }
+
+    return props;
+}
commit 5dbee474f352401efb404ff8dfb90a3ca90ce3d1
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:33 2011 -0600

    qapi: allow a 'gen' key to suppress code generation
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index f7def16..54d1f5d 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -405,6 +405,7 @@ except os.error, e:
 
 exprs = parse_schema(sys.stdin)
 commands = filter(lambda expr: expr.has_key('command'), exprs)
+commands = filter(lambda expr: not expr.has_key('gen'), commands)
 
 if dispatch_type == "sync":
     fdecl = open(h_file, 'w')
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index f64d84c..267cb49 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -238,6 +238,7 @@ fdecl.write(mcgen('''
                   guard=guardname(h_file)))
 
 exprs = parse_schema(sys.stdin)
+exprs = filter(lambda expr: not expr.has_key('gen'), exprs)
 
 for expr in exprs:
     ret = "\n"
commit 83e94fb8d5167d08d19eb1a84d058d9cd350bae9
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:32 2011 -0600

    qom: add link properties (v2)
    
    Links represent an ephemeral relationship between devices.  They are meant to
    replace the qdev concept of busses by allowing more informal relationships
    between devices.
    
    Links are fairly limited in their usefulness without implementing QOM-style
    subclassing and interfaces.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 167f459..d448275 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -1200,6 +1200,80 @@ void qdev_property_add_child(DeviceState *dev, const char *name,
     g_free(type);
 }
 
+static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
+                                   const char *name, Error **errp)
+{
+    DeviceState **child = opaque;
+    gchar *path;
+
+    if (*child) {
+        path = qdev_get_canonical_path(*child);
+        visit_type_str(v, &path, name, errp);
+        g_free(path);
+    } else {
+        path = (gchar *)"";
+        visit_type_str(v, &path, name, errp);
+    }
+}
+
+static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
+                                   const char *name, Error **errp)
+{
+    DeviceState **child = opaque;
+    bool ambiguous = false;
+    const char *type;
+    char *path;
+
+    type = qdev_property_get_type(dev, name, NULL);
+
+    visit_type_str(v, &path, name, errp);
+
+    if (*child) {
+        qdev_unref(*child);
+    }
+
+    if (strcmp(path, "") != 0) {
+        DeviceState *target;
+
+        target = qdev_resolve_path(path, &ambiguous);
+        if (target) {
+            gchar *target_type;
+
+            target_type = g_strdup_printf("link<%s>", target->info->name);
+            if (strcmp(target_type, type) == 0) {
+                *child = target;
+                qdev_ref(target);
+            } else {
+                error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
+            }
+
+            g_free(target_type);
+        } else {
+            error_set(errp, QERR_DEVICE_NOT_FOUND, path);
+        }
+    } else {
+        *child = NULL;
+    }
+
+    g_free(path);
+}
+
+void qdev_property_add_link(DeviceState *dev, const char *name,
+                            const char *type, DeviceState **child,
+                            Error **errp)
+{
+    gchar *full_type;
+
+    full_type = g_strdup_printf("link<%s>", type);
+
+    qdev_property_add(dev, name, full_type,
+                      qdev_get_link_property,
+                      qdev_set_link_property,
+                      NULL, child, errp);
+
+    g_free(full_type);
+}
+
 static gchar *qdev_get_path_in(DeviceState *parent, DeviceState *dev)
 {
     DeviceProperty *prop;
diff --git a/hw/qdev.h b/hw/qdev.h
index 38b36e8..4351e2e 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -547,4 +547,27 @@ DeviceState *qdev_resolve_path(const char *path, bool *ambiguous);
 void qdev_property_add_child(DeviceState *dev, const char *name,
                              DeviceState *child, Error **errp);
 
+/**
+ * @qdev_property_add_link - Add a link property to a device
+ *
+ * Links establish relationships between devices.  Links are unidirectional
+ * although two links can be combined to form a bidirectional relationship
+ * between devices.
+ *
+ * Links form the graph in the device model.
+ *
+ * @dev - the device to add a property to
+ *
+ * @name - the name of the property
+ *
+ * @type - the qdev type of the link
+ *
+ * @child - a pointer to where the link device reference is stored
+ *
+ * @errp - if an error occurs, a pointer to an area to store the area
+ */
+void qdev_property_add_link(DeviceState *dev, const char *name,
+                            const char *type, DeviceState **child,
+                            Error **errp);
+
 #endif
commit 3de1c3e82d06ac7fe789d912feb8876c0a8b270e
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:31 2011 -0600

    qom: add child properties (composition) (v3)
    
    Child properties express a relationship of composition.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 2519f00..167f459 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -1174,6 +1174,32 @@ DeviceState *qdev_get_root(void)
     return qdev_root;
 }
 
+static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
+                                    const char *name, Error **errp)
+{
+    DeviceState *child = opaque;
+    gchar *path;
+
+    path = qdev_get_canonical_path(child);
+    visit_type_str(v, &path, name, errp);
+    g_free(path);
+}
+
+void qdev_property_add_child(DeviceState *dev, const char *name,
+                             DeviceState *child, Error **errp)
+{
+    gchar *type;
+
+    type = g_strdup_printf("child<%s>", child->info->name);
+
+    qdev_property_add(dev, name, type, qdev_get_child_property,
+                      NULL, NULL, child, errp);
+
+    qdev_ref(child);
+
+    g_free(type);
+}
+
 static gchar *qdev_get_path_in(DeviceState *parent, DeviceState *dev)
 {
     DeviceProperty *prop;
diff --git a/hw/qdev.h b/hw/qdev.h
index 641d134..38b36e8 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -527,4 +527,24 @@ gchar *qdev_get_canonical_path(DeviceState *dev);
  */
 DeviceState *qdev_resolve_path(const char *path, bool *ambiguous);
 
+/**
+ * @qdev_property_add_child - Add a child property to a device
+ *
+ * Child properties form the composition tree.  All devices need to be a child
+ * of another device.  Devices can only be a child of one device.
+ *
+ * There is no way for a child to determine what its parent is.  It is not
+ * a bidirectional relationship.  This is by design.
+ *
+ * @dev - the device to add a property to
+ *
+ * @name - the name of the property
+ *
+ * @child - the child device
+ *
+ * @errp - if an error occurs, a pointer to an area to store the area
+ */
+void qdev_property_add_child(DeviceState *dev, const char *name,
+                             DeviceState *child, Error **errp);
+
 #endif
commit dc45c21f39f826e7ab4b8e86fc4d0c987fad3fb7
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:30 2011 -0600

    qdev: provide a path resolution (v2)
    
    There are two types of supported paths--absolute paths and partial paths.
    
    Absolute paths are derived from the root device and can follow child<> or
    link<> properties.  Since they can follow link<> properties, they can be
    arbitrarily long.  Absolute paths look like absolute filenames and are prefixed
    with a leading slash.
    
    Partial paths are look like relative filenames.  They do not begin with a
    prefix.  The matching rules for partial paths are subtle but designed to make
    specifying devices easy.  At each level of the composition tree, the partial
    path is matched as an absolute path.  The first match is not returned.  At
    least two matches are searched for.  A successful result is only returned if
    only one match is founded.  If more than one match is found, a flag is returned
    to indicate that the match was ambiguous.
    
    At the end of the day, partial path support means that if you create a device
    called 'ide0', you can just say 'ide0' as the path name and it will Just Work.
    If we internally create a device called 'i440fx', you can just say 'i440fx' and
    it will Just Work and long as you don't do anything silly.
    
    A management tool should probably always use absolute paths since then they
    don't have to deal with the possibility of ambiguity.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 79849c9..2519f00 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -1221,3 +1221,106 @@ gchar *qdev_get_canonical_path(DeviceState *dev)
 
     return newpath;
 }
+
+static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
+                                          gchar **parts,
+                                          int index)
+{
+    DeviceProperty *prop;
+    DeviceState *child;
+
+    if (parts[index] == NULL) {
+        return parent;
+    }
+
+    if (strcmp(parts[index], "") == 0) {
+        return qdev_resolve_abs_path(parent, parts, index + 1);
+    }
+
+    prop = qdev_property_find(parent, parts[index]);
+    if (prop == NULL) {
+        return NULL;
+    }
+
+    child = NULL;
+    if (strstart(prop->type, "link<", NULL)) {
+        DeviceState **pchild = prop->opaque;
+        if (*pchild) {
+            child = *pchild;
+        }
+    } else if (strstart(prop->type, "child<", NULL)) {
+        child = prop->opaque;
+    }
+
+    if (!child) {
+        return NULL;
+    }
+
+    return qdev_resolve_abs_path(child, parts, index + 1);
+}
+
+static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
+                                              gchar **parts,
+                                              bool *ambiguous)
+{
+    DeviceState *dev;
+    DeviceProperty *prop;
+
+    dev = qdev_resolve_abs_path(parent, parts, 0);
+
+    QTAILQ_FOREACH(prop, &parent->properties, node) {
+        DeviceState *found;
+
+        if (!strstart(prop->type, "child<", NULL)) {
+            continue;
+        }
+
+        found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
+        if (found) {
+            if (dev) {
+                if (ambiguous) {
+                    *ambiguous = true;
+                }
+                return NULL;
+            }
+            dev = found;
+        }
+
+        if (ambiguous && *ambiguous) {
+            return NULL;
+        }
+    }
+
+    return dev;
+}
+
+DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
+{
+    bool partial_path = true;
+    DeviceState *dev;
+    gchar **parts;
+
+    parts = g_strsplit(path, "/", 0);
+    if (parts == NULL || parts[0] == NULL) {
+        g_strfreev(parts);
+        return qdev_get_root();
+    }
+
+    if (strcmp(parts[0], "") == 0) {
+        partial_path = false;
+    }
+
+    if (partial_path) {
+        if (ambiguous) {
+            *ambiguous = false;
+        }
+        dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
+    } else {
+        dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
+    }
+
+    g_strfreev(parts);
+
+    return dev;
+}
+
diff --git a/hw/qdev.h b/hw/qdev.h
index 0f00497..641d134 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -499,4 +499,32 @@ DeviceState *qdev_get_root(void);
  */
 gchar *qdev_get_canonical_path(DeviceState *dev);
 
+/**
+ * @qdev_resolve_path - resolves a path returning a device
+ *
+ * There are two types of supported paths--absolute paths and partial paths.
+ * 
+ * Absolute paths are derived from the root device and can follow child<> or
+ * link<> properties.  Since they can follow link<> properties, they can be
+ * arbitrarily long.  Absolute paths look like absolute filenames and are
+ * prefixed with a leading slash.
+ * 
+ * Partial paths look like relative filenames.  They do not begin with a
+ * prefix.  The matching rules for partial paths are subtle but designed to make
+ * specifying devices easy.  At each level of the composition tree, the partial
+ * path is matched as an absolute path.  The first match is not returned.  At
+ * least two matches are searched for.  A successful result is only returned if
+ * only one match is founded.  If more than one match is found, a flag is
+ * return to indicate that the match was ambiguous.
+ *
+ * @path - the path to resolve
+ *
+ * @ambiguous - returns true if the path resolution failed because of an
+ *              ambiguous match
+ *
+ * Returns:
+ *   The matched device or NULL on path lookup failure.
+ */
+DeviceState *qdev_resolve_path(const char *path, bool *ambiguous);
+
 #endif
commit f9fbd2fd0e1ffe666487a072226dd87753db66f9
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:29 2011 -0600

    qdev: provide an interface to return canonical path from root (v2)
    
    The canonical path is the path in the composition tree from the root to the
    device.  This is effectively the name of the device.
    
    This is an incredibly unefficient implementation that will be optimized in
    a future patch.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index bb0b9f7..79849c9 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -1173,3 +1173,51 @@ DeviceState *qdev_get_root(void)
 
     return qdev_root;
 }
+
+static gchar *qdev_get_path_in(DeviceState *parent, DeviceState *dev)
+{
+    DeviceProperty *prop;
+
+    if (parent == dev) {
+        return g_strdup("");
+    }
+
+    QTAILQ_FOREACH(prop, &parent->properties, node) {
+        gchar *subpath;
+
+        if (!strstart(prop->type, "child<", NULL)) {
+            continue;
+        }
+
+        /* Check to see if the device is one of parent's children */
+        if (prop->opaque == dev) {
+            return g_strdup(prop->name);
+        }
+
+        /* Check to see if the device is a child of our child */
+        subpath = qdev_get_path_in(prop->opaque, dev);
+        if (subpath) {
+            gchar *path;
+
+            path = g_strdup_printf("%s/%s", prop->name, subpath);
+            g_free(subpath);
+
+            return path;
+        }
+    }
+
+    return NULL;
+}
+
+gchar *qdev_get_canonical_path(DeviceState *dev)
+{
+    gchar *path, *newpath;
+
+    path = qdev_get_path_in(qdev_get_root(), dev);
+    g_assert(path != NULL);
+
+    newpath = g_strdup_printf("/%s", path);
+    g_free(path);
+
+    return newpath;
+}
diff --git a/hw/qdev.h b/hw/qdev.h
index 52aadd2..0f00497 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -490,4 +490,13 @@ void qdev_property_add_legacy(DeviceState *dev, Property *prop, Error **errp);
  */
 DeviceState *qdev_get_root(void);
 
+/**
+ * @qdev_get_canonical_path - returns the canonical path for a device.  This
+ * is the path within the composition tree starting from the root.
+ *
+ * Returns:
+ *   The canonical path in the composition tree.
+ */
+gchar *qdev_get_canonical_path(DeviceState *dev);
+
 #endif
commit a10f07a7d0827eeef920c16b500b50030b7ff651
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:28 2011 -0600

    qom: introduce root device
    
    This is based on Jan's suggestion for how to do unique naming.  The root device
    is the root of composition.  All devices are reachable via child<> links from
    this device.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile.objs b/Makefile.objs
index 281b698..f753d83 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -278,7 +278,7 @@ hw-obj-$(CONFIG_LSI_SCSI_PCI) += lsi53c895a.o
 hw-obj-$(CONFIG_ESP) += esp.o
 
 hw-obj-y += dma-helpers.o sysbus.o isa-bus.o
-hw-obj-y += qdev-addr.o
+hw-obj-y += qdev-addr.o container.o
 
 # VGA
 hw-obj-$(CONFIG_VGA_PCI) += vga-pci.o
diff --git a/hw/container.c b/hw/container.c
new file mode 100644
index 0000000..9cbf399
--- /dev/null
+++ b/hw/container.c
@@ -0,0 +1,20 @@
+#include "sysbus.h"
+
+static int container_initfn(SysBusDevice *dev)
+{
+    return 0;
+}
+
+static SysBusDeviceInfo container_info = {
+    .init = container_initfn,
+    .qdev.name = "container",
+    .qdev.size = sizeof(SysBusDevice),
+    .qdev.no_user = 1,
+};
+
+static void container_init(void)
+{
+    sysbus_register_withprop(&container_info);
+}
+
+device_init(container_init);
diff --git a/hw/qdev.c b/hw/qdev.c
index 6f77af9..bb0b9f7 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -1161,3 +1161,15 @@ void qdev_property_add_legacy(DeviceState *dev, Property *prop,
 
     g_free(type);
 }
+
+DeviceState *qdev_get_root(void)
+{
+    static DeviceState *qdev_root;
+
+    if (!qdev_root) {
+        qdev_root = qdev_create(NULL, "container");
+        qdev_init_nofail(qdev_root);
+    }
+
+    return qdev_root;
+}
diff --git a/hw/qdev.h b/hw/qdev.h
index 3b629d4..52aadd2 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -482,4 +482,12 @@ const char *qdev_property_get_type(DeviceState *dev, const char *name,
  */
 void qdev_property_add_legacy(DeviceState *dev, Property *prop, Error **errp);
 
+/**
+ * @qdev_get_root - returns the root device of the composition tree
+ *
+ * Returns:
+ *   The root of the composition tree.
+ */
+DeviceState *qdev_get_root(void);
+
 #endif
commit a5296ca9df745d8af319282ab5d85439c211bb10
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:27 2011 -0600

    qom: register legacy properties as new style properties (v2)
    
    Expose all legacy properties through the new QOM property mechanism.  The qdev
    property types are exposed through the 'legacy<>' namespace.  They are always
    visited as strings since they do their own string parsing.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 94f14c1..6f77af9 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -83,6 +83,7 @@ static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
 static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
 {
     DeviceState *dev;
+    Property *prop;
 
     assert(bus->info == info->bus_info);
     dev = g_malloc0(info->size);
@@ -100,6 +101,15 @@ static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
     dev->instance_id_alias = -1;
     QTAILQ_INIT(&dev->properties);
     dev->state = DEV_STATE_CREATED;
+
+    for (prop = dev->info->props; prop && prop->name; prop++) {
+        qdev_property_add_legacy(dev, prop, NULL);
+    }
+
+    for (prop = dev->info->bus_info->props; prop && prop->name; prop++) {
+        qdev_property_add_legacy(dev, prop, NULL);
+    }
+
     return dev;
 }
 
@@ -1075,3 +1085,79 @@ const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **e
 
     return prop->type;
 }
+
+/**
+ * Legacy property handling
+ */
+
+static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
+                                     const char *name, Error **errp)
+{
+    Property *prop = opaque;
+
+    if (prop->info->print) {
+        char buffer[1024];
+        char *ptr = buffer;
+
+        prop->info->print(dev, prop, buffer, sizeof(buffer));
+        visit_type_str(v, &ptr, name, errp);
+    } else {
+        error_set(errp, QERR_PERMISSION_DENIED);
+    }
+}
+
+static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
+                                     const char *name, Error **errp)
+{
+    Property *prop = opaque;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    if (prop->info->parse) {
+        Error *local_err = NULL;
+        char *ptr = NULL;
+
+        visit_type_str(v, &ptr, name, &local_err);
+        if (!local_err) {
+            int ret;
+            ret = prop->info->parse(dev, prop, ptr);
+            if (ret != 0) {
+                error_set(errp, QERR_INVALID_PARAMETER_VALUE,
+                          name, prop->info->name);
+            }
+            g_free(ptr);
+        } else {
+            error_propagate(errp, local_err);
+        }
+    } else {
+        error_set(errp, QERR_PERMISSION_DENIED);
+    }
+}
+
+/**
+ * @qdev_add_legacy_property - adds a legacy property
+ *
+ * Do not use this is new code!  Properties added through this interface will
+ * be given types in the "legacy<>" type namespace.
+ *
+ * Legacy properties are always processed as strings.  The format of the string
+ * depends on the property type.
+ */
+void qdev_property_add_legacy(DeviceState *dev, Property *prop,
+                              Error **errp)
+{
+    gchar *type;
+
+    type = g_strdup_printf("legacy<%s>", prop->info->name);
+
+    qdev_property_add(dev, prop->name, type,
+                      qdev_get_legacy_property,
+                      qdev_set_legacy_property,
+                      NULL,
+                      prop, errp);
+
+    g_free(type);
+}
diff --git a/hw/qdev.h b/hw/qdev.h
index 2df3bb7..3b629d4 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -475,4 +475,11 @@ void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
 const char *qdev_property_get_type(DeviceState *dev, const char *name,
                                    Error **errp);
 
+/**
+ * @qdev_property_add_legacy - add a legacy @Property to a device
+ *
+ * DO NOT USE THIS IN NEW CODE!
+ */
+void qdev_property_add_legacy(DeviceState *dev, Property *prop, Error **errp);
+
 #endif
commit 44677ded43f1dec44fabfe52f3a4f6eb28134f95
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:26 2011 -0600

    qom: add new dynamic property infrastructure based on Visitors (v2)
    
    qdev properties are settable only during construction and static to classes.
    This isn't flexible enough for QOM.
    
    This patch introduces a property interface for qdev that provides dynamic
    properties that are tied to objects, instead of classes.  These properties are
    Visitor based instead of string based too.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index fdc9843..94f14c1 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -98,6 +98,7 @@ static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
         qdev_hot_added = true;
     }
     dev->instance_id_alias = -1;
+    QTAILQ_INIT(&dev->properties);
     dev->state = DEV_STATE_CREATED;
     return dev;
 }
@@ -395,12 +396,31 @@ void qdev_init_nofail(DeviceState *dev)
     }
 }
 
+static void qdev_property_del_all(DeviceState *dev)
+{
+    while (!QTAILQ_EMPTY(&dev->properties)) {
+        DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
+
+        QTAILQ_REMOVE(&dev->properties, prop, node);
+
+        if (prop->release) {
+            prop->release(dev, prop->name, prop->opaque);
+        }
+
+        g_free(prop->name);
+        g_free(prop->type);
+        g_free(prop);
+    }
+}
+
 /* Unlink device from bus and free the structure.  */
 void qdev_free(DeviceState *dev)
 {
     BusState *bus;
     Property *prop;
 
+    qdev_property_del_all(dev);
+
     if (dev->state == DEV_STATE_INITIALIZED) {
         while (dev->num_child_bus) {
             bus = QLIST_FIRST(&dev->child_bus);
@@ -978,3 +998,80 @@ void qdev_unref(DeviceState *dev)
     g_assert(dev->ref > 0);
     dev->ref--;
 }
+
+void qdev_property_add(DeviceState *dev, const char *name, const char *type,
+                       DevicePropertyAccessor *get, DevicePropertyAccessor *set,
+                       DevicePropertyRelease *release,
+                       void *opaque, Error **errp)
+{
+    DeviceProperty *prop = g_malloc0(sizeof(*prop));
+
+    prop->name = g_strdup(name);
+    prop->type = g_strdup(type);
+
+    prop->get = get;
+    prop->set = set;
+    prop->release = release;
+    prop->opaque = opaque;
+
+    QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
+}
+
+static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
+{
+    DeviceProperty *prop;
+
+    QTAILQ_FOREACH(prop, &dev->properties, node) {
+        if (strcmp(prop->name, name) == 0) {
+            return prop;
+        }
+    }
+
+    return NULL;
+}
+
+void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
+                       Error **errp)
+{
+    DeviceProperty *prop = qdev_property_find(dev, name);
+
+    if (prop == NULL) {
+        error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
+        return;
+    }
+
+    if (!prop->get) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+    } else {
+        prop->get(dev, v, prop->opaque, name, errp);
+    }
+}
+
+void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
+                       Error **errp)
+{
+    DeviceProperty *prop = qdev_property_find(dev, name);
+
+    if (prop == NULL) {
+        error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
+        return;
+    }
+
+    if (!prop->set) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+    } else {
+        prop->set(dev, prop->opaque, v, name, errp);
+    }
+}
+
+const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
+{
+    DeviceProperty *prop = qdev_property_find(dev, name);
+
+    if (prop == NULL) {
+        error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
+        return NULL;
+    }
+
+    return prop->type;
+}
diff --git a/hw/qdev.h b/hw/qdev.h
index 2397b4e..2df3bb7 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -5,6 +5,7 @@
 #include "qemu-queue.h"
 #include "qemu-char.h"
 #include "qemu-option.h"
+#include "qapi/qapi-visit-core.h"
 
 typedef struct Property Property;
 
@@ -27,6 +28,44 @@ enum {
     DEV_NVECTORS_UNSPECIFIED = -1,
 };
 
+/**
+ * @DevicePropertyAccessor - called when trying to get/set a property
+ *
+ * @dev the device that owns the property
+ * @v the visitor that contains the property data
+ * @opaque the device property opaque
+ * @name the name of the property
+ * @errp a pointer to an Error that is filled if getting/setting fails.
+ */
+typedef void (DevicePropertyAccessor)(DeviceState *dev,
+                                      Visitor *v,
+                                      void *opaque,
+                                      const char *name,
+                                      Error **errp);
+
+/**
+ * @DevicePropertyRelease - called when a property is removed from a device
+ *
+ * @dev the device that owns the property
+ * @name the name of the property
+ * @opaque the opaque registered with the property
+ */
+typedef void (DevicePropertyRelease)(DeviceState *dev,
+                                     const char *name,
+                                     void *opaque);
+
+typedef struct DeviceProperty
+{
+    gchar *name;
+    gchar *type;
+    DevicePropertyAccessor *get;
+    DevicePropertyAccessor *set;
+    DevicePropertyRelease *release;
+    void *opaque;
+
+    QTAILQ_ENTRY(DeviceProperty) node;
+} DeviceProperty;
+
 /* This structure should not be accessed directly.  We declare it here
    so that it can be embedded in individual device state structures.  */
 struct DeviceState {
@@ -51,6 +90,8 @@ struct DeviceState {
      * more information.
      */
     uint32_t ref;
+
+    QTAILQ_HEAD(, DeviceProperty) properties;
 };
 
 typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent);
@@ -355,4 +396,83 @@ void qdev_ref(DeviceState *dev);
  */
 void qdev_unref(DeviceState *dev);
 
+/**
+ * @qdev_property_add - add a new property to a device
+ *
+ * @dev - the device to add a property to
+ *
+ * @name - the name of the property.  This can contain any character except for
+ *         a forward slash.  In general, you should use hyphens '-' instead of
+ *         underscores '_' when naming properties.
+ *
+ * @type - the type name of the property.  This namespace is pretty loosely
+ *         defined.  Sub namespaces are constructed by using a prefix and then
+ *         to angle brackets.  For instance, the type 'virtio-net-pci' in the
+ *         'link' namespace would be 'link<virtio-net-pci>'.
+ *
+ * @get - the getter to be called to read a property.  If this is NULL, then
+ *        the property cannot be read.
+ *
+ * @set - the setter to be called to write a property.  If this is NULL,
+ *        then the property cannot be written.
+ *
+ * @release - called when the property is removed from the device.  This is
+ *            meant to allow a property to free its opaque upon device
+ *            destruction.  This may be NULL.
+ *
+ * @opaque - an opaque pointer to pass to the callbacks for the property
+ *
+ * @errp - returns an error if this function fails
+ */
+void qdev_property_add(DeviceState *dev, const char *name, const char *type,
+                       DevicePropertyAccessor *get, DevicePropertyAccessor *set,
+                       DevicePropertyRelease *release,
+                       void *opaque, Error **errp);
+
+/**
+ * @qdev_property_get - reads a property from a device
+ *
+ * @dev - the device
+ *
+ * @v - the visitor that will receive the property value.  This should be an
+ *      Output visitor and the data will be written with @name as the name.
+ *
+ * @name - the name of the property
+ *
+ * @errp - returns an error if this function fails
+ */
+void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
+                       Error **errp);
+
+/**
+ * @qdev_property_set - writes a property to a device
+ *
+ * @dev - the device
+ *
+ * @v - the visitor that will be used to write the property value.  This should
+ *      be an Input visitor and the data will be first read with @name as the
+ *      name and then written as the property value.
+ *
+ * @name - the name of the property
+ *
+ * @errp - returns an error if this function fails
+ */
+void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
+                       Error **errp);
+
+/**
+ * @qdev_property_get_type - returns the type of a property
+ *
+ * @dev - the device
+ *
+ * @name - the name of the property
+ *
+ * @errp - returns an error if this function fails
+ *
+ * Returns:
+ *   The type name of the property.
+ */
+const char *qdev_property_get_type(DeviceState *dev, const char *name,
+                                   Error **errp);
+
 #endif
diff --git a/qerror.c b/qerror.c
index 830c9c3..adde8a5 100644
--- a/qerror.c
+++ b/qerror.c
@@ -186,6 +186,10 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Could not open '%(filename)'",
     },
     {
+        .error_fmt = QERR_PERMISSION_DENIED,
+        .desc      = "Insufficient permission to perform this operation",
+    },
+    {
         .error_fmt = QERR_PROPERTY_NOT_FOUND,
         .desc      = "Property '%(device).%(property)' not found",
     },
diff --git a/qerror.h b/qerror.h
index 688e700..9190b02 100644
--- a/qerror.h
+++ b/qerror.h
@@ -156,6 +156,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_OPEN_FILE_FAILED \
     "{ 'class': 'OpenFileFailed', 'data': { 'filename': %s } }"
 
+#define QERR_PERMISSION_DENIED \
+    "{ 'class': 'PermissionDenied', 'data': {} }"
+
 #define QERR_PROPERTY_NOT_FOUND \
     "{ 'class': 'PropertyNotFound', 'data': { 'device': %s, 'property': %s } }"
 
commit 85ed303bfe1f67a4c18ffe51916e73cffd7d9e9b
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 14:29:25 2011 -0600

    qom: add a reference count to qdev objects
    
    To ensure that a device isn't removed from the graph until all of its links are
    broken.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 106407f..fdc9843 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -323,6 +323,11 @@ int qdev_unplug(DeviceState *dev)
     }
     assert(dev->info->unplug != NULL);
 
+    if (dev->ref != 0) {
+        qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
+        return -1;
+    }
+
     qdev_hot_removed = true;
 
     return dev->info->unplug(dev);
@@ -962,3 +967,14 @@ char* qdev_get_fw_dev_path(DeviceState *dev)
 
     return strdup(path);
 }
+
+void qdev_ref(DeviceState *dev)
+{
+    dev->ref++;
+}
+
+void qdev_unref(DeviceState *dev)
+{
+    g_assert(dev->ref > 0);
+    dev->ref--;
+}
diff --git a/hw/qdev.h b/hw/qdev.h
index 36a4198..2397b4e 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -45,6 +45,12 @@ struct DeviceState {
     QTAILQ_ENTRY(DeviceState) sibling;
     int instance_id_alias;
     int alias_required_for_version;
+
+    /**
+     * This tracks the number of references between devices.  See @qdev_ref for
+     * more information.
+     */
+    uint32_t ref;
 };
 
 typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent);
@@ -329,4 +335,24 @@ char *qdev_get_fw_dev_path(DeviceState *dev);
 /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
 extern struct BusInfo system_bus_info;
 
+/**
+ * @qdev_ref
+ *
+ * Increase the reference count of a device.  A device cannot be freed as long
+ * as its reference count is greater than zero.
+ *
+ * @dev - the device
+ */
+void qdev_ref(DeviceState *dev);
+
+/**
+ * @qdef_unref
+ *
+ * Decrease the reference count of a device.  A device cannot be freed as long
+ * as its reference count is greater than zero.
+ *
+ * @dev - the device
+ */
+void qdev_unref(DeviceState *dev);
+
 #endif
commit bd83b3620517ef9f2079cfda465953e60263f623
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Nov 25 12:06:22 2011 +0100

    qiov: prevent double free or use-after-free
    
    qemu_iovec_destroy does not clear the QEMUIOVector fully, and the data
    could thus be used after free or freed again.  While I do not know any
    example in the tree, I observed this using virtio-scsi (and SCSI
    scatter/gather) when canceling DMA requests.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/cutils.c b/cutils.c
index 6db6304..24b3fe3 100644
--- a/cutils.c
+++ b/cutils.c
@@ -217,7 +217,10 @@ void qemu_iovec_destroy(QEMUIOVector *qiov)
 {
     assert(qiov->nalloc != -1);
 
+    qemu_iovec_reset(qiov);
     g_free(qiov->iov);
+    qiov->nalloc = 0;
+    qiov->iov = NULL;
 }
 
 void qemu_iovec_reset(QEMUIOVector *qiov)
commit 16d2fc002a01cdd77e696ecc69de54db6720476a
Author: Li Zhi Hui <zhihuili at linux.vnet.ibm.com>
Date:   Mon Dec 12 13:54:33 2011 +0800

    block/cow: Return real error code
    
    Signed-off-by: Li Zhi Hui <zhihuili at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/cow.c b/block/cow.c
index 3c52735..bb5927c 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -64,15 +64,26 @@ static int cow_open(BlockDriverState *bs, int flags)
     struct cow_header_v2 cow_header;
     int bitmap_size;
     int64_t size;
+    int ret;
 
     /* see if it is a cow image */
-    if (bdrv_pread(bs->file, 0, &cow_header, sizeof(cow_header)) !=
-            sizeof(cow_header)) {
+    ret = bdrv_pread(bs->file, 0, &cow_header, sizeof(cow_header));
+    if (ret < 0) {
+        goto fail;
+    }
+
+    if (be32_to_cpu(cow_header.magic) != COW_MAGIC) {
+        ret = -EINVAL;
         goto fail;
     }
 
-    if (be32_to_cpu(cow_header.magic) != COW_MAGIC ||
-        be32_to_cpu(cow_header.version) != COW_VERSION) {
+    if (be32_to_cpu(cow_header.version) != COW_VERSION) {
+        char version[64];
+        snprintf(version, sizeof(version),
+               "COW version %d", cow_header.version);
+        qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
+            bs->device_name, "cow", version);
+        ret = -ENOTSUP;
         goto fail;
     }
 
@@ -88,7 +99,7 @@ static int cow_open(BlockDriverState *bs, int flags)
     qemu_co_mutex_init(&s->lock);
     return 0;
  fail:
-    return -1;
+    return ret;
 }
 
 /*
@@ -182,17 +193,19 @@ static int coroutine_fn cow_read(BlockDriverState *bs, int64_t sector_num,
             ret = bdrv_pread(bs->file,
                         s->cow_sectors_offset + sector_num * 512,
                         buf, n * 512);
-            if (ret != n * 512)
-                return -1;
+            if (ret < 0) {
+                return ret;
+            }
         } else {
             if (bs->backing_hd) {
                 /* read from the base image */
                 ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
-                if (ret < 0)
-                    return -1;
+                if (ret < 0) {
+                    return ret;
+                }
             } else {
-            memset(buf, 0, n * 512);
-        }
+                memset(buf, 0, n * 512);
+            }
         }
         nb_sectors -= n;
         sector_num += n;
@@ -220,8 +233,9 @@ static int cow_write(BlockDriverState *bs, int64_t sector_num,
 
     ret = bdrv_pwrite(bs->file, s->cow_sectors_offset + sector_num * 512,
                       buf, nb_sectors * 512);
-    if (ret != nb_sectors * 512)
-        return -1;
+    if (ret < 0) {
+        return ret;
+    }
 
     return cow_update_bitmap(bs, sector_num, nb_sectors);
 }
@@ -288,14 +302,14 @@ static int cow_create(const char *filename, QEMUOptionParameter *options)
     cow_header.sectorsize = cpu_to_be32(512);
     cow_header.size = cpu_to_be64(image_sectors * 512);
     ret = bdrv_pwrite(cow_bs, 0, &cow_header, sizeof(cow_header));
-    if (ret != sizeof(cow_header)) {
+    if (ret < 0) {
         goto exit;
     }
 
     /* resize to include at least all the bitmap */
     ret = bdrv_truncate(cow_bs,
         sizeof(cow_header) + ((image_sectors + 7) >> 3));
-    if (ret) {
+    if (ret < 0) {
         goto exit;
     }
 
commit 39a7a362e16bb27e98738d63f24d1ab5811e26a8
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Dec 5 19:20:12 2011 +0200

    coroutine: switch per-thread free pool to a global pool
    
    ucontext-based coroutines use a free pool to reduce allocations and
    deallocations of coroutine objects.  The pool is per-thread, presumably
    to improve locality.  However, as coroutines are usually allocated in
    a vcpu thread and freed in the I/O thread, the pool accounting gets
    screwed up and we end allocating and freeing a coroutine for every I/O
    request.  This is expensive since large objects are allocated via the
    kernel, and are not cached by the C runtime.
    
    Fix by switching to a global pool.  This is safe since we're protected
    by the global mutex.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/coroutine-ucontext.c b/coroutine-ucontext.c
index 2b8d3e9..3d01075 100644
--- a/coroutine-ucontext.c
+++ b/coroutine-ucontext.c
@@ -35,6 +35,10 @@ enum {
     POOL_MAX_SIZE = 64,
 };
 
+/** Free list to speed up creation */
+static QLIST_HEAD(, Coroutine) pool = QLIST_HEAD_INITIALIZER(pool);
+static unsigned int pool_size;
+
 typedef struct {
     Coroutine base;
     void *stack;
@@ -48,10 +52,6 @@ typedef struct {
     /** Currently executing coroutine */
     Coroutine *current;
 
-    /** Free list to speed up creation */
-    QLIST_HEAD(, Coroutine) pool;
-    unsigned int pool_size;
-
     /** The default coroutine */
     CoroutineUContext leader;
 } CoroutineThreadState;
@@ -75,7 +75,6 @@ static CoroutineThreadState *coroutine_get_thread_state(void)
     if (!s) {
         s = g_malloc0(sizeof(*s));
         s->current = &s->leader.base;
-        QLIST_INIT(&s->pool);
         pthread_setspecific(thread_state_key, s);
     }
     return s;
@@ -84,14 +83,19 @@ static CoroutineThreadState *coroutine_get_thread_state(void)
 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;
 
-    QLIST_FOREACH_SAFE(co, &s->pool, pool_next, tmp) {
+    QLIST_FOREACH_SAFE(co, &pool, pool_next, tmp) {
         g_free(DO_UPCAST(CoroutineUContext, base, co)->stack);
         g_free(co);
     }
-    g_free(s);
 }
 
 static void __attribute__((constructor)) coroutine_init(void)
@@ -169,13 +173,12 @@ static Coroutine *coroutine_new(void)
 
 Coroutine *qemu_coroutine_new(void)
 {
-    CoroutineThreadState *s = coroutine_get_thread_state();
     Coroutine *co;
 
-    co = QLIST_FIRST(&s->pool);
+    co = QLIST_FIRST(&pool);
     if (co) {
         QLIST_REMOVE(co, pool_next);
-        s->pool_size--;
+        pool_size--;
     } else {
         co = coroutine_new();
     }
@@ -184,13 +187,12 @@ Coroutine *qemu_coroutine_new(void)
 
 void qemu_coroutine_delete(Coroutine *co_)
 {
-    CoroutineThreadState *s = coroutine_get_thread_state();
     CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_);
 
-    if (s->pool_size < POOL_MAX_SIZE) {
-        QLIST_INSERT_HEAD(&s->pool, &co->base, pool_next);
+    if (pool_size < POOL_MAX_SIZE) {
+        QLIST_INSERT_HEAD(&pool, &co->base, pool_next);
         co->base.caller = NULL;
-        s->pool_size++;
+        pool_size++;
         return;
     }
 
commit c2c9a46609164a36b477f6cff1d10ed27a6b53fc
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Nov 16 11:35:54 2011 +0100

    qcow2: Allow >4 GB VM state
    
    This is a compatible extension to the snapshot header format that allows
    saving a 64 bit VM state size.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.h b/block.h
index 0e3ff9f..3bd4398 100644
--- a/block.h
+++ b/block.h
@@ -22,7 +22,7 @@ typedef struct QEMUSnapshotInfo {
     /* the following fields are informative. They are not needed for
        the consistency of the snapshot */
     char name[256]; /* user chosen name */
-    uint32_t vm_state_size; /* VM state info size */
+    uint64_t vm_state_size; /* VM state info size */
     uint32_t date_sec; /* UTC date of the snapshot */
     uint32_t date_nsec;
     uint64_t vm_clock_nsec; /* VM clock relative to boot */
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index c3112bf..7d3fde5 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -46,6 +46,10 @@ typedef struct QEMU_PACKED QCowSnapshotHeader {
     /* name follows  */
 } QCowSnapshotHeader;
 
+typedef struct QEMU_PACKED QCowSnapshotExtraData {
+    uint64_t vm_state_size_large;
+} QCowSnapshotExtraData;
+
 void qcow2_free_snapshots(BlockDriverState *bs)
 {
     BDRVQcowState *s = bs->opaque;
@@ -64,6 +68,7 @@ int qcow2_read_snapshots(BlockDriverState *bs)
 {
     BDRVQcowState *s = bs->opaque;
     QCowSnapshotHeader h;
+    QCowSnapshotExtraData extra;
     QCowSnapshot *sn;
     int i, id_str_size, name_size;
     int64_t offset;
@@ -100,9 +105,18 @@ int qcow2_read_snapshots(BlockDriverState *bs)
         id_str_size = be16_to_cpu(h.id_str_size);
         name_size = be16_to_cpu(h.name_size);
 
-        /* Skip extra data */
+        /* Read extra data */
+        ret = bdrv_pread(bs->file, offset, &extra,
+                         MIN(sizeof(extra), extra_data_size));
+        if (ret < 0) {
+            goto fail;
+        }
         offset += extra_data_size;
 
+        if (extra_data_size >= 8) {
+            sn->vm_state_size = be64_to_cpu(extra.vm_state_size_large);
+        }
+
         /* Read snapshot ID */
         sn->id_str = g_malloc(id_str_size + 1);
         ret = bdrv_pread(bs->file, offset, sn->id_str, id_str_size);
@@ -136,6 +150,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
     BDRVQcowState *s = bs->opaque;
     QCowSnapshot *sn;
     QCowSnapshotHeader h;
+    QCowSnapshotExtraData extra;
     int i, name_size, id_str_size, snapshots_size;
     struct {
         uint32_t nb_snapshots;
@@ -150,6 +165,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
         sn = s->snapshots + i;
         offset = align_offset(offset, 8);
         offset += sizeof(h);
+        offset += sizeof(extra);
         offset += strlen(sn->id_str);
         offset += strlen(sn->name);
     }
@@ -169,10 +185,18 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
         memset(&h, 0, sizeof(h));
         h.l1_table_offset = cpu_to_be64(sn->l1_table_offset);
         h.l1_size = cpu_to_be32(sn->l1_size);
-        h.vm_state_size = cpu_to_be32(sn->vm_state_size);
+        /* If it doesn't fit in 32 bit, older implementations should treat it
+         * as a disk-only snapshot rather than truncate the VM state */
+        if (sn->vm_state_size <= 0xffffffff) {
+            h.vm_state_size = cpu_to_be32(sn->vm_state_size);
+        }
         h.date_sec = cpu_to_be32(sn->date_sec);
         h.date_nsec = cpu_to_be32(sn->date_nsec);
         h.vm_clock_nsec = cpu_to_be64(sn->vm_clock_nsec);
+        h.extra_data_size = cpu_to_be32(sizeof(extra));
+
+        memset(&extra, 0, sizeof(extra));
+        extra.vm_state_size_large = cpu_to_be64(sn->vm_state_size);
 
         id_str_size = strlen(sn->id_str);
         name_size = strlen(sn->name);
@@ -186,6 +210,12 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
         }
         offset += sizeof(h);
 
+        ret = bdrv_pwrite(bs->file, offset, &extra, sizeof(extra));
+        if (ret < 0) {
+            goto fail;
+        }
+        offset += sizeof(extra);
+
         ret = bdrv_pwrite(bs->file, offset, sn->id_str, id_str_size);
         if (ret < 0) {
             goto fail;
diff --git a/block/qcow2.h b/block/qcow2.h
index 4e44eea..99e4536 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -78,7 +78,7 @@ typedef struct QCowSnapshot {
     uint32_t l1_size;
     char *id_str;
     char *name;
-    uint32_t vm_state_size;
+    uint64_t vm_state_size;
     uint32_t date_sec;
     uint32_t date_nsec;
     uint64_t vm_clock_nsec;
diff --git a/docs/specs/qcow2.txt b/docs/specs/qcow2.txt
index e792953..b6adcad 100644
--- a/docs/specs/qcow2.txt
+++ b/docs/specs/qcow2.txt
@@ -253,7 +253,13 @@ Snapshot table entry:
         36 - 39:    Size of extra data in the table entry (used for future
                     extensions of the format)
 
-        variable:   Extra data for future extensions. Must be ignored.
+        variable:   Extra data for future extensions. Unknown fields must be
+                    ignored. Currently defined are (offset relative to snapshot
+                    table entry):
+
+                    Byte 40 - 47:   Size of the VM state in bytes. 0 if no VM
+                                    state is saved. If this field is present,
+                                    the 32-bit value in bytes 32-35 is ignored.
 
         variable:   Unique ID string for the snapshot (not null terminated)
 
diff --git a/savevm.c b/savevm.c
index b72f6c0..f153c25 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2002,7 +2002,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
     int ret;
     QEMUFile *f;
     int saved_vm_running;
-    uint32_t vm_state_size;
+    uint64_t vm_state_size;
 #ifdef _WIN32
     struct _timeb tb;
     struct tm *ptm;
commit 3763f26f2fdff156fec6868b651fe7853fc64de5
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Dec 7 13:57:13 2011 +0100

    Documentation: Add qemu-img -t parameter in man page
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index 4be00a5..49dce7c 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -24,13 +24,13 @@ ETEXI
 DEF("commit", img_commit,
     "commit [-f fmt] [-t cache] filename")
 STEXI
- at item commit [-f @var{fmt}] @var{filename}
+ at item commit [-f @var{fmt}] [-t @var{cache}] @var{filename}
 ETEXI
 
 DEF("convert", img_convert,
     "convert [-c] [-p] [-f fmt] [-t cache] [-O output_fmt] [-o options] [-s snapshot_name] [-S sparse_size] filename [filename2 [...]] output_filename")
 STEXI
- at item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
+ at item convert [-c] [-p] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
 ETEXI
 
 DEF("info", img_info,
@@ -48,7 +48,7 @@ ETEXI
 DEF("rebase", img_rebase,
     "rebase [-f fmt] [-t cache] [-p] [-u] -b backing_file [-F backing_fmt] filename")
 STEXI
- at item rebase [-f @var{fmt}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
+ at item rebase [-f @var{fmt}] [-t @var{cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
 ETEXI
 
 DEF("resize", img_resize,
diff --git a/qemu-img.texi b/qemu-img.texi
index 70fa321..b2ca3a5 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -45,6 +45,10 @@ indicates the consecutive number of bytes that must contain only zeros
 for qemu-img to create a sparse image during conversion. This value is rounded
 down to the nearest 512 bytes. You may use the common size suffixes like
 @code{k} for kilobytes.
+ at item -t @var{cache}
+specifies the cache mode that should be used with the (destination) file. See
+the documentation of the emulator's @code{-drive cache=...} option for allowed
+values.
 @end table
 
 Parameters to snapshot subcommand:
@@ -87,11 +91,11 @@ this case. @var{backing_file} will never be modified unless you use the
 The size can also be specified using the @var{size} option with @code{-o},
 it doesn't need to be specified separately in this case.
 
- at item commit [-f @var{fmt}] @var{filename}
+ at item commit [-f @var{fmt}] [-t @var{cache}] @var{filename}
 
 Commit the changes recorded in @var{filename} in its base image.
 
- at item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
+ at item convert [-c] [-p] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
 
 Convert the disk image @var{filename} or a snapshot @var{snapshot_name} to disk image @var{output_filename}
 using format @var{output_fmt}. It can be optionally compressed (@code{-c}
@@ -121,7 +125,7 @@ they are displayed too.
 
 List, apply, create or delete snapshots in image @var{filename}.
 
- at item rebase [-f @var{fmt}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
+ at item rebase [-f @var{fmt}] [-t @var{cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
 
 Changes the backing file of an image. Only the formats @code{qcow2} and
 @code{qed} support changing the backing file.
commit 87a1b3e381c282b143023c411df284175f0b656b
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Dec 7 12:42:10 2011 +0100

    qemu-img rebase: Fix for undersized backing files
    
    Backing files may be smaller than the corresponding COW file. When
    reading directly from the backing file, qemu-img rebase must consider
    this and assume zero sectors after the end of backing files.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/qemu-img.c b/qemu-img.c
index 8bdae66..01cc0d3 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1420,6 +1420,8 @@ static int img_rebase(int argc, char **argv)
      */
     if (!unsafe) {
         uint64_t num_sectors;
+        uint64_t old_backing_num_sectors;
+        uint64_t new_backing_num_sectors;
         uint64_t sector;
         int n;
         uint8_t * buf_old;
@@ -1430,6 +1432,8 @@ static int img_rebase(int argc, char **argv)
         buf_new = qemu_blockalign(bs, IO_BUF_SIZE);
 
         bdrv_get_geometry(bs, &num_sectors);
+        bdrv_get_geometry(bs_old_backing, &old_backing_num_sectors);
+        bdrv_get_geometry(bs_new_backing, &new_backing_num_sectors);
 
         local_progress = (float)100 /
             (num_sectors / MIN(num_sectors, IO_BUF_SIZE / 512));
@@ -1448,16 +1452,36 @@ static int img_rebase(int argc, char **argv)
                 continue;
             }
 
-            /* Read old and new backing file */
-            ret = bdrv_read(bs_old_backing, sector, buf_old, n);
-            if (ret < 0) {
-                error_report("error while reading from old backing file");
-                goto out;
+            /*
+             * Read old and new backing file and take into consideration that
+             * backing files may be smaller than the COW image.
+             */
+            if (sector >= old_backing_num_sectors) {
+                memset(buf_old, 0, n * BDRV_SECTOR_SIZE);
+            } else {
+                if (sector + n > old_backing_num_sectors) {
+                    n = old_backing_num_sectors - sector;
+                }
+
+                ret = bdrv_read(bs_old_backing, sector, buf_old, n);
+                if (ret < 0) {
+                    error_report("error while reading from old backing file");
+                    goto out;
+                }
             }
-            ret = bdrv_read(bs_new_backing, sector, buf_new, n);
-            if (ret < 0) {
-                error_report("error while reading from new backing file");
-                goto out;
+
+            if (sector >= new_backing_num_sectors) {
+                memset(buf_new, 0, n * BDRV_SECTOR_SIZE);
+            } else {
+                if (sector + n > new_backing_num_sectors) {
+                    n = new_backing_num_sectors - sector;
+                }
+
+                ret = bdrv_read(bs_new_backing, sector, buf_new, n);
+                if (ret < 0) {
+                    error_report("error while reading from new backing file");
+                    goto out;
+                }
             }
 
             /* If they differ, we need to write to the COW file */
commit b9c532903fa528891c0eceb34ea40a0c47bfb5db
Author: Josh Durgin <josh.durgin at dreamhost.com>
Date:   Tue Dec 6 17:05:10 2011 -0800

    rbd: always set out parameter in qemu_rbd_snap_list
    
    The caller expects psn_tab to be NULL when there are no snapshots or
    an error occurs. This results in calling g_free on an invalid address.
    
    Reported-by: Oliver Francke <Oliver at filoo.de>
    Signed-off-by: Josh Durgin <josh.durgin at dreamhost.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/rbd.c b/block/rbd.c
index 312584a..7a2384c 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -805,7 +805,7 @@ static int qemu_rbd_snap_list(BlockDriverState *bs,
     } while (snap_count == -ERANGE);
 
     if (snap_count <= 0) {
-        return snap_count;
+        goto done;
     }
 
     sn_tab = g_malloc0(snap_count * sizeof(QEMUSnapshotInfo));
@@ -824,6 +824,7 @@ static int qemu_rbd_snap_list(BlockDriverState *bs,
     }
     rbd_snap_list_end(snaps);
 
+ done:
     *psn_tab = sn_tab;
     return snap_count;
 }
commit 28c1202ba63370d44c003fd35257584b1e68de76
Author: Li Zhi Hui <zhihuili at linux.vnet.ibm.com>
Date:   Wed Dec 7 17:25:48 2011 +0800

    block/qcow2.c: call qcow2_free_snapshots in the function of qcow2_close
    
    Signed-off-by: Li Zhi Hui <zhihuili at linux.vnet.ibm.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 37cd442..aa32e8d 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -635,6 +635,7 @@ static void qcow2_close(BlockDriverState *bs)
     g_free(s->cluster_cache);
     qemu_vfree(s->cluster_data);
     qcow2_refcount_close(bs);
+    qcow2_free_snapshots(bs);
 }
 
 static void qcow2_invalidate_cache(BlockDriverState *bs)
commit 3f3aace83046a6740d4e6f92811d333c6741db00
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Nov 14 17:50:54 2011 +0100

    block: avoid useless checks on acb->bh
    
    Coverity is confused by this "if" and reports leaks on acb->bh.
    The bottom half is always deleted before releasing the AIOCB,
    in either bdrv_aio_cancel_em or bdrv_aio_bh_cb.
    
    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 16a4c42..3f072f6 100644
--- a/block.c
+++ b/block.c
@@ -3077,9 +3077,7 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
     acb->is_write = is_write;
     acb->qiov = qiov;
     acb->bounce = qemu_blockalign(bs, qiov->size);
-
-    if (!acb->bh)
-        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
+    acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
 
     if (is_write) {
         qemu_iovec_to_buffer(acb->qiov, acb->bounce);
commit b9b2008bbff49e2714491a95109e1189e54a6491
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Nov 14 17:50:53 2011 +0100

    block: dma_bdrv_* does not return NULL
    
    Initially attempted with the following semantic patch:
    
    @ rule1 @
    expression E;
    statement S;
    @@
      E =
    (
       dma_bdrv_io
    |  dma_bdrv_read
    |  dma_bdrv_write
    )
         (...);
    (
    - if (E == NULL) { ... }
    |
    - if (E)
        { <... S ...> }
    )
    
    which however did not match anything.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 7071326..de9ed41 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -549,7 +549,6 @@ void ide_dma_cb(void *opaque, int ret)
     int n;
     int64_t sector_num;
 
-handle_rw_error:
     if (ret < 0) {
         int op = BM_STATUS_DMA_RETRY;
 
@@ -608,11 +607,6 @@ handle_rw_error:
                                          ide_issue_trim, ide_dma_cb, s, true);
         break;
     }
-
-    if (!s->bus->dma->aiocb) {
-        ret = -1;
-        goto handle_rw_error;
-    }
     return;
 
 eot:
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 40f60f0..abbc41b 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -152,10 +152,8 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
                                ide_issue_trim, pmac_ide_transfer_cb, s, true);
         break;
     }
-
-    if (!m->aiocb)
-        pmac_ide_transfer_cb(io, -1);
     return;
+
 done:
     if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) {
         bdrv_acct_done(s->bs, &s->acct);
commit 6bee44ea346aed24e12d525daf10542d695508db
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Nov 14 17:50:52 2011 +0100

    dma: the passed io_func does not return NULL
    
    Initially found with the following semantic patch:
    
    @ type @
    BlockDriverAIOCB *x;
    expression E;
    @@
      x = E;
    - if (x == NULL) { ... }
    
    @ acb1 @
    expression E, E1;
    @@
      E1->acb = E;
    - if (E1->acb == NULL) { ... }
    
    @ aiocb1 @
    expression E, E1;
    @@
      E1->aiocb = E;
    - if (E1->aiocb == NULL) { ... }
    
    @ acb @
    expression E, E1;
    @@
      E1.acb = E;
    - if (E1.acb == NULL) { ... }
    
    @ aiocb @
    expression E, E1;
    @@
      E1.aiocb = E;
    - if (E1.aiocb == NULL) { ... }
    
    but changed manually to include an assert.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/dma-helpers.c b/dma-helpers.c
index 9d6b6fa..f08cdb5 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -142,9 +142,7 @@ static void dma_bdrv_cb(void *opaque, int ret)
 
     dbs->acb = dbs->io_func(dbs->bs, dbs->sector_num, &dbs->iov,
                             dbs->iov.size / 512, dma_bdrv_cb, dbs);
-    if (!dbs->acb) {
-        dma_complete(dbs, -EIO);
-    }
+    assert(dbs->acb);
 }
 
 static void dma_aio_cancel(BlockDriverAIOCB *acb)
commit 91977c2e5f6419d00f4ae2800586f009b6070ab1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Nov 14 17:50:51 2011 +0100

    block: qemu_aio_get does not return NULL
    
    Initially done with the following semantic patch:
    
    @ rule1 @
    expression E;
    statement S;
    @@
      E = qemu_aio_get (...);
    (
    - if (E == NULL) { ... }
    |
    - if (E)
        { <... S ...> }
    )
    
    which however missed occurrences in linux-aio.c and posix-aio-compat.c.
    Those were done by hand.
    
    The change in vdi_aio_setup's caller was also done by hand.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/curl.c b/block/curl.c
index 4209ac8..e9102e3 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -509,10 +509,6 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
 
     acb = qemu_aio_get(&curl_aio_pool, bs, cb, opaque);
 
-    if (!acb) {
-        return NULL;
-    }
-
     acb->qiov = qiov;
     acb->sector_num = sector_num;
     acb->nb_sectors = nb_sectors;
diff --git a/block/rbd.c b/block/rbd.c
index 9088c52..312584a 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -632,9 +632,6 @@ static BlockDriverAIOCB *rbd_aio_rw_vector(BlockDriverState *bs,
     BDRVRBDState *s = bs->opaque;
 
     acb = qemu_aio_get(&rbd_aio_pool, bs, cb, opaque);
-    if (!acb) {
-        return NULL;
-    }
     acb->write = write;
     acb->qiov = qiov;
     acb->bounce = qemu_blockalign(bs, qiov->size);
diff --git a/block/vdi.c b/block/vdi.c
index 6bb43b8..31cdfab 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -515,28 +515,26 @@ static VdiAIOCB *vdi_aio_setup(BlockDriverState *bs, int64_t sector_num,
            bs, sector_num, qiov, nb_sectors, cb, opaque, is_write);
 
     acb = qemu_aio_get(&vdi_aio_pool, bs, cb, opaque);
-    if (acb) {
-        acb->hd_aiocb = NULL;
-        acb->sector_num = sector_num;
-        acb->qiov = qiov;
-        acb->is_write = is_write;
-
-        if (qiov->niov > 1) {
-            acb->buf = qemu_blockalign(bs, qiov->size);
-            acb->orig_buf = acb->buf;
-            if (is_write) {
-                qemu_iovec_to_buffer(qiov, acb->buf);
-            }
-        } else {
-            acb->buf = (uint8_t *)qiov->iov->iov_base;
+    acb->hd_aiocb = NULL;
+    acb->sector_num = sector_num;
+    acb->qiov = qiov;
+    acb->is_write = is_write;
+
+    if (qiov->niov > 1) {
+        acb->buf = qemu_blockalign(bs, qiov->size);
+        acb->orig_buf = acb->buf;
+        if (is_write) {
+            qemu_iovec_to_buffer(qiov, acb->buf);
         }
-        acb->nb_sectors = nb_sectors;
-        acb->n_sectors = 0;
-        acb->bmap_first = VDI_UNALLOCATED;
-        acb->bmap_last = VDI_UNALLOCATED;
-        acb->block_buffer = NULL;
-        acb->header_modified = 0;
-    }
+    } else {
+        acb->buf = (uint8_t *)qiov->iov->iov_base;
+    }
+    acb->nb_sectors = nb_sectors;
+    acb->n_sectors = 0;
+    acb->bmap_first = VDI_UNALLOCATED;
+    acb->bmap_last = VDI_UNALLOCATED;
+    acb->block_buffer = NULL;
+    acb->header_modified = 0;
     return acb;
 }
 
@@ -653,10 +651,6 @@ static BlockDriverAIOCB *vdi_aio_readv(BlockDriverState *bs,
 
     logout("\n");
     acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
-    if (!acb) {
-        return NULL;
-    }
-
     ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
     if (ret < 0) {
         if (acb->qiov->niov > 1) {
@@ -807,10 +801,6 @@ static BlockDriverAIOCB *vdi_aio_writev(BlockDriverState *bs,
 
     logout("\n");
     acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
-    if (!acb) {
-        return NULL;
-    }
-
     ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
     if (ret < 0) {
         if (acb->qiov->niov > 1) {
diff --git a/linux-aio.c b/linux-aio.c
index 1c635ef..d2fc2e7 100644
--- a/linux-aio.c
+++ b/linux-aio.c
@@ -166,8 +166,6 @@ BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
     off_t offset = sector_num * 512;
 
     laiocb = qemu_aio_get(&laio_pool, bs, cb, opaque);
-    if (!laiocb)
-        return NULL;
     laiocb->nbytes = nb_sectors * 512;
     laiocb->ctx = s;
     laiocb->ret = -EINPROGRESS;
diff --git a/posix-aio-compat.c b/posix-aio-compat.c
index c380ec1..cccb673 100644
--- a/posix-aio-compat.c
+++ b/posix-aio-compat.c
@@ -611,8 +611,6 @@ BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
     struct qemu_paiocb *acb;
 
     acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque);
-    if (!acb)
-        return NULL;
     acb->aio_type = type;
     acb->aio_fildes = fd;
 
@@ -638,8 +636,6 @@ BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
     struct qemu_paiocb *acb;
 
     acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque);
-    if (!acb)
-        return NULL;
     acb->aio_type = QEMU_AIO_IOCTL;
     acb->aio_fildes = fd;
     acb->aio_offset = 0;
commit df9309fb432f3fc9f66f4a567f70970d4e46010a
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Nov 14 17:50:50 2011 +0100

    block: simplify failure handling for bdrv_aio_multiwrite
    
    Now that early failure of bdrv_aio_writev is not possible anymore,
    mcb->num_requests can be set before the loop starts.
    
    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 434c13d..16a4c42 100644
--- a/block.c
+++ b/block.c
@@ -2842,37 +2842,13 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
 
     trace_bdrv_aio_multiwrite(mcb, mcb->num_callbacks, num_reqs);
 
-    /*
-     * Run the aio requests. As soon as one request can't be submitted
-     * successfully, fail all requests that are not yet submitted (we must
-     * return failure for all requests anyway)
-     *
-     * num_requests cannot be set to the right value immediately: If
-     * bdrv_aio_writev fails for some request, num_requests would be too high
-     * and therefore multiwrite_cb() would never recognize the multiwrite
-     * request as completed. We also cannot use the loop variable i to set it
-     * when the first request fails because the callback may already have been
-     * called for previously submitted requests. Thus, num_requests must be
-     * incremented for each request that is submitted.
-     *
-     * The problem that callbacks may be called early also means that we need
-     * to take care that num_requests doesn't become 0 before all requests are
-     * submitted - multiwrite_cb() would consider the multiwrite request
-     * completed. A dummy request that is "completed" by a manual call to
-     * multiwrite_cb() takes care of this.
-     */
-    mcb->num_requests = 1;
-
-    // Run the aio requests
+    /* Run the aio requests. */
+    mcb->num_requests = num_reqs;
     for (i = 0; i < num_reqs; i++) {
-        mcb->num_requests++;
         bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov,
             reqs[i].nb_sectors, multiwrite_cb, mcb);
     }
 
-    /* Complete the dummy request */
-    multiwrite_cb(mcb, 0);
-
     return 0;
 }
 
commit ad54ae80c73f486cf39b4b38a04b76dd971cdbf6
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Nov 30 09:12:30 2011 +0100

    block: bdrv_aio_* do not return NULL
    
    Initially done with the following semantic patch:
    
    @ rule1 @
    expression E;
    statement S;
    @@
      E =
    (
       bdrv_aio_readv
    |  bdrv_aio_writev
    |  bdrv_aio_flush
    |  bdrv_aio_discard
    |  bdrv_aio_ioctl
    )
         (...);
    (
    - if (E == NULL) { ... }
    |
    - if (E)
        { <... S ...> }
    )
    
    which however missed the occurrence in block/blkverify.c
    (as it should have done), and left behind some unused
    variables.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block-migration.c b/block-migration.c
index 423c5a0..2b7edbc 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -251,22 +251,12 @@ static int mig_save_device_bulk(Monitor *mon, QEMUFile *f,
 
     blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
                                 nr_sectors, blk_mig_read_cb, blk);
-    if (!blk->aiocb) {
-        goto error;
-    }
     block_mig_state.submitted++;
 
     bdrv_reset_dirty(bs, cur_sector, nr_sectors);
     bmds->cur_sector = cur_sector + nr_sectors;
 
     return (bmds->cur_sector >= total_sectors);
-
-error:
-    monitor_printf(mon, "Error reading sector %" PRId64 "\n", cur_sector);
-    qemu_file_set_error(f, -EIO);
-    g_free(blk->buf);
-    g_free(blk);
-    return 0;
 }
 
 static void set_dirty_tracking(int enable)
@@ -413,9 +403,6 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
 
                 blk->aiocb = bdrv_aio_readv(bmds->bs, sector, &blk->qiov,
                                             nr_sectors, blk_mig_read_cb, blk);
-                if (!blk->aiocb) {
-                    goto error;
-                }
                 block_mig_state.submitted++;
                 bmds_set_aio_inflight(bmds, sector, nr_sectors, 1);
             } else {
diff --git a/block.c b/block.c
index aa9d142..434c13d 100644
--- a/block.c
+++ b/block.c
@@ -2812,7 +2812,6 @@ static int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs,
  */
 int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
 {
-    BlockDriverAIOCB *acb;
     MultiwriteCB *mcb;
     int i;
 
@@ -2867,35 +2866,14 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
     // Run the aio requests
     for (i = 0; i < num_reqs; i++) {
         mcb->num_requests++;
-        acb = bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov,
+        bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov,
             reqs[i].nb_sectors, multiwrite_cb, mcb);
-
-        if (acb == NULL) {
-            // We can only fail the whole thing if no request has been
-            // submitted yet. Otherwise we'll wait for the submitted AIOs to
-            // complete and report the error in the callback.
-            if (i == 0) {
-                trace_bdrv_aio_multiwrite_earlyfail(mcb);
-                goto fail;
-            } else {
-                trace_bdrv_aio_multiwrite_latefail(mcb, i);
-                multiwrite_cb(mcb, -EIO);
-                break;
-            }
-        }
     }
 
     /* Complete the dummy request */
     multiwrite_cb(mcb, 0);
 
     return 0;
-
-fail:
-    for (i = 0; i < mcb->num_callbacks; i++) {
-        reqs[i].error = -EIO;
-    }
-    g_free(mcb);
-    return -1;
 }
 
 void bdrv_aio_cancel(BlockDriverAIOCB *acb)
diff --git a/block/blkverify.c b/block/blkverify.c
index 483f3b3..4ca8584 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -310,14 +310,10 @@ static BlockDriverAIOCB *blkverify_aio_readv(BlockDriverState *bs,
     qemu_iovec_init(&acb->raw_qiov, acb->qiov->niov);
     blkverify_iovec_clone(&acb->raw_qiov, qiov, acb->buf);
 
-    if (!bdrv_aio_readv(s->test_file, sector_num, qiov, nb_sectors,
-                        blkverify_aio_cb, acb)) {
-        blkverify_aio_cb(acb, -EIO);
-    }
-    if (!bdrv_aio_readv(bs->file, sector_num, &acb->raw_qiov, nb_sectors,
-                        blkverify_aio_cb, acb)) {
-        blkverify_aio_cb(acb, -EIO);
-    }
+    bdrv_aio_readv(s->test_file, sector_num, qiov, nb_sectors,
+                   blkverify_aio_cb, acb);
+    bdrv_aio_readv(bs->file, sector_num, &acb->raw_qiov, nb_sectors,
+                   blkverify_aio_cb, acb);
     return &acb->common;
 }
 
@@ -329,14 +325,10 @@ static BlockDriverAIOCB *blkverify_aio_writev(BlockDriverState *bs,
     BlkverifyAIOCB *acb = blkverify_aio_get(bs, true, sector_num, qiov,
                                             nb_sectors, cb, opaque);
 
-    if (!bdrv_aio_writev(s->test_file, sector_num, qiov, nb_sectors,
-                         blkverify_aio_cb, acb)) {
-        blkverify_aio_cb(acb, -EIO);
-    }
-    if (!bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors,
-                         blkverify_aio_cb, acb)) {
-        blkverify_aio_cb(acb, -EIO);
-    }
+    bdrv_aio_writev(s->test_file, sector_num, qiov, nb_sectors,
+                    blkverify_aio_cb, acb);
+    bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors,
+                    blkverify_aio_cb, acb);
     return &acb->common;
 }
 
diff --git a/block/qed-table.c b/block/qed-table.c
index 8ee8443..ce07b05 100644
--- a/block/qed-table.c
+++ b/block/qed-table.c
@@ -54,7 +54,6 @@ static void qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
     QEDReadTableCB *read_table_cb = gencb_alloc(sizeof(*read_table_cb),
                                                 cb, opaque);
     QEMUIOVector *qiov = &read_table_cb->qiov;
-    BlockDriverAIOCB *aiocb;
 
     trace_qed_read_table(s, offset, table);
 
@@ -64,12 +63,9 @@ static void qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
     read_table_cb->iov.iov_len = s->header.cluster_size * s->header.table_size,
 
     qemu_iovec_init_external(qiov, &read_table_cb->iov, 1);
-    aiocb = bdrv_aio_readv(s->bs->file, offset / BDRV_SECTOR_SIZE, qiov,
-                           qiov->size / BDRV_SECTOR_SIZE,
-                           qed_read_table_cb, read_table_cb);
-    if (!aiocb) {
-        qed_read_table_cb(read_table_cb, -EIO);
-    }
+    bdrv_aio_readv(s->bs->file, offset / BDRV_SECTOR_SIZE, qiov,
+                   qiov->size / BDRV_SECTOR_SIZE,
+                   qed_read_table_cb, read_table_cb);
 }
 
 typedef struct {
@@ -127,7 +123,6 @@ static void qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
                             BlockDriverCompletionFunc *cb, void *opaque)
 {
     QEDWriteTableCB *write_table_cb;
-    BlockDriverAIOCB *aiocb;
     unsigned int sector_mask = BDRV_SECTOR_SIZE / sizeof(uint64_t) - 1;
     unsigned int start, end, i;
     size_t len_bytes;
@@ -158,13 +153,10 @@ static void qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
     /* Adjust for offset into table */
     offset += start * sizeof(uint64_t);
 
-    aiocb = bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE,
-                            &write_table_cb->qiov,
-                            write_table_cb->qiov.size / BDRV_SECTOR_SIZE,
-                            qed_write_table_cb, write_table_cb);
-    if (!aiocb) {
-        qed_write_table_cb(write_table_cb, -EIO);
-    }
+    bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE,
+                    &write_table_cb->qiov,
+                    write_table_cb->qiov.size / BDRV_SECTOR_SIZE,
+                    qed_write_table_cb, write_table_cb);
 }
 
 /**
diff --git a/block/qed.c b/block/qed.c
index 22e4672..8da3ebe 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -123,7 +123,6 @@ static void qed_write_header_read_cb(void *opaque, int ret)
 {
     QEDWriteHeaderCB *write_header_cb = opaque;
     BDRVQEDState *s = write_header_cb->s;
-    BlockDriverAIOCB *acb;
 
     if (ret) {
         qed_write_header_cb(write_header_cb, ret);
@@ -133,12 +132,9 @@ static void qed_write_header_read_cb(void *opaque, int ret)
     /* Update header */
     qed_header_cpu_to_le(&s->header, (QEDHeader *)write_header_cb->buf);
 
-    acb = bdrv_aio_writev(s->bs->file, 0, &write_header_cb->qiov,
-                          write_header_cb->nsectors, qed_write_header_cb,
-                          write_header_cb);
-    if (!acb) {
-        qed_write_header_cb(write_header_cb, -EIO);
-    }
+    bdrv_aio_writev(s->bs->file, 0, &write_header_cb->qiov,
+                    write_header_cb->nsectors, qed_write_header_cb,
+                    write_header_cb);
 }
 
 /**
@@ -156,7 +152,6 @@ static void qed_write_header(BDRVQEDState *s, BlockDriverCompletionFunc cb,
      * them, and write back.
      */
 
-    BlockDriverAIOCB *acb;
     int nsectors = (sizeof(QEDHeader) + BDRV_SECTOR_SIZE - 1) /
                    BDRV_SECTOR_SIZE;
     size_t len = nsectors * BDRV_SECTOR_SIZE;
@@ -170,11 +165,8 @@ static void qed_write_header(BDRVQEDState *s, BlockDriverCompletionFunc cb,
     write_header_cb->iov.iov_len = len;
     qemu_iovec_init_external(&write_header_cb->qiov, &write_header_cb->iov, 1);
 
-    acb = bdrv_aio_readv(s->bs->file, 0, &write_header_cb->qiov, nsectors,
-                         qed_write_header_read_cb, write_header_cb);
-    if (!acb) {
-        qed_write_header_cb(write_header_cb, -EIO);
-    }
+    bdrv_aio_readv(s->bs->file, 0, &write_header_cb->qiov, nsectors,
+                   qed_write_header_read_cb, write_header_cb);
 }
 
 static uint64_t qed_max_image_size(uint32_t cluster_size, uint32_t table_size)
@@ -728,7 +720,6 @@ static void qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
                                   QEMUIOVector *qiov,
                                   BlockDriverCompletionFunc *cb, void *opaque)
 {
-    BlockDriverAIOCB *aiocb;
     uint64_t backing_length = 0;
     size_t size;
 
@@ -760,11 +751,8 @@ static void qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
     size = MIN((uint64_t)backing_length - pos, qiov->size);
 
     BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING);
-    aiocb = bdrv_aio_readv(s->bs->backing_hd, pos / BDRV_SECTOR_SIZE,
-                           qiov, size / BDRV_SECTOR_SIZE, cb, opaque);
-    if (!aiocb) {
-        cb(opaque, -EIO);
-    }
+    bdrv_aio_readv(s->bs->backing_hd, pos / BDRV_SECTOR_SIZE,
+                   qiov, size / BDRV_SECTOR_SIZE, cb, opaque);
 }
 
 typedef struct {
@@ -786,7 +774,6 @@ static void qed_copy_from_backing_file_write(void *opaque, int ret)
 {
     CopyFromBackingFileCB *copy_cb = opaque;
     BDRVQEDState *s = copy_cb->s;
-    BlockDriverAIOCB *aiocb;
 
     if (ret) {
         qed_copy_from_backing_file_cb(copy_cb, ret);
@@ -794,13 +781,9 @@ static void qed_copy_from_backing_file_write(void *opaque, int ret)
     }
 
     BLKDBG_EVENT(s->bs->file, BLKDBG_COW_WRITE);
-    aiocb = bdrv_aio_writev(s->bs->file, copy_cb->offset / BDRV_SECTOR_SIZE,
-                            &copy_cb->qiov,
-                            copy_cb->qiov.size / BDRV_SECTOR_SIZE,
-                            qed_copy_from_backing_file_cb, copy_cb);
-    if (!aiocb) {
-        qed_copy_from_backing_file_cb(copy_cb, -EIO);
-    }
+    bdrv_aio_writev(s->bs->file, copy_cb->offset / BDRV_SECTOR_SIZE,
+                    &copy_cb->qiov, copy_cb->qiov.size / BDRV_SECTOR_SIZE,
+                    qed_copy_from_backing_file_cb, copy_cb);
 }
 
 /**
@@ -1022,7 +1005,6 @@ static void qed_aio_write_main(void *opaque, int ret)
     uint64_t offset = acb->cur_cluster +
                       qed_offset_into_cluster(s, acb->cur_pos);
     BlockDriverCompletionFunc *next_fn;
-    BlockDriverAIOCB *file_acb;
 
     trace_qed_aio_write_main(s, acb, ret, offset, acb->cur_qiov.size);
 
@@ -1042,13 +1024,9 @@ static void qed_aio_write_main(void *opaque, int ret)
     }
 
     BLKDBG_EVENT(s->bs->file, BLKDBG_WRITE_AIO);
-    file_acb = bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE,
-                               &acb->cur_qiov,
-                               acb->cur_qiov.size / BDRV_SECTOR_SIZE,
-                               next_fn, acb);
-    if (!file_acb) {
-        qed_aio_complete(acb, -EIO);
-    }
+    bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE,
+                    &acb->cur_qiov, acb->cur_qiov.size / BDRV_SECTOR_SIZE,
+                    next_fn, acb);
 }
 
 /**
@@ -1215,7 +1193,6 @@ static void qed_aio_read_data(void *opaque, int ret,
     QEDAIOCB *acb = opaque;
     BDRVQEDState *s = acb_to_s(acb);
     BlockDriverState *bs = acb->common.bs;
-    BlockDriverAIOCB *file_acb;
 
     /* Adjust offset into cluster */
     offset += qed_offset_into_cluster(s, acb->cur_pos);
@@ -1240,14 +1217,9 @@ static void qed_aio_read_data(void *opaque, int ret,
     }
 
     BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
-    file_acb = bdrv_aio_readv(bs->file, offset / BDRV_SECTOR_SIZE,
-                              &acb->cur_qiov,
-                              acb->cur_qiov.size / BDRV_SECTOR_SIZE,
-                              qed_aio_next_io, acb);
-    if (!file_acb) {
-        ret = -EIO;
-        goto err;
-    }
+    bdrv_aio_readv(bs->file, offset / BDRV_SECTOR_SIZE,
+                   &acb->cur_qiov, acb->cur_qiov.size / BDRV_SECTOR_SIZE,
+                   qed_aio_next_io, acb);
     return;
 
 err:
diff --git a/block/vdi.c b/block/vdi.c
index e1d8cff..6bb43b8 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -633,10 +633,6 @@ static void vdi_aio_read_cb(void *opaque, int ret)
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
         acb->hd_aiocb = bdrv_aio_readv(bs->file, offset, &acb->hd_qiov,
                                        n_sectors, vdi_aio_read_cb, acb);
-        if (acb->hd_aiocb == NULL) {
-            ret = -EIO;
-            goto done;
-        }
     }
     return;
 done:
@@ -708,10 +704,6 @@ static void vdi_aio_write_cb(void *opaque, int ret)
             qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
             acb->hd_aiocb = bdrv_aio_writev(bs->file, 0, &acb->hd_qiov, 1,
                                             vdi_aio_write_cb, acb);
-            if (acb->hd_aiocb == NULL) {
-                ret = -EIO;
-                goto done;
-            }
             return;
         } else if (VDI_IS_ALLOCATED(acb->bmap_first)) {
             /* One or more new blocks were allocated. */
@@ -738,10 +730,6 @@ static void vdi_aio_write_cb(void *opaque, int ret)
                    n_sectors, bmap_first);
             acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov,
                                             n_sectors, vdi_aio_write_cb, acb);
-            if (acb->hd_aiocb == NULL) {
-                ret = -EIO;
-                goto done;
-            }
             return;
         }
         ret = 0;
@@ -789,10 +777,6 @@ static void vdi_aio_write_cb(void *opaque, int ret)
         acb->hd_aiocb = bdrv_aio_writev(bs->file, offset,
                                         &acb->hd_qiov, s->block_sectors,
                                         vdi_aio_write_cb, acb);
-        if (acb->hd_aiocb == NULL) {
-            ret = -EIO;
-            goto done;
-        }
     } else {
         uint64_t offset = s->header.offset_data / SECTOR_SIZE +
                           (uint64_t)bmap_entry * s->block_sectors +
@@ -802,10 +786,6 @@ static void vdi_aio_write_cb(void *opaque, int ret)
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
         acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov,
                                         n_sectors, vdi_aio_write_cb, acb);
-        if (acb->hd_aiocb == NULL) {
-            ret = -EIO;
-            goto done;
-        }
     }
 
     return;
diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
index 8af1cfd..0adb27b 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -352,14 +352,8 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
     s->bus->dma->aiocb = bdrv_aio_readv(s->bs, (int64_t)s->lba << 2,
                                        &s->bus->dma->qiov, n * 4,
                                        ide_atapi_cmd_read_dma_cb, s);
-    if (!s->bus->dma->aiocb) {
-        /* Note: media not present is the most likely case */
-        ide_atapi_cmd_error(s, NOT_READY,
-                            ASC_MEDIUM_NOT_PRESENT);
-        goto eot;
-    }
-
     return;
+
 eot:
     bdrv_acct_done(s->bs, &s->acct);
     s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT);
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 49847bd..7071326 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -718,18 +718,13 @@ static void ide_flush_cb(void *opaque, int ret)
 
 void ide_flush_cache(IDEState *s)
 {
-    BlockDriverAIOCB *acb;
-
     if (s->bs == NULL) {
         ide_flush_cb(s, 0);
         return;
     }
 
     bdrv_acct_start(s->bs, &s->acct, 0, BDRV_ACCT_FLUSH);
-    acb = bdrv_aio_flush(s->bs, ide_flush_cb, s);
-    if (acb == NULL) {
-        ide_flush_cb(s, -EIO);
-    }
+    bdrv_aio_flush(s->bs, ide_flush_cb, s);
 }
 
 static void ide_cfata_metadata_inquiry(IDEState *s)
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index c09d2e0..40f60f0 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -84,13 +84,6 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
     m->aiocb = dma_bdrv_read(s->bs, &s->sg,
                              (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9),
                              pmac_ide_atapi_transfer_cb, io);
-    if (!m->aiocb) {
-        qemu_sglist_destroy(&s->sg);
-        /* Note: media not present is the most likely case */
-        ide_atapi_cmd_error(s, NOT_READY,
-                            ASC_MEDIUM_NOT_PRESENT);
-        goto done;
-    }
     return;
 
 done:
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 673948c..505accd 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -217,9 +217,6 @@ static void scsi_read_data(SCSIRequest *req)
     bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
     r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n,
                               scsi_read_complete, r);
-    if (r->req.aiocb == NULL) {
-        scsi_read_complete(r, -EIO);
-    }
 }
 
 /*
@@ -327,9 +324,6 @@ static void scsi_write_data(SCSIRequest *req)
         bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
         r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, r->sector, &r->qiov, n,
                                        scsi_write_complete, r);
-        if (r->req.aiocb == NULL) {
-            scsi_write_complete(r, -ENOMEM);
-        }
     } else {
         /* Called for the first time.  Ask the driver to send us more data.  */
         scsi_write_complete(r, 0);
@@ -1332,9 +1326,6 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
         scsi_req_ref(&r->req);
         bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
         r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_flush_complete, r);
-        if (r->req.aiocb == NULL) {
-            scsi_flush_complete(r, -EIO);
-        }
         return 0;
     case READ_6:
     case READ_10:
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index e62044f..6f7d3db 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -152,10 +152,6 @@ static int execute_command(BlockDriverState *bdrv,
     r->io_header.flags |= SG_FLAG_DIRECT_IO;
 
     r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
-    if (r->req.aiocb == NULL) {
-        BADF("execute_command: read failed !\n");
-        return -ENOMEM;
-    }
 
     return 0;
 }
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 4b0d113..ef27421 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -288,19 +288,13 @@ static void virtio_submit_multiwrite(BlockDriverState *bs, MultiReqBuffer *mrb)
 
 static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
 {
-    BlockDriverAIOCB *acb;
-
     bdrv_acct_start(req->dev->bs, &req->acct, 0, BDRV_ACCT_FLUSH);
 
     /*
      * Make sure all outstanding writes are posted to the backing device.
      */
     virtio_submit_multiwrite(req->dev->bs, mrb);
-
-    acb = bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
-    if (!acb) {
-        virtio_blk_flush_complete(req, -EIO);
-    }
+    bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
 }
 
 static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
@@ -340,7 +334,6 @@ static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
 
 static void virtio_blk_handle_read(VirtIOBlockReq *req)
 {
-    BlockDriverAIOCB *acb;
     uint64_t sector;
 
     sector = ldq_p(&req->out->sector);
@@ -355,13 +348,9 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
         virtio_blk_rw_complete(req, -EIO);
         return;
     }
-
-    acb = bdrv_aio_readv(req->dev->bs, sector, &req->qiov,
-                         req->qiov.size / BDRV_SECTOR_SIZE,
-                         virtio_blk_rw_complete, req);
-    if (!acb) {
-        virtio_blk_rw_complete(req, -EIO);
-    }
+    bdrv_aio_readv(req->dev->bs, sector, &req->qiov,
+                   req->qiov.size / BDRV_SECTOR_SIZE,
+                   virtio_blk_rw_complete, req);
 }
 
 static void virtio_blk_handle_request(VirtIOBlockReq *req,
diff --git a/qemu-io.c b/qemu-io.c
index 622debc..ffa62fb 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -244,14 +244,10 @@ static void aio_rw_done(void *opaque, int ret)
 
 static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
 {
-    BlockDriverAIOCB *acb;
     int async_ret = NOT_DONE;
 
-    acb = bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
-                         aio_rw_done, &async_ret);
-    if (!acb) {
-        return -EIO;
-    }
+    bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
+                   aio_rw_done, &async_ret);
     while (async_ret == NOT_DONE) {
         qemu_aio_wait();
     }
@@ -262,15 +258,10 @@ static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
 
 static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
 {
-    BlockDriverAIOCB *acb;
     int async_ret = NOT_DONE;
 
-    acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
-                          aio_rw_done, &async_ret);
-    if (!acb) {
-        return -EIO;
-    }
-
+    bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
+                    aio_rw_done, &async_ret);
     while (async_ret == NOT_DONE) {
         qemu_aio_wait();
     }
@@ -1151,7 +1142,6 @@ static int aio_read_f(int argc, char **argv)
 {
     int nr_iov, c;
     struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
-    BlockDriverAIOCB *acb;
 
     while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
         switch (c) {
@@ -1206,14 +1196,8 @@ static int aio_read_f(int argc, char **argv)
     }
 
     gettimeofday(&ctx->t1, NULL);
-    acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
-                         ctx->qiov.size >> 9, aio_read_done, ctx);
-    if (!acb) {
-        free(ctx->buf);
-        free(ctx);
-        return -EIO;
-    }
-
+    bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
+                   ctx->qiov.size >> 9, aio_read_done, ctx);
     return 0;
 }
 
@@ -1254,7 +1238,6 @@ static int aio_write_f(int argc, char **argv)
     int nr_iov, c;
     int pattern = 0xcd;
     struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
-    BlockDriverAIOCB *acb;
 
     while ((c = getopt(argc, argv, "CqP:")) != EOF) {
         switch (c) {
@@ -1305,14 +1288,8 @@ static int aio_write_f(int argc, char **argv)
     }
 
     gettimeofday(&ctx->t1, NULL);
-    acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
-                          ctx->qiov.size >> 9, aio_write_done, ctx);
-    if (!acb) {
-        free(ctx->buf);
-        free(ctx);
-        return -EIO;
-    }
-
+    bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
+                    ctx->qiov.size >> 9, aio_write_done, ctx);
     return 0;
 }
 
diff --git a/trace-events b/trace-events
index bf1cf57..514849a 100644
--- a/trace-events
+++ b/trace-events
@@ -59,8 +59,6 @@ virtio_console_chr_event(unsigned int port, int event) "port %u, event %d"
 bdrv_open_common(void *bs, const char *filename, int flags, const char *format_name) "bs %p filename \"%s\" flags %#x format_name \"%s\""
 multiwrite_cb(void *mcb, int ret) "mcb %p ret %d"
 bdrv_aio_multiwrite(void *mcb, int num_callbacks, int num_reqs) "mcb %p num_callbacks %d num_reqs %d"
-bdrv_aio_multiwrite_earlyfail(void *mcb) "mcb %p"
-bdrv_aio_multiwrite_latefail(void *mcb, int i) "mcb %p i %d"
 bdrv_aio_discard(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"
 bdrv_aio_flush(void *bs, void *opaque) "bs %p opaque %p"
 bdrv_aio_readv(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"
commit 222f23f508a8d778f56eddef14752dfd26d225b4
Author: Dr. David Alan Gilbert <david.gilbert at linaro.org>
Date:   Mon Dec 12 16:37:31 2011 +0100

    tcg/arm: remove fixed map code buffer restriction
    
    On ARM, don't map the code buffer at a fixed location, and fix up the
    call/goto tcg routines to let it do long jumps.
    
    Mapping the code buffer at a fixed address could sometimes result in it being
    mapped over the top of the heap with pretty random results.
    
    Signed-off-by: Dr. David Alan Gilbert <david.gilbert at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/exec.c b/exec.c
index d8b2180..4f79cbb 100644
--- a/exec.c
+++ b/exec.c
@@ -497,9 +497,7 @@ static void code_gen_alloc(unsigned long tb_size)
         if (code_gen_buffer_size > (512 * 1024 * 1024))
             code_gen_buffer_size = (512 * 1024 * 1024);
 #elif defined(__arm__)
-        /* Map the buffer below 32M, so we can use direct calls and branches */
-        flags |= MAP_FIXED;
-        start = (void *) 0x01000000UL;
+        /* Keep the buffer no bigger than 16GB to branch between blocks */
         if (code_gen_buffer_size > 16 * 1024 * 1024)
             code_gen_buffer_size = 16 * 1024 * 1024;
 #elif defined(__s390x__)
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index e05a64f..1d32798 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -842,6 +842,12 @@ static inline void tcg_out_st8(TCGContext *s, int cond,
         tcg_out_st8_12(s, cond, rd, rn, offset);
 }
 
+/* The _goto case is normally between TBs within the same code buffer,
+ * and with the code buffer limited to 16GB we shouldn't need the long
+ * case.
+ *
+ * .... except to the prologue that is in its own buffer.
+ */
 static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
 {
     int32_t val;
@@ -855,22 +861,20 @@ static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
     if (val - 8 < 0x01fffffd && val - 8 > -0x01fffffd)
         tcg_out_b(s, cond, val);
     else {
-#if 1
-        tcg_abort();
-#else
         if (cond == COND_AL) {
             tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
-            tcg_out32(s, addr); /* XXX: This is l->u.value, can we use it? */
+            tcg_out32(s, addr);
         } else {
             tcg_out_movi32(s, cond, TCG_REG_R8, val - 8);
             tcg_out_dat_reg(s, cond, ARITH_ADD,
                             TCG_REG_PC, TCG_REG_PC,
                             TCG_REG_R8, SHIFT_IMM_LSL(0));
         }
-#endif
     }
 }
 
+/* The call case is mostly used for helpers - so it's not unreasonable
+ * for them to be beyond branch range */
 static inline void tcg_out_call(TCGContext *s, uint32_t addr)
 {
     int32_t val;
@@ -887,20 +891,9 @@ static inline void tcg_out_call(TCGContext *s, uint32_t addr)
             tcg_out_bl(s, COND_AL, val);
         }
     } else {
-#if 1
-        tcg_abort();
-#else
-        if (cond == COND_AL) {
-            tcg_out_dat_imm(s, cond, ARITH_ADD, TCG_REG_R14, TCG_REG_PC, 4);
-            tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
-            tcg_out32(s, addr); /* XXX: This is l->u.value, can we use it? */
-        } else {
-            tcg_out_movi32(s, cond, TCG_REG_R9, addr);
-            tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
-                            TCG_REG_PC, SHIFT_IMM_LSL(0));
-            tcg_out_bx(s, cond, TCG_REG_R9);
-        }
-#endif
+        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R14, TCG_REG_PC, 4);
+        tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
+        tcg_out32(s, addr);
     }
 }
 
commit 23ce84b1bbae9dd244ad8cd77a1ac30fdac07606
Merge: 9423a2e... db8336c...
Author: Andrzej Zaborowski <andrew.zaborowski at intel.com>
Date:   Wed Dec 14 21:34:00 2011 +0100

    Merge branch 'target-arm.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm

commit 9423a2e8dd362a271bfe194ec131062814557b95
Merge: da5361c... 126c791...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Dec 14 07:59:21 2011 -0600

    Merge remote-tracking branch 'stefanha/trivial-patches-next' into staging

commit 126c79133f77d1b0b7c3849899c6d5f83b2fd410
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Dec 14 07:30:24 2011 +0100

    doc: Remove Symbian Virtual Platform
    
    Commit d396a657baec8c6b7aa0c888746e0e2f78303650 removed the code
    for SVP, so the documentation needs this update.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/qemu-doc.texi b/qemu-doc.texi
index 9c3cb62..11f4166 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -107,7 +107,6 @@ For system emulation, the following hardware targets are supported:
 @item MusicPal (MV88W8618 ARM processor)
 @item Gumstix "Connex" and "Verdex" motherboards (PXA255/270).
 @item Siemens SX1 smartphone (OMAP310 processor)
- at item Syborg SVP base model (ARM Cortex-A8).
 @item AXIS-Devboard88 (CRISv32 ETRAX-FS).
 @item Petalogix Spartan 3aDSP1800 MMU ref design (MicroBlaze).
 @item Avnet LX60/LX110/LX200 boards (Xtensa)
@@ -2079,28 +2078,6 @@ Secure Digital card connected to OMAP MMC/SD host
 Three on-chip UARTs
 @end itemize
 
-The "Syborg" Symbian Virtual Platform base model includes the following
-elements:
-
- at itemize @minus
- at item
-ARM Cortex-A8 CPU
- at item
-Interrupt controller
- at item
-Timer
- at item
-Real Time Clock
- at item
-Keyboard
- at item
-Framebuffer
- at item
-Touchscreen
- at item
-UARTs
- at end itemize
-
 A Linux 2.6 test image is available on the QEMU web site. More
 information is available in the QEMU mailing-list archive.
 
commit 3060eb754145996b67036ec313ce34e9f5df1c47
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Tue Dec 13 12:40:51 2011 +0900

    migration.h: remove incoming_expected declarations
    
    The variable is deleted by 1bcef683bf840a928d633755031ac572d5fdb851
    So remove its declaration.
    
    Acked-by: Luiz Capitulino <lcapitulino at redhat.com>
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/migration.h b/migration.h
index 0682179..78a50d3 100644
--- a/migration.h
+++ b/migration.h
@@ -88,8 +88,6 @@ uint64_t ram_bytes_total(void);
 int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque);
 int ram_load(QEMUFile *f, void *opaque, int version_id);
 
-extern int incoming_expected;
-
 /**
  * @migrate_add_blocker - prevent migration from proceeding
  *
commit 73f5e3132a18654caa9705e3e8c7688f615f8c7d
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sat Dec 10 16:35:31 2011 +0000

    tcg: make tcg_const_ptr actually accept a pointer argument
    
    Make tcg_const_ptr() include a cast so that you can pass it a
    pointer. This allows us to drop the casts we had in all the places
    that use this macro.
    
    Acked-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 82e04e7..169d3b2 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -389,7 +389,7 @@ static inline void tcg_gen_helperN(void *func, int flags, int sizemask,
                                    TCGArg ret, int nargs, TCGArg *args)
 {
     TCGv_ptr fn;
-    fn = tcg_const_ptr((tcg_target_long)func);
+    fn = tcg_const_ptr(func);
     tcg_gen_callN(&tcg_ctx, fn, flags, sizemask, ret,
                   nargs, args);
     tcg_temp_free_ptr(fn);
@@ -405,7 +405,7 @@ static inline void tcg_gen_helper32(void *func, int sizemask, TCGv_i32 ret,
 {
     TCGv_ptr fn;
     TCGArg args[2];
-    fn = tcg_const_ptr((tcg_target_long)func);
+    fn = tcg_const_ptr(func);
     args[0] = GET_TCGV_I32(a);
     args[1] = GET_TCGV_I32(b);
     tcg_gen_callN(&tcg_ctx, fn, TCG_CALL_CONST | TCG_CALL_PURE, sizemask,
@@ -418,7 +418,7 @@ static inline void tcg_gen_helper64(void *func, int sizemask, TCGv_i64 ret,
 {
     TCGv_ptr fn;
     TCGArg args[2];
-    fn = tcg_const_ptr((tcg_target_long)func);
+    fn = tcg_const_ptr(func);
     args[0] = GET_TCGV_I64(a);
     args[1] = GET_TCGV_I64(b);
     tcg_gen_callN(&tcg_ctx, fn, TCG_CALL_CONST | TCG_CALL_PURE, sizemask,
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 175000f..5c28239 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -544,7 +544,7 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs);
 #define TCGV_NAT_TO_PTR(n) MAKE_TCGV_PTR(GET_TCGV_I32(n))
 #define TCGV_PTR_TO_NAT(n) MAKE_TCGV_I32(GET_TCGV_PTR(n))
 
-#define tcg_const_ptr(V) TCGV_NAT_TO_PTR(tcg_const_i32(V))
+#define tcg_const_ptr(V) TCGV_NAT_TO_PTR(tcg_const_i32((tcg_target_long)(V)))
 #define tcg_global_reg_new_ptr(R, N) \
     TCGV_NAT_TO_PTR(tcg_global_reg_new_i32((R), (N)))
 #define tcg_global_mem_new_ptr(R, O, N) \
@@ -555,7 +555,7 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs);
 #define TCGV_NAT_TO_PTR(n) MAKE_TCGV_PTR(GET_TCGV_I64(n))
 #define TCGV_PTR_TO_NAT(n) MAKE_TCGV_I64(GET_TCGV_PTR(n))
 
-#define tcg_const_ptr(V) TCGV_NAT_TO_PTR(tcg_const_i64(V))
+#define tcg_const_ptr(V) TCGV_NAT_TO_PTR(tcg_const_i64((tcg_target_long)(V)))
 #define tcg_global_reg_new_ptr(R, N) \
     TCGV_NAT_TO_PTR(tcg_global_reg_new_i64((R), (N)))
 #define tcg_global_mem_new_ptr(R, O, N) \
commit e7d81004e486b0e80a674d164d8aec0e83fa812f
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 10 00:19:46 2011 +0100

    Fix spelling in comments, documentation and messages
    
    accidently->accidentally
    annother->another
    choosen->chosen
    consideres->considers
    decriptor->descriptor
    developement->development
    paramter->parameter
    preceed->precede
    preceeding->preceding
    priviledge->privilege
    propogation->propagation
    substraction->subtraction
    throught->through
    upto->up to
    usefull->useful
    
    Fix also grammar in posix-aio-compat.c
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/Changelog b/Changelog
index 28a69af..8b63258 100644
--- a/Changelog
+++ b/Changelog
@@ -78,7 +78,7 @@ version 0.10.2:
 
   - fix savevm/loadvm (Anthony Liguori)
   - live migration: fix dirty tracking windows (Glauber Costa)
-  - live migration: improve error propogation (Glauber Costa)
+  - live migration: improve error propagation (Glauber Costa)
   - qcow2: fix image creation for > ~2TB images (Chris Wright)
   - hotplug: fix error handling for if= parameter (Eduardo Habkost)
   - qcow2: fix data corruption (Nolan Leake)
@@ -386,7 +386,7 @@ version 0.5.3:
   - support of CD-ROM change
   - multiple network interface support
   - initial x86-64 host support (Gwenole Beauchesne)
-  - lret to outer priviledge fix (OS/2 install fix)
+  - lret to outer privilege fix (OS/2 install fix)
   - task switch fixes (SkyOS boot)
   - VM save/restore commands
   - new timer API
diff --git a/audio/audio.c b/audio/audio.c
index 50d0d71..5fff6de 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -1665,7 +1665,7 @@ static void audio_pp_nb_voices (const char *typ, int nb)
         printf ("Theoretically supports many %s voices\n", typ);
         break;
     default:
-        printf ("Theoretically supports upto %d %s voices\n", nb, typ);
+        printf ("Theoretically supports up to %d %s voices\n", nb, typ);
         break;
     }
 
diff --git a/block.h b/block.h
index 1790f99..0e3ff9f 100644
--- a/block.h
+++ b/block.h
@@ -21,7 +21,7 @@ typedef struct QEMUSnapshotInfo {
     char id_str[128]; /* unique snapshot id */
     /* the following fields are informative. They are not needed for
        the consistency of the snapshot */
-    char name[256]; /* user choosen name */
+    char name[256]; /* user chosen name */
     uint32_t vm_state_size; /* VM state info size */
     uint32_t date_sec; /* UTC date of the snapshot */
     uint32_t date_nsec;
diff --git a/bsd-user/x86_64/syscall.h b/bsd-user/x86_64/syscall.h
index 5f71b7c..630514a 100644
--- a/bsd-user/x86_64/syscall.h
+++ b/bsd-user/x86_64/syscall.h
@@ -8,7 +8,7 @@ struct target_pt_regs {
 	abi_ulong r12;
 	abi_ulong rbp;
 	abi_ulong rbx;
-/* arguments: non interrupts/non tracing syscalls only save upto here*/
+/* arguments: non interrupts/non tracing syscalls only save up to here */
  	abi_ulong r11;
 	abi_ulong r10;
 	abi_ulong r9;
diff --git a/gdbstub.c b/gdbstub.c
index 640cf4e..a5806ef 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2678,7 +2678,7 @@ gdb_handlesig (CPUState *env, int sig)
         }
       else if (n == 0 || errno != EAGAIN)
         {
-          /* XXX: Connection closed.  Should probably wait for annother
+          /* XXX: Connection closed.  Should probably wait for another
              connection before continuing.  */
           return sig;
         }
diff --git a/linux-user/x86_64/syscall.h b/linux-user/x86_64/syscall.h
index 2a8d696..81314cf 100644
--- a/linux-user/x86_64/syscall.h
+++ b/linux-user/x86_64/syscall.h
@@ -8,7 +8,7 @@ struct target_pt_regs {
 	abi_ulong r12;
 	abi_ulong rbp;
 	abi_ulong rbx;
-/* arguments: non interrupts/non tracing syscalls only save upto here*/
+/* arguments: non interrupts/non tracing syscalls only save up to here */
  	abi_ulong r11;
 	abi_ulong r10;
 	abi_ulong r9;
diff --git a/pc-bios/ohw.diff b/pc-bios/ohw.diff
index 4fb5422..c6b6623 100644
--- a/pc-bios/ohw.diff
+++ b/pc-bios/ohw.diff
@@ -1065,7 +1065,7 @@ diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --
 +                        tab, 4 * sizeof(uint32_t));
 +    }
 +#if 0
-     /* escc is usefull to get MacOS X debug messages */
+     /* escc is useful to get MacOS X debug messages */
      {
          OF_regprop_t regs[8];
 @@ -2645,85 +2843,12 @@
diff --git a/pc-bios/optionrom/multiboot.S b/pc-bios/optionrom/multiboot.S
index cc5ca1b..f08222a 100644
--- a/pc-bios/optionrom/multiboot.S
+++ b/pc-bios/optionrom/multiboot.S
@@ -50,7 +50,7 @@ run_multiboot:
 	shr		$0x4, %ecx
 	mov		%cx, %gs
 
-	/* now push the indirect jump decriptor there */
+	/* now push the indirect jump descriptor there */
 	mov		(prot_jump), %ebx
 	add		%eax, %ebx
 	movl		%ebx, %gs:GS_PROT_JUMP
diff --git a/posix-aio-compat.c b/posix-aio-compat.c
index 0c0035c..c380ec1 100644
--- a/posix-aio-compat.c
+++ b/posix-aio-compat.c
@@ -128,8 +128,8 @@ static ssize_t handle_aiocb_ioctl(struct qemu_paiocb *aiocb)
         return -errno;
 
     /*
-     * This looks weird, but the aio code only consideres a request
-     * successful if it has written the number full number of bytes.
+     * This looks weird, but the aio code only considers a request
+     * successful if it has written the full number of bytes.
      *
      * Now we overload aio_nbytes as aio_ioctl_cmd for the ioctl command,
      * so in fact we return the ioctl command here to make posix_aio_read()
diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json
index fde5971..f4bcd1a 100644
--- a/qapi-schema-guest.json
+++ b/qapi-schema-guest.json
@@ -13,7 +13,7 @@
 # partially-delivered JSON text in such a way that this response
 # can be obtained.
 #
-# Such clients should also preceed this command
+# Such clients should also precede this command
 # with a 0xFF byte to make such the guest agent flushes any
 # partially read JSON data from a previous session.
 #
diff --git a/qemu-options.hx b/qemu-options.hx
index b3db10c..087a3b9 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -217,7 +217,7 @@ qcow2.  If performance is more important than correctness,
 In case you don't care about data integrity over host failures, use
 cache=unsafe. This option tells qemu that it never needs to write any data
 to the disk but can instead keeps things in cache. If anything goes wrong,
-like your host losing power, the disk storage getting disconnected accidently,
+like your host losing power, the disk storage getting disconnected accidentally,
 etc. you're image will most probably be rendered unusable.   When using
 the @option{-snapshot} option, unsafe caching is always used.
 
diff --git a/qerror.c b/qerror.c
index 656efc2..d9ab396 100644
--- a/qerror.c
+++ b/qerror.c
@@ -253,7 +253,7 @@ static const QErrorStringTable qerror_table[] = {
     },
     {
         .error_fmt = QERR_INVALID_PARAMETER_COMBINATION,
-        .desc      = "Invalid paramter combination",
+        .desc      = "Invalid parameter combination",
     },
     {}
 };
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index cce8f86..8850a5f 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1907,7 +1907,7 @@ sub process {
 			my $ok = 0;
 			for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) {
 				#print "CHECK<$lines[$ln - 1]\n";
-				# we have a preceeding printk if it ends
+				# we have a preceding printk if it ends
 				# with "\n" ignore it, else it is to blame
 				if ($lines[$ln - 1] =~ m{\bprintk\(}) {
 					if ($rawlines[$ln - 1] !~ m{\\n"}) {
@@ -1999,7 +1999,7 @@ sub process {
 			for (my $n = 0; $n < $#elements; $n += 2) {
 				$off += length($elements[$n]);
 
-				# Pick up the preceeding and succeeding characters.
+				# Pick up the preceding and succeeding characters.
 				my $ca = substr($opline, 0, $off);
 				my $cc = '';
 				if (length($opline) >= ($off + length($elements[$n + 1]))) {
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 1c58e0c..7225616 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -497,7 +497,7 @@ void do_interrupt (CPUState *env)
                 }
             } else {
                 /* For VEIC mode, the external interrupt controller feeds the
-                   vector throught the CP0Cause IP lines.  */
+                   vector through the CP0Cause IP lines.  */
                 vector = pending;
             }
             offset = 0x200 + vector * spacing;
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 202c098..b8893b3 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -513,15 +513,15 @@ enum cc_op {
 
     CC_OP_ADD_64,               /* overflow on add (64bit) */
     CC_OP_ADDU_64,              /* overflow on unsigned add (64bit) */
-    CC_OP_SUB_64,               /* overflow on substraction (64bit) */
-    CC_OP_SUBU_64,              /* overflow on unsigned substraction (64bit) */
+    CC_OP_SUB_64,               /* overflow on subtraction (64bit) */
+    CC_OP_SUBU_64,              /* overflow on unsigned subtraction (64bit) */
     CC_OP_ABS_64,               /* sign eval on abs (64bit) */
     CC_OP_NABS_64,              /* sign eval on nabs (64bit) */
 
     CC_OP_ADD_32,               /* overflow on add (32bit) */
     CC_OP_ADDU_32,              /* overflow on unsigned add (32bit) */
-    CC_OP_SUB_32,               /* overflow on substraction (32bit) */
-    CC_OP_SUBU_32,              /* overflow on unsigned substraction (32bit) */
+    CC_OP_SUB_32,               /* overflow on subtraction (32bit) */
+    CC_OP_SUBU_32,              /* overflow on unsigned subtraction (32bit) */
     CC_OP_ABS_32,               /* sign eval on abs (64bit) */
     CC_OP_NABS_32,              /* sign eval on nabs (64bit) */
 
diff --git a/ui/vnc-enc-zywrle-template.c b/ui/vnc-enc-zywrle-template.c
index 4cde6e4..561f7bf 100644
--- a/ui/vnc-enc-zywrle-template.c
+++ b/ui/vnc-enc-zywrle-template.c
@@ -9,7 +9,7 @@
  *                                                                  *
  * THE 'ZYWRLE' VNC CODEC SOURCE CODE IS (C) COPYRIGHT 2006         *
  * BY Hitachi Systems & Services, Ltd.                              *
- * (Noriaki Yamazaki, Research & Developement Center)               *
+ * (Noriaki Yamazaki, Research & Development Center)               *
  *                                                                  *
  *                                                                  *
  ********************************************************************
diff --git a/ui/vnc-enc-zywrle.h b/ui/vnc-enc-zywrle.h
index ac5d27a..1ff40b1 100644
--- a/ui/vnc-enc-zywrle.h
+++ b/ui/vnc-enc-zywrle.h
@@ -8,7 +8,7 @@
  *                                                                  *
  * THE 'ZYWRLE' VNC CODEC SOURCE CODE IS (C) COPYRIGHT 2006         *
  * BY Hitachi Systems & Services, Ltd.                              *
- * (Noriaki Yamazaki, Research & Developement Center)               *
+ * (Noriaki Yamazaki, Research & Development Center)               *
  *                                                                  *
  *                                                                  *
  ********************************************************************
commit a1b6abe76bcc7b389849744dc4196d24f625d286
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 10 00:19:45 2011 +0100

    hw: Fix spelling in comments and code
    
    compatiblity->compatibility
    transfered->transferred
    transfering->transferring
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/es1370.c b/hw/es1370.c
index c5c16b0..6a3ba55 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -788,7 +788,7 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel,
     int cnt = d->frame_cnt >> 16;
     int size = d->frame_cnt & 0xffff;
     int left = ((size - cnt + 1) << 2) + d->leftover;
-    int transfered = 0;
+    int transferred = 0;
     int temp = audio_MIN (max, audio_MIN (left, csc_bytes));
     int index = d - &s->chan[0];
 
@@ -807,7 +807,7 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel,
 
             temp -= acquired;
             addr += acquired;
-            transfered += acquired;
+            transferred += acquired;
         }
     }
     else {
@@ -823,11 +823,11 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel,
                 break;
             temp -= copied;
             addr += copied;
-            transfered += copied;
+            transferred += copied;
         }
     }
 
-    if (csc_bytes == transfered) {
+    if (csc_bytes == transferred) {
         *irq = 1;
         d->scount = sc | (sc << 16);
         ldebug ("sc = %d, rate = %f\n",
@@ -836,10 +836,10 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel,
     }
     else {
         *irq = 0;
-        d->scount = sc | (((csc_bytes - transfered - 1) >> d->shift) << 16);
+        d->scount = sc | (((csc_bytes - transferred - 1) >> d->shift) << 16);
     }
 
-    cnt += (transfered + d->leftover) >> 2;
+    cnt += (transferred + d->leftover) >> 2;
 
     if (s->sctl & loop_sel) {
         /* Bah, how stupid is that having a 0 represent true value?
@@ -853,7 +853,7 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel,
             d->frame_cnt |= cnt << 16;
     }
 
-    d->leftover = (transfered + d->leftover) & 3;
+    d->leftover = (transferred + d->leftover) & 3;
 }
 
 static void es1370_run_channel (ES1370State *s, size_t chan, int free_or_avail)
commit 26404edcce09267f15aa723d1ea0a2761e91048f
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 10 00:19:44 2011 +0100

    hw: Fix spelling in comments
    
    adress->address
    advertisment->advertisement
    begining->beginning
    bondary->boundary
    controler->controller
    controll->control
    convertion->conversion
    doesnt->doesn't
    existant->existent
    instuction->instruction
    loosing->losing
    managment->management
    multipled->multiplied
    negotation->negotiation
    runing->running
    teh->the
    unchangable->unchangeable
    writen->written
    yeild->yield
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/gusemu.h b/hw/gusemu.h
index 34872aa..331bb6f 100644
--- a/hw/gusemu.h
+++ b/hw/gusemu.h
@@ -27,7 +27,7 @@
 
 /* data types (need to be adjusted if neither a VC6 nor a C99 compatible compiler is used) */
 
-#if defined _WIN32 && defined _MSC_VER /* doesnt support other win32 compilers yet, do it yourself... */
+#if defined _WIN32 && defined _MSC_VER /* doesn't support other win32 compilers yet, do it yourself... */
  typedef unsigned char GUSbyte;
  typedef unsigned short GUSword;
  typedef unsigned int GUSdword;
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index aa8ed0a..8aace9a 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -2662,7 +2662,7 @@ static void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val)
      * Computing if we miss an interrupt here is not that correct but
      * considered that we should have had already an interrupt
      * and probably emulated is slower is better to assume this resetting was
-     * done before testing on previous rtl8139_update_irq lead to IRQ loosing
+     * done before testing on previous rtl8139_update_irq lead to IRQ losing
      */
     rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
     rtl8139_update_irq(s);
diff --git a/hw/ssd0303.c b/hw/ssd0303.c
index 401fdf5..bcad7bf 100644
--- a/hw/ssd0303.c
+++ b/hw/ssd0303.c
@@ -123,7 +123,7 @@ static int ssd0303_send(i2c_slave *i2c, uint8_t data)
             case 0xa7: /* Inverse on.  */
                 s->inverse = 1;
                 break;
-            case 0xa8: /* Set multipled ratio (Ignored).  */
+            case 0xa8: /* Set multiplied ratio (Ignored).  */
                 s->cmd_state = SSD0303_CMD_SKIP1;
                 break;
             case 0xad: /* DC-DC power control.  */
commit 4d8db4e4a0280fcdc930b6709f1bf8fc2aa0404e
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 10 00:19:43 2011 +0100

    hw: Fix spelling (licenced->licensed)
    
    New code introduced old misspellings.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/lm4549.c b/hw/lm4549.c
index 4d5b831..80b3ec4 100644
--- a/hw/lm4549.c
+++ b/hw/lm4549.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2011
  * Written by Mathieu Sonet - www.elasticsheep.com
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  *
  * *****************************************************************
  *
diff --git a/hw/lm4549.h b/hw/lm4549.h
index 70d0ac1..5948780 100644
--- a/hw/lm4549.h
+++ b/hw/lm4549.h
@@ -4,7 +4,7 @@
  * Copyright (c) 2011
  * Written by Mathieu Sonet - www.elasticsheep.com
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  *
  * *****************************************************************
  */
diff --git a/hw/pl041.c b/hw/pl041.c
index d8e55d1..4585ccf 100644
--- a/hw/pl041.c
+++ b/hw/pl041.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2011
  * Written by Mathieu Sonet - www.elasticsheep.com
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  *
  * *****************************************************************
  *
diff --git a/hw/pl041.h b/hw/pl041.h
index 1f22432..427ab6d 100644
--- a/hw/pl041.h
+++ b/hw/pl041.h
@@ -4,7 +4,7 @@
  * Copyright (c) 2011
  * Written by Mathieu Sonet - www.elasticsheep.com
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  *
  * *****************************************************************
  */
diff --git a/hw/pl041.hx b/hw/pl041.hx
index e972996..dd7188c 100644
--- a/hw/pl041.hx
+++ b/hw/pl041.hx
@@ -4,7 +4,7 @@
  * Copyright (c) 2011
  * Written by Mathieu Sonet - www.elasticsheep.com
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  *
  * *****************************************************************
  */
commit c11e80e299e57c64934c164b231fa0d4279db445
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 10 00:19:42 2011 +0100

    fmopl: Fix spelling in code and comments
    
    algorythm->algorithm
    rythm->rhythm
    
    I did not try to fix the coding standard, so checkpatch.pl
    reports lots of violations.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/fmopl.c b/hw/fmopl.c
index 6198b89..734d2f4 100644
--- a/hw/fmopl.c
+++ b/hw/fmopl.c
@@ -362,8 +362,8 @@ INLINE UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT )
 	return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]+(SLOT->ams ? ams : 0);
 }
 
-/* set algorythm connection */
-static void set_algorythm( OPL_CH *CH)
+/* set algorithm connection */
+static void set_algorithm( OPL_CH *CH)
 {
 	INT32 *carrier = &outd[0];
 	CH->connect1 = CH->CON ? carrier : &feedback2;
@@ -498,7 +498,7 @@ INLINE void OPL_CALC_CH( OPL_CH *CH )
 	}
 }
 
-/* ---------- calcrate rythm block ---------- */
+/* ---------- calcrate rhythm block ---------- */
 #define WHITE_NOISE_db 6.0
 INLINE void OPL_CALC_RH( OPL_CH *CH )
 {
@@ -895,14 +895,14 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
 		case 0xbd:
 			/* amsep,vibdep,r,bd,sd,tom,tc,hh */
 			{
-			UINT8 rkey = OPL->rythm^v;
+			UINT8 rkey = OPL->rhythm^v;
 			OPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0];
 			OPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0];
-			OPL->rythm  = v&0x3f;
-			if(OPL->rythm&0x20)
+			OPL->rhythm  = v&0x3f;
+			if(OPL->rhythm&0x20)
 			{
 #if 0
-				usrintf_showmessage("OPL Rythm mode select");
+				usrintf_showmessage("OPL Rhythm mode select");
 #endif
 				/* BD key on/off */
 				if(rkey&0x10)
@@ -995,7 +995,7 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
 		int feedback = (v>>1)&7;
 		CH->FB   = feedback ? (8+1) - feedback : 0;
 		CH->CON = v&1;
-		set_algorythm(CH);
+		set_algorithm(CH);
 		}
 		return;
 	case 0xe0: /* wave type */
@@ -1049,7 +1049,7 @@ void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
 	OPLSAMPLE *buf = buffer;
 	UINT32 amsCnt  = OPL->amsCnt;
 	UINT32 vibCnt  = OPL->vibCnt;
-	UINT8 rythm = OPL->rythm&0x20;
+	UINT8 rhythm = OPL->rhythm&0x20;
 	OPL_CH *CH,*R_CH;
 
 	if( (void *)OPL != cur_chip ){
@@ -1057,7 +1057,7 @@ void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
 		/* channel pointers */
 		S_CH = OPL->P_CH;
 		E_CH = &S_CH[9];
-		/* rythm slot */
+		/* rhythm slot */
 		SLOT7_1 = &S_CH[7].SLOT[SLOT1];
 		SLOT7_2 = &S_CH[7].SLOT[SLOT2];
 		SLOT8_1 = &S_CH[8].SLOT[SLOT1];
@@ -1068,7 +1068,7 @@ void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
 		ams_table = OPL->ams_table;
 		vib_table = OPL->vib_table;
 	}
-	R_CH = rythm ? &S_CH[6] : E_CH;
+	R_CH = rhythm ? &S_CH[6] : E_CH;
     for( i=0; i < length ; i++ )
 	{
 		/*            channel A         channel B         channel C      */
@@ -1080,7 +1080,7 @@ void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
 		for(CH=S_CH ; CH < R_CH ; CH++)
 			OPL_CALC_CH(CH);
 		/* Rythn part */
-		if(rythm)
+		if(rhythm)
 			OPL_CALC_RH(S_CH);
 		/* limit check */
 		data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
@@ -1110,7 +1110,7 @@ void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
 	OPLSAMPLE *buf = buffer;
 	UINT32 amsCnt  = OPL->amsCnt;
 	UINT32 vibCnt  = OPL->vibCnt;
-	UINT8 rythm = OPL->rythm&0x20;
+	UINT8 rhythm = OPL->rhythm&0x20;
 	OPL_CH *CH,*R_CH;
 	YM_DELTAT *DELTAT = OPL->deltat;
 
@@ -1122,7 +1122,7 @@ void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
 		/* channel pointers */
 		S_CH = OPL->P_CH;
 		E_CH = &S_CH[9];
-		/* rythm slot */
+		/* rhythm slot */
 		SLOT7_1 = &S_CH[7].SLOT[SLOT1];
 		SLOT7_2 = &S_CH[7].SLOT[SLOT2];
 		SLOT8_1 = &S_CH[8].SLOT[SLOT1];
@@ -1133,7 +1133,7 @@ void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
 		ams_table = OPL->ams_table;
 		vib_table = OPL->vib_table;
 	}
-	R_CH = rythm ? &S_CH[6] : E_CH;
+	R_CH = rhythm ? &S_CH[6] : E_CH;
     for( i=0; i < length ; i++ )
 	{
 		/*            channel A         channel B         channel C      */
@@ -1148,7 +1148,7 @@ void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
 		for(CH=S_CH ; CH < R_CH ; CH++)
 			OPL_CALC_CH(CH);
 		/* Rythn part */
-		if(rythm)
+		if(rhythm)
 			OPL_CALC_RH(S_CH);
 		/* limit check */
 		data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
diff --git a/hw/fmopl.h b/hw/fmopl.h
index a01ff90..24ba5f4 100644
--- a/hw/fmopl.h
+++ b/hw/fmopl.h
@@ -110,8 +110,8 @@ typedef struct fm_opl_f {
 	/* FM channel slots */
 	OPL_CH *P_CH;		/* pointer of CH                     */
 	int	max_ch;			/* maximum channel                   */
-	/* Rythm sention */
-	UINT8 rythm;		/* Rythm mode , key flag */
+	/* Rhythm sention */
+	UINT8 rhythm;		/* Rhythm mode , key flag */
 #if BUILD_Y8950
 	/* Delta-T ADPCM unit (Y8950) */
 	YM_DELTAT *deltat;			/* DELTA-T ADPCM       */
commit db8336cd1f04e658b2441d4fcfbbb3c5e42b0469
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Tue Dec 13 18:19:25 2011 +0000

    target-arm: Infer VFPv3 feature from VFPv4
    
    VFP4 => VFP3
    
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index bd5576c..65f4fbf 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -164,7 +164,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         break;
     case ARM_CPUID_ANY: /* For userspace emulation.  */
         set_feature(env, ARM_FEATURE_V7);
-        set_feature(env, ARM_FEATURE_VFP3);
         set_feature(env, ARM_FEATURE_VFP4);
         set_feature(env, ARM_FEATURE_VFP_FP16);
         set_feature(env, ARM_FEATURE_NEON);
@@ -245,6 +244,9 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     if (arm_feature(env, ARM_FEATURE_ARM_DIV)) {
         set_feature(env, ARM_FEATURE_THUMB_DIV);
     }
+    if (arm_feature(env, ARM_FEATURE_VFP4)) {
+        set_feature(env, ARM_FEATURE_VFP3);
+    }
     if (arm_feature(env, ARM_FEATURE_VFP3)) {
         set_feature(env, ARM_FEATURE_VFP);
     }
commit 86e72db6aaa2164d96fcab7290125ce3492718c6
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Tue Dec 13 18:19:24 2011 +0000

    target-arm: Infer VFP feature from VFPv3
    
    VFP3 => VFP
    
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index a566aa3..bd5576c 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -121,7 +121,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         break;
     case ARM_CPUID_CORTEXA8:
         set_feature(env, ARM_FEATURE_V7);
-        set_feature(env, ARM_FEATURE_VFP);
         set_feature(env, ARM_FEATURE_VFP3);
         set_feature(env, ARM_FEATURE_NEON);
         set_feature(env, ARM_FEATURE_THUMB2EE);
@@ -139,7 +138,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         break;
     case ARM_CPUID_CORTEXA9:
         set_feature(env, ARM_FEATURE_V7);
-        set_feature(env, ARM_FEATURE_VFP);
         set_feature(env, ARM_FEATURE_VFP3);
         set_feature(env, ARM_FEATURE_VFP_FP16);
         set_feature(env, ARM_FEATURE_NEON);
@@ -166,7 +164,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         break;
     case ARM_CPUID_ANY: /* For userspace emulation.  */
         set_feature(env, ARM_FEATURE_V7);
-        set_feature(env, ARM_FEATURE_VFP);
         set_feature(env, ARM_FEATURE_VFP3);
         set_feature(env, ARM_FEATURE_VFP4);
         set_feature(env, ARM_FEATURE_VFP_FP16);
@@ -248,6 +245,9 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     if (arm_feature(env, ARM_FEATURE_ARM_DIV)) {
         set_feature(env, ARM_FEATURE_THUMB_DIV);
     }
+    if (arm_feature(env, ARM_FEATURE_VFP3)) {
+        set_feature(env, ARM_FEATURE_VFP);
+    }
 }
 
 void cpu_reset(CPUARMState *env)
commit 908ce98085124019e31afebc51e80ebb95840c85
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Tue Dec 13 18:19:24 2011 +0000

    target-arm: Infer Thumb division feature from M profile
    
    M => THUMB_DIV
    
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 281b315..a566aa3 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -163,7 +163,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     case ARM_CPUID_CORTEXM3:
         set_feature(env, ARM_FEATURE_V7);
         set_feature(env, ARM_FEATURE_M);
-        set_feature(env, ARM_FEATURE_THUMB_DIV);
         break;
     case ARM_CPUID_ANY: /* For userspace emulation.  */
         set_feature(env, ARM_FEATURE_V7);
@@ -243,6 +242,9 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     if (arm_feature(env, ARM_FEATURE_V5)) {
         set_feature(env, ARM_FEATURE_V4T);
     }
+    if (arm_feature(env, ARM_FEATURE_M)) {
+        set_feature(env, ARM_FEATURE_THUMB_DIV);
+    }
     if (arm_feature(env, ARM_FEATURE_ARM_DIV)) {
         set_feature(env, ARM_FEATURE_THUMB_DIV);
     }
commit b3faf5f02e99d30cc43c74fef976701a00a8c4e9
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Tue Dec 13 18:19:24 2011 +0000

    target-arm: Infer Thumb2 feature from ARMv7
    
    V7 => THUMB2
    
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 0a7f745..281b315 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -121,7 +121,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         break;
     case ARM_CPUID_CORTEXA8:
         set_feature(env, ARM_FEATURE_V7);
-        set_feature(env, ARM_FEATURE_THUMB2);
         set_feature(env, ARM_FEATURE_VFP);
         set_feature(env, ARM_FEATURE_VFP3);
         set_feature(env, ARM_FEATURE_NEON);
@@ -140,7 +139,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         break;
     case ARM_CPUID_CORTEXA9:
         set_feature(env, ARM_FEATURE_V7);
-        set_feature(env, ARM_FEATURE_THUMB2);
         set_feature(env, ARM_FEATURE_VFP);
         set_feature(env, ARM_FEATURE_VFP3);
         set_feature(env, ARM_FEATURE_VFP_FP16);
@@ -163,14 +161,12 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00c50078;
         break;
     case ARM_CPUID_CORTEXM3:
-        set_feature(env, ARM_FEATURE_THUMB2);
         set_feature(env, ARM_FEATURE_V7);
         set_feature(env, ARM_FEATURE_M);
         set_feature(env, ARM_FEATURE_THUMB_DIV);
         break;
     case ARM_CPUID_ANY: /* For userspace emulation.  */
         set_feature(env, ARM_FEATURE_V7);
-        set_feature(env, ARM_FEATURE_THUMB2);
         set_feature(env, ARM_FEATURE_VFP);
         set_feature(env, ARM_FEATURE_VFP3);
         set_feature(env, ARM_FEATURE_VFP4);
@@ -228,6 +224,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     /* Some features automatically imply others: */
     if (arm_feature(env, ARM_FEATURE_V7)) {
         set_feature(env, ARM_FEATURE_VAPA);
+        set_feature(env, ARM_FEATURE_THUMB2);
         if (!arm_feature(env, ARM_FEATURE_M)) {
             set_feature(env, ARM_FEATURE_V6K);
         } else {
commit 10e87702745b89d56678edad9da9efb6fce4ea71
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Tue Dec 13 18:19:24 2011 +0000

    target-arm: Infer AUXCR feature from ARMv6
    
    V6 && !M => AUXCR
    
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 1108156..0a7f745 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -84,7 +84,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
          */
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_VFP);
-        set_feature(env, ARM_FEATURE_AUXCR);
         /* These ID register values are correct for 1136 but may be wrong
          * for 1136_r2 (in particular r0p2 does not actually implement most
          * of the ID registers).
@@ -100,7 +99,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     case ARM_CPUID_ARM1176:
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_VFP);
-        set_feature(env, ARM_FEATURE_AUXCR);
         set_feature(env, ARM_FEATURE_VAPA);
         env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b5;
         env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111;
@@ -113,7 +111,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     case ARM_CPUID_ARM11MPCORE:
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_VFP);
-        set_feature(env, ARM_FEATURE_AUXCR);
         set_feature(env, ARM_FEATURE_VAPA);
         env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b4;
         env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111;
@@ -124,7 +121,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         break;
     case ARM_CPUID_CORTEXA8:
         set_feature(env, ARM_FEATURE_V7);
-        set_feature(env, ARM_FEATURE_AUXCR);
         set_feature(env, ARM_FEATURE_THUMB2);
         set_feature(env, ARM_FEATURE_VFP);
         set_feature(env, ARM_FEATURE_VFP3);
@@ -144,7 +140,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         break;
     case ARM_CPUID_CORTEXA9:
         set_feature(env, ARM_FEATURE_V7);
-        set_feature(env, ARM_FEATURE_AUXCR);
         set_feature(env, ARM_FEATURE_THUMB2);
         set_feature(env, ARM_FEATURE_VFP);
         set_feature(env, ARM_FEATURE_VFP3);
@@ -244,6 +239,9 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     }
     if (arm_feature(env, ARM_FEATURE_V6)) {
         set_feature(env, ARM_FEATURE_V5);
+        if (!arm_feature(env, ARM_FEATURE_M)) {
+            set_feature(env, ARM_FEATURE_AUXCR);
+        }
     }
     if (arm_feature(env, ARM_FEATURE_V5)) {
         set_feature(env, ARM_FEATURE_V4T);
commit bbc5c5fa177156299eca4dd7fceb04cb42035c14
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Tue Dec 13 18:19:24 2011 +0000

    target-arm: Infer ARMv6(K) feature from ARMv7
    
    V7 && M => V6
    V7 && !M => V6K
    
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index a948b88..1108156 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -123,7 +123,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c0_cachetype = 0x1dd20d2;
         break;
     case ARM_CPUID_CORTEXA8:
-        set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_V7);
         set_feature(env, ARM_FEATURE_AUXCR);
         set_feature(env, ARM_FEATURE_THUMB2);
@@ -144,7 +143,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00c50078;
         break;
     case ARM_CPUID_CORTEXA9:
-        set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_V7);
         set_feature(env, ARM_FEATURE_AUXCR);
         set_feature(env, ARM_FEATURE_THUMB2);
@@ -170,14 +168,12 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00c50078;
         break;
     case ARM_CPUID_CORTEXM3:
-        set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_THUMB2);
         set_feature(env, ARM_FEATURE_V7);
         set_feature(env, ARM_FEATURE_M);
         set_feature(env, ARM_FEATURE_THUMB_DIV);
         break;
     case ARM_CPUID_ANY: /* For userspace emulation.  */
-        set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_V7);
         set_feature(env, ARM_FEATURE_THUMB2);
         set_feature(env, ARM_FEATURE_VFP);
@@ -237,6 +233,11 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     /* Some features automatically imply others: */
     if (arm_feature(env, ARM_FEATURE_V7)) {
         set_feature(env, ARM_FEATURE_VAPA);
+        if (!arm_feature(env, ARM_FEATURE_M)) {
+            set_feature(env, ARM_FEATURE_V6K);
+        } else {
+            set_feature(env, ARM_FEATURE_V6);
+        }
     }
     if (arm_feature(env, ARM_FEATURE_V6K)) {
         set_feature(env, ARM_FEATURE_V6);
commit 6bf62124f5d1df1d654f5c8c764e1894d40b5922
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Tue Dec 13 18:19:24 2011 +0000

    target-arm: Infer ARMv6 feature from v6K
    
    V6K => V6
    
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 6a78dd0..a948b88 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -98,7 +98,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00050078;
         break;
     case ARM_CPUID_ARM1176:
-        set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_VFP);
         set_feature(env, ARM_FEATURE_AUXCR);
@@ -112,7 +111,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00050078;
         break;
     case ARM_CPUID_ARM11MPCORE:
-        set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_VFP);
         set_feature(env, ARM_FEATURE_AUXCR);
@@ -125,7 +123,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c0_cachetype = 0x1dd20d2;
         break;
     case ARM_CPUID_CORTEXA8:
-        set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_V7);
         set_feature(env, ARM_FEATURE_AUXCR);
@@ -147,7 +144,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00c50078;
         break;
     case ARM_CPUID_CORTEXA9:
-        set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_V7);
         set_feature(env, ARM_FEATURE_AUXCR);
@@ -181,7 +177,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         set_feature(env, ARM_FEATURE_THUMB_DIV);
         break;
     case ARM_CPUID_ANY: /* For userspace emulation.  */
-        set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_V7);
         set_feature(env, ARM_FEATURE_THUMB2);
@@ -243,6 +238,9 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     if (arm_feature(env, ARM_FEATURE_V7)) {
         set_feature(env, ARM_FEATURE_VAPA);
     }
+    if (arm_feature(env, ARM_FEATURE_V6K)) {
+        set_feature(env, ARM_FEATURE_V6);
+    }
     if (arm_feature(env, ARM_FEATURE_V6)) {
         set_feature(env, ARM_FEATURE_V5);
     }
commit 08c40f3c626c3933e62d3d1113b04f99efa7ba4c
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Tue Dec 13 18:19:24 2011 +0000

    target-arm: Infer ARMv5 feature from ARMv6
    
    V6 => V5
    
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index eff2ac1..6a78dd0 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -82,7 +82,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
          * older core than plain "arm1136". In particular this does not
          * have the v6K features.
          */
-        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_VFP);
         set_feature(env, ARM_FEATURE_AUXCR);
@@ -99,7 +98,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00050078;
         break;
     case ARM_CPUID_ARM1176:
-        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_VFP);
@@ -114,7 +112,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00050078;
         break;
     case ARM_CPUID_ARM11MPCORE:
-        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_VFP);
@@ -128,7 +125,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c0_cachetype = 0x1dd20d2;
         break;
     case ARM_CPUID_CORTEXA8:
-        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_V7);
@@ -151,7 +147,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00c50078;
         break;
     case ARM_CPUID_CORTEXA9:
-        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_V7);
@@ -179,7 +174,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00c50078;
         break;
     case ARM_CPUID_CORTEXM3:
-        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_THUMB2);
         set_feature(env, ARM_FEATURE_V7);
@@ -187,7 +181,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         set_feature(env, ARM_FEATURE_THUMB_DIV);
         break;
     case ARM_CPUID_ANY: /* For userspace emulation.  */
-        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_V7);
@@ -250,6 +243,9 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     if (arm_feature(env, ARM_FEATURE_V7)) {
         set_feature(env, ARM_FEATURE_VAPA);
     }
+    if (arm_feature(env, ARM_FEATURE_V6)) {
+        set_feature(env, ARM_FEATURE_V5);
+    }
     if (arm_feature(env, ARM_FEATURE_V5)) {
         set_feature(env, ARM_FEATURE_V4T);
     }
commit ddb572ec48208a075187501e79fd0b80fcefa4be
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Tue Dec 13 18:19:23 2011 +0000

    target-arm: Infer ARMv4T feature from ARMv5
    
    V5 => V4T
    
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 1949202..eff2ac1 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -53,7 +53,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     env->cp15.c0_cpuid = id;
     switch (id) {
     case ARM_CPUID_ARM926:
-        set_feature(env, ARM_FEATURE_V4T);
         set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_VFP);
         env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
@@ -61,14 +60,12 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00090078;
         break;
     case ARM_CPUID_ARM946:
-        set_feature(env, ARM_FEATURE_V4T);
         set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_MPU);
         env->cp15.c0_cachetype = 0x0f004006;
         env->cp15.c1_sys = 0x00000078;
         break;
     case ARM_CPUID_ARM1026:
-        set_feature(env, ARM_FEATURE_V4T);
         set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_VFP);
         set_feature(env, ARM_FEATURE_AUXCR);
@@ -85,7 +82,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
          * older core than plain "arm1136". In particular this does not
          * have the v6K features.
          */
-        set_feature(env, ARM_FEATURE_V4T);
         set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_VFP);
@@ -103,7 +99,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00050078;
         break;
     case ARM_CPUID_ARM1176:
-        set_feature(env, ARM_FEATURE_V4T);
         set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
@@ -119,7 +114,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00050078;
         break;
     case ARM_CPUID_ARM11MPCORE:
-        set_feature(env, ARM_FEATURE_V4T);
         set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
@@ -134,7 +128,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c0_cachetype = 0x1dd20d2;
         break;
     case ARM_CPUID_CORTEXA8:
-        set_feature(env, ARM_FEATURE_V4T);
         set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
@@ -158,7 +151,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00c50078;
         break;
     case ARM_CPUID_CORTEXA9:
-        set_feature(env, ARM_FEATURE_V4T);
         set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
@@ -187,7 +179,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00c50078;
         break;
     case ARM_CPUID_CORTEXM3:
-        set_feature(env, ARM_FEATURE_V4T);
         set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_THUMB2);
@@ -196,7 +187,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         set_feature(env, ARM_FEATURE_THUMB_DIV);
         break;
     case ARM_CPUID_ANY: /* For userspace emulation.  */
-        set_feature(env, ARM_FEATURE_V4T);
         set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
@@ -226,7 +216,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     case ARM_CPUID_PXA260:
     case ARM_CPUID_PXA261:
     case ARM_CPUID_PXA262:
-        set_feature(env, ARM_FEATURE_V4T);
         set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_XSCALE);
         /* JTAG_ID is ((id << 28) | 0x09265013) */
@@ -239,7 +228,6 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     case ARM_CPUID_PXA270_B1:
     case ARM_CPUID_PXA270_C0:
     case ARM_CPUID_PXA270_C5:
-        set_feature(env, ARM_FEATURE_V4T);
         set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_XSCALE);
         /* JTAG_ID is ((id << 28) | 0x09265013) */
@@ -262,6 +250,9 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     if (arm_feature(env, ARM_FEATURE_V7)) {
         set_feature(env, ARM_FEATURE_VAPA);
     }
+    if (arm_feature(env, ARM_FEATURE_V5)) {
+        set_feature(env, ARM_FEATURE_V4T);
+    }
     if (arm_feature(env, ARM_FEATURE_ARM_DIV)) {
         set_feature(env, ARM_FEATURE_THUMB_DIV);
     }
commit dd4ebc2ecde4d607509a33f4f40d8795a0b3b88f
Author: Jean-Christophe DUBOIS <jcd at tribudubois.net>
Date:   Tue Dec 13 18:19:23 2011 +0000

    arm: Fix CP15 FSR (C5) domain setting
    
    Return the correct value in the domain field in the cp15 DFSR
    (C5) -- bug noticed during Xvisor development.
    
    Signed-off-by: Jean-Christophe DUBOIS <jcd at tribudubois.net>
    [Peter Maydell: reworded commit message]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 3fe5822..1949202 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -951,13 +951,14 @@ 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, int access_type,
-                           int is_user)
+static inline int check_ap(CPUState *env, int ap, int domain_prot,
+                           int access_type, int is_user)
 {
   int prot_ro;
 
-  if (domain == 3)
+  if (domain_prot == 3) {
     return PAGE_READ | PAGE_WRITE;
+  }
 
   if (access_type == 1)
       prot_ro = 0;
@@ -1023,6 +1024,7 @@ static int get_phys_addr_v5(CPUState *env, uint32_t address, int access_type,
     int type;
     int ap;
     int domain;
+    int domain_prot;
     uint32_t phys_addr;
 
     /* Pagetable walk.  */
@@ -1030,13 +1032,14 @@ static int get_phys_addr_v5(CPUState *env, uint32_t address, int access_type,
     table = get_level1_table_address(env, address);
     desc = ldl_phys(table);
     type = (desc & 3);
-    domain = (env->cp15.c3 >> ((desc >> 4) & 0x1e)) & 3;
+    domain = (desc >> 5) & 0x0f;
+    domain_prot = (env->cp15.c3 >> (domain * 2)) & 3;
     if (type == 0) {
         /* Section translation fault.  */
         code = 5;
         goto do_fault;
     }
-    if (domain == 0 || domain == 2) {
+    if (domain_prot == 0 || domain_prot == 2) {
         if (type == 2)
             code = 9; /* Section domain fault.  */
         else
@@ -1094,7 +1097,7 @@ static int get_phys_addr_v5(CPUState *env, uint32_t address, int access_type,
         }
         code = 15;
     }
-    *prot = check_ap(env, ap, domain, access_type, is_user);
+    *prot = check_ap(env, ap, domain_prot, access_type, is_user);
     if (!*prot) {
         /* Access permission fault.  */
         goto do_fault;
@@ -1117,6 +1120,7 @@ static int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type,
     int type;
     int ap;
     int domain;
+    int domain_prot;
     uint32_t phys_addr;
 
     /* Pagetable walk.  */
@@ -1134,10 +1138,10 @@ static int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type,
         domain = 0;
     } else {
         /* Section or page.  */
-        domain = (desc >> 4) & 0x1e;
+        domain = (desc >> 5) & 0x0f;
     }
-    domain = (env->cp15.c3 >> domain) & 3;
-    if (domain == 0 || domain == 2) {
+    domain_prot = (env->cp15.c3 >> (domain * 2)) & 3;
+    if (domain_prot == 0 || domain_prot == 2) {
         if (type == 2)
             code = 9; /* Section domain fault.  */
         else
@@ -1182,7 +1186,7 @@ static int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type,
         }
         code = 15;
     }
-    if (domain == 3) {
+    if (domain_prot == 3) {
         *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
     } else {
         if (xn && access_type == 2)
@@ -1194,7 +1198,7 @@ static int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type,
             code = (code == 15) ? 6 : 3;
             goto do_fault;
         }
-        *prot = check_ap(env, ap, domain, access_type, is_user);
+        *prot = check_ap(env, ap, domain_prot, access_type, is_user);
         if (!*prot) {
             /* Access permission fault.  */
             goto do_fault;
commit da5361cc685c004d8bb4e7c5e7b3a52c7aca2c56
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Dec 12 17:21:34 2011 +0100

    ccid: make threads joinable
    
    Destroying a mutex that another thread might have just unlocked
    is racy.  It usually works, but you cannot do that in general and
    can lead to deadlocks or segfaults.  Change ccid to use joinable
    threads instead.
    
    (Also, qemu_mutex_init/qemu_cond_init were missing).
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c
index 9fe9db5..2d2ebce 100644
--- a/hw/ccid-card-emulated.c
+++ b/hw/ccid-card-emulated.c
@@ -120,6 +120,7 @@ struct EmulatedState {
     uint8_t  atr_length;
     QSIMPLEQ_HEAD(event_list, EmulEvent) event_list;
     QemuMutex event_list_mutex;
+    QemuThread event_thread_id;
     VReader *reader;
     QSIMPLEQ_HEAD(guest_apdu_list, EmulEvent) guest_apdu_list;
     QemuMutex vreader_mutex; /* and guest_apdu_list mutex */
@@ -127,8 +128,7 @@ struct EmulatedState {
     QemuCond handle_apdu_cond;
     int      pipe[2];
     int      quit_apdu_thread;
-    QemuMutex apdu_thread_quit_mutex;
-    QemuCond apdu_thread_quit_cond;
+    QemuThread apdu_thread_id;
 };
 
 static void emulated_apdu_from_guest(CCIDCardState *base,
@@ -271,9 +271,6 @@ static void *handle_apdu_thread(void* arg)
         }
         qemu_mutex_unlock(&card->vreader_mutex);
     }
-    qemu_mutex_lock(&card->apdu_thread_quit_mutex);
-    qemu_cond_signal(&card->apdu_thread_quit_cond);
-    qemu_mutex_unlock(&card->apdu_thread_quit_mutex);
     return NULL;
 }
 
@@ -489,7 +486,6 @@ static uint32_t parse_enumeration(char *str,
 static int emulated_initfn(CCIDCardState *base)
 {
     EmulatedState *card = DO_UPCAST(EmulatedState, base, base);
-    QemuThread thread_id;
     VCardEmulError ret;
     EnumTable *ptable;
 
@@ -541,9 +537,10 @@ static int emulated_initfn(CCIDCardState *base)
         printf("%s: failed to initialize vcard\n", EMULATED_DEV_NAME);
         return -1;
     }
-    qemu_thread_create(&thread_id, event_thread, card, QEMU_THREAD_DETACHED);
-    qemu_thread_create(&thread_id, handle_apdu_thread, card,
-                       QEMU_THREAD_DETACHED);
+    qemu_thread_create(&card->event_thread_id, event_thread, card,
+                       QEMU_THREAD_JOINABLE);
+    qemu_thread_create(&card->apdu_thread_id, handle_apdu_thread, card,
+                       QEMU_THREAD_JOINABLE);
     return 0;
 }
 
@@ -553,15 +550,14 @@ static int emulated_exitfn(CCIDCardState *base)
     VEvent *vevent = vevent_new(VEVENT_LAST, NULL, NULL);
 
     vevent_queue_vevent(vevent); /* stop vevent thread */
-    qemu_mutex_lock(&card->apdu_thread_quit_mutex);
+    qemu_thread_join(&card->event_thread_id);
+
     card->quit_apdu_thread = 1; /* stop handle_apdu thread */
     qemu_cond_signal(&card->handle_apdu_cond);
-    qemu_cond_wait(&card->apdu_thread_quit_cond,
-                      &card->apdu_thread_quit_mutex);
-    /* handle_apdu thread stopped, can destroy all of it's mutexes */
+    qemu_thread_join(&card->apdu_thread_id);
+
+    /* threads exited, can destroy all condvars/mutexes */
     qemu_cond_destroy(&card->handle_apdu_cond);
-    qemu_cond_destroy(&card->apdu_thread_quit_cond);
-    qemu_mutex_destroy(&card->apdu_thread_quit_mutex);
     qemu_mutex_destroy(&card->handle_apdu_mutex);
     qemu_mutex_destroy(&card->vreader_mutex);
     qemu_mutex_destroy(&card->event_list_mutex);
commit 403e633126b7a781ecd48a29e3355770d46bbf1a
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Dec 12 17:21:33 2011 +0100

    qemu-thread: implement joinable threads for Win32
    
    Rewrite the handshaking between qemu_thread_create and the
    win32_start_routine, so that the thread can be joined without races.
    Similar handshaking is done now between qemu_thread_exit and
    qemu_thread_join.
    
    This also simplifies how QemuThreads are initialized.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c
index ff80e84..a13ffcc 100644
--- a/qemu-thread-win32.c
+++ b/qemu-thread-win32.c
@@ -193,41 +193,78 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
 }
 
 struct QemuThreadData {
-    QemuThread *thread;
-    void *(*start_routine)(void *);
-    void *arg;
+    /* Passed to win32_start_routine.  */
+    void             *(*start_routine)(void *);
+    void             *arg;
+    short             mode;
+
+    /* Only used for joinable threads. */
+    bool              exited;
+    void             *ret;
+    CRITICAL_SECTION  cs;
 };
 
 static int qemu_thread_tls_index = TLS_OUT_OF_INDEXES;
 
 static unsigned __stdcall win32_start_routine(void *arg)
 {
-    struct QemuThreadData data = *(struct QemuThreadData *) arg;
-    QemuThread *thread = data.thread;
-
-    free(arg);
-    TlsSetValue(qemu_thread_tls_index, thread);
-
-    /*
-     * Use DuplicateHandle instead of assigning thread->thread in the
-     * creating thread to avoid races.  It's simpler this way than with
-     * synchronization.
-     */
-    DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
-                    GetCurrentProcess(), &thread->thread,
-                    0, FALSE, DUPLICATE_SAME_ACCESS);
-
-    qemu_thread_exit(data.start_routine(data.arg));
+    QemuThreadData *data = (QemuThreadData *) arg;
+    void *(*start_routine)(void *) = data->start_routine;
+    void *thread_arg = data->arg;
+
+    if (data->mode == QEMU_THREAD_DETACHED) {
+        g_free(data);
+        data = NULL;
+    } else {
+        InitializeCriticalSection(&data->cs);
+    }
+    TlsSetValue(qemu_thread_tls_index, data);
+    qemu_thread_exit(start_routine(thread_arg));
     abort();
 }
 
 void qemu_thread_exit(void *arg)
 {
-    QemuThread *thread = TlsGetValue(qemu_thread_tls_index);
-    thread->ret = arg;
-    CloseHandle(thread->thread);
-    thread->thread = NULL;
-    ExitThread(0);
+    QemuThreadData *data = TlsGetValue(qemu_thread_tls_index);
+    if (data) {
+        data->ret = arg;
+        EnterCriticalSection(&data->cs);
+        data->exited = true;
+        LeaveCriticalSection(&data->cs);
+    }
+    _endthreadex(0);
+}
+
+void *qemu_thread_join(QemuThread *thread)
+{
+    QemuThreadData *data;
+    void *ret;
+    HANDLE handle;
+
+    data = thread->data;
+    if (!data) {
+        return NULL;
+    }
+    /*
+     * Because multiple copies of the QemuThread can exist via
+     * qemu_thread_get_self, we need to store a value that cannot
+     * leak there.  The simplest, non racy way is to store the TID,
+     * discard the handle that _beginthreadex gives back, and
+     * get another copy of the handle here.
+     */
+    EnterCriticalSection(&data->cs);
+    if (!data->exited) {
+        handle = OpenThread(SYNCHRONIZE, FALSE, thread->tid);
+        LeaveCriticalSection(&data->cs);
+        WaitForSingleObject(handle, INFINITE);
+        CloseHandle(handle);
+    } else {
+        LeaveCriticalSection(&data->cs);
+    }
+    ret = data->ret;
+    DeleteCriticalSection(&data->cs);
+    g_free(data);
+    return ret;
 }
 
 static inline void qemu_thread_init(void)
@@ -247,37 +284,31 @@ void qemu_thread_create(QemuThread *thread,
 {
     HANDLE hThread;
 
-    assert(mode == QEMU_THREAD_DETACHED);
-
     struct QemuThreadData *data;
     qemu_thread_init();
     data = g_malloc(sizeof *data);
-    data->thread = thread;
     data->start_routine = start_routine;
     data->arg = arg;
+    data->mode = mode;
+    data->exited = false;
 
     hThread = (HANDLE) _beginthreadex(NULL, 0, win32_start_routine,
-                                      data, 0, NULL);
+                                      data, 0, &thread->tid);
     if (!hThread) {
         error_exit(GetLastError(), __func__);
     }
     CloseHandle(hThread);
+    thread->data = (mode == QEMU_THREAD_DETACHED) ? NULL : data;
 }
 
 void qemu_thread_get_self(QemuThread *thread)
 {
-    if (!thread->thread) {
-        /* In the main thread of the process.  Initialize the QemuThread
-           pointer in TLS, and use the dummy GetCurrentThread handle as
-           the identifier for qemu_thread_is_self.  */
-        qemu_thread_init();
-        TlsSetValue(qemu_thread_tls_index, thread);
-        thread->thread = GetCurrentThread();
-    }
+    qemu_thread_init();
+    thread->data = TlsGetValue(qemu_thread_tls_index);
+    thread->tid = GetCurrentThreadId();
 }
 
 int qemu_thread_is_self(QemuThread *thread)
 {
-    QemuThread *this_thread = TlsGetValue(qemu_thread_tls_index);
-    return this_thread->thread == thread->thread;
+    return GetCurrentThreadId() == thread->tid;
 }
diff --git a/qemu-thread-win32.h b/qemu-thread-win32.h
index 878f86a..2983490 100644
--- a/qemu-thread-win32.h
+++ b/qemu-thread-win32.h
@@ -13,9 +13,10 @@ struct QemuCond {
     HANDLE continue_event;
 };
 
+typedef struct QemuThreadData QemuThreadData;
 struct QemuThread {
-    HANDLE thread;
-    void *ret;
+    QemuThreadData *data;
+    unsigned tid;
 };
 
 #endif
commit 8763046b4b27f59ce0b639dbca896a01bf7b1388
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Dec 12 17:21:32 2011 +0100

    qemu-thread: implement joinable threads for POSIX
    
    Allow to control if a QEMU thread is created joinable or not. Make it
    not joinable by default to avoid that we keep the associated resources
    around when terminating a thread without joining it (what we couldn't do
    so far for obvious reasons).
    
    The audio subsystem will need the join feature when converting it to
    QEMU threading/locking abstractions, so provide that service.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
index 49d3388..9e1b5fb 100644
--- a/qemu-thread-posix.c
+++ b/qemu-thread-posix.c
@@ -121,17 +121,29 @@ void qemu_thread_create(QemuThread *thread,
 {
     sigset_t set, oldset;
     int err;
+    pthread_attr_t attr;
 
-    assert(mode == QEMU_THREAD_DETACHED);
+    err = pthread_attr_init(&attr);
+    if (err) {
+        error_exit(err, __func__);
+    }
+    if (mode == QEMU_THREAD_DETACHED) {
+        err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+        if (err) {
+            error_exit(err, __func__);
+        }
+    }
 
     /* Leave signal handling to the iothread.  */
     sigfillset(&set);
     pthread_sigmask(SIG_SETMASK, &set, &oldset);
-    err = pthread_create(&thread->thread, NULL, start_routine, arg);
+    err = pthread_create(&thread->thread, &attr, start_routine, arg);
     if (err)
         error_exit(err, __func__);
 
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+
+    pthread_attr_destroy(&attr);
 }
 
 void qemu_thread_get_self(QemuThread *thread)
@@ -148,3 +160,15 @@ void qemu_thread_exit(void *retval)
 {
     pthread_exit(retval);
 }
+
+void *qemu_thread_join(QemuThread *thread)
+{
+    int err;
+    void *ret;
+
+    err = pthread_join(thread->thread, &ret);
+    if (err) {
+        error_exit(err, __func__);
+    }
+    return ret;
+}
commit cf218714791a78c91db34a4aa9e33348923ad659
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Dec 12 17:21:31 2011 +0100

    qemu-thread: add API for joinable threads
    
    Split from Jan's original qemu-thread-posix.c patch.  No semantic change,
    just introduce the new API that POSIX and Win32 implementations will
    conform to.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/cpus.c b/cpus.c
index 7b9f8eb..1ada0f5 100644
--- a/cpus.c
+++ b/cpus.c
@@ -910,7 +910,8 @@ static void qemu_tcg_init_vcpu(void *_env)
         env->halt_cond = g_malloc0(sizeof(QemuCond));
         qemu_cond_init(env->halt_cond);
         tcg_halt_cond = env->halt_cond;
-        qemu_thread_create(env->thread, qemu_tcg_cpu_thread_fn, env);
+        qemu_thread_create(env->thread, qemu_tcg_cpu_thread_fn, env,
+                           QEMU_THREAD_DETACHED);
         while (env->created == 0) {
             qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
         }
@@ -926,7 +927,8 @@ static void qemu_kvm_start_vcpu(CPUState *env)
     env->thread = g_malloc0(sizeof(QemuThread));
     env->halt_cond = g_malloc0(sizeof(QemuCond));
     qemu_cond_init(env->halt_cond);
-    qemu_thread_create(env->thread, qemu_kvm_cpu_thread_fn, env);
+    qemu_thread_create(env->thread, qemu_kvm_cpu_thread_fn, env,
+                       QEMU_THREAD_DETACHED);
     while (env->created == 0) {
         qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
     }
diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c
index 092301b..9fe9db5 100644
--- a/hw/ccid-card-emulated.c
+++ b/hw/ccid-card-emulated.c
@@ -541,8 +541,9 @@ static int emulated_initfn(CCIDCardState *base)
         printf("%s: failed to initialize vcard\n", EMULATED_DEV_NAME);
         return -1;
     }
-    qemu_thread_create(&thread_id, event_thread, card);
-    qemu_thread_create(&thread_id, handle_apdu_thread, card);
+    qemu_thread_create(&thread_id, event_thread, card, QEMU_THREAD_DETACHED);
+    qemu_thread_create(&thread_id, handle_apdu_thread, card,
+                       QEMU_THREAD_DETACHED);
     return 0;
 }
 
diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
index ac3c0c9..49d3388 100644
--- a/qemu-thread-posix.c
+++ b/qemu-thread-posix.c
@@ -117,13 +117,14 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
 
 void qemu_thread_create(QemuThread *thread,
                        void *(*start_routine)(void*),
-                       void *arg)
+                       void *arg, int mode)
 {
+    sigset_t set, oldset;
     int err;
 
-    /* Leave signal handling to the iothread.  */
-    sigset_t set, oldset;
+    assert(mode == QEMU_THREAD_DETACHED);
 
+    /* Leave signal handling to the iothread.  */
     sigfillset(&set);
     pthread_sigmask(SIG_SETMASK, &set, &oldset);
     err = pthread_create(&thread->thread, NULL, start_routine, arg);
diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c
index db8e744..ff80e84 100644
--- a/qemu-thread-win32.c
+++ b/qemu-thread-win32.c
@@ -243,10 +243,12 @@ static inline void qemu_thread_init(void)
 
 void qemu_thread_create(QemuThread *thread,
                        void *(*start_routine)(void *),
-                       void *arg)
+                       void *arg, int mode)
 {
     HANDLE hThread;
 
+    assert(mode == QEMU_THREAD_DETACHED);
+
     struct QemuThreadData *data;
     qemu_thread_init();
     data = g_malloc(sizeof *data);
diff --git a/qemu-thread.h b/qemu-thread.h
index e008b60..a78a8f2 100644
--- a/qemu-thread.h
+++ b/qemu-thread.h
@@ -13,6 +13,9 @@ typedef struct QemuThread QemuThread;
 #include "qemu-thread-posix.h"
 #endif
 
+#define QEMU_THREAD_JOINABLE 0
+#define QEMU_THREAD_DETACHED 1
+
 void qemu_mutex_init(QemuMutex *mutex);
 void qemu_mutex_destroy(QemuMutex *mutex);
 void qemu_mutex_lock(QemuMutex *mutex);
@@ -35,8 +38,9 @@ void qemu_cond_broadcast(QemuCond *cond);
 void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex);
 
 void qemu_thread_create(QemuThread *thread,
-                       void *(*start_routine)(void*),
-                       void *arg);
+                        void *(*start_routine)(void *),
+                        void *arg, int mode);
+void *qemu_thread_join(QemuThread *thread);
 void qemu_thread_get_self(QemuThread *thread);
 int qemu_thread_is_self(QemuThread *thread);
 void qemu_thread_exit(void *retval);
diff --git a/ui/vnc-jobs-async.c b/ui/vnc-jobs-async.c
index de5ea6b..9b3016c 100644
--- a/ui/vnc-jobs-async.c
+++ b/ui/vnc-jobs-async.c
@@ -318,7 +318,7 @@ void vnc_start_worker_thread(void)
         return ;
 
     q = vnc_queue_init();
-    qemu_thread_create(&q->thread, vnc_worker_thread, q);
+    qemu_thread_create(&q->thread, vnc_worker_thread, q, QEMU_THREAD_DETACHED);
     queue = q; /* Set global queue */
 }
 
commit d396a657baec8c6b7aa0c888746e0e2f78303650
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Dec 12 12:11:41 2011 +0000

    syborg: drop support for Symbian Virtual Platform
    
    The Symbian Virtual Platform was an ARM-based development and debugging
    board.  Since Symbian has been disbanded and the code is no longer being
    used it can now be removed.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile.target b/Makefile.target
index 39b2e5a..3df3057 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -362,9 +362,6 @@ obj-arm-y += mst_fpga.o mainstone.o
 obj-arm-y += z2.o
 obj-arm-y += musicpal.o bitbang_i2c.o marvell_88w8618_audio.o
 obj-arm-y += framebuffer.o
-obj-arm-y += syborg.o syborg_fb.o syborg_interrupt.o syborg_keyboard.o
-obj-arm-y += syborg_serial.o syborg_timer.o syborg_pointer.o syborg_rtc.o
-obj-arm-y += syborg_virtio.o
 obj-arm-y += vexpress.o
 obj-arm-y += strongarm.o
 obj-arm-y += collie.o
diff --git a/hw/syborg.c b/hw/syborg.c
deleted file mode 100644
index 248de54..0000000
--- a/hw/syborg.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Syborg (Symbian Virtual Platform) reference board
- *
- * Copyright (c) 2009 CodeSourcery
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "boards.h"
-#include "arm-misc.h"
-#include "net.h"
-#include "exec-memory.h"
-
-static struct arm_boot_info syborg_binfo;
-
-static void syborg_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;
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    qemu_irq *cpu_pic;
-    qemu_irq pic[64];
-    DeviceState *dev;
-    int i;
-
-    if (!cpu_model)
-        cpu_model = "cortex-a8";
-    env = cpu_init(cpu_model);
-    if (!env) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-
-    /* RAM at address zero. */
-    memory_region_init_ram(ram, NULL, "syborg.ram", ram_size);
-    memory_region_add_subregion(sysmem, 0, ram);
-
-    cpu_pic = arm_pic_init_cpu(env);
-    dev = sysbus_create_simple("syborg,interrupt", 0xC0000000,
-                               cpu_pic[ARM_PIC_CPU_IRQ]);
-    for (i = 0; i < 64; i++) {
-        pic[i] = qdev_get_gpio_in(dev, i);
-    }
-
-    sysbus_create_simple("syborg,rtc", 0xC0001000, NULL);
-
-    dev = qdev_create(NULL, "syborg,timer");
-    qdev_prop_set_uint32(dev, "frequency", 1000000);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xC0002000);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[1]);
-
-    sysbus_create_simple("syborg,keyboard", 0xC0003000, pic[2]);
-    sysbus_create_simple("syborg,pointer", 0xC0004000, pic[3]);
-    sysbus_create_simple("syborg,framebuffer", 0xC0005000, pic[4]);
-    sysbus_create_simple("syborg,serial", 0xC0006000, pic[5]);
-    sysbus_create_simple("syborg,serial", 0xC0007000, pic[6]);
-    sysbus_create_simple("syborg,serial", 0xC0008000, pic[7]);
-    sysbus_create_simple("syborg,serial", 0xC0009000, pic[8]);
-
-    if (nd_table[0].vlan || nd_table[0].netdev) {
-        DeviceState *dev;
-        SysBusDevice *s;
-
-        qemu_check_nic_model(&nd_table[0], "virtio");
-        dev = qdev_create(NULL, "syborg,virtio-net");
-        qdev_set_nic_properties(dev, &nd_table[0]);
-        qdev_init_nofail(dev);
-        s = sysbus_from_qdev(dev);
-        sysbus_mmio_map(s, 0, 0xc000c000);
-        sysbus_connect_irq(s, 0, pic[9]);
-    }
-
-    syborg_binfo.ram_size = ram_size;
-    syborg_binfo.kernel_filename = kernel_filename;
-    syborg_binfo.kernel_cmdline = kernel_cmdline;
-    syborg_binfo.initrd_filename = initrd_filename;
-    syborg_binfo.board_id = 0;
-    arm_load_kernel(env, &syborg_binfo);
-}
-
-static QEMUMachine syborg_machine = {
-    .name = "syborg",
-    .desc = "Syborg (Symbian Virtual Platform)",
-    .init = syborg_init,
-};
-
-static void syborg_machine_init(void)
-{
-    qemu_register_machine(&syborg_machine);
-}
-
-machine_init(syborg_machine_init);
diff --git a/hw/syborg.h b/hw/syborg.h
deleted file mode 100644
index b82ce4a..0000000
--- a/hw/syborg.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _SYBORG_H
-#define _SYBORG_H
-
-#define SYBORG_ID_PLATFORM    0xc51d1000
-#define SYBORG_ID_INT         0xc51d0000
-#define SYBORG_ID_SERIAL      0xc51d0001
-#define SYBORG_ID_KEYBOARD    0xc51d0002
-#define SYBORG_ID_TIMER       0xc51d0003
-#define SYBORG_ID_RTC         0xc51d0004
-#define SYBORG_ID_MOUSE       0xc51d0005
-#define SYBORG_ID_TOUCHSCREEN 0xc51d0006
-#define SYBORG_ID_FRAMEBUFFER 0xc51d0007
-#define SYBORG_ID_HOSTFS      0xc51d0008
-#define SYBORG_ID_SNAPSHOT    0xc51d0009
-#define SYBORG_ID_VIRTIO      0xc51d000a
-#define SYBORG_ID_NAND        0xc51d000b
-
-#endif
diff --git a/hw/syborg_fb.c b/hw/syborg_fb.c
deleted file mode 100644
index b87d7e6..0000000
--- a/hw/syborg_fb.c
+++ /dev/null
@@ -1,554 +0,0 @@
-/*
- * Syborg Framebuffer
- *
- * Copyright (c) 2009 CodeSourcery
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "console.h"
-#include "syborg.h"
-#include "framebuffer.h"
-
-//#define DEBUG_SYBORG_FB
-
-#ifdef DEBUG_SYBORG_FB
-#define DPRINTF(fmt, ...) \
-do { printf("syborg_fb: " fmt , ## __VA_ARGS__); } while (0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_fb: error: " fmt , ## __VA_ARGS__); \
-    exit(1);} while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_fb: error: " fmt , ## __VA_ARGS__);} while (0)
-#endif
-
-enum {
-    FB_ID               = 0,
-    FB_BASE             = 1,
-    FB_HEIGHT           = 2,
-    FB_WIDTH            = 3,
-    FB_ORIENTATION      = 4,
-    FB_BLANK            = 5,
-    FB_INT_MASK         = 6,
-    FB_INTERRUPT_CAUSE  = 7,
-    FB_BPP              = 8,
-    FB_COLOR_ORDER      = 9,
-    FB_BYTE_ORDER       = 10,
-    FB_PIXEL_ORDER      = 11,
-    FB_ROW_PITCH        = 12,
-    FB_ENABLED          = 13,
-    FB_PALETTE_START    = 0x400 >> 2,
-    FB_PALETTE_END   = FB_PALETTE_START+256-1,
-};
-
-#define FB_INT_VSYNC            (1U << 0)
-#define FB_INT_BASE_UPDATE_DONE (1U << 1)
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    DisplayState *ds;
-    /*QEMUConsole *console;*/
-    uint32_t need_update : 1;
-    uint32_t need_int : 1;
-    uint32_t enabled : 1;
-    uint32_t int_status;
-    uint32_t int_enable;
-    qemu_irq irq;
-
-    uint32_t base;
-    uint32_t pitch;
-    uint32_t rows;
-    uint32_t cols;
-    int blank;
-    int bpp;
-    int rgb; /* 0 = BGR, 1 = RGB */
-    int endian; /* 0 = Little, 1 = Big */
-    uint32_t raw_palette[256];
-    uint32_t palette[256];
-} SyborgFBState;
-
-enum {
-    BPP_SRC_1,
-    BPP_SRC_2,
-    BPP_SRC_4,
-    BPP_SRC_8,
-    BPP_SRC_16,
-    BPP_SRC_32,
-    /* TODO: Implement these.  */
-    BPP_SRC_15 = -1,
-    BPP_SRC_24 = -2
-};
-
-#include "pixel_ops.h"
-
-#define BITS 8
-#include "pl110_template.h"
-#define BITS 15
-#include "pl110_template.h"
-#define BITS 16
-#include "pl110_template.h"
-#define BITS 24
-#include "pl110_template.h"
-#define BITS 32
-#include "pl110_template.h"
-
-/* Update interrupts.  */
-static void syborg_fb_update(SyborgFBState *s)
-{
-    if ((s->int_status & s->int_enable) != 0) {
-        DPRINTF("Raise IRQ\n");
-        qemu_irq_raise(s->irq);
-    } else {
-        DPRINTF("Lower IRQ\n");
-        qemu_irq_lower(s->irq);
-    }
-}
-
-static int syborg_fb_enabled(const SyborgFBState *s)
-{
-    return s->enabled;
-}
-
-static void syborg_fb_update_palette(SyborgFBState *s)
-{
-    int n, i;
-    uint32_t raw;
-    unsigned int r, g, b;
-
-    switch (s->bpp) {
-    case BPP_SRC_1: n = 2; break;
-    case BPP_SRC_2: n = 4; break;
-    case BPP_SRC_4: n = 16; break;
-    case BPP_SRC_8: n = 256; break;
-    default: return;
-    }
-
-    for (i = 0; i < n; i++) {
-        raw = s->raw_palette[i];
-        r = (raw >> 16) & 0xff;
-        g = (raw >> 8) & 0xff;
-        b = raw & 0xff;
-        switch (ds_get_bits_per_pixel(s->ds)) {
-        case 8:
-            s->palette[i] = rgb_to_pixel8(r, g, b);
-            break;
-        case 15:
-            s->palette[i] = rgb_to_pixel15(r, g, b);
-            break;
-        case 16:
-            s->palette[i] = rgb_to_pixel16(r, g, b);
-            break;
-        case 24:
-        case 32:
-            s->palette[i] = rgb_to_pixel32(r, g, b);
-            break;
-        default:
-            abort();
-        }
-    }
-
-}
-
-static void syborg_fb_update_display(void *opaque)
-{
-    SyborgFBState *s = (SyborgFBState *)opaque;
-    drawfn* fntable;
-    drawfn fn;
-    int dest_width;
-    int src_width;
-    int bpp_offset;
-    int first;
-    int last;
-
-    if (!syborg_fb_enabled(s))
-        return;
-
-    switch (ds_get_bits_per_pixel(s->ds)) {
-    case 0:
-        return;
-    case 8:
-        fntable = pl110_draw_fn_8;
-        dest_width = 1;
-        break;
-    case 15:
-        fntable = pl110_draw_fn_15;
-        dest_width = 2;
-        break;
-    case 16:
-        fntable = pl110_draw_fn_16;
-        dest_width = 2;
-        break;
-    case 24:
-        fntable = pl110_draw_fn_24;
-        dest_width = 3;
-        break;
-    case 32:
-        fntable = pl110_draw_fn_32;
-        dest_width = 4;
-        break;
-    default:
-        fprintf(stderr, "syborg_fb: Bad color depth\n");
-        exit(1);
-    }
-
-    if (s->need_int) {
-        s->int_status |= FB_INT_BASE_UPDATE_DONE;
-        syborg_fb_update(s);
-        s->need_int = 0;
-    }
-
-    if (s->rgb) {
-        bpp_offset = 24;
-    } else {
-        bpp_offset = 0;
-    }
-    if (s->endian) {
-        bpp_offset += 8;
-    }
-    /* Our bpp constants mostly match the PL110/PL111 but
-     * not for the 16 bit case
-     */
-    switch (s->bpp) {
-    case BPP_SRC_16:
-        bpp_offset += 6;
-        break;
-    default:
-        bpp_offset += s->bpp;
-    }
-    fn = fntable[bpp_offset];
-
-    if (s->pitch) {
-        src_width = s->pitch;
-    } else {
-        src_width = s->cols;
-        switch (s->bpp) {
-        case BPP_SRC_1:
-            src_width >>= 3;
-            break;
-        case BPP_SRC_2:
-            src_width >>= 2;
-            break;
-        case BPP_SRC_4:
-            src_width >>= 1;
-            break;
-        case BPP_SRC_8:
-            break;
-        case BPP_SRC_15:
-        case BPP_SRC_16:
-            src_width <<= 1;
-            break;
-        case BPP_SRC_24:
-            src_width *= 3;
-            break;
-        case BPP_SRC_32:
-            src_width <<= 2;
-            break;
-        }
-    }
-    dest_width *= s->cols;
-    first = 0;
-    /* TODO: Implement blanking.  */
-    if (!s->blank) {
-        if (s->need_update && s->bpp <= BPP_SRC_8) {
-            syborg_fb_update_palette(s);
-        }
-        framebuffer_update_display(s->ds,
-                                   s->base, s->cols, s->rows,
-                                   src_width, dest_width, 0,
-                                   s->need_update,
-                                   fn, s->palette,
-                                   &first, &last);
-        if (first >= 0) {
-            dpy_update(s->ds, 0, first, s->cols, last - first + 1);
-        }
-
-        s->int_status |= FB_INT_VSYNC;
-        syborg_fb_update(s);
-    }
-
-    s->need_update = 0;
-}
-
-static void syborg_fb_invalidate_display(void * opaque)
-{
-    SyborgFBState *s = (SyborgFBState *)opaque;
-    s->need_update = 1;
-}
-
-static uint64_t syborg_fb_read(void *opaque, target_phys_addr_t offset,
-                               unsigned size)
-{
-    SyborgFBState *s = opaque;
-
-    DPRINTF("read reg %d\n", (int)offset);
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case FB_ID:
-        return SYBORG_ID_FRAMEBUFFER;
-
-    case FB_BASE:
-        return s->base;
-
-    case FB_HEIGHT:
-        return s->rows;
-
-    case FB_WIDTH:
-        return s->cols;
-
-    case FB_ORIENTATION:
-        return 0;
-
-    case FB_BLANK:
-        return s->blank;
-
-    case FB_INT_MASK:
-        return s->int_enable;
-
-    case FB_INTERRUPT_CAUSE:
-        return s->int_status;
-
-    case FB_BPP:
-        switch (s->bpp) {
-        case BPP_SRC_1: return 1;
-        case BPP_SRC_2: return 2;
-        case BPP_SRC_4: return 4;
-        case BPP_SRC_8: return 8;
-        case BPP_SRC_15: return 15;
-        case BPP_SRC_16: return 16;
-        case BPP_SRC_24: return 24;
-        case BPP_SRC_32: return 32;
-        default: return 0;
-        }
-
-    case FB_COLOR_ORDER:
-        return s->rgb;
-
-    case FB_BYTE_ORDER:
-        return s->endian;
-
-    case FB_PIXEL_ORDER:
-        return 0;
-
-    case FB_ROW_PITCH:
-        return s->pitch;
-
-    case FB_ENABLED:
-        return s->enabled;
-
-    default:
-        if ((offset >> 2) >= FB_PALETTE_START
-            && (offset >> 2) <= FB_PALETTE_END) {
-            return s->raw_palette[(offset >> 2) - FB_PALETTE_START];
-        } else {
-            cpu_abort (cpu_single_env, "syborg_fb_read: Bad offset %x\n",
-                         (int)offset);
-        }
-        return 0;
-    }
-}
-
-static void syborg_fb_write(void *opaque, target_phys_addr_t offset,
-                            uint64_t val, unsigned size)
-{
-    SyborgFBState *s = opaque;
-
-    DPRINTF("write reg %d = %d\n", (int)offset, val);
-    s->need_update = 1;
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case FB_BASE:
-        s->base = val;
-        s->need_int = 1;
-        s->need_update = 1;
-        syborg_fb_update(s);
-        break;
-
-    case FB_HEIGHT:
-        s->rows = val;
-        break;
-
-    case FB_WIDTH:
-        s->cols = val;
-        break;
-
-    case FB_ORIENTATION:
-        /* TODO: Implement rotation.  */
-        break;
-
-    case FB_BLANK:
-        s->blank = val & 1;
-        break;
-
-    case FB_INT_MASK:
-        s->int_enable = val;
-        syborg_fb_update(s);
-        break;
-
-    case FB_INTERRUPT_CAUSE:
-        s->int_status &= ~val;
-        syborg_fb_update(s);
-        break;
-
-    case FB_BPP:
-        switch (val) {
-        case 1: val = BPP_SRC_1; break;
-        case 2: val = BPP_SRC_2; break;
-        case 4: val = BPP_SRC_4; break;
-        case 8: val = BPP_SRC_8; break;
-        /* case 15: val = BPP_SRC_15; break; */
-        case 16: val = BPP_SRC_16; break;
-        /* case 24: val = BPP_SRC_24; break; */
-        case 32: val = BPP_SRC_32; break;
-        default: val = s->bpp; break;
-        }
-        s->bpp = val;
-        break;
-
-    case FB_COLOR_ORDER:
-        s->rgb = (val != 0);
-        break;
-
-    case FB_BYTE_ORDER:
-        s->endian = (val != 0);
-        break;
-
-    case FB_PIXEL_ORDER:
-        /* TODO: Implement this.  */
-        break;
-
-    case FB_ROW_PITCH:
-        s->pitch = val;
-        break;
-
-    case FB_ENABLED:
-        s->enabled = val;
-        break;
-
-    default:
-        if ((offset >> 2) >= FB_PALETTE_START
-            && (offset >> 2) <= FB_PALETTE_END) {
-            s->raw_palette[(offset >> 2) - FB_PALETTE_START] = val;
-        } else {
-            cpu_abort (cpu_single_env, "syborg_fb_write: Bad offset %x\n",
-                      (int)offset);
-        }
-        break;
-    }
-}
-
-static const MemoryRegionOps syborg_fb_ops = {
-    .read = syborg_fb_read,
-    .write = syborg_fb_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void syborg_fb_save(QEMUFile *f, void *opaque)
-{
-    SyborgFBState *s = opaque;
-    int i;
-
-    qemu_put_be32(f, s->need_int);
-    qemu_put_be32(f, s->int_status);
-    qemu_put_be32(f, s->int_enable);
-    qemu_put_be32(f, s->enabled);
-    qemu_put_be32(f, s->base);
-    qemu_put_be32(f, s->pitch);
-    qemu_put_be32(f, s->rows);
-    qemu_put_be32(f, s->cols);
-    qemu_put_be32(f, s->bpp);
-    qemu_put_be32(f, s->rgb);
-    for (i = 0; i < 256; i++) {
-        qemu_put_be32(f, s->raw_palette[i]);
-    }
-}
-
-static int syborg_fb_load(QEMUFile *f, void *opaque, int version_id)
-{
-    SyborgFBState *s = opaque;
-    int i;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    s->need_int = qemu_get_be32(f);
-    s->int_status = qemu_get_be32(f);
-    s->int_enable = qemu_get_be32(f);
-    s->enabled = qemu_get_be32(f);
-    s->base = qemu_get_be32(f);
-    s->pitch = qemu_get_be32(f);
-    s->rows = qemu_get_be32(f);
-    s->cols = qemu_get_be32(f);
-    s->bpp = qemu_get_be32(f);
-    s->rgb = qemu_get_be32(f);
-    for (i = 0; i < 256; i++) {
-        s->raw_palette[i] = qemu_get_be32(f);
-    }
-    s->need_update = 1;
-
-    return 0;
-}
-
-static int syborg_fb_init(SysBusDevice *dev)
-{
-    SyborgFBState *s = FROM_SYSBUS(SyborgFBState, dev);
-
-    sysbus_init_irq(dev, &s->irq);
-    memory_region_init_io(&s->iomem, &syborg_fb_ops, s,
-                          "framebuffer", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    s->ds = graphic_console_init(syborg_fb_update_display,
-                                 syborg_fb_invalidate_display,
-                                 NULL, NULL, s);
-
-    if (s->cols != 0 && s->rows != 0) {
-        qemu_console_resize(s->ds, s->cols, s->rows);
-    }
-
-    if (!s->cols)
-        s->cols = ds_get_width(s->ds);
-    if (!s->rows)
-        s->rows = ds_get_height(s->ds);
-
-    register_savevm(&dev->qdev, "syborg_framebuffer", -1, 1,
-                    syborg_fb_save, syborg_fb_load, s);
-    return 0;
-}
-
-static SysBusDeviceInfo syborg_fb_info = {
-    .init = syborg_fb_init,
-    .qdev.name  = "syborg,framebuffer",
-    .qdev.size  = sizeof(SyborgFBState),
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("width",  SyborgFBState, cols, 0),
-        DEFINE_PROP_UINT32("height", SyborgFBState, rows, 0),
-        DEFINE_PROP_END_OF_LIST(),
-    }
-};
-
-static void syborg_fb_register_devices(void)
-{
-    sysbus_register_withprop(&syborg_fb_info);
-}
-
-device_init(syborg_fb_register_devices)
diff --git a/hw/syborg_interrupt.c b/hw/syborg_interrupt.c
deleted file mode 100644
index 93e81c8..0000000
--- a/hw/syborg_interrupt.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Syborg interrupt controller.
- *
- * Copyright (c) 2008 CodeSourcery
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "syborg.h"
-
-//#define DEBUG_SYBORG_INT
-
-#ifdef DEBUG_SYBORG_INT
-#define DPRINTF(fmt, ...) \
-do { printf("syborg_int: " fmt , ## __VA_ARGS__); } while (0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_int: error: " fmt , ## __VA_ARGS__); \
-    exit(1);} while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_int: error: " fmt , ## __VA_ARGS__);} while (0)
-#endif
-enum {
-    INT_ID            = 0,
-    INT_STATUS        = 1, /* number of pending interrupts */
-    INT_CURRENT       = 2, /* next interrupt to be serviced */
-    INT_DISABLE_ALL   = 3,
-    INT_DISABLE       = 4,
-    INT_ENABLE        = 5,
-    INT_TOTAL         = 6
-};
-
-typedef struct {
-    unsigned level:1;
-    unsigned enabled:1;
-} syborg_int_flags;
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    int pending_count;
-    uint32_t num_irqs;
-    syborg_int_flags *flags;
-    qemu_irq parent_irq;
-} SyborgIntState;
-
-static void syborg_int_update(SyborgIntState *s)
-{
-    DPRINTF("pending %d\n", s->pending_count);
-    qemu_set_irq(s->parent_irq, s->pending_count > 0);
-}
-
-static void syborg_int_set_irq(void *opaque, int irq, int level)
-{
-    SyborgIntState *s = (SyborgIntState *)opaque;
-
-    if (s->flags[irq].level == level)
-        return;
-
-    s->flags[irq].level = level;
-    if (s->flags[irq].enabled) {
-        if (level)
-            s->pending_count++;
-        else
-            s->pending_count--;
-        syborg_int_update(s);
-    }
-}
-
-static uint64_t syborg_int_read(void *opaque, target_phys_addr_t offset,
-                                unsigned size)
-{
-    SyborgIntState *s = (SyborgIntState *)opaque;
-    int i;
-
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case INT_ID:
-        return SYBORG_ID_INT;
-    case INT_STATUS:
-        DPRINTF("read status=%d\n", s->pending_count);
-        return s->pending_count;
-
-    case INT_CURRENT:
-        for (i = 0; i < s->num_irqs; i++) {
-            if (s->flags[i].level & s->flags[i].enabled) {
-                DPRINTF("read current=%d\n", i);
-                return i;
-            }
-        }
-        DPRINTF("read current=none\n");
-        return 0xffffffffu;
-
-    default:
-        cpu_abort(cpu_single_env, "syborg_int_read: Bad offset %x\n",
-                  (int)offset);
-        return 0;
-    }
-}
-
-static void syborg_int_write(void *opaque, target_phys_addr_t offset,
-                             uint64_t value, unsigned size)
-{
-    SyborgIntState *s = (SyborgIntState *)opaque;
-    int i;
-    offset &= 0xfff;
-
-    DPRINTF("syborg_int_write offset=%d val=%d\n", (int)offset, (int)value);
-    switch (offset >> 2) {
-    case INT_DISABLE_ALL:
-        s->pending_count = 0;
-        for (i = 0; i < s->num_irqs; i++)
-            s->flags[i].enabled = 0;
-        break;
-
-    case INT_DISABLE:
-        if (value >= s->num_irqs)
-            break;
-        if (s->flags[value].enabled) {
-            if (s->flags[value].enabled)
-                s->pending_count--;
-            s->flags[value].enabled = 0;
-        }
-        break;
-
-    case INT_ENABLE:
-      if (value >= s->num_irqs)
-          break;
-      if (!(s->flags[value].enabled)) {
-          if(s->flags[value].level)
-              s->pending_count++;
-          s->flags[value].enabled = 1;
-      }
-      break;
-
-    default:
-        cpu_abort(cpu_single_env, "syborg_int_write: Bad offset %x\n",
-                  (int)offset);
-        return;
-    }
-    syborg_int_update(s);
-}
-
-static const MemoryRegionOps syborg_int_ops = {
-    .read = syborg_int_read,
-    .write = syborg_int_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void syborg_int_save(QEMUFile *f, void *opaque)
-{
-    SyborgIntState *s = (SyborgIntState *)opaque;
-    int i;
-
-    qemu_put_be32(f, s->num_irqs);
-    qemu_put_be32(f, s->pending_count);
-    for (i = 0; i < s->num_irqs; i++) {
-        qemu_put_be32(f, s->flags[i].enabled
-                         | ((unsigned)s->flags[i].level << 1));
-    }
-}
-
-static int syborg_int_load(QEMUFile *f, void *opaque, int version_id)
-{
-    SyborgIntState *s = (SyborgIntState *)opaque;
-    uint32_t val;
-    int i;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    val = qemu_get_be32(f);
-    if (val != s->num_irqs)
-        return -EINVAL;
-    s->pending_count = qemu_get_be32(f);
-    for (i = 0; i < s->num_irqs; i++) {
-        val = qemu_get_be32(f);
-        s->flags[i].enabled = val & 1;
-        s->flags[i].level = (val >> 1) & 1;
-    }
-    return 0;
-}
-
-static int syborg_int_init(SysBusDevice *dev)
-{
-    SyborgIntState *s = FROM_SYSBUS(SyborgIntState, dev);
-
-    sysbus_init_irq(dev, &s->parent_irq);
-    qdev_init_gpio_in(&dev->qdev, syborg_int_set_irq, s->num_irqs);
-    memory_region_init_io(&s->iomem, &syborg_int_ops, s,
-                          "interrupt", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    s->flags = g_malloc0(s->num_irqs * sizeof(syborg_int_flags));
-
-    register_savevm(&dev->qdev, "syborg_int", -1, 1, syborg_int_save,
-                    syborg_int_load, s);
-    return 0;
-}
-
-static SysBusDeviceInfo syborg_int_info = {
-    .init = syborg_int_init,
-    .qdev.name  = "syborg,interrupt",
-    .qdev.size  = sizeof(SyborgIntState),
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("num-interrupts", SyborgIntState, num_irqs, 64),
-        DEFINE_PROP_END_OF_LIST(),
-    }
-};
-
-static void syborg_interrupt_register_devices(void)
-{
-    sysbus_register_withprop(&syborg_int_info);
-}
-
-device_init(syborg_interrupt_register_devices)
diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c
deleted file mode 100644
index 942a7dc..0000000
--- a/hw/syborg_keyboard.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Syborg keyboard controller.
- *
- * Copyright (c) 2008 CodeSourcery
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "console.h"
-#include "syborg.h"
-
-//#define DEBUG_SYBORG_KEYBOARD
-
-#ifdef DEBUG_SYBORG_KEYBOARD
-#define DPRINTF(fmt, ...) \
-do { printf("syborg_keyboard: " fmt , ##args); } while (0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_keyboard: error: " fmt , ## __VA_ARGS__); \
-    exit(1);} while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_keyboard: error: " fmt , ## __VA_ARGS__); \
-} while (0)
-#endif
-
-enum {
-    KBD_ID          = 0,
-    KBD_DATA        = 1,
-    KBD_FIFO_COUNT  = 2,
-    KBD_INT_ENABLE  = 3,
-    KBD_FIFO_SIZE   = 4
-};
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t int_enabled;
-    int extension_bit;
-    uint32_t fifo_size;
-    uint32_t *key_fifo;
-    uint32_t read_pos, read_count;
-    qemu_irq irq;
-} SyborgKeyboardState;
-
-static void syborg_keyboard_update(SyborgKeyboardState *s)
-{
-    int level = s->read_count && s->int_enabled;
-    DPRINTF("Update IRQ %d\n", level);
-    qemu_set_irq(s->irq, level);
-}
-
-static uint64_t syborg_keyboard_read(void *opaque, target_phys_addr_t offset,
-                                    unsigned size)
-{
-    SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
-    int c;
-
-    DPRINTF("reg read %d\n", (int)offset);
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case KBD_ID:
-        return SYBORG_ID_KEYBOARD;
-    case KBD_FIFO_COUNT:
-        return s->read_count;
-    case KBD_DATA:
-        if (s->read_count == 0) {
-            c = -1;
-            DPRINTF("FIFO underflow\n");
-        } else {
-            c = s->key_fifo[s->read_pos];
-            DPRINTF("FIFO read 0x%x\n", c);
-            s->read_count--;
-            s->read_pos++;
-            if (s->read_pos == s->fifo_size)
-                s->read_pos = 0;
-        }
-        syborg_keyboard_update(s);
-        return c;
-    case KBD_INT_ENABLE:
-        return s->int_enabled;
-    case KBD_FIFO_SIZE:
-        return s->fifo_size;
-    default:
-        cpu_abort(cpu_single_env, "syborg_keyboard_read: Bad offset %x\n",
-                  (int)offset);
-        return 0;
-    }
-}
-
-static void syborg_keyboard_write(void *opaque, target_phys_addr_t offset,
-                                  uint64_t value, unsigned size)
-{
-    SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
-
-    DPRINTF("reg write %d\n", (int)offset);
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case KBD_INT_ENABLE:
-        s->int_enabled = value;
-        syborg_keyboard_update(s);
-        break;
-    default:
-        cpu_abort(cpu_single_env, "syborg_keyboard_write: Bad offset %x\n",
-                  (int)offset);
-    }
-}
-
-static const MemoryRegionOps syborg_keyboard_ops = {
-    .read = syborg_keyboard_read,
-    .write = syborg_keyboard_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void syborg_keyboard_event(void *opaque, int keycode)
-{
-    SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
-    int slot;
-    uint32_t val;
-
-    /* Strip off 0xe0 prefixes and reconstruct the full scancode.  */
-    if (keycode == 0xe0 && !s->extension_bit) {
-        DPRINTF("Extension bit\n");
-        s->extension_bit = 0x80;
-        return;
-    }
-    val = (keycode & 0x7f) | s->extension_bit;
-    if (keycode & 0x80)
-        val |= 0x80000000u;
-    s->extension_bit = 0;
-
-    DPRINTF("FIFO push 0x%x\n", val);
-    slot = s->read_pos + s->read_count;
-    if (slot >= s->fifo_size)
-        slot -= s->fifo_size;
-
-    if (s->read_count < s->fifo_size) {
-        s->read_count++;
-        s->key_fifo[slot] = val;
-    } else {
-        fprintf(stderr, "syborg_keyboard error! FIFO overflow\n");
-    }
-
-    syborg_keyboard_update(s);
-}
-
-static const VMStateDescription vmstate_syborg_keyboard = {
-    .name = "syborg_keyboard",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32_EQUAL(fifo_size, SyborgKeyboardState),
-        VMSTATE_UINT32(int_enabled, SyborgKeyboardState),
-        VMSTATE_UINT32(read_pos, SyborgKeyboardState),
-        VMSTATE_UINT32(read_count, SyborgKeyboardState),
-        VMSTATE_VARRAY_UINT32(key_fifo, SyborgKeyboardState, fifo_size, 1,
-                              vmstate_info_uint32, uint32),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int syborg_keyboard_init(SysBusDevice *dev)
-{
-    SyborgKeyboardState *s = FROM_SYSBUS(SyborgKeyboardState, dev);
-
-    sysbus_init_irq(dev, &s->irq);
-    memory_region_init_io(&s->iomem, &syborg_keyboard_ops, s,
-                              "keyboard", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    if (s->fifo_size <= 0) {
-        fprintf(stderr, "syborg_keyboard: fifo too small\n");
-        s->fifo_size = 16;
-    }
-    s->key_fifo = g_malloc0(s->fifo_size * sizeof(s->key_fifo[0]));
-
-    qemu_add_kbd_event_handler(syborg_keyboard_event, s);
-
-    vmstate_register(&dev->qdev, -1, &vmstate_syborg_keyboard, s);
-    return 0;
-}
-
-static SysBusDeviceInfo syborg_keyboard_info = {
-    .init = syborg_keyboard_init,
-    .qdev.name  = "syborg,keyboard",
-    .qdev.size  = sizeof(SyborgKeyboardState),
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("fifo-size", SyborgKeyboardState, fifo_size, 16),
-        DEFINE_PROP_END_OF_LIST(),
-    }
-};
-
-static void syborg_keyboard_register_devices(void)
-{
-    sysbus_register_withprop(&syborg_keyboard_info);
-}
-
-device_init(syborg_keyboard_register_devices)
diff --git a/hw/syborg_pointer.c b/hw/syborg_pointer.c
deleted file mode 100644
index bb75fa4..0000000
--- a/hw/syborg_pointer.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Syborg pointing device (mouse/touchscreen)
- *
- * Copyright (c) 2008 CodeSourcery
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "console.h"
-#include "syborg.h"
-
-enum {
-    POINTER_ID          = 0,
-    POINTER_LATCH       = 1,
-    POINTER_FIFO_COUNT  = 2,
-    POINTER_X           = 3,
-    POINTER_Y           = 4,
-    POINTER_Z           = 5,
-    POINTER_BUTTONS     = 6,
-    POINTER_INT_ENABLE  = 7,
-    POINTER_FIFO_SIZE   = 8
-};
-
-typedef struct {
-    int x, y, z, pointer_buttons;
-} event_data;
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    int int_enabled;
-    uint32_t fifo_size;
-    event_data *event_fifo;
-    int read_pos, read_count;
-    qemu_irq irq;
-    uint32_t absolute;
-} SyborgPointerState;
-
-static void syborg_pointer_update(SyborgPointerState *s)
-{
-    qemu_set_irq(s->irq, s->read_count && s->int_enabled);
-}
-
-static uint64_t syborg_pointer_read(void *opaque, target_phys_addr_t offset,
-                                    unsigned size)
-{
-    SyborgPointerState *s = (SyborgPointerState *)opaque;
-
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case POINTER_ID:
-        return s->absolute ? SYBORG_ID_TOUCHSCREEN : SYBORG_ID_MOUSE;
-    case POINTER_FIFO_COUNT:
-        return s->read_count;
-    case POINTER_X:
-        return s->event_fifo[s->read_pos].x;
-    case POINTER_Y:
-        return s->event_fifo[s->read_pos].y;
-    case POINTER_Z:
-        return s->event_fifo[s->read_pos].z;
-    case POINTER_BUTTONS:
-        return s->event_fifo[s->read_pos].pointer_buttons;
-    case POINTER_INT_ENABLE:
-        return s->int_enabled;
-    case POINTER_FIFO_SIZE:
-        return s->fifo_size;
-    default:
-        cpu_abort(cpu_single_env, "syborg_pointer_read: Bad offset %x\n",
-                  (int)offset);
-        return 0;
-    }
-}
-
-static void syborg_pointer_write(void *opaque, target_phys_addr_t offset,
-                                 uint64_t value, unsigned size)
-{
-    SyborgPointerState *s = (SyborgPointerState *)opaque;
-
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case POINTER_LATCH:
-        if (s->read_count > 0) {
-            s->read_count--;
-            if (++s->read_pos == s->fifo_size)
-                s->read_pos = 0;
-        }
-        break;
-    case POINTER_INT_ENABLE:
-        s->int_enabled = value;
-        break;
-    default:
-        cpu_abort(cpu_single_env, "syborg_pointer_write: Bad offset %x\n",
-                  (int)offset);
-    }
-    syborg_pointer_update(s);
-}
-
-static const MemoryRegionOps syborg_pointer_ops = {
-    .read = syborg_pointer_read,
-    .write = syborg_pointer_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void syborg_pointer_event(void *opaque, int dx, int dy, int dz,
-                                 int buttons_state)
-{
-    SyborgPointerState *s = (SyborgPointerState *)opaque;
-    int slot = s->read_pos + s->read_count;
-
-    /* This first FIFO entry is used to store current register state.  */
-    if (s->read_count < s->fifo_size - 1) {
-        s->read_count++;
-        slot++;
-    }
-
-    if (slot >= s->fifo_size)
-          slot -= s->fifo_size;
-
-    if (s->read_count == s->fifo_size && !s->absolute) {
-        /* Merge existing entries.  */
-        s->event_fifo[slot].x += dx;
-        s->event_fifo[slot].y += dy;
-        s->event_fifo[slot].z += dz;
-    } else {
-        s->event_fifo[slot].x = dx;
-        s->event_fifo[slot].y = dy;
-        s->event_fifo[slot].z = dz;
-    }
-    s->event_fifo[slot].pointer_buttons = buttons_state;
-
-    syborg_pointer_update(s);
-}
-
-static const VMStateDescription vmstate_event_data = {
-    .name = "dbma_channel",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .fields      = (VMStateField[]) {
-        VMSTATE_INT32(x, event_data),
-        VMSTATE_INT32(y, event_data),
-        VMSTATE_INT32(z, event_data),
-        VMSTATE_INT32(pointer_buttons, event_data),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription vmstate_syborg_pointer = {
-    .name = "syborg_pointer",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32_EQUAL(fifo_size, SyborgPointerState),
-        VMSTATE_UINT32_EQUAL(absolute, SyborgPointerState),
-        VMSTATE_INT32(int_enabled, SyborgPointerState),
-        VMSTATE_INT32(read_pos, SyborgPointerState),
-        VMSTATE_INT32(read_count, SyborgPointerState),
-        VMSTATE_STRUCT_VARRAY_UINT32(event_fifo, SyborgPointerState, fifo_size,
-                                     1, vmstate_event_data, event_data),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int syborg_pointer_init(SysBusDevice *dev)
-{
-    SyborgPointerState *s = FROM_SYSBUS(SyborgPointerState, dev);
-
-    sysbus_init_irq(dev, &s->irq);
-    memory_region_init_io(&s->iomem, &syborg_pointer_ops, s,
-                          "pointer", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    if (s->fifo_size <= 0) {
-        fprintf(stderr, "syborg_pointer: fifo too small\n");
-        s->fifo_size = 16;
-    }
-    s->event_fifo = g_malloc0(s->fifo_size * sizeof(s->event_fifo[0]));
-
-    qemu_add_mouse_event_handler(syborg_pointer_event, s, s->absolute,
-                                 "Syborg Pointer");
-
-    vmstate_register(&dev->qdev, -1, &vmstate_syborg_pointer, s);
-    return 0;
-}
-
-static SysBusDeviceInfo syborg_pointer_info = {
-    .init = syborg_pointer_init,
-    .qdev.name  = "syborg,pointer",
-    .qdev.size  = sizeof(SyborgPointerState),
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("fifo-size", SyborgPointerState, fifo_size, 16),
-        DEFINE_PROP_UINT32("absolute",  SyborgPointerState, absolute,   1),
-        DEFINE_PROP_END_OF_LIST(),
-    }
-};
-
-static void syborg_pointer_register_devices(void)
-{
-    sysbus_register_withprop(&syborg_pointer_info);
-}
-
-device_init(syborg_pointer_register_devices)
diff --git a/hw/syborg_rtc.c b/hw/syborg_rtc.c
deleted file mode 100644
index b5f3479..0000000
--- a/hw/syborg_rtc.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Syborg RTC
- *
- * Copyright (c) 2008 CodeSourcery
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "qemu-timer.h"
-#include "syborg.h"
-
-enum {
-    RTC_ID        = 0,
-    RTC_LATCH     = 1,
-    RTC_DATA_LOW  = 2,
-    RTC_DATA_HIGH = 3
-};
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    int64_t offset;
-    int64_t data;
-    qemu_irq irq;
-} SyborgRTCState;
-
-static uint64_t syborg_rtc_read(void *opaque, target_phys_addr_t offset,
-                                unsigned size)
-{
-    SyborgRTCState *s = (SyborgRTCState *)opaque;
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case RTC_ID:
-        return SYBORG_ID_RTC;
-    case RTC_DATA_LOW:
-        return (uint32_t)s->data;
-    case RTC_DATA_HIGH:
-        return (uint32_t)(s->data >> 32);
-    default:
-        cpu_abort(cpu_single_env, "syborg_rtc_read: Bad offset %x\n",
-                  (int)offset);
-        return 0;
-    }
-}
-
-static void syborg_rtc_write(void *opaque, target_phys_addr_t offset,
-                             uint64_t value, unsigned size)
-{
-    SyborgRTCState *s = (SyborgRTCState *)opaque;
-    uint64_t now;
-
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case RTC_LATCH:
-        now = qemu_get_clock_ns(vm_clock);
-        if (value >= 4) {
-            s->offset = s->data - now;
-        } else {
-            s->data = now + s->offset;
-            while (value) {
-                s->data /= 1000;
-                value--;
-            }
-        }
-        break;
-    case RTC_DATA_LOW:
-        s->data = (s->data & ~(uint64_t)0xffffffffu) | value;
-        break;
-    case RTC_DATA_HIGH:
-        s->data = (s->data & 0xffffffffu) | ((uint64_t)value << 32);
-        break;
-    default:
-        cpu_abort(cpu_single_env, "syborg_rtc_write: Bad offset %x\n",
-                  (int)offset);
-        break;
-    }
-}
-
-static const MemoryRegionOps syborg_rtc_ops = {
-    .read = syborg_rtc_read,
-    .write = syborg_rtc_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_syborg_rtc = {
-    .name = "syborg_keyboard",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_INT64(offset, SyborgRTCState),
-        VMSTATE_INT64(data, SyborgRTCState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int syborg_rtc_init(SysBusDevice *dev)
-{
-    SyborgRTCState *s = FROM_SYSBUS(SyborgRTCState, dev);
-    struct tm tm;
-
-    memory_region_init_io(&s->iomem, &syborg_rtc_ops, s, "rtc", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    qemu_get_timedate(&tm, 0);
-    s->offset = (uint64_t)mktime(&tm) * 1000000000;
-
-    vmstate_register(&dev->qdev, -1, &vmstate_syborg_rtc, s);
-    return 0;
-}
-
-static void syborg_rtc_register_devices(void)
-{
-    sysbus_register_dev("syborg,rtc", sizeof(SyborgRTCState), syborg_rtc_init);
-}
-
-device_init(syborg_rtc_register_devices)
diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
deleted file mode 100644
index 6f339fa..0000000
--- a/hw/syborg_serial.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Syborg serial port
- *
- * Copyright (c) 2008 CodeSourcery
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "qemu-char.h"
-#include "syborg.h"
-
-//#define DEBUG_SYBORG_SERIAL
-
-#ifdef DEBUG_SYBORG_SERIAL
-#define DPRINTF(fmt, ...) \
-do { printf("syborg_serial: " fmt , ##args); } while (0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_serial: error: " fmt , ## __VA_ARGS__); \
-    exit(1);} while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_serial: error: " fmt , ## __VA_ARGS__);} while (0)
-#endif
-
-enum {
-    SERIAL_ID           = 0,
-    SERIAL_DATA         = 1,
-    SERIAL_FIFO_COUNT   = 2,
-    SERIAL_INT_ENABLE   = 3,
-    SERIAL_DMA_TX_ADDR  = 4,
-    SERIAL_DMA_TX_COUNT = 5, /* triggers dma */
-    SERIAL_DMA_RX_ADDR  = 6,
-    SERIAL_DMA_RX_COUNT = 7, /* triggers dma */
-    SERIAL_FIFO_SIZE    = 8
-};
-
-#define SERIAL_INT_FIFO   (1u << 0)
-#define SERIAL_INT_DMA_TX (1u << 1)
-#define SERIAL_INT_DMA_RX (1u << 2)
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t int_enable;
-    uint32_t fifo_size;
-    uint32_t *read_fifo;
-    int read_pos;
-    int read_count;
-    CharDriverState *chr;
-    qemu_irq irq;
-    uint32_t dma_tx_ptr;
-    uint32_t dma_rx_ptr;
-    uint32_t dma_rx_size;
-} SyborgSerialState;
-
-static void syborg_serial_update(SyborgSerialState *s)
-{
-    int level;
-    level = 0;
-    if ((s->int_enable & SERIAL_INT_FIFO) && s->read_count)
-        level = 1;
-    if (s->int_enable & SERIAL_INT_DMA_TX)
-        level = 1;
-    if ((s->int_enable & SERIAL_INT_DMA_RX) && s->dma_rx_size == 0)
-        level = 1;
-
-    qemu_set_irq(s->irq, level);
-}
-
-static uint32_t fifo_pop(SyborgSerialState *s)
-{
-    const uint32_t c = s->read_fifo[s->read_pos];
-    s->read_count--;
-    s->read_pos++;
-    if (s->read_pos == s->fifo_size)
-        s->read_pos = 0;
-
-    DPRINTF("FIFO pop %x (%d)\n", c, s->read_count);
-    return c;
-}
-
-static void fifo_push(SyborgSerialState *s, uint32_t new_value)
-{
-    int slot;
-
-    DPRINTF("FIFO push %x (%d)\n", new_value, s->read_count);
-    slot = s->read_pos + s->read_count;
-    if (slot >= s->fifo_size)
-          slot -= s->fifo_size;
-    s->read_fifo[slot] = new_value;
-    s->read_count++;
-}
-
-static void do_dma_tx(SyborgSerialState *s, uint32_t count)
-{
-    unsigned char ch;
-
-    if (count == 0)
-        return;
-
-    if (s->chr != NULL) {
-        /* optimize later. Now, 1 byte per iteration */
-        while (count--) {
-            cpu_physical_memory_read(s->dma_tx_ptr, &ch, 1);
-            qemu_chr_fe_write(s->chr, &ch, 1);
-            s->dma_tx_ptr++;
-        }
-    } else {
-        s->dma_tx_ptr += count;
-    }
-    /* QEMU char backends do not have a nonblocking mode, so we transmit all
-       the data immediately and the interrupt status will be unchanged.  */
-}
-
-/* Initiate RX DMA, and transfer data from the FIFO.  */
-static void dma_rx_start(SyborgSerialState *s, uint32_t len)
-{
-    uint32_t dest;
-    unsigned char ch;
-
-    dest = s->dma_rx_ptr;
-    if (s->read_count < len) {
-        s->dma_rx_size = len - s->read_count;
-        len = s->read_count;
-    } else {
-        s->dma_rx_size = 0;
-    }
-
-    while (len--) {
-        ch = fifo_pop(s);
-        cpu_physical_memory_write(dest, &ch, 1);
-        dest++;
-    }
-    s->dma_rx_ptr = dest;
-    syborg_serial_update(s);
-}
-
-static uint64_t syborg_serial_read(void *opaque, target_phys_addr_t offset,
-                                   unsigned size)
-{
-    SyborgSerialState *s = (SyborgSerialState *)opaque;
-    uint32_t c;
-
-    offset &= 0xfff;
-    DPRINTF("read 0x%x\n", (int)offset);
-    switch(offset >> 2) {
-    case SERIAL_ID:
-        return SYBORG_ID_SERIAL;
-    case SERIAL_DATA:
-        if (s->read_count > 0)
-            c = fifo_pop(s);
-        else
-            c = -1;
-        syborg_serial_update(s);
-        return c;
-    case SERIAL_FIFO_COUNT:
-        return s->read_count;
-    case SERIAL_INT_ENABLE:
-        return s->int_enable;
-    case SERIAL_DMA_TX_ADDR:
-        return s->dma_tx_ptr;
-    case SERIAL_DMA_TX_COUNT:
-        return 0;
-    case SERIAL_DMA_RX_ADDR:
-        return s->dma_rx_ptr;
-    case SERIAL_DMA_RX_COUNT:
-        return s->dma_rx_size;
-    case SERIAL_FIFO_SIZE:
-        return s->fifo_size;
-
-    default:
-        cpu_abort(cpu_single_env, "syborg_serial_read: Bad offset %x\n",
-                  (int)offset);
-        return 0;
-    }
-}
-
-static void syborg_serial_write(void *opaque, target_phys_addr_t offset,
-                                uint64_t value, unsigned size)
-{
-    SyborgSerialState *s = (SyborgSerialState *)opaque;
-    unsigned char ch;
-
-    offset &= 0xfff;
-    DPRINTF("Write 0x%x=0x%x\n", (int)offset, value);
-    switch (offset >> 2) {
-    case SERIAL_DATA:
-        ch = value;
-        if (s->chr)
-            qemu_chr_fe_write(s->chr, &ch, 1);
-        break;
-    case SERIAL_INT_ENABLE:
-        s->int_enable = value;
-        syborg_serial_update(s);
-        break;
-    case SERIAL_DMA_TX_ADDR:
-        s->dma_tx_ptr = value;
-        break;
-    case SERIAL_DMA_TX_COUNT:
-        do_dma_tx(s, value);
-        break;
-    case SERIAL_DMA_RX_ADDR:
-        /* For safety, writes to this register cancel any pending DMA.  */
-        s->dma_rx_size = 0;
-        s->dma_rx_ptr = value;
-        break;
-    case SERIAL_DMA_RX_COUNT:
-        dma_rx_start(s, value);
-        break;
-    default:
-        cpu_abort(cpu_single_env, "syborg_serial_write: Bad offset %x\n",
-                  (int)offset);
-        break;
-    }
-}
-
-static int syborg_serial_can_receive(void *opaque)
-{
-    SyborgSerialState *s = (SyborgSerialState *)opaque;
-
-    if (s->dma_rx_size)
-        return s->dma_rx_size;
-    return s->fifo_size - s->read_count;
-}
-
-static void syborg_serial_receive(void *opaque, const uint8_t *buf, int size)
-{
-    SyborgSerialState *s = (SyborgSerialState *)opaque;
-
-    if (s->dma_rx_size) {
-        /* Place it in the DMA buffer.  */
-        cpu_physical_memory_write(s->dma_rx_ptr, buf, size);
-        s->dma_rx_size -= size;
-        s->dma_rx_ptr += size;
-    } else {
-        while (size--)
-            fifo_push(s, *buf);
-    }
-
-    syborg_serial_update(s);
-}
-
-static void syborg_serial_event(void *opaque, int event)
-{
-    /* TODO: Report BREAK events?  */
-}
-
-static const MemoryRegionOps syborg_serial_ops = {
-    .read = syborg_serial_read,
-    .write = syborg_serial_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_syborg_serial = {
-    .name = "syborg_serial",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32_EQUAL(fifo_size, SyborgSerialState),
-        VMSTATE_UINT32(int_enable, SyborgSerialState),
-        VMSTATE_INT32(read_pos, SyborgSerialState),
-        VMSTATE_INT32(read_count, SyborgSerialState),
-        VMSTATE_UINT32(dma_tx_ptr, SyborgSerialState),
-        VMSTATE_UINT32(dma_rx_ptr, SyborgSerialState),
-        VMSTATE_UINT32(dma_rx_size, SyborgSerialState),
-        VMSTATE_VARRAY_UINT32(read_fifo, SyborgSerialState, fifo_size, 1,
-                              vmstate_info_uint32, uint32),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int syborg_serial_init(SysBusDevice *dev)
-{
-    SyborgSerialState *s = FROM_SYSBUS(SyborgSerialState, dev);
-
-    sysbus_init_irq(dev, &s->irq);
-    memory_region_init_io(&s->iomem, &syborg_serial_ops, s,
-                          "serial", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    s->chr = qdev_init_chardev(&dev->qdev);
-    if (s->chr) {
-        qemu_chr_add_handlers(s->chr, syborg_serial_can_receive,
-                              syborg_serial_receive, syborg_serial_event, s);
-    }
-    if (s->fifo_size <= 0) {
-        fprintf(stderr, "syborg_serial: fifo too small\n");
-        s->fifo_size = 16;
-    }
-    s->read_fifo = g_malloc0(s->fifo_size * sizeof(s->read_fifo[0]));
-
-    return 0;
-}
-
-static SysBusDeviceInfo syborg_serial_info = {
-    .init = syborg_serial_init,
-    .qdev.name  = "syborg,serial",
-    .qdev.size  = sizeof(SyborgSerialState),
-    .qdev.vmsd  = &vmstate_syborg_serial,
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("fifo-size", SyborgSerialState, fifo_size, 16),
-        DEFINE_PROP_END_OF_LIST(),
-    }
-};
-
-static void syborg_serial_register_devices(void)
-{
-    sysbus_register_withprop(&syborg_serial_info);
-}
-
-device_init(syborg_serial_register_devices)
diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c
deleted file mode 100644
index 1498f01..0000000
--- a/hw/syborg_timer.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Syborg Interval Timer.
- *
- * Copyright (c) 2008 CodeSourcery
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "qemu-timer.h"
-#include "syborg.h"
-
-//#define DEBUG_SYBORG_TIMER
-
-#ifdef DEBUG_SYBORG_TIMER
-#define DPRINTF(fmt, ...) \
-do { printf("syborg_timer: " fmt , ##args); } while (0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_timer: error: " fmt , ## __VA_ARGS__); \
-    exit(1);} while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_timer: error: " fmt , ## __VA_ARGS__);} while (0)
-#endif
-
-enum {
-    TIMER_ID          = 0,
-    TIMER_RUNNING     = 1,
-    TIMER_ONESHOT     = 2,
-    TIMER_LIMIT       = 3,
-    TIMER_VALUE       = 4,
-    TIMER_INT_ENABLE  = 5,
-    TIMER_INT_STATUS  = 6,
-    TIMER_FREQ        = 7
-};
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    ptimer_state *timer;
-    int running;
-    int oneshot;
-    uint32_t limit;
-    uint32_t freq;
-    uint32_t int_level;
-    uint32_t int_enabled;
-    qemu_irq irq;
-} SyborgTimerState;
-
-static void syborg_timer_update(SyborgTimerState *s)
-{
-    /* Update interrupt.  */
-    if (s->int_level && s->int_enabled) {
-        qemu_irq_raise(s->irq);
-    } else {
-        qemu_irq_lower(s->irq);
-    }
-}
-
-static void syborg_timer_tick(void *opaque)
-{
-    SyborgTimerState *s = (SyborgTimerState *)opaque;
-    //DPRINTF("Timer Tick\n");
-    s->int_level = 1;
-    if (s->oneshot)
-        s->running = 0;
-    syborg_timer_update(s);
-}
-
-static uint64_t syborg_timer_read(void *opaque, target_phys_addr_t offset,
-                                  unsigned size)
-{
-    SyborgTimerState *s = (SyborgTimerState *)opaque;
-
-    DPRINTF("Reg read %d\n", (int)offset);
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case TIMER_ID:
-        return SYBORG_ID_TIMER;
-    case TIMER_RUNNING:
-        return s->running;
-    case TIMER_ONESHOT:
-        return s->oneshot;
-    case TIMER_LIMIT:
-        return s->limit;
-    case TIMER_VALUE:
-        return ptimer_get_count(s->timer);
-    case TIMER_INT_ENABLE:
-        return s->int_enabled;
-    case TIMER_INT_STATUS:
-        return s->int_level;
-    case TIMER_FREQ:
-        return s->freq;
-    default:
-        cpu_abort(cpu_single_env, "syborg_timer_read: Bad offset %x\n",
-                  (int)offset);
-        return 0;
-    }
-}
-
-static void syborg_timer_write(void *opaque, target_phys_addr_t offset,
-                               uint64_t value, unsigned size)
-{
-    SyborgTimerState *s = (SyborgTimerState *)opaque;
-
-    DPRINTF("Reg write %d\n", (int)offset);
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case TIMER_RUNNING:
-        if (value == s->running)
-            break;
-        s->running = value;
-        if (value) {
-            ptimer_run(s->timer, s->oneshot);
-        } else {
-            ptimer_stop(s->timer);
-        }
-        break;
-    case TIMER_ONESHOT:
-        if (s->running) {
-            ptimer_stop(s->timer);
-        }
-        s->oneshot = value;
-        if (s->running) {
-            ptimer_run(s->timer, s->oneshot);
-        }
-        break;
-    case TIMER_LIMIT:
-        s->limit = value;
-        ptimer_set_limit(s->timer, value, 1);
-        break;
-    case TIMER_VALUE:
-        ptimer_set_count(s->timer, value);
-        break;
-    case TIMER_INT_ENABLE:
-        s->int_enabled = value;
-        syborg_timer_update(s);
-        break;
-    case TIMER_INT_STATUS:
-        s->int_level &= ~value;
-        syborg_timer_update(s);
-        break;
-    default:
-        cpu_abort(cpu_single_env, "syborg_timer_write: Bad offset %x\n",
-                  (int)offset);
-        break;
-    }
-}
-
-static const MemoryRegionOps syborg_timer_ops = {
-    .read = syborg_timer_read,
-    .write = syborg_timer_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_syborg_timer = {
-    .name = "syborg_timer",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_INT32(running, SyborgTimerState),
-        VMSTATE_INT32(oneshot, SyborgTimerState),
-        VMSTATE_UINT32(limit, SyborgTimerState),
-        VMSTATE_UINT32(int_level, SyborgTimerState),
-        VMSTATE_UINT32(int_enabled, SyborgTimerState),
-        VMSTATE_PTIMER(timer, SyborgTimerState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int syborg_timer_init(SysBusDevice *dev)
-{
-    SyborgTimerState *s = FROM_SYSBUS(SyborgTimerState, dev);
-    QEMUBH *bh;
-
-    if (s->freq == 0) {
-        fprintf(stderr, "syborg_timer: Zero/unset frequency\n");
-        exit(1);
-    }
-    sysbus_init_irq(dev, &s->irq);
-    memory_region_init_io(&s->iomem, &syborg_timer_ops, s, "timer", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    bh = qemu_bh_new(syborg_timer_tick, s);
-    s->timer = ptimer_init(bh);
-    ptimer_set_freq(s->timer, s->freq);
-    vmstate_register(&dev->qdev, -1, &vmstate_syborg_timer, s);
-    return 0;
-}
-
-static SysBusDeviceInfo syborg_timer_info = {
-    .init = syborg_timer_init,
-    .qdev.name  = "syborg,timer",
-    .qdev.size  = sizeof(SyborgTimerState),
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("frequency",SyborgTimerState, freq, 0),
-        DEFINE_PROP_END_OF_LIST(),
-    }
-};
-
-static void syborg_timer_register_devices(void)
-{
-    sysbus_register_withprop(&syborg_timer_info);
-}
-
-device_init(syborg_timer_register_devices)
diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
deleted file mode 100644
index 96a0ee6..0000000
--- a/hw/syborg_virtio.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Virtio Syborg bindings
- *
- * Copyright (c) 2009 CodeSourcery
- *
- * 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 "syborg.h"
-#include "sysbus.h"
-#include "virtio.h"
-#include "virtio-net.h"
-
-//#define DEBUG_SYBORG_VIRTIO
-
-#ifdef DEBUG_SYBORG_VIRTIO
-#define DPRINTF(fmt, ...) \
-do { printf("syborg_virtio: " fmt , ## __VA_ARGS__); } while (0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_virtio: error: " fmt , ## __VA_ARGS__); \
-    exit(1);} while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_virtio: error: " fmt , ## __VA_ARGS__);} while (0)
-#endif
-
-enum {
-    SYBORG_VIRTIO_ID             = 0,
-    SYBORG_VIRTIO_DEVTYPE        = 1,
-    SYBORG_VIRTIO_HOST_FEATURES  = 2,
-    SYBORG_VIRTIO_GUEST_FEATURES = 3,
-    SYBORG_VIRTIO_QUEUE_BASE     = 4,
-    SYBORG_VIRTIO_QUEUE_NUM      = 5,
-    SYBORG_VIRTIO_QUEUE_SEL      = 6,
-    SYBORG_VIRTIO_QUEUE_NOTIFY   = 7,
-    SYBORG_VIRTIO_STATUS         = 8,
-    SYBORG_VIRTIO_INT_ENABLE     = 9,
-    SYBORG_VIRTIO_INT_STATUS     = 10
-};
-
-#define SYBORG_VIRTIO_CONFIG 0x100
-
-/* Device independent interface.  */
-
-typedef struct {
-    SysBusDevice busdev;
-    VirtIODevice *vdev;
-    MemoryRegion iomem;
-    qemu_irq irq;
-    uint32_t int_enable;
-    uint32_t id;
-    NICConf nic;
-    uint32_t host_features;
-    virtio_net_conf net;
-} SyborgVirtIOProxy;
-
-static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
-{
-    SyborgVirtIOProxy *s = opaque;
-    VirtIODevice *vdev = s->vdev;
-    uint32_t ret;
-
-    DPRINTF("readl 0x%x\n", (int)offset);
-    if (offset >= SYBORG_VIRTIO_CONFIG) {
-        return virtio_config_readl(vdev, offset - SYBORG_VIRTIO_CONFIG);
-    }
-    switch(offset >> 2) {
-    case SYBORG_VIRTIO_ID:
-        ret = SYBORG_ID_VIRTIO;
-        break;
-    case SYBORG_VIRTIO_DEVTYPE:
-        ret = s->id;
-        break;
-    case SYBORG_VIRTIO_HOST_FEATURES:
-        ret = s->host_features;
-        break;
-    case SYBORG_VIRTIO_GUEST_FEATURES:
-        ret = vdev->guest_features;
-        break;
-    case SYBORG_VIRTIO_QUEUE_BASE:
-        ret = virtio_queue_get_addr(vdev, vdev->queue_sel);
-        break;
-    case SYBORG_VIRTIO_QUEUE_NUM:
-        ret = virtio_queue_get_num(vdev, vdev->queue_sel);
-        break;
-    case SYBORG_VIRTIO_QUEUE_SEL:
-        ret = vdev->queue_sel;
-        break;
-    case SYBORG_VIRTIO_STATUS:
-        ret = vdev->status;
-        break;
-    case SYBORG_VIRTIO_INT_ENABLE:
-        ret = s->int_enable;
-        break;
-    case SYBORG_VIRTIO_INT_STATUS:
-        ret = vdev->isr;
-        break;
-    default:
-        BADF("Bad read offset 0x%x\n", (int)offset);
-        return 0;
-    }
-    return ret;
-}
-
-static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset,
-                                 uint32_t value)
-{
-    SyborgVirtIOProxy *s = opaque;
-    VirtIODevice *vdev = s->vdev;
-
-    DPRINTF("writel 0x%x = 0x%x\n", (int)offset, value);
-    if (offset >= SYBORG_VIRTIO_CONFIG) {
-        return virtio_config_writel(vdev, offset - SYBORG_VIRTIO_CONFIG,
-                                    value);
-    }
-    switch (offset >> 2) {
-    case SYBORG_VIRTIO_GUEST_FEATURES:
-        virtio_set_features(vdev, value);
-        break;
-    case SYBORG_VIRTIO_QUEUE_BASE:
-        if (value == 0)
-            virtio_reset(vdev);
-        else
-            virtio_queue_set_addr(vdev, vdev->queue_sel, value);
-        break;
-    case SYBORG_VIRTIO_QUEUE_SEL:
-        if (value < VIRTIO_PCI_QUEUE_MAX)
-            vdev->queue_sel = value;
-        break;
-    case SYBORG_VIRTIO_QUEUE_NOTIFY:
-        if (value < VIRTIO_PCI_QUEUE_MAX) {
-            virtio_queue_notify(vdev, value);
-        }
-        break;
-    case SYBORG_VIRTIO_STATUS:
-        virtio_set_status(vdev, value & 0xFF);
-        if (vdev->status == 0)
-            virtio_reset(vdev);
-        break;
-    case SYBORG_VIRTIO_INT_ENABLE:
-        s->int_enable = value;
-        virtio_update_irq(vdev);
-        break;
-    case SYBORG_VIRTIO_INT_STATUS:
-        vdev->isr &= ~value;
-        virtio_update_irq(vdev);
-        break;
-    default:
-        BADF("Bad write offset 0x%x\n", (int)offset);
-        break;
-    }
-}
-
-static uint32_t syborg_virtio_readw(void *opaque, target_phys_addr_t offset)
-{
-    SyborgVirtIOProxy *s = opaque;
-    VirtIODevice *vdev = s->vdev;
-
-    DPRINTF("readw 0x%x\n", (int)offset);
-    if (offset >= SYBORG_VIRTIO_CONFIG) {
-        return virtio_config_readw(vdev, offset - SYBORG_VIRTIO_CONFIG);
-    }
-    BADF("Bad halfword read offset 0x%x\n", (int)offset);
-    return -1;
-}
-
-static void syborg_virtio_writew(void *opaque, target_phys_addr_t offset,
-                                 uint32_t value)
-{
-    SyborgVirtIOProxy *s = opaque;
-    VirtIODevice *vdev = s->vdev;
-
-    DPRINTF("writew 0x%x = 0x%x\n", (int)offset, value);
-    if (offset >= SYBORG_VIRTIO_CONFIG) {
-        return virtio_config_writew(vdev, offset - SYBORG_VIRTIO_CONFIG,
-                                    value);
-    }
-    BADF("Bad halfword write offset 0x%x\n", (int)offset);
-}
-
-static uint32_t syborg_virtio_readb(void *opaque, target_phys_addr_t offset)
-{
-    SyborgVirtIOProxy *s = opaque;
-    VirtIODevice *vdev = s->vdev;
-
-    DPRINTF("readb 0x%x\n", (int)offset);
-    if (offset >= SYBORG_VIRTIO_CONFIG) {
-        return virtio_config_readb(vdev, offset - SYBORG_VIRTIO_CONFIG);
-    }
-    BADF("Bad byte read offset 0x%x\n", (int)offset);
-    return -1;
-}
-
-static void syborg_virtio_writeb(void *opaque, target_phys_addr_t offset,
-                                 uint32_t value)
-{
-    SyborgVirtIOProxy *s = opaque;
-    VirtIODevice *vdev = s->vdev;
-
-    DPRINTF("writeb 0x%x = 0x%x\n", (int)offset, value);
-    if (offset >= SYBORG_VIRTIO_CONFIG) {
-        return virtio_config_writeb(vdev, offset - SYBORG_VIRTIO_CONFIG,
-                                    value);
-    }
-    BADF("Bad byte write offset 0x%x\n", (int)offset);
-}
-
-static const MemoryRegionOps syborg_virtio_ops = {
-    .old_mmio = {
-        .read = { syborg_virtio_readb, syborg_virtio_readw, syborg_virtio_readl },
-        .write = { syborg_virtio_writeb, syborg_virtio_writew, syborg_virtio_writel },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void syborg_virtio_update_irq(void *opaque, uint16_t vector)
-{
-    SyborgVirtIOProxy *proxy = opaque;
-    int level;
-
-    level = proxy->int_enable & proxy->vdev->isr;
-    DPRINTF("IRQ %d\n", level);
-    qemu_set_irq(proxy->irq, level != 0);
-}
-
-static unsigned syborg_virtio_get_features(void *opaque)
-{
-    SyborgVirtIOProxy *proxy = opaque;
-    return proxy->host_features;
-}
-
-static VirtIOBindings syborg_virtio_bindings = {
-    .notify = syborg_virtio_update_irq,
-    .get_features = syborg_virtio_get_features,
-};
-
-static int syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)
-{
-    proxy->vdev = vdev;
-
-    /* Don't support multiple vectors */
-    proxy->vdev->nvectors = 0;
-    sysbus_init_irq(&proxy->busdev, &proxy->irq);
-    memory_region_init_io(&proxy->iomem, &syborg_virtio_ops, proxy,
-                          "virtio", 0x1000);
-    sysbus_init_mmio(&proxy->busdev, &proxy->iomem);
-
-    proxy->id = ((uint32_t)0x1af4 << 16) | vdev->device_id;
-
-    qemu_register_reset(virtio_reset, vdev);
-
-    virtio_bind_device(vdev, &syborg_virtio_bindings, proxy);
-    proxy->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY);
-    proxy->host_features = vdev->get_features(vdev, proxy->host_features);
-    return 0;
-}
-
-/* Device specific bindings.  */
-
-static int syborg_virtio_net_init(SysBusDevice *dev)
-{
-    VirtIODevice *vdev;
-    SyborgVirtIOProxy *proxy = FROM_SYSBUS(SyborgVirtIOProxy, dev);
-
-    vdev = virtio_net_init(&dev->qdev, &proxy->nic, &proxy->net);
-    return syborg_virtio_init(proxy, vdev);
-}
-
-static SysBusDeviceInfo syborg_virtio_net_info = {
-    .init = syborg_virtio_net_init,
-    .qdev.name  = "syborg,virtio-net",
-    .qdev.size  = sizeof(SyborgVirtIOProxy),
-    .qdev.props = (Property[]) {
-        DEFINE_NIC_PROPERTIES(SyborgVirtIOProxy, nic),
-        DEFINE_VIRTIO_NET_FEATURES(SyborgVirtIOProxy, host_features),
-        DEFINE_PROP_UINT32("x-txtimer", SyborgVirtIOProxy,
-                           net.txtimer, TX_TIMER_INTERVAL),
-        DEFINE_PROP_INT32("x-txburst", SyborgVirtIOProxy,
-                          net.txburst, TX_BURST),
-        DEFINE_PROP_STRING("tx", SyborgVirtIOProxy, net.tx),
-        DEFINE_PROP_END_OF_LIST(),
-    }
-};
-
-static void syborg_virtio_register_devices(void)
-{
-    sysbus_register_withprop(&syborg_virtio_net_info);
-}
-
-device_init(syborg_virtio_register_devices)
commit e5d1fca0f20babbe355957b9ba536fe6187691cc
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Dec 7 15:01:49 2011 +0000

    net: take ownership of fd in socket init functions
    
    Today net/socket.c has no consistent policy for closing the socket file
    descriptor when initialization fails.  This means we leak the file
    descriptor in some cases or we could also try to close it twice.
    
    Make error paths consistent by taking ownership of the file descriptor
    and closing it on error.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/net/socket.c b/net/socket.c
index 613a7ef..f999c26 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -266,14 +266,13 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
             if (saddr.sin_addr.s_addr == 0) {
                 fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, "
                         "cannot setup multicast dst addr\n", fd);
-                return NULL;
+                goto err;
             }
             /* clone dgram socket */
             newfd = net_socket_mcast_create(&saddr, NULL);
             if (newfd < 0) {
                 /* error already reported by net_socket_mcast_create() */
-                close(fd);
-                return NULL;
+                goto err;
             }
             /* clone newfd to fd, close newfd */
             dup2(newfd, fd);
@@ -283,7 +282,7 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
             fprintf(stderr,
                     "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n",
                     fd, strerror(errno));
-            return NULL;
+            goto err;
         }
     }
 
@@ -304,6 +303,10 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
     if (is_connected) s->dgram_dst=saddr;
 
     return s;
+
+err:
+    closesocket(fd);
+    return NULL;
 }
 
 static void net_socket_connect(void *opaque)
@@ -353,6 +356,7 @@ static NetSocketState *net_socket_fd_init(VLANState *vlan,
         (socklen_t *)&optlen)< 0) {
         fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n",
                 fd);
+        closesocket(fd);
         return NULL;
     }
     switch(so_type) {
@@ -386,9 +390,7 @@ static void net_socket_accept(void *opaque)
         }
     }
     s1 = net_socket_fd_init(s->vlan, s->model, s->name, fd, 1);
-    if (!s1) {
-        closesocket(fd);
-    } else {
+    if (s1) {
         snprintf(s1->nc.info_str, sizeof(s1->nc.info_str),
                  "socket: connection from %s:%d",
                  inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
@@ -549,7 +551,6 @@ int net_init_socket(QemuOpts *opts,
         }
 
         if (!net_socket_fd_init(vlan, "socket", name, fd, 1)) {
-            close(fd);
             return -1;
         }
     } else if (qemu_opt_get(opts, "listen")) {
commit 842480d493a085fd9598d35b3318765699f88709
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Dec 7 15:01:48 2011 +0000

    net: expand tabs in net/socket.c
    
    In order to make later patches sane, expand the tab characters and
    conform to QEMU coding style now.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/net/socket.c b/net/socket.c
index e9ef128..613a7ef 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -161,10 +161,11 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
 #endif
 
     if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) {
-	fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) does not contain a multicast address\n",
-		inet_ntoa(mcastaddr->sin_addr),
+        fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) "
+                "does not contain a multicast address\n",
+                inet_ntoa(mcastaddr->sin_addr),
                 (int)ntohl(mcastaddr->sin_addr.s_addr));
-	return -1;
+        return -1;
 
     }
     fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
@@ -177,8 +178,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
     ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
                    (const char *)&val, sizeof(val));
     if (ret < 0) {
-	perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
-	goto fail;
+        perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
+        goto fail;
     }
 
     ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr));
@@ -198,8 +199,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
     ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                      (const char *)&imr, sizeof(struct ip_mreq));
     if (ret < 0) {
-	perror("setsockopt(IP_ADD_MEMBERSHIP)");
-	goto fail;
+        perror("setsockopt(IP_ADD_MEMBERSHIP)");
+        goto fail;
     }
 
     /* Force mcast msgs to loopback (eg. several QEMUs in same host */
@@ -207,8 +208,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
     ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
                    (const char *)&loop, sizeof(loop));
     if (ret < 0) {
-	perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
-	goto fail;
+        perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
+        goto fail;
     }
 
     /* If a bind address is given, only send packets from that address */
@@ -260,37 +261,38 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
      */
 
     if (is_connected) {
-	if (getsockname(fd, (struct sockaddr *) &saddr, &saddr_len) == 0) {
-	    /* must be bound */
-	    if (saddr.sin_addr.s_addr==0) {
-		fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, cannot setup multicast dst addr\n",
-			fd);
-		return NULL;
-	    }
-	    /* clone dgram socket */
-	    newfd = net_socket_mcast_create(&saddr, NULL);
-	    if (newfd < 0) {
-		/* error already reported by net_socket_mcast_create() */
-		close(fd);
-		return NULL;
-	    }
-	    /* clone newfd to fd, close newfd */
-	    dup2(newfd, fd);
-	    close(newfd);
-
-	} else {
-	    fprintf(stderr, "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n",
-		    fd, strerror(errno));
-	    return NULL;
-	}
+        if (getsockname(fd, (struct sockaddr *) &saddr, &saddr_len) == 0) {
+            /* must be bound */
+            if (saddr.sin_addr.s_addr == 0) {
+                fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, "
+                        "cannot setup multicast dst addr\n", fd);
+                return NULL;
+            }
+            /* clone dgram socket */
+            newfd = net_socket_mcast_create(&saddr, NULL);
+            if (newfd < 0) {
+                /* error already reported by net_socket_mcast_create() */
+                close(fd);
+                return NULL;
+            }
+            /* clone newfd to fd, close newfd */
+            dup2(newfd, fd);
+            close(newfd);
+
+        } else {
+            fprintf(stderr,
+                    "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n",
+                    fd, strerror(errno));
+            return NULL;
+        }
     }
 
     nc = qemu_new_net_client(&net_dgram_socket_info, vlan, NULL, model, name);
 
     snprintf(nc->info_str, sizeof(nc->info_str),
-	    "socket: fd=%d (%s mcast=%s:%d)",
-	    fd, is_connected ? "cloned" : "",
-	    inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+            "socket: fd=%d (%s mcast=%s:%d)",
+            fd, is_connected ? "cloned" : "",
+            inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
 
     s = DO_UPCAST(NetSocketState, nc, nc);
 
@@ -349,8 +351,9 @@ static NetSocketState *net_socket_fd_init(VLANState *vlan,
 
     if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type,
         (socklen_t *)&optlen)< 0) {
-	fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n", fd);
-	return NULL;
+        fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n",
+                fd);
+        return NULL;
     }
     switch(so_type) {
     case SOCK_DGRAM:
@@ -509,7 +512,7 @@ static int net_socket_mcast_init(VLANState *vlan,
 
     fd = net_socket_mcast_create(&saddr, param_localaddr);
     if (fd < 0)
-	return -1;
+        return -1;
 
     s = net_socket_fd_init(vlan, model, name, fd, 0);
     if (!s)
commit bf95c0d55c24e8ce1c03e1ba491437297f8f96f4
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Dec 6 22:03:43 2011 -0600

    guest agent: add supported command list to guest-info RPC
    
    Not that there is blacklisting functionality we can no longer infer
    the agent's capabilities via version. This patch extends the current
    guest-info RPC to also return a list of dictionaries containing the name
    of each supported RPC, along with a boolean indicating whether or not
    the command has been disabled by a guest administrator/distro.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json
index fde5971..29989fe 100644
--- a/qapi-schema-guest.json
+++ b/qapi-schema-guest.json
@@ -43,7 +43,11 @@
 #
 # Since: 0.15.0
 ##
-{ 'type': 'GuestAgentInfo', 'data': {'version': 'str'} }
+{ 'type': 'GuestAgentCommandInfo',
+  'data': { 'name': 'str', 'enabled': 'bool' } }
+{ 'type': 'GuestAgentInfo',
+  'data': { 'version': 'str',
+            'supported_commands': ['GuestAgentCommandInfo'] } }
 { 'command': 'guest-info',
   'returns': 'GuestAgentInfo' }
 
diff --git a/qapi/qmp-core.h b/qapi/qmp-core.h
index 3cf1781..3bb3acb 100644
--- a/qapi/qmp-core.h
+++ b/qapi/qmp-core.h
@@ -38,6 +38,7 @@ void qmp_register_command(const char *name, QmpCommandFunc *fn);
 QmpCommand *qmp_find_command(const char *name);
 QObject *qmp_dispatch(QObject *request);
 void qmp_disable_command(const char *name);
+bool qmp_command_is_enabled(const char *name);
 char **qmp_get_command_list(void);
 
 #endif
diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c
index abafa34..25c89ad 100644
--- a/qapi/qmp-registry.c
+++ b/qapi/qmp-registry.c
@@ -52,6 +52,19 @@ void qmp_disable_command(const char *name)
     }
 }
 
+bool qmp_command_is_enabled(const char *name)
+{
+    QmpCommand *cmd;
+
+    QTAILQ_FOREACH(cmd, &qmp_commands, node) {
+        if (strcmp(cmd->name, name) == 0) {
+            return cmd->enabled;
+        }
+    }
+
+    return false;
+}
+
 char **qmp_get_command_list(void)
 {
     QmpCommand *cmd;
diff --git a/qga/guest-agent-commands.c b/qga/guest-agent-commands.c
index 6da9904..a09c8ca 100644
--- a/qga/guest-agent-commands.c
+++ b/qga/guest-agent-commands.c
@@ -57,9 +57,33 @@ void qmp_guest_ping(Error **err)
 struct GuestAgentInfo *qmp_guest_info(Error **err)
 {
     GuestAgentInfo *info = g_malloc0(sizeof(GuestAgentInfo));
+    GuestAgentCommandInfo *cmd_info;
+    GuestAgentCommandInfoList *cmd_info_list;
+    char **cmd_list_head, **cmd_list;
 
     info->version = g_strdup(QGA_VERSION);
 
+    cmd_list_head = cmd_list = qmp_get_command_list();
+    if (*cmd_list_head == NULL) {
+        goto out;
+    }
+
+    while (*cmd_list) {
+        cmd_info = g_malloc0(sizeof(GuestAgentCommandInfo));
+        cmd_info->name = strdup(*cmd_list);
+        cmd_info->enabled = qmp_command_is_enabled(cmd_info->name);
+
+        cmd_info_list = g_malloc0(sizeof(GuestAgentCommandInfoList));
+        cmd_info_list->value = cmd_info;
+        cmd_info_list->next = info->supported_commands;
+        info->supported_commands = cmd_info_list;
+
+        g_free(*cmd_list);
+        cmd_list++;
+    }
+
+out:
+    g_free(cmd_list_head);
     return info;
 }
 
commit abd6cf6d8e6be55a6535bf27b692bdf520462c15
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Dec 6 22:03:42 2011 -0600

    guest agent: add RPC blacklist command-line option
    
    This adds a command-line option, -b/--blacklist, that accepts a
    comma-seperated list of RPCs to disable, or prints a list of
    available RPCs if passed "?".
    
    In consequence this also adds general blacklisting and RPC listing
    facilities to the new QMP dispatch/registry facilities, should the
    QMP monitor ever have a need for such a thing.
    
    Ideally, to avoid support/compatability issues in the future,
    blacklisting guest agent functionality will be the exceptional
    case, but we add the functionality here to handle guest administrators
    with specific requirements.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qapi/qmp-core.h b/qapi/qmp-core.h
index f1c26e4..3cf1781 100644
--- a/qapi/qmp-core.h
+++ b/qapi/qmp-core.h
@@ -31,11 +31,14 @@ typedef struct QmpCommand
     QmpCommandType type;
     QmpCommandFunc *fn;
     QTAILQ_ENTRY(QmpCommand) node;
+    bool enabled;
 } QmpCommand;
 
 void qmp_register_command(const char *name, QmpCommandFunc *fn);
 QmpCommand *qmp_find_command(const char *name);
 QObject *qmp_dispatch(QObject *request);
+void qmp_disable_command(const char *name);
+char **qmp_get_command_list(void);
 
 #endif
 
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 5584693..43f640a 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -79,6 +79,10 @@ static QObject *do_qmp_dispatch(QObject *request, Error **errp)
         error_set(errp, QERR_COMMAND_NOT_FOUND, command);
         return NULL;
     }
+    if (!cmd->enabled) {
+        error_set(errp, QERR_COMMAND_DISABLED, command);
+        return NULL;
+    }
 
     if (!qdict_haskey(dict, "arguments")) {
         args = qdict_new();
diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c
index 5ff99cf..abafa34 100644
--- a/qapi/qmp-registry.c
+++ b/qapi/qmp-registry.c
@@ -14,7 +14,7 @@
 
 #include "qapi/qmp-core.h"
 
-static QTAILQ_HEAD(, QmpCommand) qmp_commands =
+static QTAILQ_HEAD(QmpCommandList, QmpCommand) qmp_commands =
     QTAILQ_HEAD_INITIALIZER(qmp_commands);
 
 void qmp_register_command(const char *name, QmpCommandFunc *fn)
@@ -24,17 +24,50 @@ void qmp_register_command(const char *name, QmpCommandFunc *fn)
     cmd->name = name;
     cmd->type = QCT_NORMAL;
     cmd->fn = fn;
+    cmd->enabled = true;
     QTAILQ_INSERT_TAIL(&qmp_commands, cmd, node);
 }
 
 QmpCommand *qmp_find_command(const char *name)
 {
-    QmpCommand *i;
+    QmpCommand *cmd;
 
-    QTAILQ_FOREACH(i, &qmp_commands, node) {
-        if (strcmp(i->name, name) == 0) {
-            return i;
+    QTAILQ_FOREACH(cmd, &qmp_commands, node) {
+        if (strcmp(cmd->name, name) == 0) {
+            return cmd;
         }
     }
     return NULL;
 }
+
+void qmp_disable_command(const char *name)
+{
+    QmpCommand *cmd;
+
+    QTAILQ_FOREACH(cmd, &qmp_commands, node) {
+        if (strcmp(cmd->name, name) == 0) {
+            cmd->enabled = false;
+            return;
+        }
+    }
+}
+
+char **qmp_get_command_list(void)
+{
+    QmpCommand *cmd;
+    int count = 1;
+    char **list_head, **list;
+
+    QTAILQ_FOREACH(cmd, &qmp_commands, node) {
+        count++;
+    }
+
+    list_head = list = g_malloc0(count * sizeof(char *));
+
+    QTAILQ_FOREACH(cmd, &qmp_commands, node) {
+        *list = strdup(cmd->name);
+        list++;
+    }
+
+    return list_head;
+}
diff --git a/qemu-ga.c b/qemu-ga.c
index 4932013..200bb15 100644
--- a/qemu-ga.c
+++ b/qemu-ga.c
@@ -27,6 +27,7 @@
 #include "signal.h"
 #include "qerror.h"
 #include "error_int.h"
+#include "qapi/qmp-core.h"
 
 #define QGA_VIRTIO_PATH_DEFAULT "/dev/virtio-ports/org.qemu.guest_agent.0"
 #define QGA_PIDFILE_DEFAULT "/var/run/qemu-ga.pid"
@@ -91,6 +92,8 @@ static void usage(const char *cmd)
 "  -v, --verbose     log extra debugging information\n"
 "  -V, --version     print version information and exit\n"
 "  -d, --daemonize   become a daemon\n"
+"  -b, --blacklist   comma-seperated list of RPCs to disable (no spaces, \"?\""
+"                    to list available RPCs)\n"
 "  -h, --help        display this help and exit\n"
 "\n"
 "Report bugs to <mdroth at linux.vnet.ibm.com>\n"
@@ -548,7 +551,7 @@ static void init_guest_agent(GAState *s)
 
 int main(int argc, char **argv)
 {
-    const char *sopt = "hVvdm:p:l:f:";
+    const char *sopt = "hVvdm:p:l:f:b:";
     const char *method = NULL, *path = NULL, *pidfile = QGA_PIDFILE_DEFAULT;
     const struct option lopt[] = {
         { "help", 0, NULL, 'h' },
@@ -559,13 +562,16 @@ int main(int argc, char **argv)
         { "method", 0, NULL, 'm' },
         { "path", 0, NULL, 'p' },
         { "daemonize", 0, NULL, 'd' },
+        { "blacklist", 0, NULL, 'b' },
         { NULL, 0, NULL, 0 }
     };
-    int opt_ind = 0, ch, daemonize = 0;
+    int opt_ind = 0, ch, daemonize = 0, i, j, len;
     GLogLevelFlags log_level = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL;
     FILE *log_file = stderr;
     GAState *s;
 
+    module_call_init(MODULE_INIT_QAPI);
+
     while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
         switch (ch) {
         case 'm':
@@ -595,6 +601,32 @@ int main(int argc, char **argv)
         case 'd':
             daemonize = 1;
             break;
+        case 'b': {
+            char **list_head, **list;
+            if (*optarg == '?') {
+                list_head = list = qmp_get_command_list();
+                while (*list != NULL) {
+                    printf("%s\n", *list);
+                    g_free(*list);
+                    list++;
+                }
+                g_free(list_head);
+                return 0;
+            }
+            for (j = 0, i = 0, len = strlen(optarg); i < len; i++) {
+                if (optarg[i] == ',') {
+                    optarg[i] = 0;
+                    qmp_disable_command(&optarg[j]);
+                    g_debug("disabling command: %s", &optarg[j]);
+                    j = i + 1;
+                }
+            }
+            if (j < i) {
+                qmp_disable_command(&optarg[j]);
+                g_debug("disabling command: %s", &optarg[j]);
+            }
+            break;
+        }
         case 'h':
             usage(argv[0]);
             return 0;
@@ -624,7 +656,6 @@ int main(int argc, char **argv)
     ga_command_state_init_all(s->command_state);
     ga_state = s;
 
-    module_call_init(MODULE_INIT_QAPI);
     init_guest_agent(ga_state);
     register_signal_handlers();
 
diff --git a/qerror.c b/qerror.c
index b544ced..a8ecb0f 100644
--- a/qerror.c
+++ b/qerror.c
@@ -65,6 +65,10 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "The command %(name) has not been found",
     },
     {
+        .error_fmt = QERR_COMMAND_DISABLED,
+        .desc      = "The command %(name) has been disabled for this instance",
+    },
+    {
         .error_fmt = QERR_DEVICE_ENCRYPTED,
         .desc      = "Device '%(device)' is encrypted",
     },
diff --git a/qerror.h b/qerror.h
index 1fee39d..688e700 100644
--- a/qerror.h
+++ b/qerror.h
@@ -66,6 +66,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_COMMAND_NOT_FOUND \
     "{ 'class': 'CommandNotFound', 'data': { 'name': %s } }"
 
+#define QERR_COMMAND_DISABLED \
+    "{ 'class': 'CommandDisabled', 'data': { 'name': %s } }"
+
 #define QERR_DEVICE_ENCRYPTED \
     "{ 'class': 'DeviceEncrypted', 'data': { 'device': %s } }"
 
commit 4cb016587a34fee08f42ab04ba6daa7842f41228
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Dec 12 10:58:26 2011 +0000

    Add a .mailmap to map pre-git-conversion authors to friendly names
    
    Add a .mailmap file so 'git shortlog' can map the unfriendly
    pre-git-conversion author entries to real names.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/.mailmap b/.mailmap
new file mode 100644
index 0000000..9797802
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,16 @@
+# This mailmap just translates the weird addresses from the original import into git
+# into proper addresses so that they are counted properly in git shortlog output.
+#
+Andrzej Zaborowski <balrogg at gmail.com> balrog <balrog at c046a42c-6fe2-441c-8c8c-71466251a162>
+Anthony Liguori <aliguori at us.ibm.com> aliguori <aliguori at c046a42c-6fe2-441c-8c8c-71466251a162>
+Aurelien Jarno <aurelien at aurel32.net> aurel32 <aurel32 at c046a42c-6fe2-441c-8c8c-71466251a162>
+Blue Swirl <blauwirbel at gmail.com> blueswir1 <blueswir1 at c046a42c-6fe2-441c-8c8c-71466251a162>
+Edgar E. Iglesias <edgar.iglesias at gmail.com> edgar_igl <edgar_igl at c046a42c-6fe2-441c-8c8c-71466251a162>
+Fabrice Bellard <fabrice at bellard.org> bellard <bellard at c046a42c-6fe2-441c-8c8c-71466251a162>
+Jocelyn Mayer <l_indien at magic.fr> j_mayer <j_mayer at c046a42c-6fe2-441c-8c8c-71466251a162>
+Paul Brook <paul at codesourcery.com> pbrook <pbrook at c046a42c-6fe2-441c-8c8c-71466251a162>
+Thiemo Seufer <ths at networkno.de> ths <ths at c046a42c-6fe2-441c-8c8c-71466251a162>
+malc <av1474 at comtv.ru> malc <malc at c046a42c-6fe2-441c-8c8c-71466251a162>
+# There is also a:
+#    (no author) <(no author)@c046a42c-6fe2-441c-8c8c-71466251a162>
+# for the cvs2svn initialization commit e63c3dc74bf.
commit 8160bfbc4d5d0abf78afa557f2d5832dc11cd690
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 10 10:41:48 2011 -0200

    unix_close(): check for close() errors too (v2)
    
    In case close() fails, we want to report the error back.
    
    Changes v1 -> v2:
     - Use braces on if statement to match coding style
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration-unix.c b/migration-unix.c
index 8596353..dfcf203 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -40,12 +40,15 @@ static int unix_write(MigrationState *s, const void * buf, size_t size)
 
 static int unix_close(MigrationState *s)
 {
+    int r = 0;
     DPRINTF("unix_close\n");
     if (s->fd != -1) {
-        close(s->fd);
+        if (close(s->fd) < 0) {
+            r = -errno;
+        }
         s->fd = -1;
     }
-    return 0;
+    return r;
 }
 
 static void unix_wait_for_connect(void *opaque)
commit 61a5872fd66be718ad022102bf813d7e4e9324c5
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 10 10:41:47 2011 -0200

    tcp_close(): check for close() errors too (v2)
    
    In case close() fails, we want to report the error back.
    
    Changes v1 -> v2:
     - Use braces on if statement to match coding style
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration-tcp.c b/migration-tcp.c
index 5aa742c..cf6a9b8 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -40,12 +40,15 @@ static int socket_write(MigrationState *s, const void * buf, size_t size)
 
 static int tcp_close(MigrationState *s)
 {
+    int r = 0;
     DPRINTF("tcp_close\n");
     if (s->fd != -1) {
-        close(s->fd);
+        if (close(s->fd) < 0) {
+            r = -errno;
+        }
         s->fd = -1;
     }
-    return 0;
+    return r;
 }
 
 static void tcp_wait_for_connect(void *opaque)
commit e375fe3472f6d64971d3bd8e10a3f159e72435a1
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 10 10:41:46 2011 -0200

    exec_close(): return -errno on errors (v2)
    
    All qemu_fclose() callers were already changed to accept any negative
    value as error, so we now can change it to return -errno.
    
    When the process exits with a non-zero exit code, we return -EIO to as a
    fake errno value.
    
    Changes v1 -> v2:
     - Don't use "//" comments, to make checkpatch.pl happy
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration-exec.c b/migration-exec.c
index 626b648..e14552e 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -50,12 +50,9 @@ static int exec_close(MigrationState *s)
         ret = qemu_fclose(s->opaque);
         s->opaque = NULL;
         s->fd = -1;
-        if (ret >= 0 &&
-            WIFEXITED(ret)
-            && WEXITSTATUS(ret) == 0) {
-            ret = 0;
-        } else {
-            ret = -1;
+        if (ret >= 0 && !(WIFEXITED(ret) && WEXITSTATUS(ret) == 0)) {
+            /* close succeeded, but non-zero exit code: */
+            ret = -EIO; /* fake errno value */
         }
     }
     return ret;
commit 0e286705192205cdb00d31d6757ca3dc28fb896a
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 10 10:41:45 2011 -0200

    stdio_fclose: return -errno on errors (v2)
    
    This is what qemu_fclose() expects.
    
    Changes v1 -> v2:
     - Add braces to if statement to match coding style
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/savevm.c b/savevm.c
index 392a14f..b72f6c0 100644
--- a/savevm.c
+++ b/savevm.c
@@ -245,9 +245,12 @@ static int stdio_pclose(void *opaque)
 static int stdio_fclose(void *opaque)
 {
     QEMUFileStdio *s = opaque;
-    fclose(s->stdio_file);
+    int ret = 0;
+    if (fclose(s->stdio_file) == EOF) {
+        ret = -errno;
+    }
     g_free(s);
-    return 0;
+    return ret;
 }
 
 QEMUFile *qemu_popen(FILE *stdio_file, const char *mode)
commit 26f1af0aa3db024349f6bb6ed7a0ac89052910bb
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 10 10:41:44 2011 -0200

    stdio_pclose: return -errno on error (v3)
    
    This is what qemu_fclose() expects.
    
    Changes v1 -> v2:
     - On success, keep returning pclose() return value, instead of always 0.
    
    Changes v2 -> v3:
     - Add braces on if statements to match coding style
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/savevm.c b/savevm.c
index adff421..392a14f 100644
--- a/savevm.c
+++ b/savevm.c
@@ -235,6 +235,9 @@ static int stdio_pclose(void *opaque)
     QEMUFileStdio *s = opaque;
     int ret;
     ret = pclose(s->stdio_file);
+    if (ret == -1) {
+        ret = -errno;
+    }
     g_free(s);
     return ret;
 }
commit d82ca915875ac55ba291435f7eb4fe7bfcb2cecb
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 10 10:41:43 2011 -0200

    qemu_fclose: return last_error if set (v3)
    
    This will make sure no error will be missed as long as callers always
    check for qemu_fclose() return value. For reference, this is the
    complete list of qemu_fclose() callers:
    
     - exec_close(): already fixed to check for negative values, not -1
     - migrate_fd_cleanup(): already fixed to consider only negative values
       as error, not any non-zero value
     - exec_accept_incoming_migration(): no return value check (yet)
     - fd_accept_incoming_migration(): no return value check (yet)
     - tcp_accept_incoming_migration(): no return value check (yet)
     - unix_accept_incoming_migration(): no return value check (yet)
     - do_savevm(): no return value check (yet)
     - load_vmstate(): no return value check (yet)
    
    Changes v1 -> v2:
     - Add small comment about the need to return previously-spotted errors
    
    Changes v2 -> v3:
     - Add braces to "if" statements to match coding style
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/savevm.c b/savevm.c
index e121096..adff421 100644
--- a/savevm.c
+++ b/savevm.c
@@ -436,6 +436,22 @@ void qemu_file_set_error(QEMUFile *f, int ret)
     f->last_error = ret;
 }
 
+/** Sets last_error conditionally
+ *
+ * Sets last_error only if ret is negative _and_ no error
+ * was set before.
+ */
+static void qemu_file_set_if_error(QEMUFile *f, int ret)
+{
+    if (ret < 0 && !f->last_error) {
+        qemu_file_set_error(f, ret);
+    }
+}
+
+/** Flushes QEMUFile buffer
+ *
+ * In case of error, last_error is set.
+ */
 void qemu_fflush(QEMUFile *f)
 {
     if (!f->put_buffer)
@@ -482,12 +498,41 @@ static void qemu_fill_buffer(QEMUFile *f)
         qemu_file_set_error(f, len);
 }
 
-int qemu_fclose(QEMUFile *f)
+/** Calls close function and set last_error if needed
+ *
+ * Internal function. qemu_fflush() must be called before this.
+ *
+ * Returns f->close() return value, or 0 if close function is not set.
+ */
+static int qemu_close(QEMUFile *f)
 {
     int ret = 0;
-    qemu_fflush(f);
-    if (f->close)
+    if (f->close) {
         ret = f->close(f->opaque);
+        qemu_file_set_if_error(f, ret);
+    }
+    return ret;
+}
+
+/** Closes the file
+ *
+ * Returns negative error value if any error happened on previous operations or
+ * while closing the file. Returns 0 or positive number on success.
+ *
+ * The meaning of return value on success depends on the specific backend
+ * being used.
+ */
+int qemu_fclose(QEMUFile *f)
+{
+    int ret;
+    qemu_fflush(f);
+    ret = qemu_close(f);
+    /* If any error was spotted before closing, we should report it
+     * instead of the close() return value.
+     */
+    if (f->last_error) {
+        ret = f->last_error;
+    }
     g_free(f);
     return ret;
 }
commit a6d34a949c3546404d403bda61a5e37431b4a6ad
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 10 10:41:42 2011 -0200

    migrate_fd_cleanup: accept any negative qemu_fclose() value as error
    
    Also, we now return the qemu_fclose() value unchanged to the caller. For
    reference, the migrate_fd_cleanup() callers are the following:
    
    - migrate_fd_completed(): any negative value is considered an
      error, so the change is OK.
    - migrate_fd_error(): doesn't check the migrate_fd_cleanup() return value
    - migrate_fd_cancel(): doesn't check the migrate_fd_cleanup() return
      value
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration.c b/migration.c
index 75d4f02..412fdfe 100644
--- a/migration.c
+++ b/migration.c
@@ -174,9 +174,7 @@ static int migrate_fd_cleanup(MigrationState *s)
 
     if (s->file) {
         DPRINTF("closing file\n");
-        if (qemu_fclose(s->file) != 0) {
-            ret = -1;
-        }
+        ret = qemu_fclose(s->file);
         s->file = NULL;
     } else {
         if (s->mon) {
commit ce812673dc11de6c067e87a13f5ac0341df7772d
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 10 10:41:41 2011 -0200

    exec_close(): accept any negative value as qemu_fclose() error
    
    Note that we don't return the unchanged return value back yet, because
    we need to change all qemu_fclose() callers to accept any positive value
    as success.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration-exec.c b/migration-exec.c
index b7b1055..626b648 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -50,7 +50,7 @@ static int exec_close(MigrationState *s)
         ret = qemu_fclose(s->opaque);
         s->opaque = NULL;
         s->fd = -1;
-        if (ret != -1 &&
+        if (ret >= 0 &&
             WIFEXITED(ret)
             && WEXITSTATUS(ret) == 0) {
             ret = 0;
commit 90d8454ed0ffdec3871053b696e4a44f349e561c
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 10 10:41:40 2011 -0200

    QEMUFileCloseFunc: add return value documentation (v2)
    
    qemu_fclose() and QEMUFile->close will return -errno on error, and any
    positive value on success.
    
    We need the positive non-zero success values because
    migration-exec.c:exec_close() relies on non-zero return values to get
    the process exit code.
    
    Changes v1 -> v2:
     - Cosmetic spelling change on comment text
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/hw.h b/hw/hw.h
index ed20f5a..efa04d1 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -27,7 +27,13 @@ typedef int (QEMUFilePutBufferFunc)(void *opaque, const uint8_t *buf,
 typedef int (QEMUFileGetBufferFunc)(void *opaque, uint8_t *buf,
                                     int64_t pos, int size);
 
-/* Close a file and return an error code */
+/* Close a file
+ *
+ * Return negative error number on error, 0 or positive value on success.
+ *
+ * The meaning of return value on success depends on the specific back-end being
+ * used.
+ */
 typedef int (QEMUFileCloseFunc)(void *opaque);
 
 /* Called to determine if the file has exceeded it's bandwidth allocation.  The
commit c29110d515babdff1f777189a84993b77722cd8f
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 10 10:41:39 2011 -0200

    savevm: use qemu_file_set_error() instead of setting last_error directly
    
    Some code uses qemu_file_set_error() already, so use it everywhere
    when setting last_error, for consistency.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/savevm.c b/savevm.c
index 1a21ab4..e121096 100644
--- a/savevm.c
+++ b/savevm.c
@@ -448,7 +448,7 @@ void qemu_fflush(QEMUFile *f)
         if (len > 0)
             f->buf_offset += f->buf_index;
         else
-            f->last_error = -EINVAL;
+            qemu_file_set_error(f, -EINVAL);
         f->buf_index = 0;
     }
 }
@@ -479,7 +479,7 @@ static void qemu_fill_buffer(QEMUFile *f)
     } else if (len == 0) {
         f->last_error = -EIO;
     } else if (len != -EAGAIN)
-        f->last_error = len;
+        qemu_file_set_error(f, len);
 }
 
 int qemu_fclose(QEMUFile *f)
commit 98d23704138e0be17a3ed9eb2631077bf92cc028
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 9 21:09:23 2011 +0000

    hw/usb-net.c: Fix precedence bug when checking rndis_state
    
    "!X == 2" is always false (spotted by Coverity), so the checks
    for whether rndis is in the correct state would never fire.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/usb-net.c b/hw/usb-net.c
index a8b7c8d..f91fa32 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1268,8 +1268,9 @@ static ssize_t usbnet_receive(VLANClientState *nc, const uint8_t *buf, size_t si
 
     if (is_rndis(s)) {
         msg = (struct rndis_packet_msg_type *) s->in_buf;
-        if (!s->rndis_state == RNDIS_DATA_INITIALIZED)
+        if (s->rndis_state != RNDIS_DATA_INITIALIZED) {
             return -1;
+        }
         if (size + sizeof(struct rndis_packet_msg_type) > sizeof(s->in_buf))
             return -1;
 
@@ -1302,7 +1303,7 @@ 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) {
+    if (is_rndis(s) && s->rndis_state != RNDIS_DATA_INITIALIZED) {
         return 1;
     }
 
commit 9fe2fd6716f1a6fbde1ef9867b64b6698d02b958
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Nov 4 12:03:38 2011 +1100

    Remove unnecessary casts from PCI DMA code in usb-uhci
    
    This patch removes some unnecessary casts in the usb-uhci device,
    introduced by commit fff23ee9a5de74ab111b3cea9eec56782e7d7c50
    'usb-uhci: Use PCI DMA stub functions'.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index f9e3ea5..f8912e2 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -876,7 +876,7 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet)
         uint32_t link = async->td;
         uint32_t int_mask = 0, val;
 
-        pci_dma_read(&s->dev, link & ~0xf, (uint8_t *) &td, sizeof(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);
@@ -888,8 +888,7 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet)
 
         /* update the status bits of the TD */
         val = cpu_to_le32(td.ctrl);
-        pci_dma_write(&s->dev, (link & ~0xf) + 4,
-                      (const uint8_t *)&val, sizeof(val));
+        pci_dma_write(&s->dev, (link & ~0xf) + 4, &val, sizeof(val));
         uhci_async_free(s, async);
     } else {
         async->done = 1;
@@ -952,7 +951,7 @@ static void uhci_process_frame(UHCIState *s)
 
     DPRINTF("uhci: processing frame %d addr 0x%x\n" , s->frnum, frame_addr);
 
-    pci_dma_read(&s->dev, frame_addr, (uint8_t *)&link, 4);
+    pci_dma_read(&s->dev, frame_addr, &link, 4);
     le32_to_cpus(&link);
 
     int_mask = 0;
@@ -976,7 +975,7 @@ static void uhci_process_frame(UHCIState *s)
                 break;
             }
 
-            pci_dma_read(&s->dev, link & ~0xf, (uint8_t *) &qh, sizeof(qh));
+            pci_dma_read(&s->dev, link & ~0xf, &qh, sizeof(qh));
             le32_to_cpus(&qh.link);
             le32_to_cpus(&qh.el_link);
 
@@ -996,7 +995,7 @@ static void uhci_process_frame(UHCIState *s)
         }
 
         /* TD */
-        pci_dma_read(&s->dev, link & ~0xf, (uint8_t *) &td, sizeof(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);
@@ -1010,8 +1009,7 @@ static void uhci_process_frame(UHCIState *s)
         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,
-                          (const uint8_t *)&val, sizeof(val));
+            pci_dma_write(&s->dev, (link & ~0xf) + 4, &val, sizeof(val));
         }
 
         if (ret < 0) {
@@ -1039,8 +1037,7 @@ static void uhci_process_frame(UHCIState *s)
 	    /* update QH element link */
             qh.el_link = link;
             val = cpu_to_le32(qh.el_link);
-            pci_dma_write(&s->dev, (curr_qh & ~0xf) + 4,
-                          (const uint8_t *)&val, sizeof(val));
+            pci_dma_write(&s->dev, (curr_qh & ~0xf) + 4, &val, sizeof(val));
 
             if (!depth_first(link)) {
                /* done with this QH */
commit 4bf8011910580376950dfed63214d1e0de4853eb
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Nov 4 12:03:37 2011 +1100

    Remove unnecessary casts from PCI DMA code in usb-ehci
    
    This patch removes some unnecessary casts in the usb-ehci device,
    introduced by commit 68d553587c0aa271c3eb2902921b503740d775b6
    'usb-ehci: Use PCI DMA stub functions'.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index a946e1d..7c926c0 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1109,7 +1109,7 @@ static inline int get_dwords(EHCIState *ehci, uint32_t addr,
     int i;
 
     for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
-        pci_dma_read(&ehci->dev, addr, (uint8_t *)buf, sizeof(*buf));
+        pci_dma_read(&ehci->dev, addr, buf, sizeof(*buf));
         *buf = le32_to_cpu(*buf);
     }
 
@@ -1124,7 +1124,7 @@ static inline int put_dwords(EHCIState *ehci, uint32_t addr,
 
     for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
         uint32_t tmp = cpu_to_le32(*buf);
-        pci_dma_write(&ehci->dev, addr, (uint8_t *)&tmp, sizeof(tmp));
+        pci_dma_write(&ehci->dev, addr, &tmp, sizeof(tmp));
     }
 
     return 1;
@@ -2157,7 +2157,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
         }
         list |= ((ehci->frindex & 0x1ff8) >> 1);
 
-        pci_dma_read(&ehci->dev, list, (uint8_t *) &entry, sizeof entry);
+        pci_dma_read(&ehci->dev, list, &entry, sizeof entry);
         entry = le32_to_cpu(entry);
 
         DPRINTF("PERIODIC state adv fr=%d.  [%08X] -> %08X\n",
commit a6a29eeaff88fafe344d072b6d9cd30649a46b36
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Nov 4 12:03:36 2011 +1100

    Remove unnecessary casts from PCI DMA code in rtl8139
    
    This patch removes some unnecessary casts in the rtl8139 device,
    introduced by commit 3ada003aee2004d24f23b9cd6f4eda87d9601ddb
    'rtl8139: Use PCI DMA stub functions'.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index aa8ed0a..bab6e61 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -991,13 +991,13 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 
         uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI;
 
-        pci_dma_read(&s->dev, cplus_rx_ring_desc, (uint8_t *)&val, 4);
+        pci_dma_read(&s->dev, cplus_rx_ring_desc, &val, 4);
         rxdw0 = le32_to_cpu(val);
-        pci_dma_read(&s->dev, cplus_rx_ring_desc+4, (uint8_t *)&val, 4);
+        pci_dma_read(&s->dev, cplus_rx_ring_desc+4, &val, 4);
         rxdw1 = le32_to_cpu(val);
-        pci_dma_read(&s->dev, cplus_rx_ring_desc+8, (uint8_t *)&val, 4);
+        pci_dma_read(&s->dev, cplus_rx_ring_desc+8, &val, 4);
         rxbufLO = le32_to_cpu(val);
-        pci_dma_read(&s->dev, cplus_rx_ring_desc+12, (uint8_t *)&val, 4);
+        pci_dma_read(&s->dev, cplus_rx_ring_desc+12, &val, 4);
         rxbufHI = le32_to_cpu(val);
 
         DPRINTF("+++ C+ mode RX descriptor %d %08x %08x %08x %08x\n",
commit 9e486d67656630c5a4490df85b6506ee0da9740a
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Nov 4 12:03:35 2011 +1100

    Remove unnecessary casts from PCI DMA code in lsi53c895a
    
    This patch removes some unnecessary casts in the lsi53c895a device,
    introduced by commit 9ba4524cda1348cbe741535f77815dca6a57da05
    'lsi53c895a: Use PCI DMA stub functions'.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index fcc27d7..0d3a101 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -392,7 +392,7 @@ static inline uint32_t read_dword(LSIState *s, uint32_t addr)
 {
     uint32_t buf;
 
-    pci_dma_read(&s->dev, addr, (uint8_t *)&buf, 4);
+    pci_dma_read(&s->dev, addr, &buf, 4);
     return cpu_to_le32(buf);
 }
 
@@ -1079,7 +1079,7 @@ again:
 
             /* 32-bit Table indirect */
             offset = sxt24(addr);
-            pci_dma_read(&s->dev, s->dsa + offset, (uint8_t *)buf, 8);
+            pci_dma_read(&s->dev, s->dsa + offset, buf, 8);
             /* byte count is stored in bits 0:23 only */
             s->dbc = cpu_to_le32(buf[0]) & 0xffffff;
             s->rbc = s->dbc;
commit 859e538d506cee75ebc24ab46247a0121d9c6d2b
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Nov 4 12:03:34 2011 +1100

    Remove unnecessary casts from PCI DMA code in PCI IDE
    
    This patch removes some unnecessary casts in the PCI IDE device,
    introduced by commit 552908fef5b67ad9d96b76d7cb8371ebc26c9bc8
    'PCI IDE: Use PCI DMA stub functions'.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 5078c0b..cb3de65 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -71,7 +71,7 @@ static int bmdma_prepare_buf(IDEDMA *dma, int is_write)
             if (bm->cur_prd_last ||
                 (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE)
                 return s->io_buffer_size != 0;
-            pci_dma_read(&bm->pci_dev->dev, bm->cur_addr, (uint8_t *)&prd, 8);
+            pci_dma_read(&bm->pci_dev->dev, bm->cur_addr, &prd, 8);
             bm->cur_addr += 8;
             prd.addr = le32_to_cpu(prd.addr);
             prd.size = le32_to_cpu(prd.size);
@@ -113,7 +113,7 @@ static int bmdma_rw_buf(IDEDMA *dma, int is_write)
             if (bm->cur_prd_last ||
                 (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE)
                 return 0;
-            pci_dma_read(&bm->pci_dev->dev, bm->cur_addr, (uint8_t *)&prd, 8);
+            pci_dma_read(&bm->pci_dev->dev, bm->cur_addr, &prd, 8);
             bm->cur_addr += 8;
             prd.addr = le32_to_cpu(prd.addr);
             prd.size = le32_to_cpu(prd.size);
commit 00c3a05b25533d7cb42b599509390fb1488d597c
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Nov 4 12:03:33 2011 +1100

    Remove unnecessary casts from PCI DMA code in e1000
    
    This patch removes some unnecessary casts in the e1000 device,
    introduced by commit 62ecbd353d25e62c4a6c327ea88ba5404e13507a 'e1000:
    Use PCI DMA stub functions'.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/e1000.c b/hw/e1000.c
index 986ed9c..a29c944 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -507,7 +507,7 @@ txdesc_writeback(E1000State *s, dma_addr_t base, struct e1000_tx_desc *dp)
                 ~(E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | E1000_TXD_STAT_TU);
     dp->upper.data = cpu_to_le32(txd_upper);
     pci_dma_write(&s->dev, base + ((char *)&dp->upper - (char *)dp),
-                  (void *)&dp->upper, sizeof(dp->upper));
+                  &dp->upper, sizeof(dp->upper));
     return E1000_ICR_TXDW;
 }
 
@@ -534,7 +534,7 @@ start_xmit(E1000State *s)
     while (s->mac_reg[TDH] != s->mac_reg[TDT]) {
         base = tx_desc_base(s) +
                sizeof(struct e1000_tx_desc) * s->mac_reg[TDH];
-        pci_dma_read(&s->dev, base, (void *)&desc, sizeof(desc));
+        pci_dma_read(&s->dev, base, &desc, sizeof(desc));
 
         DBGOUT(TX, "index %d: %p : %x %x\n", s->mac_reg[TDH],
                (void *)(intptr_t)desc.buffer_addr, desc.lower.data,
@@ -714,7 +714,7 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
             desc_size = s->rxbuf_size;
         }
         base = rx_desc_base(s) + sizeof(desc) * s->mac_reg[RDH];
-        pci_dma_read(&s->dev, base, (void *)&desc, sizeof(desc));
+        pci_dma_read(&s->dev, base, &desc, sizeof(desc));
         desc.special = vlan_special;
         desc.status |= (vlan_status | E1000_RXD_STAT_DD);
         if (desc.buffer_addr) {
@@ -724,8 +724,7 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
                     copy_size = s->rxbuf_size;
                 }
                 pci_dma_write(&s->dev, le64_to_cpu(desc.buffer_addr),
-                                 (void *)(buf + desc_offset + vlan_offset),
-                                 copy_size);
+                              buf + desc_offset + vlan_offset, copy_size);
             }
             desc_offset += desc_size;
             desc.length = cpu_to_le16(desc_size);
@@ -739,7 +738,7 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
         } else { // as per intel docs; skip descriptors with null buf addr
             DBGOUT(RX, "Null RX descriptor!!\n");
         }
-        pci_dma_write(&s->dev, base, (void *)&desc, sizeof(desc));
+        pci_dma_write(&s->dev, base, &desc, sizeof(desc));
 
         if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN])
             s->mac_reg[RDH] = 0;
commit e965d4bce3ebbb5a33bba24926a8f6ba0825994c
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Nov 4 12:03:32 2011 +1100

    Remove unnecessary casts from PCI DMA code in eepro100
    
    This patch removes some unnecessary casts in the eepro100 device,
    introduced by commit 16ef60c9a8eeee269f7cbc95219a431b1d7cbf29
    'eepro100: Use PCI DMA stub functions'.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/eepro100.c b/hw/eepro100.c
index 29ec5b4..17bcfd8 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -713,8 +713,7 @@ static void dump_statistics(EEPRO100State * s)
      * values which really matter.
      * Number of data should check configuration!!!
      */
-    pci_dma_write(&s->dev, s->statsaddr,
-                  (uint8_t *) &s->statistics, s->stats_size);
+    pci_dma_write(&s->dev, s->statsaddr, &s->statistics, s->stats_size);
     stl_le_pci_dma(&s->dev, s->statsaddr + 0,
                    s->statistics.tx_good_frames);
     stl_le_pci_dma(&s->dev, s->statsaddr + 36,
@@ -732,7 +731,7 @@ static void dump_statistics(EEPRO100State * s)
 
 static void read_cb(EEPRO100State *s)
 {
-    pci_dma_read(&s->dev, s->cb_address, (uint8_t *) &s->tx, sizeof(s->tx));
+    pci_dma_read(&s->dev, s->cb_address, &s->tx, sizeof(s->tx));
     s->tx.status = le16_to_cpu(s->tx.status);
     s->tx.command = le16_to_cpu(s->tx.command);
     s->tx.link = le32_to_cpu(s->tx.link);
@@ -1715,7 +1714,7 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
     /* !!! */
     eepro100_rx_t rx;
     pci_dma_read(&s->dev, s->ru_base + s->ru_offset,
-                 (uint8_t *) &rx, sizeof(eepro100_rx_t));
+                 &rx, sizeof(eepro100_rx_t));
     uint16_t rfd_command = le16_to_cpu(rx.command);
     uint16_t rfd_size = le16_to_cpu(rx.size);
 
commit ab23ebf48510c12d80f95b56f628afde3ca2c1c2
Merge: 9bf4896... 2a6ab1e...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 10:08:57 2011 -0600

    Merge remote-tracking branch 'pmaydell/arm-devs.for-upstream' into staging

commit 9bf4896e5d565785316d2c179be91fba11fbf3fb
Merge: 774d5c5... 3dc8538...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 12 10:08:08 2011 -0600

    Merge remote-tracking branch 'qmp/queue/qmp' into staging

commit 774d5c5b1604b8443a8e42048b370b6c95dbfc40
Author: Stefan Sandstrom <Stefan.Sandstrom at axis.com>
Date:   Mon Dec 12 11:38:31 2011 +0100

    cris: Handle conditional stores on CRISv10
    
    Signed-off-by: Stefan Sandstrom <Stefan.Sandstrom at axis.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index 8ae0ce3..453afbb 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -67,6 +67,8 @@
 #define Q_FLAG 0x80000000
 #define M_FLAG 0x40000000
 #define PFIX_FLAG 0x800      /* CRISv10 Only.  */
+#define F_FLAG_V10 0x400
+#define P_FLAG_V10 0x200
 #define S_FLAG 0x200
 #define R_FLAG 0x100
 #define P_FLAG 0x80
diff --git a/target-cris/helper.c b/target-cris/helper.c
index 75f0035..5bc6d81 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -157,6 +157,7 @@ static void do_interruptv10(CPUState *env)
 	/* Now that we are in kernel mode, load the handlers address.  */
 	env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4);
 	env->locked_irq = 1;
+	env->pregs[PR_CCS] |= F_FLAG_V10; /* set F.  */
 
 	qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n", 
 		      __func__, env->pc, ex_vec, 
diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c
index 637ac20..95053b6 100644
--- a/target-cris/translate_v10.c
+++ b/target-cris/translate_v10.c
@@ -62,6 +62,65 @@ static inline void cris_illegal_insn(DisasContext *dc)
     t_gen_raise_exception(EXCP_BREAK);
 }
 
+static void gen_store_v10_conditional(DisasContext *dc, TCGv addr, TCGv val,
+                       unsigned int size, int mem_index)
+{
+    int l1 = gen_new_label();
+    TCGv taddr = tcg_temp_local_new();
+    TCGv tval = tcg_temp_local_new();
+    TCGv t1 = tcg_temp_local_new();
+    dc->postinc = 0;
+    cris_evaluate_flags(dc);
+
+    tcg_gen_mov_tl(taddr, addr);
+    tcg_gen_mov_tl(tval, val);
+
+    /* Store only if F flag isn't set */
+    tcg_gen_andi_tl(t1, cpu_PR[PR_CCS], F_FLAG_V10);
+    tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+    if (size == 1) {
+        tcg_gen_qemu_st8(tval, taddr, mem_index);
+    } else if (size == 2) {
+        tcg_gen_qemu_st16(tval, taddr, mem_index);
+    } else {
+        tcg_gen_qemu_st32(tval, taddr, mem_index);
+    }
+    gen_set_label(l1);
+    tcg_gen_shri_tl(t1, t1, 1);  /* shift F to P position */
+    tcg_gen_or_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], t1); /*P=F*/
+    tcg_temp_free(t1);
+    tcg_temp_free(tval);
+    tcg_temp_free(taddr);
+}
+
+static void gen_store_v10(DisasContext *dc, TCGv addr, TCGv val,
+                       unsigned int size)
+{
+    int mem_index = cpu_mmu_index(dc->env);
+
+    /* If we get a fault on a delayslot we must keep the jmp state in
+       the cpu-state to be able to re-execute the jmp.  */
+    if (dc->delayed_branch == 1) {
+        cris_store_direct_jmp(dc);
+    }
+
+    /* Conditional writes. We only support the kind were X is known
+       at translation time.  */
+    if (dc->flagx_known && dc->flags_x) {
+        gen_store_v10_conditional(dc, addr, val, size, mem_index);
+        return;
+    }
+
+    if (size == 1) {
+        tcg_gen_qemu_st8(val, addr, mem_index);
+    } else if (size == 2) {
+        tcg_gen_qemu_st16(val, addr, mem_index);
+    } else {
+        tcg_gen_qemu_st32(val, addr, mem_index);
+    }
+}
+
+
 /* Prefix flag and register are used to handle the more complex
    addressing modes.  */
 static void cris_set_prefix(DisasContext *dc)
@@ -313,7 +372,8 @@ static unsigned int dec10_setclrf(DisasContext *dc)
     if (set) {
         tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags);
     } else {
-        tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags);
+        tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS],
+                        ~(flags|F_FLAG_V10|P_FLAG_V10));
     }
 
     dc->flags_uptodate = 1;
@@ -723,7 +783,7 @@ static unsigned int dec10_ind_move_r_m(DisasContext *dc, unsigned int size)
     LOG_DIS("move.%d $r%d, [$r%d]\n", dc->size, dc->src, dc->dst);
     addr = tcg_temp_new();
     crisv10_prepare_memaddr(dc, addr, size);
-    gen_store(dc, addr, cpu_R[dc->dst], size);
+    gen_store_v10(dc, addr, cpu_R[dc->dst], size);
     insn_len += crisv10_post_memaddr(dc, size);
 
     return insn_len;
@@ -767,10 +827,10 @@ static unsigned int dec10_ind_move_pr_m(DisasContext *dc)
         t0 = tcg_temp_new();
         cris_evaluate_flags(dc);
         tcg_gen_andi_tl(t0, cpu_PR[PR_CCS], ~PFIX_FLAG);
-        gen_store(dc, addr, t0, size);
+        gen_store_v10(dc, addr, t0, size);
         tcg_temp_free(t0);
     } else {
-        gen_store(dc, addr, cpu_PR[dc->dst], size);
+        gen_store_v10(dc, addr, cpu_PR[dc->dst], size);
     }
     t0 = tcg_temp_new();
     insn_len += crisv10_post_memaddr(dc, size);
@@ -793,9 +853,9 @@ static void dec10_movem_r_m(DisasContext *dc)
     tcg_gen_mov_tl(t0, addr);
     for (i = dc->dst; i >= 0; i--) {
         if ((pfix && dc->mode == CRISV10_MODE_AUTOINC) && dc->src == i) {
-            gen_store(dc, addr, t0, 4);
+            gen_store_v10(dc, addr, t0, 4);
         } else {
-            gen_store(dc, addr, cpu_R[i], 4);
+            gen_store_v10(dc, addr, cpu_R[i], 4);
         }
         tcg_gen_addi_tl(addr, addr, 4);
     }
commit 2a6ab1e368c07569b0d884634dcf9e9f7cbb6fca
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Dec 5 14:09:18 2011 +0000

    hw/mpcore.c: Merge with hw/arm11mpcore.c
    
    hw/mpcore.c is now implementing only ARM11MPCore specific peripherals,
    and is #included only from hw/arm11mpcore.c, so just merge it into that
    file.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index 32ecf98..bc0457e 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -7,11 +7,139 @@
  * This code is licensed under the GPL.
  */
 
+#include "sysbus.h"
+#include "qemu-timer.h"
+
 /* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
    (+ 32 internal).  However my test chip only exposes/reports 32.
    More importantly Linux falls over if more than 32 are present!  */
 #define GIC_NIRQ 64
-#include "mpcore.c"
+
+#define NCPU 4
+
+static inline int
+gic_get_current_cpu(void)
+{
+  return cpu_single_env->cpu_index;
+}
+
+#include "arm_gic.c"
+
+/* MPCore private memory region.  */
+
+typedef struct mpcore_priv_state {
+    gic_state gic;
+    uint32_t scu_control;
+    int iomemtype;
+    uint32_t old_timer_status[8];
+    uint32_t num_cpu;
+    qemu_irq *timer_irq;
+    MemoryRegion iomem;
+    MemoryRegion container;
+    DeviceState *mptimer;
+} mpcore_priv_state;
+
+/* Per-CPU private memory mapped IO.  */
+
+static uint64_t mpcore_scu_read(void *opaque, target_phys_addr_t offset,
+                                unsigned size)
+{
+    mpcore_priv_state *s = (mpcore_priv_state *)opaque;
+    int id;
+    offset &= 0xff;
+    /* SCU */
+    switch (offset) {
+    case 0x00: /* Control.  */
+        return s->scu_control;
+    case 0x04: /* Configuration.  */
+        id = ((1 << s->num_cpu) - 1) << 4;
+        return id | (s->num_cpu - 1);
+    case 0x08: /* CPU status.  */
+        return 0;
+    case 0x0c: /* Invalidate all.  */
+        return 0;
+    default:
+        hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
+    }
+}
+
+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.  */
+        s->scu_control = value & 1;
+        break;
+    case 0x0c: /* Invalidate all.  */
+        /* This is a no-op as cache is not emulated.  */
+        break;
+    default:
+        hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
+    }
+}
+
+static const MemoryRegionOps mpcore_scu_ops = {
+    .read = mpcore_scu_read,
+    .write = mpcore_scu_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void mpcore_timer_irq_handler(void *opaque, int irq, int level)
+{
+    mpcore_priv_state *s = (mpcore_priv_state *)opaque;
+    if (level && !s->old_timer_status[irq]) {
+        gic_set_pending_private(&s->gic, irq >> 1, 29 + (irq & 1));
+    }
+    s->old_timer_status[irq] = level;
+}
+
+static void mpcore_priv_map_setup(mpcore_priv_state *s)
+{
+    int i;
+    SysBusDevice *busdev = sysbus_from_qdev(s->mptimer);
+    memory_region_init(&s->container, "mpcode-priv-container", 0x2000);
+    memory_region_init_io(&s->iomem, &mpcore_scu_ops, s, "mpcore-scu", 0x100);
+    memory_region_add_subregion(&s->container, 0, &s->iomem);
+    /* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs
+     * at 0x200, 0x300...
+     */
+    for (i = 0; i < (s->num_cpu + 1); i++) {
+        target_phys_addr_t offset = 0x100 + (i * 0x100);
+        memory_region_add_subregion(&s->container, offset, &s->gic.cpuiomem[i]);
+    }
+    /* Add the regions for timer and watchdog for "current CPU" and
+     * for each specific CPU.
+     */
+    s->timer_irq = qemu_allocate_irqs(mpcore_timer_irq_handler,
+                                      s, (s->num_cpu + 1) * 2);
+    for (i = 0; i < (s->num_cpu + 1) * 2; i++) {
+        /* Timers at 0x600, 0x700, ...; watchdogs at 0x620, 0x720, ... */
+        target_phys_addr_t offset = 0x600 + (i >> 1) * 0x100 + (i & 1) * 0x20;
+        memory_region_add_subregion(&s->container, offset,
+                                    sysbus_mmio_get_region(busdev, i));
+    }
+    memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
+    /* Wire up the interrupt from each watchdog and timer. */
+    for (i = 0; i < s->num_cpu * 2; i++) {
+        sysbus_connect_irq(busdev, i, s->timer_irq[i]);
+    }
+}
+
+static int mpcore_priv_init(SysBusDevice *dev)
+{
+    mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
+
+    gic_init(&s->gic, s->num_cpu);
+    s->mptimer = qdev_create(NULL, "arm_mptimer");
+    qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
+    qdev_init_nofail(s->mptimer);
+    mpcore_priv_map_setup(s);
+    sysbus_init_mmio(dev, &s->container);
+    return 0;
+}
 
 /* Dummy PIC to route IRQ lines.  The baseboard has 4 independent IRQ
    controllers.  The output of these, plus some of the raw input lines
diff --git a/hw/mpcore.c b/hw/mpcore.c
deleted file mode 100644
index 670d7e5..0000000
--- a/hw/mpcore.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * ARM MPCore internal peripheral emulation (common code).
- *
- * Copyright (c) 2006-2007 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GPL.
- */
-
-#include "sysbus.h"
-#include "qemu-timer.h"
-
-#define NCPU 4
-
-static inline int
-gic_get_current_cpu(void)
-{
-  return cpu_single_env->cpu_index;
-}
-
-#include "arm_gic.c"
-
-/* MPCore private memory region.  */
-
-typedef struct mpcore_priv_state {
-    gic_state gic;
-    uint32_t scu_control;
-    int iomemtype;
-    uint32_t old_timer_status[8];
-    uint32_t num_cpu;
-    qemu_irq *timer_irq;
-    MemoryRegion iomem;
-    MemoryRegion container;
-    DeviceState *mptimer;
-} mpcore_priv_state;
-
-/* Per-CPU private memory mapped IO.  */
-
-static uint64_t mpcore_scu_read(void *opaque, target_phys_addr_t offset,
-                                unsigned size)
-{
-    mpcore_priv_state *s = (mpcore_priv_state *)opaque;
-    int id;
-    offset &= 0xff;
-    /* SCU */
-    switch (offset) {
-    case 0x00: /* Control.  */
-        return s->scu_control;
-    case 0x04: /* Configuration.  */
-        id = ((1 << s->num_cpu) - 1) << 4;
-        return id | (s->num_cpu - 1);
-    case 0x08: /* CPU status.  */
-        return 0;
-    case 0x0c: /* Invalidate all.  */
-        return 0;
-    default:
-        hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
-    }
-}
-
-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.  */
-        s->scu_control = value & 1;
-        break;
-    case 0x0c: /* Invalidate all.  */
-        /* This is a no-op as cache is not emulated.  */
-        break;
-    default:
-        hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
-    }
-}
-
-static const MemoryRegionOps mpcore_scu_ops = {
-    .read = mpcore_scu_read,
-    .write = mpcore_scu_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void mpcore_timer_irq_handler(void *opaque, int irq, int level)
-{
-    mpcore_priv_state *s = (mpcore_priv_state *)opaque;
-    if (level && !s->old_timer_status[irq]) {
-        gic_set_pending_private(&s->gic, irq >> 1, 29 + (irq & 1));
-    }
-    s->old_timer_status[irq] = level;
-}
-
-static void mpcore_priv_map_setup(mpcore_priv_state *s)
-{
-    int i;
-    SysBusDevice *busdev = sysbus_from_qdev(s->mptimer);
-    memory_region_init(&s->container, "mpcode-priv-container", 0x2000);
-    memory_region_init_io(&s->iomem, &mpcore_scu_ops, s, "mpcore-scu", 0x100);
-    memory_region_add_subregion(&s->container, 0, &s->iomem);
-    /* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs
-     * at 0x200, 0x300...
-     */
-    for (i = 0; i < (s->num_cpu + 1); i++) {
-        target_phys_addr_t offset = 0x100 + (i * 0x100);
-        memory_region_add_subregion(&s->container, offset, &s->gic.cpuiomem[i]);
-    }
-    /* Add the regions for timer and watchdog for "current CPU" and
-     * for each specific CPU.
-     */
-    s->timer_irq = qemu_allocate_irqs(mpcore_timer_irq_handler,
-                                      s, (s->num_cpu + 1) * 2);
-    for (i = 0; i < (s->num_cpu + 1) * 2; i++) {
-        /* Timers at 0x600, 0x700, ...; watchdogs at 0x620, 0x720, ... */
-        target_phys_addr_t offset = 0x600 + (i >> 1) * 0x100 + (i & 1) * 0x20;
-        memory_region_add_subregion(&s->container, offset,
-                                    sysbus_mmio_get_region(busdev, i));
-    }
-    memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
-    /* Wire up the interrupt from each watchdog and timer. */
-    for (i = 0; i < s->num_cpu * 2; i++) {
-        sysbus_connect_irq(busdev, i, s->timer_irq[i]);
-    }
-}
-
-static int mpcore_priv_init(SysBusDevice *dev)
-{
-    mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
-
-    gic_init(&s->gic, s->num_cpu);
-    s->mptimer = qdev_create(NULL, "arm_mptimer");
-    qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
-    qdev_init_nofail(s->mptimer);
-    mpcore_priv_map_setup(s);
-    sysbus_init_mmio(dev, &s->container);
-    return 0;
-}
commit b12080cd50f93642b3899068900b80bc867b1a38
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Dec 1 21:16:34 2011 +0000

    hw/a9mpcore.c: Implement A9MP peripherals rather than 11MPcore ones
    
    Implement the A9MP private peripheral region correctly, rather
    than piggybacking on the 11MPCore code; the two CPUs are not the
    same in this area.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 6f108f4..cd2985f 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -2,28 +2,197 @@
  * Cortex-A9MPCore internal peripheral emulation.
  *
  * Copyright (c) 2009 CodeSourcery.
- * Written by Paul Brook
+ * Copyright (c) 2011 Linaro Limited.
+ * Written by Paul Brook, Peter Maydell.
  *
  * This code is licensed under the GPL.
  */
 
-/* 64 external IRQ lines.  */
+#include "sysbus.h"
+
+/* Configuration for arm_gic.c:
+ * number of external IRQ lines, max number of CPUs, how to ID current CPU
+ */
 #define GIC_NIRQ 96
-#include "mpcore.c"
+#define NCPU 4
+
+static inline int
+gic_get_current_cpu(void)
+{
+  return cpu_single_env->cpu_index;
+}
+
+#include "arm_gic.c"
+
+/* A9MP private memory region.  */
+
+typedef struct a9mp_priv_state {
+    gic_state gic;
+    uint32_t scu_control;
+    uint32_t old_timer_status[8];
+    uint32_t num_cpu;
+    qemu_irq *timer_irq;
+    MemoryRegion scu_iomem;
+    MemoryRegion ptimer_iomem;
+    MemoryRegion container;
+    DeviceState *mptimer;
+} a9mp_priv_state;
+
+static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset,
+                            unsigned size)
+{
+    a9mp_priv_state *s = (a9mp_priv_state *)opaque;
+    switch (offset) {
+    case 0x00: /* Control */
+        return s->scu_control;
+    case 0x04: /* Configuration */
+        return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1);
+    case 0x08: /* CPU Power Status */
+        return 0;
+    case 0x0c: /* Invalidate All Registers In Secure State */
+        return 0;
+    case 0x40: /* Filtering Start Address Register */
+    case 0x44: /* Filtering End Address Register */
+        /* RAZ/WI, like an implementation with only one AXI master */
+        return 0;
+    case 0x50: /* SCU Access Control Register */
+    case 0x54: /* SCU Non-secure Access Control Register */
+        /* unimplemented, fall through */
+    default:
+        return 0;
+    }
+}
+
+static void a9_scu_write(void *opaque, target_phys_addr_t offset,
+                         uint64_t value, unsigned size)
+{
+    a9mp_priv_state *s = (a9mp_priv_state *)opaque;
+    switch (offset) {
+    case 0x00: /* Control */
+        s->scu_control = value & 1;
+        break;
+    case 0x4: /* Configuration: RO */
+        break;
+    case 0x0c: /* Invalidate All Registers In Secure State */
+        /* no-op as we do not implement caches */
+        break;
+    case 0x40: /* Filtering Start Address Register */
+    case 0x44: /* Filtering End Address Register */
+        /* RAZ/WI, like an implementation with only one AXI master */
+        break;
+    case 0x8: /* CPU Power Status */
+    case 0x50: /* SCU Access Control Register */
+    case 0x54: /* SCU Non-secure Access Control Register */
+        /* unimplemented, fall through */
+    default:
+        break;
+    }
+}
+
+static const MemoryRegionOps a9_scu_ops = {
+    .read = a9_scu_read,
+    .write = a9_scu_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void a9mpcore_timer_irq_handler(void *opaque, int irq, int level)
+{
+    a9mp_priv_state *s = (a9mp_priv_state *)opaque;
+    if (level && !s->old_timer_status[irq]) {
+        gic_set_pending_private(&s->gic, irq >> 1, 29 + (irq & 1));
+    }
+    s->old_timer_status[irq] = level;
+}
+
+static void a9mp_priv_reset(DeviceState *dev)
+{
+    a9mp_priv_state *s = FROM_SYSBUSGIC(a9mp_priv_state, sysbus_from_qdev(dev));
+    int i;
+    s->scu_control = 0;
+    for (i = 0; i < ARRAY_SIZE(s->old_timer_status); i++) {
+        s->old_timer_status[i] = 0;
+    }
+}
+
+static int a9mp_priv_init(SysBusDevice *dev)
+{
+    a9mp_priv_state *s = FROM_SYSBUSGIC(a9mp_priv_state, dev);
+    SysBusDevice *busdev;
+    int i;
+
+    if (s->num_cpu > NCPU) {
+        hw_error("a9mp_priv_init: num-cpu may not be more than %d\n", NCPU);
+    }
+
+    gic_init(&s->gic, s->num_cpu);
+
+    s->mptimer = qdev_create(NULL, "arm_mptimer");
+    qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
+    qdev_init_nofail(s->mptimer);
+    busdev = sysbus_from_qdev(s->mptimer);
+
+    /* Memory map (addresses are offsets from PERIPHBASE):
+     *  0x0000-0x00ff -- Snoop Control Unit
+     *  0x0100-0x01ff -- GIC CPU interface
+     *  0x0200-0x02ff -- Global Timer
+     *  0x0300-0x05ff -- nothing
+     *  0x0600-0x06ff -- private timers and watchdogs
+     *  0x0700-0x0fff -- nothing
+     *  0x1000-0x1fff -- GIC Distributor
+     *
+     * We should implement the global timer but don't currently do so.
+     */
+    memory_region_init(&s->container, "a9mp-priv-container", 0x2000);
+    memory_region_init_io(&s->scu_iomem, &a9_scu_ops, s, "a9mp-scu", 0x100);
+    memory_region_add_subregion(&s->container, 0, &s->scu_iomem);
+    /* GIC CPU interface */
+    memory_region_add_subregion(&s->container, 0x100, &s->gic.cpuiomem[0]);
+    /* Note that the A9 exposes only the "timer/watchdog for this core"
+     * memory region, not the "timer/watchdog for core X" ones 11MPcore has.
+     */
+    memory_region_add_subregion(&s->container, 0x600,
+                                sysbus_mmio_get_region(busdev, 0));
+    memory_region_add_subregion(&s->container, 0x620,
+                                sysbus_mmio_get_region(busdev, 1));
+    memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
+
+    sysbus_init_mmio(dev, &s->container);
+
+    /* Wire up the interrupt from each watchdog and timer. */
+    s->timer_irq = qemu_allocate_irqs(a9mpcore_timer_irq_handler,
+                                      s, (s->num_cpu + 1) * 2);
+    for (i = 0; i < s->num_cpu * 2; i++) {
+        sysbus_connect_irq(busdev, i, s->timer_irq[i]);
+    }
+    return 0;
+}
+
+static const VMStateDescription vmstate_a9mp_priv = {
+    .name = "a9mpcore_priv",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(scu_control, a9mp_priv_state),
+        VMSTATE_UINT32_ARRAY(old_timer_status, a9mp_priv_state, 8),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
-static SysBusDeviceInfo mpcore_priv_info = {
-    .init = mpcore_priv_init,
+static SysBusDeviceInfo a9mp_priv_info = {
+    .init = a9mp_priv_init,
     .qdev.name  = "a9mpcore_priv",
-    .qdev.size  = sizeof(mpcore_priv_state),
+    .qdev.size  = sizeof(a9mp_priv_state),
+    .qdev.vmsd = &vmstate_a9mp_priv,
+    .qdev.reset = a9mp_priv_reset,
     .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
+        DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
 
-static void a9mpcore_register_devices(void)
+static void a9mp_register_devices(void)
 {
-    sysbus_register_withprop(&mpcore_priv_info);
+    sysbus_register_withprop(&a9mp_priv_info);
 }
 
-device_init(a9mpcore_register_devices)
+device_init(a9mp_register_devices)
commit 538ddf65779519794f8c4e39b25ca49b47568750
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Dec 5 13:49:18 2011 +0000

    hw/mpcore: Clean up mpcore_priv_read/write as they are now SCU only
    
    The only code left in mpcore_priv_read and mpcore_priv_write is now
    the implementation of the SCU registers. Clean up by renaming functions
    and removing some unnecessary conditionals to make this clearer.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/mpcore.c b/hw/mpcore.c
index a0af1ad..670d7e5 100644
--- a/hw/mpcore.c
+++ b/hw/mpcore.c
@@ -36,59 +36,49 @@ typedef struct mpcore_priv_state {
 
 /* Per-CPU private memory mapped IO.  */
 
-static uint64_t mpcore_priv_read(void *opaque, target_phys_addr_t offset,
-                                 unsigned size)
+static uint64_t mpcore_scu_read(void *opaque, target_phys_addr_t offset,
+                                unsigned size)
 {
     mpcore_priv_state *s = (mpcore_priv_state *)opaque;
     int id;
     offset &= 0xff;
-    if (offset < 0x100) {
-        /* SCU */
-        switch (offset) {
-        case 0x00: /* Control.  */
-            return s->scu_control;
-        case 0x04: /* Configuration.  */
-            id = ((1 << s->num_cpu) - 1) << 4;
-            return id | (s->num_cpu - 1);
-        case 0x08: /* CPU status.  */
-            return 0;
-        case 0x0c: /* Invalidate all.  */
-            return 0;
-        default:
-            goto bad_reg;
-        }
+    /* SCU */
+    switch (offset) {
+    case 0x00: /* Control.  */
+        return s->scu_control;
+    case 0x04: /* Configuration.  */
+        id = ((1 << s->num_cpu) - 1) << 4;
+        return id | (s->num_cpu - 1);
+    case 0x08: /* CPU status.  */
+        return 0;
+    case 0x0c: /* Invalidate all.  */
+        return 0;
+    default:
+        hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
     }
-bad_reg:
-    hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
-    return 0;
 }
 
-static void mpcore_priv_write(void *opaque, target_phys_addr_t offset,
-                              uint64_t value, unsigned size)
+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;
-    if (offset < 0x100) {
-        /* SCU */
-        switch (offset) {
-        case 0: /* Control register.  */
-            s->scu_control = value & 1;
-            break;
-        case 0x0c: /* Invalidate all.  */
-            /* This is a no-op as cache is not emulated.  */
-            break;
-        default:
-            goto bad_reg;
-        }
+    /* SCU */
+    switch (offset) {
+    case 0: /* Control register.  */
+        s->scu_control = value & 1;
+        break;
+    case 0x0c: /* Invalidate all.  */
+        /* This is a no-op as cache is not emulated.  */
+        break;
+    default:
+        hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
     }
-    return;
-bad_reg:
-    hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
 }
 
-static const MemoryRegionOps mpcore_priv_ops = {
-    .read = mpcore_priv_read,
-    .write = mpcore_priv_write,
+static const MemoryRegionOps mpcore_scu_ops = {
+    .read = mpcore_scu_read,
+    .write = mpcore_scu_write,
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
@@ -106,8 +96,7 @@ static void mpcore_priv_map_setup(mpcore_priv_state *s)
     int i;
     SysBusDevice *busdev = sysbus_from_qdev(s->mptimer);
     memory_region_init(&s->container, "mpcode-priv-container", 0x2000);
-    memory_region_init_io(&s->iomem, &mpcore_priv_ops, s, "mpcode-priv",
-                          0x100);
+    memory_region_init_io(&s->iomem, &mpcore_scu_ops, s, "mpcore-scu", 0x100);
     memory_region_add_subregion(&s->container, 0, &s->iomem);
     /* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs
      * at 0x200, 0x300...
commit c3ffa5953abcb06decf2a02226fc5a9cc5e1ffe9
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Dec 5 13:44:14 2011 +0000

    hw/realview_gic: Use GIC memory region for the CPU interface
    
    Use the GIC provided memory region for the CPU interface rather
    than implementing our own.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 479f939..8c4d509 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -23,36 +23,13 @@ gic_get_current_cpu(void)
 
 typedef struct {
     gic_state gic;
-    MemoryRegion iomem;
     MemoryRegion container;
 } RealViewGICState;
 
-static uint64_t realview_gic_cpu_read(void *opaque, target_phys_addr_t offset,
-                                      unsigned size)
-{
-    gic_state *s = (gic_state *)opaque;
-    return gic_cpu_read(s, gic_get_current_cpu(), offset);
-}
-
-static void realview_gic_cpu_write(void *opaque, target_phys_addr_t offset,
-                                   uint64_t value, unsigned size)
-{
-    gic_state *s = (gic_state *)opaque;
-    gic_cpu_write(s, gic_get_current_cpu(), offset, value);
-}
-
-static const MemoryRegionOps realview_gic_cpu_ops = {
-    .read = realview_gic_cpu_read,
-    .write = realview_gic_cpu_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
 static void realview_gic_map_setup(RealViewGICState *s)
 {
     memory_region_init(&s->container, "realview-gic-container", 0x2000);
-    memory_region_init_io(&s->iomem, &realview_gic_cpu_ops, &s->gic,
-                          "realview-gic", 0x1000);
-    memory_region_add_subregion(&s->container, 0, &s->iomem);
+    memory_region_add_subregion(&s->container, 0, &s->gic.cpuiomem[0]);
     memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
 }
 
commit 2206d2a6aa435d9fc81bfb4b412e4de269a3b78d
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Dec 5 13:43:26 2011 +0000

    hw/mpcore.c: Use the GIC memory regions for the CPU interface
    
    Switch to using the GIC memory regions for the CPU interface
    rather than hand implementing them as a subcase of mpcore_priv_read()
    and mpcore_priv_write().
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/mpcore.c b/hw/mpcore.c
index 3d64609..a0af1ad 100644
--- a/hw/mpcore.c
+++ b/hw/mpcore.c
@@ -41,7 +41,7 @@ static uint64_t mpcore_priv_read(void *opaque, target_phys_addr_t offset,
 {
     mpcore_priv_state *s = (mpcore_priv_state *)opaque;
     int id;
-    offset &= 0xfff;
+    offset &= 0xff;
     if (offset < 0x100) {
         /* SCU */
         switch (offset) {
@@ -57,17 +57,6 @@ static uint64_t mpcore_priv_read(void *opaque, target_phys_addr_t offset,
         default:
             goto bad_reg;
         }
-    } else if (offset < 0x600) {
-        /* Interrupt controller.  */
-        if (offset < 0x200) {
-            id = gic_get_current_cpu();
-        } else {
-            id = (offset - 0x200) >> 8;
-            if (id >= s->num_cpu) {
-                return 0;
-            }
-        }
-        return gic_cpu_read(&s->gic, id, offset & 0xff);
     }
 bad_reg:
     hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
@@ -78,8 +67,7 @@ static void mpcore_priv_write(void *opaque, target_phys_addr_t offset,
                               uint64_t value, unsigned size)
 {
     mpcore_priv_state *s = (mpcore_priv_state *)opaque;
-    int id;
-    offset &= 0xfff;
+    offset &= 0xff;
     if (offset < 0x100) {
         /* SCU */
         switch (offset) {
@@ -92,16 +80,6 @@ static void mpcore_priv_write(void *opaque, target_phys_addr_t offset,
         default:
             goto bad_reg;
         }
-    } else if (offset < 0x600) {
-        /* Interrupt controller.  */
-        if (offset < 0x200) {
-            id = gic_get_current_cpu();
-        } else {
-            id = (offset - 0x200) >> 8;
-        }
-        if (id < s->num_cpu) {
-            gic_cpu_write(&s->gic, id, offset & 0xff, value);
-        }
     }
     return;
 bad_reg:
@@ -129,8 +107,15 @@ static void mpcore_priv_map_setup(mpcore_priv_state *s)
     SysBusDevice *busdev = sysbus_from_qdev(s->mptimer);
     memory_region_init(&s->container, "mpcode-priv-container", 0x2000);
     memory_region_init_io(&s->iomem, &mpcore_priv_ops, s, "mpcode-priv",
-                          0x1000);
+                          0x100);
     memory_region_add_subregion(&s->container, 0, &s->iomem);
+    /* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs
+     * at 0x200, 0x300...
+     */
+    for (i = 0; i < (s->num_cpu + 1); i++) {
+        target_phys_addr_t offset = 0x100 + (i * 0x100);
+        memory_region_add_subregion(&s->container, offset, &s->gic.cpuiomem[i]);
+    }
     /* Add the regions for timer and watchdog for "current CPU" and
      * for each specific CPU.
      */
commit e2c564657c1ad9fec1e885efcd47c2b8e0d37b05
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Dec 5 12:52:33 2011 +0000

    hw/arm_gic: Expose GIC CPU interfaces as sysbus memory regions
    
    Expose the ARM GIC CPU interfaces as memory regions, rather than
    just providing read and write functions for them.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 527c9ce..66c48fd 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -103,7 +103,14 @@ typedef struct gic_state
     int num_cpu;
 #endif
 
-    MemoryRegion iomem;
+    MemoryRegion iomem; /* Distributor */
+#ifndef NVIC
+    /* This is just so we can have an opaque pointer which identifies
+     * both this GIC and which CPU interface we should be accessing.
+     */
+    struct gic_state *backref[NCPU];
+    MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
+#endif
 } gic_state;
 
 /* TODO: Many places that call this routine could be optimized.  */
@@ -633,6 +640,54 @@ static void gic_cpu_write(gic_state *s, int cpu, int offset, uint32_t value)
     }
     gic_update(s);
 }
+
+/* Wrappers to read/write the GIC CPU interface for the current CPU */
+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);
+}
+
+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);
+}
+
+/* Wrappers to read/write the GIC CPU interface for a specific CPU.
+ * These just decode the opaque pointer into gic_state* + cpu id.
+ */
+static uint64_t gic_do_cpu_read(void *opaque, target_phys_addr_t addr,
+                                unsigned size)
+{
+    gic_state **backref = (gic_state **)opaque;
+    gic_state *s = *backref;
+    int id = (backref - s->backref);
+    return gic_cpu_read(s, id, addr & 0xff);
+}
+
+static void gic_do_cpu_write(void *opaque, target_phys_addr_t addr,
+                             uint64_t value, unsigned size)
+{
+    gic_state **backref = (gic_state **)opaque;
+    gic_state *s = *backref;
+    int id = (backref - s->backref);
+    gic_cpu_write(s, id, addr & 0xff, value);
+}
+
+static const MemoryRegionOps gic_thiscpu_ops = {
+    .read = gic_thiscpu_read,
+    .write = gic_thiscpu_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const MemoryRegionOps gic_cpu_ops = {
+    .read = gic_do_cpu_read,
+    .write = gic_do_cpu_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
 #endif
 
 static void gic_reset(gic_state *s)
@@ -752,6 +807,24 @@ static void gic_init(gic_state *s)
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }
     memory_region_init_io(&s->iomem, &gic_dist_ops, s, "gic_dist", 0x1000);
+#ifndef NVIC
+    /* Memory regions for the CPU interfaces (NVIC doesn't have these):
+     * a region for "CPU interface for this core", then a region for
+     * "CPU interface for core 0", "for core 1", ...
+     * NB that the memory region size of 0x100 applies for the 11MPCore
+     * and also cores following the GIC v1 spec (ie A9).
+     * GIC v2 defines a larger memory region (0x1000) so this will need
+     * to be extended when we implement A15.
+     */
+    memory_region_init_io(&s->cpuiomem[0], &gic_thiscpu_ops, s,
+                          "gic_cpu", 0x100);
+    for (i = 0; i < NUM_CPU(s); i++) {
+        s->backref[i] = s;
+        memory_region_init_io(&s->cpuiomem[i+1], &gic_cpu_ops, &s->backref[i],
+                              "gic_cpu", 0x100);
+    }
+#endif
+
     gic_reset(s);
     register_savevm(NULL, "arm_gic", -1, 2, gic_save, gic_load, s);
 }
commit b9dc07d42a08952926c35f07d1323381e2b707b5
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Dec 5 15:47:49 2011 +0000

    hw/arm_mptimer.c: Turn ARM MPcore private timers into qdev devices
    
    Turn the ARM MPcore private timer/watchdog blocks into separate
    qdev devices. This will allow us to share them neatly between
    11MPCore and A9MPcore.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/Makefile.target b/Makefile.target
index a111521..39b2e5a 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -344,6 +344,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 += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
+obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
 obj-arm-y += pl061.o
 obj-arm-y += arm-semi.o
diff --git a/hw/arm_mptimer.c b/hw/arm_mptimer.c
new file mode 100644
index 0000000..455a0aa
--- /dev/null
+++ b/hw/arm_mptimer.c
@@ -0,0 +1,332 @@
+/*
+ * Private peripheral timer/watchdog blocks for ARM 11MPCore and A9MP
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Copyright (c) 2011 Linaro Limited
+ * Written by Paul Brook, Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sysbus.h"
+#include "qemu-timer.h"
+
+/* This device implements the per-cpu private timer and watchdog block
+ * which is used in both the ARM11MPCore and Cortex-A9MP.
+ */
+
+#define MAX_CPUS 4
+
+/* State of a single timer or watchdog block */
+typedef struct {
+    uint32_t count;
+    uint32_t load;
+    uint32_t control;
+    uint32_t status;
+    int64_t tick;
+    QEMUTimer *timer;
+    qemu_irq irq;
+    MemoryRegion iomem;
+} timerblock;
+
+typedef struct {
+    SysBusDevice busdev;
+    uint32_t num_cpu;
+    timerblock timerblock[MAX_CPUS * 2];
+    MemoryRegion iomem[2];
+} arm_mptimer_state;
+
+static inline int get_current_cpu(arm_mptimer_state *s)
+{
+    if (cpu_single_env->cpu_index >= s->num_cpu) {
+        hw_error("arm_mptimer: num-cpu %d but this cpu is %d!\n",
+                 s->num_cpu, cpu_single_env->cpu_index);
+    }
+    return cpu_single_env->cpu_index;
+}
+
+static inline void timerblock_update_irq(timerblock *tb)
+{
+    qemu_set_irq(tb->irq, tb->status);
+}
+
+/* Return conversion factor from mpcore timer ticks to qemu timer ticks.  */
+static inline uint32_t timerblock_scale(timerblock *tb)
+{
+    return (((tb->control >> 8) & 0xff) + 1) * 10;
+}
+
+static void timerblock_reload(timerblock *tb, int restart)
+{
+    if (tb->count == 0) {
+        return;
+    }
+    if (restart) {
+        tb->tick = qemu_get_clock_ns(vm_clock);
+    }
+    tb->tick += (int64_t)tb->count * timerblock_scale(tb);
+    qemu_mod_timer(tb->timer, tb->tick);
+}
+
+static void timerblock_tick(void *opaque)
+{
+    timerblock *tb = (timerblock *)opaque;
+    tb->status = 1;
+    if (tb->control & 2) {
+        tb->count = tb->load;
+        timerblock_reload(tb, 0);
+    } else {
+        tb->count = 0;
+    }
+    timerblock_update_irq(tb);
+}
+
+static uint64_t timerblock_read(void *opaque, target_phys_addr_t addr,
+                                unsigned size)
+{
+    timerblock *tb = (timerblock *)opaque;
+    int64_t val;
+    addr &= 0x1f;
+    switch (addr) {
+    case 0: /* Load */
+        return tb->load;
+    case 4: /* Counter.  */
+        if (((tb->control & 1) == 0) || (tb->count == 0)) {
+            return 0;
+        }
+        /* Slow and ugly, but hopefully won't happen too often.  */
+        val = tb->tick - qemu_get_clock_ns(vm_clock);
+        val /= timerblock_scale(tb);
+        if (val < 0) {
+            val = 0;
+        }
+        return val;
+    case 8: /* Control.  */
+        return tb->control;
+    case 12: /* Interrupt status.  */
+        return tb->status;
+    default:
+        return 0;
+    }
+}
+
+static void timerblock_write(void *opaque, target_phys_addr_t addr,
+                             uint64_t value, unsigned size)
+{
+    timerblock *tb = (timerblock *)opaque;
+    int64_t old;
+    addr &= 0x1f;
+    switch (addr) {
+    case 0: /* Load */
+        tb->load = value;
+        /* Fall through.  */
+    case 4: /* Counter.  */
+        if ((tb->control & 1) && tb->count) {
+            /* Cancel the previous timer.  */
+            qemu_del_timer(tb->timer);
+        }
+        tb->count = value;
+        if (tb->control & 1) {
+            timerblock_reload(tb, 1);
+        }
+        break;
+    case 8: /* Control.  */
+        old = tb->control;
+        tb->control = value;
+        if (((old & 1) == 0) && (value & 1)) {
+            if (tb->count == 0 && (tb->control & 2)) {
+                tb->count = tb->load;
+            }
+            timerblock_reload(tb, 1);
+        }
+        break;
+    case 12: /* Interrupt status.  */
+        tb->status &= ~value;
+        timerblock_update_irq(tb);
+        break;
+    }
+}
+
+/* Wrapper functions to implement the "read timer/watchdog for
+ * the current CPU" memory regions.
+ */
+static uint64_t arm_thistimer_read(void *opaque, target_phys_addr_t addr,
+                                   unsigned size)
+{
+    arm_mptimer_state *s = (arm_mptimer_state *)opaque;
+    int id = get_current_cpu(s);
+    return timerblock_read(&s->timerblock[id * 2], addr, size);
+}
+
+static void arm_thistimer_write(void *opaque, target_phys_addr_t addr,
+                                uint64_t value, unsigned size)
+{
+    arm_mptimer_state *s = (arm_mptimer_state *)opaque;
+    int id = get_current_cpu(s);
+    timerblock_write(&s->timerblock[id * 2], addr, value, size);
+}
+
+static uint64_t arm_thiswdog_read(void *opaque, target_phys_addr_t addr,
+                                  unsigned size)
+{
+    arm_mptimer_state *s = (arm_mptimer_state *)opaque;
+    int id = get_current_cpu(s);
+    return timerblock_read(&s->timerblock[id * 2 + 1], addr, size);
+}
+
+static void arm_thiswdog_write(void *opaque, target_phys_addr_t addr,
+                               uint64_t value, unsigned size)
+{
+    arm_mptimer_state *s = (arm_mptimer_state *)opaque;
+    int id = get_current_cpu(s);
+    timerblock_write(&s->timerblock[id * 2 + 1], addr, value, size);
+}
+
+static const MemoryRegionOps arm_thistimer_ops = {
+    .read = arm_thistimer_read,
+    .write = arm_thistimer_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const MemoryRegionOps arm_thiswdog_ops = {
+    .read = arm_thiswdog_read,
+    .write = arm_thiswdog_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const MemoryRegionOps timerblock_ops = {
+    .read = timerblock_read,
+    .write = timerblock_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void timerblock_reset(timerblock *tb)
+{
+    tb->count = 0;
+    tb->load = 0;
+    tb->control = 0;
+    tb->status = 0;
+    tb->tick = 0;
+}
+
+static void arm_mptimer_reset(DeviceState *dev)
+{
+    arm_mptimer_state *s =
+        FROM_SYSBUS(arm_mptimer_state, sysbus_from_qdev(dev));
+    int i;
+    /* We reset every timer in the array, not just the ones we're using,
+     * because vmsave will look at every array element.
+     */
+    for (i = 0; i < ARRAY_SIZE(s->timerblock); i++) {
+        timerblock_reset(&s->timerblock[i]);
+    }
+}
+
+static int arm_mptimer_init(SysBusDevice *dev)
+{
+    arm_mptimer_state *s = FROM_SYSBUS(arm_mptimer_state, dev);
+    int i;
+    if (s->num_cpu < 1 || s->num_cpu > MAX_CPUS) {
+        hw_error("%s: num-cpu must be between 1 and %d\n", __func__, MAX_CPUS);
+    }
+    /* We implement one timer and one watchdog block per CPU, and
+     * expose multiple MMIO regions:
+     *  * region 0 is "timer for this core"
+     *  * region 1 is "watchdog for this core"
+     *  * region 2 is "timer for core 0"
+     *  * region 3 is "watchdog for core 0"
+     *  * region 4 is "timer for core 1"
+     *  * region 5 is "watchdog for core 1"
+     * and so on.
+     * The outgoing interrupt lines are
+     *  * timer for core 0
+     *  * watchdog for core 0
+     *  * timer for core 1
+     *  * watchdog for core 1
+     * and so on.
+     */
+    memory_region_init_io(&s->iomem[0], &arm_thistimer_ops, s,
+                          "arm_mptimer_timer", 0x20);
+    sysbus_init_mmio(dev, &s->iomem[0]);
+    memory_region_init_io(&s->iomem[1], &arm_thiswdog_ops, s,
+                          "arm_mptimer_wdog", 0x20);
+    sysbus_init_mmio(dev, &s->iomem[1]);
+    for (i = 0; i < (s->num_cpu * 2); i++) {
+        timerblock *tb = &s->timerblock[i];
+        tb->timer = qemu_new_timer_ns(vm_clock, timerblock_tick, tb);
+        sysbus_init_irq(dev, &tb->irq);
+        memory_region_init_io(&tb->iomem, &timerblock_ops, tb,
+                              "arm_mptimer_timerblock", 0x20);
+        sysbus_init_mmio(dev, &tb->iomem);
+    }
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_timerblock = {
+    .name = "arm_mptimer_timerblock",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(count, timerblock),
+        VMSTATE_UINT32(load, timerblock),
+        VMSTATE_UINT32(control, timerblock),
+        VMSTATE_UINT32(status, timerblock),
+        VMSTATE_INT64(tick, timerblock),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_arm_mptimer = {
+    .name = "arm_mptimer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT_ARRAY(timerblock, arm_mptimer_state, (MAX_CPUS * 2),
+                             1, vmstate_timerblock, timerblock),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo arm_mptimer_info = {
+    .init = arm_mptimer_init,
+    .qdev.name = "arm_mptimer",
+    .qdev.size = sizeof(arm_mptimer_state),
+    .qdev.vmsd = &vmstate_arm_mptimer,
+    .qdev.reset = arm_mptimer_reset,
+    .qdev.no_user = 1,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("num-cpu", arm_mptimer_state, num_cpu, 0),
+        DEFINE_PROP_END_OF_LIST()
+    }
+};
+
+static void arm_mptimer_register_devices(void)
+{
+    sysbus_register_withprop(&arm_mptimer_info);
+}
+
+device_init(arm_mptimer_register_devices)
diff --git a/hw/mpcore.c b/hw/mpcore.c
index 4357d12..3d64609 100644
--- a/hw/mpcore.c
+++ b/hw/mpcore.c
@@ -22,135 +22,18 @@ gic_get_current_cpu(void)
 
 /* MPCore private memory region.  */
 
-typedef struct {
-    uint32_t count;
-    uint32_t load;
-    uint32_t control;
-    uint32_t status;
-    uint32_t old_status;
-    int64_t tick;
-    QEMUTimer *timer;
-    struct mpcore_priv_state *mpcore;
-    int id; /* Encodes both timer/watchdog and CPU.  */
-} mpcore_timer_state;
-
 typedef struct mpcore_priv_state {
     gic_state gic;
     uint32_t scu_control;
     int iomemtype;
-    mpcore_timer_state timer[8];
+    uint32_t old_timer_status[8];
     uint32_t num_cpu;
+    qemu_irq *timer_irq;
     MemoryRegion iomem;
     MemoryRegion container;
+    DeviceState *mptimer;
 } mpcore_priv_state;
 
-/* Per-CPU Timers.  */
-
-static inline void mpcore_timer_update_irq(mpcore_timer_state *s)
-{
-    if (s->status & ~s->old_status) {
-        gic_set_pending_private(&s->mpcore->gic, s->id >> 1, 29 + (s->id & 1));
-    }
-    s->old_status = s->status;
-}
-
-/* Return conversion factor from mpcore timer ticks to qemu timer ticks.  */
-static inline uint32_t mpcore_timer_scale(mpcore_timer_state *s)
-{
-    return (((s->control >> 8) & 0xff) + 1) * 10;
-}
-
-static void mpcore_timer_reload(mpcore_timer_state *s, int restart)
-{
-    if (s->count == 0)
-        return;
-    if (restart)
-        s->tick = qemu_get_clock_ns(vm_clock);
-    s->tick += (int64_t)s->count * mpcore_timer_scale(s);
-    qemu_mod_timer(s->timer, s->tick);
-}
-
-static void mpcore_timer_tick(void *opaque)
-{
-    mpcore_timer_state *s = (mpcore_timer_state *)opaque;
-    s->status = 1;
-    if (s->control & 2) {
-        s->count = s->load;
-        mpcore_timer_reload(s, 0);
-    } else {
-        s->count = 0;
-    }
-    mpcore_timer_update_irq(s);
-}
-
-static uint32_t mpcore_timer_read(mpcore_timer_state *s, int offset)
-{
-    int64_t val;
-    switch (offset) {
-    case 0: /* Load */
-        return s->load;
-        /* Fall through.  */
-    case 4: /* Counter.  */
-        if (((s->control & 1) == 0) || (s->count == 0))
-            return 0;
-        /* Slow and ugly, but hopefully won't happen too often.  */
-        val = s->tick - qemu_get_clock_ns(vm_clock);
-        val /= mpcore_timer_scale(s);
-        if (val < 0)
-            val = 0;
-        return val;
-    case 8: /* Control.  */
-        return s->control;
-    case 12: /* Interrupt status.  */
-        return s->status;
-    default:
-        return 0;
-    }
-}
-
-static void mpcore_timer_write(mpcore_timer_state *s, int offset,
-                               uint32_t value)
-{
-    int64_t old;
-    switch (offset) {
-    case 0: /* Load */
-        s->load = value;
-        /* Fall through.  */
-    case 4: /* Counter.  */
-        if ((s->control & 1) && s->count) {
-            /* Cancel the previous timer.  */
-            qemu_del_timer(s->timer);
-        }
-        s->count = value;
-        if (s->control & 1) {
-            mpcore_timer_reload(s, 1);
-        }
-        break;
-    case 8: /* Control.  */
-        old = s->control;
-        s->control = value;
-        if (((old & 1) == 0) && (value & 1)) {
-            if (s->count == 0 && (s->control & 2))
-                s->count = s->load;
-            mpcore_timer_reload(s, 1);
-        }
-        break;
-    case 12: /* Interrupt status.  */
-        s->status &= ~value;
-        mpcore_timer_update_irq(s);
-        break;
-    }
-}
-
-static void mpcore_timer_init(mpcore_priv_state *mpcore,
-                              mpcore_timer_state *s, int id)
-{
-    s->id = id;
-    s->mpcore = mpcore;
-    s->timer = qemu_new_timer_ns(vm_clock, mpcore_timer_tick, s);
-}
-
-
 /* Per-CPU private memory mapped IO.  */
 
 static uint64_t mpcore_priv_read(void *opaque, target_phys_addr_t offset,
@@ -185,20 +68,6 @@ static uint64_t mpcore_priv_read(void *opaque, target_phys_addr_t offset,
             }
         }
         return gic_cpu_read(&s->gic, id, offset & 0xff);
-    } else if (offset < 0xb00) {
-        /* Timers.  */
-        if (offset < 0x700) {
-            id = gic_get_current_cpu();
-        } else {
-            id = (offset - 0x700) >> 8;
-            if (id >= s->num_cpu) {
-                return 0;
-            }
-        }
-        id <<= 1;
-        if (offset & 0x20)
-          id++;
-        return mpcore_timer_read(&s->timer[id], offset & 0xf);
     }
 bad_reg:
     hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
@@ -233,20 +102,6 @@ static void mpcore_priv_write(void *opaque, target_phys_addr_t offset,
         if (id < s->num_cpu) {
             gic_cpu_write(&s->gic, id, offset & 0xff, value);
         }
-    } else if (offset < 0xb00) {
-        /* Timers.  */
-        if (offset < 0x700) {
-            id = gic_get_current_cpu();
-        } else {
-            id = (offset - 0x700) >> 8;
-        }
-        if (id < s->num_cpu) {
-            id <<= 1;
-            if (offset & 0x20)
-              id++;
-            mpcore_timer_write(&s->timer[id], offset & 0xf, value);
-        }
-        return;
     }
     return;
 bad_reg:
@@ -259,25 +114,50 @@ static const MemoryRegionOps mpcore_priv_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
+static void mpcore_timer_irq_handler(void *opaque, int irq, int level)
+{
+    mpcore_priv_state *s = (mpcore_priv_state *)opaque;
+    if (level && !s->old_timer_status[irq]) {
+        gic_set_pending_private(&s->gic, irq >> 1, 29 + (irq & 1));
+    }
+    s->old_timer_status[irq] = level;
+}
+
 static void mpcore_priv_map_setup(mpcore_priv_state *s)
 {
+    int i;
+    SysBusDevice *busdev = sysbus_from_qdev(s->mptimer);
     memory_region_init(&s->container, "mpcode-priv-container", 0x2000);
     memory_region_init_io(&s->iomem, &mpcore_priv_ops, s, "mpcode-priv",
                           0x1000);
     memory_region_add_subregion(&s->container, 0, &s->iomem);
+    /* Add the regions for timer and watchdog for "current CPU" and
+     * for each specific CPU.
+     */
+    s->timer_irq = qemu_allocate_irqs(mpcore_timer_irq_handler,
+                                      s, (s->num_cpu + 1) * 2);
+    for (i = 0; i < (s->num_cpu + 1) * 2; i++) {
+        /* Timers at 0x600, 0x700, ...; watchdogs at 0x620, 0x720, ... */
+        target_phys_addr_t offset = 0x600 + (i >> 1) * 0x100 + (i & 1) * 0x20;
+        memory_region_add_subregion(&s->container, offset,
+                                    sysbus_mmio_get_region(busdev, i));
+    }
     memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
+    /* Wire up the interrupt from each watchdog and timer. */
+    for (i = 0; i < s->num_cpu * 2; i++) {
+        sysbus_connect_irq(busdev, i, s->timer_irq[i]);
+    }
 }
 
 static int mpcore_priv_init(SysBusDevice *dev)
 {
     mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
-    int i;
 
     gic_init(&s->gic, s->num_cpu);
+    s->mptimer = qdev_create(NULL, "arm_mptimer");
+    qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
+    qdev_init_nofail(s->mptimer);
     mpcore_priv_map_setup(s);
     sysbus_init_mmio(dev, &s->container);
-    for (i = 0; i < s->num_cpu * 2; i++) {
-        mpcore_timer_init(s, &s->timer[i], i);
-    }
     return 0;
 }
commit 7b4252e83f6f7d82a4bbd95257523091fdb68fa1
Author: Peter Chubb <peter.chubb at nicta.com.au>
Date:   Mon Dec 12 10:25:42 2011 +0000

    Fix sp804 dual-timer
    
    Properly implement dual-timer read/write for the sp804 dual timer module.
    Based on ARM specs at
    http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0271d/index.html
    
    Signed-off-by: Hans Jang <hsjang at ok-labs.com>
    Signed-off-by: David Mirabito <david.mirabito at nicta.com.au>
    Signed-off-by: Peter Chubb <peter.chubb at nicta.com.au>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 518bad2..0a5b9d2 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -170,9 +170,9 @@ static arm_timer_state *arm_timer_init(uint32_t freq)
 }
 
 /* ARM PrimeCell SP804 dual timer module.
-   Docs for this device don't seem to be publicly available.  This
-   implementation is based on guesswork, the linux kernel sources and the
-   Integrator/CP timer modules.  */
+ * Docs at
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0271d/index.html
+*/
 
 typedef struct {
     SysBusDevice busdev;
@@ -182,6 +182,13 @@ typedef struct {
     qemu_irq irq;
 } sp804_state;
 
+static const uint8_t sp804_ids[] = {
+    /* Timer ID */
+    0x04, 0x18, 0x14, 0,
+    /* PrimeCell ID */
+    0xd, 0xf0, 0x05, 0xb1
+};
+
 /* Merge the IRQs from the two component devices.  */
 static void sp804_set_irq(void *opaque, int irq, int level)
 {
@@ -196,12 +203,27 @@ static uint64_t sp804_read(void *opaque, target_phys_addr_t offset,
 {
     sp804_state *s = (sp804_state *)opaque;
 
-    /* ??? Don't know the PrimeCell ID for this device.  */
     if (offset < 0x20) {
         return arm_timer_read(s->timer[0], offset);
-    } else {
+    }
+    if (offset < 0x40) {
         return arm_timer_read(s->timer[1], offset - 0x20);
     }
+
+    /* TimerPeriphID */
+    if (offset >= 0xfe0 && offset <= 0xffc) {
+        return sp804_ids[(offset - 0xfe0) >> 2];
+    }
+
+    switch (offset) {
+    /* Integration Test control registers, which we won't support */
+    case 0xf00: /* TimerITCR */
+    case 0xf04: /* TimerITOP (strictly write only but..) */
+        return 0;
+    }
+
+    hw_error("%s: Bad offset %x\n", __func__, (int)offset);
+    return 0;
 }
 
 static void sp804_write(void *opaque, target_phys_addr_t offset,
@@ -211,9 +233,16 @@ static void sp804_write(void *opaque, target_phys_addr_t offset,
 
     if (offset < 0x20) {
         arm_timer_write(s->timer[0], offset, value);
-    } else {
+        return;
+    }
+
+    if (offset < 0x40) {
         arm_timer_write(s->timer[1], offset - 0x20, value);
+        return;
     }
+
+    /* Technically we could be writing to the Test Registers, but not likely */
+    hw_error("%s: Bad offset %x\n", __func__, (int)offset);
 }
 
 static const MemoryRegionOps sp804_ops = {
commit f18318eef8b4b263f4e82a5338c9b2875a6c73c8
Merge: 5bf1356... 62ba9f3...
Author: malc <av1474 at comtv.ru>
Date:   Mon Dec 12 04:12:31 2011 +0400

    Merge branch 'master' of git://git.qemu.org/qemu

commit 62ba9f3662c5481f31160daf25474c8f22d6b3d2
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Sun Dec 11 17:49:23 2011 -0600

    Update README
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/README b/README
index dfd56f2..c77d126 100644
--- a/README
+++ b/README
@@ -1,3 +1,3 @@
-Read the documentation in qemu-doc.html.
+Read the documentation in qemu-doc.html or on http://wiki.qemu.org
 
-Fabrice Bellard.
+- QEMU team
commit 5bf1356026f920de1158f32bb8472ed120a1131f
Merge: f7e80ad... daf767b...
Author: malc <av1474 at comtv.ru>
Date:   Mon Dec 12 00:47:40 2011 +0400

    Merge branch 'master' of git://git.qemu.org/qemu

commit f7e80adf3cc4b99b8230e6474d0518363773915f
Author: Andreas Gustafsson <gson at gson.org>
Date:   Mon Dec 12 00:46:32 2011 +0400

    target-i386: fix cmpxchg instruction emulation
    
    When the i386 cmpxchg instruction is executed with a memory operand
    and the comparison result is "unequal", do the memory write before
    changing the accumulator instead of the other way around, because
    otherwise the new accumulator value will incorrectly be used in the
    comparison when the instruction is restarted after a page fault.
    
    This bug was originally reported on 2010-04-25 as
    https://bugs.launchpad.net/qemu/+bug/569760
    
    Signed-off-by: Andreas Gustafsson <gson at gson.org>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 1ef8d16..8321bf3 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -4870,20 +4870,23 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             tcg_gen_sub_tl(t2, cpu_regs[R_EAX], t0);
             gen_extu(ot, t2);
             tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1);
+            label2 = gen_new_label();
             if (mod == 3) {
-                label2 = gen_new_label();
                 gen_op_mov_reg_v(ot, R_EAX, t0);
                 tcg_gen_br(label2);
                 gen_set_label(label1);
                 gen_op_mov_reg_v(ot, rm, t1);
-                gen_set_label(label2);
             } else {
-                tcg_gen_mov_tl(t1, t0);
+                /* perform no-op store cycle like physical cpu; must be
+                   before changing accumulator to ensure idempotency if
+                   the store faults and the instruction is restarted */
+                gen_op_st_v(ot + s->mem_index, t0, a0);
                 gen_op_mov_reg_v(ot, R_EAX, t0);
+                tcg_gen_br(label2);
                 gen_set_label(label1);
-                /* always store */
                 gen_op_st_v(ot + s->mem_index, t1, a0);
             }
+            gen_set_label(label2);
             tcg_gen_mov_tl(cpu_cc_src, t0);
             tcg_gen_mov_tl(cpu_cc_dst, t2);
             s->cc_op = CC_OP_SUBB + ot;
commit daf767b16aeb32e5b9a77066ba130fe723f875ca
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 3 22:32:37 2011 +0100

    w32: Disable buffering for log file
    
    W32 does not support line buffering, but it supports unbuffered output.
    
    Unbuffered output is better for writing to qemu.log than fully buffered
    output because it also shows the latest log messages when an application
    crash occurs.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/exec.c b/exec.c
index 6b92198..d8b2180 100644
--- a/exec.c
+++ b/exec.c
@@ -1603,8 +1603,10 @@ void cpu_set_log(int log_flags)
             static char logfile_buf[4096];
             setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
         }
-#elif !defined(_WIN32)
-        /* Win32 doesn't support line-buffering and requires size >= 2 */
+#elif defined(_WIN32)
+        /* Win32 doesn't support line-buffering, so use unbuffered output. */
+        setvbuf(logfile, NULL, _IONBF, 0);
+#else
         setvbuf(logfile, NULL, _IOLBF, 0);
 #endif
         log_append = 1;
commit 946fc459969b78966798399d5dc8ec7e6f4a1c1c
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 3 22:32:21 2011 +0100

    w32: QEMU applications with SDL are always GUI applications
    
    Since commit 1d14ffa97eacd3cb722271eaf6f093038396eac4 (in 2005),
    QEMU applications on W32 don't use the default SDL compiler flags:
    
    Instead of a GUI application, a console application is created.
    
    This has disadvantages (there is always an empty console window) and
    no obvious reason, so this patch removes the strange flag modification.
    
    The SDL GUI applications still can be run from a console window
    and even send stdout and stderr to that console by setting environment
    variable SDL_STDIO_REDIRECT=no.
    
    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 ca2530c..2686657 100755
--- a/configure
+++ b/configure
@@ -1523,9 +1523,6 @@ EOF
   if compile_prog "$sdl_cflags" "$sdl_libs" ; then
     sdl_libs="$sdl_libs -lX11"
   fi
-  if test "$mingw32" = "yes" ; then
-    sdl_libs="`echo $sdl_libs | sed s/-mwindows//g` -mconsole"
-  fi
   libs_softmmu="$sdl_libs $libs_softmmu"
 fi
 
commit f9db31a29e8ec43f73a9e948e980c569beef0136
Author: Brad <brad at comstyle.com>
Date:   Mon Nov 28 19:53:49 2011 -0500

    configure: Enable build by default PIE / read-only relocation sections on OpenBSD amd64/i386.
    
    Enable build by default PIE / read-only relocation sections for the QEMU
    binaries on OpenBSD amd64/i386.
    
    Signed-off-by: Brad Smith <brad at comstyle.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/configure b/configure
index 5fbd812..ca2530c 100755
--- a/configure
+++ b/configure
@@ -1111,7 +1111,7 @@ fi
 
 if test "$pie" = ""; then
   case "$cpu-$targetos" in
-    i386-Linux|x86_64-Linux)
+    i386-Linux|x86_64-Linux|i386-OpenBSD|x86_64-OpenBSD)
       ;;
     *)
       pie="no"
commit c580dee4e170adad1ebdf901d32f0e1ed7d125b9
Author: Stefan Weil <sw at weilnetz.de>
Date:   Mon Nov 21 21:06:22 2011 +0100

    bsd_user: Fix potential null pointer dereference
    
    This bug was spotted by cppcheck.
    
    Using g_try_malloc0 (as does the linux-user code) fixes this.
    
    v2:
    Use g_free in bsdload.c, too. Thanks to Peter Maydell for this hint.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/bsd-user/bsdload.c b/bsd-user/bsdload.c
index 6d9bb6f..2abc713 100644
--- a/bsd-user/bsdload.c
+++ b/bsd-user/bsdload.c
@@ -196,7 +196,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
 
     /* Something went wrong, return the inode and free the argument pages*/
     for (i=0 ; i<MAX_ARG_PAGES ; i++) {
-        free(bprm.page[i]);
+        g_free(bprm.page[i]);
     }
     return(retval);
 }
diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 1ef1f97..1288884 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -641,8 +641,7 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
                 offset = p % TARGET_PAGE_SIZE;
                 pag = (char *)page[p/TARGET_PAGE_SIZE];
                 if (!pag) {
-                    pag = (char *)malloc(TARGET_PAGE_SIZE);
-                    memset(pag, 0, TARGET_PAGE_SIZE);
+                    pag = g_try_malloc0(TARGET_PAGE_SIZE);
                     page[p/TARGET_PAGE_SIZE] = pag;
                     if (!pag)
                         return 0;
@@ -696,7 +695,7 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
             info->rss++;
             /* FIXME - check return value of memcpy_to_target() for failure */
             memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
-            free(bprm->page[i]);
+            g_free(bprm->page[i]);
         }
         stack_base += TARGET_PAGE_SIZE;
     }
commit ad3d11e6e78f8640c1af6f67420200d8287c3267
Author: Hui Kai Ran <hkran at linux.vnet.ibm.com>
Date:   Thu Dec 8 13:49:13 2011 +0800

    virtio-pci: use pci macros
    
    Signed-off-by: Hui Kai Ran <hkran at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index c665f5c..77b75bc 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -627,9 +627,10 @@ void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev)
     if (proxy->class_code) {
         pci_config_set_class(config, proxy->class_code);
     }
-    pci_set_word(config + 0x2c, pci_get_word(config + PCI_VENDOR_ID));
-    pci_set_word(config + 0x2e, vdev->device_id);
-    config[0x3d] = 1;
+    pci_set_word(config + PCI_SUBSYSTEM_VENDOR_ID,
+                 pci_get_word(config + PCI_VENDOR_ID));
+    pci_set_word(config + PCI_SUBSYSTEM_ID, vdev->device_id);
+    config[PCI_INTERRUPT_PIN] = 1;
 
     memory_region_init(&proxy->msix_bar, "virtio-msix", 4096);
     if (vdev->nvectors && !msix_init(&proxy->pci_dev, vdev->nvectors,
commit ee12e1f38a8bb2cbf58584688f0a90a7872f5dcf
Author: Chen Wei-Ren <chenwj at iis.sinica.edu.tw>
Date:   Tue Nov 15 20:47:12 2011 +0800

    LICENSE: There is no libqemu.a anymore
    
      Remove statement about libqemu.a from LICENSE.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Chen Wei-Ren <chenwj at iis.sinica.edu.tw>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/LICENSE b/LICENSE
index cbd92c0..acae9a3 100644
--- a/LICENSE
+++ b/LICENSE
@@ -6,9 +6,7 @@ The following points clarify the QEMU license:
 GNU General Public License. Hence each source file contains its own
 licensing information.
 
-In particular, the QEMU virtual CPU core library (libqemu.a) is
-released under the GNU Lesser General Public License. Many hardware
-device emulation sources are released under the BSD license.
+Many hardware device emulation sources are released under the BSD license.
 
 3) The Tiny Code Generator (TCG) is released under the BSD license
    (see license headers in files).
commit 050d99402845d3c5915e3abd8aea7cc772b85b8e
Author: Chen Wei-Ren <chenwj at iis.sinica.edu.tw>
Date:   Tue Nov 15 20:47:11 2011 +0800

    Makefile.objs: Remove libqemu_common.a from the comment
    
      Remove libqemu_common.a from the comment.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Chen Wei-Ren <chenwj at iis.sinica.edu.tw>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/Makefile.objs b/Makefile.objs
index 3a699ee..281b698 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -68,10 +68,9 @@ endif
 fsdev-obj-$(CONFIG_VIRTFS) += $(addprefix fsdev/, $(fsdev-nested-y))
 
 ######################################################################
-# libqemu_common.a: Target independent part of system emulation. The
-# long term path is to suppress *all* target specific code in case of
-# system emulation, i.e. a single QEMU executable should support all
-# CPUs and machines.
+# Target independent part of system emulation. The long term path is to
+# suppress *all* target specific code in case of system emulation, i.e. a
+# single QEMU executable should support all CPUs and machines.
 
 common-obj-y = $(block-obj-y) blockdev.o
 common-obj-y += $(net-obj-y)
commit 1c8a80f3b975884bd6ee6f239b6e728fbcc821c2
Author: Chen Wei-Ren <chenwj at iis.sinica.edu.tw>
Date:   Tue Nov 15 20:47:10 2011 +0800

    Makefile.target: Remove out of date comment
    
      Remove the out of date comment, i.e., "# libqemu" since libqemu.a is not
    available anymore.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Chen Wei-Ren <chenwj at iis.sinica.edu.tw>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/Makefile.target b/Makefile.target
index a111521..7369a89 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -92,8 +92,6 @@ tci-dis.o: QEMU_CFLAGS += -I$(SRC_PATH)/tcg -I$(SRC_PATH)/tcg/tci
 
 $(libobj-y): $(GENERATED_HEADERS)
 
-# libqemu
-
 translate.o: translate.c cpu.h
 
 translate-all.o: translate-all.c cpu.h
commit cc588764f4b52421f685e106498e7a9b758bdcd3
Author: Chen Wei-Ren <chenwj at iis.sinica.edu.tw>
Date:   Tue Nov 15 20:47:09 2011 +0800

    qemu-tech.texi: Remove libqemu related stuff from the document
    
      Remove libqemu related stuff from the document since libqemu.a is not supported
    anymore.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Chen Wei-Ren <chenwj at iis.sinica.edu.tw>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/qemu-tech.texi b/qemu-tech.texi
index 62afe45..5676fb7 100644
--- a/qemu-tech.texi
+++ b/qemu-tech.texi
@@ -96,10 +96,6 @@ Alpha and S390 hosts, but TCG (see below) doesn't support those yet.
 
 @item Precise exceptions support.
 
- at item The virtual CPU is a library (@code{libqemu}) which can be used
-in other projects (look at @file{qemu/tests/qruncom.c} to have an
-example of user mode @code{libqemu} usage).
-
 @item
 Floating point library supporting both full software emulation and
 native host FPU instructions.
@@ -685,7 +681,6 @@ are available. They are used for regression testing.
 @menu
 * test-i386::
 * linux-test::
-* qruncom.c::
 @end menu
 
 @node test-i386
@@ -711,11 +706,6 @@ This program tests various Linux system calls. It is used to verify
 that the system call parameters are correctly converted between target
 and host CPUs.
 
- at node qruncom.c
- at section @file{qruncom.c}
-
-Example of usage of @code{libqemu} to emulate a user mode i386 CPU.
-
 @node Index
 @chapter Index
 @printindex cp
commit e4aeadcb5685cdb421275025c5b22f530f830105
Author: Chen Wei-Ren <chenwj at iis.sinica.edu.tw>
Date:   Tue Nov 15 20:47:08 2011 +0800

    tests/qruncom.c: Remove libqemu.a example
    
      Remove libqemu example since libqemu.a is not available anymore.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Chen Wei-Ren <chenwj at iis.sinica.edu.tw>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/tests/qruncom.c b/tests/qruncom.c
deleted file mode 100644
index 2e93aaf..0000000
--- a/tests/qruncom.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Example of use of user mode libqemu: launch a basic .com DOS
- * executable
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <signal.h>
-#include <malloc.h>
-
-#include "cpu.h"
-
-//#define SIGTEST
-
-int cpu_get_pic_interrupt(CPUState *env)
-{
-    return -1;
-}
-
-uint64_t cpu_get_tsc(CPUState *env)
-{
-    return 0;
-}
-
-static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
-                     unsigned long addr, unsigned int sel)
-{
-    unsigned int e1, e2;
-    e1 = (addr & 0xffff) | (sel << 16);
-    e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
-    stl((uint8_t *)ptr, e1);
-    stl((uint8_t *)ptr + 4, e2);
-}
-
-uint64_t idt_table[256];
-
-/* only dpl matters as we do only user space emulation */
-static void set_idt(int n, unsigned int dpl)
-{
-    set_gate(idt_table + n, 0, dpl, 0, 0);
-}
-
-void g_free(void *ptr)
-{
-    free(ptr);
-}
-
-void *g_malloc(size_t size)
-{
-    return malloc(size);
-}
-
-void *g_malloc0(size_t size)
-{
-    void *ptr;
-    ptr = g_malloc(size);
-    if (!ptr)
-        return NULL;
-    memset(ptr, 0, size);
-    return ptr;
-}
-
-void *qemu_vmalloc(size_t size)
-{
-    return memalign(4096, size);
-}
-
-void qemu_vfree(void *ptr)
-{
-    free(ptr);
-}
-
-void qemu_printf(const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    vprintf(fmt, ap);
-    va_end(ap);
-}
-
-/* XXX: this is a bug in helper2.c */
-int errno;
-
-/**********************************************/
-
-#define COM_BASE_ADDR    0x10100
-
-static void usage(void)
-{
-    printf("qruncom version 0.1 (c) 2003 Fabrice Bellard\n"
-           "usage: qruncom file.com\n"
-           "user mode libqemu demo: run simple .com DOS executables\n");
-    exit(1);
-}
-
-static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
-{
-    return (uint8_t *)((seg << 4) + (reg & 0xffff));
-}
-
-static inline void pushw(CPUState *env, int val)
-{
-    env->regs[R_ESP] = (env->regs[R_ESP] & ~0xffff) | ((env->regs[R_ESP] - 2) & 0xffff);
-    *(uint16_t *)seg_to_linear(env->segs[R_SS].selector, env->regs[R_ESP]) = val;
-}
-
-static void host_segv_handler(int host_signum, siginfo_t *info,
-                              void *puc)
-{
-    if (cpu_signal_handler(host_signum, info, puc)) {
-        return;
-    }
-    abort();
-}
-
-int main(int argc, char **argv)
-{
-    uint8_t *vm86_mem;
-    const char *filename;
-    int fd, ret, seg;
-    CPUState *env;
-
-    if (argc != 2)
-        usage();
-    filename = argv[1];
-
-    vm86_mem = mmap((void *)0x00000000, 0x110000,
-                    PROT_WRITE | PROT_READ | PROT_EXEC,
-                    MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
-    if (vm86_mem == MAP_FAILED) {
-        perror("mmap");
-        exit(1);
-    }
-
-    /* load the MSDOS .com executable */
-    fd = open(filename, O_RDONLY);
-    if (fd < 0) {
-        perror(filename);
-        exit(1);
-    }
-    ret = read(fd, vm86_mem + COM_BASE_ADDR, 65536 - 256);
-    if (ret < 0) {
-        perror("read");
-        exit(1);
-    }
-    close(fd);
-
-    /* install exception handler for CPU emulator */
-    {
-        struct sigaction act;
-
-        sigfillset(&act.sa_mask);
-        act.sa_flags = SA_SIGINFO;
-        //        act.sa_flags |= SA_ONSTACK;
-
-        act.sa_sigaction = host_segv_handler;
-        sigaction(SIGSEGV, &act, NULL);
-        sigaction(SIGBUS, &act, NULL);
-    }
-
-    //    cpu_set_log(CPU_LOG_TB_IN_ASM | CPU_LOG_TB_OUT_ASM | CPU_LOG_EXEC);
-
-    env = cpu_init("qemu32");
-
-    cpu_x86_set_cpl(env, 3);
-
-    env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
-    /* NOTE: hflags duplicates some of the virtual CPU state */
-    env->hflags |= HF_PE_MASK | VM_MASK;
-
-    /* flags setup : we activate the IRQs by default as in user
-       mode. We also activate the VM86 flag to run DOS code */
-    env->eflags |= IF_MASK | VM_MASK;
-
-    /* init basic registers */
-    env->eip = 0x100;
-    env->regs[R_ESP] = 0xfffe;
-    seg = (COM_BASE_ADDR - 0x100) >> 4;
-
-    cpu_x86_load_seg_cache(env, R_CS, seg,
-                           (seg << 4), 0xffff, 0);
-    cpu_x86_load_seg_cache(env, R_SS, seg,
-                           (seg << 4), 0xffff, 0);
-    cpu_x86_load_seg_cache(env, R_DS, seg,
-                           (seg << 4), 0xffff, 0);
-    cpu_x86_load_seg_cache(env, R_ES, seg,
-                           (seg << 4), 0xffff, 0);
-    cpu_x86_load_seg_cache(env, R_FS, seg,
-                           (seg << 4), 0xffff, 0);
-    cpu_x86_load_seg_cache(env, R_GS, seg,
-                           (seg << 4), 0xffff, 0);
-
-    /* exception support */
-    env->idt.base = (unsigned long)idt_table;
-    env->idt.limit = sizeof(idt_table) - 1;
-    set_idt(0, 0);
-    set_idt(1, 0);
-    set_idt(2, 0);
-    set_idt(3, 3);
-    set_idt(4, 3);
-    set_idt(5, 3);
-    set_idt(6, 0);
-    set_idt(7, 0);
-    set_idt(8, 0);
-    set_idt(9, 0);
-    set_idt(10, 0);
-    set_idt(11, 0);
-    set_idt(12, 0);
-    set_idt(13, 0);
-    set_idt(14, 0);
-    set_idt(15, 0);
-    set_idt(16, 0);
-    set_idt(17, 0);
-    set_idt(18, 0);
-    set_idt(19, 0);
-
-    /* put return code */
-    *seg_to_linear(env->segs[R_CS].selector, 0) = 0xb4; /* mov ah, $0 */
-    *seg_to_linear(env->segs[R_CS].selector, 1) = 0x00;
-    *seg_to_linear(env->segs[R_CS].selector, 2) = 0xcd; /* int $0x21 */
-    *seg_to_linear(env->segs[R_CS].selector, 3) = 0x21;
-    pushw(env, 0x0000);
-
-    /* the value of these registers seem to be assumed by pi_10.com */
-    env->regs[R_ESI] = 0x100;
-    env->regs[R_ECX] = 0xff;
-    env->regs[R_EBP] = 0x0900;
-    env->regs[R_EDI] = 0xfffe;
-
-    /* inform the emulator of the mmaped memory */
-    page_set_flags(0x00000000, 0x110000,
-                   PAGE_WRITE | PAGE_READ | PAGE_EXEC | PAGE_VALID);
-
-    for(;;) {
-        ret = cpu_x86_exec(env);
-        switch(ret) {
-        case EXCP0D_GPF:
-            {
-                int int_num, ah;
-                int_num = *(uint8_t *)(env->segs[R_CS].base + env->eip + 1);
-                if (int_num != 0x21)
-                    goto unknown_int;
-                ah = (env->regs[R_EAX] >> 8) & 0xff;
-                switch(ah) {
-                case 0x00: /* exit */
-                    exit(0);
-                case 0x02: /* write char */
-                    {
-                        uint8_t c = env->regs[R_EDX];
-                        write(1, &c, 1);
-                    }
-                    break;
-                case 0x09: /* write string */
-                    {
-                        uint8_t c;
-                        for(;;) {
-                            c = *seg_to_linear(env->segs[R_DS].selector, env->regs[R_EAX]);
-                            if (c == '$')
-                                break;
-                            write(1, &c, 1);
-                        }
-                        env->regs[R_EAX] = (env->regs[R_EAX] & ~0xff) | '$';
-                    }
-                    break;
-                default:
-                unknown_int:
-                    fprintf(stderr, "unsupported int 0x%02x\n", int_num);
-                    cpu_dump_state(env, stderr, fprintf, 0);
-                    //                    exit(1);
-                }
-                env->eip += 2;
-            }
-            break;
-        default:
-            fprintf(stderr, "unhandled cpu_exec return code (0x%x)\n", ret);
-            cpu_dump_state(env, stderr, fprintf, 0);
-            exit(1);
-        }
-    }
-}
commit e7764a465855568d2813d6ff1099b75f3edd53e8
Author: Chen Wei-Ren <chenwj at iis.sinica.edu.tw>
Date:   Tue Nov 15 20:47:07 2011 +0800

    tests/Makefile: Remove qruncom target
    
      Remove qruncom target from the Makefile file.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Chen Wei-Ren <chenwj at iis.sinica.edu.tw>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/tests/Makefile b/tests/Makefile
index 430e0c1..15e36a2 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -115,12 +115,6 @@ speed: sha1 sha1-i386
 	time ./sha1
 	time $(QEMU) ./sha1-i386
 
-# broken test
-# NOTE: -fomit-frame-pointer is currently needed : this is a bug in libqemu
-qruncom: qruncom.c ../ioport-user.c ../i386-user/libqemu.a
-	$(CC) $(CFLAGS) -fomit-frame-pointer $(LDFLAGS) -I../target-i386 -I.. -I../i386-user -I../fpu \
-              -o $@ $(filter %.c, $^) -L../i386-user -lqemu -lm
-
 # arm test
 hello-arm: hello-arm.o
 	arm-linux-ld -o $@ $<
commit 46d5dee007d3300210968308983b4834d4d1403f
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Dec 7 23:31:46 2011 +0100

    tcg: Remove redundant declarations of TCG_TARGET_REG_BITS
    
    TCG_TARGET_REG_BITS is declared in tcg.h for all TCG targets.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index 7756e7b..adbb036 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -23,11 +23,6 @@
  */
 #define TCG_TARGET_I386 1
 
-#if defined(__x86_64__)
-# define TCG_TARGET_REG_BITS 64
-#else
-# define TCG_TARGET_REG_BITS 32
-#endif
 //#define TCG_TARGET_WORDS_BIGENDIAN
 
 #if TCG_TARGET_REG_BITS == 64
commit a6c5c07990059c94bf50b0422e953af1368353c0
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Dec 7 18:57:41 2011 +0200

    docs: document memory API interaction with migration
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/docs/migration.txt b/docs/migration.txt
index 4848c1e..f3ddd2f 100644
--- a/docs/migration.txt
+++ b/docs/migration.txt
@@ -219,6 +219,18 @@ The functions to do that are inside a vmstate definition, and are called:
 Example: You can look at hpet.c, that uses the three function to
          massage the state that is transferred.
 
+If you use memory API functions that update memory layout outside
+initialization (i.e., in response to a guest action), this is a strong
+indication that you need to call these functions in a post_load callback.
+Examples of such memory API functions are:
+
+  - memory_region_add_subregion()
+  - memory_region_del_subregion()
+  - memory_region_set_readonly()
+  - memory_region_set_enabled()
+  - memory_region_set_address()
+  - memory_region_set_alias_offset()
+
 === Subsections ===
 
 The use of version_id allows to be able to migrate from older versions
commit 3dc853832db7bf8ac3878e0666c639d3bc02b587
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon Nov 28 11:59:37 2011 -0200

    qapi: Convert migrate_set_speed
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 6ba694d..fdbed15 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -786,8 +786,7 @@ ETEXI
         .params     = "value",
         .help       = "set maximum speed (in bytes) for migrations. "
 	"Defaults to MB if no size suffix is specified, ie. B/K/M/G/T",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_set_speed,
+        .mhandler.cmd = hmp_migrate_set_speed,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 04e6b73..e7659d5 100644
--- a/hmp.c
+++ b/hmp.c
@@ -673,3 +673,9 @@ void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict)
     double value = qdict_get_double(qdict, "value");
     qmp_migrate_set_downtime(value, NULL);
 }
+
+void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict)
+{
+    int64_t value = qdict_get_int(qdict, "value");
+    qmp_migrate_set_speed(value, NULL);
+}
diff --git a/hmp.h b/hmp.h
index 9182622..093242d 100644
--- a/hmp.h
+++ b/hmp.h
@@ -48,5 +48,6 @@ void hmp_block_resize(Monitor *mon, const QDict *qdict);
 void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict);
 void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
 void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict);
+void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/migration.c b/migration.c
index a563162..75d4f02 100644
--- a/migration.c
+++ b/migration.c
@@ -473,21 +473,17 @@ void qmp_migrate_cancel(Error **errp)
     migrate_fd_cancel(migrate_get_current());
 }
 
-int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_migrate_set_speed(int64_t value, Error **errp)
 {
-    int64_t d;
     MigrationState *s;
 
-    d = qdict_get_int(qdict, "value");
-    if (d < 0) {
-        d = 0;
+    if (value < 0) {
+        value = 0;
     }
 
     s = migrate_get_current();
-    s->bandwidth_limit = d;
+    s->bandwidth_limit = value;
     qemu_file_set_rate_limit(s->file, s->bandwidth_limit);
-
-    return 0;
 }
 
 void qmp_migrate_set_downtime(double value, Error **errp)
diff --git a/migration.h b/migration.h
index 539f8f1..999d60f 100644
--- a/migration.h
+++ b/migration.h
@@ -42,8 +42,6 @@ int qemu_start_incoming_migration(const char *uri);
 
 int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
-int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data);
-
 uint64_t migrate_max_downtime(void);
 
 void do_info_migrate_print(Monitor *mon, const QObject *data);
diff --git a/qapi-schema.json b/qapi-schema.json
index d9b9fa1..f358b49 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1153,3 +1153,18 @@
 # Since: 0.14.0
 ##
 { 'command': 'migrate_set_downtime', 'data': {'value': 'number'} }
+
+##
+# @migrate_set_speed
+#
+# Set maximum speed for migration.
+#
+# @value: maximum speed in bytes.
+#
+# Returns: nothing on success
+#
+# Notes: A value lesser than zero will be automatically round up to zero.
+#
+# Since: 0.14.0
+##
+{ 'command': 'migrate_set_speed', 'data': {'value': 'int'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index b4cadeb..002e7e8 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -492,10 +492,7 @@ EQMP
     {
         .name       = "migrate_set_speed",
         .args_type  = "value:o",
-        .params     = "value",
-        .help       = "set maximum speed (in bytes) for migrations",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_set_speed,
+        .mhandler.cmd_new = qmp_marshal_input_migrate_set_speed,
     },
 
 SQMP
commit 4f0a993bf349e61632113a11e85ef588c66b421d
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Sun Nov 27 23:18:01 2011 -0200

    qapi: Convert migrate_set_downtime
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index e48c2ca..6ba694d 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -801,8 +801,7 @@ ETEXI
         .args_type  = "value:T",
         .params     = "value",
         .help       = "set maximum tolerated downtime (in seconds) for migrations",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_set_downtime,
+        .mhandler.cmd = hmp_migrate_set_downtime,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 92bb08f..04e6b73 100644
--- a/hmp.c
+++ b/hmp.c
@@ -667,3 +667,9 @@ void hmp_migrate_cancel(Monitor *mon, const QDict *qdict)
 {
     qmp_migrate_cancel(NULL);
 }
+
+void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict)
+{
+    double value = qdict_get_double(qdict, "value");
+    qmp_migrate_set_downtime(value, NULL);
+}
diff --git a/hmp.h b/hmp.h
index 2b0c1e4..9182622 100644
--- a/hmp.h
+++ b/hmp.h
@@ -47,5 +47,6 @@ void hmp_balloon(Monitor *mon, const QDict *qdict);
 void hmp_block_resize(Monitor *mon, const QDict *qdict);
 void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict);
 void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
+void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/migration.c b/migration.c
index fa603d6..a563162 100644
--- a/migration.c
+++ b/migration.c
@@ -490,14 +490,9 @@ int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return 0;
 }
 
-int do_migrate_set_downtime(Monitor *mon, const QDict *qdict,
-                            QObject **ret_data)
+void qmp_migrate_set_downtime(double value, Error **errp)
 {
-    double d;
-
-    d = qdict_get_double(qdict, "value") * 1e9;
-    d = MAX(0, MIN(UINT64_MAX, d));
-    max_downtime = (uint64_t)d;
-
-    return 0;
+    value *= 1e9;
+    value = MAX(0, MIN(UINT64_MAX, value));
+    max_downtime = (uint64_t)value;
 }
diff --git a/migration.h b/migration.h
index ff2e40b..539f8f1 100644
--- a/migration.h
+++ b/migration.h
@@ -46,9 +46,6 @@ int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 uint64_t migrate_max_downtime(void);
 
-int do_migrate_set_downtime(Monitor *mon, const QDict *qdict,
-                            QObject **ret_data);
-
 void do_info_migrate_print(Monitor *mon, const QObject *data);
 
 void do_info_migrate(Monitor *mon, QObject **ret_data);
diff --git a/qapi-schema.json b/qapi-schema.json
index d638f12..d9b9fa1 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1140,3 +1140,16 @@
 # Since: 0.14.0
 ##
 { 'command': 'migrate_cancel' }
+
+##
+# @migrate_set_downtime
+#
+# Set maximum tolerated downtime for migration.
+#
+# @value: maximum downtime in seconds
+#
+# Returns: nothing on success
+#
+# Since: 0.14.0
+##
+{ 'command': 'migrate_set_downtime', 'data': {'value': 'number'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 5eb4b76..b4cadeb 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -518,10 +518,7 @@ EQMP
     {
         .name       = "migrate_set_downtime",
         .args_type  = "value:T",
-        .params     = "value",
-        .help       = "set maximum tolerated downtime (in seconds) for migrations",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_set_downtime,
+        .mhandler.cmd_new = qmp_marshal_input_migrate_set_downtime,
     },
 
 SQMP
commit 6cdedb075f7a338bff7e97b3139bae5289157ae0
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Sun Nov 27 22:54:09 2011 -0200

    qapi: Convert migrate_cancel
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 131b21c..e48c2ca 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -771,8 +771,7 @@ ETEXI
         .args_type  = "",
         .params     = "",
         .help       = "cancel the current VM migration",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_cancel,
+        .mhandler.cmd = hmp_migrate_cancel,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 934e931..92bb08f 100644
--- a/hmp.c
+++ b/hmp.c
@@ -662,3 +662,8 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
     qmp_blockdev_snapshot_sync(device, filename, !!format, format, &errp);
     hmp_handle_error(mon, &errp);
 }
+
+void hmp_migrate_cancel(Monitor *mon, const QDict *qdict)
+{
+    qmp_migrate_cancel(NULL);
+}
diff --git a/hmp.h b/hmp.h
index e4227d3..2b0c1e4 100644
--- a/hmp.h
+++ b/hmp.h
@@ -46,5 +46,6 @@ void hmp_block_passwd(Monitor *mon, const QDict *qdict);
 void hmp_balloon(Monitor *mon, const QDict *qdict);
 void hmp_block_resize(Monitor *mon, const QDict *qdict);
 void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict);
+void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/migration.c b/migration.c
index 8280d71..fa603d6 100644
--- a/migration.c
+++ b/migration.c
@@ -468,10 +468,9 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return 0;
 }
 
-int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_migrate_cancel(Error **errp)
 {
     migrate_fd_cancel(migrate_get_current());
-    return 0;
 }
 
 int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
diff --git a/migration.h b/migration.h
index 0682179..ff2e40b 100644
--- a/migration.h
+++ b/migration.h
@@ -42,8 +42,6 @@ int qemu_start_incoming_migration(const char *uri);
 
 int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
-int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data);
-
 int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 uint64_t migrate_max_downtime(void);
diff --git a/qapi-schema.json b/qapi-schema.json
index 39bcc06..d638f12 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1127,3 +1127,16 @@
 { 'command': 'human-monitor-command',
   'data': {'command-line': 'str', '*cpu-index': 'int'},
   'returns': 'str' } 
+
+##
+# @migrate_cancel
+#
+# Cancel the current executing migration process.
+#
+# Returns: nothing on success
+#
+# Notes: This command succeeds even if there is no migration process running.
+#
+# Since: 0.14.0
+##
+{ 'command': 'migrate_cancel' }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index d101426..5eb4b76 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -471,10 +471,7 @@ EQMP
     {
         .name       = "migrate_cancel",
         .args_type  = "",
-        .params     = "",
-        .help       = "cancel the current VM migration",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_cancel,
+        .mhandler.cmd_new = qmp_marshal_input_migrate_cancel,
     },
 
 SQMP
commit d51a67b4d3214654a7b100c0873b77cb2bf87f29
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Fri Nov 25 17:52:45 2011 -0200

    qapi: Convert human-monitor-command
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/monitor.c b/monitor.c
index 62b1747..7334401 100644
--- a/monitor.c
+++ b/monitor.c
@@ -513,10 +513,10 @@ static int do_qmp_capabilities(Monitor *mon, const QDict *params,
 
 static void handle_user_command(Monitor *mon, const char *cmdline);
 
-static int do_hmp_passthrough(Monitor *mon, const QDict *params,
-                              QObject **ret_data)
+char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
+                                int64_t cpu_index, Error **errp)
 {
-    int ret = 0;
+    char *output = NULL;
     Monitor *old_mon, hmp;
     CharDriverState mchar;
 
@@ -527,25 +527,30 @@ static int do_hmp_passthrough(Monitor *mon, const QDict *params,
     old_mon = cur_mon;
     cur_mon = &hmp;
 
-    if (qdict_haskey(params, "cpu-index")) {
-        ret = monitor_set_cpu(qdict_get_int(params, "cpu-index"));
+    if (has_cpu_index) {
+        int ret = monitor_set_cpu(cpu_index);
         if (ret < 0) {
             cur_mon = old_mon;
-            qerror_report(QERR_INVALID_PARAMETER_VALUE, "cpu-index", "a CPU number");
+            error_set(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
+                      "a CPU number");
             goto out;
         }
     }
 
-    handle_user_command(&hmp, qdict_get_str(params, "command-line"));
+    handle_user_command(&hmp, command_line);
     cur_mon = old_mon;
 
     if (qemu_chr_mem_osize(hmp.chr) > 0) {
-        *ret_data = QOBJECT(qemu_chr_mem_to_qs(hmp.chr));
+        QString *str = qemu_chr_mem_to_qs(hmp.chr);
+        output = g_strdup(qstring_get_str(str));
+        QDECREF(str);
+    } else {
+        output = g_strdup("");
     }
 
 out:
     qemu_chr_close_mem(hmp.chr);
-    return ret;
+    return output;
 }
 
 static int compare_cmd(const char *name, const char *list)
diff --git a/qapi-schema.json b/qapi-schema.json
index 0ed39f3..39bcc06 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1099,3 +1099,31 @@
 ##
 { 'command': 'blockdev-snapshot-sync',
   'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str' } }
+
+##
+# @human-monitor-command:
+#
+# Execute a command on the human monitor and return the output.
+#
+# @command-line: the command to execute in the human monitor
+#
+# @cpu-index: #optional The CPU to use for commands that require an implicit CPU
+#
+# Returns: the output of the command as a string
+#
+# Since: 0.14.0
+#
+# Notes: This command only exists as a stop-gap.  It's use is highly
+#        discouraged.  The semantics of this command are not guaranteed.
+#
+#        Known limitations:
+#
+#        o This command is stateless, this means that commands that depend
+#          on state information (such as getfd) might not work
+#
+#       o Commands that prompt the user for data (eg. 'cont' when the block
+#         device is encrypted) don't currently work
+##
+{ 'command': 'human-monitor-command',
+  'data': {'command-line': 'str', '*cpu-index': 'int'},
+  'returns': 'str' } 
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 9d68206..d101426 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -970,10 +970,7 @@ EQMP
     {
         .name       = "human-monitor-command",
         .args_type  = "command-line:s,cpu-index:i?",
-        .params     = "",
-        .help       = "",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_hmp_passthrough,
+        .mhandler.cmd_new = qmp_marshal_input_human_monitor_command,
     },
 
 SQMP
commit 6106e2492fe0080ad85d4862dec9c3bebc57b2f0
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Fri Nov 25 16:15:19 2011 -0200

    qapi: Convert blockdev_snapshot_sync
    
    Unfortunately, this conversion required an additional change.
    
    In the old QMP command, the 'snapshot-file' argument is specified as
    optional. The idea is to take the snapshot internally if 'snapshot-file'
    is not passed. However, internal snapshots are not supported yet so
    the command returns a MissingParamater error if 'snapshot-file' is not
    passed. Which makes the argument actually required and will cause
    compatibility breakage if we change that in the future.
    
    To fix this the QAPI converted blockdev_snapshot_sync command makes the
    'snapshot-file' argument required. Again, in practice it's actually required,
    so this is not incompatible.
    
    If we do implement internal snapshots someday, we'll need a new argument
    for it.
    
    Note that this discussion doesn't affect HMP.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 5270404..c832782 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -601,28 +601,20 @@ void do_commit(Monitor *mon, const QDict *qdict)
     }
 }
 
-int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file,
+                                bool has_format, const char *format,
+                                Error **errp)
 {
-    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");
     BlockDriverState *bs;
     BlockDriver *drv, *old_drv, *proto_drv;
     int ret = 0;
     int flags;
     char old_filename[1024];
 
-    if (!filename) {
-        qerror_report(QERR_MISSING_PARAMETER, "snapshot-file");
-        ret = -1;
-        goto out;
-    }
-
     bs = bdrv_find(device);
     if (!bs) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, device);
-        ret = -1;
-        goto out;
+        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        return;
     }
 
     pstrcpy(old_filename, sizeof(old_filename), bs->filename);
@@ -630,35 +622,34 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
     old_drv = bs->drv;
     flags = bs->open_flags;
 
-    if (!format) {
+    if (!has_format) {
         format = "qcow2";
     }
 
     drv = bdrv_find_format(format);
     if (!drv) {
-        qerror_report(QERR_INVALID_BLOCK_FORMAT, format);
-        ret = -1;
-        goto out;
+        error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
+        return;
     }
 
-    proto_drv = bdrv_find_protocol(filename);
+    proto_drv = bdrv_find_protocol(snapshot_file);
     if (!proto_drv) {
-        qerror_report(QERR_INVALID_BLOCK_FORMAT, format);
-        ret = -1;
-        goto out;
+        error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
+        return;
     }
 
-    ret = bdrv_img_create(filename, format, bs->filename,
+    ret = bdrv_img_create(snapshot_file, format, bs->filename,
                           bs->drv->format_name, NULL, -1, flags);
     if (ret) {
-        goto out;
+        error_set(errp, QERR_UNDEFINED_ERROR);
+        return;
     }
 
     bdrv_drain_all();
     bdrv_flush(bs);
 
     bdrv_close(bs);
-    ret = bdrv_open(bs, filename, flags, drv);
+    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
@@ -667,17 +658,11 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
     if (ret != 0) {
         ret = bdrv_open(bs, old_filename, flags, old_drv);
         if (ret != 0) {
-            qerror_report(QERR_OPEN_FILE_FAILED, old_filename);
+            error_set(errp, QERR_OPEN_FILE_FAILED, old_filename);
         } else {
-            qerror_report(QERR_OPEN_FILE_FAILED, filename);
+            error_set(errp, QERR_OPEN_FILE_FAILED, snapshot_file);
         }
     }
-out:
-    if (ret) {
-        ret = -1;
-    }
-
-    return ret;
 }
 
 static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
diff --git a/blockdev.h b/blockdev.h
index b69a549..f1b6396 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -64,6 +64,4 @@ int do_change_block(Monitor *mon, const char *device,
 int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
 int do_block_set_io_throttle(Monitor *mon,
                              const QDict *qdict, QObject **ret_data);
-int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data);
-
 #endif
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 734a364..131b21c 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -840,7 +840,7 @@ ETEXI
                       "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)",
-        .mhandler.cmd_new = do_snapshot_blkdev,
+        .mhandler.cmd = hmp_snapshot_blkdev,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index db199b2..934e931 100644
--- a/hmp.c
+++ b/hmp.c
@@ -643,3 +643,22 @@ void hmp_block_resize(Monitor *mon, const QDict *qdict)
     qmp_block_resize(device, size, &errp);
     hmp_handle_error(mon, &errp);
 }
+
+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");
+    Error *errp = NULL;
+
+    if (!filename) {
+        /* In the future, if 'snapshot-file' is not specified, the snapshot
+           will be taken internally. Today it's actually required. */
+        error_set(&errp, QERR_MISSING_PARAMETER, "snapshot-file");
+        hmp_handle_error(mon, &errp);
+        return;
+    }
+
+    qmp_blockdev_snapshot_sync(device, filename, !!format, format, &errp);
+    hmp_handle_error(mon, &errp);
+}
diff --git a/hmp.h b/hmp.h
index c236fd2..e4227d3 100644
--- a/hmp.h
+++ b/hmp.h
@@ -45,5 +45,6 @@ void hmp_set_link(Monitor *mon, const QDict *qdict);
 void hmp_block_passwd(Monitor *mon, const QDict *qdict);
 void hmp_balloon(Monitor *mon, const QDict *qdict);
 void hmp_block_resize(Monitor *mon, const QDict *qdict);
+void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/qapi-schema.json b/qapi-schema.json
index f33fe00..0ed39f3 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1070,3 +1070,32 @@
 # Since: 0.14.0
 ##
 { 'command': 'block_resize', 'data': { 'device': 'str', 'size': 'int' }}
+
+##
+# @blockdev-snapshot-sync
+#
+# Generates a synchronous snapshot of a block device.
+#
+# @device:  the name of the device to generate the snapshot from.
+#
+# @snapshot-file: the target of the new image. If the file exists, or if it
+#                 is a device, the snapshot will be created in the existing
+#                 file/device. If does not exist, a new file will be created.
+#
+# @format: #optional the format of the snapshot image, default is 'qcow2'.
+#
+# 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' } }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 721b157..9d68206 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -665,10 +665,8 @@ EQMP
 
     {
         .name       = "blockdev-snapshot-sync",
-        .args_type  = "device:B,snapshot-file:s?,format:s?",
-        .params     = "device [new-image-file] [format]",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_snapshot_blkdev,
+        .args_type  = "device:B,snapshot-file:s,format:s?",
+        .mhandler.cmd_new = qmp_marshal_input_blockdev_snapshot_sync,
     },
 
 SQMP
commit 5e7caacb2583e6a4657fec51a92147f33c5bae43
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Fri Nov 25 14:57:10 2011 -0200

    qapi: Convert block_resize
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index aba7aaf..5270404 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -861,27 +861,23 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
  * existing QERR_ macro mess is cleaned up.  A good example for better
  * error reports can be found in the qemu-img resize code.
  */
-int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_block_resize(const char *device, int64_t size, Error **errp)
 {
-    const char *device = qdict_get_str(qdict, "device");
-    int64_t size = qdict_get_int(qdict, "size");
     BlockDriverState *bs;
 
     bs = bdrv_find(device);
     if (!bs) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, device);
-        return -1;
+        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        return;
     }
 
     if (size < 0) {
-        qerror_report(QERR_UNDEFINED_ERROR);
-        return -1;
+        error_set(errp, QERR_UNDEFINED_ERROR);
+        return;
     }
 
     if (bdrv_truncate(bs, size)) {
-        qerror_report(QERR_UNDEFINED_ERROR);
-        return -1;
+        error_set(errp, QERR_UNDEFINED_ERROR);
+        return;
     }
-
-    return 0;
 }
diff --git a/blockdev.h b/blockdev.h
index 93311a9..b69a549 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -65,6 +65,5 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
 int do_block_set_io_throttle(Monitor *mon,
                              const QDict *qdict, QObject **ret_data);
 int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data);
-int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 #endif
diff --git a/hmp-commands.hx b/hmp-commands.hx
index ea52271..734a364 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -57,8 +57,7 @@ ETEXI
         .args_type  = "device:B,size:o",
         .params     = "device size",
         .help       = "resize a block image",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_block_resize,
+        .mhandler.cmd = hmp_block_resize,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index e9d1711..db199b2 100644
--- a/hmp.c
+++ b/hmp.c
@@ -633,3 +633,13 @@ void hmp_balloon(Monitor *mon, const QDict *qdict)
         error_free(errp);
     }
 }
+
+void hmp_block_resize(Monitor *mon, const QDict *qdict)
+{
+    const char *device = qdict_get_str(qdict, "device");
+    int64_t size = qdict_get_int(qdict, "size");
+    Error *errp = NULL;
+
+    qmp_block_resize(device, size, &errp);
+    hmp_handle_error(mon, &errp);
+}
diff --git a/hmp.h b/hmp.h
index b0984ac..c236fd2 100644
--- a/hmp.h
+++ b/hmp.h
@@ -44,5 +44,6 @@ void hmp_inject_nmi(Monitor *mon, const QDict *qdict);
 void hmp_set_link(Monitor *mon, const QDict *qdict);
 void hmp_block_passwd(Monitor *mon, const QDict *qdict);
 void hmp_balloon(Monitor *mon, const QDict *qdict);
+void hmp_block_resize(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/qapi-schema.json b/qapi-schema.json
index 9bfdc39..f33fe00 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1052,3 +1052,21 @@
 # Since: 0.14.0
 ##
 { 'command': 'balloon', 'data': {'value': 'int'} }
+
+##
+# @block_resize
+#
+# Resize a block image while a guest is running.
+#
+# @device:  the name of the device to get the image resized
+#
+# @size:  new image size in bytes
+#
+# Returns: nothing on success
+#          If @device is not a valid block device, DeviceNotFound
+#
+# Notes: This command returns UndefinedError in a number of error conditions.
+#
+# Since: 0.14.0
+##
+{ 'command': 'block_resize', 'data': { 'device': 'str', 'size': 'int' }}
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 7c377f0..721b157 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -642,10 +642,7 @@ EQMP
     {
         .name       = "block_resize",
         .args_type  = "device:B,size:o",
-        .params     = "device size",
-        .help       = "resize a block image",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_block_resize,
+        .mhandler.cmd_new = qmp_marshal_input_block_resize,
     },
 
 SQMP
commit d72f326431e280a619a0fd55e27d3737747f8178
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Fri Nov 25 14:38:09 2011 -0200

    qapi: Convert balloon
    
    Note that the command being dropped uses the deprecated MONITOR_CMD_ASYNC
    API, but the new command is a regular synchronous command. There shouldn't
    be visible differences though, as MONITOR_CMD_ASYNC is internal only.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/balloon.c b/balloon.c
index e1cd5fa..0166744 100644
--- a/balloon.c
+++ b/balloon.c
@@ -100,31 +100,19 @@ BalloonInfo *qmp_query_balloon(Error **errp)
     return info;
 }
 
-/**
- * do_balloon(): Request VM to change its memory allocation
- */
-int do_balloon(Monitor *mon, const QDict *params,
-	       MonitorCompletion cb, void *opaque)
+void qmp_balloon(int64_t value, Error **errp)
 {
-    int64_t target;
-    int ret;
-
     if (kvm_enabled() && !kvm_has_sync_mmu()) {
-        qerror_report(QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
-        return -1;
+        error_set(errp, QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
+        return;
     }
 
-    target = qdict_get_int(params, "value");
-    if (target <= 0) {
+    if (value <= 0) {
         qerror_report(QERR_INVALID_PARAMETER_VALUE, "target", "a size");
-        return -1;
+        return;
     }
-    ret = qemu_balloon(target);
-    if (ret == 0) {
-        qerror_report(QERR_DEVICE_NOT_ACTIVE, "balloon");
-        return -1;
+    
+    if (qemu_balloon(value) == 0) {
+        error_set(errp, QERR_DEVICE_NOT_ACTIVE, "balloon");
     }
-
-    cb(opaque, NULL);
-    return 0;
 }
diff --git a/balloon.h b/balloon.h
index b36abea..b60fd5d 100644
--- a/balloon.h
+++ b/balloon.h
@@ -24,7 +24,4 @@ int qemu_add_balloon_handler(QEMUBalloonEvent *event_func,
 			     QEMUBalloonStatus *stat_func, void *opaque);
 void qemu_remove_balloon_handler(void *opaque);
 
-int do_balloon(Monitor *mon, const QDict *params,
-               MonitorCompletion cb, void *opaque);
-
 #endif
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 0bf8896..ea52271 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1022,9 +1022,7 @@ ETEXI
         .args_type  = "value:M",
         .params     = "target",
         .help       = "request VM to change its memory allocation (in MB)",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_async = do_balloon,
-        .flags      = MONITOR_CMD_ASYNC,
+        .mhandler.cmd = hmp_balloon,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 3893d59..e9d1711 100644
--- a/hmp.c
+++ b/hmp.c
@@ -621,3 +621,15 @@ void hmp_block_passwd(Monitor *mon, const QDict *qdict)
     qmp_block_passwd(device, password, &errp);
     hmp_handle_error(mon, &errp);
 }
+
+void hmp_balloon(Monitor *mon, const QDict *qdict)
+{
+    int64_t value = qdict_get_int(qdict, "value");
+    Error *errp = NULL;
+
+    qmp_balloon(value, &errp);
+    if (error_is_set(&errp)) {
+        monitor_printf(mon, "balloon: %s\n", error_get_pretty(errp));
+        error_free(errp);
+    }
+}
diff --git a/hmp.h b/hmp.h
index d6aa232..b0984ac 100644
--- a/hmp.h
+++ b/hmp.h
@@ -43,5 +43,6 @@ void hmp_cont(Monitor *mon, const QDict *qdict);
 void hmp_inject_nmi(Monitor *mon, const QDict *qdict);
 void hmp_set_link(Monitor *mon, const QDict *qdict);
 void hmp_block_passwd(Monitor *mon, const QDict *qdict);
+void hmp_balloon(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/qapi-schema.json b/qapi-schema.json
index 569aa74..9bfdc39 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1032,3 +1032,23 @@
 # Since: 0.14.0
 ##
 { 'command': 'block_passwd', 'data': {'device': 'str', 'password': 'str'} }
+
+##
+# @balloon:
+#
+# Request the balloon driver to change its balloon size.
+#
+# @value: the target size of the balloon in bytes
+#
+# Returns: Nothing on success
+#          If the balloon driver is enabled but not functional because the KVM
+#            kernel module cannot support it, KvmMissingCap
+#          If no balloon device is present, DeviceNotActive
+#
+# Notes: This command just issues a request to the guest.  When it returns,
+#        the balloon size may not have changed.  A guest can change the balloon
+#        size independent of this command.
+#
+# Since: 0.14.0
+##
+{ 'command': 'balloon', 'data': {'value': 'int'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index bbf9bfc..7c377f0 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -703,11 +703,7 @@ EQMP
     {
         .name       = "balloon",
         .args_type  = "value:M",
-        .params     = "target",
-        .help       = "request VM to change its memory allocation (in MB)",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_async = do_balloon,
-        .flags      = MONITOR_CMD_ASYNC,
+        .mhandler.cmd_new = qmp_marshal_input_balloon,
     },
 
 SQMP
commit a4dea8a9f4e0a4a863e5f3b366350fd697552d8a
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Nov 23 13:28:21 2011 -0200

    qapi: Convert block_passwd
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index dbf0251..aba7aaf 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -15,6 +15,7 @@
 #include "qemu-config.h"
 #include "sysemu.h"
 #include "block_int.h"
+#include "qmp-commands.h"
 
 static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
 
@@ -710,28 +711,25 @@ int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return eject_device(mon, bs, force);
 }
 
-int do_block_set_passwd(Monitor *mon, const QDict *qdict,
-                        QObject **ret_data)
+void qmp_block_passwd(const char *device, const char *password, Error **errp)
 {
     BlockDriverState *bs;
     int err;
 
-    bs = bdrv_find(qdict_get_str(qdict, "device"));
+    bs = bdrv_find(device);
     if (!bs) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
-        return -1;
+        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        return;
     }
 
-    err = bdrv_set_key(bs, qdict_get_str(qdict, "password"));
+    err = bdrv_set_key(bs, password);
     if (err == -EINVAL) {
-        qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
-        return -1;
+        error_set(errp, QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
+        return;
     } else if (err < 0) {
-        qerror_report(QERR_INVALID_PASSWORD);
-        return -1;
+        error_set(errp, QERR_INVALID_PASSWORD);
+        return;
     }
-
-    return 0;
 }
 
 int do_change_block(Monitor *mon, const char *device,
diff --git a/blockdev.h b/blockdev.h
index 1b48a75..93311a9 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -59,7 +59,6 @@ DriveInfo *add_init_drive(const char *opts);
 
 void do_commit(Monitor *mon, const QDict *qdict);
 int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data);
-int do_block_set_passwd(Monitor *mon, const QDict *qdict, QObject **ret_data);
 int do_change_block(Monitor *mon, const char *device,
                     const char *filename, const char *fmt);
 int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 93d4a7e..0bf8896 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1198,8 +1198,7 @@ ETEXI
         .args_type  = "device:B,password:s",
         .params     = "block_passwd device password",
         .help       = "set the password of encrypted block devices",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_block_set_passwd,
+        .mhandler.cmd = hmp_block_passwd,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 5d1687d..3893d59 100644
--- a/hmp.c
+++ b/hmp.c
@@ -611,3 +611,13 @@ void hmp_set_link(Monitor *mon, const QDict *qdict)
     qmp_set_link(name, up, &errp);
     hmp_handle_error(mon, &errp);
 }
+
+void hmp_block_passwd(Monitor *mon, const QDict *qdict)
+{
+    const char *device = qdict_get_str(qdict, "device");
+    const char *password = qdict_get_str(qdict, "password");
+    Error *errp = NULL;
+
+    qmp_block_passwd(device, password, &errp);
+    hmp_handle_error(mon, &errp);
+}
diff --git a/hmp.h b/hmp.h
index 32d7f68..d6aa232 100644
--- a/hmp.h
+++ b/hmp.h
@@ -42,5 +42,6 @@ void hmp_pmemsave(Monitor *mon, const QDict *qdict);
 void hmp_cont(Monitor *mon, const QDict *qdict);
 void hmp_inject_nmi(Monitor *mon, const QDict *qdict);
 void hmp_set_link(Monitor *mon, const QDict *qdict);
+void hmp_block_passwd(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/qapi-schema.json b/qapi-schema.json
index 1d6fb4d..569aa74 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -999,3 +999,36 @@
 #        notification.
 ##
 { 'command': 'set_link', 'data': {'name': 'str', 'up': 'bool'} }
+
+##
+# @block_passwd:
+#
+# This command sets the password of a block device that has not been open
+# with a password and requires one.
+#
+# The two cases where this can happen are a block device is created through
+# QEMU's initial command line or a block device is changed through the legacy
+# @change interface.
+#
+# In the event that the block device is created through the initial command
+# line, the VM will start in the stopped state regardless of whether '-S' is
+# used.  The intention is for a management tool to query the block devices to
+# determine which ones are encrypted, set the passwords with this command, and
+# then start the guest with the @cont command.
+#
+# @device:   the name of the device to set the password on
+#
+# @password: the password to use for the device
+#
+# Returns: nothing on success
+#          If @device is not a valid block device, DeviceNotFound
+#          If @device is not encrypted, DeviceNotEncrypted
+#          If @password is not valid for this device, InvalidPassword
+#
+# Notes:  Not all block formats support encryption and some that do are not
+#         able to validate that a password is correct.  Disk corruption may
+#         occur if an invalid password is specified.
+#
+# Since: 0.14.0
+##
+{ 'command': 'block_passwd', 'data': {'device': 'str', 'password': 'str'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 5054da3..bbf9bfc 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -806,10 +806,7 @@ EQMP
     {
         .name       = "block_passwd",
         .args_type  = "device:B,password:s",
-        .params     = "block_passwd device password",
-        .help       = "set the password of encrypted block devices",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_block_set_passwd,
+        .mhandler.cmd_new = qmp_marshal_input_block_passwd,
     },
 
 SQMP
commit 4b37156c40c3d7d63ac332e3bb9f85a66c3f5e5e
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Nov 23 13:11:55 2011 -0200

    qapi: Convert set_link
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index b82aff8..93d4a7e 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1038,8 +1038,7 @@ ETEXI
         .args_type  = "name:s,up:b",
         .params     = "name on|off",
         .help       = "change the link status of a network adapter",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_set_link,
+        .mhandler.cmd = hmp_set_link,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 0ebc398..5d1687d 100644
--- a/hmp.c
+++ b/hmp.c
@@ -601,3 +601,13 @@ void hmp_inject_nmi(Monitor *mon, const QDict *qdict)
     qmp_inject_nmi(&errp);
     hmp_handle_error(mon, &errp);
 }
+
+void hmp_set_link(Monitor *mon, const QDict *qdict)
+{
+    const char *name = qdict_get_str(qdict, "name");
+    int up = qdict_get_bool(qdict, "up");
+    Error *errp = NULL;
+
+    qmp_set_link(name, up, &errp);
+    hmp_handle_error(mon, &errp);
+}
diff --git a/hmp.h b/hmp.h
index 8a31f87..32d7f68 100644
--- a/hmp.h
+++ b/hmp.h
@@ -41,5 +41,6 @@ void hmp_memsave(Monitor *mon, const QDict *qdict);
 void hmp_pmemsave(Monitor *mon, const QDict *qdict);
 void hmp_cont(Monitor *mon, const QDict *qdict);
 void hmp_inject_nmi(Monitor *mon, const QDict *qdict);
+void hmp_set_link(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/net.c b/net.c
index cb52050..f7bebf8 100644
--- a/net.c
+++ b/net.c
@@ -34,6 +34,7 @@
 #include "monitor.h"
 #include "qemu-common.h"
 #include "qemu_socket.h"
+#include "qmp-commands.h"
 #include "hw/qdev.h"
 #include "iov.h"
 
@@ -1258,12 +1259,10 @@ void do_info_network(Monitor *mon)
     }
 }
 
-int do_set_link(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_set_link(const char *name, bool up, Error **errp)
 {
     VLANState *vlan;
     VLANClientState *vc = NULL;
-    const char *name = qdict_get_str(qdict, "name");
-    int up = qdict_get_bool(qdict, "up");
 
     QTAILQ_FOREACH(vlan, &vlans, next) {
         QTAILQ_FOREACH(vc, &vlan->clients, next) {
@@ -1280,8 +1279,8 @@ int do_set_link(Monitor *mon, const QDict *qdict, QObject **ret_data)
 done:
 
     if (!vc) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, name);
-        return -1;
+        error_set(errp, QERR_DEVICE_NOT_FOUND, name);
+        return;
     }
 
     vc->link_down = !up;
@@ -1300,7 +1299,6 @@ done:
     if (vc->peer && vc->peer->info->link_status_changed) {
         vc->peer->info->link_status_changed(vc->peer);
     }
-    return 0;
 }
 
 void net_cleanup(void)
diff --git a/net.h b/net.h
index 9f633f8..c6b4190 100644
--- a/net.h
+++ b/net.h
@@ -122,7 +122,6 @@ int qemu_find_nic_model(NICInfo *nd, const char * const *models,
                         const char *default_model);
 
 void do_info_network(Monitor *mon);
-int do_set_link(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 /* NIC info */
 
diff --git a/qapi-schema.json b/qapi-schema.json
index fea513f..1d6fb4d 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -979,3 +979,23 @@
 # Notes: Only x86 Virtual Machines support this command.
 ##
 { 'command': 'inject-nmi' }
+
+##
+# @set_link:
+#
+# Sets the link status of a virtual network adapter.
+#
+# @name: the device name of the virtual network adapter
+#
+# @up: true to set the link status to be up
+#
+# Returns: Nothing on success
+#          If @name is not a valid network device, DeviceNotFound
+#
+# Since: 0.14.0
+#
+# Notes: Not all network adapters support setting link status.  This command
+#        will succeed even if the network adapter does not support link status
+#        notification.
+##
+{ 'command': 'set_link', 'data': {'name': 'str', 'up': 'bool'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 2e76708..5054da3 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -730,10 +730,7 @@ EQMP
     {
         .name       = "set_link",
         .args_type  = "name:s,up:b",
-        .params     = "name on|off",
-        .help       = "change the link status of a network adapter",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_set_link,
+        .mhandler.cmd_new = qmp_marshal_input_set_link,
     },
 
 SQMP
commit ab49ab5c488237f3656689c4a3cab29e29884ca6
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Nov 23 12:55:53 2011 -0200

    qapi: Convert inject-nmi
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/cpus.c b/cpus.c
index e916137..7b9f8eb 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1213,3 +1213,16 @@ void qmp_pmemsave(int64_t addr, int64_t size, const char *filename,
 exit:
     fclose(f);
 }
+
+void qmp_inject_nmi(Error **errp)
+{
+#if defined(TARGET_I386)
+    CPUState *env;
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        cpu_interrupt(env, CPU_INTERRUPT_NMI);
+    }
+#else
+    error_set(errp, QERR_UNSUPPORTED);
+#endif
+}
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 9503751..b82aff8 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -736,8 +736,7 @@ ETEXI
         .args_type  = "",
         .params     = "",
         .help       = "inject an NMI on all guest's CPUs",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_inject_nmi,
+        .mhandler.cmd = hmp_inject_nmi,
     },
 #endif
 STEXI
diff --git a/hmp.c b/hmp.c
index d623526..0ebc398 100644
--- a/hmp.c
+++ b/hmp.c
@@ -593,3 +593,11 @@ void hmp_cont(Monitor *mon, const QDict *qdict)
         hmp_handle_error(mon, &errp);
     }
 }
+
+void hmp_inject_nmi(Monitor *mon, const QDict *qdict)
+{
+    Error *errp = NULL;
+
+    qmp_inject_nmi(&errp);
+    hmp_handle_error(mon, &errp);
+}
diff --git a/hmp.h b/hmp.h
index b034704..8a31f87 100644
--- a/hmp.h
+++ b/hmp.h
@@ -40,5 +40,6 @@ void hmp_cpu(Monitor *mon, const QDict *qdict);
 void hmp_memsave(Monitor *mon, const QDict *qdict);
 void hmp_pmemsave(Monitor *mon, const QDict *qdict);
 void hmp_cont(Monitor *mon, const QDict *qdict);
+void hmp_inject_nmi(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/monitor.c b/monitor.c
index b0d1862..62b1747 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2204,25 +2204,6 @@ static void do_wav_capture(Monitor *mon, const QDict *qdict)
 }
 #endif
 
-#if defined(TARGET_I386)
-static int do_inject_nmi(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    CPUState *env;
-
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu_interrupt(env, CPU_INTERRUPT_NMI);
-    }
-
-    return 0;
-}
-#else
-static int do_inject_nmi(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    qerror_report(QERR_UNSUPPORTED);
-    return -1;
-}
-#endif
-
 static qemu_acl *find_acl(Monitor *mon, const char *name)
 {
     qemu_acl *acl = qemu_acl_find(name);
diff --git a/qapi-schema.json b/qapi-schema.json
index b6fd3f1..fea513f 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -966,3 +966,16 @@
 ##
 { 'command': 'cont' }
 
+##
+# @inject-nmi:
+#
+# Injects an Non-Maskable Interrupt into all guest's VCPUs.
+#
+# Returns:  If successful, nothing
+#           If the Virtual Machine doesn't support NMI injection, Unsupported
+#
+# Since:  0.14.0
+#
+# Notes: Only x86 Virtual Machines support this command.
+##
+{ 'command': 'inject-nmi' }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 03b2617..2e76708 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -407,10 +407,7 @@ EQMP
     {
         .name       = "inject-nmi",
         .args_type  = "",
-        .params     = "",
-        .help       = "",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_inject_nmi,
+        .mhandler.cmd_new = qmp_marshal_input_inject_nmi,
     },
 
 SQMP
commit e42e818bf45f2f70cdd88a3864efcc3964039f37
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Tue Nov 22 17:58:31 2011 -0200

    qapi: Convert cont
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 0a721cc..9503751 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -304,8 +304,7 @@ ETEXI
         .args_type  = "",
         .params     = "",
         .help       = "resume emulation",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_cont,
+        .mhandler.cmd = hmp_cont,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 96e3ce1..d623526 100644
--- a/hmp.c
+++ b/hmp.c
@@ -561,3 +561,35 @@ void hmp_pmemsave(Monitor *mon, const QDict *qdict)
     qmp_pmemsave(addr, size, filename, &errp);
     hmp_handle_error(mon, &errp);
 }
+
+static void hmp_cont_cb(void *opaque, int err)
+{
+    Monitor *mon = opaque;
+
+    if (!err) {
+        hmp_cont(mon, NULL);
+    }
+}
+
+void hmp_cont(Monitor *mon, const QDict *qdict)
+{
+    Error *errp = NULL;
+
+    qmp_cont(&errp);
+    if (error_is_set(&errp)) {
+        if (error_is_type(errp, QERR_DEVICE_ENCRYPTED)) {
+            const char *device;
+
+            /* The device is encrypted. Ask the user for the password
+               and retry */
+
+            device = error_get_field(errp, "device");
+            assert(device != NULL);
+
+            monitor_read_block_device_key(mon, device, hmp_cont_cb, mon);
+            error_free(errp);
+            return;
+        }
+        hmp_handle_error(mon, &errp);
+    }
+}
diff --git a/hmp.h b/hmp.h
index 4882bea..b034704 100644
--- a/hmp.h
+++ b/hmp.h
@@ -39,5 +39,6 @@ void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
 void hmp_cpu(Monitor *mon, const QDict *qdict);
 void hmp_memsave(Monitor *mon, const QDict *qdict);
 void hmp_pmemsave(Monitor *mon, const QDict *qdict);
+void hmp_cont(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/monitor.c b/monitor.c
index a1b46b3..b0d1862 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1073,65 +1073,6 @@ static void do_singlestep(Monitor *mon, const QDict *qdict)
     }
 }
 
-static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs);
-
-struct bdrv_iterate_context {
-    Monitor *mon;
-    int err;
-};
-
-static void iostatus_bdrv_it(void *opaque, BlockDriverState *bs)
-{
-    bdrv_iostatus_reset(bs);
-}
-
-/**
- * do_cont(): Resume emulation.
- */
-static int do_cont(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    struct bdrv_iterate_context context = { mon, 0 };
-
-    if (runstate_check(RUN_STATE_INMIGRATE)) {
-        qerror_report(QERR_MIGRATION_EXPECTED);
-        return -1;
-    } else if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
-               runstate_check(RUN_STATE_SHUTDOWN)) {
-        qerror_report(QERR_RESET_REQUIRED);
-        return -1;
-    }
-
-    bdrv_iterate(iostatus_bdrv_it, NULL);
-    bdrv_iterate(encrypted_bdrv_it, &context);
-    /* only resume the vm if all keys are set and valid */
-    if (!context.err) {
-        vm_start();
-        return 0;
-    } else {
-        return -1;
-    }
-}
-
-static void bdrv_key_cb(void *opaque, int err)
-{
-    Monitor *mon = opaque;
-
-    /* another key was set successfully, retry to continue */
-    if (!err)
-        do_cont(mon, NULL, NULL);
-}
-
-static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
-{
-    struct bdrv_iterate_context *context = opaque;
-
-    if (!context->err && bdrv_key_required(bs)) {
-        context->err = -EBUSY;
-        monitor_read_bdrv_key_start(context->mon, bs, bdrv_key_cb,
-                                    context->mon);
-    }
-}
-
 static void do_gdbserver(Monitor *mon, const QDict *qdict)
 {
     const char *device = qdict_get_try_str(qdict, "device");
@@ -4858,3 +4799,18 @@ int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
 
     return err;
 }
+
+int monitor_read_block_device_key(Monitor *mon, const char *device,
+                                  BlockDriverCompletionFunc *completion_cb,
+                                  void *opaque)
+{
+    BlockDriverState *bs;
+
+    bs = bdrv_find(device);
+    if (!bs) {
+        monitor_printf(mon, "Device not found %s\n", device);
+        return -1;
+    }
+
+    return monitor_read_bdrv_key_start(mon, bs, completion_cb, opaque);
+}
diff --git a/monitor.h b/monitor.h
index e76795f..052f1cb 100644
--- a/monitor.h
+++ b/monitor.h
@@ -49,6 +49,9 @@ void monitor_resume(Monitor *mon);
 int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
                                 BlockDriverCompletionFunc *completion_cb,
                                 void *opaque);
+int monitor_read_block_device_key(Monitor *mon, const char *device,
+                                  BlockDriverCompletionFunc *completion_cb,
+                                  void *opaque);
 
 int monitor_get_fd(Monitor *mon, const char *fdname);
 
diff --git a/qapi-schema.json b/qapi-schema.json
index 7f9aa94..b6fd3f1 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -949,3 +949,20 @@
 ##
 { 'command': 'pmemsave',
   'data': {'val': 'int', 'size': 'int', 'filename': 'str'} }
+
+##
+# @cont:
+#
+# Resume guest VCPU execution.
+#
+# Since:  0.14.0
+#
+# Returns:  If successful, nothing
+#           If the QEMU is waiting for an incoming migration, MigrationExpected
+#           If QEMU was started with an encrypted block device and a key has
+#              not yet been set, DeviceEncrypted.
+#
+# Notes:  This command will succeed if the guest is currently running.
+##
+{ 'command': 'cont' }
+
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 5093ac9..03b2617 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -199,10 +199,7 @@ EQMP
     {
         .name       = "cont",
         .args_type  = "",
-        .params     = "",
-        .help       = "resume emulation",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_cont,
+        .mhandler.cmd_new = qmp_marshal_input_cont,
     },
 
 SQMP
diff --git a/qmp.c b/qmp.c
index 511dd62..d71ceb4 100644
--- a/qmp.c
+++ b/qmp.c
@@ -117,3 +117,40 @@ SpiceInfo *qmp_query_spice(Error **errp)
     return NULL;
 };
 #endif
+
+static void iostatus_bdrv_it(void *opaque, BlockDriverState *bs)
+{
+    bdrv_iostatus_reset(bs);
+}
+
+static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
+{
+    Error **err = opaque;
+
+    if (!error_is_set(err) && bdrv_key_required(bs)) {
+        error_set(err, QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs));
+    }
+}
+
+void qmp_cont(Error **errp)
+{
+    Error *local_err = NULL;
+
+    if (runstate_check(RUN_STATE_INMIGRATE)) {
+        error_set(errp, QERR_MIGRATION_EXPECTED);
+        return;
+    } else if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
+               runstate_check(RUN_STATE_SHUTDOWN)) {
+        error_set(errp, QERR_RESET_REQUIRED);
+        return;
+    }
+
+    bdrv_iterate(iostatus_bdrv_it, NULL);
+    bdrv_iterate(encrypted_bdrv_it, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    vm_start();
+}
commit 6d3962bf848ba06296554976f9fd86af805584bb
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Tue Nov 22 17:26:46 2011 -0200

    qapi: Convert pmemsave
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/cpus.c b/cpus.c
index 0f2ce60..e916137 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1183,3 +1183,33 @@ void qmp_memsave(int64_t addr, int64_t size, const char *filename,
 exit:
     fclose(f);
 }
+
+void qmp_pmemsave(int64_t addr, int64_t size, const char *filename,
+                  Error **errp)
+{
+    FILE *f;
+    uint32_t l;
+    uint8_t buf[1024];
+
+    f = fopen(filename, "wb");
+    if (!f) {
+        error_set(errp, QERR_OPEN_FILE_FAILED, filename);
+        return;
+    }
+
+    while (size != 0) {
+        l = sizeof(buf);
+        if (l > size)
+            l = size;
+        cpu_physical_memory_rw(addr, buf, l, 0);
+        if (fwrite(buf, 1, l, f) != l) {
+            error_set(errp, QERR_IO_ERROR);
+            goto exit;
+        }
+        addr += l;
+        size -= l;
+    }
+
+exit:
+    fclose(f);
+}
diff --git a/hmp-commands.hx b/hmp-commands.hx
index dac0b47..0a721cc 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -703,8 +703,7 @@ ETEXI
         .args_type  = "val:l,size:i,filename:s",
         .params     = "addr size file",
         .help       = "save to disk physical memory dump starting at 'addr' of size 'size'",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_physical_memory_save,
+        .mhandler.cmd = hmp_pmemsave,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 67b3eb3..96e3ce1 100644
--- a/hmp.c
+++ b/hmp.c
@@ -550,3 +550,14 @@ void hmp_memsave(Monitor *mon, const QDict *qdict)
     qmp_memsave(addr, size, filename, true, monitor_get_cpu_index(), &errp);
     hmp_handle_error(mon, &errp);
 }
+
+void hmp_pmemsave(Monitor *mon, const QDict *qdict)
+{
+    uint32_t size = qdict_get_int(qdict, "size");
+    const char *filename = qdict_get_str(qdict, "filename");
+    uint64_t addr = qdict_get_int(qdict, "val");
+    Error *errp = NULL;
+
+    qmp_pmemsave(addr, size, filename, &errp);
+    hmp_handle_error(mon, &errp);
+}
diff --git a/hmp.h b/hmp.h
index dd8ad0c..4882bea 100644
--- a/hmp.h
+++ b/hmp.h
@@ -38,5 +38,6 @@ void hmp_system_reset(Monitor *mon, const QDict *qdict);
 void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
 void hmp_cpu(Monitor *mon, const QDict *qdict);
 void hmp_memsave(Monitor *mon, const QDict *qdict);
+void hmp_pmemsave(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/monitor.c b/monitor.c
index 7272014..a1b46b3 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1370,43 +1370,6 @@ static void do_print(Monitor *mon, const QDict *qdict)
     monitor_printf(mon, "\n");
 }
 
-static int do_physical_memory_save(Monitor *mon, const QDict *qdict,
-                                    QObject **ret_data)
-{
-    FILE *f;
-    uint32_t l;
-    uint8_t buf[1024];
-    uint32_t size = qdict_get_int(qdict, "size");
-    const char *filename = qdict_get_str(qdict, "filename");
-    target_phys_addr_t addr = qdict_get_int(qdict, "val");
-    int ret = -1;
-
-    f = fopen(filename, "wb");
-    if (!f) {
-        qerror_report(QERR_OPEN_FILE_FAILED, filename);
-        return -1;
-    }
-    while (size != 0) {
-        l = sizeof(buf);
-        if (l > size)
-            l = size;
-        cpu_physical_memory_read(addr, buf, l);
-        if (fwrite(buf, 1, l, f) != l) {
-            monitor_printf(mon, "fwrite() error in do_physical_memory_save\n");
-            goto exit;
-        }
-        fflush(f);
-        addr += l;
-        size -= l;
-    }
-
-    ret = 0;
-
-exit:
-    fclose(f);
-    return ret;
-}
-
 static void do_sum(Monitor *mon, const QDict *qdict)
 {
     uint32_t addr;
diff --git a/qapi-schema.json b/qapi-schema.json
index dbf6170..7f9aa94 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -927,3 +927,25 @@
 ##
 { 'command': 'memsave',
   'data': {'val': 'int', 'size': 'int', 'filename': 'str', '*cpu-index': 'int'} }
+
+##
+# @pmemsave:
+#
+# Save a portion of guest physical memory to a file.
+#
+# @val: the physical address of the guest to start from
+#
+# @size: the size of memory region to save
+#
+# @filename: the file to save the memory to as binary data
+#
+# Returns: Nothing on success
+#          If @filename cannot be opened, OpenFileFailed
+#          If an I/O error occurs while writing the file, IOError
+#
+# Since: 0.14.0
+#
+# Notes: Errors were not reliably returned until 1.1
+##
+{ 'command': 'pmemsave',
+  'data': {'val': 'int', 'size': 'int', 'filename': 'str'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 0e2f392..5093ac9 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -382,10 +382,7 @@ EQMP
     {
         .name       = "pmemsave",
         .args_type  = "val:l,size:i,filename:s",
-        .params     = "addr size file",
-        .help       = "save to disk physical memory dump starting at 'addr' of size 'size'",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_physical_memory_save,
+        .mhandler.cmd_new = qmp_marshal_input_pmemsave,
     },
 
 SQMP
commit 0cfd6a9ab4356cd2c69bb29b1d70e1fd037bc1f2
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Tue Nov 22 16:32:37 2011 -0200

    qapi: Convert memsave
    
    Please, note that the QMP command has a new 'cpu-index' parameter.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/cpus.c b/cpus.c
index ca46ec6..0f2ce60 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1136,3 +1136,50 @@ CpuInfoList *qmp_query_cpus(Error **errp)
 
     return head;
 }
+
+void qmp_memsave(int64_t addr, int64_t size, const char *filename,
+                 bool has_cpu, int64_t cpu_index, Error **errp)
+{
+    FILE *f;
+    uint32_t l;
+    CPUState *env;
+    uint8_t buf[1024];
+
+    if (!has_cpu) {
+        cpu_index = 0;
+    }
+
+    for (env = first_cpu; env; env = env->next_cpu) {
+        if (cpu_index == env->cpu_index) {
+            break;
+        }
+    }
+
+    if (env == NULL) {
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
+                  "a CPU number");
+        return;
+    }
+
+    f = fopen(filename, "wb");
+    if (!f) {
+        error_set(errp, QERR_OPEN_FILE_FAILED, filename);
+        return;
+    }
+
+    while (size != 0) {
+        l = sizeof(buf);
+        if (l > size)
+            l = size;
+        cpu_memory_rw_debug(env, addr, buf, l, 0);
+        if (fwrite(buf, 1, l, f) != l) {
+            error_set(errp, QERR_IO_ERROR);
+            goto exit;
+        }
+        addr += l;
+        size -= l;
+    }
+
+exit:
+    fclose(f);
+}
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 79a9195..dac0b47 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -689,8 +689,7 @@ ETEXI
         .args_type  = "val:l,size:i,filename:s",
         .params     = "addr size file",
         .help       = "save to disk virtual memory dump starting at 'addr' of size 'size'",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_memory_save,
+        .mhandler.cmd = hmp_memsave,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index dfab7ad..67b3eb3 100644
--- a/hmp.c
+++ b/hmp.c
@@ -14,6 +14,14 @@
 #include "hmp.h"
 #include "qmp-commands.h"
 
+static void hmp_handle_error(Monitor *mon, Error **errp)
+{
+    if (error_is_set(errp)) {
+        monitor_printf(mon, "%s\n", error_get_pretty(*errp));
+        error_free(*errp);
+    }
+}
+
 void hmp_info_name(Monitor *mon)
 {
     NameInfo *info;
@@ -531,3 +539,14 @@ void hmp_cpu(Monitor *mon, const QDict *qdict)
         monitor_printf(mon, "invalid CPU index\n");
     }
 }
+
+void hmp_memsave(Monitor *mon, const QDict *qdict)
+{
+    uint32_t size = qdict_get_int(qdict, "size");
+    const char *filename = qdict_get_str(qdict, "filename");
+    uint64_t addr = qdict_get_int(qdict, "val");
+    Error *errp = NULL;
+
+    qmp_memsave(addr, size, filename, true, monitor_get_cpu_index(), &errp);
+    hmp_handle_error(mon, &errp);
+}
diff --git a/hmp.h b/hmp.h
index 4422578..dd8ad0c 100644
--- a/hmp.h
+++ b/hmp.h
@@ -37,5 +37,6 @@ void hmp_stop(Monitor *mon, const QDict *qdict);
 void hmp_system_reset(Monitor *mon, const QDict *qdict);
 void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
 void hmp_cpu(Monitor *mon, const QDict *qdict);
+void hmp_memsave(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/monitor.c b/monitor.c
index 344b196..7272014 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1370,44 +1370,6 @@ static void do_print(Monitor *mon, const QDict *qdict)
     monitor_printf(mon, "\n");
 }
 
-static int do_memory_save(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    FILE *f;
-    uint32_t size = qdict_get_int(qdict, "size");
-    const char *filename = qdict_get_str(qdict, "filename");
-    target_long addr = qdict_get_int(qdict, "val");
-    uint32_t l;
-    CPUState *env;
-    uint8_t buf[1024];
-    int ret = -1;
-
-    env = mon_get_cpu();
-
-    f = fopen(filename, "wb");
-    if (!f) {
-        qerror_report(QERR_OPEN_FILE_FAILED, filename);
-        return -1;
-    }
-    while (size != 0) {
-        l = sizeof(buf);
-        if (l > size)
-            l = size;
-        cpu_memory_rw_debug(env, addr, buf, l, 0);
-        if (fwrite(buf, 1, l, f) != l) {
-            monitor_printf(mon, "fwrite() error in do_memory_save\n");
-            goto exit;
-        }
-        addr += l;
-        size -= l;
-    }
-
-    ret = 0;
-
-exit:
-    fclose(f);
-    return ret;
-}
-
 static int do_physical_memory_save(Monitor *mon, const QDict *qdict,
                                     QObject **ret_data)
 {
diff --git a/qapi-schema.json b/qapi-schema.json
index fbbdbe0..dbf6170 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -901,3 +901,29 @@
 # Notes: Do not use this command.
 ##
 { 'command': 'cpu', 'data': {'index': 'int'} }
+
+##
+# @memsave:
+#
+# Save a portion of guest memory to a file.
+#
+# @val: the virtual address of the guest to start from
+#
+# @size: the size of memory region to save
+#
+# @filename: the file to save the memory to as binary data
+#
+# @cpu-index: #optional the index of the virtual CPU to use for translating the
+#                       virtual address (defaults to CPU 0)
+#
+# Returns: Nothing on success
+#          If @cpu is not a valid VCPU, InvalidParameterValue
+#          If @filename cannot be opened, OpenFileFailed
+#          If an I/O error occurs while writing the file, IOError
+#
+# Since: 0.14.0
+#
+# Notes: Errors were not reliably returned until 1.1
+##
+{ 'command': 'memsave',
+  'data': {'val': 'int', 'size': 'int', 'filename': 'str', '*cpu-index': 'int'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 4fcb92c..0e2f392 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -352,11 +352,8 @@ EQMP
 
     {
         .name       = "memsave",
-        .args_type  = "val:l,size:i,filename:s",
-        .params     = "addr size file",
-        .help       = "save to disk virtual memory dump starting at 'addr' of size 'size'",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_memory_save,
+        .args_type  = "val:l,size:i,filename:s,cpu:i?",
+        .mhandler.cmd_new = qmp_marshal_input_memsave,
     },
 
 SQMP
@@ -370,6 +367,7 @@ Arguments:
 - "val": the starting address (json-int)
 - "size": the memory size, in bytes (json-int)
 - "filename": file path (json-string)
+- "cpu": virtual CPU index (json-int, optional)
 
 Example:
 
@@ -379,8 +377,6 @@ Example:
                             "filename": "/tmp/virtual-mem-dump" } }
 <- { "return": {} }
 
-Note: Depends on the current CPU.
-
 EQMP
 
     {
commit 588988736634ad2aa356dafac78f88d1ea68b1a4
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Tue Nov 22 16:29:52 2011 -0200

    QError: Introduce QERR_IO_ERROR
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qerror.c b/qerror.c
index 656efc2..b544ced 100644
--- a/qerror.c
+++ b/qerror.c
@@ -149,6 +149,10 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Password incorrect",
     },
     {
+        .error_fmt = QERR_IO_ERROR,
+        .desc      = "An IO error has occurred",
+    },
+    {
         .error_fmt = QERR_JSON_PARSING,
         .desc      = "Invalid JSON syntax",
     },
diff --git a/qerror.h b/qerror.h
index 161d654..1fee39d 100644
--- a/qerror.h
+++ b/qerror.h
@@ -126,6 +126,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_INVALID_PASSWORD \
     "{ 'class': 'InvalidPassword', 'data': {} }"
 
+#define QERR_IO_ERROR \
+    "{ 'class': 'IOError', 'data': {} }"
+
 #define QERR_JSON_PARSING \
     "{ 'class': 'JSONParsing', 'data': {} }"
 
commit 25e48c849a64d5ceb71814b4cd08e1341fa2e899
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Sun Nov 27 23:07:45 2011 -0200

    console: Drop unused prototypes
    
    Commit e235cec3762d2aa20b548114ea7b172113690463 converted the query-mice
    command to the QAPI but forgot to remove two prototypes used by the old
    QAPI. Drop them.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/console.h b/console.h
index 6ac4ed3..9466886 100644
--- a/console.h
+++ b/console.h
@@ -74,8 +74,6 @@ struct MouseTransformInfo {
     int a[7];
 };
 
-void do_info_mice_print(Monitor *mon, const QObject *data);
-void do_info_mice(Monitor *mon, QObject **ret_data);
 void do_mouse_set(Monitor *mon, const QDict *qdict);
 
 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
commit 22e1bb9c15d932b44a2dc6fc4691ed22d5a1212f
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Sun Nov 27 22:40:03 2011 -0200

    qapi: Complete system_powerdown conversion
    
    Commit 5bc465e4b1b6f4582a400c0a7033a1c841744278 converted only
    the HMP part of the system_powerdown command to the QAPI, this
    commit completes it by converting the QMP part too.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/monitor.c b/monitor.c
index 1be222e..344b196 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1796,16 +1796,6 @@ static void do_boot_set(Monitor *mon, const QDict *qdict)
     }
 }
 
-/**
- * do_system_powerdown(): Issue a machine powerdown
- */
-static int do_system_powerdown(Monitor *mon, const QDict *qdict,
-                               QObject **ret_data)
-{
-    qemu_system_powerdown_request();
-    return 0;
-}
-
 #if defined(TARGET_I386)
 static void print_pte(Monitor *mon, target_phys_addr_t addr,
                       target_phys_addr_t pte,
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 94da2a8..4fcb92c 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -244,10 +244,7 @@ EQMP
     {
         .name       = "system_powerdown",
         .args_type  = "",
-        .params     = "",
-        .help       = "send system power down event",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_system_powerdown,
+        .mhandler.cmd_new = qmp_marshal_input_system_powerdown,
     },
 
 SQMP
commit 81244ff56d9a845327520fa42c4bef27649d029e
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon Nov 21 14:28:29 2011 -0200

    Drop test-visitor
    
    It has been superseded by the two previous commits, which introduced
    the test-qmp-output-visitor and test-qmp-input-visitor tests.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/Makefile b/Makefile
index c4884fc..2c03055 100644
--- a/Makefile
+++ b/Makefile
@@ -169,7 +169,7 @@ test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y)
 
 $(qapi-obj-y): $(GENERATED_HEADERS)
 qapi-dir := $(BUILD_DIR)/qapi-generated
-test-qmp-input-visitor.o test-qmp-output-visitor.o test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
+test-qmp-input-visitor.o test-qmp-output-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
 
 $(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
@@ -202,9 +202,6 @@ qmp-commands.h qmp-marshal.c :\
 $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -m -o "." < $<, "  GEN   $@")
 
-test-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
-test-visitor: test-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
-
 test-qmp-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
 test-qmp-output-visitor: test-qmp-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
 
diff --git a/test-visitor.c b/test-visitor.c
deleted file mode 100644
index f90b711..0000000
--- a/test-visitor.c
+++ /dev/null
@@ -1,338 +0,0 @@
-#include <glib.h>
-#include "qapi/qmp-output-visitor.h"
-#include "qapi/qmp-input-visitor.h"
-#include "test-qapi-types.h"
-#include "test-qapi-visit.h"
-#include "qemu-objects.h"
-
-typedef struct TestStruct
-{
-    int64_t x;
-    int64_t y;
-} TestStruct;
-
-typedef struct TestStructList
-{
-    TestStruct *value;
-    struct TestStructList *next;
-} TestStructList;
-
-static void visit_type_TestStruct(Visitor *v, TestStruct **obj, const char *name, Error **errp)
-{
-    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct), errp);
-    visit_type_int(v, &(*obj)->x, "x", errp);
-    visit_type_int(v, &(*obj)->y, "y", errp);
-    visit_end_struct(v, errp);
-}
-
-static void visit_type_TestStructList(Visitor *m, TestStructList ** obj, const char *name, Error **errp)
-{
-    GenericList *i, **head = (GenericList **)obj;
-
-    visit_start_list(m, name, errp);
-
-    for (*head = i = visit_next_list(m, head, errp); i; i = visit_next_list(m, &i, errp)) {
-        TestStructList *native_i = (TestStructList *)i;
-        visit_type_TestStruct(m, &native_i->value, NULL, errp);
-    }
-
-    visit_end_list(m, errp);
-}
-
-/* test core visitor methods */
-static void test_visitor_core(void)
-{
-    QmpOutputVisitor *mo;
-    QmpInputVisitor *mi;
-    Visitor *v;
-    TestStruct ts = { 42, 82 };
-    TestStruct *pts = &ts;
-    TestStructList *lts = NULL;
-    Error *err = NULL;
-    QObject *obj;
-    QList *qlist;
-    QDict *qdict;
-    QString *str;
-    int64_t value = 0;
-
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-
-    visit_type_TestStruct(v, &pts, NULL, &err);
-
-    obj = qmp_output_get_qobject(mo);
-
-    str = qobject_to_json(obj);
-
-    printf("%s\n", qstring_get_str(str));
-
-    QDECREF(str);
-
-    obj = QOBJECT(qint_from_int(0x42));
-
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-
-    visit_type_int(v, &value, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-
-    g_assert(value == 0x42);
-
-    qobject_decref(obj);
-
-    obj = qobject_from_json("{'x': 42, 'y': 84}");
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-
-    pts = NULL;
-
-    visit_type_TestStruct(v, &pts, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-
-    g_assert(pts != NULL);
-    g_assert(pts->x == 42);
-    g_assert(pts->y == 84);
-
-    qobject_decref(obj);
-    g_free(pts);
-
-    /* test list input visitor */
-    obj = qobject_from_json("[{'x': 42, 'y': 84}, {'x': 12, 'y': 24}]");
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-
-    visit_type_TestStructList(v, &lts, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-
-    g_assert(lts != NULL);
-    g_assert(lts->value->x == 42);
-    g_assert(lts->value->y == 84);
-
-    g_assert(lts->next != NULL);
-    g_assert(lts->next->value->x == 12);
-    g_assert(lts->next->value->y == 24);
-    g_assert(lts->next->next == NULL);
-
-    qobject_decref(obj);
-
-    /* test list output visitor */
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-    visit_type_TestStructList(v, &lts, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    obj = qmp_output_get_qobject(mo);
-    g_print("obj: %s\n", qstring_get_str(qobject_to_json(obj)));
-
-    qlist = qobject_to_qlist(obj);
-    assert(qlist);
-    obj = qlist_pop(qlist);
-    qdict = qobject_to_qdict(obj);
-    assert(qdict);
-    assert(qdict_get_int(qdict, "x") == 42);
-    assert(qdict_get_int(qdict, "y") == 84);
-    qobject_decref(obj);
-
-    obj = qlist_pop(qlist);
-    qdict = qobject_to_qdict(obj);
-    assert(qdict);
-    assert(qdict_get_int(qdict, "x") == 12);
-    assert(qdict_get_int(qdict, "y") == 24);
-    qobject_decref(obj);
-
-    qmp_output_visitor_cleanup(mo);
-    QDECREF(qlist);
-}
-
-/* test deep nesting with refs to other user-defined types */
-static void test_nested_structs(void)
-{
-    QmpOutputVisitor *mo;
-    QmpInputVisitor *mi;
-    Visitor *v;
-    UserDefOne ud1;
-    UserDefOne *ud1_p = &ud1, *ud1c_p = NULL;
-    UserDefTwo ud2;
-    UserDefTwo *ud2_p = &ud2, *ud2c_p = NULL;
-    Error *err = NULL;
-    QObject *obj;
-    QString *str;
-
-    ud1.integer = 42;
-    ud1.string = strdup("forty two");
-
-    /* sanity check */
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-    visit_type_UserDefOne(v, &ud1_p, "o_O", &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    obj = qmp_output_get_qobject(mo);
-    g_assert(obj);
-    qobject_decref(obj);
-
-    ud2.string = strdup("forty three");
-    ud2.dict.string = strdup("forty four");
-    ud2.dict.dict.userdef = ud1_p;
-    ud2.dict.dict.string = strdup("forty five");
-    ud2.dict.has_dict2 = true;
-    ud2.dict.dict2.userdef = ud1_p;
-    ud2.dict.dict2.string = strdup("forty six");
-
-    /* c type -> qobject */
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-    visit_type_UserDefTwo(v, &ud2_p, "unused", &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    obj = qmp_output_get_qobject(mo);
-    g_assert(obj);
-    str = qobject_to_json_pretty(obj);
-    g_print("%s\n", qstring_get_str(str));
-    QDECREF(str);
-
-    /* qobject -> c type, should match original struct */
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-    visit_type_UserDefTwo(v, &ud2c_p, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-
-    g_assert(!g_strcmp0(ud2c_p->string, ud2.string));
-    g_assert(!g_strcmp0(ud2c_p->dict.string, ud2.dict.string));
-
-    ud1c_p = ud2c_p->dict.dict.userdef;
-    g_assert(ud1c_p->integer == ud1_p->integer);
-    g_assert(!g_strcmp0(ud1c_p->string, ud1_p->string));
-
-    g_assert(!g_strcmp0(ud2c_p->dict.dict.string, ud2.dict.dict.string));
-
-    ud1c_p = ud2c_p->dict.dict2.userdef;
-    g_assert(ud1c_p->integer == ud1_p->integer);
-    g_assert(!g_strcmp0(ud1c_p->string, ud1_p->string));
-
-    g_assert(!g_strcmp0(ud2c_p->dict.dict2.string, ud2.dict.dict2.string));
-    g_free(ud1.string);
-    g_free(ud2.string);
-    g_free(ud2.dict.string);
-    g_free(ud2.dict.dict.string);
-    g_free(ud2.dict.dict2.string);
-
-    qapi_free_UserDefTwo(ud2c_p);
-
-    qobject_decref(obj);
-}
-
-/* test enum values */
-static void test_enums(void)
-{
-    QmpOutputVisitor *mo;
-    QmpInputVisitor *mi;
-    Visitor *v;
-    EnumOne enum1 = ENUM_ONE_VALUE2, enum1_cpy = ENUM_ONE_VALUE1;
-    Error *err = NULL;
-    QObject *obj;
-    QString *str;
-
-    /* C type -> QObject */
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-    visit_type_EnumOne(v, &enum1, "unused", &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    obj = qmp_output_get_qobject(mo);
-    g_assert(obj);
-    str = qobject_to_json_pretty(obj);
-    g_print("%s\n", qstring_get_str(str));
-    QDECREF(str);
-    g_assert(g_strcmp0(qstring_get_str(qobject_to_qstring(obj)), "value2") == 0);
-
-    /* QObject -> C type */
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-    visit_type_EnumOne(v, &enum1_cpy, "unused", &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    g_debug("enum1_cpy, enum1: %d, %d", enum1_cpy, enum1);
-    g_assert(enum1_cpy == enum1);
-
-    qobject_decref(obj);
-}
-
-/* test enum values nested in schema-defined structs */
-static void test_nested_enums(void)
-{
-    QmpOutputVisitor *mo;
-    QmpInputVisitor *mi;
-    Visitor *v;
-    NestedEnumsOne *nested_enums, *nested_enums_cpy = NULL;
-    Error *err = NULL;
-    QObject *obj;
-    QString *str;
-
-    nested_enums = g_malloc0(sizeof(NestedEnumsOne));
-    nested_enums->enum1 = ENUM_ONE_VALUE1;
-    nested_enums->enum2 = ENUM_ONE_VALUE2;
-    nested_enums->enum3 = ENUM_ONE_VALUE3;
-    nested_enums->enum4 = ENUM_ONE_VALUE3;
-    nested_enums->has_enum2 = false;
-    nested_enums->has_enum4 = true;
-
-    /* C type -> QObject */
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-    visit_type_NestedEnumsOne(v, &nested_enums, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    obj = qmp_output_get_qobject(mo);
-    g_assert(obj);
-    str = qobject_to_json_pretty(obj);
-    g_print("%s\n", qstring_get_str(str));
-    QDECREF(str);
-
-    /* QObject -> C type */
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-    visit_type_NestedEnumsOne(v, &nested_enums_cpy, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    g_assert(nested_enums_cpy);
-    g_assert(nested_enums_cpy->enum1 == nested_enums->enum1);
-    g_assert(nested_enums_cpy->enum3 == nested_enums->enum3);
-    g_assert(nested_enums_cpy->enum4 == nested_enums->enum4);
-    g_assert(nested_enums_cpy->has_enum2 == false);
-    g_assert(nested_enums_cpy->has_enum4 == true);
-
-    qmp_output_visitor_cleanup(mo);
-    qmp_input_visitor_cleanup(mi);
-    qapi_free_NestedEnumsOne(nested_enums);
-    qapi_free_NestedEnumsOne(nested_enums_cpy);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/0.15/visitor_core", test_visitor_core);
-    g_test_add_func("/0.15/nested_structs", test_nested_structs);
-    g_test_add_func("/0.15/enums", test_enums);
-    g_test_add_func("/0.15/nested_enums", test_nested_enums);
-
-    g_test_run();
-
-    return 0;
-}
commit d88f5fd13916aff43935c43004c52791569f4550
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon Nov 14 23:31:51 2011 -0200

    Introduce test-qmp-input-visitor
    
    Contains unit-tests for the QMP input visitor implementation.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/Makefile b/Makefile
index 206854a..c4884fc 100644
--- a/Makefile
+++ b/Makefile
@@ -169,7 +169,7 @@ test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y)
 
 $(qapi-obj-y): $(GENERATED_HEADERS)
 qapi-dir := $(BUILD_DIR)/qapi-generated
-test-qmp-output-visitor.o test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
+test-qmp-input-visitor.o test-qmp-output-visitor.o test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
 
 $(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
@@ -208,6 +208,9 @@ test-visitor: test-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qap
 test-qmp-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
 test-qmp-output-visitor: test-qmp-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
 
+test-qmp-input-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
+test-qmp-input-visitor: test-qmp-input-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+
 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
 
diff --git a/configure b/configure
index cae1f03..21fa406 100755
--- a/configure
+++ b/configure
@@ -2745,7 +2745,7 @@ if test "$softmmu" = yes ; then
       checks="check-qint check-qstring check-qdict check-qlist"
       checks="check-qfloat check-qjson $checks"
     fi
-    test_progs="$checks test-coroutine test-qmp-output-visitor"
+    test_progs="$checks test-coroutine test-qmp-output-visitor test-qmp-input-visitor"
   fi
 fi
 
diff --git a/test-qmp-input-visitor.c b/test-qmp-input-visitor.c
new file mode 100644
index 0000000..1f3ab03
--- /dev/null
+++ b/test-qmp-input-visitor.c
@@ -0,0 +1,270 @@
+/*
+ * QMP Input Visitor unit-tests.
+ *
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+#include <stdarg.h>
+
+#include "qapi/qmp-input-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestInputVisitorData {
+    QObject *obj;
+    QmpInputVisitor *qiv;
+} TestInputVisitorData;
+
+static void visitor_input_teardown(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    qobject_decref(data->obj);
+    data->obj = NULL;
+
+    if (data->qiv) {
+        qmp_input_visitor_cleanup(data->qiv);
+        data->qiv = NULL;
+    }
+}
+
+/* This is provided instead of a test setup function so that the JSON
+   string used by the tests are kept in the test functions (and not
+   int main()) */
+static Visitor *visitor_input_test_init(TestInputVisitorData *data,
+                                        const char *json_string, ...)
+{
+    Visitor *v;
+    va_list ap;
+
+    va_start(ap, json_string);
+    data->obj = qobject_from_jsonv(json_string, &ap);
+    va_end(ap);
+
+    g_assert(data->obj != NULL);
+
+    data->qiv = qmp_input_visitor_new(data->obj);
+    g_assert(data->qiv != NULL);
+
+    v = qmp_input_get_visitor(data->qiv);
+    g_assert(v != NULL);
+
+    return v;
+}
+
+static void test_visitor_in_int(TestInputVisitorData *data,
+                                const void *unused)
+{
+    int64_t res = 0, value = -42;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "%d", value);
+
+    visit_type_int(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, value);
+}
+
+static void test_visitor_in_bool(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    Error *errp = NULL;
+    bool res = false;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "true");
+
+    visit_type_bool(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, true);
+}
+
+static void test_visitor_in_number(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    double res = 0, value = 3.14;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "%f", value);
+
+    visit_type_number(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpfloat(res, ==, value);
+}
+
+static void test_visitor_in_string(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    char *res = NULL, *value = (char *) "Q E M U";
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "%s", value);
+
+    visit_type_str(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpstr(res, ==, value);
+
+    g_free(res);
+}
+
+static void test_visitor_in_enum(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    Error *errp = NULL;
+    Visitor *v;
+    EnumOne i;
+
+    for (i = 0; EnumOne_lookup[i]; i++) {
+        EnumOne res = -1;
+
+        v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
+
+        visit_type_EnumOne(v, &res, NULL, &errp);
+        g_assert(!error_is_set(&errp));
+        g_assert_cmpint(i, ==, res);
+
+        visitor_input_teardown(data, NULL);
+    }
+
+    data->obj = NULL;
+    data->qiv = NULL;
+}
+
+typedef struct TestStruct
+{
+    int64_t integer;
+    bool boolean;
+    char *string;
+} TestStruct;
+
+static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
+                                  const char *name, Error **errp)
+{
+    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
+                       errp);
+
+    visit_type_int(v, &(*obj)->integer, "integer", errp);
+    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
+    visit_type_str(v, &(*obj)->string, "string", errp);
+
+    visit_end_struct(v, errp);
+}
+
+static void test_visitor_in_struct(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(p->integer, ==, -42);
+    g_assert(p->boolean == true);
+    g_assert_cmpstr(p->string, ==, "foo");
+
+    g_free(p->string);
+    g_free(p);
+}
+
+static void check_and_free_str(char *str, const char *cmp)
+{
+    g_assert_cmpstr(str, ==, cmp);
+    g_free(str);
+}
+
+static void test_visitor_in_struct_nested(TestInputVisitorData *data,
+                                          const void *unused)
+{
+    UserDefNested *udp = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
+
+    visit_type_UserDefNested(v, &udp, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+
+    check_and_free_str(udp->string0, "string0");
+    check_and_free_str(udp->dict1.string1, "string1");
+    g_assert_cmpint(udp->dict1.dict2.userdef1->integer, ==, 42);
+    check_and_free_str(udp->dict1.dict2.userdef1->string, "string");
+    check_and_free_str(udp->dict1.dict2.string2, "string2");
+    g_assert(udp->dict1.has_dict3 == false);
+
+    g_free(udp->dict1.dict2.userdef1);
+    g_free(udp);
+}
+
+static void test_visitor_in_list(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    UserDefOneList *item, *head = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+    int i;
+
+    v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
+
+    visit_type_UserDefOneList(v, &head, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert(head != NULL);
+
+    for (i = 0, item = head; item; item = item->next, i++) {
+        char string[12];
+
+        snprintf(string, sizeof(string), "string%d", i);
+        g_assert_cmpstr(item->value->string, ==, string);
+        g_assert_cmpint(item->value->integer, ==, 42 + i);
+    }
+
+    qapi_free_UserDefOneList(head);
+}
+
+static void input_visitor_test_add(const char *testpath,
+                                   TestInputVisitorData *data,
+                                   void (*test_func)(TestInputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
+               visitor_input_teardown);
+}
+
+int main(int argc, char **argv)
+{
+    TestInputVisitorData in_visitor_data;
+
+    g_test_init(&argc, &argv, NULL);
+
+    input_visitor_test_add("/visitor/input/int",
+                           &in_visitor_data, test_visitor_in_int);
+    input_visitor_test_add("/visitor/input/bool",
+                           &in_visitor_data, test_visitor_in_bool);
+    input_visitor_test_add("/visitor/input/number",
+                           &in_visitor_data, test_visitor_in_number);
+    input_visitor_test_add("/visitor/input/string",
+                            &in_visitor_data, test_visitor_in_string);
+    input_visitor_test_add("/visitor/input/enum",
+                            &in_visitor_data, test_visitor_in_enum);
+    input_visitor_test_add("/visitor/input/struct",
+                            &in_visitor_data, test_visitor_in_struct);
+    input_visitor_test_add("/visitor/input/struct-nested",
+                            &in_visitor_data, test_visitor_in_struct_nested);
+    input_visitor_test_add("/visitor/input/list",
+                            &in_visitor_data, test_visitor_in_list);
+
+    g_test_run();
+
+    return 0;
+}
commit f294f82aa3f10e2ade5a8b7b1e927ebbb24ad55c
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon Nov 14 19:05:29 2011 -0200

    Introduce test-qmp-output-visitor
    
    Contains unit-tests for the QMP output visitor implementation.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/Makefile b/Makefile
index 301c75e..206854a 100644
--- a/Makefile
+++ b/Makefile
@@ -169,7 +169,7 @@ test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y)
 
 $(qapi-obj-y): $(GENERATED_HEADERS)
 qapi-dir := $(BUILD_DIR)/qapi-generated
-test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
+test-qmp-output-visitor.o test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
 
 $(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
@@ -205,6 +205,9 @@ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py
 test-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
 test-visitor: test-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
 
+test-qmp-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
+test-qmp-output-visitor: test-qmp-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+
 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
 
diff --git a/configure b/configure
index d88288b..cae1f03 100755
--- a/configure
+++ b/configure
@@ -2745,7 +2745,7 @@ if test "$softmmu" = yes ; then
       checks="check-qint check-qstring check-qdict check-qlist"
       checks="check-qfloat check-qjson $checks"
     fi
-    test_progs="$checks test-coroutine"
+    test_progs="$checks test-coroutine test-qmp-output-visitor"
   fi
 fi
 
diff --git a/qapi-schema-test.json b/qapi-schema-test.json
index 3acedad..2b38919 100644
--- a/qapi-schema-test.json
+++ b/qapi-schema-test.json
@@ -16,6 +16,12 @@
                       'dict': { 'userdef': 'UserDefOne', 'string': 'str' },
                       '*dict2': { 'userdef': 'UserDefOne', 'string': 'str' } } } }
 
+{ 'type': 'UserDefNested',
+  'data': { 'string0': 'str',
+            'dict1': { 'string1': 'str',
+                       'dict2': { 'userdef1': 'UserDefOne', 'string2': 'str' },
+                       '*dict3': { 'userdef2': 'UserDefOne', 'string3': 'str' } } } }
+
 # testing commands
 { 'command': 'user_def_cmd', 'data': {} }
 { 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} }
diff --git a/test-qmp-output-visitor.c b/test-qmp-output-visitor.c
new file mode 100644
index 0000000..c94c208
--- /dev/null
+++ b/test-qmp-output-visitor.c
@@ -0,0 +1,423 @@
+/*
+ * QMP Output Visitor unit-tests.
+ *
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+
+#include "qapi/qmp-output-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestOutputVisitorData {
+    QmpOutputVisitor *qov;
+    Visitor *ov;
+} TestOutputVisitorData;
+
+static void visitor_output_setup(TestOutputVisitorData *data,
+                                 const void *unused)
+{
+    data->qov = qmp_output_visitor_new();
+    g_assert(data->qov != NULL);
+
+    data->ov = qmp_output_get_visitor(data->qov);
+    g_assert(data->ov != NULL);
+}
+
+static void visitor_output_teardown(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    qmp_output_visitor_cleanup(data->qov);
+    data->qov = NULL;
+    data->ov = NULL;
+}
+
+static void test_visitor_out_int(TestOutputVisitorData *data,
+                                 const void *unused)
+{
+    int64_t value = -42;
+    Error *errp = NULL;
+    QObject *obj;
+
+    visit_type_int(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QINT);
+    g_assert_cmpint(qint_get_int(qobject_to_qint(obj)), ==, value);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_bool(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    Error *errp = NULL;
+    bool value = true;
+    QObject *obj;
+
+    visit_type_bool(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QBOOL);
+    g_assert(qbool_get_int(qobject_to_qbool(obj)) == value);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_number(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    double value = 3.14;
+    Error *errp = NULL;
+    QObject *obj;
+
+    visit_type_number(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QFLOAT);
+    g_assert(qfloat_get_double(qobject_to_qfloat(obj)) == value);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_string(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    char *string = (char *) "Q E M U";
+    Error *errp = NULL;
+    QObject *obj;
+
+    visit_type_str(data->ov, &string, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QSTRING);
+    g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, string);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_no_string(TestOutputVisitorData *data,
+                                       const void *unused)
+{
+    char *string = NULL;
+    Error *errp = NULL;
+    QObject *obj;
+
+    /* A null string should return "" */
+    visit_type_str(data->ov, &string, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QSTRING);
+    g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, "");
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_enum(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    Error *errp = NULL;
+    QObject *obj;
+    EnumOne i;
+
+    for (i = 0; i < ENUM_ONE_MAX; i++) {
+        visit_type_EnumOne(data->ov, &i, "unused", &errp);
+        g_assert(!error_is_set(&errp));
+
+        obj = qmp_output_get_qobject(data->qov);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QSTRING);
+        g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==,
+                        EnumOne_lookup[i]);
+        qobject_decref(obj);
+    }
+}
+
+static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
+                                         const void *unused)
+{
+    EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
+    Error *errp;
+
+    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
+        errp = NULL;
+        visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
+        g_assert(error_is_set(&errp) == true);
+        error_free(errp);
+    }
+}
+
+typedef struct TestStruct
+{
+    int64_t integer;
+    bool boolean;
+    char *string;
+} TestStruct;
+
+static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
+                                  const char *name, Error **errp)
+{
+    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
+                       errp);
+
+    visit_type_int(v, &(*obj)->integer, "integer", errp);
+    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
+    visit_type_str(v, &(*obj)->string, "string", errp);
+
+    visit_end_struct(v, errp);
+}
+
+static void test_visitor_out_struct(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    TestStruct test_struct = { .integer = 42,
+                               .boolean = false,
+                               .string = (char *) "foo"};
+    TestStruct *p = &test_struct;
+    Error *errp = NULL;
+    QObject *obj;
+    QDict *qdict;
+
+    visit_type_TestStruct(data->ov, &p, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QDICT);
+
+    qdict = qobject_to_qdict(obj);
+    g_assert_cmpint(qdict_size(qdict), ==, 3);
+    g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42);
+    g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, 0);
+    g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "foo");
+
+    QDECREF(qdict);
+}
+
+static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
+                                           const void *unused)
+{
+    int64_t value = 42;
+    Error *errp = NULL;
+    UserDefNested *ud2;
+    QObject *obj;
+    QDict *qdict, *dict1, *dict2, *dict3, *userdef;
+    const char *string = "user def string";
+    const char *strings[] = { "fourty two", "fourty three", "fourty four",
+                              "fourty five" };
+
+    ud2 = g_malloc0(sizeof(*ud2));
+    ud2->string0 = g_strdup(strings[0]);
+
+    ud2->dict1.string1 = g_strdup(strings[1]);
+    ud2->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
+    ud2->dict1.dict2.userdef1->string = g_strdup(string);
+    ud2->dict1.dict2.userdef1->integer = value;
+    ud2->dict1.dict2.string2 = g_strdup(strings[2]);
+
+    ud2->dict1.has_dict3 = true;
+    ud2->dict1.dict3.userdef2 = g_malloc0(sizeof(UserDefOne));
+    ud2->dict1.dict3.userdef2->string = g_strdup(string);
+    ud2->dict1.dict3.userdef2->integer = value;
+    ud2->dict1.dict3.string3 = g_strdup(strings[3]);
+
+    visit_type_UserDefNested(data->ov, &ud2, "unused", &errp);
+    g_assert(!error_is_set(&errp));
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QDICT);
+
+    qdict = qobject_to_qdict(obj);
+    g_assert_cmpint(qdict_size(qdict), ==, 2);
+    g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]);
+
+    dict1 = qdict_get_qdict(qdict, "dict1");
+    g_assert_cmpint(qdict_size(dict1), ==, 3);
+    g_assert_cmpstr(qdict_get_str(dict1, "string1"), ==, strings[1]);
+
+    dict2 = qdict_get_qdict(dict1, "dict2");
+    g_assert_cmpint(qdict_size(dict2), ==, 2);
+    g_assert_cmpstr(qdict_get_str(dict2, "string2"), ==, strings[2]);
+    userdef = qdict_get_qdict(dict2, "userdef1");
+    g_assert_cmpint(qdict_size(userdef), ==, 2);
+    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
+    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
+
+    dict3 = qdict_get_qdict(dict1, "dict3");
+    g_assert_cmpint(qdict_size(dict3), ==, 2);
+    g_assert_cmpstr(qdict_get_str(dict3, "string3"), ==, strings[3]);
+    userdef = qdict_get_qdict(dict3, "userdef2");
+    g_assert_cmpint(qdict_size(userdef), ==, 2);
+    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
+    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
+
+    QDECREF(qdict);
+    qapi_free_UserDefNested(ud2);
+}
+
+typedef struct TestStructList
+{
+    TestStruct *value;
+    struct TestStructList *next;
+} TestStructList;
+
+static void visit_type_TestStructList(Visitor *v, TestStructList **obj,
+                                      const char *name, Error **errp)
+{
+    GenericList *i, **head = (GenericList **)obj;
+
+    visit_start_list(v, name, errp);
+
+    for (*head = i = visit_next_list(v, head, errp); i; i = visit_next_list(v, &i, errp)) {
+        TestStructList *native_i = (TestStructList *)i;
+        visit_type_TestStruct(v, &native_i->value, NULL, errp);
+    }
+
+    visit_end_list(v, errp);
+}
+
+static void test_visitor_out_list(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    char *value_str = (char *) "list value";
+    TestStructList *p, *head = NULL;
+    const int max_items = 10;
+    bool value_bool = true;
+    int value_int = 10;
+    Error *errp = NULL;
+    QListEntry *entry;
+    QObject *obj;
+    QList *qlist;
+    int i;
+
+    for (i = 0; i < max_items; i++) {
+        p = g_malloc0(sizeof(*p));
+        p->value = g_malloc0(sizeof(*p->value));
+        p->value->integer = value_int;
+        p->value->boolean = value_bool;
+        p->value->string = value_str;
+
+        p->next = head;
+        head = p;
+    }
+
+    visit_type_TestStructList(data->ov, &head, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QLIST);
+
+    qlist = qobject_to_qlist(obj);
+    g_assert(!qlist_empty(qlist));
+
+    i = 0;
+    QLIST_FOREACH_ENTRY(qlist, entry) {
+        QDict *qdict;
+
+        g_assert(qobject_type(entry->value) == QTYPE_QDICT);
+        qdict = qobject_to_qdict(entry->value);
+        g_assert_cmpint(qdict_size(qdict), ==, 3);
+        g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int);
+        g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool);
+        g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
+        i++;
+    }
+    g_assert_cmpint(i, ==, max_items);
+
+    QDECREF(qlist);
+
+    for (p = head; p;) {
+        TestStructList *tmp = p->next;
+        g_free(p->value);
+        g_free(p);
+        p = tmp;
+    }
+}
+
+static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
+                                            const void *unused)
+{
+    UserDefNestedList *p, *head = NULL;
+    const char string[] = "foo bar";
+    int i, max_count = 1024;
+
+    for (i = 0; i < max_count; i++) {
+        p = g_malloc0(sizeof(*p));
+        p->value = g_malloc0(sizeof(*p->value));
+
+        p->value->string0 = g_strdup(string);
+        p->value->dict1.string1 = g_strdup(string);
+        p->value->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
+        p->value->dict1.dict2.userdef1->string = g_strdup(string);
+        p->value->dict1.dict2.userdef1->integer = 42;
+        p->value->dict1.dict2.string2 = g_strdup(string);
+        p->value->dict1.has_dict3 = false;
+
+        p->next = head;
+        head = p;
+    }
+
+    qapi_free_UserDefNestedList(head);
+}
+
+static void output_visitor_test_add(const char *testpath,
+                                    TestOutputVisitorData *data,
+                                    void (*test_func)(TestOutputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
+               test_func, visitor_output_teardown);
+}
+
+int main(int argc, char **argv)
+{
+    TestOutputVisitorData out_visitor_data;
+
+    g_test_init(&argc, &argv, NULL);
+
+    output_visitor_test_add("/visitor/output/int",
+                            &out_visitor_data, test_visitor_out_int);
+    output_visitor_test_add("/visitor/output/bool",
+                            &out_visitor_data, test_visitor_out_bool);
+    output_visitor_test_add("/visitor/output/number",
+                            &out_visitor_data, test_visitor_out_number);
+    output_visitor_test_add("/visitor/output/string",
+                            &out_visitor_data, test_visitor_out_string);
+    output_visitor_test_add("/visitor/output/no-string",
+                            &out_visitor_data, test_visitor_out_no_string);
+    output_visitor_test_add("/visitor/output/enum",
+                            &out_visitor_data, test_visitor_out_enum);
+    output_visitor_test_add("/visitor/output/enum-errors",
+                            &out_visitor_data, test_visitor_out_enum_errors);
+    output_visitor_test_add("/visitor/output/struct",
+                            &out_visitor_data, test_visitor_out_struct);
+    output_visitor_test_add("/visitor/output/struct-nested",
+                            &out_visitor_data, test_visitor_out_struct_nested);
+    output_visitor_test_add("/visitor/output/list",
+                            &out_visitor_data, test_visitor_out_list);
+    output_visitor_test_add("/visitor/output/list-qapi-free",
+                            &out_visitor_data, test_visitor_out_list_qapi_free);
+
+    g_test_run();
+
+    return 0;
+}
commit 4ec0263e2ccad312cbaff1aa12ace1721113c2f1
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon Nov 21 14:00:37 2011 -0200

    configure: Don't mix glib and libcheck tests
    
    test-coroutine is listed as a libcheck test in the 'checks' variable. This
    is not right because 'make check' won't run test-coroutine if libcheck
    tests are not enabled (either because libcheck isn't detected or because
    --disable-check-utests is passed).
    
    Tests using the glib test framework are independent from libcheck and
    afaik are always present (although having a configure switch to disable
    them is probably worth it).
    
    Untangle test-coroutine from the libcheck tests by introducing the
    'test_progs' variable and using it to generate the test list used by
    'make check'.
    
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/configure b/configure
index 5fbd812..d88288b 100755
--- a/configure
+++ b/configure
@@ -2743,8 +2743,9 @@ if test "$softmmu" = yes ; then
     fi
     if [ "$check_utests" = "yes" ]; then
       checks="check-qint check-qstring check-qdict check-qlist"
-      checks="check-qfloat check-qjson test-coroutine $checks"
+      checks="check-qfloat check-qjson $checks"
     fi
+    test_progs="$checks test-coroutine"
   fi
 fi
 
@@ -3230,7 +3231,7 @@ if test "$trace_default" = "yes"; then
 fi
 
 echo "TOOLS=$tools" >> $config_host_mak
-echo "CHECKS=$checks" >> $config_host_mak
+echo "CHECKS=$test_progs" >> $config_host_mak
 echo "ROMS=$roms" >> $config_host_mak
 echo "MAKE=$make" >> $config_host_mak
 echo "INSTALL=$install" >> $config_host_mak
commit 1c1d46cc0bb66394feba2e37a6b0196021e8d736
Author: Mark Wu <wudxw at linux.vnet.ibm.com>
Date:   Wed Nov 9 13:55:33 2011 +0800

    qmp: add test tool for QMP
    
    Anthony wrote this quickly to aid in testing.  It's similar to qmp-shell with
    a few important differences:
    
    1) It is not interactive.  That makes it useful for scripting.
    
    2) qmp-shell:
    
    (QEMU) set_password protocol=vnc password=foo
    
    3) qmp:
    
    $ qmp set_password --protocol=vnc --password=foo
    
    4) Extensible, git-style interface.  If an invalid command name is
    passed, it will try to exec qmp-$1.
    
    5) It attempts to pretty print the JSON responses in a shell friendly
    format such that tools can work with the output.
    
    Hope others will also find it useful.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Mark Wu <wudxw at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/QMP/qmp b/QMP/qmp
new file mode 100755
index 0000000..1db3c7f
--- /dev/null
+++ b/QMP/qmp
@@ -0,0 +1,126 @@
+#!/usr/bin/python
+#
+# QMP command line tool
+#
+# Copyright IBM, Corp. 2011
+#
+# Authors:
+#  Anthony Liguori <aliguori at us.ibm.com>
+#
+# This work is licensed under the terms of the GNU GPLv2 or later.
+# See the COPYING file in the top-level directory.
+
+import sys, os
+from qmp import QEMUMonitorProtocol
+
+def print_response(rsp, prefix=[]):
+    if type(rsp) == list:
+        i = 0
+        for item in rsp:
+            if prefix == []:
+                prefix = ['item']
+            print_response(item, prefix[:-1] + ['%s[%d]' % (prefix[-1], i)])
+            i += 1
+    elif type(rsp) == dict:
+        for key in rsp.keys():
+            print_response(rsp[key], prefix + [key])
+    else:
+        if len(prefix):
+            print '%s: %s' % ('.'.join(prefix), rsp)
+        else:
+            print '%s' % (rsp)
+
+def main(args):
+    path = None
+
+    # Use QMP_PATH if it's set
+    if os.environ.has_key('QMP_PATH'):
+        path = os.environ['QMP_PATH']
+
+    while len(args):
+        arg = args[0]
+
+        if arg.startswith('--'):
+            arg = arg[2:]
+            if arg.find('=') == -1:
+                value = True
+            else:
+                arg, value = arg.split('=', 1)
+
+            if arg in ['path']:
+                if type(value) == str:
+                    path = value
+            elif arg in ['help']:
+                os.execlp('man', 'man', 'qmp')
+            else:
+                print 'Unknown argument "%s"' % arg
+
+            args = args[1:]
+        else:
+            break
+
+    if not path:
+        print "QMP path isn't set, use --path=qmp-monitor-address or set QMP_PATH"
+        return 1
+
+    if len(args):
+        command, args = args[0], args[1:]
+    else:
+        print 'No command found'
+        print 'Usage: "qmp [--path=qmp-monitor-address] qmp-cmd arguments"'
+        return 1
+
+    if command in ['help']:
+        os.execlp('man', 'man', 'qmp')
+
+    srv = QEMUMonitorProtocol(path)
+    srv.connect()
+
+    def do_command(srv, cmd, **kwds):
+        rsp = srv.cmd(cmd, kwds)
+        if rsp.has_key('error'):
+            raise Exception(rsp['error']['desc'])
+        return rsp['return']
+
+    commands = map(lambda x: x['name'], do_command(srv, 'query-commands'))
+
+    srv.close()
+
+    if command not in commands:
+        fullcmd = 'qmp-%s' % command
+        try:
+            os.environ['QMP_PATH'] = path
+            os.execvp(fullcmd, [fullcmd] + args)
+        except OSError, (errno, msg):
+            if errno == 2:
+                print 'Command "%s" not found.' % (fullcmd)
+                return 1
+            raise
+        return 0
+
+    srv = QEMUMonitorProtocol(path)
+    srv.connect()
+
+    arguments = {}
+    for arg in args:
+        if not arg.startswith('--'):
+            print 'Unknown argument "%s"' % arg
+            return 1
+
+        arg = arg[2:]
+        if arg.find('=') == -1:
+            value = True
+        else:
+            arg, value = arg.split('=', 1)
+
+        if arg in ['help']:
+            os.execlp('man', 'man', 'qmp-%s' % command)
+            return 1
+
+        arguments[arg] = value
+
+    rsp = do_command(srv, command, **arguments)
+    print_response(rsp)
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv[1:]))
commit 4b389b5d6e4ccda94297142cc27ddcdb3a4667dc
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Fri Oct 28 17:43:29 2011 -0200

    docs: Add writing-qmp-commands.txt
    
    Explains how to write QMP commands using the QAPI.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/docs/writing-qmp-commands.txt b/docs/writing-qmp-commands.txt
new file mode 100644
index 0000000..0472fc3
--- /dev/null
+++ b/docs/writing-qmp-commands.txt
@@ -0,0 +1,642 @@
+= How to write QMP commands using the QAPI framework =
+
+This document is a step-by-step guide on how to write new QMP commands using
+the QAPI framework. It also shows how to implement new style HMP commands.
+
+This document doesn't discuss QMP protocol level details, nor does it dive
+into the QAPI framework implementation.
+
+For an in-depth introduction to the QAPI framework, please refer to
+docs/qapi-code-gen.txt. For documentation about the QMP protocol, please
+check the files in QMP/.
+
+== Overview ==
+
+Generally speaking, the following steps should be taken in order to write a
+new QMP command.
+
+1. Write the command's and type(s) specification in the QAPI schema file
+   (qapi-schema.json in the root source directory)
+
+2. Write the QMP command itself, which is a regular C function. Preferably,
+   the command should be exported by some QEMU subsystem. But it can also be
+   added to the qmp.c file
+
+3. At this point the command can be tested under the QMP protocol
+
+4. Write the HMP command equivalent. This is not required and should only be
+   done if it does make sense to have the functionality in HMP. The HMP command
+   is implemented in terms of the QMP command
+
+The following sections will demonstrate each of the steps above. We will start
+very simple and get more complex as we progress.
+
+=== Testing ===
+
+For all the examples in the next sections, the test setup is the same and is
+shown here.
+
+First, QEMU should be started as:
+
+# /path/to/your/source/qemu [...] \
+    -chardev socket,id=qmp,port=4444,host=localhost,server \
+    -mon chardev=qmp,mode=control,pretty=on
+
+Then, in a different terminal:
+
+$ telnet localhost 4444
+Trying 127.0.0.1...
+Connected to localhost.
+Escape character is '^]'.
+{
+    "QMP": {
+        "version": {
+            "qemu": {
+                "micro": 50, 
+                "minor": 15, 
+                "major": 0
+            }, 
+            "package": ""
+        }, 
+        "capabilities": [
+        ]
+    }
+}
+
+The above output is the QMP server saying you're connected. The server is
+actually in capabilities negotiation mode. To enter in command mode type:
+
+{ "execute": "qmp_capabilities" }
+
+Then the server should respond:
+
+{
+    "return": {
+    }
+}
+
+Which is QMP's way of saying "the latest command executed OK and didn't return
+any data". Now you're ready to enter the QMP example commands as explained in
+the following sections.
+
+== Writing a command that doesn't return data ==
+
+That's the most simple QMP command that can be written. Usually, this kind of
+command carries some meaningful action in QEMU but here it will just print
+"Hello, world" to the standard output.
+
+Our command will be called "hello-world". It takes no arguments, nor does it
+return any data.
+
+The first step is to add the following line to the bottom of the
+qapi-schema.json file:
+
+{ 'command': 'hello-world' }
+
+The "command" keyword defines a new QMP command. It's an JSON object. All
+schema entries are JSON objects. The line above will instruct the QAPI to
+generate any prototypes and the necessary code to marshal and unmarshal
+protocol data.
+
+The next step is to write the "hello-world" implementation. As explained
+earlier, it's preferable for commands to live in QEMU subsystems. But
+"hello-world" doesn't pertain to any, so we put its implementation in qmp.c:
+
+void qmp_hello_world(Error **errp)
+{
+    printf("Hello, world!\n");
+}
+
+There are a few things to be noticed:
+
+1. QMP command implementation functions must be prefixed with "qmp_"
+2. qmp_hello_world() returns void, this is in accordance with the fact that the
+   command doesn't return any data
+3. It takes an "Error **" argument. This is required. Later we will see how to
+   return errors and take additional arguments. The Error argument should not
+   be touched if the command doesn't return errors
+4. We won't add the function's prototype. That's automatically done by the QAPI
+5. Printing to the terminal is discouraged for QMP commands, we do it here
+   because it's the easiest way to demonstrate a QMP command
+
+Now a little hack is needed. As we're still using the old QMP server we need
+to add the new command to its internal dispatch table. This step won't be
+required in the near future. Open the qmp-commands.hx file and add the
+following in the botton:
+
+    {
+        .name       = "hello-world",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_hello_world,
+    },
+
+You're done. Now build qemu, run it as suggested in the "Testing" section,
+and then type the following QMP command:
+
+{ "execute": "hello-world" }
+
+Then check the terminal running qemu and look for the "Hello, world" string. If
+you don't see it then something went wrong.
+
+=== Arguments ===
+
+Let's add an argument called "message" to our "hello-world" command. The new
+argument will contain the string to be printed to stdout. It's an optional
+argument, if it's not present we print our default "Hello, World" string.
+
+The first change we have to do is to modify the command specification in the
+schema file to the following:
+
+{ 'command': 'hello-world', 'data': { '*message': 'str' } }
+
+Notice the new 'data' member in the schema. It's an JSON object whose each
+element is an argument to the command in question. Also notice the asterisk,
+it's used to mark the argument optional (that means that you shouldn't use it
+for mandatory arguments). Finally, 'str' is the argument's type, which
+stands for "string". The QAPI also supports integers, booleans, enumerations
+and user defined types.
+
+Now, let's update our C implementation in qmp.c:
+
+void qmp_hello_world(bool has_message, const char *message, Error **errp)
+{
+    if (has_message) {
+        printf("%s\n", message);
+    } else {
+        printf("Hello, world\n");
+    }
+}
+
+There are two important details to be noticed:
+
+1. All optional arguments are accompanied by a 'has_' boolean, which is set
+   if the optional argument is present or false otherwise
+2. The C implementation signature must follow the schema's argument ordering,
+   which is defined by the "data" member
+
+The last step is to update the qmp-commands.hx file:
+
+    {
+        .name       = "hello-world",
+        .args_type  = "message:s?",
+        .mhandler.cmd_new = qmp_marshal_input_hello_world,
+    },
+
+Notice that the "args_type" member got our "message" argument. The character
+"s" stands for "string" and "?" means it's optional. This too must be ordered
+according to the C implementation and schema file. You can look for more
+examples in the qmp-commands.hx file if you need to define more arguments.
+
+Again, this step won't be required in the future.
+
+Time to test our new version of the "hello-world" command. Build qemu, run it as
+described in the "Testing" section and then send two commands:
+
+{ "execute": "hello-world" }
+{
+    "return": {
+    }
+}
+
+{ "execute": "hello-world", "arguments": { "message": "We love qemu" } }
+{
+    "return": {
+    }
+}
+
+You should see "Hello, world" and "we love qemu" in the terminal running qemu,
+if you don't see these strings, then something went wrong.
+
+=== Errors ===
+
+QMP commands should use the error interface exported by the error.h header
+file. The basic function used to set an error is the error_set() one.
+
+Let's say we don't accept the string "message" to contain the word "love". If
+it does contain it, we want the "hello-world" command to the return the
+InvalidParameter error.
+
+Only one change is required, and it's in the C implementation:
+
+void qmp_hello_world(bool has_message, const char *message, Error **errp)
+{
+    if (has_message) {
+        if (strstr(message, "love")) {
+            error_set(errp, QERR_INVALID_PARAMETER, "message");
+            return;
+        }
+        printf("%s\n", message);
+    } else {
+        printf("Hello, world\n");
+    }
+}
+
+Let's test it. Build qemu, run it as defined in the "Testing" section, and
+then issue the following command:
+
+{ "execute": "hello-world", "arguments": { "message": "we love qemu" } }
+
+The QMP server's response should be:
+
+{
+    "error": {
+        "class": "InvalidParameter",
+        "desc": "Invalid parameter 'message'",
+        "data": {
+            "name": "message"
+        }
+    }
+}
+
+Which is the InvalidParameter error.
+
+When you have to return an error but you're unsure what error to return or
+which arguments an error takes, you should look at the qerror.h file. Note
+that you might be required to add new errors if needed.
+
+FIXME: describe better the error API and how to add new errors.
+
+=== Command Documentation ===
+
+There's only one step missing to make "hello-world"'s implementation complete,
+and that's its documentation in the schema file.
+
+This is very important. No QMP command will be accepted in QEMU without proper
+documentation.
+
+There are many examples of such documentation in the schema file already, but
+here goes "hello-world"'s new entry for the qapi-schema.json file:
+
+##
+# @hello-world
+#
+# Print a client provided string to the standard output stream.
+#
+# @message: #optional string to be printed
+#
+# Returns: Nothing on success.
+#          If @message contains "love", InvalidParameter
+#
+# Notes: if @message is not provided, the "Hello, world" string will
+#        be printed instead
+#
+# Since: <next qemu stable release, eg. 1.0>
+##
+{ 'command': 'hello-world', 'data': { '*message': 'str' } }
+
+Please, note that the "Returns" clause is optional if a command doesn't return
+any data nor any errors.
+
+=== Implementing the HMP command ===
+
+Now that the QMP command is in place, we can also make it available in the human
+monitor (HMP).
+
+With the introduction of the QAPI, HMP commands make QMP calls. Most of the
+time HMP commands are simple wrappers. All HMP commands implementation exist in
+the hmp.c file.
+
+Here's the implementation of the "hello-world" HMP command:
+
+void hmp_hello_world(Monitor *mon, const QDict *qdict)
+{
+    const char *message = qdict_get_try_str(qdict, "message");
+    Error *errp = NULL;
+
+    qmp_hello_world(!!message, message, &errp);
+    if (error_is_set(&errp)) {
+        monitor_printf(mon, "%s\n", error_get_pretty(errp));
+        error_free(errp);
+        return;
+    }
+}
+
+Also, you have to add the function's prototype to the hmp.h file.
+
+There are three important points to be noticed:
+
+1. The "mon" and "qdict" arguments are mandatory for all HMP functions. The
+   former is the monitor object. The latter is how the monitor passes
+   arguments entered by the user to the command implementation
+2. hmp_hello_world() performs error checking. In this example we just print
+   the error description to the user, but we could do more, like taking
+   different actions depending on the error qmp_hello_world() returns
+3. The "errp" variable must be initialized to NULL before performing the
+   QMP call
+
+There's one last step to actually make the command available to monitor users,
+we should add it to the hmp-commands.hx file:
+
+    {
+        .name       = "hello-world",
+        .args_type  = "message:s?",
+        .params     = "hello-world [message]",
+        .help       = "Print message to the standard output",
+        .mhandler.cmd = hmp_hello_world,
+    },
+
+STEXI
+ at item hello_world @var{message}
+ at findex hello_world
+Print message to the standard output
+ETEXI
+
+To test this you have to open a user monitor and issue the "hello-world"
+command. It might be instructive to check the command's documentation with
+HMP's "help" command.
+
+Please, check the "-monitor" command-line option to know how to open a user
+monitor.
+
+== Writing a command that returns data ==
+
+A QMP command is capable of returning any data the QAPI supports like integers,
+strings, booleans, enumerations and user defined types.
+
+In this section we will focus on user defined types. Please, check the QAPI
+documentation for information about the other types.
+
+=== User Defined Types ===
+
+For this example we will write the query-alarm-clock command, which returns
+information about QEMU's timer alarm. For more information about it, please
+check the "-clock" command-line option.
+
+We want to return two pieces of information. The first one is the alarm clock's
+name. The second one is when the next alarm will fire. The former information is
+returned as a string, the latter is an integer in nanoseconds (which is not
+very useful in practice, as the timer has probably already fired when the
+information reaches the client).
+
+The best way to return that data is to create a new QAPI type, as shown below:
+
+##
+# @QemuAlarmClock
+#
+# QEMU alarm clock information.
+#
+# @clock-name: The alarm clock method's name.
+#
+# @next-deadline: #optional The time (in nanoseconds) the next alarm will fire.
+#
+# Since: 1.0
+##
+{ 'type': 'QemuAlarmClock',
+  'data': { 'clock-name': 'str', '*next-deadline': 'int' } }
+
+The "type" keyword defines a new QAPI type. Its "data" member contains the
+type's members. In this example our members are the "clock-name" and the
+"next-deadline" one, which is optional.
+
+Now let's define the query-alarm-clock command:
+
+##
+# @query-alarm-clock
+#
+# Return information about QEMU's alarm clock.
+#
+# Returns a @QemuAlarmClock instance describing the alarm clock method
+# being currently used by QEMU (this is usually set by the '-clock'
+# command-line option).
+#
+# Since: 1.0
+##
+{ 'command': 'query-alarm-clock', 'returns': 'QemuAlarmClock' }
+
+Notice the "returns" keyword. As its name suggests, it's used to define the
+data returned by a command.
+
+It's time to implement the qmp_query_alarm_clock() function, you can put it
+in the qemu-timer.c file:
+
+QemuAlarmClock *qmp_query_alarm_clock(Error **errp)
+{
+    QemuAlarmClock *clock;
+    int64_t deadline;
+
+    clock = g_malloc0(sizeof(*clock));
+
+    deadline = qemu_next_alarm_deadline();
+    if (deadline > 0) {
+        clock->has_next_deadline = true;
+        clock->next_deadline = deadline;
+    }
+    clock->clock_name = g_strdup(alarm_timer->name);
+
+    return clock;
+}
+
+There are a number of things to be noticed:
+
+1. The QemuAlarmClock type is automatically generated by the QAPI framework,
+   its members correspond to the type's specification in the schema file
+2. As specified in the schema file, the function returns a QemuAlarmClock
+   instance and takes no arguments (besides the "errp" one, which is mandatory
+   for all QMP functions)
+3. The "clock" variable (which will point to our QAPI type instance) is
+   allocated by the regular g_malloc0() function. Note that we chose to
+   initialize the memory to zero. This is recomended for all QAPI types, as
+   it helps avoiding bad surprises (specially with booleans)
+4. Remember that "next_deadline" is optional? All optional members have a
+   'has_TYPE_NAME' member that should be properly set by the implementation,
+   as shown above
+5. Even static strings, such as "alarm_timer->name", should be dynamically
+   allocated by the implementation. This is so because the QAPI also generates
+   a function to free its types and it cannot distinguish between dynamically
+   or statically allocated strings
+6. You have to include the "qmp-commands.h" header file in qemu-timer.c,
+   otherwise qemu won't build
+
+The last step is to add the correspoding entry in the qmp-commands.hx file:
+
+    {
+        .name       = "query-alarm-clock",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_alarm_clock,
+    },
+
+Time to test the new command. Build qemu, run it as described in the "Testing"
+section and try this:
+
+{ "execute": "query-alarm-clock" }
+{
+    "return": {
+        "next-deadline": 2368219,
+        "clock-name": "dynticks"
+    }
+}
+
+==== The HMP command ====
+
+Here's the HMP counterpart of the query-alarm-clock command:
+
+void hmp_info_alarm_clock(Monitor *mon)
+{
+    QemuAlarmClock *clock;
+    Error *errp = NULL;
+
+    clock = qmp_query_alarm_clock(&errp);
+    if (error_is_set(&errp)) {
+        monitor_printf(mon, "Could not query alarm clock information\n");
+        error_free(errp);
+        return;
+    }
+
+    monitor_printf(mon, "Alarm clock method in use: '%s'\n", clock->clock_name);
+    if (clock->has_next_deadline) {
+        monitor_printf(mon, "Next alarm will fire in %" PRId64 " nanoseconds\n",
+                       clock->next_deadline);
+    }
+
+   qapi_free_QemuAlarmClock(clock); 
+}
+
+It's important to notice that hmp_info_alarm_clock() calls
+qapi_free_QemuAlarmClock() to free the data returned by qmp_query_alarm_clock().
+For user defined types, the QAPI will generate a qapi_free_QAPI_TYPE_NAME()
+function and that's what you have to use to free the types you define and
+qapi_free_QAPI_TYPE_NAMEList() for list types (explained in the next section).
+If the QMP call returns a string, then you should g_free() to free it.
+
+Also note that hmp_info_alarm_clock() performs error handling. That's not
+strictly required if you're sure the QMP function doesn't return errors, but
+it's good practice to always check for errors.
+
+Another important detail is that HMP's "info" commands don't go into the
+hmp-commands.hx. Instead, they go into the info_cmds[] table, which is defined
+in the monitor.c file. The entry for the "info alarmclock" follows:
+
+    {
+        .name       = "alarmclock",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show information about the alarm clock",
+        .mhandler.info = hmp_info_alarm_clock,
+    },
+
+To test this, run qemu and type "info alarmclock" in the user monitor.
+
+=== Returning Lists ===
+
+For this example, we're going to return all available methods for the timer
+alarm, which is pretty much what the command-line option "-clock ?" does,
+except that we're also going to inform which method is in use.
+
+This first step is to define a new type:
+
+##
+# @TimerAlarmMethod
+#
+# Timer alarm method information.
+#
+# @method-name: The method's name.
+#
+# @current: true if this alarm method is currently in use, false otherwise
+#
+# Since: 1.0
+##
+{ 'type': 'TimerAlarmMethod',
+  'data': { 'method-name': 'str', 'current': 'bool' } }
+
+The command will be called "query-alarm-methods", here is its schema
+specification:
+
+##
+# @query-alarm-methods
+#
+# Returns information about available alarm methods.
+#
+# Returns: a list of @TimerAlarmMethod for each method
+#
+# Since: 1.0
+##
+{ 'command': 'query-alarm-methods', 'returns': ['TimerAlarmMethod'] }
+
+Notice the syntax for returning lists "'returns': ['TimerAlarmMethod']", this
+should be read as "returns a list of TimerAlarmMethod instances".
+
+The C implementation follows:
+
+TimerAlarmMethodList *qmp_query_alarm_methods(Error **errp)
+{
+    TimerAlarmMethodList *method_list = NULL;
+    const struct qemu_alarm_timer *p;
+    bool current = true;
+
+    for (p = alarm_timers; p->name; p++) {
+        TimerAlarmMethodList *info = g_malloc0(sizeof(*info));
+        info->value = g_malloc0(sizeof(*info->value));
+        info->value->method_name = g_strdup(p->name);
+        info->value->current = current;
+
+        current = false;
+
+        info->next = method_list;
+        method_list = info;
+    }
+
+    return method_list;
+}
+
+The most important difference from the previous examples is the
+TimerAlarmMethodList type, which is automatically generated by the QAPI from
+the TimerAlarmMethod type.
+
+Each list node is represented by a TimerAlarmMethodList instance. We have to
+allocate it, and that's done inside the for loop: the "info" pointer points to
+an allocated node. We also have to allocate the node's contents, which is
+stored in its "value" member. In our example, the "value" member is a pointer
+to an TimerAlarmMethod instance.
+
+Notice that the "current" variable is used as "true" only in the first
+interation of the loop. That's because the alarm timer method in use is the
+first element of the alarm_timers array. Also notice that QAPI lists are handled
+by hand and we return the head of the list.
+
+To test this you have to add the corresponding qmp-commands.hx entry:
+
+    {
+        .name       = "query-alarm-methods",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_alarm_methods,
+    },
+
+Now Build qemu, run it as explained in the "Testing" section and try our new
+command:
+
+{ "execute": "query-alarm-methods" }
+{
+    "return": [
+        {
+            "current": false, 
+            "method-name": "unix"
+        }, 
+        {
+            "current": true, 
+            "method-name": "dynticks"
+        }
+    ]
+}
+
+The HMP counterpart is a bit more complex than previous examples because it
+has to traverse the list, it's shown below for reference:
+
+void hmp_info_alarm_methods(Monitor *mon)
+{
+    TimerAlarmMethodList *method_list, *method;
+    Error *errp = NULL;
+
+    method_list = qmp_query_alarm_methods(&errp);
+    if (error_is_set(&errp)) {
+        monitor_printf(mon, "Could not query alarm methods\n");
+        error_free(errp);
+        return;
+    }
+
+    for (method = method_list; method; method = method->next) {
+        monitor_printf(mon, "%c %s\n", method->value->current ? '*' : ' ',
+                                       method->value->method_name);
+    }
+
+    qapi_free_TimerAlarmMethodList(method_list);
+}
commit a30cfee5ee6d4c6737de4549be1cb75c3ec539c8
Author: Chen Rui <chennrui at gmail.com>
Date:   Sun Nov 13 19:42:42 2011 +0800

    mips_malta: resolve endless loop when loading bios
    
    Tested-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Chen Rui <chennrui at gmail.com>

diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index bb49749..e7dfbd6 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -911,6 +911,7 @@ void mips_malta_init (ram_addr_t ram_size,
             uint32_t *end = addr + bios_size;
             while (addr < end) {
                 bswap32s(addr);
+                addr++;
             }
         }
 #endif
commit 69ddaf6659c006599b530feb50604a584c79f329
Author: Ademar de Souza Reis Jr <areis at redhat.com>
Date:   Mon Dec 5 16:54:14 2011 -0300

    memory: minor documentation fixes/enhancements
    
    Fix typos and minor documentation errors in both memory.h and
    docs/memory.txt.
    
    Also add missing documentation formatting tags to transaction
    functions.
    
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Ademar de Souza Reis Jr <areis at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/docs/memory.txt b/docs/memory.txt
index 3fc1683..5bbee8e 100644
--- a/docs/memory.txt
+++ b/docs/memory.txt
@@ -7,7 +7,7 @@ machine.  It attempts to allow modelling of:
  - ordinary RAM
  - memory-mapped I/O (MMIO)
  - memory controllers that can dynamically reroute physical memory regions
-  to different destinations
+   to different destinations
 
 The memory model provides support for
 
@@ -121,7 +121,7 @@ pci (0-2^32-1)
 
 ram: ram at 0x00000000-0xffffffff
 
-The is a (simplified) PC memory map. The 4GB RAM block is mapped into the
+This is a (simplified) PC memory map. The 4GB RAM block is mapped into the
 system address space via two aliases: "lomem" is a 1:1 mapping of the first
 3.5GB; "himem" maps the last 0.5GB at address 4GB.  This leaves 0.5GB for the
 so-called PCI hole, that allows a 32-bit PCI bus to exist in a system with
@@ -164,7 +164,7 @@ various constraints can be supplied to control how these callbacks are called:
  - .impl.min_access_size, .impl.max_access_size define the access sizes
    (in bytes) supported by the *implementation*; other access sizes will be
    emulated using the ones available.  For example a 4-byte write will be
-   emulated using four 1-byte write, if .impl.max_access_size = 1.
+   emulated using four 1-byte writes, if .impl.max_access_size = 1.
  - .impl.valid specifies that the *implementation* only supports unaligned
    accesses; unaligned accesses will be emulated by two aligned accesses.
  - .old_portio and .old_mmio can be used to ease porting from code using
diff --git a/memory.h b/memory.h
index 53bf261..beae127 100644
--- a/memory.h
+++ b/memory.h
@@ -149,7 +149,7 @@ struct MemoryRegionPortio {
 /**
  * memory_region_init: Initialize a memory region
  *
- * The region typically acts as a container for other memory regions.  Us
+ * The region typically acts as a container for other memory regions.  Use
  * memory_region_add_subregion() to add subregions.
  *
  * @mr: the #MemoryRegion to be initialized
@@ -162,7 +162,7 @@ void memory_region_init(MemoryRegion *mr,
 /**
  * memory_region_init_io: Initialize an I/O memory region.
  *
- * Accesses into the region will be cause the callbacks in @ops to be called.
+ * Accesses into the region will cause the callbacks in @ops to be called.
  * if @size is nonzero, subregions will be clipped to @size.
  *
  * @mr: the #MemoryRegion to be initialized.
@@ -180,7 +180,7 @@ void memory_region_init_io(MemoryRegion *mr,
 
 /**
  * memory_region_init_ram:  Initialize RAM memory region.  Accesses into the
- *                          region will be modify memory directly.
+ *                          region will modify memory directly.
  *
  * @mr: the #MemoryRegion to be initialized.
  * @dev: a device associated with the region; may be %NULL.
@@ -196,7 +196,7 @@ void memory_region_init_ram(MemoryRegion *mr,
 
 /**
  * memory_region_init_ram:  Initialize RAM memory region from a user-provided.
- *                          pointer.  Accesses into the region will be modify
+ *                          pointer.  Accesses into the region will modify
  *                          memory directly.
  *
  * @mr: the #MemoryRegion to be initialized.
@@ -250,7 +250,7 @@ void memory_region_init_rom_device(MemoryRegion *mr,
                                    uint64_t size);
 
 /**
- * memory_region_destroy: Destroy a memory region and relaim all resources.
+ * memory_region_destroy: Destroy a memory region and reclaim all resources.
  *
  * @mr: the region to be destroyed.  May not currently be a subregion
  *      (see memory_region_add_subregion()) or referenced in an alias
@@ -417,7 +417,7 @@ void memory_region_clear_coalescing(MemoryRegion *mr);
  *
  * Marks a word in an IO region (initialized with memory_region_init_io())
  * as a trigger for an eventfd event.  The I/O callback will not be called.
- * The caller must be prepared to handle failure (hat is, take the required
+ * The caller must be prepared to handle failure (that is, take the required
  * action if the callback _is_ called).
  *
  * @mr: the memory region being updated.
@@ -435,10 +435,10 @@ void memory_region_add_eventfd(MemoryRegion *mr,
                                int fd);
 
 /**
- * memory_region_del_eventfd: Cancel and eventfd.
+ * memory_region_del_eventfd: Cancel an eventfd.
  *
- * Cancels an eventfd trigger request by a previous memory_region_add_eventfd()
- * call.
+ * Cancels an eventfd trigger requested by a previous
+ * memory_region_add_eventfd() call.
  *
  * @mr: the memory region being updated.
  * @addr: the address within @mr that is to be monitored
@@ -454,9 +454,9 @@ void memory_region_del_eventfd(MemoryRegion *mr,
                                uint64_t data,
                                int fd);
 /**
- * memory_region_add_subregion: Add a sub-region to a container.
+ * memory_region_add_subregion: Add a subregion to a container.
  *
- * Adds a sub-region at @offset.  The sub-region may not overlap with other
+ * Adds a subregion at @offset.  The subregion may not overlap with other
  * subregions (except for those explicitly marked as overlapping).  A region
  * may only be added once as a subregion (unless removed with
  * memory_region_del_subregion()); use memory_region_init_alias() if you
@@ -471,9 +471,9 @@ void memory_region_add_subregion(MemoryRegion *mr,
                                  target_phys_addr_t offset,
                                  MemoryRegion *subregion);
 /**
- * memory_region_add_subregion: Add a sub-region to a container, with overlap.
+ * memory_region_add_subregion: Add a subregion to a container, with overlap.
  *
- * Adds a sub-region at @offset.  The sub-region may overlap with other
+ * Adds a subregion at @offset.  The subregion may overlap with other
  * subregions.  Conflicts are resolved by having a higher @priority hide a
  * lower @priority. Subregions without priority are taken as @priority 0.
  * A region may only be added once as a subregion (unless removed with
@@ -501,11 +501,17 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr,
 void memory_region_del_subregion(MemoryRegion *mr,
                                  MemoryRegion *subregion);
 
-/* Start a transaction; changes will be accumulated and made visible only
- * when the transaction ends.
+/**
+ * memory_region_transaction_begin: Start a transaction.
+ *
+ * During a transaction, changes will be accumulated and made visible
+ * only when the transaction ends (is commited).
  */
 void memory_region_transaction_begin(void);
-/* Commit a transaction and make changes visible to the guest.
+
+/**
+ * memory_region_transaction_commit: Commit a transaction and make changes
+ *                                   visible to the guest.
  */
 void memory_region_transaction_commit(void);
 
commit 31b631936376042a503b5378d9716137b170b758
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Dec 5 23:11:50 2011 +0000

    linux-user/syscall.c: Don't skip stracing for fcntl64 failure case
    
    In an fcntl64 failure path, we were returning directly rather than
    simply breaking out of the switch statement. This skips the strace
    code for printing the syscall return value, so don't do that.
    
    Acked-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index c84cc65..2bf9e7e 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7521,8 +7521,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 
 	cmd = target_to_host_fcntl_cmd(arg2);
-	if (cmd == -TARGET_EINVAL)
-		return cmd;
+        if (cmd == -TARGET_EINVAL) {
+            ret = cmd;
+            break;
+        }
 
         switch(arg2) {
         case TARGET_F_GETLK64:
commit 4a2dd92d7b89d00cb8afa90aa588fef44a79aa88
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Dec 5 15:18:54 2011 +0100

    Rename get_tls to tls_var
    
    get_tls() can serve as a lvalue as well, so 'get' might be confusing.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/cpu-all.h b/cpu-all.h
index 7246a67..9d78715 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -336,7 +336,7 @@ void QEMU_NORETURN cpu_abort(CPUState *env, const char *fmt, ...)
     GCC_FMT_ATTR(2, 3);
 extern CPUState *first_cpu;
 DECLARE_TLS(CPUState *,cpu_single_env);
-#define cpu_single_env get_tls(cpu_single_env)
+#define cpu_single_env tls_var(cpu_single_env)
 
 /* Flags for use in ENV->INTERRUPT_PENDING.
 
diff --git a/qemu-tls.h b/qemu-tls.h
index 5b70f10..b92ea9d 100644
--- a/qemu-tls.h
+++ b/qemu-tls.h
@@ -41,12 +41,12 @@
 #ifdef __linux__
 #define DECLARE_TLS(type, x) extern DEFINE_TLS(type, x)
 #define DEFINE_TLS(type, x)  __thread __typeof__(type) tls__##x
-#define get_tls(x)           tls__##x
+#define tls_var(x)           tls__##x
 #else
 /* Dummy implementations which define plain global variables */
 #define DECLARE_TLS(type, x) extern DEFINE_TLS(type, x)
 #define DEFINE_TLS(type, x)  __typeof__(type) tls__##x
-#define get_tls(x)           tls__##x
+#define tls_var(x)           tls__##x
 #endif
 
 #endif
commit 75dfbc16cf8a7a6a0db461cf0f77f0cca40bb654
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Dec 2 19:30:45 2011 +0000

    linux-user/arm/nwfpe/fpopcode.h: Fix non-UTF-8 characters
    
    Fix some stray non-UTF-8 characters used in some ASCII art tables
    by converting them to plain ASCII '|' instead.
    
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/linux-user/arm/nwfpe/fpopcode.h b/linux-user/arm/nwfpe/fpopcode.h
index e7d1009..1b1137f 100644
--- a/linux-user/arm/nwfpe/fpopcode.h
+++ b/linux-user/arm/nwfpe/fpopcode.h
@@ -75,11 +75,11 @@ TABLE 1
 +-------------------------+---+---+---------+---------+
 |  Precision              | u | v | FPSR.EP | length  |
 +-------------------------+---+---+---------+---------+
-| Single                  | 0 ü 0 |    x    | 1 words |
-| Double                  | 1 ü 1 |    x    | 2 words |
-| Extended                | 1 ü 1 |    x    | 3 words |
-| Packed decimal          | 1 ü 1 |    0    | 3 words |
-| Expanded packed decimal | 1 ü 1 |    1    | 4 words |
+| Single                  | 0 | 0 |    x    | 1 words |
+| Double                  | 1 | 1 |    x    | 2 words |
+| Extended                | 1 | 1 |    x    | 3 words |
+| Packed decimal          | 1 | 1 |    0    | 3 words |
+| Expanded packed decimal | 1 | 1 |    1    | 4 words |
 +-------------------------+---+---+---------+---------+
 Note: x = don't care
 */
@@ -89,10 +89,10 @@ TABLE 2
 +---+---+---------------------------------+
 | w | x | Number of registers to transfer |
 +---+---+---------------------------------+
-| 0 ü 1 |  1                              |
-| 1 ü 0 |  2                              |
-| 1 ü 1 |  3                              |
-| 0 ü 0 |  4                              |
+| 0 | 1 |  1                              |
+| 1 | 0 |  2                              |
+| 1 | 1 |  3                              |
+| 0 | 0 |  4                              |
 +---+---+---------------------------------+
 */
 
@@ -153,10 +153,10 @@ TABLE 5
 +-------------------------+---+---+
 |  Rounding Precision     | e | f |
 +-------------------------+---+---+
-| IEEE Single precision   | 0 ü 0 |
-| IEEE Double precision   | 0 ü 1 |
-| IEEE Extended precision | 1 ü 0 |
-| undefined (trap)        | 1 ü 1 |
+| IEEE Single precision   | 0 | 0 |
+| IEEE Double precision   | 0 | 1 |
+| IEEE Extended precision | 1 | 0 |
+| undefined (trap)        | 1 | 1 |
 +-------------------------+---+---+
 */
 
@@ -165,10 +165,10 @@ TABLE 5
 +---------------------------------+---+---+
 |  Rounding Mode                  | g | h |
 +---------------------------------+---+---+
-| Round to nearest (default)      | 0 ü 0 |
-| Round toward plus infinity      | 0 ü 1 |
-| Round toward negative infinity  | 1 ü 0 |
-| Round toward zero               | 1 ü 1 |
+| Round to nearest (default)      | 0 | 0 |
+| Round toward plus infinity      | 0 | 1 |
+| Round toward negative infinity  | 1 | 0 |
+| Round toward zero               | 1 | 1 |
 +---------------------------------+---+---+
 */
 
commit 7ff60e158b19a5126ad2c05092f0bb3700546c99
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Dec 2 19:30:44 2011 +0000

    linux-user/cpu-uname.c: Convert to UTF-8
    
    Convert comment from ISO-8859-1 encoding to UTF-8 to match the rest
    of QEMU's source code.
    
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/linux-user/cpu-uname.c b/linux-user/cpu-uname.c
index 23afede..ddc37be 100644
--- a/linux-user/cpu-uname.c
+++ b/linux-user/cpu-uname.c
@@ -1,7 +1,7 @@
 /*
  *  cpu to uname machine name map
  *
- *  Copyright (c) 2009 Loïc Minier
+ *  Copyright (c) 2009 Loïc Minier
  *
  *  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
commit a828f1b0091ddac5ece1bb6f92f6aa4957b7465b
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 3 10:45:25 2011 +0100

    Convert keymap file to UTF-8 encoding
    
    Most QEMU files either are pure ASCII or use UTF-8.
    Convert this keymap file which still used ISO-8859-1 to UTF-8.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/pc-bios/keymaps/is b/pc-bios/keymaps/is
index 21dc1fd..935ac1d 100644
--- a/pc-bios/keymaps/is
+++ b/pc-bios/keymaps/is
@@ -1,4 +1,4 @@
-# 2004-03-16 Halldór Guðmundsson and Morten Lange
+# 2004-03-16 Halldór Guðmundsson and Morten Lange
 # Keyboard definition file for the Icelandic keyboard
 # to be used in rdesktop 1.3.x ( See rdesktop.org)
 # generated from XKB map de, and changed manually
commit bcc4e41ffd0bd17977b1497a653dd33984d012e4
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Dec 2 10:30:41 2011 +0100

    Convert source files to UTF-8 encoding
    
    Most QEMU files either are pure ASCII or use UTF-8.
    Convert some files which still used ISO-8859-1 to UTF-8.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/ds1225y.c b/hw/ds1225y.c
index 59d224e..7aa0832 100644
--- a/hw/ds1225y.c
+++ b/hw/ds1225y.c
@@ -1,7 +1,7 @@
 /*
  * QEMU NVRAM emulation for DS1225Y chip
  *
- * Copyright (c) 2007-2008 Hervé Poussineau
+ * Copyright (c) 2007-2008 Hervé Poussineau
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
diff --git a/hw/fdc.c b/hw/fdc.c
index 2adfb44..70aa5c7 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -2,7 +2,7 @@
  * QEMU Floppy disk emulator (Intel 82078)
  *
  * Copyright (c) 2003, 2007 Jocelyn Mayer
- * Copyright (c) 2008 Hervé Poussineau
+ * Copyright (c) 2008 Hervé Poussineau
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
diff --git a/hw/jazz_led.c b/hw/jazz_led.c
index 6fab334..f8a2182 100644
--- a/hw/jazz_led.c
+++ b/hw/jazz_led.c
@@ -1,7 +1,7 @@
 /*
  * QEMU JAZZ LED emulator.
  *
- * Copyright (c) 2007 Hervé Poussineau
+ * Copyright (c) 2007 Hervé Poussineau
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
diff --git a/hw/tc6393xb_template.h b/hw/tc6393xb_template.h
index 1ccf6e8..4cbbad5 100644
--- a/hw/tc6393xb_template.h
+++ b/hw/tc6393xb_template.h
@@ -5,7 +5,7 @@
  *
  * FB support code. Based on G364 fb emulator
  *
- * Copyright (c) 2007 Hervé Poussineau
+ * Copyright (c) 2007 Hervé Poussineau
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
diff --git a/hw/vmport.c b/hw/vmport.c
index b5c6fa1..0a3dbc5 100644
--- a/hw/vmport.c
+++ b/hw/vmport.c
@@ -1,7 +1,7 @@
 /*
  * QEMU VMPort emulation
  *
- * Copyright (C) 2007 Hervé Poussineau
+ * Copyright (C) 2007 Hervé Poussineau
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
commit 6efd751789896dd6ac05c12f5149bba29c12ccae
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 30 11:59:04 2011 +0000

    configure: Pull linux-headers/asm symlink creation out of loop
    
    Pull the creation of the linux-headers/asm symlink out of the loop
    so we don't pointlessly delete and recreate it once for each target.
    Also move the setting of the includes variable up so that it is
    in the same place as the other code which sets this variable.
    
    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 452b8cf..4bcb8ef 100755
--- a/configure
+++ b/configure
@@ -3286,6 +3286,22 @@ for d in libdis libdis-user; do
     echo > $d/config.mak
 done
 
+# use included Linux headers
+if test "$linux" = "yes" ; then
+  mkdir -p linux-headers
+  case "$cpu" in
+  i386|x86_64)
+    symlink $source_path/linux-headers/asm-x86 linux-headers/asm
+    ;;
+  ppcemb|ppc|ppc64)
+    symlink $source_path/linux-headers/asm-powerpc linux-headers/asm
+    ;;
+  s390x)
+    symlink $source_path/linux-headers/asm-s390 linux-headers/asm
+    ;;
+  esac
+fi
+
 for target in $target_list; do
 target_dir="$target"
 config_target_mak=$target_dir/config-target.mak
@@ -3611,6 +3627,10 @@ else
 fi
 includes="-I\$(SRC_PATH)/tcg $includes"
 
+if test "$linux" = "yes" ; then
+  includes="-I\$(SRC_PATH)/linux-headers $includes"
+fi
+
 if test "$target_user_only" = "yes" ; then
     libdis_config_mak=libdis-user/config.mak
 else
@@ -3742,23 +3762,6 @@ if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then
   esac
 fi
 
-# use included Linux headers
-if test "$linux" = "yes" ; then
-  includes="-I\$(SRC_PATH)/linux-headers $includes"
-  mkdir -p linux-headers
-  case "$cpu" in
-  i386|x86_64)
-    symlink $source_path/linux-headers/asm-x86 linux-headers/asm
-    ;;
-  ppcemb|ppc|ppc64)
-    symlink $source_path/linux-headers/asm-powerpc linux-headers/asm
-    ;;
-  s390x)
-    symlink $source_path/linux-headers/asm-s390 linux-headers/asm
-    ;;
-  esac
-fi
-
 echo "LDFLAGS+=$ldflags" >> $config_target_mak
 echo "QEMU_CFLAGS+=$cflags" >> $config_target_mak
 echo "QEMU_INCLUDES+=$includes" >> $config_target_mak
commit 1f3392b7b3790e0207e6d1fc717f02949ae17190
Author: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
Date:   Wed Nov 30 12:39:47 2011 +0800

    pcie_aer: adjust do_pcie_aer_inejct_error -> do_pcie_aer_inject_error
    
    This function name is a bit wrong. Although it doesn't impact function, it is a bit necessary that we should fixup it.
    
    Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 79a9195..54b2abf 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -923,7 +923,7 @@ ETEXI
                       "<tlb header> = 32bit x 4\n\t\t\t"
                       "<tlb header prefix> = 32bit x 4",
         .user_print  = pcie_aer_inject_error_print,
-        .mhandler.cmd_new = do_pcie_aer_inejct_error,
+        .mhandler.cmd_new = do_pcie_aer_inject_error,
     },
 
 STEXI
diff --git a/hw/pci-stub.c b/hw/pci-stub.c
index 636171c..134c448 100644
--- a/hw/pci-stub.c
+++ b/hw/pci-stub.c
@@ -34,7 +34,7 @@ static void pci_error_message(Monitor *mon)
     monitor_printf(mon, "PCI devices not supported\n");
 }
 
-int do_pcie_aer_inejct_error(Monitor *mon,
+int do_pcie_aer_inject_error(Monitor *mon,
                              const QDict *qdict, QObject **ret_data)
 {
     pci_error_message(mon);
diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c
index b9d1097..3b6981c 100644
--- a/hw/pcie_aer.c
+++ b/hw/pcie_aer.c
@@ -951,7 +951,7 @@ static int pcie_aer_parse_error_string(const char *error_name,
     return -EINVAL;
 }
 
-int do_pcie_aer_inejct_error(Monitor *mon,
+int do_pcie_aer_inject_error(Monitor *mon,
                              const QDict *qdict, QObject **ret_data)
 {
     const char *id = qdict_get_str(qdict, "id");
diff --git a/sysemu.h b/sysemu.h
index 22cd720..3806901 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -148,7 +148,7 @@ void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict);
 
 /* pcie aer error injection */
 void pcie_aer_inject_error_print(Monitor *mon, const QObject *data);
-int do_pcie_aer_inejct_error(Monitor *mon,
+int do_pcie_aer_inject_error(Monitor *mon,
                              const QDict *qdict, QObject **ret_data);
 
 /* serial ports */
commit 66a0a2cb81fb9d0e4e372a21cb62c1d0d877b112
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Tue Nov 29 16:52:39 2011 +0800

    fix spelling in hw sub directory
    
    Correct obvious spelling errors in qemu/hw directory.
    
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h
index c4b74b0..c31c965 100644
--- a/hw/9pfs/virtio-9p-coth.h
+++ b/hw/9pfs/virtio-9p-coth.h
@@ -44,7 +44,7 @@ typedef struct V9fsThPool {
                             qemu_coroutine_self());                     \
         qemu_bh_schedule(co_bh);                                        \
         /*                                                              \
-         * yeild in qemu thread and re-enter back                       \
+         * yield in qemu thread and re-enter back                       \
          * in glib worker thread                                        \
          */                                                             \
         qemu_coroutine_yield();                                         \
diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c
index 755e8e0..b556e39 100644
--- a/hw/9pfs/virtio-9p-handle.c
+++ b/hw/9pfs/virtio-9p-handle.c
@@ -520,7 +520,7 @@ static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
     }
     fh = g_malloc(sizeof(struct file_handle) + data->handle_bytes);
     fh->handle_bytes = data->handle_bytes;
-    /* add a "./" at the begining of the path */
+    /* add a "./" at the beginning of the path */
     snprintf(buffer, PATH_MAX, "./%s", name);
     /* flag = 0 imply don't follow symlink */
     ret = name_to_handle(dirfd, buffer, fh, &mnt_id, 0);
diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c
index fcc20e9..598b830 100644
--- a/hw/alpha_dp264.c
+++ b/hw/alpha_dp264.c
@@ -2,7 +2,7 @@
  * QEMU Alpha DP264/CLIPPER hardware system emulator.
  *
  * Choose CLIPPER IRQ mappings over, say, DP264, MONET, or WEBBRICK
- * variants because CLIPPER doesn't have an SMC669 SuperIO controler
+ * variants because CLIPPER doesn't have an SMC669 SuperIO controller
  * that we need to emulate as well.
  */
 
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 527c9ce..1a896fb 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -602,7 +602,7 @@ static uint32_t gic_cpu_read(gic_state *s, int cpu, int offset)
         return 0;
     case 0x0c: /* Acknowledge */
         return gic_acknowledge_irq(s, cpu);
-    case 0x14: /* Runing Priority */
+    case 0x14: /* Running Priority */
         return s->running_priority[cpu];
     case 0x18: /* Highest Pending Interrupt */
         return s->current_pending[cpu];
diff --git a/hw/bt-hci-csr.c b/hw/bt-hci-csr.c
index 0dcf897..772b677 100644
--- a/hw/bt-hci-csr.c
+++ b/hw/bt-hci-csr.c
@@ -222,7 +222,7 @@ static void csrhci_in_packet(struct csrhci_s *s, uint8_t *pkt)
 
         rpkt = csrhci_out_packet_csr(s, H4_NEG_PKT, 10);
 
-        *rpkt ++ = 0x20;	/* Operational settings negotation Ok */
+        *rpkt ++ = 0x20;	/* Operational settings negotiation Ok */
         memcpy(rpkt, pkt, 7); rpkt += 7;
         *rpkt ++ = 0xff;
         *rpkt = 0xff;
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index c7e365b..1b216e8 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -783,7 +783,7 @@ static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
                 s->cirrus_srccounter -= s->cirrus_blt_srcpitch;
                 if (s->cirrus_srccounter <= 0)
                     goto the_end;
-                /* more bytes than needed can be transfered because of
+                /* more bytes than needed can be transferred because of
                    word alignment, so we keep them for the next line */
                 /* XXX: keep alignment to speed up transfer */
                 end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
diff --git a/hw/e1000_hw.h b/hw/e1000_hw.h
index 2e341ac..9e29af8 100644
--- a/hw/e1000_hw.h
+++ b/hw/e1000_hw.h
@@ -295,7 +295,7 @@
 
 #define E1000_KUMCTRLSTA 0x00034 /* MAC-PHY interface - RW */
 #define E1000_MDPHYA     0x0003C  /* PHY address - RW */
-#define E1000_MANC2H     0x05860  /* Managment Control To Host - RW */
+#define E1000_MANC2H     0x05860  /* Management Control To Host - RW */
 #define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */
 
 #define E1000_GCR       0x05B00 /* PCI-Ex Control */
diff --git a/hw/etraxfs_dma.c b/hw/etraxfs_dma.c
index 02d0183..d2bd584 100644
--- a/hw/etraxfs_dma.c
+++ b/hw/etraxfs_dma.c
@@ -180,7 +180,7 @@ struct fs_dma_channel
 	struct dma_descr_context current_c;
 	struct dma_descr_data current_d;
 
-	/* Controll registers.  */
+	/* Control registers.  */
 	uint32_t regs[DMA_REG_MAX];
 };
 
diff --git a/hw/etraxfs_pic.c b/hw/etraxfs_pic.c
index 72cbdb8..993d6a8 100644
--- a/hw/etraxfs_pic.c
+++ b/hw/etraxfs_pic.c
@@ -53,7 +53,7 @@ static void pic_update(struct etrax_pic *fs)
 
     fs->regs[R_R_MASKED_VECT] = fs->regs[R_R_VECT] & fs->regs[R_RW_MASK];
 
-    /* The ETRAX interrupt controller signals interrupts to teh core
+    /* The ETRAX interrupt controller signals interrupts to the core
        through an interrupt request wire and an irq vector bus. If 
        multiple interrupts are simultaneously active it chooses vector 
        0x30 and lets the sw choose the priorities.  */
diff --git a/hw/fmopl.c b/hw/fmopl.c
index 5ad52ab..6198b89 100644
--- a/hw/fmopl.c
+++ b/hw/fmopl.c
@@ -715,7 +715,7 @@ static void OPLCloseTable( void )
 	free(VIB_TABLE);
 }
 
-/* CSM Key Controll */
+/* CSM Key Control */
 INLINE void CSMKeyControll(OPL_CH *CH)
 {
 	OPL_SLOT *slot1 = &CH->SLOT[SLOT1];
@@ -762,7 +762,7 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
 
 	switch(r&0xe0)
 	{
-	case 0x00: /* 00-1f:controll */
+	case 0x00: /* 00-1f:control */
 		switch(r&0x1f)
 		{
 		case 0x01:
@@ -826,7 +826,7 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
 					LOG(LOG_WAR,("OPL:write unmapped KEYBOARD port\n"));
 			}
 			return;
-		case 0x07:	/* DELTA-T controll : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */
+		case 0x07:	/* DELTA-T control : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */
 			if(OPL->type&OPL_TYPE_ADPCM)
 				YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
 			return;
@@ -1380,7 +1380,7 @@ int OPLTimerOver(FM_OPL *OPL,int c)
 	else
 	{	/* Timer A */
 		OPL_STATUS_SET(OPL,0x40);
-		/* CSM mode key,TL controll */
+		/* CSM mode key,TL control */
 		if( OPL->mode & 0x80 )
 		{	/* CSM mode total level latch and auto key on */
 			int ch;
diff --git a/hw/gusemu.h b/hw/gusemu.h
index 5093767..34872aa 100644
--- a/hw/gusemu.h
+++ b/hw/gusemu.h
@@ -83,7 +83,7 @@ void gus_dma_transferdata(GUSEmuState *state, char *dma_addr, unsigned int count
 /* it is possible to break down a single transfer into multiple ones, but take care that: */
 /* -dma_count is actually count-1 */
 /* -before and during a transfer, DREQ is set and TC cleared */
-/* -when calling gus_dma_transferdata(), TC is only set true for call transfering the last byte */
+/* -when calling gus_dma_transferdata(), TC is only set true for call transferring the last byte */
 /* -after the last transfer, DREQ is cleared and TC is set */
 
 /* ** GF1 mixer emulation functions: */
diff --git a/hw/gusemu_hal.c b/hw/gusemu_hal.c
index c6f9537..6096690 100644
--- a/hw/gusemu_hal.c
+++ b/hw/gusemu_hal.c
@@ -502,7 +502,7 @@ void gus_dma_transferdata(GUSEmuState * state, char *dma_addr, unsigned int coun
     /* this function gets called by the callback function as soon as a DMA transfer is about to start
      * dma_addr is a translated address within accessible memory, not the physical one,
      * count is (real dma count register)+1
-     * note that the amount of bytes transfered is fully determined by values in the DMA registers
+     * note that the amount of bytes transferred is fully determined by values in the DMA registers
      * do not forget to update DMA states after transferring the entire block:
      * DREQ cleared & TC asserted after the _whole_ transfer */
 
@@ -517,7 +517,7 @@ void gus_dma_transferdata(GUSEmuState * state, char *dma_addr, unsigned int coun
         int             offset = (GUSregw(GUS42DMAStart) << 4) + (GUSregb(GUS50DMAHigh) & 0xf);
         if (state->gusdma >= 4)
             offset = (offset & 0xc0000) + (2 * (offset & 0x1fff0)); /* 16 bit address translation */
-        destaddr = (char *) state->himemaddr + offset; /* wavetable RAM adress */
+        destaddr = (char *) state->himemaddr + offset; /* wavetable RAM address */
     }
 
     GUSregw(GUS42DMAStart) += (GUSword)  (count >> 4);                           /* ToDo: add 16bit GUS page limit? */
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 93a1a68..49847bd 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1000,7 +1000,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
     printf("ide: CMD=%02x\n", val);
 #endif
     s = idebus_active_if(bus);
-    /* ignore commands to non existant slave */
+    /* ignore commands to non existent slave */
     if (s != bus->ifs && !s->bs)
         return;
 
diff --git a/hw/lan9118.c b/hw/lan9118.c
index ee8b2ea..7e64c5d 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -697,7 +697,7 @@ static uint32_t do_phy_read(lan9118_state *s, int reg)
         return 0x0007;
     case 3: /* ID2 */
         return 0xc0d1;
-    case 4: /* Auto-neg advertisment */
+    case 4: /* Auto-neg advertisement */
         return s->phy_advertise;
     case 5: /* Auto-neg Link Partner Ability */
         return 0x0f71;
@@ -731,7 +731,7 @@ static void do_phy_write(lan9118_state *s, int reg, uint32_t val)
             s->phy_status |= 0x0020;
         }
         break;
-    case 4: /* Auto-neg advertisment */
+    case 4: /* Auto-neg advertisement */
         s->phy_advertise = (val & 0x2d7f) | 0x80;
         break;
         /* TODO 17, 18, 27, 31 */
diff --git a/hw/omap2.c b/hw/omap2.c
index 91577ae..c09c04a 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -1616,7 +1616,7 @@ static void omap_prcm_write(void *opaque, target_phys_addr_t addr,
     case 0x500:	/* CM_CLKEN_PLL */
         if (value & 0xffffff30)
             fprintf(stderr, "%s: write 0s in CM_CLKEN_PLL for "
-                            "future compatiblity\n", __FUNCTION__);
+                            "future compatibility\n", __FUNCTION__);
         if ((s->clken[9] ^ value) & 0xcc) {
             s->clken[9] &= ~0xcc;
             s->clken[9] |= value & 0xcc;
@@ -1635,7 +1635,7 @@ static void omap_prcm_write(void *opaque, target_phys_addr_t addr,
     case 0x540:	/* CM_CLKSEL1_PLL */
         if (value & 0xfc4000d7)
             fprintf(stderr, "%s: write 0s in CM_CLKSEL1_PLL for "
-                            "future compatiblity\n", __FUNCTION__);
+                            "future compatibility\n", __FUNCTION__);
         if ((s->clksel[5] ^ value) & 0x003fff00) {
             s->clksel[5] = value & 0x03bfff28;
             omap_prcm_dpll_update(s);
@@ -1647,7 +1647,7 @@ static void omap_prcm_write(void *opaque, target_phys_addr_t addr,
     case 0x544:	/* CM_CLKSEL2_PLL */
         if (value & ~3)
             fprintf(stderr, "%s: write 0s in CM_CLKSEL2_PLL[31:2] for "
-                            "future compatiblity\n", __FUNCTION__);
+                            "future compatibility\n", __FUNCTION__);
         if (s->clksel[6] != (value & 3)) {
             s->clksel[6] = value & 3;
             omap_prcm_dpll_update(s);
diff --git a/hw/pc.c b/hw/pc.c
index 33778fe..b6dcba2 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -983,7 +983,7 @@ void pc_memory_init(MemoryRegion *system_memory,
     linux_boot = (kernel_filename != NULL);
 
     /* Allocate RAM.  We allocate it as a single memory region and use
-     * aliases to address portions of it, mostly for backwards compatiblity
+     * aliases to address portions of it, mostly for backwards compatibility
      * with older qemus that used qemu_ram_alloc().
      */
     ram = g_malloc(sizeof(*ram));
diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c
index 62c06ea..b9d1097 100644
--- a/hw/pcie_aer.c
+++ b/hw/pcie_aer.c
@@ -826,7 +826,7 @@ typedef struct PCIEAERErrorName {
 } PCIEAERErrorName;
 
 /*
- * AER error name -> value convertion table
+ * AER error name -> value conversion table
  * This naming scheme is same to linux aer-injection tool.
  */
 static const struct PCIEAERErrorName pcie_aer_error_list[] = {
diff --git a/hw/pl110.c b/hw/pl110.c
index 7aef8a4..cc1eb6d 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -358,7 +358,7 @@ static void pl110_write(void *opaque, target_phys_addr_t offset,
     int n;
 
     /* For simplicity invalidate the display whenever a control register
-       is writen to.  */
+       is written to.  */
     s->invalidate = 1;
     if (offset >= 0x200 && offset < 0x400) {
         /* Pallette.  */
diff --git a/hw/pl181.c b/hw/pl181.c
index 46855f6..d05bc19 100644
--- a/hw/pl181.c
+++ b/hw/pl181.c
@@ -311,9 +311,9 @@ static uint64_t pl181_read(void *opaque, target_phys_addr_t offset,
     case 0x48: /* FifoCnt */
         /* The documentation is somewhat vague about exactly what FifoCnt
            does.  On real hardware it appears to be when decrememnted
-           when a word is transfered between the FIFO and the serial
+           when a word is transferred between the FIFO and the serial
            data engine.  DataCnt is decremented after each byte is
-           transfered between the serial engine and the card.
+           transferred between the serial engine and the card.
            We don't emulate this level of detail, so both can be the same.  */
         tmp = (s->datacnt + 3) >> 2;
         if (s->linux_hack) {
diff --git a/hw/sh7750_regs.h b/hw/sh7750_regs.h
index 6ec13ab..534aa48 100644
--- a/hw/sh7750_regs.h
+++ b/hw/sh7750_regs.h
@@ -157,7 +157,7 @@
  * Exeption-related registers
  */
 
-/* Immediate data for TRAPA instuction - TRA */
+/* Immediate data for TRAPA instruction - TRA */
 #define SH7750_TRA_REGOFS     0x000020	/* offset */
 #define SH7750_TRA            SH7750_P4_REG32(SH7750_TRA_REGOFS)
 #define SH7750_TRA_A7         SH7750_A7_REG32(SH7750_TRA_REGOFS)
diff --git a/hw/spapr.h b/hw/spapr.h
index df88f6a..d624841 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -141,7 +141,7 @@ typedef struct sPAPREnvironment {
 #define H_DABRX_KERNEL     (1ULL<<(63-62))
 #define H_DABRX_USER       (1ULL<<(63-63))
 
-/* Each control block has to be on a 4K bondary */
+/* Each control block has to be on a 4K boundary */
 #define H_CB_ALIGNMENT     4096
 
 /* pSeries hypervisor opcodes */
diff --git a/hw/wdt_ib700.c b/hw/wdt_ib700.c
index 81f22d0..ba1d92d 100644
--- a/hw/wdt_ib700.c
+++ b/hw/wdt_ib700.c
@@ -42,7 +42,7 @@ typedef struct IB700state {
 
 /* This is the timer.  We use a global here because the watchdog
  * code ensures there is only one watchdog (it is located at a fixed,
- * unchangable IO port, so there could only ever be one anyway).
+ * unchangeable IO port, so there could only ever be one anyway).
  */
 
 /* A write to this register enables the timer. */
commit 3a93113a002db694657fcf24ff0c96aef83303b8
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Tue Nov 29 16:52:38 2011 +0800

    fix typo: delete redundant semicolon
    
    Double semicolons should be single.
    
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/nbd.c b/block/nbd.c
index 882b2dc..95212da 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -189,7 +189,7 @@ static int nbd_read(BlockDriverState *bs, int64_t sector_num,
 
     request.type = NBD_CMD_READ;
     request.handle = (uint64_t)(intptr_t)bs;
-    request.from = sector_num * 512;;
+    request.from = sector_num * 512;
     request.len = nb_sectors * 512;
 
     if (nbd_send_request(s->sock, &request) == -1)
@@ -219,7 +219,7 @@ static int nbd_write(BlockDriverState *bs, int64_t sector_num,
 
     request.type = NBD_CMD_WRITE;
     request.handle = (uint64_t)(intptr_t)bs;
-    request.from = sector_num * 512;;
+    request.from = sector_num * 512;
     request.len = nb_sectors * 512;
 
     if (nbd_send_request(s->sock, &request) == -1)
diff --git a/cpus.c b/cpus.c
index ca46ec6..a53276a 100644
--- a/cpus.c
+++ b/cpus.c
@@ -89,7 +89,7 @@ TimersState timers_state;
 int64_t cpu_get_icount(void)
 {
     int64_t icount;
-    CPUState *env = cpu_single_env;;
+    CPUState *env = cpu_single_env;
 
     icount = qemu_icount;
     if (env) {
diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
index 9b6d47d..3d18828 100644
--- a/hw/9pfs/codir.c
+++ b/hw/9pfs/codir.c
@@ -90,7 +90,7 @@ int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name,
     V9fsState *s = pdu->s;
 
     if (v9fs_request_cancelled(pdu)) {
-        return -EINTR;;
+        return -EINTR;
     }
     cred_init(&cred);
     cred.fc_mode = mode;
@@ -124,7 +124,7 @@ int v9fs_co_opendir(V9fsPDU *pdu, V9fsFidState *fidp)
     V9fsState *s = pdu->s;
 
     if (v9fs_request_cancelled(pdu)) {
-        return -EINTR;;
+        return -EINTR;
     }
     v9fs_path_read_lock(s);
     v9fs_co_run_in_worker(
@@ -152,7 +152,7 @@ int v9fs_co_closedir(V9fsPDU *pdu, V9fsFidOpenState *fs)
     V9fsState *s = pdu->s;
 
     if (v9fs_request_cancelled(pdu)) {
-        return -EINTR;;
+        return -EINTR;
     }
     v9fs_co_run_in_worker(
         {
diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c
index f97d898..755e8e0 100644
--- a/hw/9pfs/virtio-9p-handle.c
+++ b/hw/9pfs/virtio-9p-handle.c
@@ -59,7 +59,7 @@ static inline int open_by_handle(int mountfd, const char *fh, int flags)
 static int handle_update_file_cred(int dirfd, const char *name, FsCred *credp)
 {
     int fd, ret;
-    fd = openat(dirfd, name, O_NONBLOCK | O_NOFOLLOW);;
+    fd = openat(dirfd, name, O_NONBLOCK | O_NOFOLLOW);
     if (fd < 0) {
         return fd;
     }
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index dd43209..36a862f 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -1492,7 +1492,7 @@ static void v9fs_walk(void *opaque)
     int32_t fid, newfid;
     V9fsString *wnames = NULL;
     V9fsFidState *fidp;
-    V9fsFidState *newfidp = NULL;;
+    V9fsFidState *newfidp = NULL;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
@@ -2398,7 +2398,7 @@ static void v9fs_link(void *opaque)
     V9fsState *s = pdu->s;
     int32_t dfid, oldfid;
     V9fsFidState *dfidp, *oldfidp;
-    V9fsString name;;
+    V9fsString name;
     size_t offset = 7;
     int err = 0;
 
diff --git a/hw/acpi.c b/hw/acpi.c
index 1cf35e1..9c35f2d 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -304,7 +304,7 @@ void acpi_pm_tmr_calc_overflow_time(ACPIPMTimer *tmr)
 
 uint32_t acpi_pm_tmr_get(ACPIPMTimer *tmr)
 {
-    uint32_t d = acpi_pm_tmr_get_clock();;
+    uint32_t d = acpi_pm_tmr_get_clock();
     return d & 0xffffff;
 }
 
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 29ec5b4..e430f56 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -258,7 +258,7 @@ typedef struct {
 
     /* Data in mem is always in the byte order of the controller (le).
      * It must be dword aligned to allow direct access to 32 bit values. */
-    uint8_t mem[PCI_MEM_SIZE] __attribute__((aligned(8)));;
+    uint8_t mem[PCI_MEM_SIZE] __attribute__((aligned(8)));
 
     /* Configuration bytes. */
     uint8_t configuration[22];
diff --git a/hw/ide/via.c b/hw/ide/via.c
index 098f150..a57134c 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -172,7 +172,7 @@ static void vt82c686b_init_ports(PCIIDEState *d) {
 /* via ide func */
 static int vt82c686b_ide_initfn(PCIDevice *dev)
 {
-    PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);;
+    PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
     uint8_t *pci_conf = d->dev.config;
 
     pci_config_set_prog_interface(pci_conf, 0x8a); /* legacy ATA mode */
diff --git a/hw/ppc.c b/hw/ppc.c
index d29af0b..59882e2 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -1153,7 +1153,7 @@ void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
 /* NVRAM helpers */
 static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
 {
-    return (*nvram->read_fn)(nvram->opaque, addr);;
+    return (*nvram->read_fn)(nvram->opaque, addr);
 }
 
 static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index 9a3eddf..82b8811 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -429,7 +429,7 @@ static void smc91c111_writeb(void *opaque, target_phys_addr_t offset,
             smc91c111_update(s);
             return;
         }
-        break;;
+        break;
 
     case 3:
         switch (offset) {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f227097..c84cc65 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2377,7 +2377,7 @@ static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
     if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
         return -TARGET_EFAULT;
     if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
-        return -TARGET_EFAULT;;
+        return -TARGET_EFAULT;
     target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
     target_sd->sem_otime = tswapal(host_sd->sem_otime);
     target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
diff --git a/net/tap-solaris.c b/net/tap-solaris.c
index c216d28..cf76463 100644
--- a/net/tap-solaris.c
+++ b/net/tap-solaris.c
@@ -65,7 +65,7 @@ static int tap_alloc(char *dev, size_t dev_size)
     static int arp_fd = 0;
     int ip_muxid, arp_muxid;
     struct strioctl  strioc_if, strioc_ppa;
-    int link_type = I_PLINK;;
+    int link_type = I_PLINK;
     struct lifreq ifr;
     char actual_name[32] = "";
 
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index 137bae7..b8a1a8a 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -1336,7 +1336,7 @@ void HELPER(meeb)(uint32_t f1, uint32_t val)
 uint32_t HELPER(cebr)(uint32_t f1, uint32_t f2)
 {
     float32 v1 = env->fregs[f1].l.upper;
-    float32 v2 = env->fregs[f2].l.upper;;
+    float32 v2 = env->fregs[f2].l.upper;
     HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __FUNCTION__,
                v1, f1, v2);
     return set_cc_f32(v1, v2);
@@ -1346,7 +1346,7 @@ uint32_t HELPER(cebr)(uint32_t f1, uint32_t f2)
 uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2)
 {
     float64 v1 = env->fregs[f1].d;
-    float64 v2 = env->fregs[f2].d;;
+    float64 v2 = env->fregs[f2].d;
     HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __FUNCTION__,
                v1, f1, v2);
     return set_cc_f64(v1, v2);
diff --git a/ui/vnc.c b/ui/vnc.c
index e85ee66..6767ada 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2183,7 +2183,7 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
 
 #ifdef CONFIG_VNC_TLS
        case VNC_AUTH_VENCRYPT:
-           VNC_DEBUG("Accept VeNCrypt auth\n");;
+           VNC_DEBUG("Accept VeNCrypt auth\n");
            start_auth_vencrypt(vs);
            break;
 #endif /* CONFIG_VNC_TLS */
diff --git a/usb-redir.c b/usb-redir.c
index fb91c92..a36f2a7 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -542,9 +542,9 @@ static int usbredir_handle_data(USBDevice *udev, USBPacket *p)
     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);;
+        return usbredir_handle_bulk_data(dev, p, ep);
     case USB_ENDPOINT_XFER_INT:
-        return usbredir_handle_interrupt_data(dev, p, ep);;
+        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);
commit 91a9ecefb6d7f066c6eecc09f7231ce7969d1817
Author: Zhi Hui Li <zhihuili at linux.vnet.ibm.com>
Date:   Thu Nov 24 16:27:52 2011 +0800

    win32: fix memory leak
    
    string is allocated by g_malloc, will not be used after putenv, should be
    free before return.
    
    Paolo Bonzini <pbonzini at redhat.com> confirmed this is safe under Wine:
    
    "1) the underlying Win32 APIs require separate arguments for the
    variable and value; 2) even though in the end Wine stores the
    environment as name=value
    (http://source.winehq.org/source/dlls/ntdll/env.c), it does so in a
    single consecutive block of memory, not as a char* array like POSIX
    does.  While (2) might apply only to Wine, (1) surely applies to Windows
    as well."
    
    Tested-by: Stefan Weil <sw at weilnetz.de>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Li Zhi Hui <zhihuili at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/os-win32.c b/os-win32.c
index 8ad5fa1..8523d8d 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -44,6 +44,13 @@ int setenv(const char *name, const char *value, int overwrite)
         char *string = g_malloc(length);
         snprintf(string, length, "%s=%s", name, value);
         result = putenv(string);
+
+        /* Windows takes a copy and does not continue to use our string.
+         * Therefore it can be safely freed on this platform.  POSIX code
+         * typically has to leak the string because according to the spec it
+         * becomes part of the environment.
+         */
+        g_free(string);
     }
     return result;
 }
commit c7ee8f683d93c7ea346a5eb86495da672ce7e7da
Author: Zhi Hui Li <zhihuili at linux.vnet.ibm.com>
Date:   Thu Nov 24 16:23:00 2011 +0800

    net/socket.c : fix memory leak
    
    Signed-off-by: Li Zhi Hui <zhihuili at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/net/socket.c b/net/socket.c
index e9ef128..0f09164 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -409,6 +409,7 @@ static int net_socket_listen_init(VLANState *vlan,
     fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
     if (fd < 0) {
         perror("socket");
+        g_free(s);
         return -1;
     }
     socket_set_nonblock(fd);
@@ -420,11 +421,13 @@ static int net_socket_listen_init(VLANState *vlan,
     ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
     if (ret < 0) {
         perror("bind");
+        g_free(s);
         return -1;
     }
     ret = listen(fd, 0);
     if (ret < 0) {
         perror("listen");
+        g_free(s);
         return -1;
     }
     s->vlan = vlan;
commit b48e361194530539d3d420528b9c29a3287b77dd
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 23 17:26:44 2011 +0000

    configure: Print a banner comment at the top of config.log
    
    Print a banner comment at the top of config.log identifying
    when configure was run and the arguments used. This is occasionally
    useful for debugging purposes.
    
    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 c98aed1..452b8cf 100755
--- a/configure
+++ b/configure
@@ -20,6 +20,11 @@ TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.exe"
 trap "rm -f $TMPC $TMPO $TMPE" EXIT INT QUIT TERM
 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
+echo "#" >> config.log
+
 compile_object() {
   echo $cc $QEMU_CFLAGS -c -o $TMPO $TMPC >> config.log
   $cc $QEMU_CFLAGS -c -o $TMPO $TMPC >> config.log 2>&1
commit fd786e1aee5d3a0a304fccaa5cb6ae2cbbeb435e
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 23 17:26:43 2011 +0000

    configure: Include #define name in check_define compiler error
    
    Include the name of the #define being tested for in the compiler
    error produced when a check_define test is run and fails. This
    appears only in the config.log, but it does make it a little easier
    to debug problems by inspecting config.log.
    
    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 5fbd812..c98aed1 100755
--- a/configure
+++ b/configure
@@ -249,7 +249,7 @@ source_path=`cd "$source_path"; pwd`
 check_define() {
 cat > $TMPC <<EOF
 #if !defined($1)
-#error Not defined
+#error $1 not defined
 #endif
 int main(void) { return 0; }
 EOF
commit 0eba62e03292ff91201358fd544cadfbff36f1bf
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Nov 22 12:56:10 2011 +0100

    console: Fix qemu_default_pixelformat() for 24 bpp
    
    Falls through to 32 bpp.  Harmless, because the only difference is the
    alpha component, and we're not using that.  Spotted by Coverity.
    
    Acked-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/console.c b/console.c
index ce0429d..223f8fd 100644
--- a/console.c
+++ b/console.c
@@ -1688,6 +1688,7 @@ PixelFormat qemu_default_pixelformat(int bpp)
             pf.rbits = 8;
             pf.gbits = 8;
             pf.bbits = 8;
+            break;
         case 32:
             pf.rmask = 0x00FF0000;
             pf.gmask = 0x0000FF00;
commit 95d8f9f41c313c458dd34e0a54162c414a352111
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Nov 22 11:59:07 2011 +0100

    console: Fix console_putchar() for CSI J
    
    It falls through to the code for CSI K.  "Erase Down" also does "Erase
    End of Line", "Erase Up" also does "Erase Start of Line", and "Erase
    Screen" also does "Erase Line".  Happens not to be visible.  Fix it
    anyway.  Spotted by Coverity.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/console.c b/console.c
index 374fcba..ce0429d 100644
--- a/console.c
+++ b/console.c
@@ -1011,6 +1011,7 @@ static void console_putchar(TextConsole *s, int ch)
                     }
                     break;
                 }
+                break;
             case 'K':
                 switch (s->esc_params[0]) {
                 case 0:
commit f94a950f790aabb33fcb75f0a4a3bbaaa6e3810b
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Nov 22 11:59:06 2011 +0100

    console: Clean up confusing indentation in console_putchar()
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/console.c b/console.c
index f6fe441..374fcba 100644
--- a/console.c
+++ b/console.c
@@ -1009,16 +1009,16 @@ static void console_putchar(TextConsole *s, int ch)
                             console_clear_xy(s, x, y);
                         }
                     }
-                break;
+                    break;
                 }
             case 'K':
                 switch (s->esc_params[0]) {
                 case 0:
-                /* clear to eol */
-                for(x = s->x; x < s->width; x++) {
+                    /* clear to eol */
+                    for(x = s->x; x < s->width; x++) {
                         console_clear_xy(s, x, s->y);
-                }
-                break;
+                    }
+                    break;
                 case 1:
                     /* clear from beginning of line */
                     for (x = 0; x <= s->x; x++) {
@@ -1030,12 +1030,12 @@ static void console_putchar(TextConsole *s, int ch)
                     for(x = 0; x < s->width; x++) {
                         console_clear_xy(s, x, s->y);
                     }
-                break;
-            }
+                    break;
+                }
                 break;
             case 'm':
-            console_handle_escape(s);
-            break;
+                console_handle_escape(s);
+                break;
             case 'n':
                 /* report cursor position */
                 /* TODO: send ESC[row;colR */
commit 217bfb445b54db618a30f3a39170bebd9fd9dbf2
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Dec 1 19:37:17 2011 +0100

    hw/arm_gic.c: Ignore attempts to complete nonexistent IRQs
    
    Ignore attempts to complete non-existent IRQs; this fixes a buffer
    overrun if the guest writes a bad value to the GICC_EOIR register.
    (This case is UNPREDICTABLE so ignoring it is a valid choice.)
    Note that doing nothing if the guest writes 1023 to this register
    is not in fact a change in behaviour: the old code would also
    always do nothing in this case but in a non-obvious way.
    (The buffer overrun was noted by Coverity, see bug 887883.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index f3f3516..527c9ce 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -215,17 +215,26 @@ static void gic_complete_irq(gic_state * s, int cpu, int irq)
     int update = 0;
     int cm = 1 << cpu;
     DPRINTF("EOI %d\n", irq);
+    if (irq >= GIC_NIRQ) {
+        /* This handles two cases:
+         * 1. If software writes the ID of a spurious interrupt [ie 1023]
+         * to the GICC_EOIR, the GIC ignores that write.
+         * 2. If software writes the number of a non-existent interrupt
+         * this must be a subcase of "value written does not match the last
+         * valid interrupt value read from the Interrupt Acknowledge
+         * register" and so this is UNPREDICTABLE. We choose to ignore it.
+         */
+        return;
+    }
     if (s->running_irq[cpu] == 1023)
         return; /* No active IRQ.  */
-    if (irq != 1023) {
-        /* Mark level triggered interrupts as pending if they are still
-           raised.  */
-        if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm)
-                && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
-            DPRINTF("Set %d pending mask %x\n", irq, cm);
-            GIC_SET_PENDING(irq, cm);
-            update = 1;
-        }
+    /* Mark level triggered interrupts as pending if they are still
+       raised.  */
+    if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm)
+        && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
+        DPRINTF("Set %d pending mask %x\n", irq, cm);
+        GIC_SET_PENDING(irq, cm);
+        update = 1;
     }
     if (irq != s->running_irq[cpu]) {
         /* Complete an IRQ that is not currently running.  */
commit 21d89f841a8ff547cfe7ba97952fe4d5054b0421
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 30 10:57:48 2011 +0100

    configure: Drop armv4l/armv4b distinction in $cpu
    
    Drop the distinction between armv4l/armv4b in the $cpu variable
    (ie host cpu type) in favour of calling everything 'arm'. This
    makes it the same as the ARCH setting and removes some special
    casing. The only thing we were using the distinction for was to
    decide which endianness to use in cross compilation; do a cpp
    define check there instead.
    
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/configure b/configure
index ac4840d..5fbd812 100755
--- a/configure
+++ b/configure
@@ -287,10 +287,8 @@ elif check_define __s390__ ; then
   else
     cpu="s390"
   fi
-elif check_define __ARMEB__ ; then
-  cpu="armv4b"
-elif check_define __ARMEL__ ; then
-  cpu="armv4l"
+elif check_define __arm__ ; then
+  cpu="arm"
 elif check_define __hppa__ ; then
   cpu="hppa"
 else
@@ -307,11 +305,8 @@ case "$cpu" in
   x86_64|amd64)
     cpu="x86_64"
   ;;
-  armv*b)
-    cpu="armv4b"
-  ;;
-  armv*l)
-    cpu="armv4l"
+  armv*b|armv*l|arm)
+    cpu="arm"
   ;;
   hppa|parisc|parisc64)
     cpu="hppa"
@@ -1243,7 +1238,13 @@ else
 
 # if cross compiling, cannot launch a program, so make a static guess
 case "$cpu" in
-  armv4b|hppa|m68k|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64)
+  arm)
+    # ARM can be either way; ask the compiler which one we are
+    if check_define __ARMEB__; then
+      bigendian=yes
+    fi
+  ;;
+  hppa|m68k|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64)
     bigendian=yes
   ;;
 esac
@@ -2871,12 +2872,9 @@ echo "docdir=$docdir" >> $config_host_mak
 echo "confdir=$confdir" >> $config_host_mak
 
 case "$cpu" in
-  i386|x86_64|alpha|cris|hppa|ia64|lm32|m68k|microblaze|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64|unicore32)
+  i386|x86_64|alpha|arm|cris|hppa|ia64|lm32|m68k|microblaze|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64|unicore32)
     ARCH=$cpu
   ;;
-  armv4b|armv4l)
-    ARCH=arm
-  ;;
   *)
     if test "$tcg_interpreter" = "yes" ; then
         echo "Unsupported CPU = $cpu, will use TCG with TCI (experimental)"
commit 81584fd50deb3c324cafc854a946dbb6b83c2fc6
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Nov 29 07:21:39 2011 +0100

    pseries: Fix array overrun bug in PCI code
    
    spapr_populate_pci_devices() containd a loop with PCI_NUM_REGIONS (7)
    iterations.  However this overruns the 'bars' global array, which only has
    6 elements. In fact we only want to run this loop for things listed in the
    bars array, so this patch corrects the loop bounds to reflect that.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 7162588..9b6a032 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -454,7 +454,7 @@ int spapr_populate_pci_devices(sPAPRPHBState *phb,
         reg[0].size = 0;
 
         n = 0;
-        for (i = 0; i < PCI_NUM_REGIONS; ++i) {
+        for (i = 0; i < ARRAY_SIZE(bars); ++i) {
             if (0 == dev->io_regions[i].size) {
                 continue;
             }
commit f4fc247b0df2dfccae80618ccf6741a9b9e50e49
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Nov 25 19:25:50 2011 +0100

    target-arm/helper.c: Don't allocate TCG resources unless TCG enabled
    
    Don't call arm_translate_init() (which allocates TCG resources)
    unless TCG is enabled.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 97af4d0..3fe5822 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -390,7 +390,7 @@ CPUARMState *cpu_arm_init(const char *cpu_model)
         return NULL;
     env = g_malloc0(sizeof(CPUARMState));
     cpu_exec_init(env);
-    if (!inited) {
+    if (tcg_enabled() && !inited) {
         inited = 1;
         arm_translate_init();
     }
commit 02afbf64753fcf95f3b0b36cf4066ba194ec550d
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Nov 24 19:33:31 2011 +0100

    target-arm/translate.c: Fix slightly misleading comment in Thumb decoder
    
    Clarify some slightly misleading comments in the Thumb decoder's
    handling of the memory hint space -- in particular one code path
    marked as 'UNPREDICTABLE or unallocated hint' also includes some
    legitimate preload instructions.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 0f35b60..f91553a 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9025,14 +9025,16 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                     goto illegal_op;
                 }
                 if (rn == 15) {
-                    /* UNPREDICTABLE or unallocated hint */
+                    /* UNPREDICTABLE, unallocated hint or
+                     * PLD/PLDW/PLI (literal)
+                     */
                     return 0;
                 }
                 if (op1 & 1) {
-                    return 0; /* PLD* or unallocated hint */
+                    return 0; /* PLD/PLDW/PLI or unallocated hint */
                 }
                 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
-                    return 0; /* PLD* or unallocated hint */
+                    return 0; /* PLD/PLDW/PLI or unallocated hint */
                 }
                 /* UNDEF space, or an UNPREDICTABLE */
                 return 1;
commit 4abc7ebf5f00bb53439e2923cd47f7642491abf8
Author: Peter Chubb <peter.chubb at nicta.com.au>
Date:   Tue Nov 22 04:20:23 2011 +0100

    Fix hw_error messages from arm_timer.c
    
    Two of the calls to hw_error() in arm_timer.c contain the wrong function name.
    
    As suggested by Andreas Färber, use the C99 standard __func__ macro to
    get the correct name, instead of putting the name directly into the code.
    
    Signed-off-by: Peter Chubb <peter.chubb at nicta.com.au>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 8f442d7..518bad2 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -61,7 +61,7 @@ static uint32_t arm_timer_read(void *opaque, target_phys_addr_t offset)
             return 0;
         return s->int_level;
     default:
-        hw_error("arm_timer_read: Bad offset %x\n", (int)offset);
+        hw_error("%s: Bad offset %x\n", __func__, (int)offset);
         return 0;
     }
 }
@@ -128,7 +128,7 @@ static void arm_timer_write(void *opaque, target_phys_addr_t offset,
         arm_timer_recalibrate(s, 0);
         break;
     default:
-        hw_error("arm_timer_write: Bad offset %x\n", (int)offset);
+        hw_error("%s: Bad offset %x\n", __func__, (int)offset);
     }
     arm_timer_update(s);
 }
@@ -270,7 +270,7 @@ static uint64_t icp_pit_read(void *opaque, target_phys_addr_t offset,
     /* ??? Don't know the PrimeCell ID for this device.  */
     n = offset >> 8;
     if (n > 2) {
-        hw_error("sp804_read: Bad timer %d\n", n);
+        hw_error("%s: Bad timer %d\n", __func__, n);
     }
 
     return arm_timer_read(s->timer[n], offset & 0xff);
@@ -284,7 +284,7 @@ static void icp_pit_write(void *opaque, target_phys_addr_t offset,
 
     n = offset >> 8;
     if (n > 2) {
-        hw_error("sp804_write: Bad timer %d\n", n);
+        hw_error("%s: Bad timer %d\n", __func__, n);
     }
 
     arm_timer_write(s->timer[n], offset & 0xff, value);
commit eb5d5beaebd102599a915f6c4813d445ddc9dc84
Merge: f6480ca... 922453b...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 5 09:39:25 2011 -0600

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

commit f6480ca3f3423be5bee8b673ee6f5cc387659def
Merge: cac1e30... 8b88827...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 5 09:37:49 2011 -0600

    Merge remote-tracking branch 'aneesh/1.0-fixes' into staging

commit cac1e30af72c4cf289750193426ebd5d2b6bd1d5
Merge: 01e7a53... 07f3507...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 5 08:44:33 2011 -0600

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging

commit 01e7a53aed945adafc3ee54e2159227839daf0b4
Merge: 4eb2d2d... f44336c...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 5 08:43:38 2011 -0600

    Merge remote-tracking branch 'qemu-kvm/memory/batch' into staging

commit 4eb2d2d900eb6f63cad2b5cb6ca4273bfb9b230c
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Dec 5 08:39:02 2011 -0600

    Update version for 1.1 development branch
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/VERSION b/VERSION
index d3827e7..3e9c4a6 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0
+1.0.50
commit 922453bca6a927bb527068ae8679d587cfa45dbc
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Nov 30 12:23:43 2011 +0000

    block: convert qemu_aio_flush() calls to bdrv_drain_all()
    
    Many places in QEMU call qemu_aio_flush() to complete all pending
    asynchronous I/O.  Most of these places actually want to drain all block
    requests but there is no block layer API to do so.
    
    This patch introduces the bdrv_drain_all() API to wait for requests
    across all BlockDriverStates to complete.  As a bonus we perform checks
    after qemu_aio_wait() to ensure that requests really have finished.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block-migration.c b/block-migration.c
index 5f10486..423c5a0 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -387,7 +387,7 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
 
     for (sector = bmds->cur_dirty; sector < bmds->total_sectors;) {
         if (bmds_aio_inflight(bmds, sector)) {
-            qemu_aio_flush();
+            bdrv_drain_all();
         }
         if (bdrv_get_dirty(bmds->bs, sector)) {
 
diff --git a/block.c b/block.c
index 50ce2be..aa9d142 100644
--- a/block.c
+++ b/block.c
@@ -846,6 +846,25 @@ void bdrv_close_all(void)
     }
 }
 
+/*
+ * Wait for pending requests to complete across all BlockDriverStates
+ *
+ * This function does not flush data to disk, use bdrv_flush_all() for that
+ * after calling this function.
+ */
+void bdrv_drain_all(void)
+{
+    BlockDriverState *bs;
+
+    qemu_aio_flush();
+
+    /* If requests are still pending there is a bug somewhere */
+    QTAILQ_FOREACH(bs, &bdrv_states, list) {
+        assert(QLIST_EMPTY(&bs->tracked_requests));
+        assert(qemu_co_queue_empty(&bs->throttled_reqs));
+    }
+}
+
 /* make a BlockDriverState anonymous by removing from bdrv_state list.
    Also, NULL terminate the device_name to prevent double remove */
 void bdrv_make_anon(BlockDriverState *bs)
diff --git a/block.h b/block.h
index 5f8a98a..1790f99 100644
--- a/block.h
+++ b/block.h
@@ -214,6 +214,7 @@ int bdrv_flush(BlockDriverState *bs);
 int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
 void bdrv_flush_all(void);
 void bdrv_close_all(void);
+void bdrv_drain_all(void);
 
 int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors);
 int bdrv_co_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors);
diff --git a/blockdev.c b/blockdev.c
index af4e239..dbf0251 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -653,7 +653,7 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
         goto out;
     }
 
-    qemu_aio_flush();
+    bdrv_drain_all();
     bdrv_flush(bs);
 
     bdrv_close(bs);
@@ -840,7 +840,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
     }
 
     /* quiesce block driver; prevent further io */
-    qemu_aio_flush();
+    bdrv_drain_all();
     bdrv_flush(bs);
     bdrv_close(bs);
 
diff --git a/cpus.c b/cpus.c
index 82530c4..58e173c 100644
--- a/cpus.c
+++ b/cpus.c
@@ -396,7 +396,7 @@ static void do_vm_stop(RunState state)
         pause_all_vcpus();
         runstate_set(state);
         vm_state_notify(0, state);
-        qemu_aio_flush();
+        bdrv_drain_all();
         bdrv_flush_all();
         monitor_protocol_event(QEVENT_STOP, NULL);
     }
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 70b3342..c09d2e0 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -200,8 +200,9 @@ static void pmac_ide_flush(DBDMA_io *io)
 {
     MACIOIDEState *m = io->opaque;
 
-    if (m->aiocb)
-        qemu_aio_flush();
+    if (m->aiocb) {
+        bdrv_drain_all();
+    }
 }
 
 /* PowerMac IDE memory IO */
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 49b823d..5078c0b 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -309,7 +309,7 @@ void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val)
              * aio operation with preadv/pwritev.
              */
             if (bm->bus->dma->aiocb) {
-                qemu_aio_flush();
+                bdrv_drain_all();
                 assert(bm->bus->dma->aiocb == NULL);
                 assert((bm->status & BM_STATUS_DMAING) == 0);
             }
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index d6d1f87..4b0d113 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -474,7 +474,7 @@ static void virtio_blk_reset(VirtIODevice *vdev)
      * This should cancel pending requests, but can't do nicely until there
      * are per-device request lists.
      */
-    qemu_aio_flush();
+    bdrv_drain_all();
 }
 
 /* coalesce internal state, copy to pci i/o region 0
diff --git a/hw/xen_platform.c b/hw/xen_platform.c
index 5e792f5..e62eaef 100644
--- a/hw/xen_platform.c
+++ b/hw/xen_platform.c
@@ -120,7 +120,7 @@ static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t v
            devices, and bit 2 the non-primary-master IDE devices. */
         if (val & UNPLUG_ALL_IDE_DISKS) {
             DPRINTF("unplug disks\n");
-            qemu_aio_flush();
+            bdrv_drain_all();
             bdrv_flush_all();
             pci_unplug_disks(s->pci_dev.bus);
         }
diff --git a/qemu-io.c b/qemu-io.c
index de26422..b35adbb 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1853,9 +1853,9 @@ int main(int argc, char **argv)
     command_loop();
 
     /*
-     * Make sure all outstanding requests get flushed the program exits.
+     * Make sure all outstanding requests complete before the program exits.
      */
-    qemu_aio_flush();
+    bdrv_drain_all();
 
     if (bs) {
         bdrv_delete(bs);
diff --git a/savevm.c b/savevm.c
index f53cd4c..0443554 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2104,7 +2104,7 @@ int load_vmstate(const char *name)
     }
 
     /* Flush all IO requests so they don't interfere with the new state.  */
-    qemu_aio_flush();
+    bdrv_drain_all();
 
     bs = NULL;
     while ((bs = bdrv_next(bs))) {
diff --git a/xen-mapcache.c b/xen-mapcache.c
index 7bcb86e..9fecc64 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -351,7 +351,7 @@ void xen_invalidate_map_cache(void)
     MapCacheRev *reventry;
 
     /* Flush pending AIO before destroying the mapcache */
-    qemu_aio_flush();
+    bdrv_drain_all();
 
     QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
         DPRINTF("There should be no locked mappings at this time, "
commit 5f8b6491f20732e0a31e64bbf75b62def579e044
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Nov 30 12:23:42 2011 +0000

    block: wait_for_overlapping_requests() deadlock detection
    
    Debugging a reentrant request deadlock was fun but in the future we need
    a quick and obvious way of detecting such bugs.  Add an assert that
    checks we are not about to deadlock when waiting for another request.
    
    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 ecc5b44..50ce2be 100644
--- a/block.c
+++ b/block.c
@@ -1099,6 +1099,7 @@ struct BdrvTrackedRequest {
     int nb_sectors;
     bool is_write;
     QLIST_ENTRY(BdrvTrackedRequest) list;
+    Coroutine *co; /* owner, used for deadlock detection */
     CoQueue wait_queue; /* coroutines blocked on this request */
 };
 
@@ -1126,6 +1127,7 @@ static void tracked_request_begin(BdrvTrackedRequest *req,
         .sector_num = sector_num,
         .nb_sectors = nb_sectors,
         .is_write = is_write,
+        .co = qemu_coroutine_self(),
     };
 
     qemu_co_queue_init(&req->wait_queue);
@@ -1189,6 +1191,12 @@ static void coroutine_fn wait_for_overlapping_requests(BlockDriverState *bs,
         QLIST_FOREACH(req, &bs->tracked_requests, list) {
             if (tracked_request_overlaps(req, cluster_sector_num,
                                          cluster_nb_sectors)) {
+                /* Hitting this means there was a reentrant request, for
+                 * example, a block driver issuing nested requests.  This must
+                 * never happen since it means deadlock.
+                 */
+                assert(qemu_coroutine_self() != req->co);
+
                 qemu_co_queue_wait(&req->wait_queue);
                 retry = true;
                 break;
commit bd9533e36ea3d6c964f65b8e407bad00dab59e5d
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Tue Nov 29 13:49:51 2011 +0000

    block: implement bdrv_co_is_allocated() boundary cases
    
    Cases beyond the end of the disk image are only implemented for block
    drivers that do not provide .bdrv_co_is_allocated().  It's worth making
    these cases generic so that block drivers that do implement
    .bdrv_co_is_allocated() also get them for free.
    
    Suggested-by: Mark Wu <wudxw at linux.vnet.ibm.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 dd5d5ca..ecc5b44 100644
--- a/block.c
+++ b/block.c
@@ -2117,23 +2117,33 @@ typedef struct BdrvCoIsAllocatedData {
  * not implementing the functionality are assumed to not support backing files,
  * hence all their sectors are reported as allocated.
  *
+ * If 'sector_num' is beyond the end of the disk image the return value is 0
+ * and 'pnum' is set to 0.
+ *
  * 'pnum' is set to the number of sectors (including and immediately following
  * the specified sector) that are known to be in the same
  * allocated/unallocated state.
  *
- * 'nb_sectors' is the max value 'pnum' should be set to.
+ * 'nb_sectors' is the max value 'pnum' should be set to.  If nb_sectors goes
+ * beyond the end of the disk image it will be clamped.
  */
 int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t sector_num,
                                       int nb_sectors, int *pnum)
 {
+    int64_t n;
+
+    if (sector_num >= bs->total_sectors) {
+        *pnum = 0;
+        return 0;
+    }
+
+    n = bs->total_sectors - sector_num;
+    if (n < nb_sectors) {
+        nb_sectors = n;
+    }
+
     if (!bs->drv->bdrv_co_is_allocated) {
-        int64_t n;
-        if (sector_num >= bs->total_sectors) {
-            *pnum = 0;
-            return 0;
-        }
-        n = bs->total_sectors - sector_num;
-        *pnum = (n < nb_sectors) ? (n) : (nb_sectors);
+        *pnum = nb_sectors;
         return 1;
     }
 
commit c57c465800a9d193f9b41c97dbbbb6cd4fb08ff6
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Nov 24 06:15:28 2011 -0500

    dma-helpers: Add trace events
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/dma-helpers.c b/dma-helpers.c
index bdcd38c..9d6b6fa 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -9,6 +9,7 @@
 
 #include "dma.h"
 #include "block_int.h"
+#include "trace.h"
 
 void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint)
 {
@@ -83,6 +84,8 @@ static void dma_bdrv_unmap(DMAAIOCB *dbs)
 
 static void dma_complete(DMAAIOCB *dbs, int ret)
 {
+    trace_dma_complete(dbs, ret, dbs->common.cb);
+
     dma_bdrv_unmap(dbs);
     if (dbs->common.cb) {
         dbs->common.cb(dbs->common.opaque, ret);
@@ -106,6 +109,8 @@ static void dma_bdrv_cb(void *opaque, int ret)
     target_phys_addr_t cur_addr, cur_len;
     void *mem;
 
+    trace_dma_bdrv_cb(dbs, ret);
+
     dbs->acb = NULL;
     dbs->sector_num += dbs->iov.size / 512;
     dma_bdrv_unmap(dbs);
@@ -130,6 +135,7 @@ static void dma_bdrv_cb(void *opaque, int ret)
     }
 
     if (dbs->iov.size == 0) {
+        trace_dma_map_wait(dbs);
         cpu_register_map_client(dbs, continue_after_map_failure);
         return;
     }
@@ -145,6 +151,8 @@ static void dma_aio_cancel(BlockDriverAIOCB *acb)
 {
     DMAAIOCB *dbs = container_of(acb, DMAAIOCB, common);
 
+    trace_dma_aio_cancel(dbs);
+
     if (dbs->acb) {
         BlockDriverAIOCB *acb = dbs->acb;
         dbs->acb = NULL;
@@ -168,6 +176,8 @@ BlockDriverAIOCB *dma_bdrv_io(
 {
     DMAAIOCB *dbs = qemu_aio_get(&dma_aio_pool, bs, cb, opaque);
 
+    trace_dma_bdrv_io(dbs, bs, sector_num, to_dev);
+
     dbs->acb = NULL;
     dbs->bs = bs;
     dbs->sg = sg;
diff --git a/trace-events b/trace-events
index 518b76b..bf1cf57 100644
--- a/trace-events
+++ b/trace-events
@@ -632,3 +632,10 @@ win_helper_no_switch_pstate(uint32_t new_pstate_regs) "change_pstate: regs new=%
 win_helper_wrpil(uint32_t psrpil, uint32_t new_pil) "old=%x new=%x"
 win_helper_done(uint32_t tl) "tl=%d"
 win_helper_retry(uint32_t tl) "tl=%d"
+
+# dma-helpers.c
+dma_bdrv_io(void *dbs, void *bs, int64_t sector_num, bool to_dev) "dbs=%p bs=%p sector_num=%" PRId64 " to_dev=%d"
+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"
commit e94d13873334b1880746feca59ce84c0eabc1021
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Nov 23 15:00:04 2011 +0000

    cow: use bdrv_co_is_allocated()
    
    Now that bdrv_co_is_allocated() is available we can use it instead of
    the synchronous bdrv_is_allocated() interface.  This is a follow-up that
    Kevin Wolf <kwolf at redhat.com> pointed out after applying the series that
    introduces bdrv_co_is_allocated().
    
    It is safe to make cow_read() a coroutine_fn because its only caller is
    a coroutine_fn.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/cow.c b/block/cow.c
index 7ae887b..586493c 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -171,14 +171,14 @@ static int cow_update_bitmap(BlockDriverState *bs, int64_t sector_num,
     return error;
 }
 
-static int cow_read(BlockDriverState *bs, int64_t sector_num,
-                    uint8_t *buf, int nb_sectors)
+static int coroutine_fn cow_read(BlockDriverState *bs, int64_t sector_num,
+                                 uint8_t *buf, int nb_sectors)
 {
     BDRVCowState *s = bs->opaque;
     int ret, n;
 
     while (nb_sectors > 0) {
-        if (bdrv_is_allocated(bs, sector_num, nb_sectors, &n)) {
+        if (bdrv_co_is_allocated(bs, sector_num, nb_sectors, &n)) {
             ret = bdrv_pread(bs->file,
                         s->cow_sectors_offset + sector_num * 512,
                         buf, n * 512);
commit fb0490f69feb96b7e92457f176dc834ff0b00b09
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Thu Nov 17 13:40:32 2011 +0000

    block: add -drive copy-on-read=on|off
    
    This patch adds the -drive copy-on-read=on|off command-line option:
    
      copy-on-read=on|off
      copy-on-read is "on" or "off" and enables whether to copy read backing
      file sectors into the image file.  Copy-on-read avoids accessing the
      same backing file sectors repeatedly and is useful when the backing
      file is over a slow network.  By default copy-on-read is off.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 9068c5b..af4e239 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -257,6 +257,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
     DriveInfo *dinfo;
     BlockIOLimit io_limits;
     int snapshot = 0;
+    bool copy_on_read;
     int ret;
 
     translation = BIOS_ATA_TRANSLATION_AUTO;
@@ -273,6 +274,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
 
     snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
     ro = qemu_opt_get_bool(opts, "readonly", 0);
+    copy_on_read = qemu_opt_get_bool(opts, "copy-on-read", false);
 
     file = qemu_opt_get(opts, "file");
     serial = qemu_opt_get(opts, "serial");
@@ -546,6 +548,10 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
         bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
     }
 
+    if (copy_on_read) {
+        bdrv_flags |= BDRV_O_COPY_ON_READ;
+    }
+
     if (media == MEDIA_CDROM) {
         /* CDROM is fine for any interface, don't check.  */
         ro = 1;
diff --git a/hmp-commands.hx b/hmp-commands.hx
index f8d855e..79a9195 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -860,9 +860,10 @@ ETEXI
         .args_type  = "pci_addr:s,opts:s",
         .params     = "[[<domain>:]<bus>:]<slot>\n"
                       "[file=file][,if=type][,bus=n]\n"
-                      "[,unit=m][,media=d][index=i]\n"
+                      "[,unit=m][,media=d][,index=i]\n"
                       "[,cyls=c,heads=h,secs=s[,trans=t]]\n"
-                      "[snapshot=on|off][,cache=on|off]",
+                      "[,snapshot=on|off][,cache=on|off]\n"
+                      "[,readonly=on|off][,copy-on-read=on|off]",
         .help       = "add drive to PCI storage controller",
         .mhandler.cmd = drive_hot_add,
     },
diff --git a/qemu-config.c b/qemu-config.c
index 1aa080f..18f3020 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -109,6 +109,10 @@ static QemuOptsList qemu_drive_opts = {
             .name = "bps_wr",
             .type = QEMU_OPT_NUMBER,
             .help = "limit write bytes per second",
+        },{
+            .name = "copy-on-read",
+            .type = QEMU_OPT_BOOL,
+            .help = "copy read data from backing file into image file",
         },
         { /* end of list */ }
     },
diff --git a/qemu-options.hx b/qemu-options.hx
index 25a7be7..b3db10c 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -135,7 +135,7 @@ DEF("drive", HAS_ARG, QEMU_OPTION_drive,
     "       [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n"
     "       [,cache=writethrough|writeback|none|directsync|unsafe][,format=f]\n"
     "       [,serial=s][,addr=A][,id=name][,aio=threads|native]\n"
-    "       [,readonly=on|off]\n"
+    "       [,readonly=on|off][,copy-on-read=on|off]\n"
     "       [[,bps=b]|[[,bps_rd=r][,bps_wr=w]]][[,iops=i]|[[,iops_rd=r][,iops_wr=w]]\n"
     "                use 'file' as a drive image\n", QEMU_ARCH_ALL)
 STEXI
@@ -187,6 +187,9 @@ host disk is full; report the error to the guest otherwise).
 The default setting is @option{werror=enospc} and @option{rerror=report}.
 @item readonly
 Open drive @option{file} as read-only. Guest write attempts will fail.
+ at item copy-on-read=@var{copy-on-read}
+ at var{copy-on-read} is "on" or "off" and enables whether to copy read backing
+file sectors into the image file.
 @end table
 
 By default, writethrough caching is used for all block device.  This means that
@@ -218,6 +221,10 @@ like your host losing power, the disk storage getting disconnected accidently,
 etc. you're image will most probably be rendered unusable.   When using
 the @option{-snapshot} option, unsafe caching is always used.
 
+Copy-on-read avoids accessing the same backing file sectors repeatedly and is
+useful when the backing file is over a slow network.  By default copy-on-read
+is off.
+
 Instead of @option{-cdrom} you can use:
 @example
 qemu -drive file=file,index=2,media=cdrom
commit ab1859218a95977dc6881fcccce328d8146a6bdb
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Thu Nov 17 13:40:31 2011 +0000

    block: core copy-on-read logic
    
    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 ca0e8ec..dd5d5ca 100644
--- a/block.c
+++ b/block.c
@@ -1469,6 +1469,61 @@ int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset,
     return 0;
 }
 
+static int coroutine_fn bdrv_co_copy_on_readv(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
+{
+    /* Perform I/O through a temporary buffer so that users who scribble over
+     * their read buffer while the operation is in progress do not end up
+     * modifying the image file.  This is critical for zero-copy guest I/O
+     * where anything might happen inside guest memory.
+     */
+    void *bounce_buffer;
+
+    struct iovec iov;
+    QEMUIOVector bounce_qiov;
+    int64_t cluster_sector_num;
+    int cluster_nb_sectors;
+    size_t skip_bytes;
+    int ret;
+
+    /* Cover entire cluster so no additional backing file I/O is required when
+     * allocating cluster in the image file.
+     */
+    round_to_clusters(bs, sector_num, nb_sectors,
+                      &cluster_sector_num, &cluster_nb_sectors);
+
+    trace_bdrv_co_copy_on_readv(bs, sector_num, nb_sectors,
+                                cluster_sector_num, cluster_nb_sectors);
+
+    iov.iov_len = cluster_nb_sectors * BDRV_SECTOR_SIZE;
+    iov.iov_base = bounce_buffer = qemu_blockalign(bs, iov.iov_len);
+    qemu_iovec_init_external(&bounce_qiov, &iov, 1);
+
+    ret = bs->drv->bdrv_co_readv(bs, cluster_sector_num, cluster_nb_sectors,
+                                 &bounce_qiov);
+    if (ret < 0) {
+        goto err;
+    }
+
+    ret = bs->drv->bdrv_co_writev(bs, cluster_sector_num, cluster_nb_sectors,
+                                  &bounce_qiov);
+    if (ret < 0) {
+        /* It might be okay to ignore write errors for guest requests.  If this
+         * is a deliberate copy-on-read then we don't want to ignore the error.
+         * Simply report it in all cases.
+         */
+        goto err;
+    }
+
+    skip_bytes = (sector_num - cluster_sector_num) * BDRV_SECTOR_SIZE;
+    qemu_iovec_from_buffer(qiov, bounce_buffer + skip_bytes,
+                           nb_sectors * BDRV_SECTOR_SIZE);
+
+err:
+    qemu_vfree(bounce_buffer);
+    return ret;
+}
+
 /*
  * Handle a read request in coroutine context
  */
@@ -1496,7 +1551,24 @@ static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs,
     }
 
     tracked_request_begin(&req, bs, sector_num, nb_sectors, false);
+
+    if (bs->copy_on_read) {
+        int pnum;
+
+        ret = bdrv_co_is_allocated(bs, sector_num, nb_sectors, &pnum);
+        if (ret < 0) {
+            goto out;
+        }
+
+        if (!ret || pnum != nb_sectors) {
+            ret = bdrv_co_copy_on_readv(bs, sector_num, nb_sectors, qiov);
+            goto out;
+        }
+    }
+
     ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
+
+out:
     tracked_request_end(&req);
     return ret;
 }
diff --git a/trace-events b/trace-events
index 962caca..518b76b 100644
--- a/trace-events
+++ b/trace-events
@@ -69,6 +69,7 @@ bdrv_lock_medium(void *bs, bool locked) "bs %p locked %d"
 bdrv_co_readv(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d"
 bdrv_co_writev(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d"
 bdrv_co_io_em(void *bs, int64_t sector_num, int nb_sectors, int is_write, void *acb) "bs %p sector_num %"PRId64" nb_sectors %d is_write %d acb %p"
+bdrv_co_copy_on_readv(void *bs, int64_t sector_num, int nb_sectors, int64_t cluster_sector_num, int cluster_nb_sectors) "bs %p sector_num %"PRId64" nb_sectors %d cluster_sector_num %"PRId64" cluster_nb_sectors %d"
 
 # hw/virtio-blk.c
 virtio_blk_req_complete(void *req, int status) "req %p status %d"
commit d83947ac6d2a58fdaf128fbe1b22bc9639e79fe5
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Nov 23 11:47:56 2011 +0000

    block: request overlap detection
    
    Detect overlapping requests and remember to align to cluster boundaries
    if the image format uses them.  This assumes that allocating I/O is
    performed in cluster granularity - which is true for qcow2, qed, etc.
    
    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 1b3c809..ca0e8ec 100644
--- a/block.c
+++ b/block.c
@@ -1133,21 +1133,62 @@ static void tracked_request_begin(BdrvTrackedRequest *req,
     QLIST_INSERT_HEAD(&bs->tracked_requests, req, list);
 }
 
+/**
+ * Round a region to cluster boundaries
+ */
+static void round_to_clusters(BlockDriverState *bs,
+                              int64_t sector_num, int nb_sectors,
+                              int64_t *cluster_sector_num,
+                              int *cluster_nb_sectors)
+{
+    BlockDriverInfo bdi;
+
+    if (bdrv_get_info(bs, &bdi) < 0 || bdi.cluster_size == 0) {
+        *cluster_sector_num = sector_num;
+        *cluster_nb_sectors = nb_sectors;
+    } else {
+        int64_t c = bdi.cluster_size / BDRV_SECTOR_SIZE;
+        *cluster_sector_num = QEMU_ALIGN_DOWN(sector_num, c);
+        *cluster_nb_sectors = QEMU_ALIGN_UP(sector_num - *cluster_sector_num +
+                                            nb_sectors, c);
+    }
+}
+
 static bool tracked_request_overlaps(BdrvTrackedRequest *req,
                                      int64_t sector_num, int nb_sectors) {
-    return false; /* not yet implemented */
+    /*        aaaa   bbbb */
+    if (sector_num >= req->sector_num + req->nb_sectors) {
+        return false;
+    }
+    /* bbbb   aaaa        */
+    if (req->sector_num >= sector_num + nb_sectors) {
+        return false;
+    }
+    return true;
 }
 
 static void coroutine_fn wait_for_overlapping_requests(BlockDriverState *bs,
         int64_t sector_num, int nb_sectors)
 {
     BdrvTrackedRequest *req;
+    int64_t cluster_sector_num;
+    int cluster_nb_sectors;
     bool retry;
 
+    /* If we touch the same cluster it counts as an overlap.  This guarantees
+     * that allocating writes will be serialized and not race with each other
+     * for the same cluster.  For example, in copy-on-read it ensures that the
+     * CoR read and write operations are atomic and guest writes cannot
+     * interleave between them.
+     */
+    round_to_clusters(bs, sector_num, nb_sectors,
+                      &cluster_sector_num, &cluster_nb_sectors);
+
     do {
         retry = false;
         QLIST_FOREACH(req, &bs->tracked_requests, list) {
-            if (tracked_request_overlaps(req, sector_num, nb_sectors)) {
+            if (tracked_request_overlaps(req, cluster_sector_num,
+                                         cluster_nb_sectors)) {
                 qemu_co_queue_wait(&req->wait_queue);
                 retry = true;
                 break;
commit f4658285f99473367dbbc34ce6970ec4637c2388
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Thu Nov 17 13:40:29 2011 +0000

    block: wait for overlapping requests
    
    When copy-on-read is enabled it is necessary to wait for overlapping
    requests before issuing new requests.  This prevents races between the
    copy-on-read and a write request.
    
    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 9b3cb75..1b3c809 100644
--- a/block.c
+++ b/block.c
@@ -1099,6 +1099,7 @@ struct BdrvTrackedRequest {
     int nb_sectors;
     bool is_write;
     QLIST_ENTRY(BdrvTrackedRequest) list;
+    CoQueue wait_queue; /* coroutines blocked on this request */
 };
 
 /**
@@ -1109,6 +1110,7 @@ struct BdrvTrackedRequest {
 static void tracked_request_end(BdrvTrackedRequest *req)
 {
     QLIST_REMOVE(req, list);
+    qemu_co_queue_restart_all(&req->wait_queue);
 }
 
 /**
@@ -1126,9 +1128,34 @@ static void tracked_request_begin(BdrvTrackedRequest *req,
         .is_write = is_write,
     };
 
+    qemu_co_queue_init(&req->wait_queue);
+
     QLIST_INSERT_HEAD(&bs->tracked_requests, req, list);
 }
 
+static bool tracked_request_overlaps(BdrvTrackedRequest *req,
+                                     int64_t sector_num, int nb_sectors) {
+    return false; /* not yet implemented */
+}
+
+static void coroutine_fn wait_for_overlapping_requests(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors)
+{
+    BdrvTrackedRequest *req;
+    bool retry;
+
+    do {
+        retry = false;
+        QLIST_FOREACH(req, &bs->tracked_requests, list) {
+            if (tracked_request_overlaps(req, sector_num, nb_sectors)) {
+                qemu_co_queue_wait(&req->wait_queue);
+                retry = true;
+                break;
+            }
+        }
+    } while (retry);
+}
+
 /*
  * Return values:
  * 0        - success
@@ -1423,6 +1450,10 @@ static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs,
         bdrv_io_limits_intercept(bs, false, nb_sectors);
     }
 
+    if (bs->copy_on_read) {
+        wait_for_overlapping_requests(bs, sector_num, nb_sectors);
+    }
+
     tracked_request_begin(&req, bs, sector_num, nb_sectors, false);
     ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
     tracked_request_end(&req);
@@ -1462,6 +1493,10 @@ static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs,
         bdrv_io_limits_intercept(bs, true, nb_sectors);
     }
 
+    if (bs->copy_on_read) {
+        wait_for_overlapping_requests(bs, sector_num, nb_sectors);
+    }
+
     tracked_request_begin(&req, bs, sector_num, nb_sectors, true);
 
     ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov);
commit 53fec9d3fd3d3a4ded4b92dfa843436bf71380f1
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Nov 28 16:08:47 2011 +0000

    block: add interface to toggle copy-on-read
    
    The bdrv_enable_copy_on_read()/bdrv_disable_copy_on_read() functions can
    be used to programmatically enable or disable copy-on-read for a block
    device.  Later patches add the actual copy-on-read logic.
    
    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 1643667..9b3cb75 100644
--- a/block.c
+++ b/block.c
@@ -538,6 +538,22 @@ int bdrv_parse_cache_flags(const char *mode, int *flags)
     return 0;
 }
 
+/**
+ * The copy-on-read flag is actually a reference count so multiple users may
+ * use the feature without worrying about clobbering its previous state.
+ * Copy-on-read stays enabled until all users have called to disable it.
+ */
+void bdrv_enable_copy_on_read(BlockDriverState *bs)
+{
+    bs->copy_on_read++;
+}
+
+void bdrv_disable_copy_on_read(BlockDriverState *bs)
+{
+    assert(bs->copy_on_read > 0);
+    bs->copy_on_read--;
+}
+
 /*
  * Common part for opening disk images and files
  */
@@ -559,6 +575,11 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
     bs->growable = 0;
     bs->buffer_alignment = 512;
 
+    assert(bs->copy_on_read == 0); /* bdrv_new() and bdrv_close() make it so */
+    if ((flags & BDRV_O_RDWR) && (flags & BDRV_O_COPY_ON_READ)) {
+        bdrv_enable_copy_on_read(bs);
+    }
+
     pstrcpy(bs->filename, sizeof(bs->filename), filename);
     bs->backing_file[0] = '\0';
 
@@ -801,6 +822,7 @@ void bdrv_close(BlockDriverState *bs)
 #endif
         bs->opaque = NULL;
         bs->drv = NULL;
+        bs->copy_on_read = 0;
 
         if (bs->file != NULL) {
             bdrv_close(bs->file);
diff --git a/block.h b/block.h
index 8482dbc..5f8a98a 100644
--- a/block.h
+++ b/block.h
@@ -70,6 +70,7 @@ typedef struct BlockDevOps {
 #define BDRV_O_NATIVE_AIO  0x0080 /* use native AIO instead of the thread pool */
 #define BDRV_O_NO_BACKING  0x0100 /* don't open the backing file */
 #define BDRV_O_NO_FLUSH    0x0200 /* disable flushing on this disk */
+#define BDRV_O_COPY_ON_READ 0x0400 /* copy read backing sectors into image */
 
 #define BDRV_O_CACHE_MASK  (BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH)
 
@@ -312,6 +313,9 @@ void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector,
                       int nr_sectors);
 int64_t bdrv_get_dirty_count(BlockDriverState *bs);
 
+void bdrv_enable_copy_on_read(BlockDriverState *bs);
+void bdrv_disable_copy_on_read(BlockDriverState *bs);
+
 void bdrv_set_in_use(BlockDriverState *bs, int in_use);
 int bdrv_in_use(BlockDriverState *bs);
 
diff --git a/block_int.h b/block_int.h
index ea818e4..311bd2a 100644
--- a/block_int.h
+++ b/block_int.h
@@ -198,6 +198,8 @@ struct BlockDriverState {
     int encrypted; /* if true, the media is encrypted */
     int valid_key; /* if true, a valid encryption key has been set */
     int sg;        /* if true, the device is a /dev/sg* */
+    int copy_on_read; /* if true, copy read backing sectors into image
+                         note this is a reference count */
 
     BlockDriver *drv; /* NULL means no media */
     void *opaque;
commit dbffbdcfff69431b622866ac5ea78df74fdc02d4
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Thu Nov 17 13:40:27 2011 +0000

    block: add request tracking
    
    The block layer does not know about pending requests.  This information
    is necessary for copy-on-read since overlapping requests must be
    serialized to prevent races that corrupt the image.
    
    The BlockDriverState gets a new tracked_request list field which
    contains all pending requests.  Each request is a BdrvTrackedRequest
    record with sector_num, nb_sectors, and is_write fields.
    
    Note that request tracking is always enabled but hopefully this extra
    work is so small that it doesn't justify adding an enable/disable flag.
    
    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 d82854a..1643667 100644
--- a/block.c
+++ b/block.c
@@ -1071,6 +1071,42 @@ void bdrv_commit_all(void)
     }
 }
 
+struct BdrvTrackedRequest {
+    BlockDriverState *bs;
+    int64_t sector_num;
+    int nb_sectors;
+    bool is_write;
+    QLIST_ENTRY(BdrvTrackedRequest) list;
+};
+
+/**
+ * Remove an active request from the tracked requests list
+ *
+ * This function should be called when a tracked request is completing.
+ */
+static void tracked_request_end(BdrvTrackedRequest *req)
+{
+    QLIST_REMOVE(req, list);
+}
+
+/**
+ * Add an active request to the tracked requests list
+ */
+static void tracked_request_begin(BdrvTrackedRequest *req,
+                                  BlockDriverState *bs,
+                                  int64_t sector_num,
+                                  int nb_sectors, bool is_write)
+{
+    *req = (BdrvTrackedRequest){
+        .bs = bs,
+        .sector_num = sector_num,
+        .nb_sectors = nb_sectors,
+        .is_write = is_write,
+    };
+
+    QLIST_INSERT_HEAD(&bs->tracked_requests, req, list);
+}
+
 /*
  * Return values:
  * 0        - success
@@ -1350,6 +1386,8 @@ static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs,
     int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
 {
     BlockDriver *drv = bs->drv;
+    BdrvTrackedRequest req;
+    int ret;
 
     if (!drv) {
         return -ENOMEDIUM;
@@ -1363,7 +1401,10 @@ static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs,
         bdrv_io_limits_intercept(bs, false, nb_sectors);
     }
 
-    return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
+    tracked_request_begin(&req, bs, sector_num, nb_sectors, false);
+    ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
+    tracked_request_end(&req);
+    return ret;
 }
 
 int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num,
@@ -1381,6 +1422,7 @@ static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs,
     int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
 {
     BlockDriver *drv = bs->drv;
+    BdrvTrackedRequest req;
     int ret;
 
     if (!bs->drv) {
@@ -1398,6 +1440,8 @@ static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs,
         bdrv_io_limits_intercept(bs, true, nb_sectors);
     }
 
+    tracked_request_begin(&req, bs, sector_num, nb_sectors, true);
+
     ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov);
 
     if (bs->dirty_bitmap) {
@@ -1408,6 +1452,8 @@ static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs,
         bs->wr_highest_sector = sector_num + nb_sectors - 1;
     }
 
+    tracked_request_end(&req);
+
     return ret;
 }
 
diff --git a/block_int.h b/block_int.h
index a0b46d7..ea818e4 100644
--- a/block_int.h
+++ b/block_int.h
@@ -51,6 +51,8 @@
 #define BLOCK_OPT_PREALLOC      "preallocation"
 #define BLOCK_OPT_SUBFMT        "subformat"
 
+typedef struct BdrvTrackedRequest BdrvTrackedRequest;
+
 typedef struct AIOPool {
     void (*cancel)(BlockDriverAIOCB *acb);
     int aiocb_size;
@@ -255,6 +257,8 @@ struct BlockDriverState {
     int in_use; /* users other than guest access, eg. block migration */
     QTAILQ_ENTRY(BlockDriverState) list;
     void *private;
+
+    QLIST_HEAD(, BdrvTrackedRequest) tracked_requests;
 };
 
 struct BlockDriverAIOCB {
commit e8ee5e4c476d5b0654d8f1271a2b7c065acc486e
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Thu Nov 17 13:40:26 2011 +0000

    coroutine: add qemu_co_queue_restart_all()
    
    It's common to wake up all waiting coroutines.  Introduce the
    qemu_co_queue_restart_all() function to do this instead of looping over
    qemu_co_queue_next() in every caller.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 5ac9fb4..a2be7d7 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -516,7 +516,7 @@ static void run_dependent_requests(BDRVQcowState *s, QCowL2Meta *m)
     /* Restart all dependent requests */
     if (!qemu_co_queue_empty(&m->dependent_requests)) {
         qemu_co_mutex_unlock(&s->lock);
-        while(qemu_co_queue_next(&m->dependent_requests));
+        qemu_co_queue_restart_all(&m->dependent_requests);
         qemu_co_mutex_lock(&s->lock);
     }
 }
diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c
index 9549c07..26ad76b 100644
--- a/qemu-coroutine-lock.c
+++ b/qemu-coroutine-lock.c
@@ -84,6 +84,13 @@ bool qemu_co_queue_next(CoQueue *queue)
     return (next != NULL);
 }
 
+void qemu_co_queue_restart_all(CoQueue *queue)
+{
+    while (qemu_co_queue_next(queue)) {
+        /* Do nothing */
+    }
+}
+
 bool qemu_co_queue_empty(CoQueue *queue)
 {
     return (QTAILQ_FIRST(&queue->entries) == NULL);
@@ -144,13 +151,7 @@ void qemu_co_rwlock_unlock(CoRwlock *lock)
     assert(qemu_in_coroutine());
     if (lock->writer) {
         lock->writer = false;
-        while (!qemu_co_queue_empty(&lock->queue)) {
-            /*
-             * Wakeup every body. This will include some
-             * writers too.
-             */
-            qemu_co_queue_next(&lock->queue);
-        }
+        qemu_co_queue_restart_all(&lock->queue);
     } else {
         lock->reader--;
         assert(lock->reader >= 0);
diff --git a/qemu-coroutine.h b/qemu-coroutine.h
index 8a2e5d2..8a55fe1 100644
--- a/qemu-coroutine.h
+++ b/qemu-coroutine.h
@@ -131,6 +131,11 @@ void coroutine_fn qemu_co_queue_wait_insert_head(CoQueue *queue);
 bool qemu_co_queue_next(CoQueue *queue);
 
 /**
+ * Restarts all coroutines in the CoQueue and leaves the queue empty.
+ */
+void qemu_co_queue_restart_all(CoQueue *queue);
+
+/**
  * Checks if the CoQueue is empty.
  */
 bool qemu_co_queue_empty(CoQueue *queue);
commit 3951690a4a29e031492090131d001e5047938631
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Thu Nov 17 13:40:25 2011 +0000

    qemu-common: add QEMU_ALIGN_DOWN() and QEMU_ALIGN_UP() macros
    
    Add macros for aligning a number to a multiple, for example:
    
    QEMU_ALIGN_DOWN(500, 2000) = 0
    QEMU_ALIGN_UP(500, 2000) = 2000
    
    Since ALIGN_UP() is a common macro name use the QEMU_* namespace prefix.
    Hopefully this will protect us from included headers that leak something
    with a similar name.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-common.h b/qemu-common.h
index 2ce47aa..44870fe 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -341,6 +341,12 @@ static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
     return res.ll;
 }
 
+/* Round number down to multiple */
+#define QEMU_ALIGN_DOWN(n, m) ((n) / (m) * (m))
+
+/* Round number up to multiple */
+#define QEMU_ALIGN_UP(n, m) QEMU_ALIGN_DOWN((n) + (m) - 1, (m))
+
 #include "module.h"
 
 #endif
commit 060f51c9dee3c58e2748c773ef1f7142047a4a2f
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Nov 14 12:44:26 2011 +0000

    block: add bdrv_co_is_allocated() interface
    
    This patch introduces the public bdrv_co_is_allocated() interface which
    can be used to query image allocation status while the VM is running.
    
    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 50b058d..d82854a 100644
--- a/block.c
+++ b/block.c
@@ -1896,17 +1896,6 @@ typedef struct BdrvCoIsAllocatedData {
     bool done;
 } BdrvCoIsAllocatedData;
 
-/* Coroutine wrapper for bdrv_is_allocated() */
-static void coroutine_fn bdrv_is_allocated_co_entry(void *opaque)
-{
-    BdrvCoIsAllocatedData *data = opaque;
-    BlockDriverState *bs = data->bs;
-
-    data->ret = bs->drv->bdrv_co_is_allocated(bs, data->sector_num,
-                                              data->nb_sectors, data->pnum);
-    data->done = true;
-}
-
 /*
  * Returns true iff the specified sector is present in the disk image. Drivers
  * not implementing the functionality are assumed to not support backing files,
@@ -1918,8 +1907,8 @@ static void coroutine_fn bdrv_is_allocated_co_entry(void *opaque)
  *
  * 'nb_sectors' is the max value 'pnum' should be set to.
  */
-int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
-	int *pnum)
+int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t sector_num,
+                                      int nb_sectors, int *pnum)
 {
     if (!bs->drv->bdrv_co_is_allocated) {
         int64_t n;
@@ -1932,6 +1921,28 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
         return 1;
     }
 
+    return bs->drv->bdrv_co_is_allocated(bs, sector_num, nb_sectors, pnum);
+}
+
+/* Coroutine wrapper for bdrv_is_allocated() */
+static void coroutine_fn bdrv_is_allocated_co_entry(void *opaque)
+{
+    BdrvCoIsAllocatedData *data = opaque;
+    BlockDriverState *bs = data->bs;
+
+    data->ret = bdrv_co_is_allocated(bs, data->sector_num, data->nb_sectors,
+                                     data->pnum);
+    data->done = true;
+}
+
+/*
+ * Synchronous wrapper around bdrv_co_is_allocated().
+ *
+ * See bdrv_co_is_allocated() for details.
+ */
+int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
+                      int *pnum)
+{
     Coroutine *co;
     BdrvCoIsAllocatedData data = {
         .bs = bs,
diff --git a/block.h b/block.h
index 83e17ca..8482dbc 100644
--- a/block.h
+++ b/block.h
@@ -143,6 +143,8 @@ int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num,
     int nb_sectors, QEMUIOVector *qiov);
 int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num,
     int nb_sectors, QEMUIOVector *qiov);
+int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t sector_num,
+    int nb_sectors, int *pnum);
 int bdrv_truncate(BlockDriverState *bs, int64_t offset);
 int64_t bdrv_getlength(BlockDriverState *bs);
 int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
commit 6aebab140d1891813628f0148c6c4d66b5c1dd66
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Nov 14 12:44:25 2011 +0000

    block: drop .bdrv_is_allocated() interface
    
    Now that all block drivers have been converted to
    .bdrv_co_is_allocated() we can drop .bdrv_is_allocated().
    
    Note that the public bdrv_is_allocated() interface is still available
    but is in fact a synchronous wrapper around .bdrv_co_is_allocated().
    
    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 611c429..50b058d 100644
--- a/block.c
+++ b/block.c
@@ -1921,25 +1921,8 @@ static void coroutine_fn bdrv_is_allocated_co_entry(void *opaque)
 int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
 	int *pnum)
 {
-    int64_t n;
-    if (bs->drv->bdrv_co_is_allocated) {
-        Coroutine *co;
-        BdrvCoIsAllocatedData data = {
-            .bs = bs,
-            .sector_num = sector_num,
-            .nb_sectors = nb_sectors,
-            .pnum = pnum,
-            .done = false,
-        };
-
-        co = qemu_coroutine_create(bdrv_is_allocated_co_entry);
-        qemu_coroutine_enter(co, &data);
-        while (!data.done) {
-            qemu_aio_wait();
-        }
-        return data.ret;
-    }
-    if (!bs->drv->bdrv_is_allocated) {
+    if (!bs->drv->bdrv_co_is_allocated) {
+        int64_t n;
         if (sector_num >= bs->total_sectors) {
             *pnum = 0;
             return 0;
@@ -1948,7 +1931,22 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
         *pnum = (n < nb_sectors) ? (n) : (nb_sectors);
         return 1;
     }
-    return bs->drv->bdrv_is_allocated(bs, sector_num, nb_sectors, pnum);
+
+    Coroutine *co;
+    BdrvCoIsAllocatedData data = {
+        .bs = bs,
+        .sector_num = sector_num,
+        .nb_sectors = nb_sectors,
+        .pnum = pnum,
+        .done = false,
+    };
+
+    co = qemu_coroutine_create(bdrv_is_allocated_co_entry);
+    qemu_coroutine_enter(co, &data);
+    while (!data.done) {
+        qemu_aio_wait();
+    }
+    return data.ret;
 }
 
 void bdrv_mon_event(const BlockDriverState *bdrv,
diff --git a/block_int.h b/block_int.h
index d5b5457..a0b46d7 100644
--- a/block_int.h
+++ b/block_int.h
@@ -80,8 +80,6 @@ struct BlockDriver {
                       const uint8_t *buf, int nb_sectors);
     void (*bdrv_close)(BlockDriverState *bs);
     int (*bdrv_create)(const char *filename, QEMUOptionParameter *options);
-    int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num,
-                             int nb_sectors, int *pnum);
     int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
     int (*bdrv_make_empty)(BlockDriverState *bs);
     /* aio */
commit 81145834d39897c6f153ac26a4077f90f269c5fc
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Nov 14 12:44:24 2011 +0000

    cow: convert to .bdrv_co_is_allocated()
    
    The cow block driver does not keep internal state for cluster lookups.
    This means it is safe to perform cluster lookups in coroutine context
    without risk of race conditions that corrupt internal state.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/cow.c b/block/cow.c
index 9858d71..7ae887b 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -132,8 +132,8 @@ static inline int is_bit_set(BlockDriverState *bs, int64_t bitnum)
 /* Return true if first block has been changed (ie. current version is
  * in COW file).  Set the number of continuous blocks for which that
  * is true. */
-static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num,
-        int nb_sectors, int *num_same)
+static int coroutine_fn cow_co_is_allocated(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, int *num_same)
 {
     int changed;
 
@@ -178,7 +178,7 @@ static int cow_read(BlockDriverState *bs, int64_t sector_num,
     int ret, n;
 
     while (nb_sectors > 0) {
-        if (cow_is_allocated(bs, sector_num, nb_sectors, &n)) {
+        if (bdrv_is_allocated(bs, sector_num, nb_sectors, &n)) {
             ret = bdrv_pread(bs->file,
                         s->cow_sectors_offset + sector_num * 512,
                         buf, n * 512);
@@ -335,7 +335,7 @@ static BlockDriver bdrv_cow = {
     .bdrv_read              = cow_co_read,
     .bdrv_write             = cow_co_write,
     .bdrv_co_flush_to_disk  = cow_co_flush,
-    .bdrv_is_allocated      = cow_is_allocated,
+    .bdrv_co_is_allocated   = cow_co_is_allocated,
 
     .create_options = cow_create_options,
 };
commit e850b35a1f41304c31b971bde95f0534f2afd791
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Nov 14 12:44:23 2011 +0000

    vdi: convert to .bdrv_co_is_allocated()
    
    It is trivial to switch from the synchronous .bdrv_is_allocated()
    interface to .bdrv_co_is_allocated() since vdi_is_allocated() does not
    block.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vdi.c b/block/vdi.c
index 02da6b4..e1d8cff 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -472,8 +472,8 @@ static int vdi_open(BlockDriverState *bs, int flags)
     return -1;
 }
 
-static int vdi_is_allocated(BlockDriverState *bs, int64_t sector_num,
-                             int nb_sectors, int *pnum)
+static int coroutine_fn vdi_co_is_allocated(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, int *pnum)
 {
     /* TODO: Check for too large sector_num (in bdrv_is_allocated or here). */
     BDRVVdiState *s = (BDRVVdiState *)bs->opaque;
@@ -996,7 +996,7 @@ static BlockDriver bdrv_vdi = {
     .bdrv_close = vdi_close,
     .bdrv_create = vdi_create,
     .bdrv_co_flush_to_disk = vdi_co_flush,
-    .bdrv_is_allocated = vdi_is_allocated,
+    .bdrv_co_is_allocated = vdi_co_is_allocated,
     .bdrv_make_empty = vdi_make_empty,
 
     .bdrv_aio_readv = vdi_aio_readv,
commit 73f703ca8f6c9def3c353b67ead01afd10e440c7
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Nov 14 12:44:22 2011 +0000

    vvfat: convert to .bdrv_co_is_allocated()
    
    It is trivial to switch from the synchronous .bdrv_is_allocated()
    interface to .bdrv_co_is_allocated() since vvfat_is_allocated() does not
    block.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vvfat.c b/block/vvfat.c
index a310ce8..eeffc4a 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -2758,7 +2758,7 @@ static coroutine_fn int vvfat_co_write(BlockDriverState *bs, int64_t sector_num,
     return ret;
 }
 
-static int vvfat_is_allocated(BlockDriverState *bs,
+static int coroutine_fn vvfat_co_is_allocated(BlockDriverState *bs,
 	int64_t sector_num, int nb_sectors, int* n)
 {
     BDRVVVFATState* s = bs->opaque;
@@ -2855,7 +2855,7 @@ static BlockDriver bdrv_vvfat = {
     .bdrv_read          = vvfat_co_read,
     .bdrv_write         = vvfat_co_write,
     .bdrv_close		= vvfat_close,
-    .bdrv_is_allocated	= vvfat_is_allocated,
+    .bdrv_co_is_allocated = vvfat_co_is_allocated,
     .protocol_name	= "fat",
 };
 
commit f8a2e5e3ca6146d4cc66a4750daf44a0cf043319
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Nov 14 12:44:21 2011 +0000

    block: convert qcow2, qcow2, and vmdk to .bdrv_co_is_allocated()
    
    The qcow2, qcow, and vmdk block drivers are based on coroutines.  They have a
    coroutine mutex which protects internal state.  We can convert the
    .bdrv_is_allocated() function to .bdrv_co_is_allocated() by holding the mutex
    around the cluster lookup operation.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow.c b/block/qcow.c
index 326ef87..b16955d 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -368,14 +368,16 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
     return cluster_offset;
 }
 
-static int qcow_is_allocated(BlockDriverState *bs, int64_t sector_num,
-                             int nb_sectors, int *pnum)
+static int coroutine_fn qcow_co_is_allocated(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, int *pnum)
 {
     BDRVQcowState *s = bs->opaque;
     int index_in_cluster, n;
     uint64_t cluster_offset;
 
+    qemu_co_mutex_lock(&s->lock);
     cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);
+    qemu_co_mutex_unlock(&s->lock);
     index_in_cluster = sector_num & (s->cluster_sectors - 1);
     n = s->cluster_sectors - index_in_cluster;
     if (n > nb_sectors)
@@ -844,7 +846,7 @@ static BlockDriver bdrv_qcow = {
     .bdrv_co_readv          = qcow_co_readv,
     .bdrv_co_writev         = qcow_co_writev,
     .bdrv_co_flush_to_disk  = qcow_co_flush,
-    .bdrv_is_allocated      = qcow_is_allocated,
+    .bdrv_co_is_allocated   = qcow_co_is_allocated,
 
     .bdrv_set_key           = qcow_set_key,
     .bdrv_make_empty        = qcow_make_empty,
diff --git a/block/qcow2.c b/block/qcow2.c
index 3f8a128..5ac9fb4 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -344,16 +344,19 @@ static int qcow2_set_key(BlockDriverState *bs, const char *key)
     return 0;
 }
 
-static int qcow2_is_allocated(BlockDriverState *bs, int64_t sector_num,
-                              int nb_sectors, int *pnum)
+static int coroutine_fn qcow2_co_is_allocated(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, int *pnum)
 {
+    BDRVQcowState *s = bs->opaque;
     uint64_t cluster_offset;
     int ret;
 
     *pnum = nb_sectors;
-    /* FIXME We can get errors here, but the bdrv_is_allocated interface can't
-     * pass them on today */
+    /* FIXME We can get errors here, but the bdrv_co_is_allocated interface
+     * can't pass them on today */
+    qemu_co_mutex_lock(&s->lock);
     ret = qcow2_get_cluster_offset(bs, sector_num << 9, pnum, &cluster_offset);
+    qemu_co_mutex_unlock(&s->lock);
     if (ret < 0) {
         *pnum = 0;
     }
@@ -1277,7 +1280,7 @@ static BlockDriver bdrv_qcow2 = {
     .bdrv_open          = qcow2_open,
     .bdrv_close         = qcow2_close,
     .bdrv_create        = qcow2_create,
-    .bdrv_is_allocated  = qcow2_is_allocated,
+    .bdrv_co_is_allocated = qcow2_co_is_allocated,
     .bdrv_set_key       = qcow2_set_key,
     .bdrv_make_empty    = qcow2_make_empty,
 
diff --git a/block/vmdk.c b/block/vmdk.c
index f544159..5623ac1 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -861,8 +861,8 @@ static VmdkExtent *find_extent(BDRVVmdkState *s,
     return NULL;
 }
 
-static int vmdk_is_allocated(BlockDriverState *bs, int64_t sector_num,
-                             int nb_sectors, int *pnum)
+static int coroutine_fn vmdk_co_is_allocated(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, int *pnum)
 {
     BDRVVmdkState *s = bs->opaque;
     int64_t index_in_cluster, n, ret;
@@ -873,8 +873,10 @@ static int vmdk_is_allocated(BlockDriverState *bs, int64_t sector_num,
     if (!extent) {
         return 0;
     }
+    qemu_co_mutex_lock(&s->lock);
     ret = get_cluster_offset(bs, extent, NULL,
                             sector_num * 512, 0, &offset);
+    qemu_co_mutex_unlock(&s->lock);
     /* get_cluster_offset returning 0 means success */
     ret = !ret;
 
@@ -1596,7 +1598,7 @@ static BlockDriver bdrv_vmdk = {
     .bdrv_close     = vmdk_close,
     .bdrv_create    = vmdk_create,
     .bdrv_co_flush_to_disk  = vmdk_co_flush,
-    .bdrv_is_allocated      = vmdk_is_allocated,
+    .bdrv_co_is_allocated   = vmdk_co_is_allocated,
     .bdrv_get_allocated_file_size  = vmdk_get_allocated_file_size,
 
     .create_options = vmdk_create_options,
commit b7d5a5b8ae5425a4dee69b043b1f334237b3b06a
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Nov 14 12:44:20 2011 +0000

    qed: convert to .bdrv_co_is_allocated()
    
    The bdrv_qed_is_allocated() function is a synchronous wrapper around
    qed_find_cluster(), which performs the cluster lookup.  In order to
    convert the synchronous function to a coroutine function we yield
    instead of using qemu_aio_wait().  Note that QED's cache is already safe
    for parallel requests so no locking is needed.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qed.c b/block/qed.c
index 7e22e77..22e4672 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -661,6 +661,7 @@ static int bdrv_qed_create(const char *filename, QEMUOptionParameter *options)
 }
 
 typedef struct {
+    Coroutine *co;
     int is_allocated;
     int *pnum;
 } QEDIsAllocatedCB;
@@ -670,10 +671,14 @@ static void qed_is_allocated_cb(void *opaque, int ret, uint64_t offset, size_t l
     QEDIsAllocatedCB *cb = opaque;
     *cb->pnum = len / BDRV_SECTOR_SIZE;
     cb->is_allocated = (ret == QED_CLUSTER_FOUND || ret == QED_CLUSTER_ZERO);
+    if (cb->co) {
+        qemu_coroutine_enter(cb->co, NULL);
+    }
 }
 
-static int bdrv_qed_is_allocated(BlockDriverState *bs, int64_t sector_num,
-                                  int nb_sectors, int *pnum)
+static int coroutine_fn bdrv_qed_co_is_allocated(BlockDriverState *bs,
+                                                 int64_t sector_num,
+                                                 int nb_sectors, int *pnum)
 {
     BDRVQEDState *s = bs->opaque;
     uint64_t pos = (uint64_t)sector_num * BDRV_SECTOR_SIZE;
@@ -686,8 +691,10 @@ static int bdrv_qed_is_allocated(BlockDriverState *bs, int64_t sector_num,
 
     qed_find_cluster(s, &request, pos, len, qed_is_allocated_cb, &cb);
 
+    /* Now sleep if the callback wasn't invoked immediately */
     while (cb.is_allocated == -1) {
-        qemu_aio_wait();
+        cb.co = qemu_coroutine_self();
+        qemu_coroutine_yield();
     }
 
     qed_unref_l2_cache_entry(request.l2_table);
@@ -1485,7 +1492,7 @@ static BlockDriver bdrv_qed = {
     .bdrv_open                = bdrv_qed_open,
     .bdrv_close               = bdrv_qed_close,
     .bdrv_create              = bdrv_qed_create,
-    .bdrv_is_allocated        = bdrv_qed_is_allocated,
+    .bdrv_co_is_allocated     = bdrv_qed_co_is_allocated,
     .bdrv_make_empty          = bdrv_qed_make_empty,
     .bdrv_aio_readv           = bdrv_qed_aio_readv,
     .bdrv_aio_writev          = bdrv_qed_aio_writev,
commit 376ae3f1cb5a08f53c9425bfaf90b3f70ab240f1
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Nov 14 12:44:19 2011 +0000

    block: add .bdrv_co_is_allocated()
    
    This patch adds the .bdrv_co_is_allocated() interface which is identical
    to .bdrv_is_allocated() but runs in coroutine context.  Running in
    coroutine context implies that other coroutines might be performing I/O
    at the same time.   Therefore it must be safe to run while the following
    BlockDriver functions are in-flight:
    
        .bdrv_co_readv()
        .bdrv_co_writev()
        .bdrv_co_flush()
        .bdrv_co_is_allocated()
    
    The new .bdrv_co_is_allocated() interface is useful because it can be
    used when a VM is running, whereas .bdrv_is_allocated() is a synchronous
    interface that does not cope with parallel requests.
    
    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 0d5bee0..611c429 100644
--- a/block.c
+++ b/block.c
@@ -1887,6 +1887,26 @@ int bdrv_has_zero_init(BlockDriverState *bs)
     return 1;
 }
 
+typedef struct BdrvCoIsAllocatedData {
+    BlockDriverState *bs;
+    int64_t sector_num;
+    int nb_sectors;
+    int *pnum;
+    int ret;
+    bool done;
+} BdrvCoIsAllocatedData;
+
+/* Coroutine wrapper for bdrv_is_allocated() */
+static void coroutine_fn bdrv_is_allocated_co_entry(void *opaque)
+{
+    BdrvCoIsAllocatedData *data = opaque;
+    BlockDriverState *bs = data->bs;
+
+    data->ret = bs->drv->bdrv_co_is_allocated(bs, data->sector_num,
+                                              data->nb_sectors, data->pnum);
+    data->done = true;
+}
+
 /*
  * Returns true iff the specified sector is present in the disk image. Drivers
  * not implementing the functionality are assumed to not support backing files,
@@ -1902,6 +1922,23 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
 	int *pnum)
 {
     int64_t n;
+    if (bs->drv->bdrv_co_is_allocated) {
+        Coroutine *co;
+        BdrvCoIsAllocatedData data = {
+            .bs = bs,
+            .sector_num = sector_num,
+            .nb_sectors = nb_sectors,
+            .pnum = pnum,
+            .done = false,
+        };
+
+        co = qemu_coroutine_create(bdrv_is_allocated_co_entry);
+        qemu_coroutine_enter(co, &data);
+        while (!data.done) {
+            qemu_aio_wait();
+        }
+        return data.ret;
+    }
     if (!bs->drv->bdrv_is_allocated) {
         if (sector_num >= bs->total_sectors) {
             *pnum = 0;
diff --git a/block_int.h b/block_int.h
index e2799e4..d5b5457 100644
--- a/block_int.h
+++ b/block_int.h
@@ -103,6 +103,8 @@ struct BlockDriver {
         int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
     int coroutine_fn (*bdrv_co_discard)(BlockDriverState *bs,
         int64_t sector_num, int nb_sectors);
+    int coroutine_fn (*bdrv_co_is_allocated)(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, int *pnum);
 
     /*
      * Invalidate any cached meta-data.
commit 05c4af54c670f5143bd4ac5d79aa1ef53a9f31ca
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Nov 14 12:44:18 2011 +0000

    block: use public bdrv_is_allocated() interface
    
    There is no need for bdrv_commit() to use the BlockDriver
    .bdrv_is_allocated() interface directly.  Converting to the public
    interface gives us the freedom to drop .bdrv_is_allocated() entirely in
    favor of a new .bdrv_co_is_allocated() in the future.
    
    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 5f979bd..0d5bee0 100644
--- a/block.c
+++ b/block.c
@@ -1013,7 +1013,7 @@ int bdrv_commit(BlockDriverState *bs)
     buf = g_malloc(COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE);
 
     for (sector = 0; sector < total_sectors; sector += n) {
-        if (drv->bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n)) {
+        if (bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n)) {
 
             if (bdrv_read(bs, sector, buf, n) != 0) {
                 ret = -EIO;
commit e3f652b33228e16e117a93fb919c4e1e4753f5a5
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Nov 16 17:30:33 2011 +0100

    qcow2: Fix error path in qcow2_snapshot_load_tmp
    
    If the bdrv_read() of the snapshot's L1 table fails, return the right
    error code and make sure that the old L1 table is still loaded and we
    don't break the BlockDriverState completely.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index e959ef2..c3112bf 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -573,32 +573,42 @@ int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
 
 int qcow2_snapshot_load_tmp(BlockDriverState *bs, const char *snapshot_name)
 {
-    int i, snapshot_index, l1_size2;
+    int i, snapshot_index;
     BDRVQcowState *s = bs->opaque;
     QCowSnapshot *sn;
+    uint64_t *new_l1_table;
+    int new_l1_bytes;
+    int ret;
 
+    assert(bs->read_only);
+
+    /* Search the snapshot */
     snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_name);
     if (snapshot_index < 0) {
         return -ENOENT;
     }
-
     sn = &s->snapshots[snapshot_index];
-    s->l1_size = sn->l1_size;
-    l1_size2 = s->l1_size * sizeof(uint64_t);
-    if (s->l1_table != NULL) {
-        g_free(s->l1_table);
-    }
 
-    s->l1_table_offset = sn->l1_table_offset;
-    s->l1_table = g_malloc0(align_offset(l1_size2, 512));
+    /* Allocate and read in the snapshot's L1 table */
+    new_l1_bytes = s->l1_size * sizeof(uint64_t);
+    new_l1_table = g_malloc0(align_offset(new_l1_bytes, 512));
 
-    if (bdrv_pread(bs->file, sn->l1_table_offset,
-                   s->l1_table, l1_size2) != l1_size2) {
-        return -1;
+    ret = bdrv_pread(bs->file, sn->l1_table_offset, new_l1_table, new_l1_bytes);
+    if (ret < 0) {
+        g_free(new_l1_table);
+        return ret;
     }
 
+    /* Switch the L1 table */
+    g_free(s->l1_table);
+
+    s->l1_size = sn->l1_size;
+    s->l1_table_offset = sn->l1_table_offset;
+    s->l1_table = new_l1_table;
+
     for(i = 0;i < s->l1_size; i++) {
         be64_to_cpus(&s->l1_table[i]);
     }
+
     return 0;
 }
commit 9a4767809fe9ac184806bef38be2e2a84e451a65
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Nov 16 17:22:10 2011 +0100

    qcow2: Fix order in qcow2_snapshot_delete
    
    First the snapshot must be deleted and only then the refcounts can be
    decreased.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 9fb3ff0..e959ef2 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -489,32 +489,50 @@ fail:
 int qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
 {
     BDRVQcowState *s = bs->opaque;
-    QCowSnapshot *sn;
+    QCowSnapshot sn;
     int snapshot_index, ret;
 
+    /* Search the snapshot */
     snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id);
-    if (snapshot_index < 0)
+    if (snapshot_index < 0) {
         return -ENOENT;
-    sn = &s->snapshots[snapshot_index];
+    }
+    sn = s->snapshots[snapshot_index];
 
-    ret = qcow2_update_snapshot_refcount(bs, sn->l1_table_offset, sn->l1_size, -1);
-    if (ret < 0)
+    /* Remove it from the snapshot list */
+    memmove(s->snapshots + snapshot_index,
+            s->snapshots + snapshot_index + 1,
+            (s->nb_snapshots - snapshot_index - 1) * sizeof(sn));
+    s->nb_snapshots--;
+    ret = qcow2_write_snapshots(bs);
+    if (ret < 0) {
         return ret;
-    /* must update the copied flag on the current cluster offsets */
-    ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 0);
-    if (ret < 0)
+    }
+
+    /*
+     * The snapshot is now unused, clean up. If we fail after this point, we
+     * won't recover but just leak clusters.
+     */
+    g_free(sn.id_str);
+    g_free(sn.name);
+
+    /*
+     * Now decrease the refcounts of clusters referenced by the snapshot and
+     * free the L1 table.
+     */
+    ret = qcow2_update_snapshot_refcount(bs, sn.l1_table_offset,
+                                         sn.l1_size, -1);
+    if (ret < 0) {
         return ret;
-    qcow2_free_clusters(bs, sn->l1_table_offset, sn->l1_size * sizeof(uint64_t));
+    }
+    qcow2_free_clusters(bs, sn.l1_table_offset, sn.l1_size * sizeof(uint64_t));
 
-    g_free(sn->id_str);
-    g_free(sn->name);
-    memmove(sn, sn + 1, (s->nb_snapshots - snapshot_index - 1) * sizeof(*sn));
-    s->nb_snapshots--;
-    ret = qcow2_write_snapshots(bs);
+    /* must update the copied flag on the current cluster offsets */
+    ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 0);
     if (ret < 0) {
-        /* XXX: restore snapshot if error ? */
         return ret;
     }
+
 #ifdef DEBUG_ALLOC
     {
         BdrvCheckResult result = {0};
commit 43a0cac4658bbee9c9e84554712a94daa092c1cd
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Nov 16 15:20:45 2011 +0100

    qcow2: Fix order of refcount updates in qcow2_snapshot_goto
    
    The refcount updates must be moved so that in the worst case we can get
    cluster leaks, but refcounts may never be too low.
    
    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 9605367..2db2ede 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -700,6 +700,10 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
     l2_table = NULL;
     l1_table = NULL;
     l1_size2 = l1_size * sizeof(uint64_t);
+
+    /* WARNING: qcow2_snapshot_goto relies on this function not using the
+     * l1_table_offset when it is the current s->l1_table_offset! Be careful
+     * when changing this! */
     if (l1_table_offset != s->l1_table_offset) {
         if (l1_size2 != 0) {
             l1_table = g_malloc0(align_offset(l1_size2, 512));
@@ -819,7 +823,8 @@ fail:
     qcow2_cache_set_writethrough(bs, s->refcount_block_cache,
         old_refcount_writethrough);
 
-    if (l1_modified) {
+    /* Update L1 only if it isn't deleted anyway (addend = -1) */
+    if (addend >= 0 && l1_modified) {
         for(i = 0; i < l1_size; i++)
             cpu_to_be64s(&l1_table[i]);
         if (bdrv_pwrite_sync(bs->file, l1_table_offset, l1_table,
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 1ee22eb..9fb3ff0 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -387,6 +387,7 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
     int i, snapshot_index;
     int cur_l1_bytes, sn_l1_bytes;
     int ret;
+    uint64_t *sn_l1_table = NULL;
 
     /* Search the snapshot */
     snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id);
@@ -395,14 +396,6 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
     }
     sn = &s->snapshots[snapshot_index];
 
-    /* Decrease refcount of clusters of current L1 table.
-     * FIXME This is too early! */
-    ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset,
-                                         s->l1_size, -1);
-    if (ret < 0) {
-        goto fail;
-    }
-
     /*
      * Make sure that the current L1 table is big enough to contain the whole
      * L1 table of the snapshot. If the snapshot L1 table is smaller, the
@@ -416,33 +409,66 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
     cur_l1_bytes = s->l1_size * sizeof(uint64_t);
     sn_l1_bytes = sn->l1_size * sizeof(uint64_t);
 
-    if (cur_l1_bytes > sn_l1_bytes) {
-        memset(s->l1_table + sn->l1_size, 0, cur_l1_bytes - sn_l1_bytes);
-    }
-
     /*
      * Copy the snapshot L1 table to the current L1 table.
      *
      * Before overwriting the old current L1 table on disk, make sure to
      * increase all refcounts for the clusters referenced by the new one.
+     * Decrease the refcount referenced by the old one only when the L1
+     * table is overwritten.
      */
-    ret = bdrv_pread(bs->file, sn->l1_table_offset, s->l1_table, sn_l1_bytes);
+    sn_l1_table = g_malloc0(cur_l1_bytes);
+
+    ret = bdrv_pread(bs->file, sn->l1_table_offset, sn_l1_table, sn_l1_bytes);
+    if (ret < 0) {
+        goto fail;
+    }
+
+    ret = qcow2_update_snapshot_refcount(bs, sn->l1_table_offset,
+                                         sn->l1_size, 1);
     if (ret < 0) {
         goto fail;
     }
 
-    ret = bdrv_pwrite_sync(bs->file, s->l1_table_offset, s->l1_table,
+    ret = bdrv_pwrite_sync(bs->file, s->l1_table_offset, sn_l1_table,
                            cur_l1_bytes);
     if (ret < 0) {
         goto fail;
     }
 
+    /*
+     * Decrease refcount of clusters of current L1 table.
+     *
+     * At this point, the in-memory s->l1_table points to the old L1 table,
+     * whereas on disk we already have the new one.
+     *
+     * qcow2_update_snapshot_refcount special cases the current L1 table to use
+     * the in-memory data instead of really using the offset to load a new one,
+     * which is why this works.
+     */
+    ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset,
+                                         s->l1_size, -1);
+
+    /*
+     * Now update the in-memory L1 table to be in sync with the on-disk one. We
+     * need to do this even if updating refcounts failed.
+     */
     for(i = 0;i < s->l1_size; i++) {
-        be64_to_cpus(&s->l1_table[i]);
+        s->l1_table[i] = be64_to_cpu(sn_l1_table[i]);
     }
 
-    /* FIXME This is too late! */
-    ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1);
+    if (ret < 0) {
+        goto fail;
+    }
+
+    g_free(sn_l1_table);
+    sn_l1_table = NULL;
+
+    /*
+     * Update QCOW_OFLAG_COPIED in the active L1 table (it may have changed
+     * when we decreased the refcount of the old snapshot.
+     */
+    ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 0);
     if (ret < 0) {
         goto fail;
     }
@@ -456,6 +482,7 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
     return 0;
 
 fail:
+    g_free(sn_l1_table);
     return ret;
 }
 
commit 589f284b7690bbb4ed37170590bae9527ed31b42
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Nov 16 15:04:11 2011 +0100

    qcow2: Return real error in qcow2_snapshot_goto
    
    Besides fixing the return code, this adds some comments that make clear
    how the code works and that it potentially breaks images if we fail in
    the wrong place. Actually fixing this is left for the next patch.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index a8add9c..1ee22eb 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -386,17 +386,32 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
     QCowSnapshot *sn;
     int i, snapshot_index;
     int cur_l1_bytes, sn_l1_bytes;
+    int ret;
 
+    /* Search the snapshot */
     snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id);
-    if (snapshot_index < 0)
+    if (snapshot_index < 0) {
         return -ENOENT;
+    }
     sn = &s->snapshots[snapshot_index];
 
-    if (qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, -1) < 0)
+    /* Decrease refcount of clusters of current L1 table.
+     * FIXME This is too early! */
+    ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset,
+                                         s->l1_size, -1);
+    if (ret < 0) {
         goto fail;
+    }
 
-    if (qcow2_grow_l1_table(bs, sn->l1_size, true) < 0)
+    /*
+     * Make sure that the current L1 table is big enough to contain the whole
+     * L1 table of the snapshot. If the snapshot L1 table is smaller, the
+     * current one must be padded with zeros.
+     */
+    ret = qcow2_grow_l1_table(bs, sn->l1_size, true);
+    if (ret < 0) {
         goto fail;
+    }
 
     cur_l1_bytes = s->l1_size * sizeof(uint64_t);
     sn_l1_bytes = sn->l1_size * sizeof(uint64_t);
@@ -405,19 +420,32 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
         memset(s->l1_table + sn->l1_size, 0, cur_l1_bytes - sn_l1_bytes);
     }
 
-    /* copy the snapshot l1 table to the current l1 table */
-    if (bdrv_pread(bs->file, sn->l1_table_offset,
-                   s->l1_table, sn_l1_bytes) < 0)
+    /*
+     * Copy the snapshot L1 table to the current L1 table.
+     *
+     * Before overwriting the old current L1 table on disk, make sure to
+     * increase all refcounts for the clusters referenced by the new one.
+     */
+    ret = bdrv_pread(bs->file, sn->l1_table_offset, s->l1_table, sn_l1_bytes);
+    if (ret < 0) {
         goto fail;
-    if (bdrv_pwrite_sync(bs->file, s->l1_table_offset,
-                    s->l1_table, cur_l1_bytes) < 0)
+    }
+
+    ret = bdrv_pwrite_sync(bs->file, s->l1_table_offset, s->l1_table,
+                           cur_l1_bytes);
+    if (ret < 0) {
         goto fail;
+    }
+
     for(i = 0;i < s->l1_size; i++) {
         be64_to_cpus(&s->l1_table[i]);
     }
 
-    if (qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1) < 0)
+    /* FIXME This is too late! */
+    ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1);
+    if (ret < 0) {
         goto fail;
+    }
 
 #ifdef DEBUG_ALLOC
     {
@@ -426,8 +454,9 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
     }
 #endif
     return 0;
- fail:
-    return -EIO;
+
+fail:
+    return ret;
 }
 
 int qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
commit d1ea98d56dc2485b4637a1ca19feef786b3aee8f
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Nov 16 12:43:59 2011 +0100

    qcow2: Rework qcow2_snapshot_create error handling
    
    Increase refcounts only after allocating a new L1 table has succeeded in
    order to make leaks less likely. If writing the snapshot table fails,
    revert in-memory state to be consistent with that on disk.
    
    While at it, make it return the real error codes instead of -1.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 53d9233..a8add9c 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -277,7 +277,9 @@ static int find_snapshot_by_id_or_name(BlockDriverState *bs, const char *name)
 int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
 {
     BDRVQcowState *s = bs->opaque;
-    QCowSnapshot *snapshots1, sn1, *sn = &sn1;
+    QCowSnapshot *new_snapshot_list = NULL;
+    QCowSnapshot *old_snapshot_list = NULL;
+    QCowSnapshot sn1, *sn = &sn1;
     int i, ret;
     uint64_t *l1_table = NULL;
     int64_t l1_table_offset;
@@ -303,16 +305,12 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     sn->date_nsec = sn_info->date_nsec;
     sn->vm_clock_nsec = sn_info->vm_clock_nsec;
 
-    ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1);
-    if (ret < 0)
-        goto fail;
-
     /* Allocate the L1 table of the snapshot and copy the current one there. */
     l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * sizeof(uint64_t));
     if (l1_table_offset < 0) {
+        ret = l1_table_offset;
         goto fail;
     }
-    bdrv_flush(bs->file);
 
     sn->l1_table_offset = l1_table_offset;
     sn->l1_size = s->l1_size;
@@ -321,22 +319,50 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     for(i = 0; i < s->l1_size; i++) {
         l1_table[i] = cpu_to_be64(s->l1_table[i]);
     }
-    if (bdrv_pwrite_sync(bs->file, sn->l1_table_offset,
-                    l1_table, s->l1_size * sizeof(uint64_t)) < 0)
+
+    ret = bdrv_pwrite(bs->file, sn->l1_table_offset, l1_table,
+                      s->l1_size * sizeof(uint64_t));
+    if (ret < 0) {
         goto fail;
+    }
+
     g_free(l1_table);
     l1_table = NULL;
 
-    snapshots1 = g_malloc((s->nb_snapshots + 1) * sizeof(QCowSnapshot));
+    /*
+     * Increase the refcounts of all clusters and make sure everything is
+     * stable on disk before updating the snapshot table to contain a pointer
+     * to the new L1 table.
+     */
+    ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1);
+    if (ret < 0) {
+        goto fail;
+    }
+
+    ret = bdrv_flush(bs);
+    if (ret < 0) {
+        goto fail;
+    }
+
+    /* Append the new snapshot to the snapshot list */
+    new_snapshot_list = g_malloc((s->nb_snapshots + 1) * sizeof(QCowSnapshot));
     if (s->snapshots) {
-        memcpy(snapshots1, s->snapshots, s->nb_snapshots * sizeof(QCowSnapshot));
-        g_free(s->snapshots);
+        memcpy(new_snapshot_list, s->snapshots,
+               s->nb_snapshots * sizeof(QCowSnapshot));
+        old_snapshot_list = s->snapshots;
     }
-    s->snapshots = snapshots1;
+    s->snapshots = new_snapshot_list;
     s->snapshots[s->nb_snapshots++] = *sn;
 
-    if (qcow2_write_snapshots(bs) < 0)
+    ret = qcow2_write_snapshots(bs);
+    if (ret < 0) {
+        g_free(s->snapshots);
+        s->snapshots = old_snapshot_list;
         goto fail;
+    }
+
+    g_free(old_snapshot_list);
+
 #ifdef DEBUG_ALLOC
     {
       BdrvCheckResult result = {0};
@@ -349,7 +375,8 @@ fail:
     g_free(sn->id_str);
     g_free(sn->name);
     g_free(l1_table);
-    return -1;
+
+    return ret;
 }
 
 /* copy the snapshot 'snapshot_name' into the current disk image */
commit 03343166f703d5c8f02b8519f8493c56e5541ae7
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Nov 16 17:46:29 2011 +0100

    qcow2: Cleanups and memleak fix in qcow2_snapshot_create
    
    sn->id_str could be leaked before this. The rest of this patch changes
    comments, fixes coding style or removes checks that are unnecessary with
    g_malloc.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 1976df7..53d9233 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -284,21 +284,20 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
 
     memset(sn, 0, sizeof(*sn));
 
+    /* Generate an ID if it wasn't passed */
     if (sn_info->id_str[0] == '\0') {
-        /* compute a new id */
         find_new_snapshot_id(bs, sn_info->id_str, sizeof(sn_info->id_str));
     }
 
-    /* check that the ID is unique */
-    if (find_snapshot_by_id(bs, sn_info->id_str) >= 0)
+    /* Check that the ID is unique */
+    if (find_snapshot_by_id(bs, sn_info->id_str) >= 0) {
         return -ENOENT;
+    }
 
+    /* Populate sn with passed data */
     sn->id_str = g_strdup(sn_info->id_str);
-    if (!sn->id_str)
-        goto fail;
     sn->name = g_strdup(sn_info->name);
-    if (!sn->name)
-        goto fail;
+
     sn->vm_state_size = sn_info->vm_state_size;
     sn->date_sec = sn_info->date_sec;
     sn->date_nsec = sn_info->date_nsec;
@@ -308,7 +307,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     if (ret < 0)
         goto fail;
 
-    /* create the L1 table of the snapshot */
+    /* Allocate the L1 table of the snapshot and copy the current one there. */
     l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * sizeof(uint64_t));
     if (l1_table_offset < 0) {
         goto fail;
@@ -318,12 +317,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     sn->l1_table_offset = l1_table_offset;
     sn->l1_size = s->l1_size;
 
-    if (s->l1_size != 0) {
-        l1_table = g_malloc(s->l1_size * sizeof(uint64_t));
-    } else {
-        l1_table = NULL;
-    }
-
+    l1_table = g_malloc(s->l1_size * sizeof(uint64_t));
     for(i = 0; i < s->l1_size; i++) {
         l1_table[i] = cpu_to_be64(s->l1_table[i]);
     }
@@ -350,7 +344,9 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     }
 #endif
     return 0;
- fail:
+
+fail:
+    g_free(sn->id_str);
     g_free(sn->name);
     g_free(l1_table);
     return -1;
commit d69969c4046a81af106e723ff1bc2740365e67c1
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Nov 18 18:27:00 2011 +0100

    qcow2: Update snapshot table information at once
    
    Failing in the middle wouldn't help with the integrity of the image, so
    doing everything in a single request seems better.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index e91a286..1976df7 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -137,8 +137,10 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
     QCowSnapshot *sn;
     QCowSnapshotHeader h;
     int i, name_size, id_str_size, snapshots_size;
-    uint64_t data64;
-    uint32_t data32;
+    struct {
+        uint32_t nb_snapshots;
+        uint64_t snapshots_offset;
+    } QEMU_PACKED header_data;
     int64_t offset, snapshots_offset;
     int ret;
 
@@ -200,24 +202,20 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
     /*
      * Update the header to point to the new snapshot table. This requires the
      * new table and its refcounts to be stable on disk.
-     *
-     * FIXME This should be done with a single write
      */
     ret = bdrv_flush(bs);
     if (ret < 0) {
         goto fail;
     }
 
-    data64 = cpu_to_be64(snapshots_offset);
-    ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, snapshots_offset),
-                      &data64, sizeof(data64));
-    if (ret < 0) {
-        goto fail;
-    }
+    QEMU_BUILD_BUG_ON(offsetof(QCowHeader, snapshots_offset) !=
+        offsetof(QCowHeader, nb_snapshots) + sizeof(header_data.nb_snapshots));
+
+    header_data.nb_snapshots        = cpu_to_be32(s->nb_snapshots);
+    header_data.snapshots_offset    = cpu_to_be64(snapshots_offset);
 
-    data32 = cpu_to_be32(s->nb_snapshots);
     ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots),
-                           &data32, sizeof(data32));
+                           &header_data, sizeof(header_data));
     if (ret < 0) {
         goto fail;
     }
commit 07fd8779001c3e6ff3ac25416a31381ff8aca308
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Nov 16 12:00:59 2011 +0100

    qcow2: Return real error code in qcow2_write_snapshots
    
    Doesn't immediately fix anything as the callers don't use the return
    value, but they will be fixed next.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 4134bbc..e91a286 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -140,6 +140,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
     uint64_t data64;
     uint32_t data32;
     int64_t offset, snapshots_offset;
+    int ret;
 
     /* compute the size of the snapshots */
     offset = 0;
@@ -152,6 +153,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
     }
     snapshots_size = offset;
 
+    /* Allocate space for the new snapshot list */
     snapshots_offset = qcow2_alloc_clusters(bs, snapshots_size);
     bdrv_flush(bs->file);
     offset = snapshots_offset;
@@ -159,6 +161,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
         return offset;
     }
 
+    /* Write all snapshots to the new list */
     for(i = 0; i < s->nb_snapshots; i++) {
         sn = s->snapshots + i;
         memset(&h, 0, sizeof(h));
@@ -174,34 +177,59 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
         h.id_str_size = cpu_to_be16(id_str_size);
         h.name_size = cpu_to_be16(name_size);
         offset = align_offset(offset, 8);
-        if (bdrv_pwrite_sync(bs->file, offset, &h, sizeof(h)) < 0)
+
+        ret = bdrv_pwrite(bs->file, offset, &h, sizeof(h));
+        if (ret < 0) {
             goto fail;
+        }
         offset += sizeof(h);
-        if (bdrv_pwrite_sync(bs->file, offset, sn->id_str, id_str_size) < 0)
+
+        ret = bdrv_pwrite(bs->file, offset, sn->id_str, id_str_size);
+        if (ret < 0) {
             goto fail;
+        }
         offset += id_str_size;
-        if (bdrv_pwrite_sync(bs->file, offset, sn->name, name_size) < 0)
+
+        ret = bdrv_pwrite(bs->file, offset, sn->name, name_size);
+        if (ret < 0) {
             goto fail;
+        }
         offset += name_size;
     }
 
-    /* update the various header fields */
+    /*
+     * Update the header to point to the new snapshot table. This requires the
+     * new table and its refcounts to be stable on disk.
+     *
+     * FIXME This should be done with a single write
+     */
+    ret = bdrv_flush(bs);
+    if (ret < 0) {
+        goto fail;
+    }
+
     data64 = cpu_to_be64(snapshots_offset);
-    if (bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, snapshots_offset),
-                    &data64, sizeof(data64)) < 0)
+    ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, snapshots_offset),
+                      &data64, sizeof(data64));
+    if (ret < 0) {
         goto fail;
+    }
+
     data32 = cpu_to_be32(s->nb_snapshots);
-    if (bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots),
-                    &data32, sizeof(data32)) < 0)
+    ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots),
+                           &data32, sizeof(data32));
+    if (ret < 0) {
         goto fail;
+    }
 
     /* free the old snapshot table */
     qcow2_free_clusters(bs, s->snapshots_offset, s->snapshots_size);
     s->snapshots_offset = snapshots_offset;
     s->snapshots_size = snapshots_size;
     return 0;
- fail:
-    return -1;
+
+fail:
+    return ret;
 }
 
 static void find_new_snapshot_id(BlockDriverState *bs,
commit 42deb29fed92577db57c54e844f852481600b756
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Nov 16 11:43:28 2011 +0100

    qcow2: Return real error code in qcow2_read_snapshots
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index bdc33ba..4134bbc 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -68,6 +68,7 @@ int qcow2_read_snapshots(BlockDriverState *bs)
     int i, id_str_size, name_size;
     int64_t offset;
     uint32_t extra_data_size;
+    int ret;
 
     if (!s->nb_snapshots) {
         s->snapshots = NULL;
@@ -77,10 +78,15 @@ int qcow2_read_snapshots(BlockDriverState *bs)
 
     offset = s->snapshots_offset;
     s->snapshots = g_malloc0(s->nb_snapshots * sizeof(QCowSnapshot));
+
     for(i = 0; i < s->nb_snapshots; i++) {
+        /* Read statically sized part of the snapshot header */
         offset = align_offset(offset, 8);
-        if (bdrv_pread(bs->file, offset, &h, sizeof(h)) != sizeof(h))
+        ret = bdrv_pread(bs->file, offset, &h, sizeof(h));
+        if (ret < 0) {
             goto fail;
+        }
+
         offset += sizeof(h);
         sn = s->snapshots + i;
         sn->l1_table_offset = be64_to_cpu(h.l1_table_offset);
@@ -94,25 +100,34 @@ int qcow2_read_snapshots(BlockDriverState *bs)
         id_str_size = be16_to_cpu(h.id_str_size);
         name_size = be16_to_cpu(h.name_size);
 
+        /* Skip extra data */
         offset += extra_data_size;
 
+        /* Read snapshot ID */
         sn->id_str = g_malloc(id_str_size + 1);
-        if (bdrv_pread(bs->file, offset, sn->id_str, id_str_size) != id_str_size)
+        ret = bdrv_pread(bs->file, offset, sn->id_str, id_str_size);
+        if (ret < 0) {
             goto fail;
+        }
         offset += id_str_size;
         sn->id_str[id_str_size] = '\0';
 
+        /* Read snapshot name */
         sn->name = g_malloc(name_size + 1);
-        if (bdrv_pread(bs->file, offset, sn->name, name_size) != name_size)
+        ret = bdrv_pread(bs->file, offset, sn->name, name_size);
+        if (ret < 0) {
             goto fail;
+        }
         offset += name_size;
         sn->name[name_size] = '\0';
     }
+
     s->snapshots_size = offset - s->snapshots_offset;
     return 0;
- fail:
+
+fail:
     qcow2_free_snapshots(bs);
-    return -1;
+    return ret;
 }
 
 /* add at the end of the file a new list of snapshots */
diff --git a/block/qcow2.c b/block/qcow2.c
index a6a4f47..3f8a128 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -273,8 +273,9 @@ static int qcow2_open(BlockDriverState *bs, int flags)
         }
         bs->backing_file[len] = '\0';
     }
-    if (qcow2_read_snapshots(bs) < 0) {
-        ret = -EINVAL;
+
+    ret = qcow2_read_snapshots(bs);
+    if (ret < 0) {
         goto fail;
     }
 
commit a968168c580cb45a700e0b218c7f6871d91ee257
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Thu Nov 10 16:23:22 2011 +0800

    block: Add coroutine_fn marker to coroutine functions
    
    Looks better when reviewing these source files.
    
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow.c b/block/qcow.c
index 4814ed0..326ef87 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -433,7 +433,7 @@ static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
     return 0;
 }
 
-static int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
+static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
                          int nb_sectors, QEMUIOVector *qiov)
 {
     BDRVQcowState *s = bs->opaque;
@@ -531,7 +531,7 @@ fail:
     goto done;
 }
 
-static int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
+static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
                           int nb_sectors, QEMUIOVector *qiov)
 {
     BDRVQcowState *s = bs->opaque;
diff --git a/block/qcow2.c b/block/qcow2.c
index d7805ce..a6a4f47 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -377,7 +377,7 @@ int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov,
     return n1;
 }
 
-static int qcow2_co_readv(BlockDriverState *bs, int64_t sector_num,
+static coroutine_fn int qcow2_co_readv(BlockDriverState *bs, int64_t sector_num,
                           int remaining_sectors, QEMUIOVector *qiov)
 {
     BDRVQcowState *s = bs->opaque;
@@ -517,7 +517,7 @@ static void run_dependent_requests(BDRVQcowState *s, QCowL2Meta *m)
     }
 }
 
-static int qcow2_co_writev(BlockDriverState *bs,
+static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
                            int64_t sector_num,
                            int remaining_sectors,
                            QEMUIOVector *qiov)
@@ -1137,7 +1137,7 @@ fail:
     return ret;
 }
 
-static int qcow2_co_flush_to_os(BlockDriverState *bs)
+static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs)
 {
     BDRVQcowState *s = bs->opaque;
     int ret;
@@ -1159,7 +1159,7 @@ static int qcow2_co_flush_to_os(BlockDriverState *bs)
     return 0;
 }
 
-static int qcow2_co_flush_to_disk(BlockDriverState *bs)
+static coroutine_fn int qcow2_co_flush_to_disk(BlockDriverState *bs)
 {
     return bdrv_co_flush(bs->file);
 }
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 62f1f3a..aa9707f 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -1715,7 +1715,7 @@ out:
     return 1;
 }
 
-static int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
+static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
                         int nb_sectors, QEMUIOVector *qiov)
 {
     SheepdogAIOCB *acb;
@@ -1744,7 +1744,7 @@ static int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
     return acb->ret;
 }
 
-static int sd_co_readv(BlockDriverState *bs, int64_t sector_num,
+static coroutine_fn int sd_co_readv(BlockDriverState *bs, int64_t sector_num,
                        int nb_sectors, QEMUIOVector *qiov)
 {
     SheepdogAIOCB *acb;
commit 727f005e6a5416ea903d0ccc2428cbdc663aa1d2
Author: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
Date:   Tue Nov 8 13:00:31 2011 +0800

    hmp/qmp: add block_set_io_throttle
    
    Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.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 42bd308..5f979bd 100644
--- a/block.c
+++ b/block.c
@@ -1978,6 +1978,21 @@ BlockInfoList *qmp_query_block(Error **errp)
                 info->value->inserted->has_backing_file = true;
                 info->value->inserted->backing_file = g_strdup(bs->backing_file);
             }
+
+            if (bs->io_limits_enabled) {
+                info->value->inserted->bps =
+                               bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL];
+                info->value->inserted->bps_rd =
+                               bs->io_limits.bps[BLOCK_IO_LIMIT_READ];
+                info->value->inserted->bps_wr =
+                               bs->io_limits.bps[BLOCK_IO_LIMIT_WRITE];
+                info->value->inserted->iops =
+                               bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL];
+                info->value->inserted->iops_rd =
+                               bs->io_limits.iops[BLOCK_IO_LIMIT_READ];
+                info->value->inserted->iops_wr =
+                               bs->io_limits.iops[BLOCK_IO_LIMIT_WRITE];
+            }
         }
 
         /* XXX: waiting for the qapi to support GSList */
diff --git a/blockdev.c b/blockdev.c
index bbe5f11..9068c5b 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -759,6 +759,65 @@ int do_change_block(Monitor *mon, const char *device,
     return monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
 }
 
+/* throttling disk I/O limits */
+int do_block_set_io_throttle(Monitor *mon,
+                       const QDict *qdict, QObject **ret_data)
+{
+    BlockIOLimit io_limits;
+    const char *devname = qdict_get_str(qdict, "device");
+    BlockDriverState *bs;
+
+    io_limits.bps[BLOCK_IO_LIMIT_TOTAL]
+                        = qdict_get_try_int(qdict, "bps", -1);
+    io_limits.bps[BLOCK_IO_LIMIT_READ]
+                        = qdict_get_try_int(qdict, "bps_rd", -1);
+    io_limits.bps[BLOCK_IO_LIMIT_WRITE]
+                        = qdict_get_try_int(qdict, "bps_wr", -1);
+    io_limits.iops[BLOCK_IO_LIMIT_TOTAL]
+                        = qdict_get_try_int(qdict, "iops", -1);
+    io_limits.iops[BLOCK_IO_LIMIT_READ]
+                        = qdict_get_try_int(qdict, "iops_rd", -1);
+    io_limits.iops[BLOCK_IO_LIMIT_WRITE]
+                        = qdict_get_try_int(qdict, "iops_wr", -1);
+
+    bs = bdrv_find(devname);
+    if (!bs) {
+        qerror_report(QERR_DEVICE_NOT_FOUND, devname);
+        return -1;
+    }
+
+    if ((io_limits.bps[BLOCK_IO_LIMIT_TOTAL] == -1)
+        || (io_limits.bps[BLOCK_IO_LIMIT_READ] == -1)
+        || (io_limits.bps[BLOCK_IO_LIMIT_WRITE] == -1)
+        || (io_limits.iops[BLOCK_IO_LIMIT_TOTAL] == -1)
+        || (io_limits.iops[BLOCK_IO_LIMIT_READ] == -1)
+        || (io_limits.iops[BLOCK_IO_LIMIT_WRITE] == -1)) {
+        qerror_report(QERR_MISSING_PARAMETER,
+                      "bps/bps_rd/bps_wr/iops/iops_rd/iops_wr");
+        return -1;
+    }
+
+    if (!do_check_io_limits(&io_limits)) {
+        qerror_report(QERR_INVALID_PARAMETER_COMBINATION);
+        return -1;
+    }
+
+    bs->io_limits = io_limits;
+    bs->slice_time = BLOCK_IO_SLICE_TIME;
+
+    if (!bs->io_limits_enabled && bdrv_io_limits_enabled(bs)) {
+        bdrv_io_limits_enable(bs);
+    } else if (bs->io_limits_enabled && !bdrv_io_limits_enabled(bs)) {
+        bdrv_io_limits_disable(bs);
+    } else {
+        if (bs->block_timer) {
+            qemu_mod_timer(bs->block_timer, qemu_get_clock_ns(vm_clock));
+        }
+    }
+
+    return 0;
+}
+
 int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     const char *id = qdict_get_str(qdict, "id");
diff --git a/blockdev.h b/blockdev.h
index 3587786..1b48a75 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -63,6 +63,8 @@ int do_block_set_passwd(Monitor *mon, const QDict *qdict, QObject **ret_data);
 int do_change_block(Monitor *mon, const char *device,
                     const char *filename, const char *fmt);
 int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int do_block_set_io_throttle(Monitor *mon,
+                             const QDict *qdict, QObject **ret_data);
 int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data);
 int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 089c1ac..f8d855e 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1207,6 +1207,21 @@ ETEXI
     },
 
 STEXI
+ at item block_set_io_throttle @var{device} @var{bps} @var{bps_rd} @var{bps_wr} @var{iops} @var{iops_rd} @var{iops_wr}
+ at findex block_set_io_throttle
+Change I/O throttle limits for a block drive to @var{bps} @var{bps_rd} @var{bps_wr} @var{iops} @var{iops_rd} @var{iops_wr}
+ETEXI
+
+    {
+        .name       = "block_set_io_throttle",
+        .args_type  = "device:B,bps:l,bps_rd:l,bps_wr:l,iops:l,iops_rd:l,iops_wr:l",
+        .params     = "device bps bps_rd bps_wr iops iops_rd iops_wr",
+        .help       = "change I/O throttle limits for a block drive",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = do_block_set_io_throttle,
+    },
+
+STEXI
 @item block_passwd @var{device} @var{password}
 @findex block_passwd
 Set the encrypted device @var{device} password to @var{password}
diff --git a/hmp.c b/hmp.c
index 443d3a7..dfab7ad 100644
--- a/hmp.c
+++ b/hmp.c
@@ -216,6 +216,16 @@ void hmp_info_block(Monitor *mon)
                            info->value->inserted->ro,
                            info->value->inserted->drv,
                            info->value->inserted->encrypted);
+
+            monitor_printf(mon, " bps=%" PRId64 " bps_rd=%" PRId64
+                            " bps_wr=%" PRId64 " iops=%" PRId64
+                            " iops_rd=%" PRId64 " iops_wr=%" PRId64,
+                            info->value->inserted->bps,
+                            info->value->inserted->bps_rd,
+                            info->value->inserted->bps_wr,
+                            info->value->inserted->iops,
+                            info->value->inserted->iops_rd,
+                            info->value->inserted->iops_wr);
         } else {
             monitor_printf(mon, " [not inserted]");
         }
diff --git a/qapi-schema.json b/qapi-schema.json
index cb1ba77..fbbdbe0 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -370,13 +370,27 @@
 #
 # @encrypted: true if the backing device is encrypted
 #
+# @bps: total throughput limit in bytes per second is specified
+#
+# @bps_rd: read throughput limit in bytes per second is specified
+#
+# @bps_wr: write throughput limit in bytes per second is specified
+#
+# @iops: total I/O operations per second is specified
+#
+# @iops_rd: read I/O operations per second is specified
+#
+# @iops_wr: write I/O operations per second is specified
+#
 # Since: 0.14.0
 #
 # Notes: This interface is only found in @BlockInfo.
 ##
 { 'type': 'BlockDeviceInfo',
   'data': { 'file': 'str', 'ro': 'bool', 'drv': 'str',
-            '*backing_file': 'str', 'encrypted': 'bool' } }
+            '*backing_file': 'str', 'encrypted': 'bool',
+            'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',
+            'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int'} }
 
 ##
 # @BlockDeviceIoStatus:
diff --git a/qerror.c b/qerror.c
index fdf62b9..d679d67 100644
--- a/qerror.c
+++ b/qerror.c
@@ -246,6 +246,10 @@ static const QErrorStringTable qerror_table[] = {
         .error_fmt = QERR_QGA_COMMAND_FAILED,
         .desc      = "Guest agent command failed, error was '%(message)'",
     },
+    {
+        .error_fmt = QERR_INVALID_PARAMETER_COMBINATION,
+        .desc      = "Invalid paramter combination",
+    },
     {}
 };
 
diff --git a/qerror.h b/qerror.h
index 2d3d43b..560d458 100644
--- a/qerror.h
+++ b/qerror.h
@@ -204,4 +204,7 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_QGA_COMMAND_FAILED \
     "{ 'class': 'QgaCommandFailed', 'data': { 'message': %s } }"
 
+#define QERR_INVALID_PARAMETER_COMBINATION \
+    "{ 'class': 'InvalidParameterCombination', 'data': {} }"
+
 #endif /* QERROR_H */
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 97975a5..94da2a8 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -851,6 +851,44 @@ Example:
 EQMP
 
     {
+        .name       = "block_set_io_throttle",
+        .args_type  = "device:B,bps:l,bps_rd:l,bps_wr:l,iops:l,iops_rd:l,iops_wr:l",
+        .params     = "device bps bps_rd bps_wr iops iops_rd iops_wr",
+        .help       = "change I/O throttle limits for a block drive",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = do_block_set_io_throttle,
+    },
+
+SQMP
+block_set_io_throttle
+------------
+
+Change I/O throttle limits for a block drive.
+
+Arguments:
+
+- "device": device name (json-string)
+- "bps":  total throughput limit in bytes per second(json-int)
+- "bps_rd":  read throughput limit in bytes per second(json-int)
+- "bps_wr":  read throughput limit in bytes per second(json-int)
+- "iops":  total I/O operations per second(json-int)
+- "iops_rd":  read I/O operations per second(json-int)
+- "iops_wr":  write I/O operations per second(json-int)
+
+Example:
+
+-> { "execute": "block_set_io_throttle", "arguments": { "device": "virtio0",
+                                               "bps": "1000000",
+                                               "bps_rd": "0",
+                                               "bps_wr": "0",
+                                               "iops": "0",
+                                               "iops_rd": "0",
+                                               "iops_wr": "0" } }
+<- { "return": {} }
+
+EQMP
+
+    {
         .name       = "set_password",
         .args_type  = "protocol:s,password:s,connected:s?",
         .params     = "protocol password action-if-connected",
@@ -1152,6 +1190,13 @@ Each json-object contain the following:
                                 "tftp", "vdi", "vmdk", "vpc", "vvfat"
          - "backing_file": backing file name (json-string, optional)
          - "encrypted": true if encrypted, false otherwise (json-bool)
+         - "bps": limit total bytes per second (json-int)
+         - "bps_rd": limit read bytes per second (json-int)
+         - "bps_wr": limit write bytes per second (json-int)
+         - "iops": limit total I/O operations per second (json-int)
+         - "iops_rd": limit read operations per second (json-int)
+         - "iops_wr": limit write operations per second (json-int)
+
 - "io-status": I/O operation status, only present if the device supports it
                and the VM is configured to stop on errors. It's always reset
                to "ok" when the "cont" command is issued (json_string, optional)
@@ -1171,7 +1216,13 @@ Example:
                "ro":false,
                "drv":"qcow2",
                "encrypted":false,
-               "file":"disks/test.img"
+               "file":"disks/test.img",
+               "bps":1000000,
+               "bps_rd":0,
+               "bps_wr":0,
+               "iops":1000000,
+               "iops_rd":0,
+               "iops_wr":0,
             },
             "type":"unknown"
          },
commit 98f90dba5ee56f699b28509a6cc7a9a8a57636eb
Author: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
Date:   Tue Nov 8 13:00:14 2011 +0800

    block: add I/O throttling algorithm
    
    Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.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 8cb41c0..42bd308 100644
--- a/block.c
+++ b/block.c
@@ -74,6 +74,13 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
                                                bool is_write);
 static void coroutine_fn bdrv_co_do_rw(void *opaque);
 
+static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors,
+        bool is_write, double elapsed_time, uint64_t *wait);
+static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write,
+        double elapsed_time, uint64_t *wait);
+static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors,
+        bool is_write, int64_t *wait);
+
 static QTAILQ_HEAD(, BlockDriverState) bdrv_states =
     QTAILQ_HEAD_INITIALIZER(bdrv_states);
 
@@ -107,6 +114,24 @@ int is_windows_drive(const char *filename)
 #endif
 
 /* throttling disk I/O limits */
+void bdrv_io_limits_disable(BlockDriverState *bs)
+{
+    bs->io_limits_enabled = false;
+
+    while (qemu_co_queue_next(&bs->throttled_reqs));
+
+    if (bs->block_timer) {
+        qemu_del_timer(bs->block_timer);
+        qemu_free_timer(bs->block_timer);
+        bs->block_timer = NULL;
+    }
+
+    bs->slice_start = 0;
+    bs->slice_end   = 0;
+    bs->slice_time  = 0;
+    memset(&bs->io_base, 0, sizeof(bs->io_base));
+}
+
 static void bdrv_block_timer(void *opaque)
 {
     BlockDriverState *bs = opaque;
@@ -136,6 +161,31 @@ bool bdrv_io_limits_enabled(BlockDriverState *bs)
          || io_limits->iops[BLOCK_IO_LIMIT_TOTAL];
 }
 
+static void bdrv_io_limits_intercept(BlockDriverState *bs,
+                                     bool is_write, int nb_sectors)
+{
+    int64_t wait_time = -1;
+
+    if (!qemu_co_queue_empty(&bs->throttled_reqs)) {
+        qemu_co_queue_wait(&bs->throttled_reqs);
+    }
+
+    /* In fact, we hope to keep each request's timing, in FIFO mode. The next
+     * throttled requests will not be dequeued until the current request is
+     * allowed to be serviced. So if the current request still exceeds the
+     * limits, it will be inserted to the head. All requests followed it will
+     * be still in throttled_reqs queue.
+     */
+
+    while (bdrv_exceed_io_limits(bs, nb_sectors, is_write, &wait_time)) {
+        qemu_mod_timer(bs->block_timer,
+                       wait_time + qemu_get_clock_ns(vm_clock));
+        qemu_co_queue_wait_insert_head(&bs->throttled_reqs);
+    }
+
+    qemu_co_queue_next(&bs->throttled_reqs);
+}
+
 /* check if the path starts with "<protocol>:" */
 static int path_has_protocol(const char *path)
 {
@@ -718,6 +768,11 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
         bdrv_dev_change_media_cb(bs, true);
     }
 
+    /* throttling disk I/O limits */
+    if (bs->io_limits_enabled) {
+        bdrv_io_limits_enable(bs);
+    }
+
     return 0;
 
 unlink_and_fail:
@@ -753,6 +808,11 @@ void bdrv_close(BlockDriverState *bs)
 
         bdrv_dev_change_media_cb(bs, false);
     }
+
+    /*throttling disk I/O limits*/
+    if (bs->io_limits_enabled) {
+        bdrv_io_limits_disable(bs);
+    }
 }
 
 void bdrv_close_all(void)
@@ -1298,6 +1358,11 @@ static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs,
         return -EIO;
     }
 
+    /* throttling disk read I/O */
+    if (bs->io_limits_enabled) {
+        bdrv_io_limits_intercept(bs, false, nb_sectors);
+    }
+
     return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
 }
 
@@ -1328,6 +1393,11 @@ static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs,
         return -EIO;
     }
 
+    /* throttling disk write I/O */
+    if (bs->io_limits_enabled) {
+        bdrv_io_limits_intercept(bs, true, nb_sectors);
+    }
+
     ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov);
 
     if (bs->dirty_bitmap) {
@@ -2519,6 +2589,170 @@ void bdrv_aio_cancel(BlockDriverAIOCB *acb)
     acb->pool->cancel(acb);
 }
 
+/* block I/O throttling */
+static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors,
+                 bool is_write, double elapsed_time, uint64_t *wait)
+{
+    uint64_t bps_limit = 0;
+    double   bytes_limit, bytes_base, bytes_res;
+    double   slice_time, wait_time;
+
+    if (bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL]) {
+        bps_limit = bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL];
+    } else if (bs->io_limits.bps[is_write]) {
+        bps_limit = bs->io_limits.bps[is_write];
+    } else {
+        if (wait) {
+            *wait = 0;
+        }
+
+        return false;
+    }
+
+    slice_time = bs->slice_end - bs->slice_start;
+    slice_time /= (NANOSECONDS_PER_SECOND);
+    bytes_limit = bps_limit * slice_time;
+    bytes_base  = bs->nr_bytes[is_write] - bs->io_base.bytes[is_write];
+    if (bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL]) {
+        bytes_base += bs->nr_bytes[!is_write] - bs->io_base.bytes[!is_write];
+    }
+
+    /* bytes_base: the bytes of data which have been read/written; and
+     *             it is obtained from the history statistic info.
+     * bytes_res: the remaining bytes of data which need to be read/written.
+     * (bytes_base + bytes_res) / bps_limit: used to calcuate
+     *             the total time for completing reading/writting all data.
+     */
+    bytes_res   = (unsigned) nb_sectors * BDRV_SECTOR_SIZE;
+
+    if (bytes_base + bytes_res <= bytes_limit) {
+        if (wait) {
+            *wait = 0;
+        }
+
+        return false;
+    }
+
+    /* Calc approx time to dispatch */
+    wait_time = (bytes_base + bytes_res) / bps_limit - elapsed_time;
+
+    /* When the I/O rate at runtime exceeds the limits,
+     * bs->slice_end need to be extended in order that the current statistic
+     * info can be kept until the timer fire, so it is increased and tuned
+     * based on the result of experiment.
+     */
+    bs->slice_time = wait_time * BLOCK_IO_SLICE_TIME * 10;
+    bs->slice_end += bs->slice_time - 3 * BLOCK_IO_SLICE_TIME;
+    if (wait) {
+        *wait = wait_time * BLOCK_IO_SLICE_TIME * 10;
+    }
+
+    return true;
+}
+
+static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write,
+                             double elapsed_time, uint64_t *wait)
+{
+    uint64_t iops_limit = 0;
+    double   ios_limit, ios_base;
+    double   slice_time, wait_time;
+
+    if (bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL]) {
+        iops_limit = bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL];
+    } else if (bs->io_limits.iops[is_write]) {
+        iops_limit = bs->io_limits.iops[is_write];
+    } else {
+        if (wait) {
+            *wait = 0;
+        }
+
+        return false;
+    }
+
+    slice_time = bs->slice_end - bs->slice_start;
+    slice_time /= (NANOSECONDS_PER_SECOND);
+    ios_limit  = iops_limit * slice_time;
+    ios_base   = bs->nr_ops[is_write] - bs->io_base.ios[is_write];
+    if (bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL]) {
+        ios_base += bs->nr_ops[!is_write] - bs->io_base.ios[!is_write];
+    }
+
+    if (ios_base + 1 <= ios_limit) {
+        if (wait) {
+            *wait = 0;
+        }
+
+        return false;
+    }
+
+    /* Calc approx time to dispatch */
+    wait_time = (ios_base + 1) / iops_limit;
+    if (wait_time > elapsed_time) {
+        wait_time = wait_time - elapsed_time;
+    } else {
+        wait_time = 0;
+    }
+
+    bs->slice_time = wait_time * BLOCK_IO_SLICE_TIME * 10;
+    bs->slice_end += bs->slice_time - 3 * BLOCK_IO_SLICE_TIME;
+    if (wait) {
+        *wait = wait_time * BLOCK_IO_SLICE_TIME * 10;
+    }
+
+    return true;
+}
+
+static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors,
+                           bool is_write, int64_t *wait)
+{
+    int64_t  now, max_wait;
+    uint64_t bps_wait = 0, iops_wait = 0;
+    double   elapsed_time;
+    int      bps_ret, iops_ret;
+
+    now = qemu_get_clock_ns(vm_clock);
+    if ((bs->slice_start < now)
+        && (bs->slice_end > now)) {
+        bs->slice_end = now + bs->slice_time;
+    } else {
+        bs->slice_time  =  5 * BLOCK_IO_SLICE_TIME;
+        bs->slice_start = now;
+        bs->slice_end   = now + bs->slice_time;
+
+        bs->io_base.bytes[is_write]  = bs->nr_bytes[is_write];
+        bs->io_base.bytes[!is_write] = bs->nr_bytes[!is_write];
+
+        bs->io_base.ios[is_write]    = bs->nr_ops[is_write];
+        bs->io_base.ios[!is_write]   = bs->nr_ops[!is_write];
+    }
+
+    elapsed_time  = now - bs->slice_start;
+    elapsed_time  /= (NANOSECONDS_PER_SECOND);
+
+    bps_ret  = bdrv_exceed_bps_limits(bs, nb_sectors,
+                                      is_write, elapsed_time, &bps_wait);
+    iops_ret = bdrv_exceed_iops_limits(bs, is_write,
+                                      elapsed_time, &iops_wait);
+    if (bps_ret || iops_ret) {
+        max_wait = bps_wait > iops_wait ? bps_wait : iops_wait;
+        if (wait) {
+            *wait = max_wait;
+        }
+
+        now = qemu_get_clock_ns(vm_clock);
+        if (bs->slice_end < now + max_wait) {
+            bs->slice_end = now + max_wait;
+        }
+
+        return true;
+    }
+
+    if (wait) {
+        *wait = 0;
+    }
+
+    return false;
+}
 
 /**************************************************************/
 /* async block device emulation */
diff --git a/block.h b/block.h
index 2d24408..83e17ca 100644
--- a/block.h
+++ b/block.h
@@ -100,6 +100,7 @@ void bdrv_info_stats(Monitor *mon, QObject **ret_data);
 
 /* disk I/O throttling */
 void bdrv_io_limits_enable(BlockDriverState *bs);
+void bdrv_io_limits_disable(BlockDriverState *bs);
 bool bdrv_io_limits_enabled(BlockDriverState *bs);
 
 void bdrv_init(void);
diff --git a/block_int.h b/block_int.h
index 97b1c2b..e2799e4 100644
--- a/block_int.h
+++ b/block_int.h
@@ -39,6 +39,7 @@
 #define BLOCK_IO_LIMIT_TOTAL    2
 
 #define BLOCK_IO_SLICE_TIME     100000000
+#define NANOSECONDS_PER_SECOND  1000000000.0
 
 #define BLOCK_OPT_SIZE          "size"
 #define BLOCK_OPT_ENCRYPT       "encryption"
commit e9e6295b28b331762e67d466f77ba07a349edbbc
Author: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
Date:   Thu Nov 3 16:57:26 2011 +0800

    CoQueue: introduce qemu_co_queue_wait_insert_head
    
    Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c
index 6b58160..9549c07 100644
--- a/qemu-coroutine-lock.c
+++ b/qemu-coroutine-lock.c
@@ -61,6 +61,14 @@ void coroutine_fn qemu_co_queue_wait(CoQueue *queue)
     assert(qemu_in_coroutine());
 }
 
+void coroutine_fn qemu_co_queue_wait_insert_head(CoQueue *queue)
+{
+    Coroutine *self = qemu_coroutine_self();
+    QTAILQ_INSERT_HEAD(&queue->entries, self, co_queue_next);
+    qemu_coroutine_yield();
+    assert(qemu_in_coroutine());
+}
+
 bool qemu_co_queue_next(CoQueue *queue)
 {
     Coroutine *next;
diff --git a/qemu-coroutine.h b/qemu-coroutine.h
index b8fc4f4..8a2e5d2 100644
--- a/qemu-coroutine.h
+++ b/qemu-coroutine.h
@@ -118,6 +118,12 @@ void qemu_co_queue_init(CoQueue *queue);
 void coroutine_fn qemu_co_queue_wait(CoQueue *queue);
 
 /**
+ * Adds the current coroutine to the head of the CoQueue and transfers control to the
+ * caller of the coroutine.
+ */
+void coroutine_fn qemu_co_queue_wait_insert_head(CoQueue *queue);
+
+/**
  * Restarts the next coroutine in the CoQueue and removes it from the queue.
  *
  * Returns true if a coroutine was restarted, false if the queue is empty.
commit 0563e191516289c9d2f282a8c50f2eecef2fa773
Author: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
Date:   Thu Nov 3 16:57:25 2011 +0800

    block: add the blockio limits command line support
    
    Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.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 d015887..8cb41c0 100644
--- a/block.c
+++ b/block.c
@@ -30,6 +30,7 @@
 #include "qjson.h"
 #include "qemu-coroutine.h"
 #include "qmp-commands.h"
+#include "qemu-timer.h"
 
 #ifdef CONFIG_BSD
 #include <sys/types.h>
@@ -105,6 +106,36 @@ int is_windows_drive(const char *filename)
 }
 #endif
 
+/* throttling disk I/O limits */
+static void bdrv_block_timer(void *opaque)
+{
+    BlockDriverState *bs = opaque;
+
+    qemu_co_queue_next(&bs->throttled_reqs);
+}
+
+void bdrv_io_limits_enable(BlockDriverState *bs)
+{
+    qemu_co_queue_init(&bs->throttled_reqs);
+    bs->block_timer = qemu_new_timer_ns(vm_clock, bdrv_block_timer, bs);
+    bs->slice_time  = 5 * BLOCK_IO_SLICE_TIME;
+    bs->slice_start = qemu_get_clock_ns(vm_clock);
+    bs->slice_end   = bs->slice_start + bs->slice_time;
+    memset(&bs->io_base, 0, sizeof(bs->io_base));
+    bs->io_limits_enabled = true;
+}
+
+bool bdrv_io_limits_enabled(BlockDriverState *bs)
+{
+    BlockIOLimit *io_limits = &bs->io_limits;
+    return io_limits->bps[BLOCK_IO_LIMIT_READ]
+         || io_limits->bps[BLOCK_IO_LIMIT_WRITE]
+         || io_limits->bps[BLOCK_IO_LIMIT_TOTAL]
+         || io_limits->iops[BLOCK_IO_LIMIT_READ]
+         || io_limits->iops[BLOCK_IO_LIMIT_WRITE]
+         || io_limits->iops[BLOCK_IO_LIMIT_TOTAL];
+}
+
 /* check if the path starts with "<protocol>:" */
 static int path_has_protocol(const char *path)
 {
@@ -1526,6 +1557,14 @@ void bdrv_get_geometry_hint(BlockDriverState *bs,
     *psecs = bs->secs;
 }
 
+/* throttling disk io limits */
+void bdrv_set_io_limits(BlockDriverState *bs,
+                        BlockIOLimit *io_limits)
+{
+    bs->io_limits = *io_limits;
+    bs->io_limits_enabled = bdrv_io_limits_enabled(bs);
+}
+
 /* Recognize floppy formats */
 typedef struct FDFormat {
     FDriveType drive;
diff --git a/block.h b/block.h
index a826059..2d24408 100644
--- a/block.h
+++ b/block.h
@@ -98,6 +98,10 @@ void bdrv_info(Monitor *mon, QObject **ret_data);
 void bdrv_stats_print(Monitor *mon, const QObject *data);
 void bdrv_info_stats(Monitor *mon, QObject **ret_data);
 
+/* disk I/O throttling */
+void bdrv_io_limits_enable(BlockDriverState *bs);
+bool bdrv_io_limits_enabled(BlockDriverState *bs);
+
 void bdrv_init(void);
 void bdrv_init_with_whitelist(void);
 BlockDriver *bdrv_find_protocol(const char *filename);
diff --git a/block_int.h b/block_int.h
index 77c0187..97b1c2b 100644
--- a/block_int.h
+++ b/block_int.h
@@ -34,6 +34,12 @@
 #define BLOCK_FLAG_ENCRYPT	1
 #define BLOCK_FLAG_COMPAT6	4
 
+#define BLOCK_IO_LIMIT_READ     0
+#define BLOCK_IO_LIMIT_WRITE    1
+#define BLOCK_IO_LIMIT_TOTAL    2
+
+#define BLOCK_IO_SLICE_TIME     100000000
+
 #define BLOCK_OPT_SIZE          "size"
 #define BLOCK_OPT_ENCRYPT       "encryption"
 #define BLOCK_OPT_COMPAT6       "compat6"
@@ -50,6 +56,16 @@ typedef struct AIOPool {
     BlockDriverAIOCB *free_aiocb;
 } AIOPool;
 
+typedef struct BlockIOLimit {
+    int64_t bps[3];
+    int64_t iops[3];
+} BlockIOLimit;
+
+typedef struct BlockIOBaseValue {
+    uint64_t bytes[2];
+    uint64_t ios[2];
+} BlockIOBaseValue;
+
 struct BlockDriver {
     const char *format_name;
     int instance_size;
@@ -201,6 +217,16 @@ struct BlockDriverState {
 
     void *sync_aiocb;
 
+    /* the time for latest disk I/O */
+    int64_t slice_time;
+    int64_t slice_start;
+    int64_t slice_end;
+    BlockIOLimit io_limits;
+    BlockIOBaseValue  io_base;
+    CoQueue      throttled_reqs;
+    QEMUTimer    *block_timer;
+    bool         io_limits_enabled;
+
     /* I/O stats (display with "info blockstats"). */
     uint64_t nr_bytes[BDRV_MAX_IOTYPE];
     uint64_t nr_ops[BDRV_MAX_IOTYPE];
@@ -244,6 +270,9 @@ void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
                    BlockDriverCompletionFunc *cb, void *opaque);
 void qemu_aio_release(void *p);
 
+void bdrv_set_io_limits(BlockDriverState *bs,
+                        BlockIOLimit *io_limits);
+
 #ifdef _WIN32
 int is_windows_drive(const char *filename);
 #endif
diff --git a/blockdev.c b/blockdev.c
index 2228186..bbe5f11 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -216,6 +216,26 @@ static int parse_block_error_action(const char *buf, int is_read)
     }
 }
 
+static bool do_check_io_limits(BlockIOLimit *io_limits)
+{
+    bool bps_flag;
+    bool iops_flag;
+
+    assert(io_limits);
+
+    bps_flag  = (io_limits->bps[BLOCK_IO_LIMIT_TOTAL] != 0)
+                 && ((io_limits->bps[BLOCK_IO_LIMIT_READ] != 0)
+                 || (io_limits->bps[BLOCK_IO_LIMIT_WRITE] != 0));
+    iops_flag = (io_limits->iops[BLOCK_IO_LIMIT_TOTAL] != 0)
+                 && ((io_limits->iops[BLOCK_IO_LIMIT_READ] != 0)
+                 || (io_limits->iops[BLOCK_IO_LIMIT_WRITE] != 0));
+    if (bps_flag || iops_flag) {
+        return false;
+    }
+
+    return true;
+}
+
 DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
 {
     const char *buf;
@@ -235,6 +255,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
     int on_read_error, on_write_error;
     const char *devaddr;
     DriveInfo *dinfo;
+    BlockIOLimit io_limits;
     int snapshot = 0;
     int ret;
 
@@ -353,6 +374,26 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
         }
     }
 
+    /* disk I/O throttling */
+    io_limits.bps[BLOCK_IO_LIMIT_TOTAL]  =
+                           qemu_opt_get_number(opts, "bps", 0);
+    io_limits.bps[BLOCK_IO_LIMIT_READ]   =
+                           qemu_opt_get_number(opts, "bps_rd", 0);
+    io_limits.bps[BLOCK_IO_LIMIT_WRITE]  =
+                           qemu_opt_get_number(opts, "bps_wr", 0);
+    io_limits.iops[BLOCK_IO_LIMIT_TOTAL] =
+                           qemu_opt_get_number(opts, "iops", 0);
+    io_limits.iops[BLOCK_IO_LIMIT_READ]  =
+                           qemu_opt_get_number(opts, "iops_rd", 0);
+    io_limits.iops[BLOCK_IO_LIMIT_WRITE] =
+                           qemu_opt_get_number(opts, "iops_wr", 0);
+
+    if (!do_check_io_limits(&io_limits)) {
+        error_report("bps(iops) and bps_rd/bps_wr(iops_rd/iops_wr) "
+                     "cannot be used at the same time");
+        return NULL;
+    }
+
     on_write_error = BLOCK_ERR_STOP_ENOSPC;
     if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
         if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
@@ -460,6 +501,9 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
 
     bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
 
+    /* disk I/O throttling */
+    bdrv_set_io_limits(dinfo->bdrv, &io_limits);
+
     switch(type) {
     case IF_IDE:
     case IF_SCSI:
diff --git a/qemu-config.c b/qemu-config.c
index 597d7e1..1aa080f 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -85,6 +85,30 @@ static QemuOptsList qemu_drive_opts = {
             .name = "readonly",
             .type = QEMU_OPT_BOOL,
             .help = "open drive file as read-only",
+        },{
+            .name = "iops",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit total I/O operations per second",
+        },{
+            .name = "iops_rd",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit read operations per second",
+        },{
+            .name = "iops_wr",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit write operations per second",
+        },{
+            .name = "bps",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit total bytes per second",
+        },{
+            .name = "bps_rd",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit read bytes per second",
+        },{
+            .name = "bps_wr",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit write bytes per second",
         },
         { /* end of list */ }
     },
diff --git a/qemu-options.hx b/qemu-options.hx
index 681eaf1..25a7be7 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -136,6 +136,7 @@ DEF("drive", HAS_ARG, QEMU_OPTION_drive,
     "       [,cache=writethrough|writeback|none|directsync|unsafe][,format=f]\n"
     "       [,serial=s][,addr=A][,id=name][,aio=threads|native]\n"
     "       [,readonly=on|off]\n"
+    "       [[,bps=b]|[[,bps_rd=r][,bps_wr=w]]][[,iops=i]|[[,iops_rd=r][,iops_wr=w]]\n"
     "                use 'file' as a drive image\n", QEMU_ARCH_ALL)
 STEXI
 @item -drive @var{option}[, at var{option}[, at var{option}[,...]]]
commit 3535a9c6bef5234ab4df3f143763a0e89a1ad29c
Author: Li Zhi Hui <zhihuili at linux.vnet.ibm.com>
Date:   Tue Nov 8 14:21:13 2011 +0800

    block: Use bdrv functions to replace file operation in cow.c
    
    Since common file operation functions lack of error detection,
    so change them to bdrv series functions.
    
    Signed-off-by: Li Zhi Hui <zhihuili at linux.vnet.ibm.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/cow.c b/block/cow.c
index 089d395..9858d71 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -243,12 +243,12 @@ static void cow_close(BlockDriverState *bs)
 
 static int cow_create(const char *filename, QEMUOptionParameter *options)
 {
-    int fd, cow_fd;
     struct cow_header_v2 cow_header;
     struct stat st;
     int64_t image_sectors = 0;
     const char *image_filename = NULL;
     int ret;
+    BlockDriverState *cow_bs;
 
     /* Read out options */
     while (options && options->name) {
@@ -260,10 +260,16 @@ static int cow_create(const char *filename, QEMUOptionParameter *options)
         options++;
     }
 
-    cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
-              0644);
-    if (cow_fd < 0)
-        return -errno;
+    ret = bdrv_create_file(filename, options);
+    if (ret < 0) {
+        return ret;
+    }
+
+    ret = bdrv_file_open(&cow_bs, filename, BDRV_O_RDWR);
+    if (ret < 0) {
+        return ret;
+    }
+
     memset(&cow_header, 0, sizeof(cow_header));
     cow_header.magic = cpu_to_be32(COW_MAGIC);
     cow_header.version = cpu_to_be32(COW_VERSION);
@@ -271,16 +277,9 @@ static int cow_create(const char *filename, QEMUOptionParameter *options)
         /* Note: if no file, we put a dummy mtime */
         cow_header.mtime = cpu_to_be32(0);
 
-        fd = open(image_filename, O_RDONLY | O_BINARY);
-        if (fd < 0) {
-            close(cow_fd);
-            goto mtime_fail;
-        }
-        if (fstat(fd, &st) != 0) {
-            close(fd);
+        if (stat(image_filename, &st) != 0) {
             goto mtime_fail;
         }
-        close(fd);
         cow_header.mtime = cpu_to_be32(st.st_mtime);
     mtime_fail:
         pstrcpy(cow_header.backing_file, sizeof(cow_header.backing_file),
@@ -288,21 +287,20 @@ static int cow_create(const char *filename, QEMUOptionParameter *options)
     }
     cow_header.sectorsize = cpu_to_be32(512);
     cow_header.size = cpu_to_be64(image_sectors * 512);
-    ret = qemu_write_full(cow_fd, &cow_header, sizeof(cow_header));
+    ret = bdrv_pwrite(cow_bs, 0, &cow_header, sizeof(cow_header));
     if (ret != sizeof(cow_header)) {
-        ret = -errno;
         goto exit;
     }
 
     /* resize to include at least all the bitmap */
-    ret = ftruncate(cow_fd, sizeof(cow_header) + ((image_sectors + 7) >> 3));
+    ret = bdrv_truncate(cow_bs,
+        sizeof(cow_header) + ((image_sectors + 7) >> 3));
     if (ret) {
-        ret = -errno;
         goto exit;
     }
 
 exit:
-    close(cow_fd);
+    bdrv_delete(cow_bs);
     return ret;
 }
 
commit 4e5b184d63b5f031800c3ac215eebac126b1ab31
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Oct 28 18:03:58 2011 +0200

    xen_disk: remove dead code
    
    Xen_disk.c has support for using synchronous I/O instead of asynchronous,
    but it is compiled out by default.  Remove it.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 286bbac..192e817 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -49,7 +49,6 @@ static int syncwrite    = 0;
 static int batch_maps   = 0;
 
 static int max_requests = 32;
-static int use_aio      = 1;
 
 /* ------------------------------------------------------------- */
 
@@ -314,76 +313,6 @@ static int ioreq_map(struct ioreq *ioreq)
     return 0;
 }
 
-static int ioreq_runio_qemu_sync(struct ioreq *ioreq)
-{
-    struct XenBlkDev *blkdev = ioreq->blkdev;
-    int i, rc;
-    off_t pos;
-
-    if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1) {
-        goto err_no_map;
-    }
-    if (ioreq->presync) {
-        bdrv_flush(blkdev->bs);
-    }
-
-    switch (ioreq->req.operation) {
-    case BLKIF_OP_READ:
-        pos = ioreq->start;
-        for (i = 0; i < ioreq->v.niov; i++) {
-            rc = bdrv_read(blkdev->bs, pos / BLOCK_SIZE,
-                           ioreq->v.iov[i].iov_base,
-                           ioreq->v.iov[i].iov_len / BLOCK_SIZE);
-            if (rc != 0) {
-                xen_be_printf(&blkdev->xendev, 0, "rd I/O error (%p, len %zd)\n",
-                              ioreq->v.iov[i].iov_base,
-                              ioreq->v.iov[i].iov_len);
-                goto err;
-            }
-            pos += ioreq->v.iov[i].iov_len;
-        }
-        break;
-    case BLKIF_OP_WRITE:
-    case BLKIF_OP_WRITE_BARRIER:
-        if (!ioreq->req.nr_segments) {
-            break;
-        }
-        pos = ioreq->start;
-        for (i = 0; i < ioreq->v.niov; i++) {
-            rc = bdrv_write(blkdev->bs, pos / BLOCK_SIZE,
-                            ioreq->v.iov[i].iov_base,
-                            ioreq->v.iov[i].iov_len / BLOCK_SIZE);
-            if (rc != 0) {
-                xen_be_printf(&blkdev->xendev, 0, "wr I/O error (%p, len %zd)\n",
-                              ioreq->v.iov[i].iov_base,
-                              ioreq->v.iov[i].iov_len);
-                goto err;
-            }
-            pos += ioreq->v.iov[i].iov_len;
-        }
-        break;
-    default:
-        /* unknown operation (shouldn't happen -- parse catches this) */
-        goto err;
-    }
-
-    if (ioreq->postsync) {
-        bdrv_flush(blkdev->bs);
-    }
-    ioreq->status = BLKIF_RSP_OKAY;
-
-    ioreq_unmap(ioreq);
-    ioreq_finish(ioreq);
-    return 0;
-
-err:
-    ioreq_unmap(ioreq);
-err_no_map:
-    ioreq_finish(ioreq);
-    ioreq->status = BLKIF_RSP_ERROR;
-    return -1;
-}
-
 static void qemu_aio_complete(void *opaque, int ret)
 {
     struct ioreq *ioreq = opaque;
@@ -554,9 +483,7 @@ static void blk_handle_requests(struct XenBlkDev *blkdev)
     rp = blkdev->rings.common.sring->req_prod;
     xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
 
-    if (use_aio) {
-        blk_send_response_all(blkdev);
-    }
+    blk_send_response_all(blkdev);
     while (rc != rp) {
         /* pull request from ring */
         if (RING_REQUEST_CONS_OVERFLOW(&blkdev->rings.common, rc)) {
@@ -579,16 +506,7 @@ static void blk_handle_requests(struct XenBlkDev *blkdev)
             continue;
         }
 
-        if (use_aio) {
-            /* run i/o in aio mode */
-            ioreq_runio_qemu_aio(ioreq);
-        } else {
-            /* run i/o in sync mode */
-            ioreq_runio_qemu_sync(ioreq);
-        }
-    }
-    if (!use_aio) {
-        blk_send_response_all(blkdev);
+        ioreq_runio_qemu_aio(ioreq);
     }
 
     if (blkdev->more_work && blkdev->requests_inflight < max_requests) {
commit 23e9a39e7db60a8cbe4ac1291d4f4feab08930ce
Author: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
Date:   Tue Nov 1 16:04:32 2011 +0800

    qed: adjust the way to get nb_sectors
    
    This patch is only to refactor some lines of codes to get better and more robust codes.
    
    As you have seen, in qed_read_table_cb() it's nice to
    use qiov->size because that function doesn't obviously use a single
    struct iovec.
    
    In other two functions, if qiov use more than one struct iovec, the existing way will get wrong nb_sectors.
    To make the code more robust, it will be nicer to refactor the existing way as below.
    
    Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
    Acked-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qed-table.c b/block/qed-table.c
index f31f9ff..8ee8443 100644
--- a/block/qed-table.c
+++ b/block/qed-table.c
@@ -29,7 +29,7 @@ static void qed_read_table_cb(void *opaque, int ret)
 {
     QEDReadTableCB *read_table_cb = opaque;
     QEDTable *table = read_table_cb->table;
-    int noffsets = read_table_cb->iov.iov_len / sizeof(uint64_t);
+    int noffsets = read_table_cb->qiov.size / sizeof(uint64_t);
     int i;
 
     /* Handle I/O error */
@@ -65,7 +65,7 @@ static void qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
 
     qemu_iovec_init_external(qiov, &read_table_cb->iov, 1);
     aiocb = bdrv_aio_readv(s->bs->file, offset / BDRV_SECTOR_SIZE, qiov,
-                           read_table_cb->iov.iov_len / BDRV_SECTOR_SIZE,
+                           qiov->size / BDRV_SECTOR_SIZE,
                            qed_read_table_cb, read_table_cb);
     if (!aiocb) {
         qed_read_table_cb(read_table_cb, -EIO);
@@ -160,7 +160,7 @@ static void qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
 
     aiocb = bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE,
                             &write_table_cb->qiov,
-                            write_table_cb->iov.iov_len / BDRV_SECTOR_SIZE,
+                            write_table_cb->qiov.size / BDRV_SECTOR_SIZE,
                             qed_write_table_cb, write_table_cb);
     if (!aiocb) {
         qed_write_table_cb(write_table_cb, -EIO);
commit aef4acb6616ab7fb5c105660aa8a2cee4e250e75
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Nov 30 12:23:41 2011 +0000

    qcow2: avoid reentrant bdrv_read() in copy_sectors()
    
    A BlockDriverState should not issue requests on itself through the
    public block layer interface.  Nested, or reentrant, requests are
    problematic because they do I/O throttling and request tracking twice.
    
    Features like block layer copy-on-read use request tracking to avoid
    race conditions between concurrent requests.  The reentrant request will
    have to "wait" for its parent request to complete.  But the parent is
    waiting for the reentrant request to make progress so we have reached
    deadlock.
    
    The solution is for block drivers to avoid the public block layer
    interfaces for reentrant requests.   Instead they should call their own
    internal functions if they wish to perform reentrant requests.
    
    This is also a good opportunity to make copy_sectors() a true
    coroutine_fn.  That means calling bdrv_co_writev() instead of
    bdrv_write().  Behavior is unchanged but we're being explicit that this
    executes in coroutine context.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 0e33707..07a2e93 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -289,12 +289,15 @@ void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
     }
 }
 
-static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
-                        uint64_t cluster_offset, int n_start, int n_end)
+static int coroutine_fn copy_sectors(BlockDriverState *bs,
+                                     uint64_t start_sect,
+                                     uint64_t cluster_offset,
+                                     int n_start, int n_end)
 {
     BDRVQcowState *s = bs->opaque;
+    QEMUIOVector qiov;
+    struct iovec iov;
     int n, ret;
-    void *buf;
 
     /*
      * If this is the last cluster and it is only partially used, we must only
@@ -310,29 +313,37 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
         return 0;
     }
 
-    buf = qemu_blockalign(bs, n * BDRV_SECTOR_SIZE);
+    iov.iov_len = n * BDRV_SECTOR_SIZE;
+    iov.iov_base = qemu_blockalign(bs, iov.iov_len);
+
+    qemu_iovec_init_external(&qiov, &iov, 1);
 
     BLKDBG_EVENT(bs->file, BLKDBG_COW_READ);
-    ret = bdrv_read(bs, start_sect + n_start, buf, n);
+
+    /* Call .bdrv_co_readv() directly instead of using the public block-layer
+     * interface.  This avoids double I/O throttling and request tracking,
+     * which can lead to deadlock when block layer copy-on-read is enabled.
+     */
+    ret = bs->drv->bdrv_co_readv(bs, start_sect + n_start, n, &qiov);
     if (ret < 0) {
         goto out;
     }
 
     if (s->crypt_method) {
         qcow2_encrypt_sectors(s, start_sect + n_start,
-                        buf, buf, n, 1,
+                        iov.iov_base, iov.iov_base, n, 1,
                         &s->aes_encrypt_key);
     }
 
     BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE);
-    ret = bdrv_write(bs->file, (cluster_offset >> 9) + n_start, buf, n);
+    ret = bdrv_co_writev(bs->file, (cluster_offset >> 9) + n_start, n, &qiov);
     if (ret < 0) {
         goto out;
     }
 
     ret = 0;
 out:
-    qemu_vfree(buf);
+    qemu_vfree(iov.iov_base);
     return ret;
 }
 
commit 1b9f1491f82de0c8f9b09d1a06ac33304449a634
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Sep 19 11:26:48 2011 +0200

    qcow2: Unlock during COW
    
    Unlocking during COW allows for more parallelism. One change it requires is
    that buffers are dynamically allocated instead of just using a per-image
    buffer.
    
    While touching the code, drop the synchronous qcow2_read() function and replace
    it by a bdrv_read() call.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index f4e049f..0e33707 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -289,89 +289,51 @@ void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
     }
 }
 
-
-static int qcow2_read(BlockDriverState *bs, int64_t sector_num,
-                      uint8_t *buf, int nb_sectors)
-{
-    BDRVQcowState *s = bs->opaque;
-    int ret, index_in_cluster, n, n1;
-    uint64_t cluster_offset;
-    struct iovec iov;
-    QEMUIOVector qiov;
-
-    while (nb_sectors > 0) {
-        n = nb_sectors;
-
-        ret = qcow2_get_cluster_offset(bs, sector_num << 9, &n,
-            &cluster_offset);
-        if (ret < 0) {
-            return ret;
-        }
-
-        index_in_cluster = sector_num & (s->cluster_sectors - 1);
-        if (!cluster_offset) {
-            if (bs->backing_hd) {
-                /* read from the base image */
-                iov.iov_base = buf;
-                iov.iov_len = n * 512;
-                qemu_iovec_init_external(&qiov, &iov, 1);
-
-                n1 = qcow2_backing_read1(bs->backing_hd, &qiov, sector_num, n);
-                if (n1 > 0) {
-                    BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING);
-                    ret = bdrv_read(bs->backing_hd, sector_num, buf, n1);
-                    if (ret < 0)
-                        return -1;
-                }
-            } else {
-                memset(buf, 0, 512 * n);
-            }
-        } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
-            if (qcow2_decompress_cluster(bs, cluster_offset) < 0)
-                return -1;
-            memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
-        } else {
-            BLKDBG_EVENT(bs->file, BLKDBG_READ);
-            ret = bdrv_pread(bs->file, cluster_offset + index_in_cluster * 512, buf, n * 512);
-            if (ret != n * 512)
-                return -1;
-            if (s->crypt_method) {
-                qcow2_encrypt_sectors(s, sector_num, buf, buf, n, 0,
-                                &s->aes_decrypt_key);
-            }
-        }
-        nb_sectors -= n;
-        sector_num += n;
-        buf += n * 512;
-    }
-    return 0;
-}
-
 static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
                         uint64_t cluster_offset, int n_start, int n_end)
 {
     BDRVQcowState *s = bs->opaque;
     int n, ret;
+    void *buf;
+
+    /*
+     * If this is the last cluster and it is only partially used, we must only
+     * copy until the end of the image, or bdrv_check_request will fail for the
+     * bdrv_read/write calls below.
+     */
+    if (start_sect + n_end > bs->total_sectors) {
+        n_end = bs->total_sectors - start_sect;
+    }
 
     n = n_end - n_start;
-    if (n <= 0)
+    if (n <= 0) {
         return 0;
+    }
+
+    buf = qemu_blockalign(bs, n * BDRV_SECTOR_SIZE);
+
     BLKDBG_EVENT(bs->file, BLKDBG_COW_READ);
-    ret = qcow2_read(bs, start_sect + n_start, s->cluster_data, n);
-    if (ret < 0)
-        return ret;
+    ret = bdrv_read(bs, start_sect + n_start, buf, n);
+    if (ret < 0) {
+        goto out;
+    }
+
     if (s->crypt_method) {
         qcow2_encrypt_sectors(s, start_sect + n_start,
-                        s->cluster_data,
-                        s->cluster_data, n, 1,
+                        buf, buf, n, 1,
                         &s->aes_encrypt_key);
     }
+
     BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE);
-    ret = bdrv_write(bs->file, (cluster_offset >> 9) + n_start,
-        s->cluster_data, n);
-    if (ret < 0)
-        return ret;
-    return 0;
+    ret = bdrv_write(bs->file, (cluster_offset >> 9) + n_start, buf, n);
+    if (ret < 0) {
+        goto out;
+    }
+
+    ret = 0;
+out:
+    qemu_vfree(buf);
+    return ret;
 }
 
 
@@ -620,7 +582,9 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
     start_sect = (m->offset & ~(s->cluster_size - 1)) >> 9;
     if (m->n_start) {
         cow = true;
+        qemu_co_mutex_unlock(&s->lock);
         ret = copy_sectors(bs, start_sect, cluster_offset, 0, m->n_start);
+        qemu_co_mutex_lock(&s->lock);
         if (ret < 0)
             goto err;
     }
@@ -628,8 +592,10 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
     if (m->nb_available & (s->cluster_sectors - 1)) {
         uint64_t end = m->nb_available & ~(uint64_t)(s->cluster_sectors - 1);
         cow = true;
+        qemu_co_mutex_unlock(&s->lock);
         ret = copy_sectors(bs, start_sect + end, cluster_offset + (end << 9),
                 m->nb_available - end, s->cluster_sectors);
+        qemu_co_mutex_lock(&s->lock);
         if (ret < 0)
             goto err;
     }
commit b41e1ed4b35b4aa35018a348d80c46e40e6f4163
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Dec 4 20:06:16 2011 +0200

    piix_pci: adapt smram mapping to use memory mutators
    
    Eliminates fake state ->smram_enabled.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index d183443..ac3d898 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -81,7 +81,6 @@ struct PCII440FXState {
     PAMMemoryRegion pam_regions[13];
     MemoryRegion smram_region;
     uint8_t smm_enabled;
-    bool smram_enabled;
     PIIX3State *piix3;
 };
 
@@ -141,6 +140,7 @@ static void i440fx_update_memory_mappings(PCII440FXState *d)
 {
     int i, r;
     uint32_t smram;
+    bool smram_enabled;
 
     memory_region_transaction_begin();
     update_pam(d, 0xf0000, 0x100000, (d->dev.config[I440FX_PAM] >> 4) & 3,
@@ -151,18 +151,8 @@ static void i440fx_update_memory_mappings(PCII440FXState *d)
                    &d->pam_regions[i+1]);
     }
     smram = d->dev.config[I440FX_SMRAM];
-    if ((d->smm_enabled && (smram & 0x08)) || (smram & 0x40)) {
-        if (!d->smram_enabled) {
-            memory_region_del_subregion(d->system_memory, &d->smram_region);
-            d->smram_enabled = true;
-        }
-    } else {
-        if (d->smram_enabled) {
-            memory_region_add_subregion_overlap(d->system_memory, 0xa0000,
-                                                &d->smram_region, 1);
-            d->smram_enabled = false;
-        }
-    }
+    smram_enabled = (d->smm_enabled && (smram & 0x08)) || (smram & 0x40);
+    memory_region_set_enabled(&d->smram_region, !smram_enabled);
     memory_region_transaction_commit();
 }
 
@@ -307,7 +297,9 @@ static PCIBus *i440fx_common_init(const char *device_name,
     }
     memory_region_init_alias(&f->smram_region, "smram-region",
                              f->pci_address_space, 0xa0000, 0x20000);
-    f->smram_enabled = true;
+    memory_region_add_subregion_overlap(f->system_memory, 0xa0000,
+                                        &f->smram_region, 1);
+    memory_region_set_enabled(&f->smram_region, false);
 
     /* Xen supports additional interrupt routes from the PCI devices to
      * the IOAPIC: the four pins of each PCI device on the bus are also
commit 7969d9ed5c9eca24e63f2f033b29131981c64a09
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Dec 4 19:49:22 2011 +0200

    cirrus_vga: adapt to memory mutators API
    
    Simplify the code by avoiding dynamic creation and destruction of
    memory regions.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index c7e365b..9f7fea1 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -205,7 +205,7 @@ typedef struct CirrusVGAState {
     bool linear_vram;  /* vga.vram mapped over cirrus_linear_io */
     MemoryRegion low_mem_container; /* container for 0xa0000-0xc0000 */
     MemoryRegion low_mem;           /* always mapped, overridden by: */
-    MemoryRegion *cirrus_bank[2];   /*   aliases at 0xa0000-0xb0000  */
+    MemoryRegion cirrus_bank[2];    /*   aliases at 0xa0000-0xb0000  */
     uint32_t cirrus_addr_mask;
     uint32_t linear_mmio_mask;
     uint8_t cirrus_shadow_gr0;
@@ -2363,40 +2363,16 @@ static const MemoryRegionOps cirrus_linear_bitblt_io_ops = {
     },
 };
 
-static void unmap_bank(CirrusVGAState *s, unsigned bank)
-{
-    if (s->cirrus_bank[bank]) {
-        memory_region_del_subregion(&s->low_mem_container,
-                                    s->cirrus_bank[bank]);
-        memory_region_destroy(s->cirrus_bank[bank]);
-        g_free(s->cirrus_bank[bank]);
-        s->cirrus_bank[bank] = NULL;
-    }
-}
-
 static void map_linear_vram_bank(CirrusVGAState *s, unsigned bank)
 {
-    MemoryRegion *mr;
-    static const char *names[] = { "vga.bank0", "vga.bank1" };
-
-    if (!(s->cirrus_srcptr != s->cirrus_srcptr_end)
+    MemoryRegion *mr = &s->cirrus_bank[bank];
+    bool enabled = !(s->cirrus_srcptr != s->cirrus_srcptr_end)
         && !((s->vga.sr[0x07] & 0x01) == 0)
         && !((s->vga.gr[0x0B] & 0x14) == 0x14)
-        && !(s->vga.gr[0x0B] & 0x02)) {
-
-        mr = g_malloc(sizeof(*mr));
-        memory_region_init_alias(mr, names[bank], &s->vga.vram,
-                                 s->cirrus_bank_base[bank], 0x8000);
-        memory_region_add_subregion_overlap(
-            &s->low_mem_container,
-            0x8000 * bank,
-            mr,
-            1);
-        unmap_bank(s, bank);
-        s->cirrus_bank[bank] = mr;
-    } else {
-        unmap_bank(s, bank);
-    }
+        && !(s->vga.gr[0x0B] & 0x02);
+
+    memory_region_set_enabled(mr, enabled);
+    memory_region_set_alias_offset(mr, s->cirrus_bank_base[bank]);
 }
 
 static void map_linear_vram(CirrusVGAState *s)
@@ -2415,8 +2391,8 @@ static void unmap_linear_vram(CirrusVGAState *s)
         s->linear_vram = false;
         memory_region_del_subregion(&s->pci_bar, &s->vga.vram);
     }
-    unmap_bank(s, 0);
-    unmap_bank(s, 1);
+    memory_region_set_enabled(&s->cirrus_bank[0], false);
+    memory_region_set_enabled(&s->cirrus_bank[1], false);
 }
 
 /* Compute the memory access functions */
@@ -2856,6 +2832,14 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci,
     memory_region_init_io(&s->low_mem, &cirrus_vga_mem_ops, s,
                           "cirrus-low-memory", 0x20000);
     memory_region_add_subregion(&s->low_mem_container, 0, &s->low_mem);
+    for (i = 0; i < 2; ++i) {
+        static const char *names[] = { "vga.bank0", "vga.bank1" };
+        MemoryRegion *bank = &s->cirrus_bank[i];
+        memory_region_init_alias(bank, names[i], &s->vga.vram, 0, 0x8000);
+        memory_region_set_enabled(bank, false);
+        memory_region_add_subregion_overlap(&s->low_mem_container, i * 0x8000,
+                                            bank, 1);
+    }
     memory_region_add_subregion_overlap(system_memory,
                                         isa_mem_base + 0x000a0000,
                                         &s->low_mem_container,
commit e87c099f1c9e461dcaa093b1b40b14e7e899e70f
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Sep 14 12:16:20 2011 +0300

    memory: optimize empty transactions due to mutators
    
    The mutating memory APIs can easily cause empty transactions,
    where the mutators don't actually change anything, or perhaps
    only modify disabled regions.  Detect these conditions and
    avoid regenerating the memory topology.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/memory.c b/memory.c
index 7e842b3..87639ab 100644
--- a/memory.c
+++ b/memory.c
@@ -19,6 +19,7 @@
 #include <assert.h>
 
 unsigned memory_region_transaction_depth = 0;
+static bool memory_region_update_pending = false;
 
 typedef struct AddrRange AddrRange;
 
@@ -757,6 +758,7 @@ static void address_space_update_topology(AddressSpace *as)
 static void memory_region_update_topology(MemoryRegion *mr)
 {
     if (memory_region_transaction_depth) {
+        memory_region_update_pending |= !mr || mr->enabled;
         return;
     }
 
@@ -770,6 +772,8 @@ static void memory_region_update_topology(MemoryRegion *mr)
     if (address_space_io.root) {
         address_space_update_topology(&address_space_io);
     }
+
+    memory_region_update_pending = false;
 }
 
 void memory_region_transaction_begin(void)
@@ -781,7 +785,9 @@ void memory_region_transaction_commit(void)
 {
     assert(memory_region_transaction_depth);
     --memory_region_transaction_depth;
-    memory_region_update_topology(NULL);
+    if (!memory_region_transaction_depth && memory_region_update_pending) {
+        memory_region_update_topology(NULL);
+    }
 }
 
 static void memory_region_destructor_none(MemoryRegion *mr)
commit 4703359e0eeb27c382fdf2951b842cf8bde26672
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Dec 4 19:16:50 2011 +0200

    memory: introduce memory_region_set_alias_offset()
    
    Add an API to update an alias offset of an active alias.  This can be
    used to simplify implementation of dynamic memory banks.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/memory.c b/memory.c
index a080d21..7e842b3 100644
--- a/memory.c
+++ b/memory.c
@@ -1345,6 +1345,20 @@ void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr)
     memory_region_transaction_commit();
 }
 
+void memory_region_set_alias_offset(MemoryRegion *mr, target_phys_addr_t offset)
+{
+    target_phys_addr_t old_offset = mr->alias_offset;
+
+    assert(mr->alias);
+    mr->alias_offset = offset;
+
+    if (offset == old_offset || !mr->parent) {
+        return;
+    }
+
+    memory_region_update_topology(mr);
+}
+
 void set_system_memory_map(MemoryRegion *mr)
 {
     address_space_memory.root = mr;
diff --git a/memory.h b/memory.h
index db53422..c07bcca 100644
--- a/memory.h
+++ b/memory.h
@@ -529,6 +529,18 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled);
  */
 void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr);
 
+/*
+ * memory_region_set_alias_offset: dynamically update a memory alias's offset
+ *
+ * Dynamically updates the offset into the target region that an alias points
+ * to, as if the fourth argument to memory_region_init_alias() has changed.
+ *
+ * @mr: the #MemoryRegion to be updated; should be an alias.
+ * @offset: the new offset into the target memory region
+ */
+void memory_region_set_alias_offset(MemoryRegion *mr,
+                                    target_phys_addr_t offset);
+
 /* Start a transaction; changes will be accumulated and made visible only
  * when the transaction ends.
  */
commit 2282e1af408db47bab0f900344c0ba0935835f48
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Sep 14 12:10:12 2011 +0300

    memory: introduce memory_region_set_address()
    
    Allow changing the address of a memory region while it is
    in the memory hierarchy.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/memory.c b/memory.c
index d0f90ca..a080d21 100644
--- a/memory.c
+++ b/memory.c
@@ -1324,6 +1324,27 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled)
     memory_region_update_topology(NULL);
 }
 
+void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr)
+{
+    MemoryRegion *parent = mr->parent;
+    unsigned priority = mr->priority;
+    bool may_overlap = mr->may_overlap;
+
+    if (addr == mr->addr || !parent) {
+        mr->addr = addr;
+        return;
+    }
+
+    memory_region_transaction_begin();
+    memory_region_del_subregion(parent, mr);
+    if (may_overlap) {
+        memory_region_add_subregion_overlap(parent, addr, mr, priority);
+    } else {
+        memory_region_add_subregion(parent, addr, mr);
+    }
+    memory_region_transaction_commit();
+}
+
 void set_system_memory_map(MemoryRegion *mr)
 {
     address_space_memory.root = mr;
diff --git a/memory.h b/memory.h
index c6997c4..db53422 100644
--- a/memory.h
+++ b/memory.h
@@ -518,6 +518,17 @@ void memory_region_del_subregion(MemoryRegion *mr,
  */
 void memory_region_set_enabled(MemoryRegion *mr, bool enabled);
 
+/*
+ * memory_region_set_address: dynamically update the address of a region
+ *
+ * Dynamically updates the address of a region, relative to its parent.
+ * May be used on regions are currently part of a memory hierarchy.
+ *
+ * @mr: the region to be updated
+ * @addr: new address, relative to parent region
+ */
+void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr);
+
 /* Start a transaction; changes will be accumulated and made visible only
  * when the transaction ends.
  */
commit 8b8882722210334f19b41950c82c529e33f97b00
Author: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
Date:   Sun Dec 4 22:35:28 2011 +0530

    hw/9pfs: Use the correct file descriptor in Fsdriver Callback
    
    Fsdriver callback that operate on file descriptor need to
    differentiate between directory fd and file fd.
    
    Based on the original patch from Sassan Panahinejad <sassan at sassan.me.uk>
    
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 1928da2..a85ecd3 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -112,10 +112,10 @@ typedef struct FileOperations
     ssize_t (*pwritev)(FsContext *, V9fsFidOpenState *,
                        const struct iovec *, int, off_t);
     int (*mkdir)(FsContext *, V9fsPath *, const char *, FsCred *);
-    int (*fstat)(FsContext *, V9fsFidOpenState *, struct stat *);
+    int (*fstat)(FsContext *, int, V9fsFidOpenState *, struct stat *);
     int (*rename)(FsContext *, const char *, const char *);
     int (*truncate)(FsContext *, V9fsPath *, off_t);
-    int (*fsync)(FsContext *, V9fsFidOpenState *, int);
+    int (*fsync)(FsContext *, int, V9fsFidOpenState *, int);
     int (*statfs)(FsContext *s, V9fsPath *path, struct statfs *stbuf);
     ssize_t (*lgetxattr)(FsContext *, V9fsPath *,
                          const char *, void *, size_t);
diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c
index 586b038..b15838c 100644
--- a/hw/9pfs/cofile.c
+++ b/hw/9pfs/cofile.c
@@ -71,7 +71,7 @@ int v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, struct stat *stbuf)
     }
     v9fs_co_run_in_worker(
         {
-            err = s->ops->fstat(&s->ctx, &fidp->fs, stbuf);
+            err = s->ops->fstat(&s->ctx, fidp->fid_type, &fidp->fs, stbuf);
             if (err < 0) {
                 err = -errno;
             }
@@ -192,7 +192,7 @@ int v9fs_co_fsync(V9fsPDU *pdu, V9fsFidState *fidp, int datasync)
     }
     v9fs_co_run_in_worker(
         {
-            err = s->ops->fsync(&s->ctx, &fidp->fs, datasync);
+            err = s->ops->fsync(&s->ctx, fidp->fid_type, &fidp->fs, datasync);
             if (err < 0) {
                 err = -errno;
             }
diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c
index a62f690..f97d898 100644
--- a/hw/9pfs/virtio-9p-handle.c
+++ b/hw/9pfs/virtio-9p-handle.c
@@ -255,10 +255,17 @@ static int handle_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
     return ret;
 }
 
-static int handle_fstat(FsContext *fs_ctx, V9fsFidOpenState *fs,
-                        struct stat *stbuf)
+static int handle_fstat(FsContext *fs_ctx, int fid_type,
+                        V9fsFidOpenState *fs, struct stat *stbuf)
 {
-    return fstat(fs->fd, stbuf);
+    int fd;
+
+    if (fid_type == P9_FID_DIR) {
+        fd = dirfd(fs->dir);
+    } else {
+        fd = fs->fd;
+    }
+    return fstat(fd, stbuf);
 }
 
 static int handle_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
@@ -395,12 +402,21 @@ static int handle_remove(FsContext *ctx, const char *path)
     return -1;
 }
 
-static int handle_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync)
+static int handle_fsync(FsContext *ctx, int fid_type,
+                        V9fsFidOpenState *fs, int datasync)
 {
+    int fd;
+
+    if (fid_type == P9_FID_DIR) {
+        fd = dirfd(fs->dir);
+    } else {
+        fd = fs->fd;
+    }
+
     if (datasync) {
-        return qemu_fdatasync(fs->fd);
+        return qemu_fdatasync(fd);
     } else {
-        return fsync(fs->fd);
+        return fsync(fd);
     }
 }
 
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 99ef0cd..371a94d 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -366,11 +366,18 @@ out:
     return err;
 }
 
-static int local_fstat(FsContext *fs_ctx,
+static int local_fstat(FsContext *fs_ctx, int fid_type,
                        V9fsFidOpenState *fs, struct stat *stbuf)
 {
-    int err;
-    err = fstat(fs->fd, stbuf);
+    int err, fd;
+
+    if (fid_type == P9_FID_DIR) {
+        fd = dirfd(fs->dir);
+    } else {
+        fd = fs->fd;
+    }
+
+    err = fstat(fd, stbuf);
     if (err) {
         return err;
     }
@@ -381,19 +388,19 @@ static int local_fstat(FsContext *fs_ctx,
         mode_t tmp_mode;
         dev_t tmp_dev;
 
-        if (fgetxattr(fs->fd, "user.virtfs.uid",
+        if (fgetxattr(fd, "user.virtfs.uid",
                       &tmp_uid, sizeof(uid_t)) > 0) {
             stbuf->st_uid = tmp_uid;
         }
-        if (fgetxattr(fs->fd, "user.virtfs.gid",
+        if (fgetxattr(fd, "user.virtfs.gid",
                       &tmp_gid, sizeof(gid_t)) > 0) {
             stbuf->st_gid = tmp_gid;
         }
-        if (fgetxattr(fs->fd, "user.virtfs.mode",
+        if (fgetxattr(fd, "user.virtfs.mode",
                       &tmp_mode, sizeof(mode_t)) > 0) {
             stbuf->st_mode = tmp_mode;
         }
-        if (fgetxattr(fs->fd, "user.virtfs.rdev",
+        if (fgetxattr(fd, "user.virtfs.rdev",
                       &tmp_dev, sizeof(dev_t)) > 0) {
                 stbuf->st_rdev = tmp_dev;
         }
@@ -592,12 +599,21 @@ static int local_remove(FsContext *ctx, const char *path)
     return remove(rpath(ctx, path, buffer));
 }
 
-static int local_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync)
+static int local_fsync(FsContext *ctx, int fid_type,
+                       V9fsFidOpenState *fs, int datasync)
 {
+    int fd;
+
+    if (fid_type == P9_FID_DIR) {
+        fd = dirfd(fs->dir);
+    } else {
+        fd = fs->fd;
+    }
+
     if (datasync) {
-        return qemu_fdatasync(fs->fd);
+        return qemu_fdatasync(fd);
     } else {
-        return fsync(fs->fd);
+        return fsync(fd);
     }
 }
 
diff --git a/hw/9pfs/virtio-9p-synth.c b/hw/9pfs/virtio-9p-synth.c
index f573616..92e0b09 100644
--- a/hw/9pfs/virtio-9p-synth.c
+++ b/hw/9pfs/virtio-9p-synth.c
@@ -166,7 +166,7 @@ static int v9fs_synth_lstat(FsContext *fs_ctx,
     return 0;
 }
 
-static int v9fs_synth_fstat(FsContext *fs_ctx,
+static int v9fs_synth_fstat(FsContext *fs_ctx, int fid_type,
                             V9fsFidOpenState *fs, struct stat *stbuf)
 {
     V9fsSynthOpenState *synth_open = fs->private;
@@ -414,7 +414,8 @@ static int v9fs_synth_remove(FsContext *ctx, const char *path)
     return -1;
 }
 
-static int v9fs_synth_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync)
+static int v9fs_synth_fsync(FsContext *ctx, int fid_type,
+                            V9fsFidOpenState *fs, int datasync)
 {
     errno = ENOSYS;
     return 0;
commit 8798d6c98ea32bde6cebf7652730c3273ce38fd4
Author: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
Date:   Sun Dec 4 22:35:28 2011 +0530

    hw/9pfs: Add qdev.reset callback for virtio-9p-pci device
    
    Add the device reset callback
    
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index c9bca8b..cd343e1 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -176,7 +176,8 @@ static PCIDeviceInfo virtio_9p_info = {
         DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
         DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
         DEFINE_PROP_END_OF_LIST(),
-    }
+    },
+    .qdev.reset = virtio_pci_reset,
 };
 
 static void virtio_9p_register_devices(void)
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 64c6a94..c665f5c 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -266,7 +266,7 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
     proxy->ioeventfd_started = false;
 }
 
-static void virtio_pci_reset(DeviceState *d)
+void virtio_pci_reset(DeviceState *d)
 {
     VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev);
     virtio_pci_stop_ioeventfd(proxy);
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index f8404de..344c22b 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -45,6 +45,7 @@ typedef struct {
 } VirtIOPCIProxy;
 
 void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
+void virtio_pci_reset(DeviceState *d);
 
 /* Virtio ABI version, if we increment this, we break the guest driver. */
 #define VIRTIO_PCI_ABI_VERSION          0
commit b41e2992b279bf13c2a424082e64d8722546b013
Author: Deepak C Shetty <deepakcs at linux.vnet.ibm.com>
Date:   Sun Dec 4 22:35:28 2011 +0530

    hw/9pfs: Reset server state during TVERSION
    
    As per the 9p rfc, during TVERSION its necessary to clean all the active
    fids, so that we start the session from a clean state. Its also needed in
    scenarios where the guest is booting off 9p, and boot fails, and client
    restarts, without any knowledge of the past, it will issue a TVERSION again
    so this ensures that we always start from a clean state.
    
    Signed-off-by: Deepak C Shetty <deepakcs at linux.vnet.ibm.com>
    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 32b98dd..dd43209 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -523,6 +523,30 @@ static int v9fs_mark_fids_unreclaim(V9fsPDU *pdu, V9fsPath *path)
     return 0;
 }
 
+static void virtfs_reset(V9fsPDU *pdu)
+{
+    V9fsState *s = pdu->s;
+    V9fsFidState *fidp = NULL;
+
+    /* Free all fids */
+    while (s->fid_list) {
+        fidp = s->fid_list;
+        s->fid_list = fidp->next;
+
+        if (fidp->ref) {
+            fidp->clunked = 1;
+        } else {
+            free_fid(pdu, fidp);
+        }
+    }
+    if (fidp) {
+        /* One or more unclunked fids found... */
+        error_report("9pfs:%s: One or more uncluncked fids "
+                     "found during reset", __func__);
+    }
+    return;
+}
+
 #define P9_QID_TYPE_DIR         0x80
 #define P9_QID_TYPE_SYMLINK     0x02
 
@@ -1196,6 +1220,8 @@ static void v9fs_version(void *opaque)
     pdu_unmarshal(pdu, offset, "ds", &s->msize, &version);
     trace_v9fs_version(pdu->tag, pdu->id, s->msize, version.data);
 
+    virtfs_reset(pdu);
+
     if (!strcmp(version.data, "9P2000.u")) {
         s->proto_version = V9FS_PROTO_2000U;
     } else if (!strcmp(version.data, "9P2000.L")) {
commit e9a0152ba182c5ce9929ee60f83a37b61a1d5195
Author: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
Date:   Sun Dec 4 22:35:28 2011 +0530

    hw/9pfs: use migration blockers to prevent live migration when virtfs export path is mounted
    
    Now when you try to migrate with VirtFS export path mounted, you get a proper QMP error:
    
    (qemu) migrate tcp:localhost:4444
    Migration is disabled when VirtFS export path '/tmp/' is mounted in the guest using mount_tag 'v_tmp'
    (qemu)
    
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index bba4c54..c9bca8b 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -33,13 +33,15 @@ static V9fsState *to_virtio_9p(VirtIODevice *vdev)
 
 static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
 {
+    int len;
     struct virtio_9p_config *cfg;
     V9fsState *s = to_virtio_9p(vdev);
 
-    cfg = g_malloc0(sizeof(struct virtio_9p_config) +
-                        s->tag_len);
-    stw_raw(&cfg->tag_len, s->tag_len);
-    memcpy(cfg->tag, s->tag, s->tag_len);
+    len = strlen(s->tag);
+    cfg = g_malloc0(sizeof(struct virtio_9p_config) + len);
+    stw_raw(&cfg->tag_len, len);
+    /* We don't copy the terminating null to config space */
+    memcpy(cfg->tag, s->tag, len);
     memcpy(config, cfg, s->config_size);
     g_free(cfg);
 }
@@ -96,20 +98,18 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
     }
 
     len = strlen(conf->tag);
-    if (len > MAX_TAG_LEN) {
+    if (len > MAX_TAG_LEN - 1) {
         fprintf(stderr, "mount tag '%s' (%d bytes) is longer than "
-                "maximum (%d bytes)", conf->tag, len, MAX_TAG_LEN);
+                "maximum (%d bytes)", conf->tag, len, MAX_TAG_LEN - 1);
         exit(1);
     }
-    /* s->tag is non-NULL terminated string */
-    s->tag = g_malloc(len);
-    memcpy(s->tag, conf->tag, len);
-    s->tag_len = len;
+
+    s->tag = strdup(conf->tag);
     s->ctx.uid = -1;
 
     s->ops = fse->ops;
     s->vdev.get_features = virtio_9p_get_features;
-    s->config_size = sizeof(struct virtio_9p_config) + s->tag_len;
+    s->config_size = sizeof(struct virtio_9p_config) + len;
     s->vdev.get_config = virtio_9p_get_config;
     s->fid_list = NULL;
     qemu_co_rwlock_init(&s->rename_lock);
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 1b2fc5d..32b98dd 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -23,6 +23,7 @@
 #include "virtio-9p-xattr.h"
 #include "virtio-9p-coth.h"
 #include "trace.h"
+#include "migration.h"
 
 int open_fd_hw;
 int total_open_fd;
@@ -373,6 +374,19 @@ static void put_fid(V9fsPDU *pdu, V9fsFidState *fidp)
      * Don't free the fid if it is in reclaim list
      */
     if (!fidp->ref && fidp->clunked) {
+        if (fidp->fid == pdu->s->root_fid) {
+            /*
+             * if the clunked fid is root fid then we
+             * have unmounted the fs on the client side.
+             * delete the migration blocker. Ideally, this
+             * should be hooked to transport close notification
+             */
+            if (pdu->s->migration_blocker) {
+                migrate_del_blocker(pdu->s->migration_blocker);
+                error_free(pdu->s->migration_blocker);
+                pdu->s->migration_blocker = NULL;
+            }
+        }
         free_fid(pdu, fidp);
     }
 }
@@ -1235,6 +1249,11 @@ static void v9fs_attach(void *opaque)
     err = offset;
     trace_v9fs_attach_return(pdu->tag, pdu->id,
                              qid.type, qid.version, qid.path);
+    s->root_fid = fid;
+    /* disable migration */
+    error_set(&s->migration_blocker, QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION,
+              s->ctx.fs_root, s->tag);
+    migrate_add_blocker(s->migration_blocker);
 out:
     put_fid(pdu, fidp);
 out_nofid:
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 7f88356..8b612da 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -246,8 +246,7 @@ typedef struct V9fsState
     V9fsFidState *fid_list;
     FileOperations *ops;
     FsContext ctx;
-    uint16_t tag_len;
-    uint8_t *tag;
+    char *tag;
     size_t config_size;
     enum p9_proto_version proto_version;
     int32_t msize;
@@ -256,6 +255,8 @@ typedef struct V9fsState
      * on rename.
      */
     CoRwlock rename_lock;
+    int32_t root_fid;
+    Error *migration_blocker;
 } V9fsState;
 
 typedef struct V9fsStatState {
diff --git a/qerror.c b/qerror.c
index fdf62b9..25bc91e 100644
--- a/qerror.c
+++ b/qerror.c
@@ -235,6 +235,11 @@ static const QErrorStringTable qerror_table[] = {
                      "supported by this qemu version: %(feature)",
     },
     {
+        .error_fmt = QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION,
+        .desc      = "Migration is disabled when VirtFS export path '%(path)' "
+                     "is mounted in the guest using mount_tag '%(tag)'",
+    },
+    {
         .error_fmt = QERR_VNC_SERVER_FAILED,
         .desc      = "Could not start VNC server on %(target)",
     },
diff --git a/qerror.h b/qerror.h
index 2d3d43b..6414cd9 100644
--- a/qerror.h
+++ b/qerror.h
@@ -192,6 +192,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_UNKNOWN_BLOCK_FORMAT_FEATURE \
     "{ 'class': 'UnknownBlockFormatFeature', 'data': { 'device': %s, 'format': %s, 'feature': %s } }"
 
+#define QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION \
+    "{ 'class': 'VirtFSFeatureBlocksMigration', 'data': { 'path': %s, 'tag': %s } }"
+
 #define QERR_VNC_SERVER_FAILED \
     "{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }"
 
commit 77eec1b3f1493ca4813eae2fbf8702d1ef58f147
Author: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
Date:   Sun Dec 4 22:35:27 2011 +0530

    hw/9pfs: Improve portability to older systems
    
    handle fs driver require a set of newly added syscalls. Don't
    Compile handle FS driver if those syscalls are not available.
    Instead of adding #ifdef for all those syscalls we check for
    open by handle syscall. If that is available then rest of the
    syscalls used by the driver should be available.
    
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/Makefile.objs b/Makefile.objs
index d7a6539..3a699ee 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -310,8 +310,8 @@ hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o
 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o cofs.o codir.o cofile.o
-9pfs-nested-$(CONFIG_VIRTFS) += coxattr.o virtio-9p-handle.o
-9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-synth.o
+9pfs-nested-$(CONFIG_VIRTFS) += coxattr.o virtio-9p-synth.o
+9pfs-nested-$(CONFIG_OPEN_BY_HANDLE) +=  virtio-9p-handle.o
 
 hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y))
 $(addprefix 9pfs/, $(9pfs-nested-y)): QEMU_CFLAGS+=$(GLIB_CFLAGS)
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
index 7fd2aa7..6684f7e 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -23,7 +23,9 @@ static QTAILQ_HEAD(FsDriverEntry_head, FsDriverListEntry) fsdriver_entries =
 
 static FsDriverTable FsDrivers[] = {
     { .name = "local", .ops = &local_ops},
+#ifdef CONFIG_OPEN_BY_HANDLE
     { .name = "handle", .ops = &handle_ops},
+#endif
     { .name = "synth", .ops = &synth_ops},
 };
 
diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c
index 7644ae5..a62f690 100644
--- a/hw/9pfs/virtio-9p-handle.c
+++ b/hw/9pfs/virtio-9p-handle.c
@@ -45,7 +45,6 @@ struct handle_data {
     int handle_bytes;
 };
 
-#ifdef CONFIG_OPEN_BY_HANDLE
 static inline int name_to_handle(int dirfd, const char *name,
                                  struct file_handle *fh, int *mnt_id, int flags)
 {
@@ -56,38 +55,6 @@ static inline int open_by_handle(int mountfd, const char *fh, int flags)
 {
     return open_by_handle_at(mountfd, (struct file_handle *)fh, flags);
 }
-#else
-
-struct rpl_file_handle {
-    unsigned int handle_bytes;
-    int handle_type;
-    unsigned char handle[0];
-};
-#define file_handle rpl_file_handle
-
-#ifndef AT_REMOVEDIR
-#define AT_REMOVEDIR    0x200
-#endif
-#ifndef AT_EMPTY_PATH
-#define AT_EMPTY_PATH   0x1000  /* Allow empty relative pathname */
-#endif
-#ifndef O_PATH
-#define O_PATH    010000000
-#endif
-
-static inline int name_to_handle(int dirfd, const char *name,
-                                 struct file_handle *fh, int *mnt_id, int flags)
-{
-    errno = ENOSYS;
-    return -1;
-}
-
-static inline int open_by_handle(int mountfd, const char *fh, int flags)
-{
-    errno = ENOSYS;
-    return -1;
-}
-#endif
 
 static int handle_update_file_cred(int dirfd, const char *name, FsCred *credp)
 {
commit 6bba19ba4e2b8c89496569439ca38a328cf29a77
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Sep 14 11:54:58 2011 +0300

    memory: introduce memory_region_set_enabled()
    
    This allows users to disable a memory region without removing
    it from the hierarchy, simplifying the implementation of
    memory routers.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/memory.c b/memory.c
index adfdf14..d0f90ca 100644
--- a/memory.c
+++ b/memory.c
@@ -528,6 +528,10 @@ static void render_memory_region(FlatView *view,
     FlatRange fr;
     AddrRange tmp;
 
+    if (!mr->enabled) {
+        return;
+    }
+
     int128_addto(&base, int128_make64(mr->addr));
     readonly |= mr->readonly;
 
@@ -750,12 +754,16 @@ static void address_space_update_topology(AddressSpace *as)
     address_space_update_ioeventfds(as);
 }
 
-static void memory_region_update_topology(void)
+static void memory_region_update_topology(MemoryRegion *mr)
 {
     if (memory_region_transaction_depth) {
         return;
     }
 
+    if (mr && !mr->enabled) {
+        return;
+    }
+
     if (address_space_memory.root) {
         address_space_update_topology(&address_space_memory);
     }
@@ -773,7 +781,7 @@ void memory_region_transaction_commit(void)
 {
     assert(memory_region_transaction_depth);
     --memory_region_transaction_depth;
-    memory_region_update_topology();
+    memory_region_update_topology(NULL);
 }
 
 static void memory_region_destructor_none(MemoryRegion *mr)
@@ -813,6 +821,7 @@ void memory_region_init(MemoryRegion *mr,
     }
     mr->addr = 0;
     mr->offset = 0;
+    mr->enabled = true;
     mr->terminates = false;
     mr->readable = true;
     mr->readonly = false;
@@ -1058,7 +1067,7 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
     uint8_t mask = 1 << client;
 
     mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask);
-    memory_region_update_topology();
+    memory_region_update_topology(mr);
 }
 
 bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
@@ -1090,7 +1099,7 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
 {
     if (mr->readonly != readonly) {
         mr->readonly = readonly;
-        memory_region_update_topology();
+        memory_region_update_topology(mr);
     }
 }
 
@@ -1098,7 +1107,7 @@ void memory_region_rom_device_set_readable(MemoryRegion *mr, bool readable)
 {
     if (mr->readable != readable) {
         mr->readable = readable;
-        memory_region_update_topology();
+        memory_region_update_topology(mr);
     }
 }
 
@@ -1203,7 +1212,7 @@ void memory_region_add_eventfd(MemoryRegion *mr,
     memmove(&mr->ioeventfds[i+1], &mr->ioeventfds[i],
             sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb-1 - i));
     mr->ioeventfds[i] = mrfd;
-    memory_region_update_topology();
+    memory_region_update_topology(mr);
 }
 
 void memory_region_del_eventfd(MemoryRegion *mr,
@@ -1233,7 +1242,7 @@ void memory_region_del_eventfd(MemoryRegion *mr,
     --mr->ioeventfd_nb;
     mr->ioeventfds = g_realloc(mr->ioeventfds,
                                   sizeof(*mr->ioeventfds)*mr->ioeventfd_nb + 1);
-    memory_region_update_topology();
+    memory_region_update_topology(mr);
 }
 
 static void memory_region_add_subregion_common(MemoryRegion *mr,
@@ -1274,7 +1283,7 @@ static void memory_region_add_subregion_common(MemoryRegion *mr,
     }
     QTAILQ_INSERT_TAIL(&mr->subregions, subregion, subregions_link);
 done:
-    memory_region_update_topology();
+    memory_region_update_topology(mr);
 }
 
 
@@ -1303,19 +1312,28 @@ void memory_region_del_subregion(MemoryRegion *mr,
     assert(subregion->parent == mr);
     subregion->parent = NULL;
     QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
-    memory_region_update_topology();
+    memory_region_update_topology(mr);
+}
+
+void memory_region_set_enabled(MemoryRegion *mr, bool enabled)
+{
+    if (enabled == mr->enabled) {
+        return;
+    }
+    mr->enabled = enabled;
+    memory_region_update_topology(NULL);
 }
 
 void set_system_memory_map(MemoryRegion *mr)
 {
     address_space_memory.root = mr;
-    memory_region_update_topology();
+    memory_region_update_topology(NULL);
 }
 
 void set_system_io_map(MemoryRegion *mr)
 {
     address_space_io.root = mr;
-    memory_region_update_topology();
+    memory_region_update_topology(NULL);
 }
 
 typedef struct MemoryRegionList MemoryRegionList;
diff --git a/memory.h b/memory.h
index 53bf261..c6997c4 100644
--- a/memory.h
+++ b/memory.h
@@ -123,6 +123,7 @@ struct MemoryRegion {
     bool terminates;
     bool readable;
     bool readonly; /* For RAM regions */
+    bool enabled;
     MemoryRegion *alias;
     target_phys_addr_t alias_offset;
     unsigned priority;
@@ -501,6 +502,22 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr,
 void memory_region_del_subregion(MemoryRegion *mr,
                                  MemoryRegion *subregion);
 
+
+/*
+ * memory_region_set_enabled: dynamically enable or disable a region
+ *
+ * Enables or disables a memory region.  A disabled memory region
+ * ignores all accesses to itself and its subregions.  It does not
+ * obscure sibling subregions with lower priority - it simply behaves as
+ * if it was removed from the hierarchy.
+ *
+ * Regions default to being enabled.
+ *
+ * @mr: the region to be updated
+ * @enabled: whether to enable or disable the region
+ */
+void memory_region_set_enabled(MemoryRegion *mr, bool enabled);
+
 /* Start a transaction; changes will be accumulated and made visible only
  * when the transaction ends.
  */
commit 07f35073c6d6d1b2f42a6b3671b8af2f271986b9
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Tue Nov 22 18:06:26 2011 +0800

    fix spelling in main directory
    
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/arm-dis.c b/arm-dis.c
index 3ece02c..6bc4d71 100644
--- a/arm-dis.c
+++ b/arm-dis.c
@@ -1624,7 +1624,7 @@ arm_decode_shift (long given, fprintf_function func, void *stream,
 }
 
 /* Print one coprocessor instruction on INFO->STREAM.
-   Return true if the instuction matched, false if this is not a
+   Return true if the instruction matched, false if this is not a
    recognised coprocessor instruction.  */
 
 static bfd_boolean
@@ -2214,7 +2214,7 @@ print_arm_address (bfd_vma pc, struct disassemble_info *info, long given)
 }
 
 /* Print one neon instruction on INFO->STREAM.
-   Return true if the instuction matched, false if this is not a
+   Return true if the instruction matched, false if this is not a
    recognised neon instruction.  */
 
 static bfd_boolean
@@ -3927,7 +3927,7 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info)
 	    n = last_mapping_sym - 1;
 
 	  /* No mapping symbol found at this address.  Look backwards
-	     for a preceeding one.  */
+	     for a preceding one.  */
 	  for (; n >= 0; n--)
 	    {
 	      if (get_sym_code_type (info, n, &type))
diff --git a/cpu-all.h b/cpu-all.h
index 5f47ab8..7246a67 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -368,7 +368,7 @@ DECLARE_TLS(CPUState *,cpu_single_env);
 #define CPU_INTERRUPT_TGT_EXT_4   0x1000
 
 /* Several target-specific internal interrupts.  These differ from the
-   preceeding target-specific interrupts in that they are intended to
+   preceding target-specific interrupts in that they are intended to
    originate from within the cpu itself, typically in response to some
    instruction being executed.  These, therefore, are not masked while
    single-stepping within the debugger.  */
diff --git a/cpu-common.h b/cpu-common.h
index c9878ba..7c9cef8 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -1,7 +1,7 @@
 #ifndef CPU_COMMON_H
 #define CPU_COMMON_H 1
 
-/* CPU interfaces that are target indpendent.  */
+/* CPU interfaces that are target independent.  */
 
 #ifdef TARGET_PHYS_ADDR_BITS
 #include "targphys.h"
diff --git a/cpus.c b/cpus.c
index 82530c4..9d2a2cb 100644
--- a/cpus.c
+++ b/cpus.c
@@ -281,7 +281,7 @@ void qemu_clock_warp(QEMUClock *clock)
          * (related to the time left until the next event) has passed.  This
          * rt_clock timer will do this.  This avoids that the warps are too
          * visible externally---for example, you will not be sending network
-         * packets continously instead of every 100ms.
+         * packets continuously instead of every 100ms.
          */
         qemu_mod_timer(icount_warp_timer, vm_clock_warp_start + deadline);
     } else {
diff --git a/exec-memory.h b/exec-memory.h
index 334219f..1cd92ee 100644
--- a/exec-memory.h
+++ b/exec-memory.h
@@ -1,5 +1,5 @@
 /*
- * Internal memory managment interfaces
+ * Internal memory management interfaces
  *
  * Copyright 2011 Red Hat, Inc. and/or its affiliates
  *
diff --git a/hppa-dis.c b/hppa-dis.c
index 435da73..420a7d2 100644
--- a/hppa-dis.c
+++ b/hppa-dis.c
@@ -564,7 +564,7 @@ If not, see <http://www.gnu.org/licenses/>. */
  */
 
 /* There are two kinds of delay slot nullification: normal which is
- * controled by the nullification bit, and conditional, which depends
+ * controlled by the nullification bit, and conditional, which depends
  * on the direction of the branch and its success or failure.
  *
  * NONE is unfortunately #defined in the hiux system include files.
diff --git a/m68k-dis.c b/m68k-dis.c
index 04f837a..2b155de 100644
--- a/m68k-dis.c
+++ b/m68k-dis.c
@@ -3518,7 +3518,7 @@ const struct m68k_opcode m68k_opcodes[] =
 
 /* NOTE: The mcf5200 family programmer's reference manual does not
    indicate the byte form of the movea instruction is invalid (as it
-   is on 68000 family cpus).  However, experiments on the 5202 yeild
+   is on 68000 family cpus).  However, experiments on the 5202 yield
    unexpected results.  The value is copied, but it is not sign extended
    (as is done with movea.w) and the top three bytes in the address
    register are not disturbed.  I don't know if this is the intended
diff --git a/main-loop.h b/main-loop.h
index 8a716b1..876092d 100644
--- a/main-loop.h
+++ b/main-loop.h
@@ -111,7 +111,7 @@ typedef int PollingFunc(void *opaque);
  * qemu_add_wait_object.
  *
  * Polling callbacks really have nothing Windows specific in them, but
- * as they are a hack and are currenly not necessary under POSIX systems,
+ * as they are a hack and are currently not necessary under POSIX systems,
  * they are only available when QEMU is running under Windows.
  *
  * @func: The function that does the polling, and returns 1 to force
diff --git a/nbd.c b/nbd.c
index e6c931c..de880fe 100644
--- a/nbd.c
+++ b/nbd.c
@@ -203,7 +203,7 @@ int nbd_negotiate(int csock, off_t size, uint32_t flags)
         return -1;
     }
 
-    TRACE("Negotation succeeded.");
+    TRACE("Negotiation succeeded.");
 
     return 0;
 }
@@ -215,7 +215,7 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
     uint64_t magic, s;
     uint16_t tmp;
 
-    TRACE("Receiving negotation.");
+    TRACE("Receiving negotiation.");
 
     if (read_sync(csock, buf, 8) != 8) {
         LOG("read failed");
diff --git a/qemu-io.c b/qemu-io.c
index de26422..f70de0b 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -445,7 +445,7 @@ static int read_f(int argc, char **argv)
     }
 
     if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
-        printf("pattern verfication range exceeds end of read data\n");
+        printf("pattern verification range exceeds end of read data\n");
         return 0;
     }
 
diff --git a/qemu-option.c b/qemu-option.c
index f97a758..6b23c31 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -480,7 +480,7 @@ void print_option_parameters(QEMUOptionParameter *list)
                 printf("%s=%" PRId64 " ", list->name, list->value.n);
                 break;
             default:
-                printf("%s=(unkown type) ", list->name);
+                printf("%s=(unknown type) ", list->name);
                 break;
         }
         list++;
diff --git a/qerror.c b/qerror.c
index fdf62b9..b12c85c 100644
--- a/qerror.c
+++ b/qerror.c
@@ -223,7 +223,7 @@ static const QErrorStringTable qerror_table[] = {
     },
     {
         .error_fmt = QERR_UNDEFINED_ERROR,
-        .desc      = "An undefined error has ocurred",
+        .desc      = "An undefined error has occurred",
     },
     {
         .error_fmt = QERR_UNSUPPORTED,
diff --git a/savevm.c b/savevm.c
index f53cd4c..a827ca2 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1552,7 +1552,7 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
 }
 
 /*
- * this funtion has three return values:
+ * this function has three return values:
  *   negative: there was one error, and we have -errno.
  *   0 : We haven't finished, caller have to go again
  *   1 : We have finished, we can go to complete phase
diff --git a/test-visitor.c b/test-visitor.c
index 847ce14..f90b711 100644
--- a/test-visitor.c
+++ b/test-visitor.c
@@ -166,7 +166,7 @@ static void test_nested_structs(void)
     QString *str;
 
     ud1.integer = 42;
-    ud1.string = strdup("fourty two");
+    ud1.string = strdup("forty two");
 
     /* sanity check */
     mo = qmp_output_visitor_new();
@@ -179,13 +179,13 @@ static void test_nested_structs(void)
     g_assert(obj);
     qobject_decref(obj);
 
-    ud2.string = strdup("fourty three");
-    ud2.dict.string = strdup("fourty four");
+    ud2.string = strdup("forty three");
+    ud2.dict.string = strdup("forty four");
     ud2.dict.dict.userdef = ud1_p;
-    ud2.dict.dict.string = strdup("fourty five");
+    ud2.dict.dict.string = strdup("forty five");
     ud2.dict.has_dict2 = true;
     ud2.dict.dict2.userdef = ud1_p;
-    ud2.dict.dict2.string = strdup("fourty six");
+    ud2.dict.dict2.string = strdup("forty six");
 
     /* c type -> qobject */
     mo = qmp_output_visitor_new();
diff --git a/vl.c b/vl.c
index a50842b..5372a96 100644
--- a/vl.c
+++ b/vl.c
@@ -820,7 +820,7 @@ static void validate_bootdevices(char *devices)
         /* Allowed boot devices are:
          * a-b: floppy disk drives
          * c-f: IDE disk drives
-         * g-m: machine implementation dependant drives
+         * g-m: machine implementation dependent drives
          * n-p: network devices
          * It's up to each machine implementation to check if the given boot
          * devices match the actual hardware implementation and firmware
commit 9b2260cbd52c93335dd0a3a79a8c7dd4665a1dea
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Tue Nov 22 18:06:25 2011 +0800

    fix spelling in block sub directory
    
    Cc: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/cow.c b/block/cow.c
index 089d395..3448296 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -92,7 +92,7 @@ static int cow_open(BlockDriverState *bs, int flags)
 }
 
 /*
- * XXX(hch): right now these functions are extremly ineffcient.
+ * XXX(hch): right now these functions are extremely ineffcient.
  * We should just read the whole bitmap we'll need in one go instead.
  */
 static inline int cow_set_bit(BlockDriverState *bs, int64_t bitnum)
diff --git a/block/qcow2.c b/block/qcow2.c
index d7805ce..9e1b1eb 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -92,7 +92,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
         if (offset > s->cluster_size)
             printf("qcow2_read_extension: suspicious offset %lu\n", offset);
 
-        printf("attemting to read extended header in offset %lu\n", offset);
+        printf("attempting to read extended header in offset %lu\n", offset);
 #endif
 
         if (bdrv_pread(bs->file, offset, &ext, sizeof(ext)) != sizeof(ext)) {
@@ -821,7 +821,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
                          int flags, size_t cluster_size, int prealloc,
                          QEMUOptionParameter *options)
 {
-    /* Calulate cluster_bits */
+    /* Calculate cluster_bits */
     int cluster_bits;
     cluster_bits = ffs(cluster_size) - 1;
     if (cluster_bits < MIN_CLUSTER_BITS || cluster_bits > MAX_CLUSTER_BITS ||
diff --git a/block/raw-posix.c b/block/raw-posix.c
index a3de373..2ee5d69 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -1153,7 +1153,7 @@ static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
     if (ret)
         return ret;
 
-    /* make sure the door isnt locked at this time */
+    /* make sure the door isn't locked at this time */
     ioctl(s->fd, CDIOCALLOW);
     return 0;
 }
@@ -1184,7 +1184,7 @@ static int cdrom_reopen(BlockDriverState *bs)
     }
     s->fd = fd;
 
-    /* make sure the door isnt locked at this time */
+    /* make sure the door isn't locked at this time */
     ioctl(s->fd, CDIOCALLOW);
     return 0;
 }
commit e5bed759baec31af67734868324e87ff61523627
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Tue Nov 22 18:06:24 2011 +0800

    fix spelling in ui sub directory
    
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index 40018f7..e85ee66 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1732,7 +1732,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
 
     /*
      * Start from the end because the encodings are sent in order of preference.
-     * This way the prefered encoding (first encoding defined in the array)
+     * This way the preferred encoding (first encoding defined in the array)
      * will be set at the end of the loop.
      */
     for (i = n_encodings - 1; i >= 0; i--) {
@@ -2117,7 +2117,7 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
 
     /* Compare expected vs actual challenge response */
     if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
-        VNC_DEBUG("Client challenge reponse did not match\n");
+        VNC_DEBUG("Client challenge response did not match\n");
         goto reject;
     } else {
         VNC_DEBUG("Accepting VNC challenge response\n");
commit 45658076ad643c78b9a9bae8cd0b091c512411e3
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Tue Nov 22 18:06:23 2011 +0800

    fix spelling in tests sub directory
    
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/tests/cris/check_glibc_kernelversion.c b/tests/cris/check_glibc_kernelversion.c
index fcbc7b0..0744872 100644
--- a/tests/cris/check_glibc_kernelversion.c
+++ b/tests/cris/check_glibc_kernelversion.c
@@ -70,7 +70,7 @@
                                                                               \
         /* Now we can test with the required version.  */                     \
         if (version < __LINUX_KERNEL_VERSION)                                 \
-          /* Not sufficent.  */                                               \
+          /* Not sufficient.  */                                               \
           FATAL ("FATAL: kernel too old\n");                                  \
                                                                               \
         _dl_osversion = version;                                              \
diff --git a/tests/cris/check_moveq.c b/tests/cris/check_moveq.c
index 9f71194..80f2dff 100644
--- a/tests/cris/check_moveq.c
+++ b/tests/cris/check_moveq.c
@@ -20,7 +20,7 @@ int main(void)
 	if (t != 10)
 		err();
 
-	/* make sure moveq doesnt clobber the zflag.  */
+	/* make sure moveq doesn't clobber the zflag.  */
 	cris_tst_cc_init();
 	asm volatile ("setf vnc\n");
 	asm volatile ("clearf z\n");
@@ -29,7 +29,7 @@ int main(void)
 	if (t != 0)
 		err();
 
-	/* make sure moveq doesnt clobber the nflag.
+	/* make sure moveq doesn't clobber the nflag.
 	   Also check large immediates  */
 	cris_tst_cc_init();
 	asm volatile ("setf zvc\n");
commit 9814dd27954b42d908addb1fefa1d19bf438dd39
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Tue Nov 22 18:06:22 2011 +0800

    fix spelling in tcg sub directory
    
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 77bd6ef..d43fa4a 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1555,7 +1555,7 @@ static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
     }
 }
 
-/* save globals to their cannonical location and assume they can be
+/* save globals to their canonical location and assume they can be
    modified be the following code. 'allocated_regs' is used in case a
    temporary registers needs to be allocated to store a constant. */
 static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 755a8b3..175000f 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -178,7 +178,7 @@ typedef tcg_target_ulong TCGArg;
 /* Define a type and accessor macros for variables.  Using a struct is
    nice because it gives some level of type safely.  Ideally the compiler
    be able to see through all this.  However in practice this is not true,
-   expecially on targets with braindamaged ABIs (e.g. i386).
+   especially on targets with braindamaged ABIs (e.g. i386).
    We use plain int by default to avoid this runtime overhead.
    Users of tcg_gen_* don't need to know about any of this, and should
    treat TCGv as an opaque type.
commit 4abf79a428bd1db681d6f4b5e521aa78cf913322
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Tue Nov 22 18:06:21 2011 +0800

    fix spelling in target sub directory
    
    Cc: Richard Henderson <rth at twiddle.net>
    Cc: Edgar E. Iglesias <edgar.iglesias at gmail.com>
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Cc: Alexander Graf <agraf at suse.de>
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/target-alpha/STATUS b/target-alpha/STATUS
index 353d543..742e370 100644
--- a/target-alpha/STATUS
+++ b/target-alpha/STATUS
@@ -18,7 +18,7 @@ Linux user mode emulation status:
 a few programs start to run. Most crash at a certain point, dereferencing a
 NULL pointer. It seems that the UNIQUE register is not initialized properly.
 It may appear that old executables, not relying on TLS support, run but
-this is to be prooved...
+this is to be proved...
 
 Full system emulation status:
 * Alpha PALCode emulation is in a very early stage and is not sufficient
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 3530286..1a307e3 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -243,7 +243,7 @@ typedef struct CPUMBState {
 #define DRTE_FLAG	(1 << 17)
 #define DRTB_FLAG	(1 << 18)
 #define D_FLAG		(1 << 19)  /* Bit in ESR.  */
-/* TB dependant CPUState.  */
+/* TB dependent CPUState.  */
 #define IFLAGS_TB_MASK  (D_FLAG | IMM_FLAG | DRTI_FLAG | DRTE_FLAG | DRTB_FLAG)
     uint32_t iflags;
 
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 366fd3e..d7f513d 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -120,7 +120,7 @@ static inline int sign_extend(unsigned int val, unsigned int width)
 
 static inline void t_sync_flags(DisasContext *dc)
 {
-    /* Synch the tb dependant flags between translator and runtime.  */
+    /* Synch the tb dependent flags between translator and runtime.  */
     if (dc->tb_flags != dc->synced_flags) {
         tcg_gen_movi_tl(env_iflags, dc->tb_flags);
         dc->synced_flags = dc->tb_flags;
@@ -1122,7 +1122,7 @@ static void dec_store(DisasContext *dc)
     if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
         tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
         /* FIXME: if the alignment is wrong, we should restore the value
-         *        in memory. One possible way to acheive this is to probe
+         *        in memory. One possible way to achieve this is to probe
          *        the MMU prior to the memaccess, thay way we could put
          *        the alignment checks in between the probe and the mem
          *        access.
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 79e2558..71cb4e8 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -678,7 +678,7 @@ static inline int mips_vpe_active(CPUState *env)
     if (!(env->mvp->CP0_MVPControl & (1 << CP0MVPCo_EVP))) {
         active = 0;
     }
-    /* Check that the VPE is actived.  */
+    /* Check that the VPE is activated.  */
     if (!(env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))) {
         active = 0;
     }
diff --git a/target-mips/machine.c b/target-mips/machine.c
index be72b36..a506ee0 100644
--- a/target-mips/machine.c
+++ b/target-mips/machine.c
@@ -302,7 +302,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     for (i = 0; i < MIPS_FPU_MAX; i++)
         load_fpu(f, &env->fpus[i]);
 
-    /* XXX: ensure compatiblity for halted bit ? */
+    /* XXX: ensure compatibility for halted bit ? */
     tlb_flush(env, 1);
     return 0;
 }
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index e84108c..2d67d1f 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1004,7 +1004,7 @@ struct CPUPPCState {
     int error_code;
     uint32_t pending_interrupts;
 #if !defined(CONFIG_USER_ONLY)
-    /* This is the IRQ controller, which is implementation dependant
+    /* This is the IRQ controller, which is implementation dependent
      * and only relevant when emulating a complete machine.
      */
     uint32_t irq_input_state;
@@ -1024,7 +1024,7 @@ struct CPUPPCState {
 
     /* Those resources are used only in Qemu core */
     target_ulong hflags;      /* hflags is a MSR & HFLAGS_MASK         */
-    target_ulong hflags_nmsr; /* specific hflags, not comming from MSR */
+    target_ulong hflags_nmsr; /* specific hflags, not coming from MSR */
     int mmu_idx;         /* precomputed MMU index to speed up mem accesses */
 
     /* Power management */
diff --git a/target-ppc/mfrom_table_gen.c b/target-ppc/mfrom_table_gen.c
index 4c06aa4..a140ded 100644
--- a/target-ppc/mfrom_table_gen.c
+++ b/target-ppc/mfrom_table_gen.c
@@ -11,7 +11,7 @@ int main (void)
 
     printf("static const uint8_t mfrom_ROM_table[602] =\n{\n    ");
     for (i = 0; i < 602; i++) {
-        /* Extremly decomposed:
+        /* Extremely decomposed:
          *                    -T0 / 256
          * T0 = 256 * log10(10          + 1.0) + 0.5
          */
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 134b0c6..6339c95 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -1795,7 +1795,7 @@ void helper_rfsvc (void)
 /* 602 specific instructions */
 /* mfrom is the most crazy instruction ever seen, imho ! */
 /* Real implementation uses a ROM table. Do the same */
-/* Extremly decomposed:
+/* Extremely decomposed:
  *                      -arg / 256
  * return 256 * log10(10           + 1.0) + 0.5
  */
@@ -3070,7 +3070,7 @@ static inline uint32_t word_reverse(uint32_t val)
         (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
 }
 
-#define MASKBITS 16 // Random value - to be fixed (implementation dependant)
+#define MASKBITS 16 // Random value - to be fixed (implementation dependent)
 target_ulong helper_brinc (target_ulong arg1, target_ulong arg2)
 {
     uint32_t a, b, d, mask;
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index 5a1e15e..9df0719 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -814,7 +814,7 @@ int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr)
     /*
      * TODO : Evaluate CCR and check if the cache is on or off.
      *        Now CCR is not in CPUSH4State, but in SH7750State.
-     *        When you move the ccr inot CPUSH4State, the code will be
+     *        When you move the ccr into CPUSH4State, the code will be
      *        as follows.
      */
 #if 0
diff --git a/target-sparc/TODO b/target-sparc/TODO
index c87459f..b8c727e 100644
--- a/target-sparc/TODO
+++ b/target-sparc/TODO
@@ -15,7 +15,7 @@ CPU common:
  - NPC/PC static optimisations (use JUMP_TB when possible)? (Is this
  obsolete?)
  - Synthetic instructions
- - MMU model dependant on CPU model
+ - MMU model dependent on CPU model
  - Select ASI helper at translation time (on V9 only if known)
  - KQemu/KVM support for VM only
  - Hardware breakpoint/watchpoint support
commit 68dfbcd4d556056c904a6bda14b59242ba22e6cf
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Tue Nov 22 18:06:20 2011 +0800

    fix spelling in scripts sub directory
    
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 04ab990..cce8f86 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1901,7 +1901,7 @@ sub process {
 # printk should use KERN_* levels.  Note that follow on printk's on the
 # same line do not need a level, so we use the current block context
 # to try and find and validate the current printk.  In summary the current
-# printk includes all preceeding printk's which have no newline on the end.
+# printk includes all preceding printk's which have no newline on the end.
 # we assume the first bad printk is the one to report.
 		if ($line =~ /\bprintk\((?!KERN_)\s*"/) {
 			my $ok = 0;
commit dee3bffca79315d12c0a119b82d9cc5e954fc8bd
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Tue Nov 22 18:06:19 2011 +0800

    fix spelling in QMP sub directory
    
    Cc: Markus Armbruster <armbru at redhat.com>
    Acked-by: Luiz Capitulino <lcapitulino at redhat.com>
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt
index 0ce5d4e..af586ec 100644
--- a/QMP/qmp-events.txt
+++ b/QMP/qmp-events.txt
@@ -126,7 +126,7 @@ the authentication ID is not provided.
 VNC_DISCONNECTED
 ----------------
 
-Emitted when the conection is closed.
+Emitted when the connection is closed.
 
 Data:
 
commit cba919dad5bd5c314f25ced00dae999f6bbb5f54
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Tue Nov 22 18:06:18 2011 +0800

    fix spelling in libcacard sub directory
    
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/libcacard/card_7816.c b/libcacard/card_7816.c
index 6fe27d5..8d06326 100644
--- a/libcacard/card_7816.c
+++ b/libcacard/card_7816.c
@@ -125,7 +125,7 @@ vcard_response_new_bytes(VCard *card, unsigned char *buf, int len, int Le,
 }
 
 /*
- * get a new Reponse buffer that only has a status.
+ * get a new Response buffer that only has a status.
  */
 static VCardResponse *
 vcard_response_new_status(vcard_7816_status_t status)
@@ -239,7 +239,7 @@ vcard_apdu_set_class(VCardAPDU *apdu) {
 }
 
 /*
- * set the Le and Lc fiels according to table 5 of the
+ * set the Le and Lc fields according to table 5 of the
  * 7816-4 part 4 spec
  */
 static vcard_7816_status_t
diff --git a/libcacard/card_7816.h b/libcacard/card_7816.h
index 2bb2a0d..4a01993 100644
--- a/libcacard/card_7816.h
+++ b/libcacard/card_7816.h
@@ -23,7 +23,7 @@ VCardResponse *vcard_response_new_bytes(VCard *card, unsigned char *buf,
 /* response from just status bytes */
 VCardResponse *vcard_response_new_status_bytes(unsigned char sw1,
                                                unsigned char sw2);
-/* response from just status: NOTE this cannot fail, it will alwyas return a
+/* response from just status: NOTE this cannot fail, it will always return a
  * valid response, if it can't allocate memory, the response will be
  * VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE */
 VCardResponse *vcard_make_response(vcard_7816_status_t status);
diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index 397485c..bdc3c79 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -1250,7 +1250,7 @@ vcard_emul_usage(void)
 "  {card_type_to_emulate}  What card interface to present to the guest\n"
 "  {param_for_card}        Card interface specific parameters\n"
 "  {slot_name}             NSS slot that contains the certs\n"
-"  {vreader_name}          Virutal reader name to present to the guest\n"
+"  {vreader_name}          Virtual reader name to present to the guest\n"
 "  {certN}                 Nickname of the certificate n on the virtual card\n"
 "\n"
 "These parameters come as a single string separated by blanks or newlines."
diff --git a/libcacard/vscard_common.h b/libcacard/vscard_common.h
index 609ae98..08f68e4 100644
--- a/libcacard/vscard_common.h
+++ b/libcacard/vscard_common.h
@@ -44,7 +44,7 @@
  * to the existing messages, addition of fields.
  *
  * The major digit is for a breaking change of protocol, presumably
- * something that cannot be accomodated with the existing protocol.
+ * something that cannot be accommodated with the existing protocol.
  */
 
 #define VSCARD_VERSION MAKE_VERSION(0, 0, 2)
commit b4916d7b9d6b086d653db090d366ffe2f44c1323
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Tue Nov 22 18:06:17 2011 +0800

    fix spelling in linux-user sub directory
    
    Cc: Riku Voipio <riku.voipio at iki.fi>
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 4635bb2..ea61d0d 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2339,7 +2339,7 @@ static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
      * strictly necessary but we do it here for sake of completeness.
      */
 
-    /* find out lenght of the vector, AT_NULL is terminator */
+    /* find out length of the vector, AT_NULL is terminator */
     i = len = 0;
     do {
         get_user_ual(val, auxv);
diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index 1062da3..be79496 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -575,7 +575,7 @@ static int load_flat_file(struct linux_binprm * bprm,
      * help simplify all this mumbo jumbo
      *
      * We've got two different sections of relocation entries.
-     * The first is the GOT which resides at the begining of the data segment
+     * The first is the GOT which resides at the beginning of the data segment
      * and is terminated with a -1.  This one can be relocated in place.
      * The second is the extra relocation entries tacked after the image's
      * data segment. These require a little more processing as the entry is
diff --git a/linux-user/main.c b/linux-user/main.c
index d1bbc57..64d2208 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1638,7 +1638,7 @@ void cpu_loop(CPUPPCState *env)
             queue_signal(env, info.si_signo, &info);
             break;
         case POWERPC_EXCP_PIT:      /* Programmable interval timer IRQ       */
-            cpu_abort(env, "Programable interval timer interrupt "
+            cpu_abort(env, "Programmable interval timer interrupt "
                       "while in user mode. Aborting\n");
             break;
         case POWERPC_EXCP_IO:       /* IO error exception                    */
@@ -2434,7 +2434,7 @@ void cpu_loop (CPUState *env)
             if (env->iflags & D_FLAG) {
                 env->sregs[SR_ESR] |= 1 << 12;
                 env->sregs[SR_PC] -= 4;
-                /* FIXME: if branch was immed, replay the imm aswell.  */
+                /* FIXME: if branch was immed, replay the imm as well.  */
             }
 
             env->iflags &= ~(IMM_FLAG | D_FLAG);
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 78e3380..ded12ca 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -80,7 +80,7 @@ static uint8_t host_to_target_signal_table[_NSIG] = {
     [SIGSYS] = TARGET_SIGSYS,
     /* next signals stay the same */
     /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
-       host libpthread signals.  This assumes noone actually uses SIGRTMAX :-/
+       host libpthread signals.  This assumes no one actually uses SIGRTMAX :-/
        To fix this properly we need to do manual signal delivery multiplexed
        over a single host signal.  */
     [__SIGRTMIN] = __SIGRTMAX,
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 9dd1b8e..2857805 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -1,7 +1,7 @@
 /* common syscall defines for all architectures */
 
 /* Note: although the syscall numbers change between architectures,
-   most of them stay the same, so we handle it by puting ifdefs if
+   most of them stay the same, so we handle it by putting ifdefs if
    necessary */
 
 #include "syscall_nr.h"
@@ -669,7 +669,7 @@ typedef struct target_siginfo {
  * SIGBUS si_codes
  */
 #define TARGET_BUS_ADRALN       (1)	/* invalid address alignment */
-#define TARGET_BUS_ADRERR       (2)	/* non-existant physical address */
+#define TARGET_BUS_ADRERR       (2)	/* non-existent physical address */
 #define TARGET_BUS_OBJERR       (3)	/* object specific hardware error */
 
 /*
@@ -868,7 +868,7 @@ struct target_pollfd {
 #define TARGET_CDROM_GET_MCN		0x5311 /* Obtain the "Universal Product Code"
                                            if available (struct cdrom_mcn) */
 #define TARGET_CDROM_GET_UPC		TARGET_CDROM_GET_MCN  /* This one is depricated,
-                                          but here anyway for compatability */
+                                          but here anyway for compatibility */
 #define TARGET_CDROMRESET		0x5312 /* hard-reset the drive */
 #define TARGET_CDROMVOLREAD		0x5313 /* Get the drive's volume setting
                                           (struct cdrom_volctrl) */
commit bcb15d9c84a27f23a9b5c20b3c034a3f2fe9e2ac
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Tue Nov 22 18:06:16 2011 +0800

    fix spelling in darwin-user sub directory
    
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/darwin-user/machload.c b/darwin-user/machload.c
index 0aa8282..26dd293 100644
--- a/darwin-user/machload.c
+++ b/darwin-user/machload.c
@@ -460,7 +460,7 @@ int load_object(const char *filename, struct target_pt_regs * regs, void ** mh)
     int mach_hdr_pos = 0;
     struct mach_header mach_hdr;
 
-    /* for symbol lookup whith -d flag. */
+    /* for symbol lookup with -d flag. */
     struct symtab_command *    symtabcmd = 0;
     struct nlist_extended *symtab, *sym;
     struct nlist     *symtab_std, *syment;
@@ -645,7 +645,7 @@ int load_object(const char *filename, struct target_pt_regs * regs, void ** mh)
             case LC_PREBIND_CKSUM:
             case LC_SUB_LIBRARY:
                 break;
-            default: fprintf(stderr, "warning: unkown command 0x%x in '%s'\n", lc->cmd, filename);
+            default: fprintf(stderr, "warning: unknown command 0x%x in '%s'\n", lc->cmd, filename);
         }
         lc = (struct load_command*)((int)(lc)+(lc->cmdsize));
     }
@@ -809,7 +809,7 @@ unsigned long setup_arg_pages(void * mh, char ** argv, char ** env)
         page_set_flags((int)env[i], (int)(env[i]+strlen(env[i])), PROT_READ | PAGE_VALID);
     }
 
-    /* Add on the stack the interp_prefix choosen if so */
+    /* Add on the stack the interp_prefix chosen if so */
     if(interp_prefix[0])
     {
         char *dyld_root;
diff --git a/darwin-user/main.c b/darwin-user/main.c
index c0f14f8..9b57c20 100644
--- a/darwin-user/main.c
+++ b/darwin-user/main.c
@@ -394,7 +394,7 @@ void cpu_loop(CPUPPCState *env)
             queue_signal(info.si_signo, &info);
             break;
         case POWERPC_EXCP_PIT:      /* Programmable interval timer IRQ       */
-            cpu_abort(env, "Programable interval timer interrupt "
+            cpu_abort(env, "Programmable interval timer interrupt "
                       "while in user mode. Aborting\n");
             break;
         case POWERPC_EXCP_IO:       /* IO error exception                    */
diff --git a/darwin-user/syscall.c b/darwin-user/syscall.c
index f3cc1f8..8a16883 100644
--- a/darwin-user/syscall.c
+++ b/darwin-user/syscall.c
@@ -755,7 +755,7 @@ struct attrbuf_header {
 
 static inline void byteswap_attrbuf(struct attrbuf_header *attrbuf, struct attrlist *attrlist)
 {
-    DPRINTF("attrBuf.lenght %lx\n", attrbuf->length);
+    DPRINTF("attrBuf.length %lx\n", attrbuf->length);
 }
 
 static inline void byteswap_statfs(struct statfs *s)
commit 7a4bbe8dab2c4e9f900e26172b6b6f831d3d5bb0
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Nov 19 20:18:39 2011 +0100

    darwin-user: Fix format string in debug message
    
    This was spotted by cppcheck.
    
    Reviewed-by: 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/darwin-user/signal.c b/darwin-user/signal.c
index c530227..317ef92 100644
--- a/darwin-user/signal.c
+++ b/darwin-user/signal.c
@@ -270,8 +270,7 @@ int do_sigaction(int sig, const struct sigaction *act,
         host_sig = target_to_host_signal(sig);
         if (host_sig != SIGSEGV && host_sig != SIGBUS) {
 #if defined(DEBUG_SIGNAL)
-    fprintf(stderr, "sigaction handler going to call sigaction\n",
-            act->sa_handler, act->sa_flags, act->sa_mask);
+            fprintf(stderr, "sigaction handler going to call sigaction\n");
 #endif
 
             sigfillset(&act1.sa_mask);
commit c91bbffb41ecb80336e03aa069b7ea27cf150453
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 9 19:45:38 2011 +0000

    MAINTAINERS: Delete spurious '.'
    
    Signed-off-by: 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 06df70c..e22bfa1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20,7 +20,7 @@ Descriptions of section entries:
 	   Supported:	Someone is actually paid to look after this.
 	   Maintained:	Someone actually looks after it.
 	   Odd Fixes:	It has a maintainer but they don't have time to do
-			much other than throw the odd patch in. See below..
+			much other than throw the odd patch in. See below.
 	   Orphan:	No current maintainer [but maybe you could take the
 			role as you write your new code].
 	   Obsolete:	Old code. Something tagged obsolete generally means
commit 66d3f1962d81c3516d100e2417a9be7a6ae5f73f
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Nov 9 09:52:55 2011 +0100

    qxl: Don't convert from size_t to int and back in qxl_cursor()
    
    Just for cleanliness; it would take a truly gigantic cursor to break.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 2c51ba9..133d093 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -157,7 +157,7 @@ static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor)
 {
     QEMUCursor *c;
     uint8_t *image, *mask;
-    int size;
+    size_t size;
 
     c = cursor_alloc(cursor->header.width, cursor->header.height);
     c->hot_x = cursor->header.hot_spot_x;
commit d18058962133a00ec5731657fb34146f9c7dd572
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Sun Nov 6 22:48:50 2011 +0100

    sonic: fix typo
    
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/dp8393x.c b/hw/dp8393x.c
index f66844b..cfec4cb 100644
--- a/hw/dp8393x.c
+++ b/hw/dp8393x.c
@@ -515,7 +515,7 @@ static void write_register(dp8393xState *s, int reg, uint16_t val)
     switch (reg) {
         /* Command register */
         case SONIC_CR:
-            do_command(s, val);;
+            do_command(s, val);
             break;
         /* Prevent write to read-only registers */
         case SONIC_CAP2:
commit 1c8a881daaca6fe0646a425b0970fb3ad25f6732
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Dec 1 14:04:21 2011 -0600

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

diff --git a/VERSION b/VERSION
index 490438d..d3827e7 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.15.94
+1.0
commit 9b129408589b2ed7bb2cdea03d2aba46a5fd74d4
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Nov 29 16:47:49 2011 -0600

    Makefile: use full path for qapi-generated directory
    
    Generally $(BUILD_DIR) == $(CURDIR), but that isn't necessarilly the
    case, so use $(BUILD_DIR)/qapi-generated for generated files to
    avoid potentionally sticking generating files in odd places outside
    the build's include paths.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index 7c93739..301c75e 100644
--- a/Makefile
+++ b/Makefile
@@ -168,7 +168,7 @@ check-qjson: check-qjson.o $(qobject-obj-y) $(tools-obj-y)
 test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(tools-obj-y)
 
 $(qapi-obj-y): $(GENERATED_HEADERS)
-qapi-dir := qapi-generated
+qapi-dir := $(BUILD_DIR)/qapi-generated
 test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
 
commit d8e1f214a0046b85f5297b0396f3678531b8982d
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Nov 29 16:47:48 2011 -0600

    qapi: fix guardname generation
    
    Fix a bug in handling dotted paths, and exclude directory prefixes
    from generated guardnames to avoid odd/pseudo-random guardnames in
    generated headers.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/scripts/qapi.py b/scripts/qapi.py
index 5299976..6e05469 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -200,6 +200,7 @@ def basename(filename):
     return filename.split("/")[-1]
 
 def guardname(filename):
-    if filename.startswith('./'):
-        filename = filename[2:]
-    return filename.replace("/", "_").replace("-", "_").split(".")[0].upper() + '_H'
+    guard = basename(filename).rsplit(".", 1)[0]
+    for substr in [".", " ", "-"]:
+        guard = guard.replace(substr, "_")
+    return guard.upper() + '_H'
commit 85e83264b2acaaeaf737386d693373c39c30cb0d
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Nov 28 11:37:57 2011 -0600

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

diff --git a/VERSION b/VERSION
index 82fd641..490438d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.15.93
+0.15.94
commit 7e62255a4b3e0e2ab84a3ec7398640e8ed58620a
Author: Markus Armbruster <armbru at redhat.com>
Date:   Mon Nov 28 20:27:37 2011 +0100

    ccid: Fix buffer overrun in handling of VSC_ATR message
    
    ATR size exceeding the limit is diagnosed, but then we merrily use it
    anyway, overrunning card->atr[].
    
    The message is read from a character device.  Obvious security
    implications unless the other end of the character device is trusted.
    
    Spotted by Coverity.  CVE-2011-4111.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
index 2cbc81b..9f51c6c 100644
--- a/hw/ccid-card-passthru.c
+++ b/hw/ccid-card-passthru.c
@@ -150,6 +150,7 @@ static void ccid_card_vscard_handle_message(PassthruState *card,
             error_report("ATR size exceeds spec, ignoring");
             ccid_card_vscard_send_error(card, scr_msg_header->reader_id,
                                         VSC_GENERAL_ERROR);
+            break;
         }
         memcpy(card->atr, data, scr_msg_header->length);
         card->atr_length = scr_msg_header->length;
commit aea317aaa5d92ee8789f976ccf105be67d956f5e
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Nov 28 12:45:28 2011 -0600

    Revert "fix out of tree build"
    
    This reverts commit be85c90b74f56dca51782fa3080fcdf88593e045.
    
    This patch is incorrect and breaks the build with a freshly cloned git tree.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index b06599c..7c93739 100644
--- a/Makefile
+++ b/Makefile
@@ -168,7 +168,7 @@ check-qjson: check-qjson.o $(qobject-obj-y) $(tools-obj-y)
 test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(tools-obj-y)
 
 $(qapi-obj-y): $(GENERATED_HEADERS)
-qapi-dir := $(SRC_PATH)/qapi-generated
+qapi-dir := qapi-generated
 test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
 
commit 023ddd743136d2b1f7a2e6b3772736f96bfca1ff
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Thu Nov 24 16:11:31 2011 +0400

    configure: avoid screening of --{en, dis}able-usb-redir options
    
    --*dir) option pattern precede --{en,dis}able-usb-redir) patterns in the
    option analysis switch, making the latter options have no effect.
    
    There were some --*dir that are supported by Autoconf and not by QEMU configure.
    The aim was to let QEMU packagers use the rpm (or similar) macro that overrides
    directories for their distribution.
    
    Replace --*dir with exact option names.
    
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index a7caf1e..ac4840d 100755
--- a/configure
+++ b/configure
@@ -569,6 +569,14 @@ for opt do
   ;;
   --sysconfdir=*) sysconfdir="$optarg"
   ;;
+  --sbindir=*|--libexecdir=*|--sharedstatedir=*|--localstatedir=*|\
+  --oldincludedir=*|--datarootdir=*|--infodir=*|--localedir=*|\
+  --htmldir=*|--dvidir=*|--pdfdir=*|--psdir=*)
+    # These switches are silently ignored, for compatibility with
+    # autoconf-generated configure scripts. This allows QEMU's
+    # configure to be used by RPM and similar macros that set
+    # lots of directory switches by default.
+  ;;
   --disable-sdl) sdl="no"
   ;;
   --enable-sdl) sdl="yes"
@@ -759,8 +767,6 @@ for opt do
   ;;
   --enable-opengl) opengl="yes"
   ;;
-  --*dir)
-  ;;
   --disable-rbd) rbd="no"
   ;;
   --enable-rbd) rbd="yes"
commit eba90e4efc80bc30c7d952ee6ea442207517a0da
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Nov 22 09:46:06 2011 +0100

    cutils: Make strtosz & friends leave follow set to callers
    
    strtosz() & friends require the size to be at the end of the string,
    or be followed by whitespace or ','.  I find this surprising, because
    the name suggests it works like strtol().
    
    The check simplifies callers that accept exactly that follow set
    slightly.  No such callers exist.
    
    The check is redundant for callers that accept a smaller follow set,
    and thus need to check themselves anyway.  Right now, this is the case
    for all but one caller.  All of them neglected to check, or checked
    incorrectly, but the previous few commits fixed them up.
    
    Finally, the check is problematic for callers that accept a larger
    follow set.  This is the case in monitor_parse_command().
    Fortunately, the problems there are relatively harmless.
    
    monitor_parse_command() uses strtosz() for argument type 'o'.  When
    the last argument is of type 'o', a trailing ',' is diagnosed
    differently than other trailing junk:
    
        (qemu) migrate_set_speed 1x
        invalid size
        (qemu) migrate_set_speed 1,
        migrate_set_speed: extraneous characters at the end of line
    
    A related inconsistency exists with non-last arguments.  No such
    command exists, but let's use memsave to explore the inconsistency.
    
    The monitor permits, but does not require whitespace between
    arguments.  For instance, "memsave (1-1)1024foo" is parsed as command
    memsave with three arguments 0, 1024 and "foo".  Yes, this is daft,
    but at least it's consistently daft.
    
    If I change memsave's second argument from 'i' to 'o', then "memsave
    (1-1)1foo" is rejected, because the size is followed by an 'f'.  But
    "memsave (1-1)1," is still accepted, and duly saves to file ",".
    
    We don't have any users of strtosz that profit from the check.  In the
    users we have, it appears to encourage sloppy error checking, or gets
    in the way.  Drop the bothersome check.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/cutils.c b/cutils.c
index 55b0596..6db6304 100644
--- a/cutils.c
+++ b/cutils.c
@@ -315,18 +315,34 @@ int fcntl_setfl(int fd, int flag)
 }
 #endif
 
+static int64_t suffix_mul(char suffix, int64_t unit)
+{
+    switch (qemu_toupper(suffix)) {
+    case STRTOSZ_DEFSUFFIX_B:
+        return 1;
+    case STRTOSZ_DEFSUFFIX_KB:
+        return unit;
+    case STRTOSZ_DEFSUFFIX_MB:
+        return unit * unit;
+    case STRTOSZ_DEFSUFFIX_GB:
+        return unit * unit * unit;
+    case STRTOSZ_DEFSUFFIX_TB:
+        return unit * unit * unit * unit;
+    }
+    return -1;
+}
+
 /*
  * Convert string to bytes, allowing either B/b for bytes, K/k for KB,
  * M/m for MB, G/g for GB or T/t for TB. End pointer will be returned
- * in *end, if not NULL. A valid value must be terminated by
- * whitespace, ',' or '\0'. Return -1 on error.
+ * in *end, if not NULL. Return -1 on error.
  */
 int64_t strtosz_suffix_unit(const char *nptr, char **end,
                             const char default_suffix, int64_t unit)
 {
     int64_t retval = -1;
     char *endptr;
-    unsigned char c, d;
+    unsigned char c;
     int mul_required = 0;
     double val, mul, integral, fraction;
 
@@ -339,51 +355,17 @@ int64_t strtosz_suffix_unit(const char *nptr, char **end,
     if (fraction != 0) {
         mul_required = 1;
     }
-    /*
-     * Any whitespace character is fine for terminating the number,
-     * in addition we accept ',' to handle strings where the size is
-     * part of a multi token argument.
-     */
     c = *endptr;
-    d = c;
-    if (qemu_isspace(c) || c == '\0' || c == ',') {
-        c = 0;
-        d = default_suffix;
+    mul = suffix_mul(c, unit);
+    if (mul >= 0) {
+        endptr++;
+    } else {
+        mul = suffix_mul(default_suffix, unit);
+        assert(mul >= 0);
     }
-    switch (qemu_toupper(d)) {
-    case STRTOSZ_DEFSUFFIX_B:
-        mul = 1;
-        if (mul_required) {
-            goto fail;
-        }
-        break;
-    case STRTOSZ_DEFSUFFIX_KB:
-        mul = unit;
-        break;
-    case STRTOSZ_DEFSUFFIX_MB:
-        mul = unit * unit;
-        break;
-    case STRTOSZ_DEFSUFFIX_GB:
-        mul = unit * unit * unit;
-        break;
-    case STRTOSZ_DEFSUFFIX_TB:
-        mul = unit * unit * unit * unit;
-        break;
-    default:
+    if (mul == 1 && mul_required) {
         goto fail;
     }
-    /*
-     * If not terminated by whitespace, ',', or \0, increment endptr
-     * to point to next character, then check that we are terminated
-     * by an appropriate separating character, ie. whitespace, ',', or
-     * \0. If not, we are seeing trailing garbage, thus fail.
-     */
-    if (c != 0) {
-        endptr++;
-        if (!qemu_isspace(*endptr) && *endptr != ',' && *endptr != 0) {
-            goto fail;
-        }
-    }
     if ((val * mul >= INT64_MAX) || val < 0) {
         goto fail;
     }
commit e36b369577784ac59a7d74725368eec66f23ad52
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Nov 22 09:46:05 2011 +0100

    qemu-img: Tighten parsing of size arguments
    
    strtosz_suffix() fails unless the size is followed by 0, whitespace or
    ','.  Useless here, because we need to fail for any junk following the
    size, even if it starts with whitespace or ','.  Check manually.
    Things like "qemu-img create xxx 1024," and "qemu-img convert -S '1024
    junk'" are now caught.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-img.c b/qemu-img.c
index 86127f0..8bdae66 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -332,8 +332,9 @@ static int img_create(int argc, char **argv)
     /* Get image size, if specified */
     if (optind < argc) {
         int64_t sval;
-        sval = strtosz_suffix(argv[optind++], NULL, STRTOSZ_DEFSUFFIX_B);
-        if (sval < 0) {
+        char *end;
+        sval = strtosz_suffix(argv[optind++], &end, STRTOSZ_DEFSUFFIX_B);
+        if (sval < 0 || *end) {
             error_report("Invalid image size specified! You may use k, M, G or "
                   "T suffixes for ");
             error_report("kilobytes, megabytes, gigabytes and terabytes.");
@@ -710,8 +711,9 @@ static int img_convert(int argc, char **argv)
         case 'S':
         {
             int64_t sval;
-            sval = strtosz_suffix(optarg, NULL, STRTOSZ_DEFSUFFIX_B);
-            if (sval < 0) {
+            char *end;
+            sval = strtosz_suffix(optarg, &end, STRTOSZ_DEFSUFFIX_B);
+            if (sval < 0 || *end) {
                 error_report("Invalid minimum zero buffer size for sparse output specified");
                 return 1;
             }
commit 45009a3087b4acd8b1c91fcd0b1ee723ac3b0aec
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Nov 22 09:46:04 2011 +0100

    x86/cpuid: Tighten parsing of tsc_freq=FREQ
    
    cpu_x86_find_by_name() uses strtosz_suffix_unit(), but screws up the
    error checking.  It detects some failures, but not all.  Undetected
    failures result in a zero tsc_khz value (error value -1 divided by
    1000), which means "no tsc_freq set".
    
    To reproduce, try "-cpu qemu64,tsc_freq=9999999T".
    strtosz_suffix_unit() fails, because the value overflows int64_t,
    
    Signed-off-by: Markus Armbruster <armbru 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 9fc9769..0b3af90 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -711,7 +711,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
 
                 tsc_freq = strtosz_suffix_unit(val, &err,
                                                STRTOSZ_DEFSUFFIX_B, 1000);
-                if (!*val || *err) {
+                if (tsc_freq < 0 || *err) {
                     fprintf(stderr, "bad numerical value %s\n", val);
                     goto error;
                 }
commit 961b42b9dc858936f32effc3f47c76b1c4e7de56
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Nov 22 09:46:03 2011 +0100

    vl: Tighten parsing of -m argument
    
    strtosz_suffix() fails unless the size is followed by 0, whitespace or
    ','.  Useless here, because we need to fail for any junk following the
    size, even if it starts with whitespace or ','.  Check manually.
    Things like "-m 1024," are now caught.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index b9146cf..a50842b 100644
--- a/vl.c
+++ b/vl.c
@@ -2535,9 +2535,10 @@ int main(int argc, char **argv, char **envp)
                 break;
             case QEMU_OPTION_m: {
                 int64_t value;
+                char *end;
 
-                value = strtosz(optarg, NULL);
-                if (value < 0) {
+                value = strtosz(optarg, &end);
+                if (value < 0 || *end) {
                     fprintf(stderr, "qemu: invalid ram size: %s\n", optarg);
                     exit(1);
                 }
commit c03417b438624988f1a027ce7829696ac98c3165
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Nov 22 09:46:02 2011 +0100

    vl: Tighten parsing of -numa's parameter mem
    
    strtosz_suffix() fails unless the size is followed by 0, whitespace or
    ','.  Useless here, because we need to fail for any junk following the
    size, even if it starts with whitespace or ','.  Check manually.
    
    Things like
    
        -smp 4 -numa "node,mem=1024,cpus=0-1" -numa "node,mem=1024 cpus=2-3"
    
    are now caught.  Before, the second -numa's argument was silently
    interpreted as just "node,mem=1024".
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index f5afed4..b9146cf 100644
--- a/vl.c
+++ b/vl.c
@@ -953,8 +953,8 @@ static void numa_add(const char *optarg)
             node_mem[nodenr] = 0;
         } else {
             int64_t sval;
-            sval = strtosz(option, NULL);
-            if (sval < 0) {
+            sval = strtosz(option, &endptr);
+            if (sval < 0 || *endptr) {
                 fprintf(stderr, "qemu: invalid numa mem size: %s\n", optarg);
                 exit(1);
             }
commit 8dddfb553151724a6a2110e56e8ced3213faf750
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Nov 22 09:46:01 2011 +0100

    cutils: Drop broken support for zero strtosz default_suffix
    
    Commit 9f9b17a4's strtosz() defaults a missing suffix to 'M', except
    it rejects fractions then (switch case 0).
    
    When commit d8427002 introduced strtosz_suffix(), that changed:
    fractions are no longer rejected, because we go to switch case 'M' on
    missing suffix now.  Not mentioned in commit message, probably
    unintentional.  Not worth changing back now.
    
    Because case 0 is still around, you can get the old behavior by
    passing a zero default_suffix to strtosz_suffix() or
    strtosz_suffix_unit().  Undocumented and not used.  Drop.
    
    Commit d8427002 also neglected to update the function comment.  Fix it
    up.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/cutils.c b/cutils.c
index 5d995bc..55b0596 100644
--- a/cutils.c
+++ b/cutils.c
@@ -317,10 +317,9 @@ int fcntl_setfl(int fd, int flag)
 
 /*
  * Convert string to bytes, allowing either B/b for bytes, K/k for KB,
- * M/m for MB, G/g for GB or T/t for TB. Default without any postfix
- * is MB. End pointer will be returned in *end, if not NULL. A valid
- * value must be terminated by whitespace, ',' or '\0'. Return -1 on
- * error.
+ * M/m for MB, G/g for GB or T/t for TB. End pointer will be returned
+ * in *end, if not NULL. A valid value must be terminated by
+ * whitespace, ',' or '\0'. Return -1 on error.
  */
 int64_t strtosz_suffix_unit(const char *nptr, char **end,
                             const char default_suffix, int64_t unit)
@@ -349,11 +348,7 @@ int64_t strtosz_suffix_unit(const char *nptr, char **end,
     d = c;
     if (qemu_isspace(c) || c == '\0' || c == ',') {
         c = 0;
-        if (default_suffix) {
-            d = default_suffix;
-        } else {
-            d = c;
-        }
+        d = default_suffix;
     }
     switch (qemu_toupper(d)) {
     case STRTOSZ_DEFSUFFIX_B:
@@ -365,10 +360,6 @@ int64_t strtosz_suffix_unit(const char *nptr, char **end,
     case STRTOSZ_DEFSUFFIX_KB:
         mul = unit;
         break;
-    case 0:
-        if (mul_required) {
-            goto fail;
-        }
     case STRTOSZ_DEFSUFFIX_MB:
         mul = unit * unit;
         break;
commit 21d4a791da47cf35956102d0b96208e3e595b617
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Nov 23 11:24:25 2011 +0200

    configure: tighten pie toolchain support test for tls variables
    
    Some toolchains don't support pie properly when tls variables are
    in use.  Disallow pie when such toolchains are detected.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index f033438..a7caf1e 100755
--- a/configure
+++ b/configure
@@ -1120,7 +1120,17 @@ fi
 
 if test "$pie" != "no" ; then
   cat > $TMPC << EOF
-int main(void) { return 0; }
+
+#ifdef __linux__
+#  define THREAD __thread
+#else
+#  define THREAD
+#endif
+
+static THREAD int tls_var;
+
+int main(void) { return tls_var; }
+
 EOF
   if compile_prog "-fPIE -DPIE" "-pie"; then
     QEMU_CFLAGS="-fPIE -DPIE $QEMU_CFLAGS"
commit c1b71a1df682fc49f91218130b1837d6d91dcb57
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sat Nov 19 10:22:47 2011 +0100

    usb-redir: Don't try to write to the chardev after a close event
    
    Since we handle close async in a bh, do_write and thus write can get
    called after receiving a close event. This patch adds a check to
    the usb-redir write callback to not call qemu_chr_fe_write on a closed
    backend.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/usb-redir.c b/usb-redir.c
index 24fdd31..fb91c92 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -225,6 +225,10 @@ 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);
 }
 
commit 99f08100cd2b35a35e1c5b2e6b043911a568906c
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sat Nov 19 10:22:46 2011 +0100

    usb-redir: Device disconnect + re-connect robustness fixes
    
    These fixes mainly target the other side sending some (error status)
    packets after a disconnect packet. In some cases these would get queued
    up and then reported to the controller when a new device gets connected.
    
    * Fully reset device state on disconnect
    * Don't allow a connect message when already connected
    * Ignore iso and interrupt status messages when disconnected
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/usb-redir.c b/usb-redir.c
index 9e13410..24fdd31 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -881,6 +881,11 @@ static void usbredir_device_connect(void *priv,
 {
     USBRedirDevice *dev = priv;
 
+    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:
         DPRINTF("attaching low speed device\n");
@@ -909,19 +914,26 @@ static void usbredir_device_connect(void *priv,
 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);
-        usbredir_cleanup_device_queues(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);
+    }
 }
 
 static void usbredir_interface_info(void *priv,
@@ -1013,6 +1025,10 @@ static void usbredir_iso_stream_status(void *priv, uint32_t id,
     DPRINTF("iso status %d ep %02X id %u\n", iso_stream_status->status,
             ep, id);
 
+    if (!dev->dev.attached) {
+        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);
@@ -1030,6 +1046,10 @@ static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
     DPRINTF("interrupt recv status %d ep %02X id %u\n",
             interrupt_receiving_status->status, ep, id);
 
+    if (!dev->dev.attached) {
+        return;
+    }
+
     dev->endpoint[EP2I(ep)].interrupt_error =
         interrupt_receiving_status->status;
     if (interrupt_receiving_status->status == usb_redir_stall) {
commit 65f9d98673cb04436257628958177516416456fa
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sat Nov 19 10:22:45 2011 +0100

    usb-redir: Call qemu_chr_fe_open/close
    
    To let the chardev now we're ready start receiving data. This is necessary
    with the spicevmc chardev to get it registered with the spice-server.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/usb-redir.c b/usb-redir.c
index c74b156..9e13410 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -814,6 +814,8 @@ static int usbredir_initfn(USBDevice *udev)
     /* 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);
 
@@ -837,6 +839,7 @@ 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);
commit f76e4c7f16c7ab966a792310b6630d3e240688b3
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sat Nov 19 10:22:44 2011 +0100

    spice-qemu-char: Generate chardev open/close events
    
    Define a state callback and make that generate chardev open/close events when
    called by the spice-server.
    
    Notes:
    
    1) For all but the newest spice-server versions (which have a fix for this)
    the code ignores these events for a spicevmc with a subtype of vdagent, this
    subtype specific knowledge is undesirable, but unavoidable for now, see:
    http://lists.freedesktop.org/archives/spice-devel/2011-July/004837.html
    
    2) This code deliberately sends the events immediately rather then from a
    bh. This is done this way because:
    a) There is no need to do it from a bh; and
    b) Doing it from a bh actually causes issues because the spice-server may send
    data immediately after the open and when the open runs from a bh, then
    qemu_chr_be_can_write will return 0 for the first write which the spice-server
    does not expect, when this happens the spice-server will never retry the write
    causing communication to stall.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index ac52202..7e8eaa9 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -69,11 +69,40 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
     return bytes;
 }
 
+static void vmc_state(SpiceCharDeviceInstance *sin, int connected)
+{
+    SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
+
+#if SPICE_SERVER_VERSION < 0x000901
+    /*
+     * spice-server calls the state callback for the agent channel when the
+     * spice client connects / disconnects. Given that not the client but
+     * the server is doing the parsing of the messages this is wrong as the
+     * server is still listening. Worse, this causes the parser in the server
+     * to go out of sync, so we ignore state calls for subtype vdagent
+     * spicevmc chardevs. For the full story see:
+     * http://lists.freedesktop.org/archives/spice-devel/2011-July/004837.html
+     */
+    if (strcmp(sin->subtype, "vdagent") == 0) {
+        return;
+    }
+#endif
+
+    if ((scd->chr->opened && connected) ||
+        (!scd->chr->opened && !connected)) {
+        return;
+    }
+
+    qemu_chr_be_event(scd->chr,
+                      connected ? CHR_EVENT_OPENED : CHR_EVENT_CLOSED);
+}
+
 static SpiceCharDeviceInterface vmc_interface = {
     .base.type          = SPICE_INTERFACE_CHAR_DEVICE,
     .base.description   = "spice virtual channel char device",
     .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
     .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
+    .state              = vmc_state,
     .write              = vmc_write,
     .read               = vmc_read,
 };
@@ -197,7 +226,12 @@ int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr)
     chr->chr_guest_open = spice_chr_guest_open;
     chr->chr_guest_close = spice_chr_guest_close;
 
-    qemu_chr_generic_open(chr);
+#if SPICE_SERVER_VERSION < 0x000901
+    /* See comment in vmc_state() */
+    if (strcmp(subtype, "vdagent") == 0) {
+        qemu_chr_generic_open(chr);
+    }
+#endif
 
     *_chr = chr;
     return 0;
commit a425d23f8fad482f7792745036896eb2f72330de
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sat Nov 19 10:22:43 2011 +0100

    qemu-char: rename qemu_chr_event to qemu_chr_be_event and make it public
    
    Rename qemu_chr_event to qemu_chr_be_event, since it is only to be
    called by backends and make it public so that it can be used by chardev
    code which lives outside of qemu-char.c
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index b562bf8..27abcb9 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -106,7 +106,7 @@
 static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
     QTAILQ_HEAD_INITIALIZER(chardevs);
 
-static void qemu_chr_event(CharDriverState *s, int event)
+void qemu_chr_be_event(CharDriverState *s, int event)
 {
     /* Keep track if the char device is open */
     switch (event) {
@@ -126,7 +126,7 @@ static void qemu_chr_event(CharDriverState *s, int event)
 static void qemu_chr_generic_open_bh(void *opaque)
 {
     CharDriverState *s = opaque;
-    qemu_chr_event(s, CHR_EVENT_OPENED);
+    qemu_chr_be_event(s, CHR_EVENT_OPENED);
     qemu_bh_delete(s->bh);
     s->bh = NULL;
 }
@@ -359,7 +359,7 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
             bdrv_commit_all();
             break;
         case 'b':
-            qemu_chr_event(chr, CHR_EVENT_BREAK);
+            qemu_chr_be_event(chr, CHR_EVENT_BREAK);
             break;
         case 'c':
             /* Switch to the next registered device */
@@ -580,7 +580,7 @@ static void fd_chr_read(void *opaque)
     if (size == 0) {
         /* FD has been closed. Remove it from the active list.  */
         qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL);
-        qemu_chr_event(chr, CHR_EVENT_CLOSED);
+        qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
         return;
     }
     if (size > 0) {
@@ -613,7 +613,7 @@ static void fd_chr_close(struct CharDriverState *chr)
     }
 
     g_free(s);
-    qemu_chr_event(chr, CHR_EVENT_CLOSED);
+    qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
 /* open a character device to a unix fd */
@@ -715,7 +715,7 @@ static void stdio_read(void *opaque)
     if (size == 0) {
         /* stdin has been closed. Remove it from the active list.  */
         qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL);
-        qemu_chr_event(chr, CHR_EVENT_CLOSED);
+        qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
         return;
     }
     if (size > 0) {
@@ -977,7 +977,7 @@ static void pty_chr_close(struct CharDriverState *chr)
     qemu_del_timer(s->timer);
     qemu_free_timer(s->timer);
     g_free(s);
-    qemu_chr_event(chr, CHR_EVENT_CLOSED);
+    qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
 static int qemu_chr_open_pty(QemuOpts *opts, CharDriverState **_chr)
@@ -1355,7 +1355,7 @@ static void pp_close(CharDriverState *chr)
     ioctl(fd, PPRELEASE);
     close(fd);
     g_free(drv);
-    qemu_chr_event(chr, CHR_EVENT_CLOSED);
+    qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
 static int qemu_chr_open_pp(QemuOpts *opts, CharDriverState **_chr)
@@ -1500,7 +1500,7 @@ static void win_chr_close(CharDriverState *chr)
     else
         qemu_del_polling_cb(win_chr_poll, chr);
 
-    qemu_chr_event(chr, CHR_EVENT_CLOSED);
+    qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
 static int win_chr_init(CharDriverState *chr, const char *filename)
@@ -2108,7 +2108,7 @@ static void udp_chr_close(CharDriverState *chr)
         closesocket(s->fd);
     }
     g_free(s);
-    qemu_chr_event(chr, CHR_EVENT_CLOSED);
+    qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
 static int qemu_chr_open_udp(QemuOpts *opts, CharDriverState **_chr)
@@ -2213,7 +2213,7 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr,
             } else {
                 if ((unsigned char)buf[i] == IAC_BREAK && s->do_telnetopt == 2) {
                     /* Handle IAC break commands by sending a serial break */
-                    qemu_chr_event(chr, CHR_EVENT_BREAK);
+                    qemu_chr_be_event(chr, CHR_EVENT_BREAK);
                     s->do_telnetopt++;
                 }
                 s->do_telnetopt++;
@@ -2321,7 +2321,7 @@ static void tcp_chr_read(void *opaque)
         qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
         closesocket(s->fd);
         s->fd = -1;
-        qemu_chr_event(chr, CHR_EVENT_CLOSED);
+        qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
     } else if (size > 0) {
         if (s->do_telnetopt)
             tcp_chr_process_IAC_bytes(chr, s, buf, &size);
@@ -2433,7 +2433,7 @@ static void tcp_chr_close(CharDriverState *chr)
         closesocket(s->listen_fd);
     }
     g_free(s);
-    qemu_chr_event(chr, CHR_EVENT_CLOSED);
+    qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
 static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
diff --git a/qemu-char.h b/qemu-char.h
index 7efcf99..8ca1e2d 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -212,6 +212,16 @@ int qemu_chr_be_can_write(CharDriverState *s);
  */
 void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len);
 
+
+/**
+ * @qemu_chr_be_event:
+ *
+ * Send an event from the back end to the front end.
+ *
+ * @event the event to send
+ */
+void qemu_chr_be_event(CharDriverState *s, int event);
+
 void qemu_chr_add_handlers(CharDriverState *s,
                            IOCanReadHandler *fd_can_read,
                            IOReadHandler *fd_read,
commit 2507718baf311ea78156c6777d38410a9f89ce89
Author: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
Date:   Wed Nov 23 11:46:27 2011 +0530

    9pfs: improve portability to older systems
    
    I guess we can also make sure we don't  call local_ioc_getversion at
    all.
    
    Reported-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index cbd07e8..99ef0cd 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -717,10 +717,14 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path,
 
 static int local_init(FsContext *ctx)
 {
-    int err;
+    int err = 0;
     struct statfs stbuf;
 
     ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
+#ifdef FS_IOC_GETVERSION
+    /*
+     * use ioc_getversion only if the iocl is definied
+     */
     err = statfs(ctx->fs_root, &stbuf);
     if (!err) {
         switch (stbuf.f_type) {
@@ -732,6 +736,7 @@ static int local_init(FsContext *ctx)
             break;
         }
     }
+#endif
     return err;
 }
 
commit 51711aee8cb0b17d53872cc06fe73af50c7d9ebd
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Nov 24 23:16:10 2011 +0100

    tci: Make flush_icache_range() inline
    
    This is standard for other tcg targets and improves tci, too.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c
index 942910e..fc0880c 100644
--- a/tcg/tci/tcg-target.c
+++ b/tcg/tci/tcg-target.c
@@ -373,10 +373,6 @@ static const char *const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
 };
 #endif
 
-static void flush_icache_range(unsigned long start, unsigned long stop)
-{
-}
-
 static void patch_reloc(uint8_t *code_ptr, int type,
                         tcg_target_long value, tcg_target_long addend)
 {
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
index cb5858c..03e0fd1 100644
--- a/tcg/tci/tcg-target.h
+++ b/tcg/tci/tcg-target.h
@@ -157,4 +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)
+{
+}
+
 #endif /* TCG_TARGET_H */
commit c16ada980f439c414eac83d184ac9fb66ed60cc0
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Nov 23 22:20:30 2011 +0100

    eepro100: Fix alignment requirement for statistical counters
    
    According to Intel's Open Source Software Developer Manual,
    the dump counters address must be Dword aligned.
    
    The new code enforces this alignment, so s->statsaddr may now
    be used with stw_le_pci_dma() and stl_le_pci_dma().
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/eepro100.c b/hw/eepro100.c
index 7d59e71..29ec5b4 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -976,7 +976,15 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
     case CU_STATSADDR:
         /* Load dump counters address. */
         s->statsaddr = e100_read_reg4(s, SCBPointer);
-        TRACE(OTHER, logout("val=0x%02x (status address)\n", val));
+        TRACE(OTHER, logout("val=0x%02x (dump counters address)\n", val));
+        if (s->statsaddr & 3) {
+            /* Memory must be Dword aligned. */
+            logout("unaligned dump counters address\n");
+            /* Handling of misaligned addresses is undefined.
+             * Here we align the address by ignoring the lower bits. */
+            /* TODO: Test unaligned dump counter address on real hardware. */
+            s->statsaddr &= ~3;
+        }
         break;
     case CU_SHOWSTATS:
         /* Dump statistical counters. */
commit ad0c93328dcb7a0ad68a68d0f66ea1949ebaaa2d
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Nov 24 13:28:52 2011 +0100

    virtio: add and use virtio_set_features
    
    vdev->guest_features is not masking features that are not supported by
    the guest.  Fix this by introducing a common wrapper to be used by all
    virtio bus implementations.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 0ce6406..c4b9a99 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -254,10 +254,7 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev)
     /* Update guest supported feature bitmap */
 
     features = bswap32(ldl_be_phys(dev->feat_offs));
-    if (vdev->set_features) {
-        vdev->set_features(vdev, features);
-    }
-    vdev->guest_features = features;
+    virtio_set_features(vdev, features);
 }
 
 VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus)
diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
index 00c7be8..6de952c 100644
--- a/hw/syborg_virtio.c
+++ b/hw/syborg_virtio.c
@@ -131,9 +131,7 @@ static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset,
     }
     switch (offset >> 2) {
     case SYBORG_VIRTIO_GUEST_FEATURES:
-        if (vdev->set_features)
-            vdev->set_features(vdev, value);
-        vdev->guest_features = value;
+        virtio_set_features(vdev, value);
         break;
     case SYBORG_VIRTIO_QUEUE_BASE:
         if (value == 0)
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index ca5923c..64c6a94 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -285,14 +285,9 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
     case VIRTIO_PCI_GUEST_FEATURES:
 	/* Guest does not negotiate properly?  We have to assume nothing. */
 	if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
-	    if (vdev->bad_features)
-		val = proxy->host_features & vdev->bad_features(vdev);
-	    else
-		val = 0;
+            val = vdev->bad_features ? vdev->bad_features(vdev) : 0;
 	}
-        if (vdev->set_features)
-            vdev->set_features(vdev, val);
-        vdev->guest_features = val;
+        virtio_set_features(vdev, val);
         break;
     case VIRTIO_PCI_QUEUE_PFN:
         pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
diff --git a/hw/virtio.c b/hw/virtio.c
index 7011b5b..81ecc40 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -763,12 +763,25 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
     }
 }
 
+int virtio_set_features(VirtIODevice *vdev, uint32_t val)
+{
+    uint32_t supported_features =
+        vdev->binding->get_features(vdev->binding_opaque);
+    bool bad = (val & ~supported_features) != 0;
+
+    val &= supported_features;
+    if (vdev->set_features) {
+        vdev->set_features(vdev, val);
+    }
+    vdev->guest_features = val;
+    return bad ? -1 : 0;
+}
+
 int virtio_load(VirtIODevice *vdev, QEMUFile *f)
 {
     int num, i, ret;
     uint32_t features;
-    uint32_t supported_features =
-        vdev->binding->get_features(vdev->binding_opaque);
+    uint32_t supported_features;
 
     if (vdev->binding->load_config) {
         ret = vdev->binding->load_config(vdev->binding_opaque, f);
@@ -780,14 +793,13 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
     qemu_get_8s(f, &vdev->isr);
     qemu_get_be16s(f, &vdev->queue_sel);
     qemu_get_be32s(f, &features);
-    if (features & ~supported_features) {
+
+    if (virtio_set_features(vdev, features) < 0) {
+        supported_features = vdev->binding->get_features(vdev->binding_opaque);
         error_report("Features 0x%x unsupported. Allowed features: 0x%x",
                      features, supported_features);
         return -1;
     }
-    if (vdev->set_features)
-        vdev->set_features(vdev, features);
-    vdev->guest_features = features;
     vdev->config_len = qemu_get_be32(f);
     qemu_get_buffer(f, vdev->config, vdev->config_len);
 
diff --git a/hw/virtio.h b/hw/virtio.h
index 2d18209..25f5564 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -185,6 +185,7 @@ void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector);
 void virtio_set_status(VirtIODevice *vdev, uint8_t val);
 void virtio_reset(void *opaque);
 void virtio_update_irq(VirtIODevice *vdev);
+int virtio_set_features(VirtIODevice *vdev, uint32_t val);
 
 void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
                         void *opaque);
commit ae0f940e6b4f5177892dd6a12762282fa9089972
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Nov 21 09:29:11 2011 +0100

    9pfs: improve portability to older systems
    
    Small requirements on "new" features have percolated to virtio-9p-local.c.
    In particular, the utimensat wrapper actually only supports dirfd = AT_FDCWD
    and flags = AT_SYMLINK_NOFOLLOW in the fallback code.  Remove the arguments
    so that virtio-9p-local.c will not use AT_* constants.
    
    At the same time, fail local_ioc_getversion if the ioctl is not supported
    by the host.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 7f1c089..cbd07e8 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -583,8 +583,7 @@ static int local_utimensat(FsContext *s, V9fsPath *fs_path,
     char buffer[PATH_MAX];
     char *path = fs_path->data;
 
-    return qemu_utimensat(AT_FDCWD, rpath(s, path, buffer), buf,
-                          AT_SYMLINK_NOFOLLOW);
+    return qemu_utimens(rpath(s, path, buffer), buf);
 }
 
 static int local_remove(FsContext *ctx, const char *path)
@@ -694,6 +693,7 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path,
                                 mode_t st_mode, uint64_t *st_gen)
 {
     int err;
+#ifdef FS_IOC_GETVERSION
     V9fsFidOpenState fid_open;
 
     /*
@@ -709,6 +709,9 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path,
     }
     err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen);
     local_close(ctx, &fid_open);
+#else
+    err = -ENOTTY;
+#endif
     return err;
 }
 
diff --git a/oslib-posix.c b/oslib-posix.c
index 6f29762..ce75549 100644
--- a/oslib-posix.c
+++ b/oslib-posix.c
@@ -162,8 +162,7 @@ int qemu_pipe(int pipefd[2])
     return ret;
 }
 
-int qemu_utimensat(int dirfd, const char *path, const struct timespec *times,
-                   int flags)
+int qemu_utimens(const char *path, const struct timespec *times)
 {
     struct timeval tv[2], tv_now;
     struct stat st;
@@ -171,7 +170,7 @@ int qemu_utimensat(int dirfd, const char *path, const struct timespec *times,
 #ifdef CONFIG_UTIMENSAT
     int ret;
 
-    ret = utimensat(dirfd, path, times, flags);
+    ret = utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW);
     if (ret != -1 || errno != ENOSYS) {
         return ret;
     }
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 920499d..8e1149d 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -44,7 +44,6 @@ typedef struct timeval qemu_timeval;
 #endif
 #endif
 typedef struct timespec qemu_timespec;
-int qemu_utimensat(int dirfd, const char *path, const qemu_timespec *times,
-    int flags);
+int qemu_utimens(const char *path, const qemu_timespec *times);
 
 #endif
commit 13bd0b5026265611809e99749bd74c2fd095247d
Merge: f043037... 5bb1cba...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Nov 28 11:15:10 2011 -0600

    Merge remote-tracking branch 'kwolf/block-stable' into staging

commit f04303743ac59361795b4f0effc3c01bea9b65a3
Merge: 684a7a7... c7662da...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Nov 28 11:12:39 2011 -0600

    Merge remote-tracking branch 'kraxel/usb.32' into staging

commit 684a7a7459e6693b9764ab35e8037f40549606a3
Merge: a1fd24a... be85c90...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Nov 28 11:11:09 2011 -0600

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging

commit a1fd24af4d4d5f96283ba48e7b1e83ffe3b72273
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Sun Nov 27 11:13:01 2011 -0600

    Revert "i386: derive '-cpu host' from KVM_GET_SUPPORTED_CPUID"
    
    This reverts commit 66e3dd9282141b5ae75637c9676002cf3ceeb988.
    
    From Avi,
    
     "Anthony, I think we should revert that commit and refactor cpuid for
      1.1.  The logic is spread over too many places which makes it hard to
      reason about."
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 21e5896..9fc9769 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -107,14 +107,33 @@ void host_cpuid(uint32_t function, uint32_t count,
                 uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
 {
 #if defined(CONFIG_KVM)
+    uint32_t vec[4];
+
+#ifdef __x86_64__
+    asm volatile("cpuid"
+                 : "=a"(vec[0]), "=b"(vec[1]),
+                   "=c"(vec[2]), "=d"(vec[3])
+                 : "0"(function), "c"(count) : "cc");
+#else
+    asm volatile("pusha \n\t"
+                 "cpuid \n\t"
+                 "mov %%eax, 0(%2) \n\t"
+                 "mov %%ebx, 4(%2) \n\t"
+                 "mov %%ecx, 8(%2) \n\t"
+                 "mov %%edx, 12(%2) \n\t"
+                 "popa"
+                 : : "a"(function), "c"(count), "S"(vec)
+                 : "memory", "cc");
+#endif
+
     if (eax)
-        *eax = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_EAX);
+        *eax = vec[0];
     if (ebx)
-        *ebx = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_EBX);
+        *ebx = vec[1];
     if (ecx)
-        *ecx = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_ECX);
+        *ecx = vec[2];
     if (edx)
-        *edx = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_EDX);
+        *edx = vec[3];
 #endif
 }
 
commit f44336c594c7e7887ee43ece3b53ba68b827fd1d
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Nov 28 15:40:49 2011 +0200

    omap_l4: rename omap_l4_attach_region() to omap_l4_attach()
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap.h b/hw/omap.h
index 656251d..42eb361 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -94,7 +94,7 @@ struct omap_target_agent_s *omap_l4ta_get(
     const struct omap_l4_region_s *regions,
     const struct omap_l4_agent_info_s *agents,
     int cs);
-target_phys_addr_t omap_l4_attach_region(struct omap_target_agent_s *ta,
+target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
                                          int region, MemoryRegion *mr);
 target_phys_addr_t omap_l4_region_base(struct omap_target_agent_s *ta,
                                        int region);
diff --git a/hw/omap2.c b/hw/omap2.c
index 676e5d5..91577ae 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -605,7 +605,7 @@ static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
 
     memory_region_init_io(&s->iomem, &omap_eac_ops, s, "omap.eac",
                           omap_l4_region_size(ta, 0));
-    omap_l4_attach_region(ta, 0, &s->iomem);
+    omap_l4_attach(ta, 0, &s->iomem);
 
     return s;
 }
@@ -793,7 +793,7 @@ static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
 
     memory_region_init_io(&s->iomem, &omap_sti_ops, s, "omap.sti",
                           omap_l4_region_size(ta, 0));
-    omap_l4_attach_region(ta, 0, &s->iomem);
+    omap_l4_attach(ta, 0, &s->iomem);
 
     memory_region_init_io(&s->iomem_fifo, &omap_sti_fifo_ops, s,
                           "omap.sti.fifo", 0x10000);
@@ -1813,8 +1813,8 @@ static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
                           omap_l4_region_size(ta, 0));
     memory_region_init_io(&s->iomem1, &omap_prcm_ops, s, "omap.pcrm1",
                           omap_l4_region_size(ta, 1));
-    omap_l4_attach_region(ta, 0, &s->iomem0);
-    omap_l4_attach_region(ta, 1, &s->iomem1);
+    omap_l4_attach(ta, 0, &s->iomem0);
+    omap_l4_attach(ta, 1, &s->iomem1);
 
     return s;
 }
@@ -2187,7 +2187,7 @@ static struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
 
     memory_region_init_io(&s->iomem, &omap_sysctl_ops, s, "omap.sysctl",
                           omap_l4_region_size(ta, 0));
-    omap_l4_attach_region(ta, 0, &s->iomem);
+    omap_l4_attach(ta, 0, &s->iomem);
 
     return s;
 }
diff --git a/hw/omap_dss.c b/hw/omap_dss.c
index 9e592ce..ede640b 100644
--- a/hw/omap_dss.c
+++ b/hw/omap_dss.c
@@ -1064,10 +1064,10 @@ struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
     memory_region_init_io(&s->iomem_im3, &omap_im3_ops, s,
                           "omap.im3", 0x1000);
 
-    omap_l4_attach_region(ta, 0, &s->iomem_diss1);
-    omap_l4_attach_region(ta, 1, &s->iomem_disc1);
-    omap_l4_attach_region(ta, 2, &s->iomem_rfbi1);
-    omap_l4_attach_region(ta, 3, &s->iomem_venc1);
+    omap_l4_attach(ta, 0, &s->iomem_diss1);
+    omap_l4_attach(ta, 1, &s->iomem_disc1);
+    omap_l4_attach(ta, 2, &s->iomem_rfbi1);
+    omap_l4_attach(ta, 3, &s->iomem_venc1);
     memory_region_add_subregion(sysmem, l3_base, &s->iomem_im3);
 
 #if 0
diff --git a/hw/omap_gptimer.c b/hw/omap_gptimer.c
index 414b98a..7a14519 100644
--- a/hw/omap_gptimer.c
+++ b/hw/omap_gptimer.c
@@ -482,7 +482,7 @@ struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
 
     memory_region_init_io(&s->iomem, &omap_gp_timer_ops, s, "omap.gptimer",
                           omap_l4_region_size(ta, 0));
-    omap_l4_attach_region(ta, 0, &s->iomem);
+    omap_l4_attach(ta, 0, &s->iomem);
 
     return s;
 }
diff --git a/hw/omap_i2c.c b/hw/omap_i2c.c
index ca875f6..5ec422c 100644
--- a/hw/omap_i2c.c
+++ b/hw/omap_i2c.c
@@ -464,7 +464,7 @@ struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
 
     memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap2.i2c",
                           omap_l4_region_size(ta, 0));
-    omap_l4_attach_region(ta, 0, &s->iomem);
+    omap_l4_attach(ta, 0, &s->iomem);
 
     return s;
 }
diff --git a/hw/omap_l4.c b/hw/omap_l4.c
index 78f02d9..dbad7f6 100644
--- a/hw/omap_l4.c
+++ b/hw/omap_l4.c
@@ -138,12 +138,12 @@ struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus,
 
     memory_region_init_io(&ta->iomem, &omap_l4ta_ops, ta, "omap.l4ta",
                           omap_l4_region_size(ta, info->ta_region));
-    omap_l4_attach_region(ta, info->ta_region, &ta->iomem);
+    omap_l4_attach(ta, info->ta_region, &ta->iomem);
 
     return ta;
 }
 
-target_phys_addr_t omap_l4_attach_region(struct omap_target_agent_s *ta,
+target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
                                          int region, MemoryRegion *mr)
 {
     target_phys_addr_t base;
diff --git a/hw/omap_mmc.c b/hw/omap_mmc.c
index ba960c1..aec0285 100644
--- a/hw/omap_mmc.c
+++ b/hw/omap_mmc.c
@@ -614,7 +614,7 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
 
     memory_region_init_io(&s->iomem, &omap_mmc_ops, s, "omap.mmc",
                           omap_l4_region_size(ta, 0));
-    omap_l4_attach_region(ta, 0, &s->iomem);
+    omap_l4_attach(ta, 0, &s->iomem);
 
     /* Instantiate the storage */
     s->card = sd_init(bd, 0);
diff --git a/hw/omap_spi.c b/hw/omap_spi.c
index 4823bd0..8f2b697 100644
--- a/hw/omap_spi.c
+++ b/hw/omap_spi.c
@@ -332,7 +332,7 @@ struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
 
     memory_region_init_io(&s->iomem, &omap_mcspi_ops, s, "omap.mcspi",
                           omap_l4_region_size(ta, 0));
-    omap_l4_attach_region(ta, 0, &s->iomem);
+    omap_l4_attach(ta, 0, &s->iomem);
 
     return s;
 }
diff --git a/hw/omap_synctimer.c b/hw/omap_synctimer.c
index cd1d754..367f26e 100644
--- a/hw/omap_synctimer.c
+++ b/hw/omap_synctimer.c
@@ -96,7 +96,7 @@ struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta,
     omap_synctimer_reset(s);
     memory_region_init_io(&s->iomem, &omap_synctimer_ops, s, "omap.synctimer",
                           omap_l4_region_size(ta, 0));
-    omap_l4_attach_region(ta, 0, &s->iomem);
+    omap_l4_attach(ta, 0, &s->iomem);
 
     return s;
 }
diff --git a/hw/omap_tap.c b/hw/omap_tap.c
index 1b4820c..0277c73 100644
--- a/hw/omap_tap.c
+++ b/hw/omap_tap.c
@@ -112,5 +112,5 @@ void omap_tap_init(struct omap_target_agent_s *ta,
 {
     memory_region_init_io(&mpu->tap_iomem, &omap_tap_ops, mpu, "omap.tap",
                           omap_l4_region_size(ta, 0));
-    omap_l4_attach_region(ta, 0, &mpu->tap_iomem);
+    omap_l4_attach(ta, 0, &mpu->tap_iomem);
 }
diff --git a/hw/omap_uart.c b/hw/omap_uart.c
index 64fc9f5..167d5c4 100644
--- a/hw/omap_uart.c
+++ b/hw/omap_uart.c
@@ -165,7 +165,7 @@ struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem,
                 qemu_irq txdma, qemu_irq rxdma,
                 const char *label, CharDriverState *chr)
 {
-    target_phys_addr_t base = omap_l4_attach_region(ta, 0, NULL);
+    target_phys_addr_t base = omap_l4_attach(ta, 0, NULL);
     struct omap_uart_s *s = omap_uart_init(base, irq,
                     fclk, iclk, txdma, rxdma, label, chr);
 
commit a6dbd3c83622fc0156e17c0d2fab54fe79afd07f
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Nov 28 15:37:30 2011 +0200

    omap_l4: remove omap_l4_attach()
    
    No longer used.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap.h b/hw/omap.h
index 0724ffe..656251d 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -94,8 +94,6 @@ struct omap_target_agent_s *omap_l4ta_get(
     const struct omap_l4_region_s *regions,
     const struct omap_l4_agent_info_s *agents,
     int cs);
-target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
-                int iotype);
 target_phys_addr_t omap_l4_attach_region(struct omap_target_agent_s *ta,
                                          int region, MemoryRegion *mr);
 target_phys_addr_t omap_l4_region_base(struct omap_target_agent_s *ta,
diff --git a/hw/omap_l4.c b/hw/omap_l4.c
index cf4b971..78f02d9 100644
--- a/hw/omap_l4.c
+++ b/hw/omap_l4.c
@@ -143,26 +143,6 @@ struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus,
     return ta;
 }
 
-target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
-                int iotype)
-{
-    target_phys_addr_t base;
-    ssize_t size;
-
-    if (region < 0 || region >= ta->regions) {
-        fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region);
-        exit(-1);
-    }
-
-    base = ta->bus->base + ta->start[region].offset;
-    size = ta->start[region].size;
-    if (iotype) {
-        cpu_register_physical_memory(base, size, iotype);
-    }
-
-    return base;
-}
-
 target_phys_addr_t omap_l4_attach_region(struct omap_target_agent_s *ta,
                                          int region, MemoryRegion *mr)
 {
commit 748781390916caa6a8258ed89524a82e508efadc
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Fri Nov 25 15:21:37 2011 +0100

    omap_i2c: convert to memory API
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap.h b/hw/omap.h
index b7f339c..0724ffe 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -771,8 +771,11 @@ 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(target_phys_addr_t base,
-                qemu_irq irq, qemu_irq *dma, omap_clk clk);
+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);
diff --git a/hw/omap1.c b/hw/omap1.c
index f985f8d..53cde76 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -3964,7 +3964,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
     omap_pwl_init(system_memory, 0xfffb5800, s, omap_findclk(s, "armxor_ck"));
     omap_pwt_init(system_memory, 0xfffb6000, s, omap_findclk(s, "armxor_ck"));
 
-    s->i2c[0] = omap_i2c_init(0xfffb3800,
+    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"));
 
diff --git a/hw/omap_i2c.c b/hw/omap_i2c.c
index 52c38ba..ca875f6 100644
--- a/hw/omap_i2c.c
+++ b/hw/omap_i2c.c
@@ -21,6 +21,7 @@
 #include "omap.h"
 
 struct omap_i2c_s {
+    MemoryRegion iomem;
     qemu_irq irq;
     qemu_irq drq[2];
     i2c_bus *bus;
@@ -409,22 +410,28 @@ static void omap_i2c_writeb(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_i2c_readfn[] = {
-    omap_badwidth_read16,
-    omap_i2c_read,
-    omap_badwidth_read16,
+static const MemoryRegionOps omap_i2c_ops = {
+    .old_mmio = {
+        .read = {
+            omap_badwidth_read16,
+            omap_i2c_read,
+            omap_badwidth_read16,
+        },
+        .write = {
+            omap_i2c_writeb, /* Only the last fifo write can be 8 bit.  */
+            omap_i2c_write,
+            omap_badwidth_write16,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const omap_i2c_writefn[] = {
-    omap_i2c_writeb,	/* Only the last fifo write can be 8 bit.  */
-    omap_i2c_write,
-    omap_badwidth_write16,
-};
-
-struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
-                qemu_irq irq, qemu_irq *dma, omap_clk clk)
+struct omap_i2c_s *omap_i2c_init(MemoryRegion *sysmem,
+                                 target_phys_addr_t base,
+                                 qemu_irq irq,
+                                 qemu_irq *dma,
+                                 omap_clk clk)
 {
-    int iomemtype;
     struct omap_i2c_s *s = (struct omap_i2c_s *)
             g_malloc0(sizeof(struct omap_i2c_s));
 
@@ -436,9 +443,8 @@ struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
     s->bus = i2c_init_bus(NULL, "i2c");
     omap_i2c_reset(s);
 
-    iomemtype = cpu_register_io_memory(omap_i2c_readfn,
-                    omap_i2c_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x800, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap.i2c", 0x800);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     return s;
 }
@@ -446,7 +452,6 @@ struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
 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)
 {
-    int iomemtype;
     struct omap_i2c_s *s = (struct omap_i2c_s *)
             g_malloc0(sizeof(struct omap_i2c_s));
 
@@ -457,9 +462,9 @@ struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
     s->bus = i2c_init_bus(NULL, "i2c");
     omap_i2c_reset(s);
 
-    iomemtype = cpu_register_io_memory(omap_i2c_readfn,
-                    omap_i2c_writefn, s, DEVICE_NATIVE_ENDIAN);
-    omap_l4_attach(ta, 0, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap2.i2c",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach_region(ta, 0, &s->iomem);
 
     return s;
 }
commit 30af1ec7295b3fecab641320cf97208b0936571f
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Nov 28 13:53:36 2011 +0100

    omap_lcdc: convert to memory API
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap.h b/hw/omap.h
index 9dcba6a..b7f339c 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -733,8 +733,11 @@ void omap_tap_init(struct omap_target_agent_s *ta,
 /* omap_lcdc.c */
 struct omap_lcd_panel_s;
 void omap_lcdc_reset(struct omap_lcd_panel_s *s);
-struct omap_lcd_panel_s *omap_lcdc_init(target_phys_addr_t base, qemu_irq irq,
-                struct omap_dma_lcd_channel_s *dma, omap_clk clk);
+struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem,
+                                        target_phys_addr_t base,
+                                        qemu_irq irq,
+                                        struct omap_dma_lcd_channel_s *dma,
+                                        omap_clk clk);
 
 /* omap_dss.c */
 struct rfbi_chip_s {
diff --git a/hw/omap1.c b/hw/omap1.c
index 79b5178..f985f8d 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -3884,7 +3884,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
                     qdev_get_gpio_in(s->ih[1], OMAP_INT_OS_TIMER),
                     omap_findclk(s, "clk32-kHz"));
 
-    s->lcd = omap_lcdc_init(0xfffec000,
+    s->lcd = omap_lcdc_init(system_memory, 0xfffec000,
                             qdev_get_gpio_in(s->ih[0], OMAP_INT_LCD_CTRL),
                             omap_dma_get_lcdch(s->dma),
                             omap_findclk(s, "lcd_ck"));
diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c
index 29e6048..8484f70 100644
--- a/hw/omap_lcdc.c
+++ b/hw/omap_lcdc.c
@@ -22,6 +22,7 @@
 #include "framebuffer.h"
 
 struct omap_lcd_panel_s {
+    MemoryRegion iomem;
     qemu_irq irq;
     DisplayState *state;
 
@@ -323,7 +324,8 @@ static void omap_lcd_update(struct omap_lcd_panel_s *s) {
     }
 }
 
-static uint32_t omap_lcdc_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_lcdc_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *) opaque;
 
@@ -356,7 +358,7 @@ static uint32_t omap_lcdc_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_lcdc_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *) opaque;
 
@@ -399,16 +401,10 @@ static void omap_lcdc_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_lcdc_readfn[] = {
-    omap_lcdc_read,
-    omap_lcdc_read,
-    omap_lcdc_read,
-};
-
-static CPUWriteMemoryFunc * const omap_lcdc_writefn[] = {
-    omap_lcdc_write,
-    omap_lcdc_write,
-    omap_lcdc_write,
+static const MemoryRegionOps omap_lcdc_ops = {
+    .read = omap_lcdc_read,
+    .write = omap_lcdc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 void omap_lcdc_reset(struct omap_lcd_panel_s *s)
@@ -433,10 +429,12 @@ void omap_lcdc_reset(struct omap_lcd_panel_s *s)
     s->ctrl = 0;
 }
 
-struct omap_lcd_panel_s *omap_lcdc_init(target_phys_addr_t base, qemu_irq irq,
-                struct omap_dma_lcd_channel_s *dma, omap_clk clk)
+struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem,
+                                        target_phys_addr_t base,
+                                        qemu_irq irq,
+                                        struct omap_dma_lcd_channel_s *dma,
+                                        omap_clk clk)
 {
-    int iomemtype;
     struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *)
             g_malloc0(sizeof(struct omap_lcd_panel_s));
 
@@ -444,9 +442,8 @@ struct omap_lcd_panel_s *omap_lcdc_init(target_phys_addr_t base, qemu_irq irq,
     s->dma = dma;
     omap_lcdc_reset(s);
 
-    iomemtype = cpu_register_io_memory(omap_lcdc_readfn,
-                    omap_lcdc_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x100, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_lcdc_ops, s, "omap.lcdc", 0x100);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     s->state = graphic_console_init(omap_update_display,
                                     omap_invalidate_display,
commit 1a0726900e4f472cdb389fd249bfdfa0e30f21e7
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Nov 28 13:53:35 2011 +0100

    omap_spi: convert to memory API
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap_spi.c b/hw/omap_spi.c
index c20f425..4823bd0 100644
--- a/hw/omap_spi.c
+++ b/hw/omap_spi.c
@@ -24,6 +24,7 @@
 
 /* Multichannel SPI */
 struct omap_mcspi_s {
+    MemoryRegion iomem;
     qemu_irq irq;
     int chnum;
 
@@ -129,12 +130,17 @@ void omap_mcspi_reset(struct omap_mcspi_s *s)
     omap_mcspi_interrupt_update(s);
 }
 
-static uint32_t omap_mcspi_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_mcspi_read(void *opaque, target_phys_addr_t addr,
+                                unsigned size)
 {
     struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
     int ch = 0;
     uint32_t ret;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x00:	/* MCSPI_REVISION */
         return 0x91;
@@ -199,11 +205,15 @@ static uint32_t omap_mcspi_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_mcspi_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                             uint64_t value, unsigned size)
 {
     struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
     int ch = 0;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x00:	/* MCSPI_REVISION */
     case 0x14:	/* MCSPI_SYSSTATUS */
@@ -267,7 +277,7 @@ static void omap_mcspi_write(void *opaque, target_phys_addr_t addr,
         if (((value >> 12) & 3) == 3)			/* TRM */
             fprintf(stderr, "%s: invalid TRM value (3)\n", __FUNCTION__);
         if (((value >> 7) & 0x1f) < 3)			/* WL */
-            fprintf(stderr, "%s: invalid WL value (%i)\n",
+            fprintf(stderr, "%s: invalid WL value (%" PRIx64 ")\n",
                             __FUNCTION__, (value >> 7) & 0x1f);
         s->ch[ch].config = value & 0x7fffff;
         break;
@@ -298,22 +308,15 @@ static void omap_mcspi_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_mcspi_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_mcspi_read,
-};
-
-static CPUWriteMemoryFunc * const omap_mcspi_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_mcspi_write,
+static const MemoryRegionOps omap_mcspi_ops = {
+    .read = omap_mcspi_read,
+    .write = omap_mcspi_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
                 qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
 {
-    int iomemtype;
     struct omap_mcspi_s *s = (struct omap_mcspi_s *)
             g_malloc0(sizeof(struct omap_mcspi_s));
     struct omap_mcspi_ch_s *ch = s->ch;
@@ -327,9 +330,9 @@ struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
     }
     omap_mcspi_reset(s);
 
-    iomemtype = cpu_register_io_memory(omap_mcspi_readfn,
-                    omap_mcspi_writefn, s, DEVICE_NATIVE_ENDIAN);
-    omap_l4_attach(ta, 0, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_mcspi_ops, s, "omap.mcspi",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach_region(ta, 0, &s->iomem);
 
     return s;
 }
commit ba1580299d04504b024e02999b4034947c4005b8
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Nov 28 13:53:34 2011 +0100

    omap_sx1: convert to memory API
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index fe53545..8e58645 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -59,46 +59,28 @@
  * - 1 RTC
  */
 
-static uint32_t static_readb(void *opaque, target_phys_addr_t offset)
+static uint64_t static_read(void *opaque, target_phys_addr_t offset,
+                            unsigned size)
 {
     uint32_t *val = (uint32_t *) opaque;
+    uint32_t mask = (4 / size) - 1;
 
-    return *val >> ((offset & 3) << 3);
-}
-
-static uint32_t static_readh(void *opaque, target_phys_addr_t offset)
-{
-    uint32_t *val = (uint32_t *) opaque;
-
-    return *val >> ((offset & 1) << 3);
-}
-
-static uint32_t static_readw(void *opaque, target_phys_addr_t offset)
-{
-    uint32_t *val = (uint32_t *) opaque;
-
-    return *val >> ((offset & 0) << 3);
+    return *val >> ((offset & mask) << 3);
 }
 
 static void static_write(void *opaque, target_phys_addr_t offset,
-                uint32_t value)
+                         uint64_t value, unsigned size)
 {
 #ifdef SPY
-    printf("%s: value %08lx written at " PA_FMT "\n",
-                    __FUNCTION__, value, offset);
+    printf("%s: value %" PRIx64 " %u bytes written at 0x%x\n",
+                    __func__, value, size, (int)offset);
 #endif
 }
 
-static CPUReadMemoryFunc * const static_readfn[] = {
-    static_readb,
-    static_readh,
-    static_readw,
-};
-
-static CPUWriteMemoryFunc * const static_writefn[] = {
-    static_write,
-    static_write,
-    static_write,
+static const MemoryRegionOps static_ops = {
+    .read = static_read,
+    .write = static_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 #define sdram_size	0x02000000
@@ -123,7 +105,9 @@ static void sx1_init(ram_addr_t ram_size,
 {
     struct omap_mpu_state_s *cpu;
     MemoryRegion *address_space = get_system_memory();
-    int io;
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
+    MemoryRegion *flash_1 = g_new(MemoryRegion, 1);
+    MemoryRegion *cs = g_new(MemoryRegion, 4);
     static uint32_t cs0val = 0x00213090;
     static uint32_t cs1val = 0x00215070;
     static uint32_t cs2val = 0x00001139;
@@ -140,20 +124,25 @@ static void sx1_init(ram_addr_t ram_size,
     cpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, cpu_model);
 
     /* External Flash (EMIFS) */
-    cpu_register_physical_memory(OMAP_CS0_BASE, flash_size,
-                                 qemu_ram_alloc(NULL, "omap_sx1.flash0-0",
-                                                flash_size) | IO_MEM_ROM);
-
-    io = cpu_register_io_memory(static_readfn, static_writefn, &cs0val,
-                                DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(OMAP_CS0_BASE + flash_size,
-                    OMAP_CS0_SIZE - flash_size, io);
-    io = cpu_register_io_memory(static_readfn, static_writefn, &cs2val,
-                                DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(OMAP_CS2_BASE, OMAP_CS2_SIZE, io);
-    io = cpu_register_io_memory(static_readfn, static_writefn, &cs3val,
-                                DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(OMAP_CS3_BASE, OMAP_CS3_SIZE, io);
+    memory_region_init_ram(flash, NULL, "omap_sx1.flash0-0", flash_size);
+    memory_region_set_readonly(flash, true);
+    memory_region_add_subregion(address_space, OMAP_CS0_BASE, flash);
+
+    memory_region_init_io(&cs[0], &static_ops, &cs0val,
+                          "sx1.cs0", OMAP_CS0_SIZE - flash_size);
+    memory_region_add_subregion(address_space,
+                                OMAP_CS0_BASE + flash_size, &cs[0]);
+
+
+    memory_region_init_io(&cs[2], &static_ops, &cs2val,
+                          "sx1.cs2", OMAP_CS2_SIZE);
+    memory_region_add_subregion(address_space,
+                                OMAP_CS2_BASE, &cs[2]);
+
+    memory_region_init_io(&cs[3], &static_ops, &cs3val,
+                          "sx1.cs3", OMAP_CS3_SIZE);
+    memory_region_add_subregion(address_space,
+                                OMAP_CS2_BASE, &cs[3]);
 
     fl_idx = 0;
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -176,13 +165,14 @@ static void sx1_init(ram_addr_t ram_size,
 
     if ((version == 1) &&
             (dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
-        cpu_register_physical_memory(OMAP_CS1_BASE, flash1_size,
-                                     qemu_ram_alloc(NULL, "omap_sx1.flash1-0",
-                                                    flash1_size) | IO_MEM_ROM);
-        io = cpu_register_io_memory(static_readfn, static_writefn, &cs1val,
-                                    DEVICE_NATIVE_ENDIAN);
-        cpu_register_physical_memory(OMAP_CS1_BASE + flash1_size,
-                        OMAP_CS1_SIZE - flash1_size, io);
+        memory_region_init_ram(flash_1, NULL, "omap_sx1.flash1-0", flash1_size);
+        memory_region_set_readonly(flash_1, true);
+        memory_region_add_subregion(address_space, OMAP_CS1_BASE, flash_1);
+
+        memory_region_init_io(&cs[1], &static_ops, &cs1val,
+                              "sx1.cs1", OMAP_CS1_SIZE - flash1_size);
+        memory_region_add_subregion(address_space,
+                                OMAP_CS1_BASE + flash1_size, &cs[1]);
 
         if (!pflash_cfi01_register(OMAP_CS1_BASE, NULL,
                                    "omap_sx1.flash1-1", flash1_size,
@@ -194,9 +184,10 @@ static void sx1_init(ram_addr_t ram_size,
         }
         fl_idx++;
     } else {
-        io = cpu_register_io_memory(static_readfn, static_writefn, &cs1val,
-                                    DEVICE_NATIVE_ENDIAN);
-        cpu_register_physical_memory(OMAP_CS1_BASE, OMAP_CS1_SIZE, io);
+        memory_region_init_io(&cs[1], &static_ops, &cs1val,
+                              "sx1.cs1", OMAP_CS1_SIZE);
+        memory_region_add_subregion(address_space,
+                                OMAP_CS1_BASE, &cs[1]);
     }
 
     if (!kernel_filename && !fl_idx) {
commit 3892f842c9341ef4ff8cdb787b1626c7ea1756e2
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Fri Nov 25 15:21:36 2011 +0100

    omap_l4: convert to memory API
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap.h b/hw/omap.h
index 65d3c98..9dcba6a 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -76,6 +76,7 @@ struct omap_l4_agent_info_s {
     int ta_region;
 };
 struct omap_target_agent_s {
+    MemoryRegion iomem;
     struct omap_l4_s *bus;
     int regions;
     const struct omap_l4_region_s *start;
diff --git a/hw/omap_l4.c b/hw/omap_l4.c
index a0bed5c..cf4b971 100644
--- a/hw/omap_l4.c
+++ b/hw/omap_l4.c
@@ -52,10 +52,15 @@ target_phys_addr_t omap_l4_region_size(struct omap_target_agent_s *ta,
     return ta->start[region].size;
 }
 
-static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_l4ta_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
 
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
     switch (addr) {
     case 0x00:	/* COMPONENT */
         return s->component;
@@ -72,10 +77,14 @@ static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_l4ta_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x00:	/* COMPONENT */
     case 0x28:	/* AGENT_STATUS */
@@ -93,16 +102,10 @@ static void omap_l4ta_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_l4ta_readfn[] = {
-    omap_badwidth_read16,
-    omap_l4ta_read,
-    omap_badwidth_read16,
-};
-
-static CPUWriteMemoryFunc * const omap_l4ta_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_l4ta_write,
+static const MemoryRegionOps omap_l4ta_ops = {
+    .read = omap_l4ta_read,
+    .write = omap_l4ta_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus,
@@ -110,7 +113,7 @@ struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus,
 	const struct omap_l4_agent_info_s *agents,
 	int cs)
 {
-    int i, iomemtype;
+    int i;
     struct omap_target_agent_s *ta = NULL;
     const struct omap_l4_agent_info_s *info = NULL;
 
@@ -133,9 +136,9 @@ struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus,
     ta->status = 0x00000000;
     ta->control = 0x00000200;	/* XXX 01000200 for L4TAO */
 
-    iomemtype = cpu_register_io_memory(omap_l4ta_readfn,
-                    omap_l4ta_writefn, ta, DEVICE_NATIVE_ENDIAN);
-    ta->base = omap_l4_attach(ta, info->ta_region, iomemtype);
+    memory_region_init_io(&ta->iomem, &omap_l4ta_ops, ta, "omap.l4ta",
+                          omap_l4_region_size(ta, info->ta_region));
+    omap_l4_attach_region(ta, info->ta_region, &ta->iomem);
 
     return ta;
 }
commit 4852e5d8c3bb48823a90b8963c3e7f19791b3cec
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Nov 28 13:10:11 2011 +0200

    omap_dss: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap.h b/hw/omap.h
index 0a45515..65d3c98 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -745,6 +745,7 @@ struct rfbi_chip_s {
 struct omap_dss_s;
 void omap_dss_reset(struct omap_dss_s *s);
 struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
+                MemoryRegion *sysmem,
                 target_phys_addr_t l3_base,
                 qemu_irq irq, qemu_irq drq,
                 omap_clk fck1, omap_clk fck2, omap_clk ck54m,
diff --git a/hw/omap2.c b/hw/omap2.c
index a7660f6..676e5d5 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -2462,7 +2462,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
                     omap_findclk(s, "spi2_fclk"),
                     omap_findclk(s, "spi2_iclk"));
 
-    s->dss = omap_dss_init(omap_l4ta(s->l4, 10), 0x68000800,
+    s->dss = omap_dss_init(omap_l4ta(s->l4, 10), sysmem, 0x68000800,
                     /* XXX wire M_IRQ_25, D_L2_IRQ_30 and I_IRQ_13 together */
                     qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_DSS_IRQ),
                            s->drq[OMAP24XX_DMA_DSS],
diff --git a/hw/omap_dss.c b/hw/omap_dss.c
index b138c23..9e592ce 100644
--- a/hw/omap_dss.c
+++ b/hw/omap_dss.c
@@ -25,6 +25,7 @@ struct omap_dss_s {
     qemu_irq irq;
     qemu_irq drq;
     DisplayState *state;
+    MemoryRegion iomem_diss1, iomem_disc1, iomem_rfbi1, iomem_venc1, iomem_im3;
 
     int autoidle;
     int control;
@@ -167,10 +168,15 @@ void omap_dss_reset(struct omap_dss_s *s)
     omap_dispc_interrupt_update(s);
 }
 
-static uint32_t omap_diss_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_diss_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x00:	/* DSS_REVISIONNUMBER */
         return 0x20;
@@ -201,10 +207,14 @@ static uint32_t omap_diss_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_diss_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x00:	/* DSS_REVISIONNUMBER */
     case 0x14:	/* DSS_SYSSTATUS */
@@ -230,22 +240,21 @@ static void omap_diss_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_diss1_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_diss_read,
+static const MemoryRegionOps omap_diss_ops = {
+    .read = omap_diss_read,
+    .write = omap_diss_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const omap_diss1_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_diss_write,
-};
-
-static uint32_t omap_disc_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_disc_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x000:	/* DISPC_REVISION */
         return 0x20;
@@ -363,10 +372,14 @@ static uint32_t omap_disc_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_disc_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x010:	/* DISPC_SYSCONFIG */
         if (value & 2)						/* SOFTRESET */
@@ -570,16 +583,10 @@ static void omap_disc_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_disc1_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_disc_read,
-};
-
-static CPUWriteMemoryFunc * const omap_disc1_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_disc_write,
+static const MemoryRegionOps omap_disc_ops = {
+    .read = omap_disc_read,
+    .write = omap_disc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void omap_rfbi_transfer_stop(struct omap_dss_s *s)
@@ -656,10 +663,15 @@ static void omap_rfbi_transfer_start(struct omap_dss_s *s)
     omap_dispc_interrupt_update(s);
 }
 
-static uint32_t omap_rfbi_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_rfbi_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x00:	/* RFBI_REVISION */
         return 0x10;
@@ -719,10 +731,14 @@ static uint32_t omap_rfbi_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_rfbi_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x10:	/* RFBI_SYSCONFIG */
         if (value & 2)						/* SOFTRESET */
@@ -842,20 +858,19 @@ static void omap_rfbi_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_rfbi1_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_rfbi_read,
-};
-
-static CPUWriteMemoryFunc * const omap_rfbi1_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_rfbi_write,
+static const MemoryRegionOps omap_rfbi_ops = {
+    .read = omap_rfbi_read,
+    .write = omap_rfbi_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static uint32_t omap_venc_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_venc_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x00:	/* REV_ID */
     case 0x04:	/* STATUS */
@@ -910,8 +925,12 @@ static uint32_t omap_venc_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_venc_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, size);
+    }
+
     switch (addr) {
     case 0x08:	/* F_CONTROL */
     case 0x10:	/* VIDOUT_CTRL */
@@ -961,20 +980,19 @@ static void omap_venc_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_venc1_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_venc_read,
+static const MemoryRegionOps omap_venc_ops = {
+    .read = omap_venc_read,
+    .write = omap_venc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const omap_venc1_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_venc_write,
-};
-
-static uint32_t omap_im3_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_im3_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x0a8:	/* SBIMERRLOGA */
     case 0x0b0:	/* SBIMERRLOG */
@@ -995,8 +1013,12 @@ static uint32_t omap_im3_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_im3_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                           uint64_t value, unsigned size)
 {
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x0b0:	/* SBIMERRLOG */
     case 0x190:	/* SBIMSTATE */
@@ -1011,25 +1033,19 @@ static void omap_im3_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_im3_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_im3_read,
-};
-
-static CPUWriteMemoryFunc * const omap_im3_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_im3_write,
+static const MemoryRegionOps omap_im3_ops = {
+    .read = omap_im3_read,
+    .write = omap_im3_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
+                MemoryRegion *sysmem,
                 target_phys_addr_t l3_base,
                 qemu_irq irq, qemu_irq drq,
                 omap_clk fck1, omap_clk fck2, omap_clk ck54m,
                 omap_clk ick1, omap_clk ick2)
 {
-    int iomemtype[5];
     struct omap_dss_s *s = (struct omap_dss_s *)
             g_malloc0(sizeof(struct omap_dss_s));
 
@@ -1037,21 +1053,22 @@ struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
     s->drq = drq;
     omap_dss_reset(s);
 
-    iomemtype[0] = cpu_register_io_memory(omap_diss1_readfn,
-                    omap_diss1_writefn, s, DEVICE_NATIVE_ENDIAN);
-    iomemtype[1] = cpu_register_io_memory(omap_disc1_readfn,
-                    omap_disc1_writefn, s, DEVICE_NATIVE_ENDIAN);
-    iomemtype[2] = cpu_register_io_memory(omap_rfbi1_readfn,
-                    omap_rfbi1_writefn, s, DEVICE_NATIVE_ENDIAN);
-    iomemtype[3] = cpu_register_io_memory(omap_venc1_readfn,
-                    omap_venc1_writefn, s, DEVICE_NATIVE_ENDIAN);
-    iomemtype[4] = cpu_register_io_memory(omap_im3_readfn,
-                    omap_im3_writefn, s, DEVICE_NATIVE_ENDIAN);
-    omap_l4_attach(ta, 0, iomemtype[0]);
-    omap_l4_attach(ta, 1, iomemtype[1]);
-    omap_l4_attach(ta, 2, iomemtype[2]);
-    omap_l4_attach(ta, 3, iomemtype[3]);
-    cpu_register_physical_memory(l3_base, 0x1000, iomemtype[4]);
+    memory_region_init_io(&s->iomem_diss1, &omap_diss_ops, s, "omap.diss1",
+                          omap_l4_region_size(ta, 0));
+    memory_region_init_io(&s->iomem_disc1, &omap_disc_ops, s, "omap.disc1",
+                          omap_l4_region_size(ta, 1));
+    memory_region_init_io(&s->iomem_rfbi1, &omap_rfbi_ops, s, "omap.rfbi1",
+                          omap_l4_region_size(ta, 2));
+    memory_region_init_io(&s->iomem_venc1, &omap_venc_ops, s, "omap.venc1",
+                          omap_l4_region_size(ta, 3));
+    memory_region_init_io(&s->iomem_im3, &omap_im3_ops, s,
+                          "omap.im3", 0x1000);
+
+    omap_l4_attach_region(ta, 0, &s->iomem_diss1);
+    omap_l4_attach_region(ta, 1, &s->iomem_disc1);
+    omap_l4_attach_region(ta, 2, &s->iomem_rfbi1);
+    omap_l4_attach_region(ta, 3, &s->iomem_venc1);
+    memory_region_add_subregion(sysmem, l3_base, &s->iomem_im3);
 
 #if 0
     s->state = graphic_console_init(omap_update_display,
commit 011a98a15bf06138b4abcbb0a8b9f30dcb69a9e9
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 27 11:53:29 2011 +0200

    omap2: convert to memory API (part II)
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap.h b/hw/omap.h
index 759e90f..0a45515 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -833,6 +833,8 @@ struct omap_mpu_state_s {
     MemoryRegion tap_iomem;
     MemoryRegion imif_ram;
     MemoryRegion emiff_ram;
+    MemoryRegion sdram;
+    MemoryRegion sram;
 
     struct omap_dma_port_if_s {
         uint32_t (*read[3])(struct omap_mpu_state_s *s,
diff --git a/hw/omap2.c b/hw/omap2.c
index a5f9b7d..a7660f6 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -1000,6 +1000,8 @@ static const struct omap_l4_agent_info_s omap_l4_agent_info[54] = {
 struct omap_prcm_s {
     qemu_irq irq[3];
     struct omap_mpu_state_s *mpu;
+    MemoryRegion iomem0;
+    MemoryRegion iomem1;
 
     uint32_t irqst[3];
     uint32_t irqen[3];
@@ -1038,11 +1040,16 @@ static void omap_prcm_int_update(struct omap_prcm_s *s, int dom)
     /* XXX or is the mask applied before PRCM_IRQSTATUS_* ? */
 }
 
-static uint32_t omap_prcm_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_prcm_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
     uint32_t ret;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x000:	/* PRCM_REVISION */
         return 0x10;
@@ -1346,10 +1353,14 @@ static void omap_prcm_dpll_update(struct omap_prcm_s *s)
 }
 
 static void omap_prcm_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x000:	/* PRCM_REVISION */
     case 0x054:	/* PRCM_VOLTST */
@@ -1699,16 +1710,10 @@ static void omap_prcm_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_prcm_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_prcm_read,
-};
-
-static CPUWriteMemoryFunc * const omap_prcm_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_prcm_write,
+static const MemoryRegionOps omap_prcm_ops = {
+    .read = omap_prcm_read,
+    .write = omap_prcm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void omap_prcm_reset(struct omap_prcm_s *s)
@@ -1795,7 +1800,6 @@ static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
                 qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
                 struct omap_mpu_state_s *mpu)
 {
-    int iomemtype;
     struct omap_prcm_s *s = (struct omap_prcm_s *)
             g_malloc0(sizeof(struct omap_prcm_s));
 
@@ -1805,10 +1809,12 @@ static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
     s->mpu = mpu;
     omap_prcm_coldreset(s);
 
-    iomemtype = cpu_register_io_memory(omap_prcm_readfn,
-                    omap_prcm_writefn, s, DEVICE_NATIVE_ENDIAN);
-    omap_l4_attach(ta, 0, iomemtype);
-    omap_l4_attach(ta, 1, iomemtype);
+    memory_region_init_io(&s->iomem0, &omap_prcm_ops, s, "omap.pcrm0",
+                          omap_l4_region_size(ta, 0));
+    memory_region_init_io(&s->iomem1, &omap_prcm_ops, s, "omap.pcrm1",
+                          omap_l4_region_size(ta, 1));
+    omap_l4_attach_region(ta, 0, &s->iomem0);
+    omap_l4_attach_region(ta, 1, &s->iomem1);
 
     return s;
 }
@@ -1816,6 +1822,7 @@ static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
 /* System and Pinout control */
 struct omap_sysctl_s {
     struct omap_mpu_state_s *mpu;
+    MemoryRegion iomem;
 
     uint32_t sysconfig;
     uint32_t devconfig;
@@ -2069,16 +2076,20 @@ static void omap_sysctl_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_sysctl_readfn[] = {
-    omap_sysctl_read8,
-    omap_badwidth_read32,	/* TODO */
-    omap_sysctl_read,
-};
-
-static CPUWriteMemoryFunc * const omap_sysctl_writefn[] = {
-    omap_sysctl_write8,
-    omap_badwidth_write32,	/* TODO */
-    omap_sysctl_write,
+static const MemoryRegionOps omap_sysctl_ops = {
+    .old_mmio = {
+        .read = {
+            omap_sysctl_read8,
+            omap_badwidth_read32,	/* TODO */
+            omap_sysctl_read,
+        },
+        .write = {
+            omap_sysctl_write8,
+            omap_badwidth_write32,	/* TODO */
+            omap_sysctl_write,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void omap_sysctl_reset(struct omap_sysctl_s *s)
@@ -2168,16 +2179,15 @@ static void omap_sysctl_reset(struct omap_sysctl_s *s)
 static struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
                 omap_clk iclk, struct omap_mpu_state_s *mpu)
 {
-    int iomemtype;
     struct omap_sysctl_s *s = (struct omap_sysctl_s *)
             g_malloc0(sizeof(struct omap_sysctl_s));
 
     s->mpu = mpu;
     omap_sysctl_reset(s);
 
-    iomemtype = cpu_register_io_memory(omap_sysctl_readfn,
-                    omap_sysctl_writefn, s, DEVICE_NATIVE_ENDIAN);
-    omap_l4_attach(ta, 0, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_sysctl_ops, s, "omap.sysctl",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach_region(ta, 0, &s->iomem);
 
     return s;
 }
@@ -2236,7 +2246,6 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
             g_malloc0(sizeof(struct omap_mpu_state_s));
-    ram_addr_t sram_base, q2_base;
     qemu_irq *cpu_irq;
     qemu_irq dma_irqs[4];
     DriveInfo *dinfo;
@@ -2260,12 +2269,10 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
     omap_clk_init(s);
 
     /* Memory-mapped stuff */
-    cpu_register_physical_memory(OMAP2_Q2_BASE, s->sdram_size,
-                    (q2_base = qemu_ram_alloc(NULL, "omap2.dram",
-                                              s->sdram_size)) | IO_MEM_RAM);
-    cpu_register_physical_memory(OMAP2_SRAM_BASE, s->sram_size,
-                    (sram_base = qemu_ram_alloc(NULL, "omap2.sram",
-                                                s->sram_size)) | IO_MEM_RAM);
+    memory_region_init_ram(&s->sdram, NULL, "omap2.dram", s->sdram_size);
+    memory_region_add_subregion(sysmem, OMAP2_Q2_BASE, &s->sdram);
+    memory_region_init_ram(&s->sram, NULL, "omap2.sram", s->sram_size);
+    memory_region_add_subregion(sysmem, OMAP2_SRAM_BASE, &s->sram);
 
     s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54);
 
@@ -2298,9 +2305,9 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
     s->port->addr_valid = omap2_validate_addr;
 
     /* Register SDRAM and SRAM ports for fast DMA transfers.  */
-    soc_dma_port_add_mem(s->dma, qemu_get_ram_ptr(q2_base),
+    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sdram),
                          OMAP2_Q2_BASE, s->sdram_size);
-    soc_dma_port_add_mem(s->dma, qemu_get_ram_ptr(sram_base),
+    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sram),
                          OMAP2_SRAM_BASE, s->sram_size);
 
     s->uart[0] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 19),
commit 9bac7d6c157f1e0dfa4dbf2c65ec994eb1a4a3a2
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 27 11:53:29 2011 +0200

    omap2: convert to memory API (part I)
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap2.c b/hw/omap2.c
index 3a7b210..a5f9b7d 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -33,6 +33,7 @@
 /* Enhanced Audio Controller (CODEC only) */
 struct omap_eac_s {
     qemu_irq irq;
+    MemoryRegion iomem;
 
     uint16_t sysconfig;
     uint8_t config[4];
@@ -323,11 +324,16 @@ static void omap_eac_reset(struct omap_eac_s *s)
     omap_eac_interrupt_update(s);
 }
 
-static uint32_t omap_eac_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_eac_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     struct omap_eac_s *s = (struct omap_eac_s *) opaque;
     uint32_t ret;
 
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
     switch (addr) {
     case 0x000:	/* CPCFR1 */
         return s->config[0];
@@ -435,10 +441,14 @@ static uint32_t omap_eac_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_eac_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                           uint64_t value, unsigned size)
 {
     struct omap_eac_s *s = (struct omap_eac_s *) opaque;
 
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x098:	/* APD1LCR */
     case 0x09c:	/* APD1RCR */
@@ -574,22 +584,15 @@ static void omap_eac_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_eac_readfn[] = {
-    omap_badwidth_read16,
-    omap_eac_read,
-    omap_badwidth_read16,
-};
-
-static CPUWriteMemoryFunc * const omap_eac_writefn[] = {
-    omap_badwidth_write16,
-    omap_eac_write,
-    omap_badwidth_write16,
+static const MemoryRegionOps omap_eac_ops = {
+    .read = omap_eac_read,
+    .write = omap_eac_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
                 qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
 {
-    int iomemtype;
     struct omap_eac_s *s = (struct omap_eac_s *)
             g_malloc0(sizeof(struct omap_eac_s));
 
@@ -600,9 +603,9 @@ static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
 
     AUD_register_card("OMAP EAC", &s->codec.card);
 
-    iomemtype = cpu_register_io_memory(omap_eac_readfn,
-                    omap_eac_writefn, s, DEVICE_NATIVE_ENDIAN);
-    omap_l4_attach(ta, 0, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_eac_ops, s, "omap.eac",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach_region(ta, 0, &s->iomem);
 
     return s;
 }
@@ -610,6 +613,8 @@ static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
 /* STI/XTI (emulation interface) console - reverse engineered only */
 struct omap_sti_s {
     qemu_irq irq;
+    MemoryRegion iomem;
+    MemoryRegion iomem_fifo;
     CharDriverState *chr;
 
     uint32_t sysconfig;
@@ -639,10 +644,15 @@ static void omap_sti_reset(struct omap_sti_s *s)
     omap_sti_interrupt_update(s);
 }
 
-static uint32_t omap_sti_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_sti_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     struct omap_sti_s *s = (struct omap_sti_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x00:	/* STI_REVISION */
         return 0x10;
@@ -676,10 +686,14 @@ static uint32_t omap_sti_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_sti_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                           uint64_t value, unsigned size)
 {
     struct omap_sti_s *s = (struct omap_sti_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x00:	/* STI_REVISION */
     case 0x14:	/* STI_SYSSTATUS / STI_RX_STATUS / XTI_SYSSTATUS */
@@ -721,31 +735,30 @@ static void omap_sti_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_sti_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_sti_read,
+static const MemoryRegionOps omap_sti_ops = {
+    .read = omap_sti_read,
+    .write = omap_sti_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const omap_sti_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_sti_write,
-};
-
-static uint32_t omap_sti_fifo_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_sti_fifo_read(void *opaque, target_phys_addr_t addr,
+                                   unsigned size)
 {
     OMAP_BAD_REG(addr);
     return 0;
 }
 
 static void omap_sti_fifo_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                                uint64_t value, unsigned size)
 {
     struct omap_sti_s *s = (struct omap_sti_s *) opaque;
     int ch = addr >> 6;
     uint8_t byte = value;
 
+    if (size != 1) {
+        return omap_badwidth_write8(opaque, addr, size);
+    }
+
     if (ch == STI_TRACE_CONTROL_CHANNEL) {
         /* Flush channel <i>value</i>.  */
         qemu_chr_fe_write(s->chr, (const uint8_t *) "\r", 1);
@@ -759,23 +772,17 @@ static void omap_sti_fifo_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_sti_fifo_readfn[] = {
-    omap_sti_fifo_read,
-    omap_badwidth_read8,
-    omap_badwidth_read8,
-};
-
-static CPUWriteMemoryFunc * const omap_sti_fifo_writefn[] = {
-    omap_sti_fifo_write,
-    omap_badwidth_write8,
-    omap_badwidth_write8,
+static const MemoryRegionOps omap_sti_fifo_ops = {
+    .read = omap_sti_fifo_read,
+    .write = omap_sti_fifo_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
+                MemoryRegion *sysmem,
                 target_phys_addr_t channel_base, qemu_irq irq, omap_clk clk,
                 CharDriverState *chr)
 {
-    int iomemtype;
     struct omap_sti_s *s = (struct omap_sti_s *)
             g_malloc0(sizeof(struct omap_sti_s));
 
@@ -784,13 +791,13 @@ static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
 
     s->chr = chr ?: qemu_chr_new("null", "null", NULL);
 
-    iomemtype = cpu_register_io_memory(omap_sti_readfn,
-                    omap_sti_writefn, s, DEVICE_NATIVE_ENDIAN);
-    omap_l4_attach(ta, 0, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_sti_ops, s, "omap.sti",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach_region(ta, 0, &s->iomem);
 
-    iomemtype = cpu_register_io_memory(omap_sti_fifo_readfn,
-                    omap_sti_fifo_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(channel_base, 0x10000, iomemtype);
+    memory_region_init_io(&s->iomem_fifo, &omap_sti_fifo_ops, s,
+                          "omap.sti.fifo", 0x10000);
+    memory_region_add_subregion(sysmem, channel_base, &s->iomem_fifo);
 
     return s;
 }
@@ -2457,7 +2464,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
                     omap_findclk(s, "dss_l3_iclk"),
                     omap_findclk(s, "dss_l4_iclk"));
 
-    omap_sti_init(omap_l4ta(s->l4, 18), 0x54000000,
+    omap_sti_init(omap_l4ta(s->l4, 18), sysmem, 0x54000000,
                   qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_STI),
                   omap_findclk(s, "emul_ck"),
                     serial_hds[0] && serial_hds[1] && serial_hds[2] ?
commit 750ecd444ff7e4e27928d65164228b3e1ae5a95b
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 27 11:38:10 2011 +0200

    sysbus: rename sysbus_init_mmio_region() to sysbus_init_mmio()
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index c232946..3a1b111 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -410,18 +410,18 @@ static int pci_pbm_init_device(SysBusDevice *dev)
     memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config",
                           0x10000);
     /* at region 0 */
-    sysbus_init_mmio_region(dev, &s->apb_config);
+    sysbus_init_mmio(dev, &s->apb_config);
 
     memory_region_init_io(&s->pci_config, &pci_config_ops, s, "apb-pci-config",
                           0x1000000);
     /* at region 1 */
-    sysbus_init_mmio_region(dev, &s->pci_config);
+    sysbus_init_mmio(dev, &s->pci_config);
 
     /* pci_ioport */
     memory_region_init_io(&s->pci_ioport, &pci_ioport_ops, s,
                           "apb-pci-ioport", 0x10000);
     /* at region 2 */
-    sysbus_init_mmio_region(dev, &s->pci_ioport);
+    sysbus_init_mmio(dev, &s->pci_ioport);
 
     return 0;
 }
diff --git a/hw/apic.c b/hw/apic.c
index 8289eef..9d0f460 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -998,7 +998,7 @@ static int apic_init1(SysBusDevice *dev)
     }
     memory_region_init_io(&s->io_memory, &apic_io_ops, s, "apic",
                           MSI_ADDR_SIZE);
-    sysbus_init_mmio_region(dev, &s->io_memory);
+    sysbus_init_mmio(dev, &s->io_memory);
 
     s->timer = qemu_new_timer_ns(vm_clock, apic_timer, s);
     s->idx = last_apic_idx++;
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index 974a0d8..32ecf98 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -73,7 +73,7 @@ static int realview_mpcore_init(SysBusDevice *dev)
         }
     }
     qdev_init_gpio_in(&dev->qdev, mpcore_rirq_set_irq, 64);
-    sysbus_init_mmio_region(dev, sysbus_mmio_get_region(s->priv, 0));
+    sysbus_init_mmio(dev, sysbus_mmio_get_region(s->priv, 0));
     return 0;
 }
 
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index 477fc6f..4b88648 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -383,7 +383,7 @@ static int arm_sysctl_init1(SysBusDevice *dev)
     arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev);
 
     memory_region_init_io(&s->iomem, &arm_sysctl_ops, s, "arm-sysctl", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     qdev_init_gpio_in(&s->busdev.qdev, arm_sysctl_gpio_set, 2);
     qdev_init_gpio_out(&s->busdev.qdev, &s->pl110_mux_ctrl, 1);
     return 0;
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 66db81d..8f442d7 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -247,7 +247,7 @@ static int sp804_init(SysBusDevice *dev)
     s->timer[0]->irq = qi[0];
     s->timer[1]->irq = qi[1];
     memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     vmstate_register(&dev->qdev, -1, &vmstate_sp804, s);
     return 0;
 }
@@ -311,7 +311,7 @@ static int icp_pit_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->timer[2]->irq);
 
     memory_region_init_io(&s->iomem, &icp_pit_ops, s, "icp_pit", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     /* This device has no state to save/restore.  The component timers will
        save themselves.  */
     return 0;
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 28d41b8..eb8c0d6 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -126,7 +126,7 @@ static int bitband_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &bitband_ops, &s->base, "bitband",
                           0x02000000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
diff --git a/hw/bitbang_i2c.c b/hw/bitbang_i2c.c
index 71dd595..18df411 100644
--- a/hw/bitbang_i2c.c
+++ b/hw/bitbang_i2c.c
@@ -207,7 +207,7 @@ static int gpio_i2c_init(SysBusDevice *dev)
     i2c_bus *bus;
 
     memory_region_init(&s->dummy_iomem, "gpio_i2c", 0);
-    sysbus_init_mmio_region(dev, &s->dummy_iomem);
+    sysbus_init_mmio(dev, &s->dummy_iomem);
 
     bus = i2c_init_bus(&dev->qdev, "i2c");
     s->bitbang = bitbang_i2c_init(bus);
diff --git a/hw/bonito.c b/hw/bonito.c
index 1e52f61..04d706a 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -684,29 +684,29 @@ static int bonito_initfn(PCIDevice *dev)
     /* set the north bridge register mapping */
     memory_region_init_io(&s->iomem, &bonito_ops, s,
                           "north-bridge-register", BONITO_INTERNAL_REG_SIZE);
-    sysbus_init_mmio_region(sysbus, &s->iomem);
+    sysbus_init_mmio(sysbus, &s->iomem);
     sysbus_mmio_map(sysbus, 0, BONITO_INTERNAL_REG_BASE);
 
     /* set the north bridge pci configure  mapping */
     memory_region_init_io(&s->pcihost->conf_mem, &bonito_pciconf_ops, s,
                           "north-bridge-pci-config", BONITO_PCICONFIG_SIZE);
-    sysbus_init_mmio_region(sysbus, &s->pcihost->conf_mem);
+    sysbus_init_mmio(sysbus, &s->pcihost->conf_mem);
     sysbus_mmio_map(sysbus, 1, BONITO_PCICONFIG_BASE);
 
     /* set the south bridge pci configure  mapping */
     memory_region_init_io(&s->pcihost->data_mem, &bonito_spciconf_ops, s,
                           "south-bridge-pci-config", BONITO_SPCICONFIG_SIZE);
-    sysbus_init_mmio_region(sysbus, &s->pcihost->data_mem);
+    sysbus_init_mmio(sysbus, &s->pcihost->data_mem);
     sysbus_mmio_map(sysbus, 2, BONITO_SPCICONFIG_BASE);
 
     memory_region_init_io(&s->iomem_ldma, &bonito_ldma_ops, s,
                           "ldma", 0x100);
-    sysbus_init_mmio_region(sysbus, &s->iomem_ldma);
+    sysbus_init_mmio(sysbus, &s->iomem_ldma);
     sysbus_mmio_map(sysbus, 3, 0xbfe00200);
 
     memory_region_init_io(&s->iomem_cop, &bonito_cop_ops, s,
                           "cop", 0x100);
-    sysbus_init_mmio_region(sysbus, &s->iomem_cop);
+    sysbus_init_mmio(sysbus, &s->iomem_cop);
     sysbus_mmio_map(sysbus, 4, 0xbfe00300);
 
     /* Map PCI IO Space  0x1fd0 0000 - 0x1fd1 0000 */
diff --git a/hw/cs4231.c b/hw/cs4231.c
index 0349838..2dfb708 100644
--- a/hw/cs4231.c
+++ b/hw/cs4231.c
@@ -145,7 +145,7 @@ static int cs4231_init1(SysBusDevice *dev)
     CSState *s = FROM_SYSBUS(CSState, dev);
 
     memory_region_init_io(&s->iomem, &cs_mem_ops, s, "cs4321", CS_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
     return 0;
diff --git a/hw/dec_pci.c b/hw/dec_pci.c
index 1aec066..08d4e06 100644
--- a/hw/dec_pci.c
+++ b/hw/dec_pci.c
@@ -87,8 +87,8 @@ static int pci_dec_21154_init_device(SysBusDevice *dev)
                           &s->host_state, "pci-conf-idx", 0x1000);
     memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
                           &s->host_state, "pci-data-idx", 0x1000);
-    sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio_region(dev, &s->host_state.data_mem);
+    sysbus_init_mmio(dev, &s->host_state.conf_mem);
+    sysbus_init_mmio(dev, &s->host_state.data_mem);
     return 0;
 }
 
diff --git a/hw/ds1225y.c b/hw/ds1225y.c
index a93fbe6..59d224e 100644
--- a/hw/ds1225y.c
+++ b/hw/ds1225y.c
@@ -118,7 +118,7 @@ static int nvram_sysbus_initfn(SysBusDevice *dev)
     s->contents = g_malloc0(s->chip_size);
 
     memory_region_init_io(&s->iomem, &nvram_ops, s, "nvram", s->chip_size);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     /* Read current file */
     file = fopen(s->filename, "rb");
diff --git a/hw/eccmemctl.c b/hw/eccmemctl.c
index 56cac25..7743465 100644
--- a/hw/eccmemctl.c
+++ b/hw/eccmemctl.c
@@ -297,12 +297,12 @@ static int ecc_init1(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
     s->regs[0] = s->version;
     memory_region_init_io(&s->iomem, &ecc_mem_ops, s, "ecc", ECC_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     if (s->version == ECC_MCC) { // SS-600MP only
         memory_region_init_io(&s->iomem_diag, &ecc_diag_mem_ops, s,
                               "ecc.diag", ECC_DIAG_SIZE);
-        sysbus_init_mmio_region(dev, &s->iomem_diag);
+        sysbus_init_mmio(dev, &s->iomem_diag);
     }
 
     return 0;
diff --git a/hw/empty_slot.c b/hw/empty_slot.c
index 626ba69..8b734f2 100644
--- a/hw/empty_slot.c
+++ b/hw/empty_slot.c
@@ -72,7 +72,7 @@ static int empty_slot_init1(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &empty_slot_ops, s,
                           "empty-slot", s->size);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
diff --git a/hw/escc.c b/hw/escc.c
index 13c7e66..81204a6 100644
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -888,7 +888,7 @@ static int escc_init1(SysBusDevice *dev)
 
     memory_region_init_io(&s->mmio, &escc_mem_ops, s, "escc",
                           ESCC_SIZE << s->it_shift);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
 
     if (s->chn[0].type == mouse) {
         qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0,
diff --git a/hw/esp.c b/hw/esp.c
index 9ab41ba..9551c78 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -745,7 +745,7 @@ static int esp_init1(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &esp_mem_ops, s,
                           "esp", ESP_REGS << s->it_shift);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2);
 
diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c
index 246a279..5ac2d15 100644
--- a/hw/etraxfs_eth.c
+++ b/hw/etraxfs_eth.c
@@ -604,7 +604,7 @@ static int fs_eth_init(SysBusDevice *dev)
 	s->dma_in->client.pull = NULL;
 
 	memory_region_init_io(&s->mmio, &eth_ops, s, "etraxfs-eth", 0x5c);
-	sysbus_init_mmio_region(dev, &s->mmio);
+	sysbus_init_mmio(dev, &s->mmio);
 
 	qemu_macaddr_default_if_unset(&s->conf.macaddr);
 	s->nic = qemu_new_nic(&net_etraxfs_info, &s->conf,
diff --git a/hw/etraxfs_pic.c b/hw/etraxfs_pic.c
index 47a56d7..72cbdb8 100644
--- a/hw/etraxfs_pic.c
+++ b/hw/etraxfs_pic.c
@@ -147,7 +147,7 @@ static int etraxfs_pic_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->parent_nmi);
 
     memory_region_init_io(&s->mmio, &pic_ops, s, "etraxfs-pic", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
     return 0;
 }
 
diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
index 298b985..2623dab 100644
--- a/hw/etraxfs_ser.c
+++ b/hw/etraxfs_ser.c
@@ -214,7 +214,7 @@ static int etraxfs_ser_init(SysBusDevice *dev)
 
     sysbus_init_irq(dev, &s->irq);
     memory_region_init_io(&s->mmio, &ser_ops, s, "etraxfs-serial", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
 
     s->chr = qdev_init_chardev(&dev->qdev);
     if (s->chr)
diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c
index 57dc739..319cee1 100644
--- a/hw/etraxfs_timer.c
+++ b/hw/etraxfs_timer.c
@@ -323,7 +323,7 @@ static int etraxfs_timer_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &t->nmi);
 
     memory_region_init_io(&t->mmio, &timer_ops, t, "etraxfs-timer", 0x5c);
-    sysbus_init_mmio_region(dev, &t->mmio);
+    sysbus_init_mmio(dev, &t->mmio);
     qemu_register_reset(etraxfs_timer_reset, t);
     return 0;
 }
diff --git a/hw/fdc.c b/hw/fdc.c
index a3329c9..2adfb44 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -1911,7 +1911,7 @@ static int sysbus_fdc_init1(SysBusDevice *dev)
     int ret;
 
     memory_region_init_io(&fdctrl->iomem, &fdctrl_mem_ops, fdctrl, "fdc", 0x08);
-    sysbus_init_mmio_region(dev, &fdctrl->iomem);
+    sysbus_init_mmio(dev, &fdctrl->iomem);
     sysbus_init_irq(dev, &fdctrl->irq);
     qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1);
     fdctrl->dma_chann = -1;
@@ -1928,7 +1928,7 @@ static int sun4m_fdc_init1(SysBusDevice *dev)
 
     memory_region_init_io(&fdctrl->iomem, &fdctrl_mem_strict_ops, fdctrl,
                           "fdctrl", 0x08);
-    sysbus_init_mmio_region(dev, &fdctrl->iomem);
+    sysbus_init_mmio(dev, &fdctrl->iomem);
     sysbus_init_irq(dev, &fdctrl->irq);
     qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1);
 
diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
index 449f6d9..f953532 100644
--- a/hw/fw_cfg.c
+++ b/hw/fw_cfg.c
@@ -510,10 +510,10 @@ static int fw_cfg_init1(SysBusDevice *dev)
 
     memory_region_init_io(&s->ctl_iomem, &fw_cfg_ctl_mem_ops, s,
                           "fwcfg.ctl", FW_CFG_SIZE);
-    sysbus_init_mmio_region(dev, &s->ctl_iomem);
+    sysbus_init_mmio(dev, &s->ctl_iomem);
     memory_region_init_io(&s->data_iomem, &fw_cfg_data_mem_ops, s,
                           "fwcfg.data", FW_CFG_DATA_SIZE);
-    sysbus_init_mmio_region(dev, &s->data_iomem);
+    sysbus_init_mmio(dev, &s->data_iomem);
     /* In case ctl and data overlap: */
     memory_region_init_io(&s->comb_iomem, &fw_cfg_comb_mem_ops, s,
                           "fwcfg", FW_CFG_SIZE);
diff --git a/hw/g364fb.c b/hw/g364fb.c
index f00ee27..34fb08c 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -540,8 +540,8 @@ static int g364fb_sysbus_init(SysBusDevice *dev)
 
     g364fb_init(&dev->qdev, s);
     sysbus_init_irq(dev, &s->irq);
-    sysbus_init_mmio_region(dev, &s->mem_ctrl);
-    sysbus_init_mmio_region(dev, &s->mem_vram);
+    sysbus_init_mmio(dev, &s->mem_ctrl);
+    sysbus_init_mmio(dev, &s->mem_vram);
 
     return 0;
 }
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index 94a608e..1e529fb 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -108,8 +108,8 @@ static int pci_grackle_init_device(SysBusDevice *dev)
                           &s->host_state, "pci-conf-idx", 0x1000);
     memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
                           &s->host_state, "pci-data-idx", 0x1000);
-    sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio_region(dev, &s->host_state.data_mem);
+    sysbus_init_mmio(dev, &s->host_state.conf_mem);
+    sysbus_init_mmio(dev, &s->host_state.data_mem);
 
     qemu_register_reset(pci_grackle_reset, &s->host_state);
     return 0;
diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
index 12dbca0..62bdb03 100644
--- a/hw/grlib_apbuart.c
+++ b/hw/grlib_apbuart.c
@@ -164,7 +164,7 @@ static int grlib_apbuart_init(SysBusDevice *dev)
     memory_region_init_io(&uart->iomem, &grlib_apbuart_ops, uart,
                           "uart", UART_REG_SIZE);
 
-    sysbus_init_mmio_region(dev, &uart->iomem);
+    sysbus_init_mmio(dev, &uart->iomem);
 
     return 0;
 }
diff --git a/hw/grlib_gptimer.c b/hw/grlib_gptimer.c
index c142a5b..5645054 100644
--- a/hw/grlib_gptimer.c
+++ b/hw/grlib_gptimer.c
@@ -367,7 +367,7 @@ static int grlib_gptimer_init(SysBusDevice *dev)
     memory_region_init_io(&unit->iomem, &grlib_gptimer_ops, unit, "gptimer",
                           UNIT_REG_SIZE + GPTIMER_REG_SIZE * unit->nr_timers);
 
-    sysbus_init_mmio_region(dev, &unit->iomem);
+    sysbus_init_mmio(dev, &unit->iomem);
     return 0;
 }
 
diff --git a/hw/grlib_irqmp.c b/hw/grlib_irqmp.c
index dce0bbb..2872556 100644
--- a/hw/grlib_irqmp.c
+++ b/hw/grlib_irqmp.c
@@ -349,7 +349,7 @@ static int grlib_irqmp_init(SysBusDevice *dev)
 
     irqmp->state = g_malloc0(sizeof *irqmp->state);
 
-    sysbus_init_mmio_region(dev, &irqmp->iomem);
+    sysbus_init_mmio(dev, &irqmp->iomem);
 
     return 0;
 }
diff --git a/hw/hpet.c b/hw/hpet.c
index 382b257..5312df7 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -691,7 +691,7 @@ static int hpet_init(SysBusDevice *dev)
 
     /* HPET Area */
     memory_region_init_io(&s->iomem, &hpet_ram_ops, s, "hpet", 0x400);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index 7f79560..2551236 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -266,7 +266,7 @@ static int integratorcm_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &integratorcm_ops, s,
                           "integratorcm", 0x00800000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     integratorcm_do_remap(s, 1);
     /* ??? Save/restore.  */
@@ -387,7 +387,7 @@ static int icp_pic_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->parent_irq);
     sysbus_init_irq(dev, &s->parent_fiq);
     memory_region_init_io(&s->iomem, &icp_pic_ops, s, "icp-pic", 0x00800000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
diff --git a/hw/ioapic.c b/hw/ioapic.c
index eb75766..27b07c6 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -334,7 +334,7 @@ static int ioapic_init1(SysBusDevice *dev)
     }
 
     memory_region_init_io(&s->io_memory, &ioapic_io_ops, s, "ioapic", 0x1000);
-    sysbus_init_mmio_region(dev, &s->io_memory);
+    sysbus_init_mmio(dev, &s->io_memory);
 
     qdev_init_gpio_in(&dev->qdev, ioapic_set_irq, IOAPIC_NUM_PINS);
 
diff --git a/hw/lan9118.c b/hw/lan9118.c
index f8149e6..ee8b2ea 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -1132,7 +1132,7 @@ static int lan9118_init1(SysBusDevice *dev)
     int i;
 
     memory_region_init_io(&s->mmio, &lan9118_mem_ops, s, "lan9118-mmio", 0x100);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
     sysbus_init_irq(dev, &s->irq);
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
 
diff --git a/hw/lance.c b/hw/lance.c
index 93d5fda..7164700 100644
--- a/hw/lance.c
+++ b/hw/lance.c
@@ -121,7 +121,7 @@ static int lance_init(SysBusDevice *dev)
 
     qdev_init_gpio_in(&dev->qdev, parent_lance_reset, 1);
 
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
 
     sysbus_init_irq(dev, &s->irq);
 
diff --git a/hw/lm32_sys.c b/hw/lm32_sys.c
index 0c8e971..83974ee 100644
--- a/hw/lm32_sys.c
+++ b/hw/lm32_sys.c
@@ -119,7 +119,7 @@ static int lm32_sys_init(SysBusDevice *dev)
     LM32SysState *s = FROM_SYSBUS(typeof(*s), dev);
 
     memory_region_init_io(&s->iomem, &sys_ops , s, "sys", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     /* Note: This device is not created in the board initialization,
      * instead it has to be added with the -device parameter. Therefore,
diff --git a/hw/lm32_timer.c b/hw/lm32_timer.c
index a3a21ed..445847f 100644
--- a/hw/lm32_timer.c
+++ b/hw/lm32_timer.c
@@ -180,7 +180,7 @@ static int lm32_timer_init(SysBusDevice *dev)
     ptimer_set_freq(s->ptimer, s->freq_hz);
 
     memory_region_init_io(&s->iomem, &timer_ops, s, "timer", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c
index 46a5ae0..d013abd 100644
--- a/hw/lm32_uart.c
+++ b/hw/lm32_uart.c
@@ -250,7 +250,7 @@ static int lm32_uart_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
 
     memory_region_init_io(&s->iomem, &uart_ops, s, "uart", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     s->chr = qdev_init_chardev(&dev->qdev);
     if (s->chr) {
diff --git a/hw/m48t59.c b/hw/m48t59.c
index 06a3974..8d8d495 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -713,7 +713,7 @@ static int m48t59_init1(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->IRQ);
 
     memory_region_init_io(&s->iomem, &nvram_ops, s, "m48t59.nvram", s->size);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     m48t59_init_common(s);
 
     return 0;
diff --git a/hw/marvell_88w8618_audio.c b/hw/marvell_88w8618_audio.c
index 6982352..855b792 100644
--- a/hw/marvell_88w8618_audio.c
+++ b/hw/marvell_88w8618_audio.c
@@ -245,7 +245,7 @@ static int mv88w8618_audio_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &mv88w8618_audio_ops, s,
                           "audio", MP_AUDIO_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c
index 5c5ed27..e824a49 100644
--- a/hw/milkymist-ac97.c
+++ b/hw/milkymist-ac97.c
@@ -302,7 +302,7 @@ static int milkymist_ac97_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &ac97_mmio_ops, s,
             "milkymist-ac97", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     return 0;
 }
diff --git a/hw/milkymist-hpdmc.c b/hw/milkymist-hpdmc.c
index 17c840f..be575c9 100644
--- a/hw/milkymist-hpdmc.c
+++ b/hw/milkymist-hpdmc.c
@@ -129,7 +129,7 @@ static int milkymist_hpdmc_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &hpdmc_mmio_ops, s,
             "milkymist-hpdmc", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     return 0;
 }
diff --git a/hw/milkymist-memcard.c b/hw/milkymist-memcard.c
index fb6e558..865a46c 100644
--- a/hw/milkymist-memcard.c
+++ b/hw/milkymist-memcard.c
@@ -255,7 +255,7 @@ static int milkymist_memcard_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &memcard_mmio_ops, s,
             "milkymist-memcard", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     return 0;
 }
diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c
index 85d9400..b5e0dac 100644
--- a/hw/milkymist-minimac2.c
+++ b/hw/milkymist-minimac2.c
@@ -465,7 +465,7 @@ static int milkymist_minimac2_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &minimac2_ops, s,
                           "milkymist-minimac2", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     /* register buffers memory */
     memory_region_init_ram(&s->buffers, NULL, "milkymist-minimac2.buffers",
diff --git a/hw/milkymist-pfpu.c b/hw/milkymist-pfpu.c
index 672f6e4..dc92eb6 100644
--- a/hw/milkymist-pfpu.c
+++ b/hw/milkymist-pfpu.c
@@ -499,7 +499,7 @@ static int milkymist_pfpu_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &pfpu_mmio_ops, s,
             "milkymist-pfpu", MICROCODE_END * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     return 0;
 }
diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c
index ec5f334..6dd953c 100644
--- a/hw/milkymist-softusb.c
+++ b/hw/milkymist-softusb.c
@@ -264,7 +264,7 @@ static int milkymist_softusb_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &softusb_mmio_ops, s,
                           "milkymist-softusb", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     /* register pmem and dmem */
     memory_region_init_ram(&s->pmem, NULL, "milkymist-softusb.pmem",
diff --git a/hw/milkymist-sysctl.c b/hw/milkymist-sysctl.c
index 5783f08..6326b70 100644
--- a/hw/milkymist-sysctl.c
+++ b/hw/milkymist-sysctl.c
@@ -273,7 +273,7 @@ static int milkymist_sysctl_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &sysctl_mmio_ops, s,
             "milkymist-sysctl", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     return 0;
 }
diff --git a/hw/milkymist-tmu2.c b/hw/milkymist-tmu2.c
index aad0ed0..20110e5 100644
--- a/hw/milkymist-tmu2.c
+++ b/hw/milkymist-tmu2.c
@@ -449,7 +449,7 @@ static int milkymist_tmu2_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &tmu2_mmio_ops, s,
             "milkymist-tmu2", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     return 0;
 }
diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c
index 5404ca9..eaf1c0d 100644
--- a/hw/milkymist-uart.c
+++ b/hw/milkymist-uart.c
@@ -197,7 +197,7 @@ static int milkymist_uart_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &uart_mmio_ops, s,
             "milkymist-uart", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     s->chr = qdev_init_chardev(&dev->qdev);
     if (s->chr) {
diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c
index be81abd..01cd309 100644
--- a/hw/milkymist-vgafb.c
+++ b/hw/milkymist-vgafb.c
@@ -272,7 +272,7 @@ static int milkymist_vgafb_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &vgafb_mmio_ops, s,
             "milkymist-vgafb", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     s->ds = graphic_console_init(vgafb_update_display,
                                  vgafb_invalidate_display,
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index 605367b..b1234b8 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -236,7 +236,7 @@ static int mipsnet_sysbus_init(SysBusDevice *dev)
     MIPSnetState *s = DO_UPCAST(MIPSnetState, busdev, dev);
 
     memory_region_init_io(&s->io, &mipsnet_ioport_ops, s, "mipsnet-io", 36);
-    sysbus_init_mmio_region(dev, &s->io);
+    sysbus_init_mmio(dev, &s->io);
     sysbus_init_irq(dev, &s->irq);
 
     s->nic = qemu_new_nic(&net_mipsnet_info, &s->conf,
diff --git a/hw/mpc8544_guts.c b/hw/mpc8544_guts.c
index 00637f6..f01b38c 100644
--- a/hw/mpc8544_guts.c
+++ b/hw/mpc8544_guts.c
@@ -116,7 +116,7 @@ static int mpc8544_guts_initfn(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &mpc8544_guts_ops, s,
                           "mpc6544.guts", MPC8544_GUTS_MMIO_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
diff --git a/hw/mpcore.c b/hw/mpcore.c
index d6175cf..4357d12 100644
--- a/hw/mpcore.c
+++ b/hw/mpcore.c
@@ -275,7 +275,7 @@ static int mpcore_priv_init(SysBusDevice *dev)
 
     gic_init(&s->gic, s->num_cpu);
     mpcore_priv_map_setup(s);
-    sysbus_init_mmio_region(dev, &s->container);
+    sysbus_init_mmio(dev, &s->container);
     for (i = 0; i < s->num_cpu * 2; i++) {
         mpcore_timer_init(s, &s->timer[i], i);
     }
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index cf9957b..9324702 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -207,7 +207,7 @@ static int mst_fpga_init(SysBusDevice *dev)
 
 	memory_region_init_io(&s->iomem, &mst_fpga_ops, s,
 			    "fpga", 0x00100000);
-	sysbus_init_mmio_region(dev, &s->iomem);
+	sysbus_init_mmio(dev, &s->iomem);
 	return 0;
 }
 
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 23acc1d..3c6cefe 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -386,7 +386,7 @@ static int mv88w8618_eth_init(SysBusDevice *dev)
                           dev->qdev.info->name, dev->qdev.id, s);
     memory_region_init_io(&s->iomem, &mv88w8618_eth_ops, s, "mv88w8618-eth",
                           MP_ETH_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
@@ -593,7 +593,7 @@ static int musicpal_lcd_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &musicpal_lcd_ops, s,
                           "musicpal-lcd", MP_LCD_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     s->ds = graphic_console_init(lcd_refresh, lcd_invalidate,
                                  NULL, NULL, s);
@@ -713,7 +713,7 @@ static int mv88w8618_pic_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->parent_irq);
     memory_region_init_io(&s->iomem, &mv88w8618_pic_ops, s,
                           "musicpal-pic", MP_PIC_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
@@ -869,7 +869,7 @@ static int mv88w8618_pit_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &mv88w8618_pit_ops, s,
                           "musicpal-pit", MP_PIT_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
@@ -954,7 +954,7 @@ static int mv88w8618_flashcfg_init(SysBusDevice *dev)
     s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
     memory_region_init_io(&s->iomem, &mv88w8618_flashcfg_ops, s,
                           "musicpal-flashcfg", MP_FLASHCFG_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
@@ -1050,7 +1050,7 @@ static int mv88w8618_wlan_init(SysBusDevice *dev)
 
     memory_region_init_io(iomem, &mv88w8618_wlan_ops, NULL,
                           "musicpal-wlan", MP_WLAN_SIZE);
-    sysbus_init_mmio_region(dev, iomem);
+    sysbus_init_mmio(dev, iomem);
     return 0;
 }
 
@@ -1256,7 +1256,7 @@ static int musicpal_gpio_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &musicpal_gpio_ops, s,
                           "musicpal-gpio", MP_GPIO_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
 
@@ -1403,7 +1403,7 @@ static int musicpal_key_init(SysBusDevice *dev)
     musicpal_key_state *s = FROM_SYSBUS(musicpal_key_state, dev);
 
     memory_region_init(&s->iomem, "dummy", 0);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     s->kbd_extended = 0;
     s->pressed_keys = 0;
diff --git a/hw/omap_gpio.c b/hw/omap_gpio.c
index 0bfd661..29147be 100644
--- a/hw/omap_gpio.c
+++ b/hw/omap_gpio.c
@@ -679,7 +679,7 @@ static int omap_gpio_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->omap1.irq);
     memory_region_init_io(&s->iomem, &omap_gpio_ops, &s->omap1,
                           "omap.gpio", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
@@ -694,7 +694,7 @@ static int omap2_gpio_init(SysBusDevice *dev)
         s->modulecount = (s->mpu_model < omap2430) ? 4 : 5;
         memory_region_init_io(&s->iomem, &omap2_gpif_top_ops, s,
                               "omap2.gpio", 0x1000);
-        sysbus_init_mmio_region(dev, &s->iomem);
+        sysbus_init_mmio(dev, &s->iomem);
     } else {
         s->modulecount = 6;
     }
@@ -714,7 +714,7 @@ static int omap2_gpio_init(SysBusDevice *dev)
         sysbus_init_irq(dev, &m->wkup);
         memory_region_init_io(&m->iomem, &omap2_gpio_module_ops, m,
                               "omap.gpio-module", 0x1000);
-        sysbus_init_mmio_region(dev, &m->iomem);
+        sysbus_init_mmio(dev, &m->iomem);
     }
     return 0;
 }
diff --git a/hw/omap_intc.c b/hw/omap_intc.c
index 45efa25..fc53ec7 100644
--- a/hw/omap_intc.c
+++ b/hw/omap_intc.c
@@ -369,7 +369,7 @@ static int omap_intc_init(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, omap_set_intr, s->nbanks * 32);
     memory_region_init_io(&s->mmio, &omap_inth_mem_ops, s,
                           "omap-intc", s->size);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
     return 0;
 }
 
@@ -600,7 +600,7 @@ static int omap2_intc_init(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, omap_set_intr_noedge, s->nbanks * 32);
     memory_region_init_io(&s->mmio, &omap2_inth_mem_ops, s,
                           "omap2-intc", 0x1000);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
     return 0;
 }
 
diff --git a/hw/onenand.c b/hw/onenand.c
index 7898da9..a9d8d67 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -791,7 +791,7 @@ static int onenand_initfn(SysBusDevice *dev)
     s->data[1][1] = ram + ((0x8010 + (1 << (PAGE_SHIFT - 6))) << s->shift);
     onenand_mem_setup(s);
     sysbus_init_irq(dev, &s->intr);
-    sysbus_init_mmio_region(dev, &s->container);
+    sysbus_init_mmio(dev, &s->container);
     vmstate_register(&dev->qdev,
                      ((s->shift & 0x7f) << 24)
                      | ((s->id.man & 0xff) << 16)
diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c
index 2c1e475..f7cc1b4 100644
--- a/hw/opencores_eth.c
+++ b/hw/opencores_eth.c
@@ -708,11 +708,11 @@ static int sysbus_open_eth_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->reg_io, &open_eth_reg_ops, s,
             "open_eth.regs", 0x54);
-    sysbus_init_mmio_region(dev, &s->reg_io);
+    sysbus_init_mmio(dev, &s->reg_io);
 
     memory_region_init_io(&s->desc_io, &open_eth_desc_ops, s,
             "open_eth.desc", 0x400);
-    sysbus_init_mmio_region(dev, &s->desc_io);
+    sysbus_init_mmio(dev, &s->desc_io);
 
     sysbus_init_irq(dev, &s->irq);
 
diff --git a/hw/pl011.c b/hw/pl011.c
index 9cf6dea..1b05d76 100644
--- a/hw/pl011.c
+++ b/hw/pl011.c
@@ -261,7 +261,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
     pl011_state *s = FROM_SYSBUS(pl011_state, dev);
 
     memory_region_init_io(&s->iomem, &pl011_ops, s, "pl011", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     s->id = id;
     s->chr = qdev_init_chardev(&dev->qdev);
diff --git a/hw/pl022.c b/hw/pl022.c
index e0cf2b0..d43e4a2 100644
--- a/hw/pl022.c
+++ b/hw/pl022.c
@@ -277,7 +277,7 @@ static int pl022_init(SysBusDevice *dev)
     pl022_state *s = FROM_SYSBUS(pl022_state, dev);
 
     memory_region_init_io(&s->iomem, &pl022_ops, s, "pl022", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     s->ssi = ssi_create_bus(&dev->qdev, "ssi");
     pl022_reset(s);
diff --git a/hw/pl031.c b/hw/pl031.c
index 4ff96f9..a007ff0 100644
--- a/hw/pl031.c
+++ b/hw/pl031.c
@@ -200,7 +200,7 @@ static int pl031_init(SysBusDevice *dev)
     struct tm tm;
 
     memory_region_init_io(&s->iomem, &pl031_ops, s, "pl031", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     sysbus_init_irq(dev, &s->irq);
     /* ??? We assume vm_clock is zero at this point.  */
diff --git a/hw/pl041.c b/hw/pl041.c
index efd52ac..d8e55d1 100644
--- a/hw/pl041.c
+++ b/hw/pl041.c
@@ -543,7 +543,7 @@ static int pl041_init(SysBusDevice *dev)
 
     /* Connect the device to the sysbus */
     memory_region_init_io(&s->iomem, &pl041_ops, s, "pl041", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
     /* Init the codec */
diff --git a/hw/pl050.c b/hw/pl050.c
index dedd622..8182a1c 100644
--- a/hw/pl050.c
+++ b/hw/pl050.c
@@ -137,7 +137,7 @@ static int pl050_init(SysBusDevice *dev, int is_mouse)
     pl050_state *s = FROM_SYSBUS(pl050_state, dev);
 
     memory_region_init_io(&s->iomem, &pl050_ops, s, "pl050", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     s->is_mouse = is_mouse;
     if (s->is_mouse)
diff --git a/hw/pl061.c b/hw/pl061.c
index 0e16e8a..f33ae84 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -275,7 +275,7 @@ static int pl061_init(SysBusDevice *dev, const unsigned char *id)
     pl061_state *s = FROM_SYSBUS(pl061_state, dev);
     s->id = id;
     memory_region_init_io(&s->iomem, &pl061_ops, s, "pl061", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     qdev_init_gpio_in(&dev->qdev, pl061_set_irq, 8);
     qdev_init_gpio_out(&dev->qdev, s->out, 8);
diff --git a/hw/pl080.c b/hw/pl080.c
index 1efd3bd..e001df9 100644
--- a/hw/pl080.c
+++ b/hw/pl080.c
@@ -357,7 +357,7 @@ static int pl08x_init(SysBusDevice *dev, int nchannels)
     pl080_state *s = FROM_SYSBUS(pl080_state, dev);
 
     memory_region_init_io(&s->iomem, &pl080_ops, s, "pl080", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     s->nchannels = nchannels;
     return 0;
diff --git a/hw/pl110.c b/hw/pl110.c
index fbbcb2e..7aef8a4 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -435,7 +435,7 @@ static int pl110_init(SysBusDevice *dev)
     pl110_state *s = FROM_SYSBUS(pl110_state, dev);
 
     memory_region_init_io(&s->iomem, &pl110_ops, s, "pl110", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     qdev_init_gpio_in(&s->busdev.qdev, pl110_mux_ctrl_set, 1);
     s->ds = graphic_console_init(pl110_update_display,
diff --git a/hw/pl181.c b/hw/pl181.c
index e13ea8e..46855f6 100644
--- a/hw/pl181.c
+++ b/hw/pl181.c
@@ -453,7 +453,7 @@ static int pl181_init(SysBusDevice *dev)
     DriveInfo *dinfo;
 
     memory_region_init_io(&s->iomem, &pl181_ops, s, "pl181", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq[0]);
     sysbus_init_irq(dev, &s->irq[1]);
     qdev_init_gpio_out(&s->busdev.qdev, s->cardstatus, 2);
diff --git a/hw/pl190.c b/hw/pl190.c
index a3d008d..6fc2656 100644
--- a/hw/pl190.c
+++ b/hw/pl190.c
@@ -229,7 +229,7 @@ static int pl190_init(SysBusDevice *dev)
     pl190_state *s = FROM_SYSBUS(pl190_state, dev);
 
     memory_region_init_io(&s->iomem, &pl190_ops, s, "pl190", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     qdev_init_gpio_in(&dev->qdev, pl190_set_irq, 32);
     sysbus_init_irq(dev, &s->irq);
     sysbus_init_irq(dev, &s->fiq);
diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c
index cccd940..df74953 100644
--- a/hw/ppce500_spin.c
+++ b/hw/ppce500_spin.c
@@ -195,7 +195,7 @@ static int ppce500_spin_initfn(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &spin_rw_ops, s, "e500 spin pv device",
                           sizeof(SpinInfo) * MAX_CPUS);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     qemu_register_reset(spin_reset, s);
 
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 668b2b3..bd177b7 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -813,7 +813,7 @@ static int pxa2xx_ssp_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
 
     memory_region_init_io(&s->iomem, &pxa2xx_ssp_ops, s, "pxa2xx-ssp", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     register_savevm(&dev->qdev, "pxa2xx_ssp", -1, 0,
                     pxa2xx_ssp_save, pxa2xx_ssp_load, s);
 
@@ -1180,7 +1180,7 @@ static int pxa2xx_rtc_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->rtc_irq);
 
     memory_region_init_io(&s->iomem, &pxa2xx_rtc_ops, s, "pxa2xx-rtc", 0x10000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
@@ -1515,7 +1515,7 @@ static int pxa2xx_i2c_initfn(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &pxa2xx_i2c_ops, s,
                           "pxa2xx-i2x", s->region_size);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
     return 0;
diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c
index b5d1d61..cb28107 100644
--- a/hw/pxa2xx_dma.c
+++ b/hw/pxa2xx_dma.c
@@ -467,7 +467,7 @@ static int pxa2xx_dma_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &pxa2xx_dma_ops, s,
                           "pxa2xx.dma", 0x00010000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
     return 0;
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index aed3d4c..cc58c40 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -281,7 +281,7 @@ static int pxa2xx_gpio_initfn(SysBusDevice *dev)
     qdev_init_gpio_out(&dev->qdev, s->handler, s->lines);
 
     memory_region_init_io(&s->iomem, &pxa_gpio_ops, s, "pxa2xx-gpio", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq0);
     sysbus_init_irq(dev, &s->irq1);
     sysbus_init_irq(dev, &s->irqX);
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 13f96a9..92effbc 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -266,7 +266,7 @@ DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env)
     /* Enable IC memory-mapped registers access.  */
     memory_region_init_io(&s->iomem, &pxa2xx_pic_ops, s,
                           "pxa2xx-pic", 0x00100000);
-    sysbus_init_mmio_region(sysbus_from_qdev(dev), &s->iomem);
+    sysbus_init_mmio(sysbus_from_qdev(dev), &s->iomem);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
 
     /* Enable IC coprocessor access.  */
diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index 0c8e0d3..50e2678 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -416,7 +416,7 @@ static int pxa2xx_timer_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &pxa2xx_timer_ops, s,
                           "pxa2xx-timer", 0x00001000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
diff --git a/hw/realview.c b/hw/realview.c
index 9a8e63c..750a279 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -77,7 +77,7 @@ static int realview_i2c_init(SysBusDevice *dev)
     s->bitbang = bitbang_i2c_init(bus);
     memory_region_init_io(&s->iomem, &realview_i2c_ops, s,
                           "realview-i2c", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index cd6a44d..479f939 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -62,7 +62,7 @@ static int realview_gic_init(SysBusDevice *dev)
 
     gic_init(&s->gic);
     realview_gic_map_setup(s);
-    sysbus_init_mmio_region(dev, &s->container);
+    sysbus_init_mmio(dev, &s->container);
     return 0;
 }
 
diff --git a/hw/sbi.c b/hw/sbi.c
index 2f64d59..8965a71 100644
--- a/hw/sbi.c
+++ b/hw/sbi.c
@@ -126,7 +126,7 @@ static int sbi_init1(SysBusDevice *dev)
     }
 
     memory_region_init_io(&s->iomem, &sbi_mem_ops, s, "sbi", SBI_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index 36f3930..86f468e 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -154,8 +154,8 @@ static int sh_pci_init_device(SysBusDevice *dev)
                              0, 0x224);
     isa_mmio_setup(&s->isa, 0x40000);
     sysbus_init_mmio_cb2(dev, sh_pci_map, sh_pci_unmap);
-    sysbus_init_mmio_region(dev, &s->memconfig_a7);
-    sysbus_init_mmio_region(dev, &s->isa);
+    sysbus_init_mmio(dev, &s->memconfig_a7);
+    sysbus_init_mmio(dev, &s->isa);
     s->dev = pci_create_simple(s->bus, PCI_DEVFN(0, 0), "sh_pci_host");
     return 0;
 }
diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index e7812ed..9925e64 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -428,7 +428,7 @@ static int slavio_intctl_init1(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, slavio_set_irq_all, 32 + MAX_CPUS);
     memory_region_init_io(&s->iomem, &slavio_intctlm_mem_ops, s,
                           "master-interrupt-controller", INTCTLM_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     for (i = 0; i < MAX_CPUS; i++) {
         snprintf(slave_name, sizeof(slave_name),
@@ -438,7 +438,7 @@ static int slavio_intctl_init1(SysBusDevice *dev)
         }
         memory_region_init_io(&s->slaves[i].iomem, &slavio_intctl_mem_ops,
                               &s->slaves[i], slave_name, INTCTL_SIZE);
-        sysbus_init_mmio_region(dev, &s->slaves[i].iomem);
+        sysbus_init_mmio(dev, &s->slaves[i].iomem);
         s->slaves[i].cpu = i;
         s->slaves[i].master = s;
     }
diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index ccc1c53..484301c 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -414,7 +414,7 @@ static int apc_init1(SysBusDevice *dev)
     /* Power management (APC) XXX: not a Slavio device */
     memory_region_init_io(&s->iomem, &apc_mem_ops, s,
                           "apc", MISC_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
@@ -429,39 +429,39 @@ static int slavio_misc_init1(SysBusDevice *dev)
     /* Slavio control */
     memory_region_init_io(&s->cfg_iomem, &slavio_cfg_mem_ops, s,
                           "configuration", MISC_SIZE);
-    sysbus_init_mmio_region(dev, &s->cfg_iomem);
+    sysbus_init_mmio(dev, &s->cfg_iomem);
 
     /* Diagnostics */
     memory_region_init_io(&s->diag_iomem, &slavio_diag_mem_ops, s,
                           "diagnostic", MISC_SIZE);
-    sysbus_init_mmio_region(dev, &s->diag_iomem);
+    sysbus_init_mmio(dev, &s->diag_iomem);
 
     /* Modem control */
     memory_region_init_io(&s->mdm_iomem, &slavio_mdm_mem_ops, s,
                           "modem", MISC_SIZE);
-    sysbus_init_mmio_region(dev, &s->mdm_iomem);
+    sysbus_init_mmio(dev, &s->mdm_iomem);
 
     /* 16 bit registers */
     /* ss600mp diag LEDs */
     memory_region_init_io(&s->led_iomem, &slavio_led_mem_ops, s,
                           "leds", MISC_SIZE);
-    sysbus_init_mmio_region(dev, &s->led_iomem);
+    sysbus_init_mmio(dev, &s->led_iomem);
 
     /* 32 bit registers */
     /* System control */
     memory_region_init_io(&s->sysctrl_iomem, &slavio_sysctrl_mem_ops, s,
                           "system-control", MISC_SIZE);
-    sysbus_init_mmio_region(dev, &s->sysctrl_iomem);
+    sysbus_init_mmio(dev, &s->sysctrl_iomem);
 
     /* AUX 1 (Misc System Functions) */
     memory_region_init_io(&s->aux1_iomem, &slavio_aux1_mem_ops, s,
                           "misc-system-functions", MISC_SIZE);
-    sysbus_init_mmio_region(dev, &s->aux1_iomem);
+    sysbus_init_mmio(dev, &s->aux1_iomem);
 
     /* AUX 2 (Software Powerdown Control) */
     memory_region_init_io(&s->aux2_iomem, &slavio_aux2_mem_ops, s,
                           "software-powerdown-control", MISC_SIZE);
-    sysbus_init_mmio_region(dev, &s->aux2_iomem);
+    sysbus_init_mmio(dev, &s->aux2_iomem);
 
     qdev_init_gpio_in(&dev->qdev, slavio_set_power_fail, 1);
 
diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c
index c23f990..2353c43 100644
--- a/hw/slavio_timer.c
+++ b/hw/slavio_timer.c
@@ -395,7 +395,7 @@ static int slavio_timer_init1(SysBusDevice *dev)
         snprintf(timer_name, sizeof(timer_name), "timer-%i", i);
         memory_region_init_io(&tc->iomem, &slavio_timer_mem_ops, tc,
                               timer_name, size);
-        sysbus_init_mmio_region(dev, &tc->iomem);
+        sysbus_init_mmio(dev, &tc->iomem);
 
         sysbus_init_irq(dev, &s->cputimer[i].irq);
     }
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index fc8c498..9a3eddf 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -748,7 +748,7 @@ static int smc91c111_init1(SysBusDevice *dev)
     smc91c111_state *s = FROM_SYSBUS(smc91c111_state, dev);
     memory_region_init_io(&s->mmio, &smc91c111_mem_ops, s,
                           "smc91c111-mmio", 16);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
     sysbus_init_irq(dev, &s->irq);
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     s->nic = qemu_new_nic(&net_smc91c111_info, &s->conf,
diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c
index 7878820..035d2e2 100644
--- a/hw/sparc32_dma.c
+++ b/hw/sparc32_dma.c
@@ -275,7 +275,7 @@ static int sparc32_dma_init1(SysBusDevice *dev)
 
     reg_size = s->is_ledma ? DMA_ETH_SIZE : DMA_SIZE;
     memory_region_init_io(&s->iomem, &dma_mem_ops, s, "dma", reg_size);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     qdev_init_gpio_in(&dev->qdev, dma_set_irq, 1);
     qdev_init_gpio_out(&dev->qdev, s->gpio, 2);
diff --git a/hw/spitz.c b/hw/spitz.c
index 23f9d41..df0e146 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -167,7 +167,7 @@ static int sl_nand_init(SysBusDevice *dev) {
     s->nand = nand_init(nand ? nand->bdrv : NULL, s->manf_id, s->chip_id);
 
     memory_region_init_io(&s->iomem, &sl_ops, s, "sl", 0x40);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 2ab7ec7..ce62a98 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -309,7 +309,7 @@ static int stellaris_gptm_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &gptm_ops, s,
                           "gptm", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     s->opaque[0] = s->opaque[1] = s;
     s->timer[0] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[0]);
@@ -863,7 +863,7 @@ static int stellaris_i2c_init(SysBusDevice * dev)
 
     memory_region_init_io(&s->iomem, &stellaris_i2c_ops, s,
                           "i2c", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     /* ??? For now we only implement the master interface.  */
     stellaris_i2c_reset(s);
     vmstate_register(&dev->qdev, -1, &vmstate_stellaris_i2c, s);
@@ -1146,7 +1146,7 @@ static int stellaris_adc_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &stellaris_adc_ops, s,
                           "adc", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     stellaris_adc_reset(s);
     qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1);
     vmstate_register(&dev->qdev, -1, &vmstate_stellaris_adc, s);
diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c
index d5613ff..866c9a2 100644
--- a/hw/stellaris_enet.c
+++ b/hw/stellaris_enet.c
@@ -406,7 +406,7 @@ static int stellaris_enet_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->mmio, &stellaris_enet_ops, s, "stellaris_enet",
                           0x1000);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
     sysbus_init_irq(dev, &s->irq);
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
 
diff --git a/hw/strongarm.c b/hw/strongarm.c
index a3d9080..7c75bb9 100644
--- a/hw/strongarm.c
+++ b/hw/strongarm.c
@@ -170,7 +170,7 @@ static int strongarm_pic_initfn(SysBusDevice *dev)
 
     qdev_init_gpio_in(&dev->qdev, strongarm_pic_set_irq, SA_PIC_SRCS);
     memory_region_init_io(&s->iomem, &strongarm_pic_ops, s, "pic", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     sysbus_init_irq(dev, &s->fiq);
 
@@ -371,7 +371,7 @@ static int strongarm_rtc_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->rtc_hz_irq);
 
     memory_region_init_io(&s->iomem, &strongarm_rtc_ops, s, "rtc", 0x10000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
@@ -617,7 +617,7 @@ static int strongarm_gpio_initfn(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &strongarm_gpio_ops, s, "gpio", 0x1000);
 
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     for (i = 0; i < 11; i++) {
         sysbus_init_irq(dev, &s->irqs[i]);
     }
@@ -779,7 +779,7 @@ static int strongarm_ppc_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &strongarm_ppc_ops, s, "ppc", 0x1000);
 
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
@@ -1165,7 +1165,7 @@ static int strongarm_uart_init(SysBusDevice *dev)
     StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev);
 
     memory_region_init_io(&s->iomem, &strongarm_uart_ops, s, "uart", 0x10000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
     s->rx_timeout_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_rx_to, s);
@@ -1446,7 +1446,7 @@ static int strongarm_ssp_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
 
     memory_region_init_io(&s->iomem, &strongarm_ssp_ops, s, "ssp", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     s->bus = ssi_create_bus(&dev->qdev, "ssi");
     return 0;
diff --git a/hw/sun4c_intctl.c b/hw/sun4c_intctl.c
index f4dbf5d..e15b167 100644
--- a/hw/sun4c_intctl.c
+++ b/hw/sun4c_intctl.c
@@ -196,7 +196,7 @@ static int sun4c_intctl_init1(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &sun4c_intctl_mem_ops, s,
                           "intctl", INTCTL_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     qdev_init_gpio_in(&dev->qdev, sun4c_set_irq, 8);
 
     for (i = 0; i < MAX_PILS; i++) {
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 314edc4..3f172ad 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -604,7 +604,7 @@ static int idreg_init1(SysBusDevice *dev)
 
     memory_region_init_ram(&s->mem, NULL, "sun4m.idreg", sizeof(idreg_data));
     memory_region_set_readonly(&s->mem, true);
-    sysbus_init_mmio_region(dev, &s->mem);
+    sysbus_init_mmio(dev, &s->mem);
     return 0;
 }
 
@@ -644,7 +644,7 @@ static int afx_init1(SysBusDevice *dev)
     AFXState *s = FROM_SYSBUS(AFXState, dev);
 
     memory_region_init_ram(&s->mem, NULL, "sun4m.afx", 4);
-    sysbus_init_mmio_region(dev, &s->mem);
+    sysbus_init_mmio(dev, &s->mem);
     return 0;
 }
 
@@ -713,7 +713,7 @@ static int prom_init1(SysBusDevice *dev)
 
     memory_region_init_ram(&s->prom, NULL, "sun4m.prom", PROM_SIZE_MAX);
     memory_region_set_readonly(&s->prom, true);
-    sysbus_init_mmio_region(dev, &s->prom);
+    sysbus_init_mmio(dev, &s->prom);
     return 0;
 }
 
@@ -746,7 +746,7 @@ static int ram_init1(SysBusDevice *dev)
     RamDevice *d = FROM_SYSBUS(RamDevice, dev);
 
     memory_region_init_ram(&d->ram, NULL, "sun4m.ram", d->size);
-    sysbus_init_mmio_region(dev, &d->ram);
+    sysbus_init_mmio(dev, &d->ram);
     return 0;
 }
 
diff --git a/hw/sun4m_iommu.c b/hw/sun4m_iommu.c
index 8ba7e75..ef7627c 100644
--- a/hw/sun4m_iommu.c
+++ b/hw/sun4m_iommu.c
@@ -352,7 +352,7 @@ static int iommu_init1(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &iommu_mem_ops, s, "iommu",
                           IOMMU_NREGS * sizeof(uint32_t));
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
diff --git a/hw/sun4u.c b/hw/sun4u.c
index eaaefe3..97600a9 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -626,7 +626,7 @@ static int prom_init1(SysBusDevice *dev)
 
     memory_region_init_ram(&s->prom, NULL, "sun4u.prom", PROM_SIZE_MAX);
     memory_region_set_readonly(&s->prom, true);
-    sysbus_init_mmio_region(dev, &s->prom);
+    sysbus_init_mmio(dev, &s->prom);
     return 0;
 }
 
@@ -660,7 +660,7 @@ static int ram_init1(SysBusDevice *dev)
     RamDevice *d = FROM_SYSBUS(RamDevice, dev);
 
     memory_region_init_ram(&d->ram, NULL, "sun4u.ram", d->size);
-    sysbus_init_mmio_region(dev, &d->ram);
+    sysbus_init_mmio(dev, &d->ram);
     return 0;
 }
 
diff --git a/hw/syborg_fb.c b/hw/syborg_fb.c
index 3b71c72..b87d7e6 100644
--- a/hw/syborg_fb.c
+++ b/hw/syborg_fb.c
@@ -515,7 +515,7 @@ static int syborg_fb_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
     memory_region_init_io(&s->iomem, &syborg_fb_ops, s,
                           "framebuffer", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     s->ds = graphic_console_init(syborg_fb_update_display,
                                  syborg_fb_invalidate_display,
diff --git a/hw/syborg_interrupt.c b/hw/syborg_interrupt.c
index 512910a..93e81c8 100644
--- a/hw/syborg_interrupt.c
+++ b/hw/syborg_interrupt.c
@@ -207,7 +207,7 @@ static int syborg_int_init(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, syborg_int_set_irq, s->num_irqs);
     memory_region_init_io(&s->iomem, &syborg_int_ops, s,
                           "interrupt", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     s->flags = g_malloc0(s->num_irqs * sizeof(syborg_int_flags));
 
     register_savevm(&dev->qdev, "syborg_int", -1, 1, syborg_int_save,
diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c
index 03d2183..942a7dc 100644
--- a/hw/syborg_keyboard.c
+++ b/hw/syborg_keyboard.c
@@ -184,7 +184,7 @@ static int syborg_keyboard_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
     memory_region_init_io(&s->iomem, &syborg_keyboard_ops, s,
                               "keyboard", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     if (s->fifo_size <= 0) {
         fprintf(stderr, "syborg_keyboard: fifo too small\n");
         s->fifo_size = 16;
diff --git a/hw/syborg_pointer.c b/hw/syborg_pointer.c
index a0f8b32..bb75fa4 100644
--- a/hw/syborg_pointer.c
+++ b/hw/syborg_pointer.c
@@ -186,7 +186,7 @@ static int syborg_pointer_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
     memory_region_init_io(&s->iomem, &syborg_pointer_ops, s,
                           "pointer", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     if (s->fifo_size <= 0) {
         fprintf(stderr, "syborg_pointer: fifo too small\n");
diff --git a/hw/syborg_rtc.c b/hw/syborg_rtc.c
index 375664f..b5f3479 100644
--- a/hw/syborg_rtc.c
+++ b/hw/syborg_rtc.c
@@ -117,7 +117,7 @@ static int syborg_rtc_init(SysBusDevice *dev)
     struct tm tm;
 
     memory_region_init_io(&s->iomem, &syborg_rtc_ops, s, "rtc", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     qemu_get_timedate(&tm, 0);
     s->offset = (uint64_t)mktime(&tm) * 1000000000;
diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
index b73a009..6f339fa 100644
--- a/hw/syborg_serial.c
+++ b/hw/syborg_serial.c
@@ -295,7 +295,7 @@ static int syborg_serial_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
     memory_region_init_io(&s->iomem, &syborg_serial_ops, s,
                           "serial", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     s->chr = qdev_init_chardev(&dev->qdev);
     if (s->chr) {
         qemu_chr_add_handlers(s->chr, syborg_serial_can_receive,
diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c
index dfee457..1498f01 100644
--- a/hw/syborg_timer.c
+++ b/hw/syborg_timer.c
@@ -197,7 +197,7 @@ static int syborg_timer_init(SysBusDevice *dev)
     }
     sysbus_init_irq(dev, &s->irq);
     memory_region_init_io(&s->iomem, &syborg_timer_ops, s, "timer", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     bh = qemu_bh_new(syborg_timer_tick, s);
     s->timer = ptimer_init(bh);
diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
index af0c370..3bb10b5 100644
--- a/hw/syborg_virtio.c
+++ b/hw/syborg_virtio.c
@@ -262,7 +262,7 @@ static int syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)
     sysbus_init_irq(&proxy->busdev, &proxy->irq);
     memory_region_init_io(&proxy->iomem, &syborg_virtio_ops, proxy,
                           "virtio", 0x1000);
-    sysbus_init_mmio_region(&proxy->busdev, &proxy->iomem);
+    sysbus_init_mmio(&proxy->busdev, &proxy->iomem);
 
     proxy->id = ((uint32_t)0x1af4 << 16) | vdev->device_id;
 
diff --git a/hw/sysbus.c b/hw/sysbus.c
index 047a76f..b315a8c 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -101,7 +101,7 @@ void sysbus_init_mmio_cb2(SysBusDevice *dev,
     dev->mmio[n].unmap = unmap;
 }
 
-void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory)
+void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory)
 {
     int n;
 
diff --git a/hw/sysbus.h b/hw/sysbus.h
index e3b4c91..9bac582 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -45,7 +45,7 @@ void sysbus_register_withprop(SysBusDeviceInfo *info);
 void *sysbus_new(void);
 void sysbus_init_mmio_cb2(SysBusDevice *dev,
                           mmio_mapfunc cb, mmio_mapfunc unmap);
-void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory);
+void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory);
 MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n);
 void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p);
 void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target);
diff --git a/hw/tcx.c b/hw/tcx.c
index cd24100..a987357 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -529,21 +529,21 @@ static int tcx_init1(SysBusDevice *dev)
     size = s->vram_size;
     memory_region_init_alias(&s->vram_8bit, "tcx.vram.8bit",
                              &s->vram_mem, vram_offset, size);
-    sysbus_init_mmio_region(dev, &s->vram_8bit);
+    sysbus_init_mmio(dev, &s->vram_8bit);
     vram_offset += size;
     vram_base += size;
 
     /* DAC */
     memory_region_init_io(&s->dac, &tcx_dac_ops, s, "tcx.dac", TCX_DAC_NREGS);
-    sysbus_init_mmio_region(dev, &s->dac);
+    sysbus_init_mmio(dev, &s->dac);
 
     /* TEC (dummy) */
     memory_region_init_io(&s->tec, &dummy_ops, s, "tcx.tec", TCX_TEC_NREGS);
-    sysbus_init_mmio_region(dev, &s->tec);
+    sysbus_init_mmio(dev, &s->tec);
     /* THC: NetBSD writes here even with 8-bit display: dummy */
     memory_region_init_io(&s->thc24, &dummy_ops, s, "tcx.thc24",
                           TCX_THC_NREGS_24);
-    sysbus_init_mmio_region(dev, &s->thc24);
+    sysbus_init_mmio(dev, &s->thc24);
 
     if (s->depth == 24) {
         /* 24-bit plane */
@@ -552,7 +552,7 @@ static int tcx_init1(SysBusDevice *dev)
         s->vram24_offset = vram_offset;
         memory_region_init_alias(&s->vram_24bit, "tcx.vram.24bit",
                                  &s->vram_mem, vram_offset, size);
-        sysbus_init_mmio_region(dev, &s->vram_24bit);
+        sysbus_init_mmio(dev, &s->vram_24bit);
         vram_offset += size;
         vram_base += size;
 
@@ -562,7 +562,7 @@ static int tcx_init1(SysBusDevice *dev)
         s->cplane_offset = vram_offset;
         memory_region_init_alias(&s->vram_cplane, "tcx.vram.cplane",
                                  &s->vram_mem, vram_offset, size);
-        sysbus_init_mmio_region(dev, &s->vram_cplane);
+        sysbus_init_mmio(dev, &s->vram_cplane);
 
         s->ds = graphic_console_init(tcx24_update_display,
                                      tcx24_invalidate_display,
@@ -571,7 +571,7 @@ static int tcx_init1(SysBusDevice *dev)
         /* THC 8 bit (dummy) */
         memory_region_init_io(&s->thc8, &dummy_ops, s, "tcx.thc8",
                               TCX_THC_NREGS_8);
-        sysbus_init_mmio_region(dev, &s->thc8);
+        sysbus_init_mmio(dev, &s->thc8);
 
         s->ds = graphic_console_init(tcx_update_display,
                                      tcx_invalidate_display,
diff --git a/hw/tusb6010.c b/hw/tusb6010.c
index ce7c81f..276300a 100644
--- a/hw/tusb6010.c
+++ b/hw/tusb6010.c
@@ -781,8 +781,8 @@ static int tusb6010_init(SysBusDevice *dev)
     s->pwr_timer = qemu_new_timer_ns(vm_clock, tusb_power_tick, s);
     memory_region_init_io(&s->iomem[1], &tusb_async_ops, s, "tusb-async",
                           UINT32_MAX);
-    sysbus_init_mmio_region(dev, &s->iomem[0]);
-    sysbus_init_mmio_region(dev, &s->iomem[1]);
+    sysbus_init_mmio(dev, &s->iomem[0]);
+    sysbus_init_mmio(dev, &s->iomem[1]);
     sysbus_init_irq(dev, &s->irq);
     qdev_init_gpio_in(&dev->qdev, tusb6010_irq, musb_irq_max + 1);
     s->musb = musb_init(&dev->qdev, 1);
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index 4299052..14d9914 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -144,8 +144,8 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
                           &s->host_state, "pci-conf-idx", 0x1000);
     memory_region_init_io(&s->host_state.data_mem, &unin_data_ops, s,
                           "pci-conf-data", 0x1000);
-    sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio_region(dev, &s->host_state.data_mem);
+    sysbus_init_mmio(dev, &s->host_state.conf_mem);
+    sysbus_init_mmio(dev, &s->host_state.data_mem);
 
     qemu_register_reset(pci_unin_reset, &s->host_state);
     return 0;
@@ -163,8 +163,8 @@ static int pci_u3_agp_init_device(SysBusDevice *dev)
                           &s->host_state, "pci-conf-idx", 0x1000);
     memory_region_init_io(&s->host_state.data_mem, &unin_data_ops, s,
                           "pci-conf-data", 0x1000);
-    sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio_region(dev, &s->host_state.data_mem);
+    sysbus_init_mmio(dev, &s->host_state.conf_mem);
+    sysbus_init_mmio(dev, &s->host_state.data_mem);
 
     qemu_register_reset(pci_unin_reset, &s->host_state);
 
@@ -182,8 +182,8 @@ static int pci_unin_agp_init_device(SysBusDevice *dev)
                           &s->host_state, "pci-conf-idx", 0x1000);
     memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
                           &s->host_state, "pci-conf-data", 0x1000);
-    sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio_region(dev, &s->host_state.data_mem);
+    sysbus_init_mmio(dev, &s->host_state.conf_mem);
+    sysbus_init_mmio(dev, &s->host_state.data_mem);
     return 0;
 }
 
@@ -198,8 +198,8 @@ static int pci_unin_internal_init_device(SysBusDevice *dev)
                           &s->host_state, "pci-conf-idx", 0x1000);
     memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
                           &s->host_state, "pci-conf-data", 0x1000);
-    sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio_region(dev, &s->host_state.data_mem);
+    sysbus_init_mmio(dev, &s->host_state.conf_mem);
+    sysbus_init_mmio(dev, &s->host_state.data_mem);
     return 0;
 }
 
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index c2981c5..e68be70 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1829,7 +1829,7 @@ static int ohci_init_pxa(SysBusDevice *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_region(dev, &s->ohci.mem);
+    sysbus_init_mmio(dev, &s->ohci.mem);
 
     return 0;
 }
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index 8a88696..a285f7f 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -81,13 +81,13 @@ static int pci_vpb_init(SysBusDevice *dev)
      */
     memory_region_init_io(&s->mem_config, &pci_vpb_config_ops, bus,
                           "pci-vpb-selfconfig", 0x1000000);
-    sysbus_init_mmio_region(dev, &s->mem_config);
+    sysbus_init_mmio(dev, &s->mem_config);
     memory_region_init_io(&s->mem_config2, &pci_vpb_config_ops, bus,
                           "pci-vpb-config", 0x1000000);
-    sysbus_init_mmio_region(dev, &s->mem_config2);
+    sysbus_init_mmio(dev, &s->mem_config2);
     if (s->realview) {
         isa_mmio_setup(&s->isa, 0x0100000);
-        sysbus_init_mmio_region(dev, &s->isa);
+        sysbus_init_mmio(dev, &s->isa);
     }
 
     pci_create_simple(bus, -1, "versatile_pci_host");
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index e4aeea4..a6315fc 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -151,7 +151,7 @@ static int vpb_sic_init(SysBusDevice *dev)
     }
     s->irq = 31;
     memory_region_init_io(&s->iomem, &vpb_sic_ops, s, "vpb-sic", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index 2fd360e..596ec0e 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -473,7 +473,7 @@ static int xilinx_axidma_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &axidma_ops, s,
                           "axidma", R_MAX * 4 * 2);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     for (i = 0; i < 2; i++) {
         stream_reset(&s->streams[i]);
diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index a69874b..a2eb3e6 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -852,7 +852,7 @@ static int xilinx_enet_init(SysBusDevice *dev)
     xlx_dma_connect_client(s->dmach, s, axienet_stream_push);
 
     memory_region_init_io(&s->iomem, &enet_ops, s, "enet", 0x40000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     s->nic = qemu_new_nic(&net_xilinx_enet_info, &s->conf,
diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c
index 6f44c84..6777254 100644
--- a/hw/xilinx_ethlite.c
+++ b/hw/xilinx_ethlite.c
@@ -217,7 +217,7 @@ static int xilinx_ethlite_init(SysBusDevice *dev)
     s->rxbuf = 0;
 
     memory_region_init_io(&s->mmio, &eth_ops, s, "xilinx-ethlite", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf,
diff --git a/hw/xilinx_intc.c b/hw/xilinx_intc.c
index 58b73d9..c567885 100644
--- a/hw/xilinx_intc.c
+++ b/hw/xilinx_intc.c
@@ -157,7 +157,7 @@ static int xilinx_intc_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &p->parent_irq);
 
     memory_region_init_io(&p->mmio, &pic_ops, p, "xilinx-pic", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &p->mmio);
+    sysbus_init_mmio(dev, &p->mmio);
     return 0;
 }
 
diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c
index 8779c56..0b2f32a 100644
--- a/hw/xilinx_timer.c
+++ b/hw/xilinx_timer.c
@@ -214,7 +214,7 @@ static int xilinx_timer_init(SysBusDevice *dev)
 
     memory_region_init_io(&t->mmio, &timer_ops, t, "xilinx-timer",
                           R_MAX * 4 * t->nr_timers);
-    sysbus_init_mmio_region(dev, &t->mmio);
+    sysbus_init_mmio(dev, &t->mmio);
     return 0;
 }
 
diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
index ceb7b4d..6533df9 100644
--- a/hw/xilinx_uartlite.c
+++ b/hw/xilinx_uartlite.c
@@ -203,7 +203,7 @@ static int xilinx_uartlite_init(SysBusDevice *dev)
 
     uart_update_status(s);
     memory_region_init_io(&s->mmio, &uart_ops, s, "xilinx-uartlite", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
 
     s->chr = qdev_init_chardev(&dev->qdev);
     if (s->chr)
diff --git a/hw/zaurus.c b/hw/zaurus.c
index 3c27cd8..c4bcd29 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -171,7 +171,7 @@ static int scoop_init(SysBusDevice *dev)
     qdev_init_gpio_in(&s->busdev.qdev, scoop_gpio_set, 16);
     memory_region_init_io(&s->iomem, &scoop_ops, s, "scoop", 0x1000);
 
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
commit 3f7f1c8067157e06fd468f09d050803c11d4ae53
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 27 11:32:34 2011 +0200

    sysbus: remove sysbus_init_mmio()
    
    No longer used - replaced by sysbus_init_mmio_region().
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/sysbus.c b/hw/sysbus.c
index fd2fc6a..047a76f 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -55,9 +55,6 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)
                                         dev->mmio[n].memory);
         } else if (dev->mmio[n].unmap) {
             dev->mmio[n].unmap(dev, dev->mmio[n].addr);
-        } else {
-            cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size,
-                                         IO_MEM_UNASSIGNED);
         }
     }
     dev->mmio[n].addr = addr;
@@ -67,9 +64,6 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)
                                     dev->mmio[n].memory);
     } else if (dev->mmio[n].cb) {
         dev->mmio[n].cb(dev, addr);
-    } else {
-        cpu_register_physical_memory(addr, dev->mmio[n].size,
-                                     dev->mmio[n].iofunc);
     }
 }
 
@@ -95,18 +89,6 @@ void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target)
     }
 }
 
-void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size,
-                      ram_addr_t iofunc)
-{
-    int n;
-
-    assert(dev->num_mmio < QDEV_MAX_MMIO);
-    n = dev->num_mmio++;
-    dev->mmio[n].addr = -1;
-    dev->mmio[n].size = size;
-    dev->mmio[n].iofunc = iofunc;
-}
-
 void sysbus_init_mmio_cb2(SysBusDevice *dev,
                           mmio_mapfunc cb, mmio_mapfunc unmap)
 {
@@ -115,7 +97,6 @@ void sysbus_init_mmio_cb2(SysBusDevice *dev,
     assert(dev->num_mmio < QDEV_MAX_MMIO);
     n = dev->num_mmio++;
     dev->mmio[n].addr = -1;
-    dev->mmio[n].size = 0;
     dev->mmio[n].cb = cb;
     dev->mmio[n].unmap = unmap;
 }
@@ -127,7 +108,6 @@ void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory)
     assert(dev->num_mmio < QDEV_MAX_MMIO);
     n = dev->num_mmio++;
     dev->mmio[n].addr = -1;
-    dev->mmio[n].size = memory_region_size(memory);
     dev->mmio[n].memory = memory;
 }
 
@@ -237,12 +217,17 @@ DeviceState *sysbus_try_create_varargs(const char *name,
 static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
 {
     SysBusDevice *s = sysbus_from_qdev(dev);
+    target_phys_addr_t size;
     int i;
 
     monitor_printf(mon, "%*sirq %d\n", indent, "", s->num_irq);
     for (i = 0; i < s->num_mmio; i++) {
+        size = 0;
+        if (s->mmio[i].memory) {
+            size = memory_region_size(s->mmio[i].memory);
+        }
         monitor_printf(mon, "%*smmio " TARGET_FMT_plx "/" TARGET_FMT_plx "\n",
-                       indent, "", s->mmio[i].addr, s->mmio[i].size);
+                       indent, "", s->mmio[i].addr, size);
     }
 }
 
diff --git a/hw/sysbus.h b/hw/sysbus.h
index 6c36537..e3b4c91 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -21,10 +21,8 @@ struct SysBusDevice {
     int num_mmio;
     struct {
         target_phys_addr_t addr;
-        target_phys_addr_t size;
         mmio_mapfunc cb;
         mmio_mapfunc unmap;
-        ram_addr_t iofunc;
         MemoryRegion *memory;
     } mmio[QDEV_MAX_MMIO];
     int num_pio;
@@ -45,8 +43,6 @@ typedef struct {
 void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init);
 void sysbus_register_withprop(SysBusDeviceInfo *info);
 void *sysbus_new(void);
-void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size,
-                      ram_addr_t iofunc);
 void sysbus_init_mmio_cb2(SysBusDevice *dev,
                           mmio_mapfunc cb, mmio_mapfunc unmap);
 void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory);
commit 9a542a482160182cb56f3014ad929ee9079b1532
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Thu Nov 24 14:31:22 2011 +0100

    bonito: convert cop to memory API
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/bonito.c b/hw/bonito.c
index 7980363..1e52f61 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -203,6 +203,7 @@ typedef struct PCIBonitoState
     /* Bonito registers */
     MemoryRegion iomem;
     MemoryRegion iomem_ldma;
+    MemoryRegion iomem_cop;
 
     target_phys_addr_t bonito_pciio_start;
     target_phys_addr_t bonito_pciio_length;
@@ -212,10 +213,6 @@ typedef struct PCIBonitoState
     target_phys_addr_t bonito_localio_length;
     int bonito_localio_handle;
 
-    target_phys_addr_t bonito_cop_start;
-    target_phys_addr_t bonito_cop_length;
-    int bonito_cop_handle;
-
 } PCIBonitoState;
 
 PCIBonitoState * bonito_state;
@@ -370,7 +367,8 @@ static const MemoryRegionOps bonito_ldma_ops = {
     },
 };
 
-static uint32_t bonito_cop_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t bonito_cop_readl(void *opaque, target_phys_addr_t addr,
+                                 unsigned size)
 {
     uint32_t val;
     PCIBonitoState *s = opaque;
@@ -381,23 +379,21 @@ static uint32_t bonito_cop_readl(void *opaque, target_phys_addr_t addr)
 }
 
 static void bonito_cop_writel(void *opaque, target_phys_addr_t addr,
-                              uint32_t val)
+                              uint64_t val, unsigned size)
 {
     PCIBonitoState *s = opaque;
 
     ((uint32_t *)(&s->boncop))[addr/sizeof(uint32_t)] = val & 0xffffffff;
 }
 
-static CPUWriteMemoryFunc * const bonito_cop_write[] = {
-    NULL,
-    NULL,
-    bonito_cop_writel,
-};
-
-static CPUReadMemoryFunc * const bonito_cop_read[] = {
-    NULL,
-    NULL,
-    bonito_cop_readl,
+static const MemoryRegionOps bonito_cop_ops = {
+    .read = bonito_cop_readl,
+    .write = bonito_cop_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static uint32_t bonito_sbridge_pciaddr(void *opaque, target_phys_addr_t addr)
@@ -708,13 +704,10 @@ static int bonito_initfn(PCIDevice *dev)
     sysbus_init_mmio_region(sysbus, &s->iomem_ldma);
     sysbus_mmio_map(sysbus, 3, 0xbfe00200);
 
-    s->bonito_cop_handle = cpu_register_io_memory(bonito_cop_read,
-                                                  bonito_cop_write, s,
-                                                  DEVICE_NATIVE_ENDIAN);
-    s->bonito_cop_start = 0xbfe00300;
-    s->bonito_cop_length = 0x100;
-    cpu_register_physical_memory(s->bonito_cop_start, s->bonito_cop_length,
-                                 s->bonito_cop_handle);
+    memory_region_init_io(&s->iomem_cop, &bonito_cop_ops, s,
+                          "cop", 0x100);
+    sysbus_init_mmio_region(sysbus, &s->iomem_cop);
+    sysbus_mmio_map(sysbus, 4, 0xbfe00300);
 
     /* Map PCI IO Space  0x1fd0 0000 - 0x1fd1 0000 */
     s->bonito_pciio_start = BONITO_PCIIO_BASE;
commit def344a6eaece5d7799b0a9466cc9f347bde5c5a
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Thu Nov 24 14:31:21 2011 +0100

    bonito: convert ldma to memory API
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/bonito.c b/hw/bonito.c
index ab5c00d..7980363 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -202,6 +202,7 @@ typedef struct PCIBonitoState
 
     /* Bonito registers */
     MemoryRegion iomem;
+    MemoryRegion iomem_ldma;
 
     target_phys_addr_t bonito_pciio_start;
     target_phys_addr_t bonito_pciio_length;
@@ -211,10 +212,6 @@ typedef struct PCIBonitoState
     target_phys_addr_t bonito_localio_length;
     int bonito_localio_handle;
 
-    target_phys_addr_t bonito_ldma_start;
-    target_phys_addr_t bonito_ldma_length;
-    int bonito_ldma_handle;
-
     target_phys_addr_t bonito_cop_start;
     target_phys_addr_t bonito_cop_length;
     int bonito_cop_handle;
@@ -344,7 +341,8 @@ static const MemoryRegionOps bonito_pciconf_ops = {
     },
 };
 
-static uint32_t bonito_ldma_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t bonito_ldma_readl(void *opaque, target_phys_addr_t addr,
+                                  unsigned size)
 {
     uint32_t val;
     PCIBonitoState *s = opaque;
@@ -355,23 +353,21 @@ static uint32_t bonito_ldma_readl(void *opaque, target_phys_addr_t addr)
 }
 
 static void bonito_ldma_writel(void *opaque, target_phys_addr_t addr,
-                               uint32_t val)
+                               uint64_t val, unsigned size)
 {
     PCIBonitoState *s = opaque;
 
     ((uint32_t *)(&s->bonldma))[addr/sizeof(uint32_t)] = val & 0xffffffff;
 }
 
-static CPUWriteMemoryFunc * const bonito_ldma_write[] = {
-    NULL,
-    NULL,
-    bonito_ldma_writel,
-};
-
-static CPUReadMemoryFunc * const bonito_ldma_read[] = {
-    NULL,
-    NULL,
-    bonito_ldma_readl,
+static const MemoryRegionOps bonito_ldma_ops = {
+    .read = bonito_ldma_readl,
+    .write = bonito_ldma_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static uint32_t bonito_cop_readl(void *opaque, target_phys_addr_t addr)
@@ -707,13 +703,10 @@ static int bonito_initfn(PCIDevice *dev)
     sysbus_init_mmio_region(sysbus, &s->pcihost->data_mem);
     sysbus_mmio_map(sysbus, 2, BONITO_SPCICONFIG_BASE);
 
-    s->bonito_ldma_handle = cpu_register_io_memory(bonito_ldma_read,
-                                                   bonito_ldma_write, s,
-                                                   DEVICE_NATIVE_ENDIAN);
-    s->bonito_ldma_start = 0xbfe00200;
-    s->bonito_ldma_length = 0x100;
-    cpu_register_physical_memory(s->bonito_ldma_start, s->bonito_ldma_length,
-                                 s->bonito_ldma_handle);
+    memory_region_init_io(&s->iomem_ldma, &bonito_ldma_ops, s,
+                          "ldma", 0x100);
+    sysbus_init_mmio_region(sysbus, &s->iomem_ldma);
+    sysbus_mmio_map(sysbus, 3, 0xbfe00200);
 
     s->bonito_cop_handle = cpu_register_io_memory(bonito_cop_read,
                                                   bonito_cop_write, s,
commit 845cbeb8e3fd62598414baae98a851af355cd728
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Thu Nov 24 14:31:20 2011 +0100

    bonito: convert south bridge pci config to memory API
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/bonito.c b/hw/bonito.c
index 4972b94..ab5c00d 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -203,10 +203,6 @@ typedef struct PCIBonitoState
     /* Bonito registers */
     MemoryRegion iomem;
 
-    target_phys_addr_t bonito_spciconf_start;
-    target_phys_addr_t bonito_spciconf_length;
-    int bonito_spciconf_handle;
-
     target_phys_addr_t bonito_pciio_start;
     target_phys_addr_t bonito_pciio_length;
     int bonito_pciio_handle;
@@ -596,16 +592,20 @@ static uint32_t bonito_spciconf_readl(void *opaque, target_phys_addr_t addr)
 }
 
 /* south bridge PCI configure space. 0x1fe8 0000 - 0x1fef ffff */
-static CPUWriteMemoryFunc * const bonito_spciconf_write[] = {
-    bonito_spciconf_writeb,
-    bonito_spciconf_writew,
-    bonito_spciconf_writel,
-};
-
-static CPUReadMemoryFunc * const bonito_spciconf_read[] = {
-    bonito_spciconf_readb,
-    bonito_spciconf_readw,
-    bonito_spciconf_readl,
+static const MemoryRegionOps bonito_spciconf_ops = {
+    .old_mmio = {
+        .read = {
+            bonito_spciconf_readb,
+            bonito_spciconf_readw,
+            bonito_spciconf_readl,
+        },
+        .write = {
+            bonito_spciconf_writeb,
+            bonito_spciconf_writew,
+            bonito_spciconf_writel,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 #define BONITO_IRQ_BASE 32
@@ -702,13 +702,10 @@ static int bonito_initfn(PCIDevice *dev)
     sysbus_mmio_map(sysbus, 1, BONITO_PCICONFIG_BASE);
 
     /* set the south bridge pci configure  mapping */
-    s->bonito_spciconf_handle = cpu_register_io_memory(bonito_spciconf_read,
-                                                       bonito_spciconf_write, s,
-                                                       DEVICE_NATIVE_ENDIAN);
-    s->bonito_spciconf_start = BONITO_SPCICONFIG_BASE;
-    s->bonito_spciconf_length = BONITO_SPCICONFIG_SIZE;
-    cpu_register_physical_memory(s->bonito_spciconf_start, s->bonito_spciconf_length,
-                                 s->bonito_spciconf_handle);
+    memory_region_init_io(&s->pcihost->data_mem, &bonito_spciconf_ops, s,
+                          "south-bridge-pci-config", BONITO_SPCICONFIG_SIZE);
+    sysbus_init_mmio_region(sysbus, &s->pcihost->data_mem);
+    sysbus_mmio_map(sysbus, 2, BONITO_SPCICONFIG_BASE);
 
     s->bonito_ldma_handle = cpu_register_io_memory(bonito_ldma_read,
                                                    bonito_ldma_write, s,
commit 183e1d40dbd2284486739ced2cc7c2b5a71b3d9b
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Thu Nov 24 14:31:19 2011 +0100

    bonito: convert north bridge pci config to memory API
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/bonito.c b/hw/bonito.c
index ad4fc63..4972b94 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -203,10 +203,6 @@ typedef struct PCIBonitoState
     /* Bonito registers */
     MemoryRegion iomem;
 
-    target_phys_addr_t bonito_pciconf_start;
-    target_phys_addr_t bonito_pciconf_length;
-    int bonito_pciconf_handle;
-
     target_phys_addr_t bonito_spciconf_start;
     target_phys_addr_t bonito_spciconf_length;
     int bonito_spciconf_handle;
@@ -322,7 +318,7 @@ static const MemoryRegionOps bonito_ops = {
 };
 
 static void bonito_pciconf_writel(void *opaque, target_phys_addr_t addr,
-                                  uint32_t val)
+                                  uint64_t val, unsigned size)
 {
     PCIBonitoState *s = opaque;
 
@@ -330,7 +326,8 @@ static void bonito_pciconf_writel(void *opaque, target_phys_addr_t addr,
     s->dev.config_write(&s->dev, addr, val, 4);
 }
 
-static uint32_t bonito_pciconf_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t bonito_pciconf_readl(void *opaque, target_phys_addr_t addr,
+                                     unsigned size)
 {
 
     PCIBonitoState *s = opaque;
@@ -340,16 +337,15 @@ static uint32_t bonito_pciconf_readl(void *opaque, target_phys_addr_t addr)
 }
 
 /* north bridge PCI configure space. 0x1fe0 0000 - 0x1fe0 00ff */
-static CPUWriteMemoryFunc * const bonito_pciconf_write[] = {
-    NULL,
-    NULL,
-    bonito_pciconf_writel,
-};
 
-static CPUReadMemoryFunc * const bonito_pciconf_read[] = {
-    NULL,
-    NULL,
-    bonito_pciconf_readl,
+static const MemoryRegionOps bonito_pciconf_ops = {
+    .read = bonito_pciconf_readl,
+    .write = bonito_pciconf_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static uint32_t bonito_ldma_readl(void *opaque, target_phys_addr_t addr)
@@ -700,13 +696,10 @@ static int bonito_initfn(PCIDevice *dev)
     sysbus_mmio_map(sysbus, 0, BONITO_INTERNAL_REG_BASE);
 
     /* set the north bridge pci configure  mapping */
-    s->bonito_pciconf_handle = cpu_register_io_memory(bonito_pciconf_read,
-                                                      bonito_pciconf_write, s,
-                                                      DEVICE_NATIVE_ENDIAN);
-    s->bonito_pciconf_start = BONITO_PCICONFIG_BASE;
-    s->bonito_pciconf_length = BONITO_PCICONFIG_SIZE;
-    cpu_register_physical_memory(s->bonito_pciconf_start, s->bonito_pciconf_length,
-                                 s->bonito_pciconf_handle);
+    memory_region_init_io(&s->pcihost->conf_mem, &bonito_pciconf_ops, s,
+                          "north-bridge-pci-config", BONITO_PCICONFIG_SIZE);
+    sysbus_init_mmio_region(sysbus, &s->pcihost->conf_mem);
+    sysbus_mmio_map(sysbus, 1, BONITO_PCICONFIG_BASE);
 
     /* set the south bridge pci configure  mapping */
     s->bonito_spciconf_handle = cpu_register_io_memory(bonito_spciconf_read,
commit 89200979aa8d5e718d88472706b629042fea3170
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Thu Nov 24 14:31:18 2011 +0100

    bonito: convert north bridge register mapping to memory API
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/bonito.c b/hw/bonito.c
index fdb8198..ad4fc63 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -201,9 +201,7 @@ typedef struct PCIBonitoState
     } boncop;
 
     /* Bonito registers */
-    target_phys_addr_t bonito_reg_start;
-    target_phys_addr_t bonito_reg_length;
-    int bonito_reg_handle;
+    MemoryRegion iomem;
 
     target_phys_addr_t bonito_pciconf_start;
     target_phys_addr_t bonito_pciconf_length;
@@ -233,7 +231,8 @@ typedef struct PCIBonitoState
 
 PCIBonitoState * bonito_state;
 
-static void bonito_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void bonito_writel(void *opaque, target_phys_addr_t addr,
+                          uint64_t val, unsigned size)
 {
     PCIBonitoState *s = opaque;
     uint32_t saddr;
@@ -295,7 +294,8 @@ static void bonito_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
-static uint32_t bonito_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t bonito_readl(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
 {
     PCIBonitoState *s = opaque;
     uint32_t saddr;
@@ -311,16 +311,14 @@ static uint32_t bonito_readl(void *opaque, target_phys_addr_t addr)
     }
 }
 
-static CPUWriteMemoryFunc * const bonito_write[] = {
-    NULL,
-    NULL,
-    bonito_writel,
-};
-
-static CPUReadMemoryFunc * const bonito_read[] = {
-    NULL,
-    NULL,
-    bonito_readl,
+static const MemoryRegionOps bonito_ops = {
+    .read = bonito_readl,
+    .write = bonito_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static void bonito_pciconf_writel(void *opaque, target_phys_addr_t addr,
@@ -690,17 +688,16 @@ static int bonito_pcihost_initfn(SysBusDevice *dev)
 static int bonito_initfn(PCIDevice *dev)
 {
     PCIBonitoState *s = DO_UPCAST(PCIBonitoState, dev, dev);
+    SysBusDevice *sysbus = &s->pcihost->busdev;
 
     /* Bonito North Bridge, built on FPGA, VENDOR_ID/DEVICE_ID are "undefined" */
     pci_config_set_prog_interface(dev->config, 0x00);
 
     /* set the north bridge register mapping */
-    s->bonito_reg_handle = cpu_register_io_memory(bonito_read, bonito_write, s,
-                                                  DEVICE_NATIVE_ENDIAN);
-    s->bonito_reg_start = BONITO_INTERNAL_REG_BASE;
-    s->bonito_reg_length = BONITO_INTERNAL_REG_SIZE;
-    cpu_register_physical_memory(s->bonito_reg_start, s->bonito_reg_length,
-                                 s->bonito_reg_handle);
+    memory_region_init_io(&s->iomem, &bonito_ops, s,
+                          "north-bridge-register", BONITO_INTERNAL_REG_SIZE);
+    sysbus_init_mmio_region(sysbus, &s->iomem);
+    sysbus_mmio_map(sysbus, 0, BONITO_INTERNAL_REG_BASE);
 
     /* set the north bridge pci configure  mapping */
     s->bonito_pciconf_handle = cpu_register_io_memory(bonito_pciconf_read,
@@ -780,10 +777,12 @@ PCIBus *bonito_init(qemu_irq *pic)
     pcihost->bus = b;
     qdev_init_nofail(dev);
 
-    d = pci_create_simple(b, PCI_DEVFN(0, 0), "Bonito");
+    /* set the pcihost pointer before bonito_initfn is called */
+    d = pci_create(b, PCI_DEVFN(0, 0), "Bonito");
     s = DO_UPCAST(PCIBonitoState, dev, d);
     s->pcihost = pcihost;
     bonito_state = s;
+    qdev_init_nofail(&d->qdev);
 
     return b;
 }
commit 0aa27efa93b024ffa3c99bd2e0cdfc997a25031a
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Thu Nov 24 14:31:17 2011 +0100

    lm32_sys: convert to memory API
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/lm32_sys.c b/hw/lm32_sys.c
index e5ff962..0c8e971 100644
--- a/hw/lm32_sys.c
+++ b/hw/lm32_sys.c
@@ -47,6 +47,7 @@ enum {
 
 struct LM32SysState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t base;
     uint32_t regs[R_MAX];
     uint8_t testname[MAX_TESTNAME_LEN];
@@ -60,7 +61,8 @@ static void copy_testname(LM32SysState *s)
     s->testname[MAX_TESTNAME_LEN - 1] = '\0';
 }
 
-static void sys_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void sys_write(void *opaque, target_phys_addr_t addr,
+                      uint64_t value, unsigned size)
 {
     LM32SysState *s = opaque;
     char *testname;
@@ -89,16 +91,16 @@ static void sys_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     }
 }
 
-static CPUReadMemoryFunc * const sys_read_fn[] = {
-    NULL,
-    NULL,
-    NULL,
-};
+static bool sys_ops_accepts(void *opaque, target_phys_addr_t addr,
+                            unsigned size, bool is_write)
+{
+    return is_write && size == 4;
+}
 
-static CPUWriteMemoryFunc * const sys_write_fn[] = {
-    NULL,
-    NULL,
-    &sys_write,
+static const MemoryRegionOps sys_ops = {
+    .write = sys_write,
+    .valid.accepts = sys_ops_accepts,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void sys_reset(DeviceState *d)
@@ -115,11 +117,9 @@ static void sys_reset(DeviceState *d)
 static int lm32_sys_init(SysBusDevice *dev)
 {
     LM32SysState *s = FROM_SYSBUS(typeof(*s), dev);
-    int sys_regs;
 
-    sys_regs = cpu_register_io_memory(sys_read_fn, sys_write_fn, s,
-            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, sys_regs);
+    memory_region_init_io(&s->iomem, &sys_ops , s, "sys", R_MAX * 4);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     /* Note: This device is not created in the board initialization,
      * instead it has to be added with the -device parameter. Therefore,
commit 5f2be17af15806e334d892447ca5863fb4922003
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Thu Nov 24 14:31:16 2011 +0100

    lm32_uart: convert to memory API
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c
index 3678545..46a5ae0 100644
--- a/hw/lm32_uart.c
+++ b/hw/lm32_uart.c
@@ -91,6 +91,7 @@ enum {
 
 struct LM32UartState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     CharDriverState *chr;
     qemu_irq irq;
 
@@ -124,7 +125,8 @@ static void uart_update_irq(LM32UartState *s)
     qemu_set_irq(s->irq, irq);
 }
 
-static uint32_t uart_read(void *opaque, target_phys_addr_t addr)
+static uint64_t uart_read(void *opaque, target_phys_addr_t addr,
+                          unsigned size)
 {
     LM32UartState *s = opaque;
     uint32_t r = 0;
@@ -158,7 +160,8 @@ static uint32_t uart_read(void *opaque, target_phys_addr_t addr)
     return r;
 }
 
-static void uart_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void uart_write(void *opaque, target_phys_addr_t addr,
+                       uint64_t value, unsigned size)
 {
     LM32UartState *s = opaque;
     unsigned char ch = value;
@@ -192,16 +195,14 @@ static void uart_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     uart_update_irq(s);
 }
 
-static CPUReadMemoryFunc * const uart_read_fn[] = {
-    NULL,
-    NULL,
-    &uart_read,
-};
-
-static CPUWriteMemoryFunc * const uart_write_fn[] = {
-    NULL,
-    NULL,
-    &uart_write,
+static const MemoryRegionOps uart_ops = {
+    .read = uart_read,
+    .write = uart_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static void uart_rx(void *opaque, const uint8_t *buf, int size)
@@ -245,13 +246,11 @@ static void uart_reset(DeviceState *d)
 static int lm32_uart_init(SysBusDevice *dev)
 {
     LM32UartState *s = FROM_SYSBUS(typeof(*s), dev);
-    int uart_regs;
 
     sysbus_init_irq(dev, &s->irq);
 
-    uart_regs = cpu_register_io_memory(uart_read_fn, uart_write_fn, s,
-            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, uart_regs);
+    memory_region_init_io(&s->iomem, &uart_ops, s, "uart", R_MAX * 4);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     s->chr = qdev_init_chardev(&dev->qdev);
     if (s->chr) {
commit 663d94467a9c2895754dc4bfd7232db08b3373ad
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Thu Nov 24 14:31:15 2011 +0100

    mcf_intc: convert to memory API
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/mcf.h b/hw/mcf.h
index 2f88ff0..baa790b 100644
--- a/hw/mcf.h
+++ b/hw/mcf.h
@@ -15,7 +15,9 @@ void mcf_uart_mm_init(struct MemoryRegion *sysmem,
                       qemu_irq irq, CharDriverState *chr);
 
 /* mcf_intc.c */
-qemu_irq *mcf_intc_init(target_phys_addr_t base, CPUState *env);
+qemu_irq *mcf_intc_init(struct MemoryRegion *sysmem,
+                        target_phys_addr_t base,
+                        CPUState *env);
 
 /* mcf_fec.c */
 void mcf_fec_init(struct MemoryRegion *sysmem, NICInfo *nd,
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index e03d80b..ec608a1 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -221,7 +221,7 @@ static void mcf5208evb_init(ram_addr_t ram_size,
     memory_region_add_subregion(address_space_mem, 0x80000000, sram);
 
     /* Internal peripherals.  */
-    pic = mcf_intc_init(0xfc048000, env);
+    pic = mcf_intc_init(address_space_mem, 0xfc048000, env);
 
     mcf_uart_mm_init(address_space_mem, 0xfc060000, pic[26], serial_hds[0]);
     mcf_uart_mm_init(address_space_mem, 0xfc064000, pic[27], serial_hds[1]);
diff --git a/hw/mcf_intc.c b/hw/mcf_intc.c
index 99092e7..0b498dd 100644
--- a/hw/mcf_intc.c
+++ b/hw/mcf_intc.c
@@ -7,8 +7,10 @@
  */
 #include "hw.h"
 #include "mcf.h"
+#include "exec-memory.h"
 
 typedef struct {
+    MemoryRegion iomem;
     uint64_t ipr;
     uint64_t imr;
     uint64_t ifr;
@@ -41,7 +43,8 @@ static void mcf_intc_update(mcf_intc_state *s)
     m68k_set_irq_level(s->env, best_level, s->active_vector);
 }
 
-static uint32_t mcf_intc_read(void *opaque, target_phys_addr_t addr)
+static uint64_t mcf_intc_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     int offset;
     mcf_intc_state *s = (mcf_intc_state *)opaque;
@@ -73,7 +76,8 @@ static uint32_t mcf_intc_read(void *opaque, target_phys_addr_t addr)
     }
 }
 
-static void mcf_intc_write(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void mcf_intc_write(void *opaque, target_phys_addr_t addr,
+                           uint64_t val, unsigned size)
 {
     int offset;
     mcf_intc_state *s = (mcf_intc_state *)opaque;
@@ -127,31 +131,24 @@ static void mcf_intc_reset(mcf_intc_state *s)
     s->active_vector = 24;
 }
 
-static CPUReadMemoryFunc * const mcf_intc_readfn[] = {
-   mcf_intc_read,
-   mcf_intc_read,
-   mcf_intc_read
+static const MemoryRegionOps mcf_intc_ops = {
+    .read = mcf_intc_read,
+    .write = mcf_intc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const mcf_intc_writefn[] = {
-   mcf_intc_write,
-   mcf_intc_write,
-   mcf_intc_write
-};
-
-qemu_irq *mcf_intc_init(target_phys_addr_t base, CPUState *env)
+qemu_irq *mcf_intc_init(MemoryRegion *sysmem,
+                        target_phys_addr_t base,
+                        CPUState *env)
 {
     mcf_intc_state *s;
-    int iomemtype;
 
     s = g_malloc0(sizeof(mcf_intc_state));
     s->env = env;
     mcf_intc_reset(s);
 
-    iomemtype = cpu_register_io_memory(mcf_intc_readfn,
-                                       mcf_intc_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x100, iomemtype);
+    memory_region_init_io(&s->iomem, &mcf_intc_ops, s, "mcf", 0x100);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     return qemu_allocate_irqs(mcf_intc_set_irq, s, 64);
 }
commit c65fc1dff328f0964bf148efa3603c4992a609fc
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Thu Nov 24 14:31:14 2011 +0100

    mcf_fec: convert to memory API
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/mcf.h b/hw/mcf.h
index e2f6727..2f88ff0 100644
--- a/hw/mcf.h
+++ b/hw/mcf.h
@@ -18,7 +18,8 @@ void mcf_uart_mm_init(struct MemoryRegion *sysmem,
 qemu_irq *mcf_intc_init(target_phys_addr_t base, CPUState *env);
 
 /* mcf_fec.c */
-void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq);
+void mcf_fec_init(struct MemoryRegion *sysmem, NICInfo *nd,
+                  target_phys_addr_t base, qemu_irq *irq);
 
 /* mcf5206.c */
 qemu_irq *mcf5206_init(struct MemoryRegion *sysmem,
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index 0119430..e03d80b 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -234,7 +234,8 @@ static void mcf5208evb_init(ram_addr_t ram_size,
         exit(1);
     }
     if (nd_table[0].vlan)
-        mcf_fec_init(&nd_table[0], 0xfc030000, pic + 36);
+        mcf_fec_init(address_space_mem, &nd_table[0],
+                     0xfc030000, pic + 36);
 
     /*  0xfc000000 SCM.  */
     /*  0xfc004000 XBS.  */
diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c
index 42a5d77..ae37bef 100644
--- a/hw/mcf_fec.c
+++ b/hw/mcf_fec.c
@@ -10,6 +10,7 @@
 #include "mcf.h"
 /* For crc32 */
 #include <zlib.h>
+#include "exec-memory.h"
 
 //#define DEBUG_FEC 1
 
@@ -23,8 +24,9 @@ do { printf("mcf_fec: " fmt , ## __VA_ARGS__); } while (0)
 #define FEC_MAX_FRAME_SIZE 2032
 
 typedef struct {
+    MemoryRegion *sysmem;
+    MemoryRegion iomem;
     qemu_irq *irq;
-    int mmio_index;
     NICState *nic;
     NICConf conf;
     uint32_t irq_state;
@@ -214,7 +216,8 @@ static void mcf_fec_reset(mcf_fec_state *s)
     s->rfsr = 0x500;
 }
 
-static uint32_t mcf_fec_read(void *opaque, target_phys_addr_t addr)
+static uint64_t mcf_fec_read(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
 {
     mcf_fec_state *s = (mcf_fec_state *)opaque;
     switch (addr & 0x3ff) {
@@ -251,7 +254,8 @@ static uint32_t mcf_fec_read(void *opaque, target_phys_addr_t addr)
     }
 }
 
-static void mcf_fec_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void mcf_fec_write(void *opaque, target_phys_addr_t addr,
+                          uint64_t value, unsigned size)
 {
     mcf_fec_state *s = (mcf_fec_state *)opaque;
     switch (addr & 0x3ff) {
@@ -429,23 +433,18 @@ static ssize_t mcf_fec_receive(VLANClientState *nc, const uint8_t *buf, size_t s
     return size;
 }
 
-static CPUReadMemoryFunc * const mcf_fec_readfn[] = {
-   mcf_fec_read,
-   mcf_fec_read,
-   mcf_fec_read
-};
-
-static CPUWriteMemoryFunc * const mcf_fec_writefn[] = {
-   mcf_fec_write,
-   mcf_fec_write,
-   mcf_fec_write
+static const MemoryRegionOps mcf_fec_ops = {
+    .read = mcf_fec_read,
+    .write = mcf_fec_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void mcf_fec_cleanup(VLANClientState *nc)
 {
     mcf_fec_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
-    cpu_unregister_io_memory(s->mmio_index);
+    memory_region_del_subregion(s->sysmem, &s->iomem);
+    memory_region_destroy(&s->iomem);
 
     g_free(s);
 }
@@ -458,18 +457,19 @@ static NetClientInfo net_mcf_fec_info = {
     .cleanup = mcf_fec_cleanup,
 };
 
-void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq)
+void mcf_fec_init(MemoryRegion *sysmem, NICInfo *nd,
+                  target_phys_addr_t base, qemu_irq *irq)
 {
     mcf_fec_state *s;
 
     qemu_check_nic_model(nd, "mcf_fec");
 
     s = (mcf_fec_state *)g_malloc0(sizeof(mcf_fec_state));
+    s->sysmem = sysmem;
     s->irq = irq;
-    s->mmio_index = cpu_register_io_memory(mcf_fec_readfn,
-                                           mcf_fec_writefn, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x400, s->mmio_index);
+
+    memory_region_init_io(&s->iomem, &mcf_fec_ops, s, "fec", 0x400);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     s->conf.macaddr = nd->macaddr;
     s->conf.vlan = nd->vlan;
commit aa6e4986b8f6c435bf4e8aa4328b06d9e84524bb
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Thu Nov 24 14:31:13 2011 +0100

    mcf_uart: convert to memory API
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/mcf.h b/hw/mcf.h
index 572424d..e2f6727 100644
--- a/hw/mcf.h
+++ b/hw/mcf.h
@@ -5,11 +5,14 @@
 struct MemoryRegion;
 
 /* mcf_uart.c */
-uint32_t mcf_uart_read(void *opaque, target_phys_addr_t addr);
-void mcf_uart_write(void *opaque, target_phys_addr_t addr, uint32_t val);
+uint64_t mcf_uart_read(void *opaque, target_phys_addr_t addr,
+                       unsigned size);
+void mcf_uart_write(void *opaque, target_phys_addr_t addr,
+                    uint64_t val, unsigned size);
 void *mcf_uart_init(qemu_irq irq, CharDriverState *chr);
-void mcf_uart_mm_init(target_phys_addr_t base, qemu_irq irq,
-                      CharDriverState *chr);
+void mcf_uart_mm_init(struct MemoryRegion *sysmem,
+                      target_phys_addr_t base,
+                      qemu_irq irq, CharDriverState *chr);
 
 /* mcf_intc.c */
 qemu_irq *mcf_intc_init(target_phys_addr_t base, CPUState *env);
diff --git a/hw/mcf5206.c b/hw/mcf5206.c
index 987687d..7b6d501 100644
--- a/hw/mcf5206.c
+++ b/hw/mcf5206.c
@@ -263,16 +263,17 @@ static void m5206_mbar_reset(m5206_mbar_state *s)
     s->par = 0;
 }
 
-static uint32_t m5206_mbar_read(m5206_mbar_state *s, uint32_t offset)
+static uint64_t m5206_mbar_read(m5206_mbar_state *s,
+                                uint64_t offset, unsigned size)
 {
     if (offset >= 0x100 && offset < 0x120) {
         return m5206_timer_read(s->timer[0], offset - 0x100);
     } else if (offset >= 0x120 && offset < 0x140) {
         return m5206_timer_read(s->timer[1], offset - 0x120);
     } else if (offset >= 0x140 && offset < 0x160) {
-        return mcf_uart_read(s->uart[0], offset - 0x140);
+        return mcf_uart_read(s->uart[0], offset - 0x140, size);
     } else if (offset >= 0x180 && offset < 0x1a0) {
-        return mcf_uart_read(s->uart[1], offset - 0x180);
+        return mcf_uart_read(s->uart[1], offset - 0x180, size);
     }
     switch (offset) {
     case 0x03: return s->scr;
@@ -301,7 +302,7 @@ static uint32_t m5206_mbar_read(m5206_mbar_state *s, uint32_t offset)
 }
 
 static void m5206_mbar_write(m5206_mbar_state *s, uint32_t offset,
-                             uint32_t value)
+                             uint64_t value, unsigned size)
 {
     if (offset >= 0x100 && offset < 0x120) {
         m5206_timer_write(s->timer[0], offset - 0x100, value);
@@ -310,10 +311,10 @@ static void m5206_mbar_write(m5206_mbar_state *s, uint32_t offset,
         m5206_timer_write(s->timer[1], offset - 0x120, value);
         return;
     } else if (offset >= 0x140 && offset < 0x160) {
-        mcf_uart_write(s->uart[0], offset - 0x140, value);
+        mcf_uart_write(s->uart[0], offset - 0x140, value, size);
         return;
     } else if (offset >= 0x180 && offset < 0x1a0) {
-        mcf_uart_write(s->uart[1], offset - 0x180, value);
+        mcf_uart_write(s->uart[1], offset - 0x180, value, size);
         return;
     }
     switch (offset) {
@@ -387,7 +388,7 @@ static uint32_t m5206_mbar_readb(void *opaque, target_phys_addr_t offset)
         }
         return val & 0xff;
     }
-    return m5206_mbar_read(s, offset);
+    return m5206_mbar_read(s, offset, 1);
 }
 
 static uint32_t m5206_mbar_readw(void *opaque, target_phys_addr_t offset)
@@ -411,7 +412,7 @@ static uint32_t m5206_mbar_readw(void *opaque, target_phys_addr_t offset)
         val |= m5206_mbar_readb(opaque, offset + 1);
         return val;
     }
-    return m5206_mbar_read(s, offset);
+    return m5206_mbar_read(s, offset, 2);
 }
 
 static uint32_t m5206_mbar_readl(void *opaque, target_phys_addr_t offset)
@@ -429,7 +430,7 @@ static uint32_t m5206_mbar_readl(void *opaque, target_phys_addr_t offset)
         val |= m5206_mbar_readw(opaque, offset + 2);
         return val;
     }
-    return m5206_mbar_read(s, offset);
+    return m5206_mbar_read(s, offset, 4);
 }
 
 static void m5206_mbar_writew(void *opaque, target_phys_addr_t offset,
@@ -458,7 +459,7 @@ static void m5206_mbar_writeb(void *opaque, target_phys_addr_t offset,
         m5206_mbar_writew(opaque, offset & ~1, tmp);
         return;
     }
-    m5206_mbar_write(s, offset, value);
+    m5206_mbar_write(s, offset, value, 1);
 }
 
 static void m5206_mbar_writew(void *opaque, target_phys_addr_t offset,
@@ -486,7 +487,7 @@ static void m5206_mbar_writew(void *opaque, target_phys_addr_t offset,
         m5206_mbar_writeb(opaque, offset + 1, value & 0xff);
         return;
     }
-    m5206_mbar_write(s, offset, value);
+    m5206_mbar_write(s, offset, value, 2);
 }
 
 static void m5206_mbar_writel(void *opaque, target_phys_addr_t offset,
@@ -504,7 +505,7 @@ static void m5206_mbar_writel(void *opaque, target_phys_addr_t offset,
         m5206_mbar_writew(opaque, offset + 2, value & 0xffff);
         return;
     }
-    m5206_mbar_write(s, offset, value);
+    m5206_mbar_write(s, offset, value, 4);
 }
 
 static const MemoryRegionOps m5206_mbar_ops = {
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index 1c2c0c4..0119430 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -223,9 +223,9 @@ static void mcf5208evb_init(ram_addr_t ram_size,
     /* Internal peripherals.  */
     pic = mcf_intc_init(0xfc048000, env);
 
-    mcf_uart_mm_init(0xfc060000, pic[26], serial_hds[0]);
-    mcf_uart_mm_init(0xfc064000, pic[27], serial_hds[1]);
-    mcf_uart_mm_init(0xfc068000, pic[28], serial_hds[2]);
+    mcf_uart_mm_init(address_space_mem, 0xfc060000, pic[26], serial_hds[0]);
+    mcf_uart_mm_init(address_space_mem, 0xfc064000, pic[27], serial_hds[1]);
+    mcf_uart_mm_init(address_space_mem, 0xfc068000, pic[28], serial_hds[2]);
 
     mcf5208_sys_init(address_space_mem, pic);
 
diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
index e6b2ab0..ec6a87f 100644
--- a/hw/mcf_uart.c
+++ b/hw/mcf_uart.c
@@ -8,8 +8,10 @@
 #include "hw.h"
 #include "mcf.h"
 #include "qemu-char.h"
+#include "exec-memory.h"
 
 typedef struct {
+    MemoryRegion iomem;
     uint8_t mr[2];
     uint8_t sr;
     uint8_t isr;
@@ -64,7 +66,8 @@ static void mcf_uart_update(mcf_uart_state *s)
     qemu_set_irq(s->irq, (s->isr & s->imr) != 0);
 }
 
-uint32_t mcf_uart_read(void *opaque, target_phys_addr_t addr)
+uint64_t mcf_uart_read(void *opaque, target_phys_addr_t addr,
+                       unsigned size)
 {
     mcf_uart_state *s = (mcf_uart_state *)opaque;
     switch (addr & 0x3f) {
@@ -182,7 +185,8 @@ static void mcf_do_command(mcf_uart_state *s, uint8_t cmd)
     }
 }
 
-void mcf_uart_write(void *opaque, target_phys_addr_t addr, uint32_t val)
+void mcf_uart_write(void *opaque, target_phys_addr_t addr,
+                    uint64_t val, unsigned size)
 {
     mcf_uart_state *s = (mcf_uart_state *)opaque;
     switch (addr & 0x3f) {
@@ -283,28 +287,20 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
     return s;
 }
 
-
-static CPUReadMemoryFunc * const mcf_uart_readfn[] = {
-   mcf_uart_read,
-   mcf_uart_read,
-   mcf_uart_read
-};
-
-static CPUWriteMemoryFunc * const mcf_uart_writefn[] = {
-   mcf_uart_write,
-   mcf_uart_write,
-   mcf_uart_write
+static const MemoryRegionOps mcf_uart_ops = {
+    .read = mcf_uart_read,
+    .write = mcf_uart_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-void mcf_uart_mm_init(target_phys_addr_t base, qemu_irq irq,
+void mcf_uart_mm_init(MemoryRegion *sysmem,
+                      target_phys_addr_t base,
+                      qemu_irq irq,
                       CharDriverState *chr)
 {
     mcf_uart_state *s;
-    int iomemtype;
 
     s = mcf_uart_init(irq, chr);
-    iomemtype = cpu_register_io_memory(mcf_uart_readfn,
-                                       mcf_uart_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x40, iomemtype);
+    memory_region_init_io(&s->iomem, &mcf_uart_ops, s, "uart", 0x40);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 }
commit 653fa85c9a626f48c92806e4e28c7ccebc05c43e
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Thu Nov 24 14:31:12 2011 +0100

    mcf5206: convert to memory API
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/an5206.c b/hw/an5206.c
index 3fe1f00..319a40e 100644
--- a/hw/an5206.c
+++ b/hw/an5206.c
@@ -53,7 +53,7 @@ static void an5206_init(ram_addr_t ram_size,
     memory_region_init_ram(sram, NULL, "an5206.sram", 512);
     memory_region_add_subregion(address_space_mem, AN5206_RAMBAR_ADDR, sram);
 
-    mcf5206_init(AN5206_MBAR_ADDR, env);
+    mcf5206_init(address_space_mem, AN5206_MBAR_ADDR, env);
 
     /* Load kernel.  */
     if (!kernel_filename) {
diff --git a/hw/mcf.h b/hw/mcf.h
index 91f2821..572424d 100644
--- a/hw/mcf.h
+++ b/hw/mcf.h
@@ -2,6 +2,8 @@
 #define HW_MCF_H
 /* Motorola ColdFire device prototypes.  */
 
+struct MemoryRegion;
+
 /* mcf_uart.c */
 uint32_t mcf_uart_read(void *opaque, target_phys_addr_t addr);
 void mcf_uart_write(void *opaque, target_phys_addr_t addr, uint32_t val);
@@ -16,6 +18,7 @@ qemu_irq *mcf_intc_init(target_phys_addr_t base, CPUState *env);
 void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq);
 
 /* mcf5206.c */
-qemu_irq *mcf5206_init(uint32_t base, CPUState *env);
+qemu_irq *mcf5206_init(struct MemoryRegion *sysmem,
+                       uint32_t base, CPUState *env);
 
 #endif
diff --git a/hw/mcf5206.c b/hw/mcf5206.c
index 15d6f22..987687d 100644
--- a/hw/mcf5206.c
+++ b/hw/mcf5206.c
@@ -9,6 +9,7 @@
 #include "mcf.h"
 #include "qemu-timer.h"
 #include "sysemu.h"
+#include "exec-memory.h"
 
 /* General purpose timer module.  */
 typedef struct {
@@ -144,6 +145,7 @@ static m5206_timer_state *m5206_timer_init(qemu_irq irq)
 
 typedef struct {
     CPUState *env;
+    MemoryRegion iomem;
     m5206_timer_state *timer[2];
     void *uart[2];
     uint8_t scr;
@@ -505,29 +507,32 @@ static void m5206_mbar_writel(void *opaque, target_phys_addr_t offset,
     m5206_mbar_write(s, offset, value);
 }
 
-static CPUReadMemoryFunc * const m5206_mbar_readfn[] = {
-   m5206_mbar_readb,
-   m5206_mbar_readw,
-   m5206_mbar_readl
+static const MemoryRegionOps m5206_mbar_ops = {
+    .old_mmio = {
+        .read = {
+            m5206_mbar_readb,
+            m5206_mbar_readw,
+            m5206_mbar_readl,
+        },
+        .write = {
+            m5206_mbar_writeb,
+            m5206_mbar_writew,
+            m5206_mbar_writel,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const m5206_mbar_writefn[] = {
-   m5206_mbar_writeb,
-   m5206_mbar_writew,
-   m5206_mbar_writel
-};
-
-qemu_irq *mcf5206_init(uint32_t base, CPUState *env)
+qemu_irq *mcf5206_init(MemoryRegion *sysmem, uint32_t base, CPUState *env)
 {
     m5206_mbar_state *s;
     qemu_irq *pic;
-    int iomemtype;
 
     s = (m5206_mbar_state *)g_malloc0(sizeof(m5206_mbar_state));
-    iomemtype = cpu_register_io_memory(m5206_mbar_readfn,
-                                       m5206_mbar_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x00001000, iomemtype);
+
+    memory_region_init_io(&s->iomem, &m5206_mbar_ops, s,
+                          "mbar", 0x00001000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     pic = qemu_allocate_irqs(m5206_mbar_set_irq, s, 14);
     s->timer[0] = m5206_timer_init(pic[9]);
commit 9244b42dea8208e57868ef5552c3be3f921ebd99
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Nov 24 14:32:34 2011 +0200

    omap_gpio: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap_gpio.c b/hw/omap_gpio.c
index 30630a8..0bfd661 100644
--- a/hw/omap_gpio.c
+++ b/hw/omap_gpio.c
@@ -37,6 +37,7 @@ struct omap_gpio_s {
 
 struct omap_gpif_s {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     int mpu_model;
     void *clk;
     struct omap_gpio_s omap1;
@@ -60,11 +61,16 @@ static void omap_gpio_set(void *opaque, int line, int level)
     }
 }
 
-static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_gpio_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
     int offset = addr & OMAP_MPUI_REG_MASK;
 
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
     switch (offset) {
     case 0x00:	/* DATA_INPUT */
         return s->inputs & s->pins;
@@ -94,13 +100,17 @@ static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
     int offset = addr & OMAP_MPUI_REG_MASK;
     uint16_t diff;
     int ln;
 
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
     switch (offset) {
     case 0x00:	/* DATA_INPUT */
         OMAP_RO_REG(addr);
@@ -156,16 +166,10 @@ static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
 }
 
 /* *Some* sources say the memory region is 32-bit.  */
-static CPUReadMemoryFunc * const omap_gpio_readfn[] = {
-    omap_badwidth_read16,
-    omap_gpio_read,
-    omap_badwidth_read16,
-};
-
-static CPUWriteMemoryFunc * const omap_gpio_writefn[] = {
-    omap_badwidth_write16,
-    omap_gpio_write,
-    omap_badwidth_write16,
+static const MemoryRegionOps omap_gpio_ops = {
+    .read = omap_gpio_read,
+    .write = omap_gpio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void omap_gpio_reset(struct omap_gpio_s *s)
@@ -183,6 +187,7 @@ struct omap2_gpio_s {
     qemu_irq irq[2];
     qemu_irq wkup;
     qemu_irq *handler;
+    MemoryRegion iomem;
 
     uint8_t revision;
     uint8_t config[2];
@@ -200,6 +205,7 @@ struct omap2_gpio_s {
 
 struct omap2_gpif_s {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     int mpu_model;
     void *iclk;
     void *fclk[6];
@@ -563,16 +569,20 @@ static void omap2_gpio_module_writep(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap2_gpio_module_readfn[] = {
-    omap2_gpio_module_readp,
-    omap2_gpio_module_readp,
-    omap2_gpio_module_read,
-};
-
-static CPUWriteMemoryFunc * const omap2_gpio_module_writefn[] = {
-    omap2_gpio_module_writep,
-    omap2_gpio_module_writep,
-    omap2_gpio_module_write,
+static const MemoryRegionOps omap2_gpio_module_ops = {
+    .old_mmio = {
+        .read = {
+            omap2_gpio_module_readp,
+            omap2_gpio_module_readp,
+            omap2_gpio_module_read,
+        },
+        .write = {
+            omap2_gpio_module_writep,
+            omap2_gpio_module_writep,
+            omap2_gpio_module_write,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void omap_gpif_reset(DeviceState *dev)
@@ -594,7 +604,8 @@ static void omap2_gpif_reset(DeviceState *dev)
     s->gpo = 0;
 }
 
-static uint32_t omap2_gpif_top_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap2_gpif_top_read(void *opaque, target_phys_addr_t addr,
+                                    unsigned size)
 {
     struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
 
@@ -623,7 +634,7 @@ static uint32_t omap2_gpif_top_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap2_gpif_top_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                                 uint64_t value, unsigned size)
 {
     struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
 
@@ -651,16 +662,10 @@ static void omap2_gpif_top_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap2_gpif_top_readfn[] = {
-    omap2_gpif_top_read,
-    omap2_gpif_top_read,
-    omap2_gpif_top_read,
-};
-
-static CPUWriteMemoryFunc * const omap2_gpif_top_writefn[] = {
-    omap2_gpif_top_write,
-    omap2_gpif_top_write,
-    omap2_gpif_top_write,
+static const MemoryRegionOps omap2_gpif_top_ops = {
+    .read = omap2_gpif_top_read,
+    .write = omap2_gpif_top_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int omap_gpio_init(SysBusDevice *dev)
@@ -672,11 +677,9 @@ static int omap_gpio_init(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, omap_gpio_set, 16);
     qdev_init_gpio_out(&dev->qdev, s->omap1.handler, 16);
     sysbus_init_irq(dev, &s->omap1.irq);
-    sysbus_init_mmio(dev, 0x1000,
-                    cpu_register_io_memory(omap_gpio_readfn,
-                                    omap_gpio_writefn,
-                                    &s->omap1,
-                                    DEVICE_NATIVE_ENDIAN));
+    memory_region_init_io(&s->iomem, &omap_gpio_ops, &s->omap1,
+                          "omap.gpio", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     return 0;
 }
 
@@ -689,10 +692,9 @@ static int omap2_gpio_init(SysBusDevice *dev)
     }
     if (s->mpu_model < omap3430) {
         s->modulecount = (s->mpu_model < omap2430) ? 4 : 5;
-        sysbus_init_mmio(dev, 0x1000,
-                        cpu_register_io_memory(omap2_gpif_top_readfn,
-                                        omap2_gpif_top_writefn, s,
-                                        DEVICE_NATIVE_ENDIAN));
+        memory_region_init_io(&s->iomem, &omap2_gpif_top_ops, s,
+                              "omap2.gpio", 0x1000);
+        sysbus_init_mmio_region(dev, &s->iomem);
     } else {
         s->modulecount = 6;
     }
@@ -710,10 +712,9 @@ static int omap2_gpio_init(SysBusDevice *dev)
         sysbus_init_irq(dev, &m->irq[0]); /* mpu irq */
         sysbus_init_irq(dev, &m->irq[1]); /* dsp irq */
         sysbus_init_irq(dev, &m->wkup);
-        sysbus_init_mmio(dev, 0x1000,
-                        cpu_register_io_memory(omap2_gpio_module_readfn,
-                                        omap2_gpio_module_writefn,
-                                        m, DEVICE_NATIVE_ENDIAN));
+        memory_region_init_io(&m->iomem, &omap2_gpio_module_ops, m,
+                              "omap.gpio-module", 0x1000);
+        sysbus_init_mmio_region(dev, &m->iomem);
     }
     return 0;
 }
commit 7405165e26606299682ec1a2a40024cc3d55bbff
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Nov 24 14:32:34 2011 +0200

    omap_dma: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap.h b/hw/omap.h
index d40ef95..759e90f 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -435,9 +435,11 @@ enum omap_dma_model {
 
 struct soc_dma_s;
 struct soc_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
+                MemoryRegion *sysmem,
                 qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk,
                 enum omap_dma_model model);
 struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
+                MemoryRegion *sysmem,
                 struct omap_mpu_state_s *mpu, int fifo,
                 int chans, omap_clk iclk, omap_clk fclk);
 void omap_dma_reset(struct soc_dma_s *s);
diff --git a/hw/omap1.c b/hw/omap1.c
index 7d84a0e..79b5178 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -3849,7 +3849,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
         dma_irqs[i] = qdev_get_gpio_in(s->ih[omap1_dma_irq_map[i].ih],
                                        omap1_dma_irq_map[i].intr);
     }
-    s->dma = omap_dma_init(0xfffed800, dma_irqs,
+    s->dma = omap_dma_init(0xfffed800, dma_irqs, system_memory,
                            qdev_get_gpio_in(s->ih[0], OMAP_INT_DMA_LCD),
                            s, omap_findclk(s, "dma_ck"), omap_dma_3_1);
 
diff --git a/hw/omap2.c b/hw/omap2.c
index 1da8e8b..3a7b210 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -2285,7 +2285,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
         dma_irqs[i] = qdev_get_gpio_in(s->ih[omap2_dma_irq_map[i].ih],
                                        omap2_dma_irq_map[i].intr);
     }
-    s->dma = omap_dma4_init(0x48056000, dma_irqs, s, 256, 32,
+    s->dma = omap_dma4_init(0x48056000, dma_irqs, sysmem, s, 256, 32,
                     omap_findclk(s, "sdma_iclk"),
                     omap_findclk(s, "sdma_fclk"));
     s->port->addr_valid = omap2_validate_addr;
diff --git a/hw/omap_dma.c b/hw/omap_dma.c
index f943d4e..389cb78 100644
--- a/hw/omap_dma.c
+++ b/hw/omap_dma.c
@@ -102,6 +102,7 @@ struct omap_dma_channel_s {
 
 struct omap_dma_s {
     struct soc_dma_s *dma;
+    MemoryRegion iomem;
 
     struct omap_mpu_state_s *mpu;
     omap_clk clk;
@@ -1445,12 +1446,17 @@ static int omap_dma_sys_read(struct omap_dma_s *s, int offset,
     return 0;
 }
 
-static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_dma_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     struct omap_dma_s *s = (struct omap_dma_s *) opaque;
     int reg, ch;
     uint16_t ret;
 
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
     switch (addr) {
     case 0x300 ... 0x3fe:
         if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
@@ -1489,11 +1495,15 @@ static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_dma_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                           uint64_t value, unsigned size)
 {
     struct omap_dma_s *s = (struct omap_dma_s *) opaque;
     int reg, ch;
 
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x300 ... 0x3fe:
         if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
@@ -1530,16 +1540,10 @@ static void omap_dma_write(void *opaque, target_phys_addr_t addr,
     OMAP_BAD_REG(addr);
 }
 
-static CPUReadMemoryFunc * const omap_dma_readfn[] = {
-    omap_badwidth_read16,
-    omap_dma_read,
-    omap_badwidth_read16,
-};
-
-static CPUWriteMemoryFunc * const omap_dma_writefn[] = {
-    omap_badwidth_write16,
-    omap_dma_write,
-    omap_badwidth_write16,
+static const MemoryRegionOps omap_dma_ops = {
+    .read = omap_dma_read,
+    .write = omap_dma_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void omap_dma_request(void *opaque, int drq, int req)
@@ -1615,10 +1619,11 @@ static void omap_dma_setcaps(struct omap_dma_s *s)
 }
 
 struct soc_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
+                MemoryRegion *sysmem,
                 qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk,
                 enum omap_dma_model model)
 {
-    int iomemtype, num_irqs, memsize, i;
+    int num_irqs, memsize, i;
     struct omap_dma_s *s = (struct omap_dma_s *)
             g_malloc0(sizeof(struct omap_dma_s));
 
@@ -1658,9 +1663,8 @@ struct soc_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
     omap_dma_reset(s->dma);
     omap_dma_clk_update(s, 0, 1);
 
-    iomemtype = cpu_register_io_memory(omap_dma_readfn,
-                    omap_dma_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, memsize, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_dma_ops, s, "omap.dma", memsize);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     mpu->drq = s->dma->drq;
 
@@ -1688,12 +1692,17 @@ static void omap_dma_interrupts_4_update(struct omap_dma_s *s)
         qemu_irq_raise(s->irq[3]);
 }
 
-static uint32_t omap_dma4_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_dma4_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_dma_s *s = (struct omap_dma_s *) opaque;
     int irqn = 0, chnum;
     struct omap_dma_channel_s *ch;
 
+    if (size == 1) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
     switch (addr) {
     case 0x00:	/* DMA4_REVISION */
         return 0x40;
@@ -1834,12 +1843,16 @@ static uint32_t omap_dma4_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_dma4_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_dma_s *s = (struct omap_dma_s *) opaque;
     int chnum, irqn = 0;
     struct omap_dma_channel_s *ch;
 
+    if (size == 1) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x14:	/* DMA4_IRQSTATUS_L3 */
         irqn ++;
@@ -2021,23 +2034,18 @@ static void omap_dma4_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_dma4_readfn[] = {
-    omap_badwidth_read16,
-    omap_dma4_read,
-    omap_dma4_read,
-};
-
-static CPUWriteMemoryFunc * const omap_dma4_writefn[] = {
-    omap_badwidth_write16,
-    omap_dma4_write,
-    omap_dma4_write,
+static const MemoryRegionOps omap_dma4_ops = {
+    .read = omap_dma4_read,
+    .write = omap_dma4_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
+                MemoryRegion *sysmem,
                 struct omap_mpu_state_s *mpu, int fifo,
                 int chans, omap_clk iclk, omap_clk fclk)
 {
-    int iomemtype, i;
+    int i;
     struct omap_dma_s *s = (struct omap_dma_s *)
             g_malloc0(sizeof(struct omap_dma_s));
 
@@ -2065,9 +2073,8 @@ struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
     omap_dma_reset(s->dma);
     omap_dma_clk_update(s, 0, !!s->dma->freq);
 
-    iomemtype = cpu_register_io_memory(omap_dma4_readfn,
-                    omap_dma4_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_dma4_ops, s, "omap.dma4", 0x1000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     mpu->drq = s->dma->drq;
 
commit 6a0148e7b57515d94d158e84175da3a29de1f850
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Nov 24 14:32:34 2011 +0200

    omap_sdrc: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap.h b/hw/omap.h
index 1da6787..d40ef95 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -104,7 +104,8 @@ target_phys_addr_t omap_l4_region_size(struct omap_target_agent_s *ta,
 
 /* OMAP2 SDRAM controller */
 struct omap_sdrc_s;
-struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base);
+struct omap_sdrc_s *omap_sdrc_init(MemoryRegion *sysmem,
+                                   target_phys_addr_t base);
 void omap_sdrc_reset(struct omap_sdrc_s *s);
 
 /* OMAP2 general purpose memory controller */
diff --git a/hw/omap2.c b/hw/omap2.c
index 5fc3fcf..1da8e8b 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -2422,7 +2422,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
     sysbus_mmio_map(busdev, 3, omap_l4_region_base(ta, 4));
     sysbus_mmio_map(busdev, 4, omap_l4_region_base(ta, 5));
 
-    s->sdrc = omap_sdrc_init(0x68009000);
+    s->sdrc = omap_sdrc_init(sysmem, 0x68009000);
     s->gpmc = omap_gpmc_init(s, 0x6800a000,
                              qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPMC_IRQ),
                              s->drq[OMAP24XX_DMA_GPMC]);
diff --git a/hw/omap_sdrc.c b/hw/omap_sdrc.c
index 1df2fd8..784e326 100644
--- a/hw/omap_sdrc.c
+++ b/hw/omap_sdrc.c
@@ -22,6 +22,7 @@
 
 /* SDRAM Controller Subsystem */
 struct omap_sdrc_s {
+    MemoryRegion iomem;
     uint8_t config;
 };
 
@@ -30,10 +31,15 @@ void omap_sdrc_reset(struct omap_sdrc_s *s)
     s->config = 0x10;
 }
 
-static uint32_t omap_sdrc_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_sdrc_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x00:	/* SDRC_REVISION */
         return 0x20;
@@ -81,10 +87,14 @@ static uint32_t omap_sdrc_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_sdrc_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x00:	/* SDRC_REVISION */
     case 0x14:	/* SDRC_SYSSTATUS */
@@ -97,7 +107,7 @@ static void omap_sdrc_write(void *opaque, target_phys_addr_t addr,
     case 0x10:	/* SDRC_SYSCONFIG */
         if ((value >> 3) != 0x2)
             fprintf(stderr, "%s: bad SDRAM idle mode %i\n",
-                            __FUNCTION__, value >> 3);
+                    __FUNCTION__, (unsigned)value >> 3);
         if (value & 2)
             omap_sdrc_reset(s);
         s->config = value & 0x18;
@@ -137,29 +147,22 @@ static void omap_sdrc_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_sdrc_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_sdrc_read,
-};
-
-static CPUWriteMemoryFunc * const omap_sdrc_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_sdrc_write,
+static const MemoryRegionOps omap_sdrc_ops = {
+    .read = omap_sdrc_read,
+    .write = omap_sdrc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base)
+struct omap_sdrc_s *omap_sdrc_init(MemoryRegion *sysmem,
+                                   target_phys_addr_t base)
 {
-    int iomemtype;
     struct omap_sdrc_s *s = (struct omap_sdrc_s *)
             g_malloc0(sizeof(struct omap_sdrc_s));
 
     omap_sdrc_reset(s);
 
-    iomemtype = cpu_register_io_memory(omap_sdrc_readfn,
-                    omap_sdrc_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_sdrc_ops, s, "omap.sdrc", 0x1000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     return s;
 }
commit 9832b74c149b2859c3a4e142ba719a0acc4e2733
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Nov 24 14:32:34 2011 +0200

    omap_gp_timer: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap_gptimer.c b/hw/omap_gptimer.c
index c1cbdf8..414b98a 100644
--- a/hw/omap_gptimer.c
+++ b/hw/omap_gptimer.c
@@ -23,6 +23,7 @@
 
 /* GP timers */
 struct omap_gp_timer_s {
+    MemoryRegion iomem;
     qemu_irq irq;
     qemu_irq wkup;
     qemu_irq in;
@@ -337,12 +338,6 @@ static uint32_t omap_gp_timer_readh(void *opaque, target_phys_addr_t addr)
     }
 }
 
-static CPUReadMemoryFunc * const omap_gp_timer_readfn[] = {
-    omap_badwidth_read32,
-    omap_gp_timer_readh,
-    omap_gp_timer_readw,
-};
-
 static void omap_gp_timer_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
@@ -454,16 +449,25 @@ static void omap_gp_timer_writeh(void *opaque, target_phys_addr_t addr,
         s->writeh = (uint16_t) value;
 }
 
-static CPUWriteMemoryFunc * const omap_gp_timer_writefn[] = {
-    omap_badwidth_write32,
-    omap_gp_timer_writeh,
-    omap_gp_timer_write,
+static const MemoryRegionOps omap_gp_timer_ops = {
+    .old_mmio = {
+        .read = {
+            omap_badwidth_read32,
+            omap_gp_timer_readh,
+            omap_gp_timer_readw,
+        },
+        .write = {
+            omap_badwidth_write32,
+            omap_gp_timer_writeh,
+            omap_gp_timer_write,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
                 qemu_irq irq, omap_clk fclk, omap_clk iclk)
 {
-    int iomemtype;
     struct omap_gp_timer_s *s = (struct omap_gp_timer_s *)
             g_malloc0(sizeof(struct omap_gp_timer_s));
 
@@ -476,9 +480,9 @@ struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
     omap_gp_timer_reset(s);
     omap_gp_timer_clk_setup(s);
 
-    iomemtype = cpu_register_io_memory(omap_gp_timer_readfn,
-                    omap_gp_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
-    omap_l4_attach(ta, 0, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_gp_timer_ops, s, "omap.gptimer",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach_region(ta, 0, &s->iomem);
 
     return s;
 }
commit fcb40162bfa1e0eb80bbe6c7782750e0d5a925ec
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Nov 24 14:32:34 2011 +0200

    omap_synctimer: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap_synctimer.c b/hw/omap_synctimer.c
index ece5388..cd1d754 100644
--- a/hw/omap_synctimer.c
+++ b/hw/omap_synctimer.c
@@ -21,6 +21,7 @@
 #include "qemu-timer.h"
 #include "omap.h"
 struct omap_synctimer_s {
+    MemoryRegion iomem;
     uint32_t val;
     uint16_t readh;
 };
@@ -65,22 +66,26 @@ static uint32_t omap_synctimer_readh(void *opaque, target_phys_addr_t addr)
     }
 }
 
-static CPUReadMemoryFunc * const omap_synctimer_readfn[] = {
-    omap_badwidth_read32,
-    omap_synctimer_readh,
-    omap_synctimer_readw,
-};
-
 static void omap_synctimer_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
     OMAP_BAD_REG(addr);
 }
 
-static CPUWriteMemoryFunc * const omap_synctimer_writefn[] = {
-    omap_badwidth_write32,
-    omap_synctimer_write,
-    omap_synctimer_write,
+static const MemoryRegionOps omap_synctimer_ops = {
+    .old_mmio = {
+        .read = {
+            omap_badwidth_read32,
+            omap_synctimer_readh,
+            omap_synctimer_readw,
+        },
+        .write = {
+            omap_badwidth_write32,
+            omap_synctimer_write,
+            omap_synctimer_write,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta,
@@ -89,9 +94,9 @@ struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta,
     struct omap_synctimer_s *s = g_malloc0(sizeof(*s));
 
     omap_synctimer_reset(s);
-    omap_l4_attach(ta, 0, cpu_register_io_memory(
-                      omap_synctimer_readfn, omap_synctimer_writefn, s,
-                      DEVICE_NATIVE_ENDIAN));
+    memory_region_init_io(&s->iomem, &omap_synctimer_ops, s, "omap.synctimer",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach_region(ta, 0, &s->iomem);
 
     return s;
 }
commit 0a9ee1a7d5616abace48819a84275274e8c15ed0
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Nov 24 11:58:20 2011 +0200

    omap_tap: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap.h b/hw/omap.h
index f2f7383..1da6787 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -827,6 +827,7 @@ struct omap_mpu_state_s {
     MemoryRegion pwl_iomem;
     MemoryRegion pwt_iomem;
     MemoryRegion mpui_io_iomem;
+    MemoryRegion tap_iomem;
     MemoryRegion imif_ram;
     MemoryRegion emiff_ram;
 
diff --git a/hw/omap_tap.c b/hw/omap_tap.c
index e685288..1b4820c 100644
--- a/hw/omap_tap.c
+++ b/hw/omap_tap.c
@@ -22,10 +22,15 @@
 #include "omap.h"
 
 /* TEST-Chip-level TAP */
-static uint32_t omap_tap_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_tap_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x204:	/* IDCODE_reg */
         switch (s->mpu_model) {
@@ -87,27 +92,25 @@ static uint32_t omap_tap_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_tap_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                           uint64_t value, unsigned size)
 {
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     OMAP_BAD_REG(addr);
 }
 
-static CPUReadMemoryFunc * const omap_tap_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_tap_read,
-};
-
-static CPUWriteMemoryFunc * const omap_tap_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_tap_write,
+static const MemoryRegionOps omap_tap_ops = {
+    .read = omap_tap_read,
+    .write = omap_tap_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 void omap_tap_init(struct omap_target_agent_s *ta,
                 struct omap_mpu_state_s *mpu)
 {
-    omap_l4_attach(ta, 0, cpu_register_io_memory(
-                            omap_tap_readfn, omap_tap_writefn, mpu,
-                            DEVICE_NATIVE_ENDIAN));
+    memory_region_init_io(&mpu->tap_iomem, &omap_tap_ops, mpu, "omap.tap",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach_region(ta, 0, &mpu->tap_iomem);
 }
commit c304fed7eb1ed3117bd16e4f0e88edf092c6ccd5
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Nov 24 11:49:29 2011 +0200

    omap_mmc: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap.h b/hw/omap.h
index 367ba11..f2f7383 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -751,6 +751,7 @@ void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip);
 /* omap_mmc.c */
 struct omap_mmc_s;
 struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
+                MemoryRegion *sysmem,
                 BlockDriverState *bd,
                 qemu_irq irq, qemu_irq dma[], omap_clk clk);
 struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
diff --git a/hw/omap1.c b/hw/omap1.c
index 619812c..7d84a0e 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -3938,7 +3938,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
         fprintf(stderr, "qemu: missing SecureDigital device\n");
         exit(1);
     }
-    s->mmc = omap_mmc_init(0xfffb7800, dinfo->bdrv,
+    s->mmc = omap_mmc_init(0xfffb7800, system_memory, dinfo->bdrv,
                            qdev_get_gpio_in(s->ih[1], OMAP_INT_OQN),
                            &s->drq[OMAP_DMA_MMC_TX],
                     omap_findclk(s, "mmc_ck"));
diff --git a/hw/omap_mmc.c b/hw/omap_mmc.c
index b42cf90..ba960c1 100644
--- a/hw/omap_mmc.c
+++ b/hw/omap_mmc.c
@@ -24,6 +24,7 @@ struct omap_mmc_s {
     qemu_irq irq;
     qemu_irq *dma;
     qemu_irq coverswitch;
+    MemoryRegion iomem;
     omap_clk clk;
     SDState *card;
     uint16_t last_cmd;
@@ -305,11 +306,15 @@ void omap_mmc_reset(struct omap_mmc_s *host)
     host->clkdiv = 0;
 }
 
-static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset)
+static uint64_t omap_mmc_read(void *opaque, target_phys_addr_t offset,
+                              unsigned size)
 {
     uint16_t i;
     struct omap_mmc_s *s = (struct omap_mmc_s *) opaque;
-    offset &= OMAP_MPUI_REG_MASK;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, offset);
+    }
 
     switch (offset) {
     case 0x00:	/* MMC_CMD */
@@ -395,11 +400,14 @@ static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void omap_mmc_write(void *opaque, target_phys_addr_t offset,
-                uint32_t value)
+                           uint64_t value, unsigned size)
 {
     int i;
     struct omap_mmc_s *s = (struct omap_mmc_s *) opaque;
-    offset &= OMAP_MPUI_REG_MASK;
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, offset, value);
+    }
 
     switch (offset) {
     case 0x00:	/* MMC_CMD */
@@ -540,16 +548,10 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static CPUReadMemoryFunc * const omap_mmc_readfn[] = {
-    omap_badwidth_read16,
-    omap_mmc_read,
-    omap_badwidth_read16,
-};
-
-static CPUWriteMemoryFunc * const omap_mmc_writefn[] = {
-    omap_badwidth_write16,
-    omap_mmc_write,
-    omap_badwidth_write16,
+static const MemoryRegionOps omap_mmc_ops = {
+    .read = omap_mmc_read,
+    .write = omap_mmc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void omap_mmc_cover_cb(void *opaque, int line, int level)
@@ -571,10 +573,10 @@ static void omap_mmc_cover_cb(void *opaque, int line, int level)
 }
 
 struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
+                MemoryRegion *sysmem,
                 BlockDriverState *bd,
                 qemu_irq irq, qemu_irq dma[], omap_clk clk)
 {
-    int iomemtype;
     struct omap_mmc_s *s = (struct omap_mmc_s *)
             g_malloc0(sizeof(struct omap_mmc_s));
 
@@ -586,9 +588,8 @@ struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
 
     omap_mmc_reset(s);
 
-    iomemtype = cpu_register_io_memory(omap_mmc_readfn,
-                    omap_mmc_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x800, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_mmc_ops, s, "omap.mmc", 0x800);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     /* Instantiate the storage */
     s->card = sd_init(bd, 0);
@@ -600,7 +601,6 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
                 BlockDriverState *bd, qemu_irq irq, qemu_irq dma[],
                 omap_clk fclk, omap_clk iclk)
 {
-    int iomemtype;
     struct omap_mmc_s *s = (struct omap_mmc_s *)
             g_malloc0(sizeof(struct omap_mmc_s));
 
@@ -612,9 +612,9 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
 
     omap_mmc_reset(s);
 
-    iomemtype = cpu_register_io_memory(omap_mmc_readfn,
-                    omap_mmc_writefn, s, DEVICE_NATIVE_ENDIAN);
-    omap_l4_attach(ta, 0, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_mmc_ops, s, "omap.mmc",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach_region(ta, 0, &s->iomem);
 
     /* Instantiate the storage */
     s->card = sd_init(bd, 0);
commit f32261498c83bf434dde74f7832ead98678cb8ae
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Nov 23 15:17:36 2011 +0200

    omap_l4: add memory API variant of omap_l4_attach()
    
    Also add omap_l4_region_size(), since memory API functions need
    the size during initialization.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap.h b/hw/omap.h
index d12f402..367ba11 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -84,7 +84,8 @@ struct omap_target_agent_s {
     uint32_t control;
     uint32_t status;
 };
-struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num);
+struct omap_l4_s *omap_l4_init(MemoryRegion *address_space,
+                               target_phys_addr_t base, int ta_num);
 
 struct omap_target_agent_s;
 struct omap_target_agent_s *omap_l4ta_get(
@@ -94,8 +95,12 @@ struct omap_target_agent_s *omap_l4ta_get(
     int cs);
 target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
                 int iotype);
+target_phys_addr_t omap_l4_attach_region(struct omap_target_agent_s *ta,
+                                         int region, MemoryRegion *mr);
 target_phys_addr_t omap_l4_region_base(struct omap_target_agent_s *ta,
                                        int region);
+target_phys_addr_t omap_l4_region_size(struct omap_target_agent_s *ta,
+                                       int region);
 
 /* OMAP2 SDRAM controller */
 struct omap_sdrc_s;
diff --git a/hw/omap2.c b/hw/omap2.c
index 8a0fa73..5fc3fcf 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -2260,7 +2260,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
                     (sram_base = qemu_ram_alloc(NULL, "omap2.sram",
                                                 s->sram_size)) | IO_MEM_RAM);
 
-    s->l4 = omap_l4_init(OMAP2_L4_BASE, 54);
+    s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54);
 
     /* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */
     cpu_irq = arm_pic_init_cpu(s->env);
diff --git a/hw/omap_l4.c b/hw/omap_l4.c
index a19ea70..a0bed5c 100644
--- a/hw/omap_l4.c
+++ b/hw/omap_l4.c
@@ -21,16 +21,19 @@
 #include "omap.h"
 
 struct omap_l4_s {
+    MemoryRegion *address_space;
     target_phys_addr_t base;
     int ta_num;
     struct omap_target_agent_s ta[0];
 };
 
-struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num)
+struct omap_l4_s *omap_l4_init(MemoryRegion *address_space,
+                               target_phys_addr_t base, int ta_num)
 {
     struct omap_l4_s *bus = g_malloc0(
                     sizeof(*bus) + ta_num * sizeof(*bus->ta));
 
+    bus->address_space = address_space;
     bus->ta_num = ta_num;
     bus->base = base;
 
@@ -43,6 +46,12 @@ target_phys_addr_t omap_l4_region_base(struct omap_target_agent_s *ta,
     return ta->bus->base + ta->start[region].offset;
 }
 
+target_phys_addr_t omap_l4_region_size(struct omap_target_agent_s *ta,
+                                       int region)
+{
+    return ta->start[region].size;
+}
+
 static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr)
 {
     struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
@@ -150,3 +159,21 @@ target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
 
     return base;
 }
+
+target_phys_addr_t omap_l4_attach_region(struct omap_target_agent_s *ta,
+                                         int region, MemoryRegion *mr)
+{
+    target_phys_addr_t base;
+
+    if (region < 0 || region >= ta->regions) {
+        fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region);
+        exit(-1);
+    }
+
+    base = ta->bus->base + ta->start[region].offset;
+    if (mr) {
+        memory_region_add_subregion(ta->bus->address_space, base, mr);
+    }
+
+    return base;
+}
commit a56e423c7c39af0fa1515d575fddfda032a02916
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Nov 23 14:58:10 2011 +0200

    omap: eliminate l4_register_io_memory
    
    This is a trivial wrapper around cpu_register_io_memory(), adding
    no value.  Inline it into all callers.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap.h b/hw/omap.h
index 8bd1810..d12f402 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -96,8 +96,6 @@ target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
                 int iotype);
 target_phys_addr_t omap_l4_region_base(struct omap_target_agent_s *ta,
                                        int region);
-int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
-                CPUWriteMemoryFunc * const *mem_write, void *opaque);
 
 /* OMAP2 SDRAM controller */
 struct omap_sdrc_s;
diff --git a/hw/omap2.c b/hw/omap2.c
index e299884..8a0fa73 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -784,8 +784,8 @@ static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
 
     s->chr = chr ?: qemu_chr_new("null", "null", NULL);
 
-    iomemtype = l4_register_io_memory(omap_sti_readfn,
-                    omap_sti_writefn, s);
+    iomemtype = cpu_register_io_memory(omap_sti_readfn,
+                    omap_sti_writefn, s, DEVICE_NATIVE_ENDIAN);
     omap_l4_attach(ta, 0, iomemtype);
 
     iomemtype = cpu_register_io_memory(omap_sti_fifo_readfn,
@@ -1798,8 +1798,8 @@ static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
     s->mpu = mpu;
     omap_prcm_coldreset(s);
 
-    iomemtype = l4_register_io_memory(omap_prcm_readfn,
-                    omap_prcm_writefn, s);
+    iomemtype = cpu_register_io_memory(omap_prcm_readfn,
+                    omap_prcm_writefn, s, DEVICE_NATIVE_ENDIAN);
     omap_l4_attach(ta, 0, iomemtype);
     omap_l4_attach(ta, 1, iomemtype);
 
@@ -2168,8 +2168,8 @@ static struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
     s->mpu = mpu;
     omap_sysctl_reset(s);
 
-    iomemtype = l4_register_io_memory(omap_sysctl_readfn,
-                    omap_sysctl_writefn, s);
+    iomemtype = cpu_register_io_memory(omap_sysctl_readfn,
+                    omap_sysctl_writefn, s, DEVICE_NATIVE_ENDIAN);
     omap_l4_attach(ta, 0, iomemtype);
 
     return s;
diff --git a/hw/omap_dss.c b/hw/omap_dss.c
index b4a8b4c..b138c23 100644
--- a/hw/omap_dss.c
+++ b/hw/omap_dss.c
@@ -1037,14 +1037,14 @@ struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
     s->drq = drq;
     omap_dss_reset(s);
 
-    iomemtype[0] = l4_register_io_memory(omap_diss1_readfn,
-                    omap_diss1_writefn, s);
-    iomemtype[1] = l4_register_io_memory(omap_disc1_readfn,
-                    omap_disc1_writefn, s);
-    iomemtype[2] = l4_register_io_memory(omap_rfbi1_readfn,
-                    omap_rfbi1_writefn, s);
-    iomemtype[3] = l4_register_io_memory(omap_venc1_readfn,
-                    omap_venc1_writefn, s);
+    iomemtype[0] = cpu_register_io_memory(omap_diss1_readfn,
+                    omap_diss1_writefn, s, DEVICE_NATIVE_ENDIAN);
+    iomemtype[1] = cpu_register_io_memory(omap_disc1_readfn,
+                    omap_disc1_writefn, s, DEVICE_NATIVE_ENDIAN);
+    iomemtype[2] = cpu_register_io_memory(omap_rfbi1_readfn,
+                    omap_rfbi1_writefn, s, DEVICE_NATIVE_ENDIAN);
+    iomemtype[3] = cpu_register_io_memory(omap_venc1_readfn,
+                    omap_venc1_writefn, s, DEVICE_NATIVE_ENDIAN);
     iomemtype[4] = cpu_register_io_memory(omap_im3_readfn,
                     omap_im3_writefn, s, DEVICE_NATIVE_ENDIAN);
     omap_l4_attach(ta, 0, iomemtype[0]);
diff --git a/hw/omap_gptimer.c b/hw/omap_gptimer.c
index 704b000..c1cbdf8 100644
--- a/hw/omap_gptimer.c
+++ b/hw/omap_gptimer.c
@@ -476,8 +476,8 @@ struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
     omap_gp_timer_reset(s);
     omap_gp_timer_clk_setup(s);
 
-    iomemtype = l4_register_io_memory(omap_gp_timer_readfn,
-                    omap_gp_timer_writefn, s);
+    iomemtype = cpu_register_io_memory(omap_gp_timer_readfn,
+                    omap_gp_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
     omap_l4_attach(ta, 0, iomemtype);
 
     return s;
diff --git a/hw/omap_i2c.c b/hw/omap_i2c.c
index 11577b1..52c38ba 100644
--- a/hw/omap_i2c.c
+++ b/hw/omap_i2c.c
@@ -457,8 +457,8 @@ struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
     s->bus = i2c_init_bus(NULL, "i2c");
     omap_i2c_reset(s);
 
-    iomemtype = l4_register_io_memory(omap_i2c_readfn,
-                    omap_i2c_writefn, s);
+    iomemtype = cpu_register_io_memory(omap_i2c_readfn,
+                    omap_i2c_writefn, s, DEVICE_NATIVE_ENDIAN);
     omap_l4_attach(ta, 0, iomemtype);
 
     return s;
diff --git a/hw/omap_l4.c b/hw/omap_l4.c
index ebec874..a19ea70 100644
--- a/hw/omap_l4.c
+++ b/hw/omap_l4.c
@@ -20,14 +20,6 @@
 #include "hw.h"
 #include "omap.h"
 
-int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
-                          CPUWriteMemoryFunc * const *mem_write,
-                          void *opaque)
-{
-    return cpu_register_io_memory(mem_read, mem_write, opaque,
-                                  DEVICE_NATIVE_ENDIAN);
-}
-
 struct omap_l4_s {
     target_phys_addr_t base;
     int ta_num;
@@ -132,8 +124,8 @@ struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus,
     ta->status = 0x00000000;
     ta->control = 0x00000200;	/* XXX 01000200 for L4TAO */
 
-    iomemtype = l4_register_io_memory(omap_l4ta_readfn,
-                    omap_l4ta_writefn, ta);
+    iomemtype = cpu_register_io_memory(omap_l4ta_readfn,
+                    omap_l4ta_writefn, ta, DEVICE_NATIVE_ENDIAN);
     ta->base = omap_l4_attach(ta, info->ta_region, iomemtype);
 
     return ta;
diff --git a/hw/omap_mmc.c b/hw/omap_mmc.c
index a1afeb5..b42cf90 100644
--- a/hw/omap_mmc.c
+++ b/hw/omap_mmc.c
@@ -612,8 +612,8 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
 
     omap_mmc_reset(s);
 
-    iomemtype = l4_register_io_memory(omap_mmc_readfn,
-                    omap_mmc_writefn, s);
+    iomemtype = cpu_register_io_memory(omap_mmc_readfn,
+                    omap_mmc_writefn, s, DEVICE_NATIVE_ENDIAN);
     omap_l4_attach(ta, 0, iomemtype);
 
     /* Instantiate the storage */
diff --git a/hw/omap_spi.c b/hw/omap_spi.c
index 6030ad9..c20f425 100644
--- a/hw/omap_spi.c
+++ b/hw/omap_spi.c
@@ -327,8 +327,8 @@ struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
     }
     omap_mcspi_reset(s);
 
-    iomemtype = l4_register_io_memory(omap_mcspi_readfn,
-                    omap_mcspi_writefn, s);
+    iomemtype = cpu_register_io_memory(omap_mcspi_readfn,
+                    omap_mcspi_writefn, s, DEVICE_NATIVE_ENDIAN);
     omap_l4_attach(ta, 0, iomemtype);
 
     return s;
diff --git a/hw/omap_synctimer.c b/hw/omap_synctimer.c
index b47ca88..ece5388 100644
--- a/hw/omap_synctimer.c
+++ b/hw/omap_synctimer.c
@@ -89,8 +89,9 @@ struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta,
     struct omap_synctimer_s *s = g_malloc0(sizeof(*s));
 
     omap_synctimer_reset(s);
-    omap_l4_attach(ta, 0, l4_register_io_memory(
-                      omap_synctimer_readfn, omap_synctimer_writefn, s));
+    omap_l4_attach(ta, 0, cpu_register_io_memory(
+                      omap_synctimer_readfn, omap_synctimer_writefn, s,
+                      DEVICE_NATIVE_ENDIAN));
 
     return s;
 }
diff --git a/hw/omap_tap.c b/hw/omap_tap.c
index 1f18ddd..e685288 100644
--- a/hw/omap_tap.c
+++ b/hw/omap_tap.c
@@ -107,6 +107,7 @@ static CPUWriteMemoryFunc * const omap_tap_writefn[] = {
 void omap_tap_init(struct omap_target_agent_s *ta,
                 struct omap_mpu_state_s *mpu)
 {
-    omap_l4_attach(ta, 0, l4_register_io_memory(
-                            omap_tap_readfn, omap_tap_writefn, mpu));
+    omap_l4_attach(ta, 0, cpu_register_io_memory(
+                            omap_tap_readfn, omap_tap_writefn, mpu,
+                            DEVICE_NATIVE_ENDIAN));
 }
commit 92c0bba9a95739c92e959fe478cb1acb92fa5446
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Nov 23 14:06:31 2011 +0200

    omap: remove L4_MUX_HACK
    
    This was introduced apparently to overcome a limitation on the number of
    cpu_register_io_memory() calls.  477b24ef91175 (July 2008) removed use
    of the hack, but retained the code.  This patch removes the code as well.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andrzej Zaborowski <balrogg at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/omap.h b/hw/omap.h
index 924618e..8bd1810 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -1127,7 +1127,4 @@ inline static int debug_register_io_memory(CPUReadMemoryFunc * const *mem_read,
 #  define cpu_register_io_memory	debug_register_io_memory
 # endif
 
-/* Define when we want to reduce the number of IO regions registered.  */
-/*# define L4_MUX_HACK*/
-
 #endif /* hw_omap_h */
diff --git a/hw/omap_l4.c b/hw/omap_l4.c
index a4a8883..ebec874 100644
--- a/hw/omap_l4.c
+++ b/hw/omap_l4.c
@@ -20,89 +20,6 @@
 #include "hw.h"
 #include "omap.h"
 
-#ifdef L4_MUX_HACK
-static int omap_l4_io_entries;
-static int omap_cpu_io_entry;
-static struct omap_l4_entry {
-        CPUReadMemoryFunc * const *mem_read;
-        CPUWriteMemoryFunc * const *mem_write;
-        void *opaque;
-} *omap_l4_io_entry;
-static CPUReadMemoryFunc * const *omap_l4_io_readb_fn;
-static CPUReadMemoryFunc * const *omap_l4_io_readh_fn;
-static CPUReadMemoryFunc * const *omap_l4_io_readw_fn;
-static CPUWriteMemoryFunc * const *omap_l4_io_writeb_fn;
-static CPUWriteMemoryFunc * const *omap_l4_io_writeh_fn;
-static CPUWriteMemoryFunc * const *omap_l4_io_writew_fn;
-static void **omap_l4_io_opaque;
-
-int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
-                CPUWriteMemoryFunc * const *mem_write, void *opaque)
-{
-    omap_l4_io_entry[omap_l4_io_entries].mem_read = mem_read;
-    omap_l4_io_entry[omap_l4_io_entries].mem_write = mem_write;
-    omap_l4_io_entry[omap_l4_io_entries].opaque = opaque;
-
-    return omap_l4_io_entries ++;
-}
-
-static uint32_t omap_l4_io_readb(void *opaque, target_phys_addr_t addr)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_readb_fn[i](omap_l4_io_opaque[i], addr);
-}
-
-static uint32_t omap_l4_io_readh(void *opaque, target_phys_addr_t addr)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_readh_fn[i](omap_l4_io_opaque[i], addr);
-}
-
-static uint32_t omap_l4_io_readw(void *opaque, target_phys_addr_t addr)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_readw_fn[i](omap_l4_io_opaque[i], addr);
-}
-
-static void omap_l4_io_writeb(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_writeb_fn[i](omap_l4_io_opaque[i], addr, value);
-}
-
-static void omap_l4_io_writeh(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_writeh_fn[i](omap_l4_io_opaque[i], addr, value);
-}
-
-static void omap_l4_io_writew(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_writew_fn[i](omap_l4_io_opaque[i], addr, value);
-}
-
-static CPUReadMemoryFunc * const omap_l4_io_readfn[] = {
-    omap_l4_io_readb,
-    omap_l4_io_readh,
-    omap_l4_io_readw,
-};
-
-static CPUWriteMemoryFunc * const omap_l4_io_writefn[] = {
-    omap_l4_io_writeb,
-    omap_l4_io_writeh,
-    omap_l4_io_writew,
-};
-#else
 int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
                           CPUWriteMemoryFunc * const *mem_write,
                           void *opaque)
@@ -110,7 +27,6 @@ int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
     return cpu_register_io_memory(mem_read, mem_write, opaque,
                                   DEVICE_NATIVE_ENDIAN);
 }
-#endif
 
 struct omap_l4_s {
     target_phys_addr_t base;
@@ -126,23 +42,6 @@ struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num)
     bus->ta_num = ta_num;
     bus->base = base;
 
-#ifdef L4_MUX_HACK
-    omap_l4_io_entries = 1;
-    omap_l4_io_entry = g_malloc0(125 * sizeof(*omap_l4_io_entry));
-
-    omap_cpu_io_entry =
-            cpu_register_io_memory(omap_l4_io_readfn,
-                            omap_l4_io_writefn, bus, DEVICE_NATIVE_ENDIAN);
-# define L4_PAGES	(0xb4000 / TARGET_PAGE_SIZE)
-    omap_l4_io_readb_fn = g_malloc0(sizeof(void *) * L4_PAGES);
-    omap_l4_io_readh_fn = g_malloc0(sizeof(void *) * L4_PAGES);
-    omap_l4_io_readw_fn = g_malloc0(sizeof(void *) * L4_PAGES);
-    omap_l4_io_writeb_fn = g_malloc0(sizeof(void *) * L4_PAGES);
-    omap_l4_io_writeh_fn = g_malloc0(sizeof(void *) * L4_PAGES);
-    omap_l4_io_writew_fn = g_malloc0(sizeof(void *) * L4_PAGES);
-    omap_l4_io_opaque = g_malloc0(sizeof(void *) * L4_PAGES);
-#endif
-
     return bus;
 }
 
@@ -245,9 +144,6 @@ target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
 {
     target_phys_addr_t base;
     ssize_t size;
-#ifdef L4_MUX_HACK
-    int i;
-#endif
 
     if (region < 0 || region >= ta->regions) {
         fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region);
@@ -257,21 +153,7 @@ target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
     base = ta->bus->base + ta->start[region].offset;
     size = ta->start[region].size;
     if (iotype) {
-#ifndef L4_MUX_HACK
         cpu_register_physical_memory(base, size, iotype);
-#else
-        cpu_register_physical_memory(base, size, omap_cpu_io_entry);
-        i = (base - ta->bus->base) / TARGET_PAGE_SIZE;
-        for (; size > 0; size -= TARGET_PAGE_SIZE, i ++) {
-            omap_l4_io_readb_fn[i] = omap_l4_io_entry[iotype].mem_read[0];
-            omap_l4_io_readh_fn[i] = omap_l4_io_entry[iotype].mem_read[1];
-            omap_l4_io_readw_fn[i] = omap_l4_io_entry[iotype].mem_read[2];
-            omap_l4_io_writeb_fn[i] = omap_l4_io_entry[iotype].mem_write[0];
-            omap_l4_io_writeh_fn[i] = omap_l4_io_entry[iotype].mem_write[1];
-            omap_l4_io_writew_fn[i] = omap_l4_io_entry[iotype].mem_write[2];
-            omap_l4_io_opaque[i] = omap_l4_io_entry[iotype].opaque;
-        }
-#endif
     }
 
     return base;
commit aee39503dfae943728e99a67decf06e76211ade0
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Nov 22 15:06:46 2011 +0200

    omap_uart: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/nseries.c b/hw/nseries.c
index eb99143..d429dbd 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -33,6 +33,7 @@
 #include "loader.h"
 #include "blockdev.h"
 #include "sysbus.h"
+#include "exec-memory.h"
 
 /* Nokia N8x0 support */
 struct n800_s {
@@ -1275,11 +1276,12 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
                 const char *kernel_cmdline, const char *initrd_filename,
                 const char *cpu_model, struct arm_boot_info *binfo, int model)
 {
+    MemoryRegion *sysmem = get_system_memory();
     struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s));
     int sdram_size = binfo->ram_size;
     DisplayState *ds;
 
-    s->cpu = omap2420_mpu_init(sdram_size, cpu_model);
+    s->cpu = omap2420_mpu_init(sysmem, sdram_size, cpu_model);
 
     /* Setup peripherals
      *
diff --git a/hw/omap.h b/hw/omap.h
index cc09a3c..924618e 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -658,7 +658,8 @@ struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
                 qemu_irq irq, omap_clk fclk, omap_clk iclk,
                 qemu_irq txdma, qemu_irq rxdma,
                 const char *label, CharDriverState *chr);
-struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta,
+struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem,
+                struct omap_target_agent_s *ta,
                 qemu_irq irq, omap_clk fclk, omap_clk iclk,
                 qemu_irq txdma, qemu_irq rxdma,
                 const char *label, CharDriverState *chr);
@@ -952,7 +953,8 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
                 const char *core);
 
 /* omap2.c */
-struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
+struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
+                unsigned long sdram_size,
                 const char *core);
 
 # if TARGET_PHYS_ADDR_BITS == 32
diff --git a/hw/omap2.c b/hw/omap2.c
index 5197fef..e299884 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -2223,7 +2223,8 @@ static const struct dma_irq_map omap2_dma_irq_map[] = {
     { 0, OMAP_INT_24XX_SDMA_IRQ3 },
 };
 
-struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
+struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
+                unsigned long sdram_size,
                 const char *core)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
@@ -2295,7 +2296,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
     soc_dma_port_add_mem(s->dma, qemu_get_ram_ptr(sram_base),
                          OMAP2_SRAM_BASE, s->sram_size);
 
-    s->uart[0] = omap2_uart_init(omap_l4ta(s->l4, 19),
+    s->uart[0] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 19),
                                  qdev_get_gpio_in(s->ih[0],
                                                   OMAP_INT_24XX_UART1_IRQ),
                     omap_findclk(s, "uart1_fclk"),
@@ -2304,7 +2305,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
                     s->drq[OMAP24XX_DMA_UART1_RX],
                     "uart1",
                     serial_hds[0]);
-    s->uart[1] = omap2_uart_init(omap_l4ta(s->l4, 20),
+    s->uart[1] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 20),
                                  qdev_get_gpio_in(s->ih[0],
                                                   OMAP_INT_24XX_UART2_IRQ),
                     omap_findclk(s, "uart2_fclk"),
@@ -2313,7 +2314,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
                     s->drq[OMAP24XX_DMA_UART2_RX],
                     "uart2",
                     serial_hds[0] ? serial_hds[1] : NULL);
-    s->uart[2] = omap2_uart_init(omap_l4ta(s->l4, 21),
+    s->uart[2] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 21),
                                  qdev_get_gpio_in(s->ih[0],
                                                   OMAP_INT_24XX_UART3_IRQ),
                     omap_findclk(s, "uart3_fclk"),
diff --git a/hw/omap_uart.c b/hw/omap_uart.c
index 19f8e6e..64fc9f5 100644
--- a/hw/omap_uart.c
+++ b/hw/omap_uart.c
@@ -26,6 +26,7 @@
 
 /* UARTs */
 struct omap_uart_s {
+    MemoryRegion iomem;
     target_phys_addr_t base;
     SerialState *serial; /* TODO */
     struct omap_target_agent_s *ta;
@@ -68,11 +69,15 @@ struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
     return s;
 }
 
-static uint32_t omap_uart_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_uart_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_uart_s *s = (struct omap_uart_s *) opaque;
 
-    addr &= 0xff;
+    if (size == 4) {
+        return omap_badwidth_read8(opaque, addr);
+    }
+
     switch (addr) {
     case 0x20:	/* MDR1 */
         return s->mdr[0];
@@ -103,11 +108,14 @@ static uint32_t omap_uart_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_uart_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_uart_s *s = (struct omap_uart_s *) opaque;
 
-    addr &= 0xff;
+    if (size == 4) {
+        return omap_badwidth_write8(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x20:	/* MDR1 */
         s->mdr[0] = value & 0x7f;
@@ -145,32 +153,27 @@ static void omap_uart_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_uart_readfn[] = {
-    omap_uart_read,
-    omap_uart_read,
-    omap_badwidth_read8,
+static const MemoryRegionOps omap_uart_ops = {
+    .read = omap_uart_read,
+    .write = omap_uart_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const omap_uart_writefn[] = {
-    omap_uart_write,
-    omap_uart_write,
-    omap_badwidth_write8,
-};
-
-struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta,
+struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem,
+                struct omap_target_agent_s *ta,
                 qemu_irq irq, omap_clk fclk, omap_clk iclk,
                 qemu_irq txdma, qemu_irq rxdma,
                 const char *label, CharDriverState *chr)
 {
-    target_phys_addr_t base = omap_l4_attach(ta, 0, 0);
+    target_phys_addr_t base = omap_l4_attach_region(ta, 0, NULL);
     struct omap_uart_s *s = omap_uart_init(base, irq,
                     fclk, iclk, txdma, rxdma, label, chr);
-    int iomemtype = cpu_register_io_memory(omap_uart_readfn,
-                    omap_uart_writefn, s, DEVICE_NATIVE_ENDIAN);
+
+    memory_region_init_io(&s->iomem, &omap_uart_ops, s, "omap.uart", 0x100);
 
     s->ta = ta;
 
-    cpu_register_physical_memory(base + 0x20, 0x100, iomemtype);
+    memory_region_add_subregion(sysmem, base + 0x20, &s->iomem);
 
     return s;
 }
commit bc75c9e50d308b2ec6623a40179c5cdc84b63dae
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Nov 24 23:20:43 2011 +0100

    tci: Add entry to MAINTAINERS
    
    This should have be part of my TCI patch series.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/MAINTAINERS b/MAINTAINERS
index a8b397d..06df70c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -559,3 +559,8 @@ SPARC target
 M: Blue Swirl <blauwirbel at gmail.com>
 S: Maintained
 F: tcg/sparc/
+
+TCI target
+M: Stefan Weil <sw at weilnetz.de>
+S: Maintained
+F: tcg/tci
commit 14f40fdc98e57cd92c1cbbada5ff07c531148df2
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Nov 26 09:51:23 2011 +0000

    MAINTAINERS: add checkpatch
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/MAINTAINERS b/MAINTAINERS
index 7ee301e..a8b397d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -485,6 +485,11 @@ S: Maintained
 F: trace/
 T: git://repo.or.cz/qemu/stefanha.git tracing
 
+Checkpatch
+M: Blue Swirl <blauwirbel at gmail.com>
+S: Odd Fixes
+F: scripts/checkpatch.pl
+
 Usermode Emulation
 ------------------
 BSD user
commit 61669f9a83c68d41d9254272f10f1e905f339427
Author: Florian Mickler <florian at mickler.org>
Date:   Fri Nov 25 10:24:16 2011 +0100

    checkpatch.pl: fix CAST detection
    
    We should only claim that something is a cast if we did not encouter a
    token before, that did set av_pending.
    
    This fixes the operator * in the line below to be detected as binary (vs
    unary).
    
    kmalloc(sizeof(struct alphatrack_ocmd) * true_size, GFP_KERNEL);
    
    Reported-by: Peter Chubb <nicta.com.au>
    Signed-off-by: Florian Mickler <florian at mickler.org>
    (cherry-picked from Linux kernel commit c023e4734c3e8801e0ecb5e81b831d42a374d861)
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 7a71324..04ab990 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -859,7 +859,7 @@ sub annotate_values {
 				$av_preprocessor = 0;
 			}
 
-		} elsif ($cur =~ /^(\(\s*$Type\s*)\)/) {
+		} elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') {
 			print "CAST($1)\n" if ($dbg_values > 1);
 			push(@av_paren_type, $type);
 			$type = 'C';
commit 0fdd2e1d06884b0236c2f124c1cfd2dd4765341a
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Tue Nov 22 11:59:16 2011 +0400

    target-xtensa: fix MMUv3 initialization
    
    - ITLB/DTLB ways 5 and 6 have 4 and 8 entries respectively;
    - ITLB/DTLB way 6 attr field is set to 3 on reset.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index fc85815..2a0cb1a 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -273,7 +273,7 @@ static void reset_tlb_mmu_ways56(CPUState *env,
             entry[6][ei].vaddr = ei << 29;
             entry[6][ei].paddr = ei << 29;
             entry[6][ei].asid = 1;
-            entry[6][ei].attr = 2;
+            entry[6][ei].attr = 3;
         }
     }
 }
diff --git a/target-xtensa/overlay_tool.h b/target-xtensa/overlay_tool.h
index 9cef27d..df19cc9 100644
--- a/target-xtensa/overlay_tool.h
+++ b/target-xtensa/overlay_tool.h
@@ -256,7 +256,7 @@
         .way_size = { \
             (refill_way_size), (refill_way_size), \
             (refill_way_size), (refill_way_size), \
-            4, 2, 2, 1, 1, 1, \
+            4, (way56) ? 4 : 2, (way56) ? 8 : 2, 1, 1, 1, \
         }, \
         .varway56 = (way56), \
         .nrefillentries = (refill_way_size) * 4, \
commit f81138ce972dd2e8e292b950429fe02308b984c7
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Nov 21 17:16:57 2011 +0200

    prep_pci: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pci_host.h b/hw/pci_host.h
index 0211086..359e38f 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -34,6 +34,7 @@ struct PCIHostState {
     SysBusDevice busdev;
     MemoryRegion conf_mem;
     MemoryRegion data_mem;
+    MemoryRegion mmcfg;
     MemoryRegion *address_space;
     uint32_t config_reg;
     PCIBus *bus;
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index 149807a..ea9fb69 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -86,16 +86,12 @@ static uint32_t PPC_PCIIO_readl (void *opaque, target_phys_addr_t addr)
     return val;
 }
 
-static CPUWriteMemoryFunc * const PPC_PCIIO_write[] = {
-    &PPC_PCIIO_writeb,
-    &PPC_PCIIO_writew,
-    &PPC_PCIIO_writel,
-};
-
-static CPUReadMemoryFunc * const PPC_PCIIO_read[] = {
-    &PPC_PCIIO_readb,
-    &PPC_PCIIO_readw,
-    &PPC_PCIIO_readl,
+static const MemoryRegionOps PPC_PCIIO_ops = {
+    .old_mmio = {
+        .read = { PPC_PCIIO_readb, PPC_PCIIO_readw, PPC_PCIIO_readl, },
+        .write = { PPC_PCIIO_writeb, PPC_PCIIO_writew, PPC_PCIIO_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int prep_map_irq(PCIDevice *pci_dev, int irq_num)
@@ -116,7 +112,6 @@ PCIBus *pci_prep_init(qemu_irq *pic,
 {
     PREPPCIState *s;
     PCIDevice *d;
-    int PPC_io_memory;
 
     s = g_malloc0(sizeof(PREPPCIState));
     s->bus = pci_register_bus(NULL, "pci",
@@ -135,10 +130,8 @@ PCIBus *pci_prep_init(qemu_irq *pic,
     memory_region_add_subregion(address_space_io, 0xcfc, &s->data_mem);
     sysbus_init_ioports(&s->busdev, 0xcfc, 1);
 
-    PPC_io_memory = cpu_register_io_memory(PPC_PCIIO_read,
-                                           PPC_PCIIO_write, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(0x80800000, 0x00400000, PPC_io_memory);
+    memory_region_init_io(&s->mmcfg, &PPC_PCIIO_ops, s, "pciio", 0x00400000);
+    memory_region_add_subregion(address_space_mem, 0x80800000, &s->mmcfg);
 
     /* PCI host bridge */
     d = pci_register_device(s->bus, "PREP Host Bridge - Motorola Raven",
commit cd5cba7941df7d35e94c28dfdb7defb543b27c79
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 20 11:52:58 2011 +0200

    ppce500_pci: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 960a5d0..6232af1 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -79,12 +79,13 @@ struct PPCE500PCIState {
     uint32_t gasket_time;
     qemu_irq irq[4];
     /* mmio maps */
-    int reg;
+    MemoryRegion iomem;
 };
 
 typedef struct PPCE500PCIState PPCE500PCIState;
 
-static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
+static uint64_t pci_reg_read4(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     PPCE500PCIState *pci = opaque;
     unsigned long win;
@@ -152,14 +153,8 @@ static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
     return value;
 }
 
-static CPUReadMemoryFunc * const e500_pci_reg_read[] = {
-    &pci_reg_read4,
-    &pci_reg_read4,
-    &pci_reg_read4,
-};
-
 static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
-                               uint32_t value)
+                           uint64_t value, unsigned size)
 {
     PPCE500PCIState *pci = opaque;
     unsigned long win;
@@ -168,7 +163,7 @@ static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
     win = addr & 0xfe0;
 
     pci_debug("%s: value:%x -> win:%lx(addr:" TARGET_FMT_plx ")\n",
-              __func__, value, win, addr);
+              __func__, (unsigned)value, win, addr);
 
     switch (win) {
     case PPCE500_PCI_OW1:
@@ -225,10 +220,10 @@ static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
     };
 }
 
-static CPUWriteMemoryFunc * const e500_pci_reg_write[] = {
-    &pci_reg_write4,
-    &pci_reg_write4,
-    &pci_reg_write4,
+static const MemoryRegionOps e500_pci_reg_ops = {
+    .read = pci_reg_read4,
+    .write = pci_reg_write4,
+    .endianness = DEVICE_BIG_ENDIAN,
 };
 
 static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
@@ -310,18 +305,17 @@ static void e500_pci_map(SysBusDevice *dev, target_phys_addr_t base)
 
     sysbus_add_memory(dev, base + PCIE500_CFGADDR, &h->conf_mem);
     sysbus_add_memory(dev, base + PCIE500_CFGDATA, &h->data_mem);
-    cpu_register_physical_memory(base + PCIE500_REG_BASE, PCIE500_REG_SIZE,
-                                 s->reg);
+    sysbus_add_memory(dev, base + PCIE500_REG_BASE, &s->iomem);
 }
 
 static void e500_pci_unmap(SysBusDevice *dev, target_phys_addr_t base)
 {
     PCIHostState *h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
+    PPCE500PCIState *s = DO_UPCAST(PPCE500PCIState, pci_state, h);
 
     sysbus_del_memory(dev, &h->conf_mem);
     sysbus_del_memory(dev, &h->data_mem);
-    cpu_register_physical_memory(base + PCIE500_REG_BASE, PCIE500_REG_SIZE,
-                                 IO_MEM_UNASSIGNED);
+    sysbus_del_memory(dev, &s->iomem);
 }
 
 #include "exec-memory.h"
@@ -353,8 +347,8 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
                           "pci-conf-idx", 4);
     memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, h,
                           "pci-conf-data", 4);
-    s->reg = cpu_register_io_memory(e500_pci_reg_read, e500_pci_reg_write, s,
-                                    DEVICE_BIG_ENDIAN);
+    memory_region_init_io(&s->iomem, &e500_pci_reg_ops, s,
+                          "pci.reg", PCIE500_REG_SIZE);
     sysbus_init_mmio_cb2(dev, e500_pci_map, e500_pci_unmap);
 
     return 0;
commit da726e5e067b83f507a2b5cec7b50817ab3c0bab
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 20 11:44:37 2011 +0200

    ppc4xx_pci: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index 339b38e..2c69210 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -54,6 +54,8 @@ struct PPC4xxPCIState {
 
     PCIHostState pci_state;
     PCIDevice *pci_dev;
+    MemoryRegion iomem_addr;
+    MemoryRegion iomem_regs;
 };
 typedef struct PPC4xxPCIState PPC4xxPCIState;
 
@@ -84,35 +86,30 @@ typedef struct PPC4xxPCIState PPC4xxPCIState;
 #define PCI_REG_SIZE        0x40
 
 
-static uint32_t pci4xx_cfgaddr_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t pci4xx_cfgaddr_read(void *opaque, target_phys_addr_t addr,
+                                    unsigned size)
 {
     PPC4xxPCIState *ppc4xx_pci = opaque;
 
     return ppc4xx_pci->pci_state.config_reg;
 }
 
-static CPUReadMemoryFunc * const pci4xx_cfgaddr_read[] = {
-    &pci4xx_cfgaddr_readl,
-    &pci4xx_cfgaddr_readl,
-    &pci4xx_cfgaddr_readl,
-};
-
-static void pci4xx_cfgaddr_writel(void *opaque, target_phys_addr_t addr,
-                                  uint32_t value)
+static void pci4xx_cfgaddr_write(void *opaque, target_phys_addr_t addr,
+                                  uint64_t value, unsigned size)
 {
     PPC4xxPCIState *ppc4xx_pci = opaque;
 
     ppc4xx_pci->pci_state.config_reg = value & ~0x3;
 }
 
-static CPUWriteMemoryFunc * const pci4xx_cfgaddr_write[] = {
-    &pci4xx_cfgaddr_writel,
-    &pci4xx_cfgaddr_writel,
-    &pci4xx_cfgaddr_writel,
+static const MemoryRegionOps pci4xx_cfgaddr_ops = {
+    .read = pci4xx_cfgaddr_read,
+    .write = pci4xx_cfgaddr_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static void ppc4xx_pci_reg_write4(void *opaque, target_phys_addr_t offset,
-                                  uint32_t value)
+                                  uint64_t value, unsigned size)
 {
     struct PPC4xxPCIState *pci = opaque;
 
@@ -179,7 +176,8 @@ static void ppc4xx_pci_reg_write4(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static uint32_t ppc4xx_pci_reg_read4(void *opaque, target_phys_addr_t offset)
+static uint64_t ppc4xx_pci_reg_read4(void *opaque, target_phys_addr_t offset,
+                                     unsigned size)
 {
     struct PPC4xxPCIState *pci = opaque;
     uint32_t value;
@@ -246,16 +244,10 @@ static uint32_t ppc4xx_pci_reg_read4(void *opaque, target_phys_addr_t offset)
     return value;
 }
 
-static CPUReadMemoryFunc * const pci_reg_read[] = {
-    &ppc4xx_pci_reg_read4,
-    &ppc4xx_pci_reg_read4,
-    &ppc4xx_pci_reg_read4,
-};
-
-static CPUWriteMemoryFunc * const pci_reg_write[] = {
-    &ppc4xx_pci_reg_write4,
-    &ppc4xx_pci_reg_write4,
-    &ppc4xx_pci_reg_write4,
+static const MemoryRegionOps pci_reg_ops = {
+    .read = ppc4xx_pci_reg_read4,
+    .write = ppc4xx_pci_reg_write4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static void ppc4xx_pci_reset(void *opaque)
@@ -337,7 +329,6 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
                         target_phys_addr_t registers)
 {
     PPC4xxPCIState *controller;
-    int index;
     static int ppc4xx_pci_id;
     uint8_t *pci_conf;
 
@@ -360,12 +351,11 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
     pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_OTHER);
 
     /* CFGADDR */
-    index = cpu_register_io_memory(pci4xx_cfgaddr_read,
-                                   pci4xx_cfgaddr_write, controller,
-                                   DEVICE_LITTLE_ENDIAN);
-    if (index < 0)
-        goto free;
-    cpu_register_physical_memory(config_space + PCIC0_CFGADDR, 4, index);
+    memory_region_init_io(&controller->iomem_addr, &pci4xx_cfgaddr_ops,
+                          controller, "pci.cfgaddr", 4);
+    memory_region_add_subregion(get_system_memory(),
+                                config_space + PCIC0_CFGADDR,
+                                &controller->iomem_addr);
 
     /* CFGDATA */
     memory_region_init_io(&controller->pci_state.data_mem,
@@ -376,11 +366,10 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
                                 &controller->pci_state.data_mem);
 
     /* Internal registers */
-    index = cpu_register_io_memory(pci_reg_read, pci_reg_write, controller,
-                                   DEVICE_LITTLE_ENDIAN);
-    if (index < 0)
-        goto free;
-    cpu_register_physical_memory(registers, PCI_REG_SIZE, index);
+    memory_region_init_io(&controller->iomem_regs, &pci_reg_ops, controller,
+                          "pci.regs", PCI_REG_SIZE);
+    memory_region_add_subregion(get_system_memory(), registers,
+                                &controller->iomem_regs);
 
     qemu_register_reset(ppc4xx_pci_reset, controller);
 
@@ -389,9 +378,4 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
                      &vmstate_ppc4xx_pci, controller);
 
     return controller->pci_state.bus;
-
-free:
-    printf("%s error\n", __func__);
-    g_free(controller);
-    return NULL;
 }
commit d09510b2766ddfce0a1c2f26fd14054076cbb248
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 20 11:44:25 2011 +0200

    lm32_timer: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/lm32_timer.c b/hw/lm32_timer.c
index 49cbb22..a3a21ed 100644
--- a/hw/lm32_timer.c
+++ b/hw/lm32_timer.c
@@ -51,6 +51,7 @@ enum {
 
 struct LM32TimerState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
 
     QEMUBH *bh;
     ptimer_state *ptimer;
@@ -70,7 +71,7 @@ static void timer_update_irq(LM32TimerState *s)
     qemu_set_irq(s->irq, state);
 }
 
-static uint32_t timer_read(void *opaque, target_phys_addr_t addr)
+static uint64_t timer_read(void *opaque, target_phys_addr_t addr, unsigned size)
 {
     LM32TimerState *s = opaque;
     uint32_t r = 0;
@@ -95,7 +96,8 @@ static uint32_t timer_read(void *opaque, target_phys_addr_t addr)
     return r;
 }
 
-static void timer_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void timer_write(void *opaque, target_phys_addr_t addr,
+                        uint64_t value, unsigned size)
 {
     LM32TimerState *s = opaque;
 
@@ -131,16 +133,14 @@ static void timer_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     timer_update_irq(s);
 }
 
-static CPUReadMemoryFunc * const timer_read_fn[] = {
-    NULL,
-    NULL,
-    &timer_read,
-};
-
-static CPUWriteMemoryFunc * const timer_write_fn[] = {
-    NULL,
-    NULL,
-    &timer_write,
+static const MemoryRegionOps timer_ops = {
+    .read = timer_read,
+    .write = timer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static void timer_hit(void *opaque)
@@ -172,7 +172,6 @@ static void timer_reset(DeviceState *d)
 static int lm32_timer_init(SysBusDevice *dev)
 {
     LM32TimerState *s = FROM_SYSBUS(typeof(*s), dev);
-    int timer_regs;
 
     sysbus_init_irq(dev, &s->irq);
 
@@ -180,9 +179,8 @@ static int lm32_timer_init(SysBusDevice *dev)
     s->ptimer = ptimer_init(s->bh);
     ptimer_set_freq(s->ptimer, s->freq_hz);
 
-    timer_regs = cpu_register_io_memory(timer_read_fn, timer_write_fn, s,
-            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, timer_regs);
+    memory_region_init_io(&s->iomem, &timer_ops, s, "timer", R_MAX * 4);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     return 0;
 }
commit 9a9d0b816b0bde227977c0aebe96ff6240f21b21
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Thu Nov 17 14:23:02 2011 +0100

    sh_serial: convert to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/sh.h b/hw/sh.h
index c377584..6488db2 100644
--- a/hw/sh.h
+++ b/hw/sh.h
@@ -39,7 +39,8 @@ void tmu012_init(struct MemoryRegion *sysmem, target_phys_addr_t base,
 
 /* sh_serial.c */
 #define SH_SERIAL_FEAT_SCIF (1 << 0)
-void sh_serial_init (target_phys_addr_t base, int feat,
+void sh_serial_init(MemoryRegion *sysmem,
+                    target_phys_addr_t base, int feat,
 		     uint32_t freq, CharDriverState *chr,
 		     qemu_irq eri_source,
 		     qemu_irq rxi_source,
diff --git a/hw/sh7750.c b/hw/sh7750.c
index 20ac605..4f4d8e7 100644
--- a/hw/sh7750.c
+++ b/hw/sh7750.c
@@ -766,19 +766,21 @@ SH7750State *sh7750_init(CPUSH4State * cpu, MemoryRegion *sysmem)
 
     cpu->intc_handle = &s->intc;
 
-    sh_serial_init(0x1fe00000, 0, s->periph_freq, serial_hds[0],
-		   s->intc.irqs[SCI1_ERI],
-		   s->intc.irqs[SCI1_RXI],
-		   s->intc.irqs[SCI1_TXI],
-		   s->intc.irqs[SCI1_TEI],
-		   NULL);
-    sh_serial_init(0x1fe80000, SH_SERIAL_FEAT_SCIF,
-		   s->periph_freq, serial_hds[1],
-		   s->intc.irqs[SCIF_ERI],
-		   s->intc.irqs[SCIF_RXI],
-		   s->intc.irqs[SCIF_TXI],
-		   NULL,
-		   s->intc.irqs[SCIF_BRI]);
+    sh_serial_init(sysmem, 0x1fe00000,
+                   0, s->periph_freq, serial_hds[0],
+                   s->intc.irqs[SCI1_ERI],
+                   s->intc.irqs[SCI1_RXI],
+                   s->intc.irqs[SCI1_TXI],
+                   s->intc.irqs[SCI1_TEI],
+                   NULL);
+    sh_serial_init(sysmem, 0x1fe80000,
+                   SH_SERIAL_FEAT_SCIF,
+                   s->periph_freq, serial_hds[1],
+                   s->intc.irqs[SCIF_ERI],
+                   s->intc.irqs[SCIF_RXI],
+                   s->intc.irqs[SCIF_TXI],
+                   NULL,
+                   s->intc.irqs[SCIF_BRI]);
 
     tmu012_init(sysmem, 0x1fd80000,
 		TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
diff --git a/hw/sh_serial.c b/hw/sh_serial.c
index a20c59e..43b0eb1 100644
--- a/hw/sh_serial.c
+++ b/hw/sh_serial.c
@@ -27,6 +27,7 @@
 #include "hw.h"
 #include "sh.h"
 #include "qemu-char.h"
+#include "exec-memory.h"
 
 //#define DEBUG_SERIAL
 
@@ -39,6 +40,9 @@
 #define SH_RX_FIFO_LENGTH (16)
 
 typedef struct {
+    MemoryRegion iomem;
+    MemoryRegion iomem_p4;
+    MemoryRegion iomem_a7;
     uint8_t smr;
     uint8_t brr;
     uint8_t scr;
@@ -74,7 +78,8 @@ static void sh_serial_clear_fifo(sh_serial_state * s)
     s->rx_tail = 0;
 }
 
-static void sh_serial_write(void *opaque, uint32_t offs, uint32_t val)
+static void sh_serial_write(void *opaque, target_phys_addr_t offs,
+                            uint64_t val, unsigned size)
 {
     sh_serial_state *s = opaque;
     unsigned char ch;
@@ -185,7 +190,8 @@ static void sh_serial_write(void *opaque, uint32_t offs, uint32_t val)
     abort();
 }
 
-static uint32_t sh_serial_read(void *opaque, uint32_t offs)
+static uint64_t sh_serial_read(void *opaque, target_phys_addr_t offs,
+                               unsigned size)
 {
     sh_serial_state *s = opaque;
     uint32_t ret = ~0;
@@ -338,28 +344,22 @@ static void sh_serial_event(void *opaque, int event)
         sh_serial_receive_break(s);
 }
 
-static CPUReadMemoryFunc * const sh_serial_readfn[] = {
-    &sh_serial_read,
-    &sh_serial_read,
-    &sh_serial_read,
+static const MemoryRegionOps sh_serial_ops = {
+    .read = sh_serial_read,
+    .write = sh_serial_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const sh_serial_writefn[] = {
-    &sh_serial_write,
-    &sh_serial_write,
-    &sh_serial_write,
-};
-
-void sh_serial_init (target_phys_addr_t base, int feat,
-		     uint32_t freq, CharDriverState *chr,
-		     qemu_irq eri_source,
-		     qemu_irq rxi_source,
-		     qemu_irq txi_source,
-		     qemu_irq tei_source,
-		     qemu_irq bri_source)
+void sh_serial_init(MemoryRegion *sysmem,
+                    target_phys_addr_t base, int feat,
+                    uint32_t freq, CharDriverState *chr,
+                    qemu_irq eri_source,
+                    qemu_irq rxi_source,
+                    qemu_irq txi_source,
+                    qemu_irq tei_source,
+                    qemu_irq bri_source)
 {
     sh_serial_state *s;
-    int s_io_memory;
 
     s = g_malloc0(sizeof(sh_serial_state));
 
@@ -381,11 +381,16 @@ void sh_serial_init (target_phys_addr_t base, int feat,
 
     sh_serial_clear_fifo(s);
 
-    s_io_memory = cpu_register_io_memory(sh_serial_readfn,
-					 sh_serial_writefn, s,
-                                         DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(P4ADDR(base), 0x28, s_io_memory);
-    cpu_register_physical_memory(A7ADDR(base), 0x28, s_io_memory);
+    memory_region_init_io(&s->iomem, &sh_serial_ops, s,
+                          "serial", 0x100000000ULL);
+
+    memory_region_init_alias(&s->iomem_p4, "serial-p4", &s->iomem,
+                             0, 0x28);
+    memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4);
+
+    memory_region_init_alias(&s->iomem_a7, "serial-a7", &s->iomem,
+                             0, 0x28);
+    memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
 
     s->chr = chr;
 
commit b279e5efc0aa3a62c5bce21bc31700e828ca9cd8
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Thu Nov 17 14:23:01 2011 +0100

    sh_intc: convert interrupt controller to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/sh7750.c b/hw/sh7750.c
index c659756..20ac605 100644
--- a/hw/sh7750.c
+++ b/hw/sh7750.c
@@ -756,7 +756,7 @@ SH7750State *sh7750_init(CPUSH4State * cpu, MemoryRegion *sysmem)
                           "cache-and-tlb", 0x08000000);
     memory_region_add_subregion(sysmem, 0xf0000000, &s->mmct_iomem);
 
-    sh_intc_init(&s->intc, NR_SOURCES,
+    sh_intc_init(sysmem, &s->intc, NR_SOURCES,
 		 _INTC_ARRAY(mask_registers),
 		 _INTC_ARRAY(prio_registers));
 
diff --git a/hw/sh_intc.c b/hw/sh_intc.c
index e07424f..b24ec77 100644
--- a/hw/sh_intc.c
+++ b/hw/sh_intc.c
@@ -219,7 +219,8 @@ static void sh_intc_toggle_mask(struct intc_desc *desc, intc_enum id,
 #endif
 }
 
-static uint32_t sh_intc_read(void *opaque, target_phys_addr_t offset)
+static uint64_t sh_intc_read(void *opaque, target_phys_addr_t offset,
+                             unsigned size)
 {
     struct intc_desc *desc = opaque;
     intc_enum *enum_ids = NULL;
@@ -238,7 +239,7 @@ static uint32_t sh_intc_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void sh_intc_write(void *opaque, target_phys_addr_t offset,
-			  uint32_t value)
+                          uint64_t value, unsigned size)
 {
     struct intc_desc *desc = opaque;
     intc_enum *enum_ids = NULL;
@@ -282,16 +283,10 @@ static void sh_intc_write(void *opaque, target_phys_addr_t offset,
 #endif
 }
 
-static CPUReadMemoryFunc * const sh_intc_readfn[] = {
-    sh_intc_read,
-    sh_intc_read,
-    sh_intc_read
-};
-
-static CPUWriteMemoryFunc * const sh_intc_writefn[] = {
-    sh_intc_write,
-    sh_intc_write,
-    sh_intc_write
+static const struct MemoryRegionOps sh_intc_ops = {
+    .read = sh_intc_read,
+    .write = sh_intc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id)
@@ -302,15 +297,36 @@ struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id)
     return NULL;
 }
 
-static void sh_intc_register(struct intc_desc *desc, 
-			     unsigned long address)
+static unsigned int sh_intc_register(MemoryRegion *sysmem,
+                             struct intc_desc *desc,
+                             const unsigned long address,
+                             const char *type,
+                             const char *action,
+                             const unsigned int index)
 {
-    if (address) {
-        cpu_register_physical_memory_offset(P4ADDR(address), 4,
-                                            desc->iomemtype, INTC_A7(address));
-        cpu_register_physical_memory_offset(A7ADDR(address), 4,
-                                            desc->iomemtype, INTC_A7(address));
+    char name[60];
+    MemoryRegion *iomem, *iomem_p4, *iomem_a7;
+
+    if (!address) {
+        return 0;
     }
+
+    iomem = &desc->iomem;
+    iomem_p4 = desc->iomem_aliases + index;
+    iomem_a7 = iomem_p4 + 1;
+
+#define SH_INTC_IOMEM_FORMAT "interrupt-controller-%s-%s-%s"
+    snprintf(name, sizeof(name), SH_INTC_IOMEM_FORMAT, type, action, "p4");
+    memory_region_init_alias(iomem_p4, name, iomem, INTC_A7(address), 4);
+    memory_region_add_subregion(sysmem, P4ADDR(address), iomem_p4);
+
+    snprintf(name, sizeof(name), SH_INTC_IOMEM_FORMAT, type, action, "a7");
+    memory_region_init_alias(iomem_a7, name, iomem, INTC_A7(address), 4);
+    memory_region_add_subregion(sysmem, A7ADDR(address), iomem_a7);
+#undef SH_INTC_IOMEM_FORMAT
+
+    /* used to increment aliases index */
+    return 2;
 }
 
 static void sh_intc_register_source(struct intc_desc *desc,
@@ -415,14 +431,15 @@ void sh_intc_register_sources(struct intc_desc *desc,
     }
 }
 
-int sh_intc_init(struct intc_desc *desc,
+int sh_intc_init(MemoryRegion *sysmem,
+         struct intc_desc *desc,
 		 int nr_sources,
 		 struct intc_mask_reg *mask_regs,
 		 int nr_mask_regs,
 		 struct intc_prio_reg *prio_regs,
 		 int nr_prio_regs)
 {
-    unsigned int i;
+    unsigned int i, j;
 
     desc->pending = 0;
     desc->nr_sources = nr_sources;
@@ -430,7 +447,12 @@ int sh_intc_init(struct intc_desc *desc,
     desc->nr_mask_regs = nr_mask_regs;
     desc->prio_regs = prio_regs;
     desc->nr_prio_regs = nr_prio_regs;
+    /* Allocate 4 MemoryRegions per register (2 actions * 2 aliases).
+     **/
+    desc->iomem_aliases = g_new0(MemoryRegion,
+                                 (nr_mask_regs + nr_prio_regs) * 4);
 
+    j = 0;
     i = sizeof(struct intc_source) * nr_sources;
     desc->sources = g_malloc0(i);
 
@@ -442,15 +464,19 @@ int sh_intc_init(struct intc_desc *desc,
 
     desc->irqs = qemu_allocate_irqs(sh_intc_set_irq, desc, nr_sources);
  
-    desc->iomemtype = cpu_register_io_memory(sh_intc_readfn,
-					     sh_intc_writefn, desc,
-                                             DEVICE_NATIVE_ENDIAN);
+    memory_region_init_io(&desc->iomem, &sh_intc_ops, desc,
+                          "interrupt-controller", 0x100000000ULL);
+
+#define INT_REG_PARAMS(reg_struct, type, action, j) \
+        reg_struct->action##_reg, #type, #action, j
     if (desc->mask_regs) {
         for (i = 0; i < desc->nr_mask_regs; i++) {
 	    struct intc_mask_reg *mr = desc->mask_regs + i;
 
-	    sh_intc_register(desc, mr->set_reg);
-	    sh_intc_register(desc, mr->clr_reg);
+            j += sh_intc_register(sysmem, desc,
+                                  INT_REG_PARAMS(mr, mask, set, j));
+            j += sh_intc_register(sysmem, desc,
+                                  INT_REG_PARAMS(mr, mask, clr, j));
 	}
     }
 
@@ -458,10 +484,13 @@ int sh_intc_init(struct intc_desc *desc,
         for (i = 0; i < desc->nr_prio_regs; i++) {
 	    struct intc_prio_reg *pr = desc->prio_regs + i;
 
-	    sh_intc_register(desc, pr->set_reg);
-	    sh_intc_register(desc, pr->clr_reg);
+            j += sh_intc_register(sysmem, desc,
+                                  INT_REG_PARAMS(pr, prio, set, j));
+            j += sh_intc_register(sysmem, desc,
+                                  INT_REG_PARAMS(pr, prio, clr, j));
 	}
     }
+#undef INT_REG_PARAMS
 
     return 0;
 }
diff --git a/hw/sh_intc.h b/hw/sh_intc.h
index c117d6f..80c9430 100644
--- a/hw/sh_intc.h
+++ b/hw/sh_intc.h
@@ -3,6 +3,7 @@
 
 #include "qemu-common.h"
 #include "irq.h"
+#include "exec-memory.h"
 
 typedef unsigned char intc_enum;
 
@@ -46,6 +47,8 @@ struct intc_source {
 };
 
 struct intc_desc {
+    MemoryRegion iomem;
+    MemoryRegion *iomem_aliases;
     qemu_irq *irqs;
     struct intc_source *sources;
     int nr_sources;
@@ -53,7 +56,6 @@ struct intc_desc {
     int nr_mask_regs;
     struct intc_prio_reg *prio_regs;
     int nr_prio_regs;
-    int iomemtype;
     int pending; /* number of interrupt sources that has pending set */
 };
 
@@ -68,7 +70,8 @@ void sh_intc_register_sources(struct intc_desc *desc,
 			      struct intc_group *groups,
 			      int nr_groups);
 
-int sh_intc_init(struct intc_desc *desc,
+int sh_intc_init(MemoryRegion *sysmem,
+                 struct intc_desc *desc,
 		 int nr_sources,
 		 struct intc_mask_reg *mask_regs,
 		 int nr_mask_regs,
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index 5a1e15e..f4dda48 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -24,7 +24,10 @@
 #include <signal.h>
 
 #include "cpu.h"
+
+#if !defined(CONFIG_USER_ONLY)
 #include "hw/sh_intc.h"
+#endif
 
 #if defined(CONFIG_USER_ONLY)
 
commit 89e29451407353587a744a27d2896850d7c7624d
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Thu Nov 17 14:23:00 2011 +0100

    sh_timer: convert to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/sh.h b/hw/sh.h
index cf3f6f6..c377584 100644
--- a/hw/sh.h
+++ b/hw/sh.h
@@ -31,7 +31,8 @@ int sh7750_register_io_device(struct SH7750State *s,
 #define TMU012_FEAT_TOCR   (1 << 0)
 #define TMU012_FEAT_3CHAN  (1 << 1)
 #define TMU012_FEAT_EXTCLK (1 << 2)
-void tmu012_init(target_phys_addr_t base, int feat, uint32_t freq,
+void tmu012_init(struct MemoryRegion *sysmem, target_phys_addr_t base,
+                 int feat, uint32_t freq,
 		 qemu_irq ch0_irq, qemu_irq ch1_irq,
 		 qemu_irq ch2_irq0, qemu_irq ch2_irq1);
 
diff --git a/hw/sh7750.c b/hw/sh7750.c
index 6ad76df..c659756 100644
--- a/hw/sh7750.c
+++ b/hw/sh7750.c
@@ -780,7 +780,7 @@ SH7750State *sh7750_init(CPUSH4State * cpu, MemoryRegion *sysmem)
 		   NULL,
 		   s->intc.irqs[SCIF_BRI]);
 
-    tmu012_init(0x1fd80000,
+    tmu012_init(sysmem, 0x1fd80000,
 		TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
 		s->periph_freq,
 		s->intc.irqs[TMU0],
@@ -804,7 +804,7 @@ SH7750State *sh7750_init(CPUSH4State * cpu, MemoryRegion *sysmem)
         sh_intc_register_sources(&s->intc,
 				 _INTC_ARRAY(vectors_tmu34),
 				 NULL, 0);
-        tmu012_init(0x1e100000, 0, s->periph_freq,
+        tmu012_init(sysmem, 0x1e100000, 0, s->periph_freq,
 		    s->intc.irqs[TMU3],
 		    s->intc.irqs[TMU4],
 		    NULL, NULL);
diff --git a/hw/sh_timer.c b/hw/sh_timer.c
index dca3c94..d2c0cec 100644
--- a/hw/sh_timer.c
+++ b/hw/sh_timer.c
@@ -11,6 +11,7 @@
 #include "hw.h"
 #include "sh.h"
 #include "qemu-timer.h"
+#include "exec-memory.h"
 
 //#define DEBUG_TIMER
 
@@ -210,6 +211,9 @@ static void *sh_timer_init(uint32_t freq, int feat, qemu_irq irq)
 }
 
 typedef struct {
+    MemoryRegion iomem;
+    MemoryRegion iomem_p4;
+    MemoryRegion iomem_a7;
     void *timer[3];
     int level[3];
     uint32_t tocr;
@@ -217,7 +221,8 @@ typedef struct {
     int feat;
 } tmu012_state;
 
-static uint32_t tmu012_read(void *opaque, target_phys_addr_t offset)
+static uint64_t tmu012_read(void *opaque, target_phys_addr_t offset,
+                            unsigned size)
 {
     tmu012_state *s = (tmu012_state *)opaque;
 
@@ -248,7 +253,7 @@ static uint32_t tmu012_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void tmu012_write(void *opaque, target_phys_addr_t offset,
-                        uint32_t value)
+                        uint64_t value, unsigned size)
 {
     tmu012_state *s = (tmu012_state *)opaque;
 
@@ -291,23 +296,17 @@ static void tmu012_write(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static CPUReadMemoryFunc * const tmu012_readfn[] = {
-    tmu012_read,
-    tmu012_read,
-    tmu012_read
+static const MemoryRegionOps tmu012_ops = {
+    .read = tmu012_read,
+    .write = tmu012_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const tmu012_writefn[] = {
-    tmu012_write,
-    tmu012_write,
-    tmu012_write
-};
-
-void tmu012_init(target_phys_addr_t base, int feat, uint32_t freq,
+void tmu012_init(MemoryRegion *sysmem, target_phys_addr_t base,
+                 int feat, uint32_t freq,
 		 qemu_irq ch0_irq, qemu_irq ch1_irq,
 		 qemu_irq ch2_irq0, qemu_irq ch2_irq1)
 {
-    int iomemtype;
     tmu012_state *s;
     int timer_feat = (feat & TMU012_FEAT_EXTCLK) ? TIMER_FEAT_EXTCLK : 0;
 
@@ -318,10 +317,16 @@ void tmu012_init(target_phys_addr_t base, int feat, uint32_t freq,
     if (feat & TMU012_FEAT_3CHAN)
         s->timer[2] = sh_timer_init(freq, timer_feat | TIMER_FEAT_CAPT,
 				    ch2_irq0); /* ch2_irq1 not supported */
-    iomemtype = cpu_register_io_memory(tmu012_readfn,
-                                       tmu012_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(P4ADDR(base), 0x00001000, iomemtype);
-    cpu_register_physical_memory(A7ADDR(base), 0x00001000, iomemtype);
+
+    memory_region_init_io(&s->iomem, &tmu012_ops, s,
+                          "timer", 0x100000000ULL);
+
+    memory_region_init_alias(&s->iomem_p4, "timer-p4",
+                             &s->iomem, 0, 0x1000);
+    memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4);
+
+    memory_region_init_alias(&s->iomem_a7, "timer-a7",
+                             &s->iomem, 0, 0x1000);
+    memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
     /* ??? Save/restore.  */
 }
commit 1a4004c7720c0d8d113c3bb180522fa466afd29e
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Thu Nov 17 14:22:59 2011 +0100

    sh7750: convert cache and tlb to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/sh7750.c b/hw/sh7750.c
index 3bf568d..6ad76df 100644
--- a/hw/sh7750.c
+++ b/hw/sh7750.c
@@ -42,6 +42,7 @@ typedef struct SH7750State {
     MemoryRegion iomem_ff8;
     MemoryRegion iomem_1fc;
     MemoryRegion iomem_ffc;
+    MemoryRegion mmct_iomem;
     /* CPU */
     CPUSH4State *cpu;
     /* Peripheral frequency in Hz */
@@ -623,18 +624,23 @@ static struct intc_group groups_irl[] = {
 #define MM_UTLB_DATA     (7)
 #define MM_REGION_TYPE(addr)  ((addr & MM_REGION_MASK) >> 24)
 
-static uint32_t invalid_read(void *opaque, target_phys_addr_t addr)
+static uint64_t invalid_read(void *opaque, target_phys_addr_t addr)
 {
     abort();
 
     return 0;
 }
 
-static uint32_t sh7750_mmct_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t sh7750_mmct_read(void *opaque, target_phys_addr_t addr,
+                                 unsigned size)
 {
     SH7750State *s = opaque;
     uint32_t ret = 0;
 
+    if (size != 4) {
+        return invalid_read(opaque, addr);
+    }
+
     switch (MM_REGION_TYPE(addr)) {
     case MM_ICACHE_ADDR:
     case MM_ICACHE_DATA:
@@ -664,16 +670,20 @@ static uint32_t sh7750_mmct_readl(void *opaque, target_phys_addr_t addr)
 }
 
 static void invalid_write(void *opaque, target_phys_addr_t addr,
-			  uint32_t mem_value)
+                          uint64_t mem_value)
 {
     abort();
 }
 
-static void sh7750_mmct_writel(void *opaque, target_phys_addr_t addr,
-				uint32_t mem_value)
+static void sh7750_mmct_write(void *opaque, target_phys_addr_t addr,
+                              uint64_t mem_value, unsigned size)
 {
     SH7750State *s = opaque;
 
+    if (size != 4) {
+        invalid_write(opaque, addr, mem_value);
+    }
+
     switch (MM_REGION_TYPE(addr)) {
     case MM_ICACHE_ADDR:
     case MM_ICACHE_DATA:
@@ -702,22 +712,15 @@ static void sh7750_mmct_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const sh7750_mmct_read[] = {
-    invalid_read,
-    invalid_read,
-    sh7750_mmct_readl
-};
-
-static CPUWriteMemoryFunc * const sh7750_mmct_write[] = {
-    invalid_write,
-    invalid_write,
-    sh7750_mmct_writel
+static const struct MemoryRegionOps sh7750_mmct_ops = {
+    .read = sh7750_mmct_read,
+    .write = sh7750_mmct_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 SH7750State *sh7750_init(CPUSH4State * cpu, MemoryRegion *sysmem)
 {
     SH7750State *s;
-    int sh7750_mm_cache_and_tlb; /* memory mapped cache and tlb */
 
     s = g_malloc0(sizeof(SH7750State));
     s->cpu = cpu;
@@ -749,11 +752,9 @@ SH7750State *sh7750_init(CPUSH4State * cpu, MemoryRegion *sysmem)
                              &s->iomem, 0x1fc00000, 0x1000);
     memory_region_add_subregion(sysmem, 0xffc00000, &s->iomem_ffc);
 
-    sh7750_mm_cache_and_tlb = cpu_register_io_memory(sh7750_mmct_read,
-						     sh7750_mmct_write, s,
-                                                     DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(0xf0000000, 0x08000000,
-				 sh7750_mm_cache_and_tlb);
+    memory_region_init_io(&s->mmct_iomem, &sh7750_mmct_ops, s,
+                          "cache-and-tlb", 0x08000000);
+    memory_region_add_subregion(sysmem, 0xf0000000, &s->mmct_iomem);
 
     sh_intc_init(&s->intc, NR_SOURCES,
 		 _INTC_ARRAY(mask_registers),
commit 382863e2c6caaa07ecedc04f33e569ace746564c
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Thu Nov 17 14:22:58 2011 +0100

    sh7750: convert memory controller/ioport to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/r2d.c b/hw/r2d.c
index a9aefa2..9b6fcba 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -250,7 +250,7 @@ static void r2d_init(ram_addr_t ram_size,
     memory_region_init_ram(sdram, NULL, "r2d.sdram", SDRAM_SIZE);
     memory_region_add_subregion(address_space_mem, SDRAM_BASE, sdram);
     /* Register peripherals */
-    s = sh7750_init(env);
+    s = sh7750_init(env, address_space_mem);
     irq = r2d_fpga_init(address_space_mem, 0x04000000, sh7750_irl(s));
     sysbus_create_varargs("sh_pci", 0x1e200000, irq[PCI_INTA], irq[PCI_INTB],
                           irq[PCI_INTC], irq[PCI_INTD], NULL);
diff --git a/hw/sh.h b/hw/sh.h
index d30e9f5..cf3f6f6 100644
--- a/hw/sh.h
+++ b/hw/sh.h
@@ -9,8 +9,9 @@
 
 /* sh7750.c */
 struct SH7750State;
+struct MemoryRegion;
 
-struct SH7750State *sh7750_init(CPUState * cpu);
+struct SH7750State *sh7750_init(CPUState * cpu, struct MemoryRegion *sysmem);
 
 typedef struct {
     /* The callback will be triggered if any of the designated lines change */
diff --git a/hw/sh7750.c b/hw/sh7750.c
index 9f3ea92..3bf568d 100644
--- a/hw/sh7750.c
+++ b/hw/sh7750.c
@@ -30,10 +30,18 @@
 #include "sh7750_regnames.h"
 #include "sh_intc.h"
 #include "cpu.h"
+#include "exec-memory.h"
 
 #define NB_DEVICES 4
 
 typedef struct SH7750State {
+    MemoryRegion iomem;
+    MemoryRegion iomem_1f0;
+    MemoryRegion iomem_ff0;
+    MemoryRegion iomem_1f8;
+    MemoryRegion iomem_ff8;
+    MemoryRegion iomem_1fc;
+    MemoryRegion iomem_ffc;
     /* CPU */
     CPUSH4State *cpu;
     /* Peripheral frequency in Hz */
@@ -436,16 +444,16 @@ static void sh7750_mem_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const sh7750_mem_read[] = {
-    sh7750_mem_readb,
-    sh7750_mem_readw,
-    sh7750_mem_readl
-};
-
-static CPUWriteMemoryFunc * const sh7750_mem_write[] = {
-    sh7750_mem_writeb,
-    sh7750_mem_writew,
-    sh7750_mem_writel
+static const MemoryRegionOps sh7750_mem_ops = {
+    .old_mmio = {
+        .read = {sh7750_mem_readb,
+                 sh7750_mem_readw,
+                 sh7750_mem_readl },
+        .write = {sh7750_mem_writeb,
+                  sh7750_mem_writew,
+                  sh7750_mem_writel },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 /* sh775x interrupt controller tables for sh_intc.c
@@ -706,30 +714,40 @@ static CPUWriteMemoryFunc * const sh7750_mmct_write[] = {
     sh7750_mmct_writel
 };
 
-SH7750State *sh7750_init(CPUSH4State * cpu)
+SH7750State *sh7750_init(CPUSH4State * cpu, MemoryRegion *sysmem)
 {
     SH7750State *s;
-    int sh7750_io_memory;
     int sh7750_mm_cache_and_tlb; /* memory mapped cache and tlb */
 
     s = g_malloc0(sizeof(SH7750State));
     s->cpu = cpu;
     s->periph_freq = 60000000;	/* 60MHz */
-    sh7750_io_memory = cpu_register_io_memory(sh7750_mem_read,
-					      sh7750_mem_write, s,
-                                              DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory_offset(0x1f000000, 0x1000,
-                                        sh7750_io_memory, 0x1f000000);
-    cpu_register_physical_memory_offset(0xff000000, 0x1000,
-                                        sh7750_io_memory, 0x1f000000);
-    cpu_register_physical_memory_offset(0x1f800000, 0x1000,
-                                        sh7750_io_memory, 0x1f800000);
-    cpu_register_physical_memory_offset(0xff800000, 0x1000,
-                                        sh7750_io_memory, 0x1f800000);
-    cpu_register_physical_memory_offset(0x1fc00000, 0x1000,
-                                        sh7750_io_memory, 0x1fc00000);
-    cpu_register_physical_memory_offset(0xffc00000, 0x1000,
-                                        sh7750_io_memory, 0x1fc00000);
+    memory_region_init_io(&s->iomem, &sh7750_mem_ops, s,
+                          "memory", 0x1fc01000);
+
+    memory_region_init_alias(&s->iomem_1f0, "memory-1f0",
+                             &s->iomem, 0x1f000000, 0x1000);
+    memory_region_add_subregion(sysmem, 0x1f000000, &s->iomem_1f0);
+
+    memory_region_init_alias(&s->iomem_ff0, "memory-ff0",
+                             &s->iomem, 0x1f000000, 0x1000);
+    memory_region_add_subregion(sysmem, 0xff000000, &s->iomem_ff0);
+
+    memory_region_init_alias(&s->iomem_1f8, "memory-1f8",
+                             &s->iomem, 0x1f800000, 0x1000);
+    memory_region_add_subregion(sysmem, 0x1f800000, &s->iomem_1f8);
+
+    memory_region_init_alias(&s->iomem_ff8, "memory-ff8",
+                             &s->iomem, 0x1f800000, 0x1000);
+    memory_region_add_subregion(sysmem, 0xff800000, &s->iomem_ff8);
+
+    memory_region_init_alias(&s->iomem_1fc, "memory-1fc",
+                             &s->iomem, 0x1fc00000, 0x1000);
+    memory_region_add_subregion(sysmem, 0x1fc00000, &s->iomem_1fc);
+
+    memory_region_init_alias(&s->iomem_ffc, "memory-ffc",
+                             &s->iomem, 0x1fc00000, 0x1000);
+    memory_region_add_subregion(sysmem, 0xffc00000, &s->iomem_ffc);
 
     sh7750_mm_cache_and_tlb = cpu_register_io_memory(sh7750_mmct_read,
 						     sh7750_mmct_write, s,
diff --git a/hw/shix.c b/hw/shix.c
index 670ddb5..e0c2200 100644
--- a/hw/shix.c
+++ b/hw/shix.c
@@ -80,7 +80,7 @@ static void shix_init(ram_addr_t ram_size,
     }
 
     /* Register peripherals */
-    s = sh7750_init(env);
+    s = sh7750_init(env, sysmem);
     /* XXXXX Check success */
     tc58128_init(s, "shix_linux_nand.bin", NULL);
     fprintf(stderr, "initialization terminated\n");
commit a3d12d073e1d1b4cfb5841a0984f83601911abbc
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Tue Nov 15 12:14:02 2011 +0100

    slavio_timer: convert to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c
index 84449ba..c23f990 100644
--- a/hw/slavio_timer.c
+++ b/hw/slavio_timer.c
@@ -61,6 +61,7 @@ typedef struct SLAVIO_TIMERState {
 } SLAVIO_TIMERState;
 
 typedef struct TimerContext {
+    MemoryRegion iomem;
     SLAVIO_TIMERState *s;
     unsigned int timer_index; /* 0 for system, 1 ... MAX_CPUS for CPU timers */
 } TimerContext;
@@ -128,7 +129,8 @@ static void slavio_timer_irq(void *opaque)
     }
 }
 
-static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr,
+                                       unsigned size)
 {
     TimerContext *tc = opaque;
     SLAVIO_TIMERState *s = tc->s;
@@ -188,7 +190,7 @@ static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
 }
 
 static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr,
-                                    uint32_t val)
+                                    uint64_t val, unsigned size)
 {
     TimerContext *tc = opaque;
     SLAVIO_TIMERState *s = tc->s;
@@ -311,16 +313,14 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const slavio_timer_mem_read[3] = {
-    NULL,
-    NULL,
-    slavio_timer_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const slavio_timer_mem_write[3] = {
-    NULL,
-    NULL,
-    slavio_timer_mem_writel,
+static const MemoryRegionOps slavio_timer_mem_ops = {
+    .read = slavio_timer_mem_readl,
+    .write = slavio_timer_mem_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static const VMStateDescription vmstate_timer = {
@@ -374,13 +374,15 @@ static void slavio_timer_reset(DeviceState *d)
 
 static int slavio_timer_init1(SysBusDevice *dev)
 {
-    int io;
     SLAVIO_TIMERState *s = FROM_SYSBUS(SLAVIO_TIMERState, dev);
     QEMUBH *bh;
     unsigned int i;
     TimerContext *tc;
 
     for (i = 0; i <= MAX_CPUS; i++) {
+        uint64_t size;
+        char timer_name[20];
+
         tc = g_malloc0(sizeof(TimerContext));
         tc->s = s;
         tc->timer_index = i;
@@ -389,14 +391,11 @@ static int slavio_timer_init1(SysBusDevice *dev)
         s->cputimer[i].timer = ptimer_init(bh);
         ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
 
-        io = cpu_register_io_memory(slavio_timer_mem_read,
-                                    slavio_timer_mem_write, tc,
-                                    DEVICE_NATIVE_ENDIAN);
-        if (i == 0) {
-            sysbus_init_mmio(dev, SYS_TIMER_SIZE, io);
-        } else {
-            sysbus_init_mmio(dev, CPU_TIMER_SIZE, io);
-        }
+        size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE;
+        snprintf(timer_name, sizeof(timer_name), "timer-%i", i);
+        memory_region_init_io(&tc->iomem, &slavio_timer_mem_ops, tc,
+                              timer_name, size);
+        sysbus_init_mmio_region(dev, &tc->iomem);
 
         sysbus_init_irq(dev, &s->cputimer[i].irq);
     }
commit 8bb5ef333ae82632845785265fdb0a5ee52c34b2
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Tue Nov 15 12:14:00 2011 +0100

    slavio_intctl: convert slaves interrupt controllers to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index 0bc2a0b..e7812ed 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -46,6 +46,7 @@
 struct SLAVIO_INTCTLState;
 
 typedef struct SLAVIO_CPUINTCTLState {
+    MemoryRegion iomem;
     struct SLAVIO_INTCTLState *master;
     uint32_t intreg_pending;
     uint32_t cpu;
@@ -77,7 +78,8 @@ typedef struct SLAVIO_INTCTLState {
 static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs);
 
 // per-cpu interrupt controller
-static uint32_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr,
+                                        unsigned size)
 {
     SLAVIO_CPUINTCTLState *s = opaque;
     uint32_t saddr, ret;
@@ -97,7 +99,7 @@ static uint32_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr)
 }
 
 static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr,
-                                     uint32_t val)
+                                     uint64_t val, unsigned size)
 {
     SLAVIO_CPUINTCTLState *s = opaque;
     uint32_t saddr;
@@ -122,16 +124,14 @@ static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const slavio_intctl_mem_read[3] = {
-    NULL,
-    NULL,
-    slavio_intctl_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const slavio_intctl_mem_write[3] = {
-    NULL,
-    NULL,
-    slavio_intctl_mem_writel,
+static const MemoryRegionOps slavio_intctl_mem_ops = {
+    .read = slavio_intctl_mem_readl,
+    .write = slavio_intctl_mem_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 // master system interrupt controller
@@ -422,8 +422,8 @@ static void slavio_intctl_reset(DeviceState *d)
 static int slavio_intctl_init1(SysBusDevice *dev)
 {
     SLAVIO_INTCTLState *s = FROM_SYSBUS(SLAVIO_INTCTLState, dev);
-    int io_memory;
     unsigned int i, j;
+    char slave_name[45];
 
     qdev_init_gpio_in(&dev->qdev, slavio_set_irq_all, 32 + MAX_CPUS);
     memory_region_init_io(&s->iomem, &slavio_intctlm_mem_ops, s,
@@ -431,14 +431,14 @@ static int slavio_intctl_init1(SysBusDevice *dev)
     sysbus_init_mmio_region(dev, &s->iomem);
 
     for (i = 0; i < MAX_CPUS; i++) {
+        snprintf(slave_name, sizeof(slave_name),
+                 "slave-interrupt-controller-%i", i);
         for (j = 0; j < MAX_PILS; j++) {
             sysbus_init_irq(dev, &s->cpu_irqs[i][j]);
         }
-        io_memory = cpu_register_io_memory(slavio_intctl_mem_read,
-                                           slavio_intctl_mem_write,
-                                           &s->slaves[i],
-                                           DEVICE_NATIVE_ENDIAN);
-        sysbus_init_mmio(dev, INTCTL_SIZE, io_memory);
+        memory_region_init_io(&s->slaves[i].iomem, &slavio_intctl_mem_ops,
+                              &s->slaves[i], slave_name, INTCTL_SIZE);
+        sysbus_init_mmio_region(dev, &s->slaves[i].iomem);
         s->slaves[i].cpu = i;
         s->slaves[i].master = s;
     }
commit 13c89a1125feb48a9e21019223fdb99f4d8bcd41
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Tue Nov 15 12:13:59 2011 +0100

    slavio_intctl: convert master interrupt controller to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index 329c251..0bc2a0b 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -54,6 +54,7 @@ typedef struct SLAVIO_CPUINTCTLState {
 
 typedef struct SLAVIO_INTCTLState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
 #ifdef DEBUG_IRQ_COUNT
     uint64_t irq_count[32];
 #endif
@@ -134,7 +135,8 @@ static CPUWriteMemoryFunc * const slavio_intctl_mem_write[3] = {
 };
 
 // master system interrupt controller
-static uint32_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr,
+                                         unsigned size)
 {
     SLAVIO_INTCTLState *s = opaque;
     uint32_t saddr, ret;
@@ -160,7 +162,7 @@ static uint32_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr)
 }
 
 static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr,
-                                      uint32_t val)
+                                      uint64_t val, unsigned size)
 {
     SLAVIO_INTCTLState *s = opaque;
     uint32_t saddr;
@@ -192,16 +194,14 @@ static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const slavio_intctlm_mem_read[3] = {
-    NULL,
-    NULL,
-    slavio_intctlm_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const slavio_intctlm_mem_write[3] = {
-    NULL,
-    NULL,
-    slavio_intctlm_mem_writel,
+static const MemoryRegionOps slavio_intctlm_mem_ops = {
+    .read = slavio_intctlm_mem_readl,
+    .write = slavio_intctlm_mem_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 void slavio_pic_info(Monitor *mon, DeviceState *dev)
@@ -426,10 +426,9 @@ static int slavio_intctl_init1(SysBusDevice *dev)
     unsigned int i, j;
 
     qdev_init_gpio_in(&dev->qdev, slavio_set_irq_all, 32 + MAX_CPUS);
-    io_memory = cpu_register_io_memory(slavio_intctlm_mem_read,
-                                       slavio_intctlm_mem_write, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, INTCTLM_SIZE, io_memory);
+    memory_region_init_io(&s->iomem, &slavio_intctlm_mem_ops, s,
+                          "master-interrupt-controller", INTCTLM_SIZE);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     for (i = 0; i < MAX_CPUS; i++) {
         for (j = 0; j < MAX_PILS; j++) {
commit 40ce02fcd12ddcd1d6c152be3ddebe77713e5f1f
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Tue Nov 15 12:13:58 2011 +0100

    slavio_misc: convert aux2 to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index 7a51e1b..ccc1c53 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -42,6 +42,7 @@ typedef struct MiscState {
     MemoryRegion led_iomem;
     MemoryRegion sysctrl_iomem;
     MemoryRegion aux1_iomem;
+    MemoryRegion aux2_iomem;
     qemu_irq irq;
     qemu_irq fdc_tc;
     uint32_t dummy;
@@ -236,7 +237,7 @@ static const MemoryRegionOps slavio_aux1_mem_ops = {
 };
 
 static void slavio_aux2_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                   uint32_t val)
+                                   uint64_t val, unsigned size)
 {
     MiscState *s = opaque;
 
@@ -251,7 +252,8 @@ static void slavio_aux2_mem_writeb(void *opaque, target_phys_addr_t addr,
     slavio_misc_update_irq(s);
 }
 
-static uint32_t slavio_aux2_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_aux2_mem_readb(void *opaque, target_phys_addr_t addr,
+                                      unsigned size)
 {
     MiscState *s = opaque;
     uint32_t ret = 0;
@@ -261,16 +263,14 @@ static uint32_t slavio_aux2_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static CPUReadMemoryFunc * const slavio_aux2_mem_read[3] = {
-    slavio_aux2_mem_readb,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const slavio_aux2_mem_write[3] = {
-    slavio_aux2_mem_writeb,
-    NULL,
-    NULL,
+static const MemoryRegionOps slavio_aux2_mem_ops = {
+    .read = slavio_aux2_mem_readb,
+    .write = slavio_aux2_mem_writeb,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static void apc_mem_writeb(void *opaque, target_phys_addr_t addr,
@@ -421,7 +421,6 @@ static int apc_init1(SysBusDevice *dev)
 static int slavio_misc_init1(SysBusDevice *dev)
 {
     MiscState *s = FROM_SYSBUS(MiscState, dev);
-    int io;
 
     sysbus_init_irq(dev, &s->irq);
     sysbus_init_irq(dev, &s->fdc_tc);
@@ -460,10 +459,9 @@ static int slavio_misc_init1(SysBusDevice *dev)
     sysbus_init_mmio_region(dev, &s->aux1_iomem);
 
     /* AUX 2 (Software Powerdown Control) */
-    io = cpu_register_io_memory(slavio_aux2_mem_read,
-                                slavio_aux2_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, MISC_SIZE, io);
+    memory_region_init_io(&s->aux2_iomem, &slavio_aux2_mem_ops, s,
+                          "software-powerdown-control", MISC_SIZE);
+    sysbus_init_mmio_region(dev, &s->aux2_iomem);
 
     qdev_init_gpio_in(&dev->qdev, slavio_set_power_fail, 1);
 
commit cccd43c544c300b207f8b049dbed768cf19285b7
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Tue Nov 15 12:13:57 2011 +0100

    slavio_misc: convert aux1 to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index 29eca9b..7a51e1b 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -41,6 +41,7 @@ typedef struct MiscState {
     MemoryRegion mdm_iomem;
     MemoryRegion led_iomem;
     MemoryRegion sysctrl_iomem;
+    MemoryRegion aux1_iomem;
     qemu_irq irq;
     qemu_irq fdc_tc;
     uint32_t dummy;
@@ -197,7 +198,7 @@ static const MemoryRegionOps slavio_mdm_mem_ops = {
 };
 
 static void slavio_aux1_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                   uint32_t val)
+                                   uint64_t val, unsigned size)
 {
     MiscState *s = opaque;
 
@@ -213,7 +214,8 @@ static void slavio_aux1_mem_writeb(void *opaque, target_phys_addr_t addr,
     s->aux1 = val & 0xff;
 }
 
-static uint32_t slavio_aux1_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_aux1_mem_readb(void *opaque, target_phys_addr_t addr,
+                                      unsigned size)
 {
     MiscState *s = opaque;
     uint32_t ret = 0;
@@ -223,16 +225,14 @@ static uint32_t slavio_aux1_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static CPUReadMemoryFunc * const slavio_aux1_mem_read[3] = {
-    slavio_aux1_mem_readb,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const slavio_aux1_mem_write[3] = {
-    slavio_aux1_mem_writeb,
-    NULL,
-    NULL,
+static const MemoryRegionOps slavio_aux1_mem_ops = {
+    .read = slavio_aux1_mem_readb,
+    .write = slavio_aux1_mem_writeb,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static void slavio_aux2_mem_writeb(void *opaque, target_phys_addr_t addr,
@@ -455,10 +455,9 @@ static int slavio_misc_init1(SysBusDevice *dev)
     sysbus_init_mmio_region(dev, &s->sysctrl_iomem);
 
     /* AUX 1 (Misc System Functions) */
-    io = cpu_register_io_memory(slavio_aux1_mem_read,
-                                slavio_aux1_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, MISC_SIZE, io);
+    memory_region_init_io(&s->aux1_iomem, &slavio_aux1_mem_ops, s,
+                          "misc-system-functions", MISC_SIZE);
+    sysbus_init_mmio_region(dev, &s->aux1_iomem);
 
     /* AUX 2 (Software Powerdown Control) */
     io = cpu_register_io_memory(slavio_aux2_mem_read,
commit cd64a524fae457586c35dad53b6216f81fd7bb2c
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Tue Nov 15 12:13:56 2011 +0100

    slavio_misc: convert system control to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index db266ba..29eca9b 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -40,6 +40,7 @@ typedef struct MiscState {
     MemoryRegion diag_iomem;
     MemoryRegion mdm_iomem;
     MemoryRegion led_iomem;
+    MemoryRegion sysctrl_iomem;
     qemu_irq irq;
     qemu_irq fdc_tc;
     uint32_t dummy;
@@ -300,7 +301,8 @@ static const MemoryRegionOps apc_mem_ops = {
     }
 };
 
-static uint32_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr,
+                                         unsigned size)
 {
     MiscState *s = opaque;
     uint32_t ret = 0;
@@ -317,7 +319,7 @@ static uint32_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr)
 }
 
 static void slavio_sysctrl_mem_writel(void *opaque, target_phys_addr_t addr,
-                                      uint32_t val)
+                                      uint64_t val, unsigned size)
 {
     MiscState *s = opaque;
 
@@ -334,16 +336,14 @@ static void slavio_sysctrl_mem_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const slavio_sysctrl_mem_read[3] = {
-    NULL,
-    NULL,
-    slavio_sysctrl_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const slavio_sysctrl_mem_write[3] = {
-    NULL,
-    NULL,
-    slavio_sysctrl_mem_writel,
+static const MemoryRegionOps slavio_sysctrl_mem_ops = {
+    .read = slavio_sysctrl_mem_readl,
+    .write = slavio_sysctrl_mem_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static uint64_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr,
@@ -450,10 +450,9 @@ static int slavio_misc_init1(SysBusDevice *dev)
 
     /* 32 bit registers */
     /* System control */
-    io = cpu_register_io_memory(slavio_sysctrl_mem_read,
-                                slavio_sysctrl_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, SYSCTRL_SIZE, io);
+    memory_region_init_io(&s->sysctrl_iomem, &slavio_sysctrl_mem_ops, s,
+                          "system-control", MISC_SIZE);
+    sysbus_init_mmio_region(dev, &s->sysctrl_iomem);
 
     /* AUX 1 (Misc System Functions) */
     io = cpu_register_io_memory(slavio_aux1_mem_read,
commit aca23c71d306ed5719c90bcb117f2c05a64f3e99
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Tue Nov 15 12:13:55 2011 +0100

    slavio_misc: convert leds to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index 9110c64..db266ba 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -39,6 +39,7 @@ typedef struct MiscState {
     MemoryRegion cfg_iomem;
     MemoryRegion diag_iomem;
     MemoryRegion mdm_iomem;
+    MemoryRegion led_iomem;
     qemu_irq irq;
     qemu_irq fdc_tc;
     uint32_t dummy;
@@ -345,7 +346,8 @@ static CPUWriteMemoryFunc * const slavio_sysctrl_mem_write[3] = {
     slavio_sysctrl_mem_writel,
 };
 
-static uint32_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr,
+                                     unsigned size)
 {
     MiscState *s = opaque;
     uint32_t ret = 0;
@@ -362,7 +364,7 @@ static uint32_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr)
 }
 
 static void slavio_led_mem_writew(void *opaque, target_phys_addr_t addr,
-                                  uint32_t val)
+                                  uint64_t val, unsigned size)
 {
     MiscState *s = opaque;
 
@@ -376,16 +378,14 @@ static void slavio_led_mem_writew(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const slavio_led_mem_read[3] = {
-    NULL,
-    slavio_led_mem_readw,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const slavio_led_mem_write[3] = {
-    NULL,
-    slavio_led_mem_writew,
-    NULL,
+static const MemoryRegionOps slavio_led_mem_ops = {
+    .read = slavio_led_mem_readw,
+    .write = slavio_led_mem_writew,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 2,
+        .max_access_size = 2,
+    },
 };
 
 static const VMStateDescription vmstate_misc = {
@@ -444,10 +444,9 @@ static int slavio_misc_init1(SysBusDevice *dev)
 
     /* 16 bit registers */
     /* ss600mp diag LEDs */
-    io = cpu_register_io_memory(slavio_led_mem_read,
-                                slavio_led_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, MISC_SIZE, io);
+    memory_region_init_io(&s->led_iomem, &slavio_led_mem_ops, s,
+                          "leds", MISC_SIZE);
+    sysbus_init_mmio_region(dev, &s->led_iomem);
 
     /* 32 bit registers */
     /* System control */
commit 2e66ac3d47643779cc35f71e7625cf8536b3307a
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Tue Nov 15 12:13:54 2011 +0100

    slavio_misc: convert modem to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index 60a115d..9110c64 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -38,6 +38,7 @@ typedef struct MiscState {
     SysBusDevice busdev;
     MemoryRegion cfg_iomem;
     MemoryRegion diag_iomem;
+    MemoryRegion mdm_iomem;
     qemu_irq irq;
     qemu_irq fdc_tc;
     uint32_t dummy;
@@ -164,7 +165,7 @@ static const MemoryRegionOps slavio_diag_mem_ops = {
 };
 
 static void slavio_mdm_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                  uint32_t val)
+                                  uint64_t val, unsigned size)
 {
     MiscState *s = opaque;
 
@@ -172,7 +173,8 @@ static void slavio_mdm_mem_writeb(void *opaque, target_phys_addr_t addr,
     s->mctrl = val & 0xff;
 }
 
-static uint32_t slavio_mdm_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_mdm_mem_readb(void *opaque, target_phys_addr_t addr,
+                                     unsigned size)
 {
     MiscState *s = opaque;
     uint32_t ret = 0;
@@ -182,16 +184,14 @@ static uint32_t slavio_mdm_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static CPUReadMemoryFunc * const slavio_mdm_mem_read[3] = {
-    slavio_mdm_mem_readb,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const slavio_mdm_mem_write[3] = {
-    slavio_mdm_mem_writeb,
-    NULL,
-    NULL,
+static const MemoryRegionOps slavio_mdm_mem_ops = {
+    .read = slavio_mdm_mem_readb,
+    .write = slavio_mdm_mem_writeb,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static void slavio_aux1_mem_writeb(void *opaque, target_phys_addr_t addr,
@@ -438,10 +438,9 @@ static int slavio_misc_init1(SysBusDevice *dev)
     sysbus_init_mmio_region(dev, &s->diag_iomem);
 
     /* Modem control */
-    io = cpu_register_io_memory(slavio_mdm_mem_read,
-                                slavio_mdm_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, MISC_SIZE, io);
+    memory_region_init_io(&s->mdm_iomem, &slavio_mdm_mem_ops, s,
+                          "modem", MISC_SIZE);
+    sysbus_init_mmio_region(dev, &s->mdm_iomem);
 
     /* 16 bit registers */
     /* ss600mp diag LEDs */
commit 96891e593e5fa75385d3494adfec7492f2f919fc
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Tue Nov 15 12:13:53 2011 +0100

    slavio_misc: convert diagnostic to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index 7b98f11..60a115d 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -37,6 +37,7 @@
 typedef struct MiscState {
     SysBusDevice busdev;
     MemoryRegion cfg_iomem;
+    MemoryRegion diag_iomem;
     qemu_irq irq;
     qemu_irq fdc_tc;
     uint32_t dummy;
@@ -133,7 +134,7 @@ static const MemoryRegionOps slavio_cfg_mem_ops = {
 };
 
 static void slavio_diag_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                   uint32_t val)
+                                   uint64_t val, unsigned size)
 {
     MiscState *s = opaque;
 
@@ -141,7 +142,8 @@ static void slavio_diag_mem_writeb(void *opaque, target_phys_addr_t addr,
     s->diag = val & 0xff;
 }
 
-static uint32_t slavio_diag_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_diag_mem_readb(void *opaque, target_phys_addr_t addr,
+                                      unsigned size)
 {
     MiscState *s = opaque;
     uint32_t ret = 0;
@@ -151,16 +153,14 @@ static uint32_t slavio_diag_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static CPUReadMemoryFunc * const slavio_diag_mem_read[3] = {
-    slavio_diag_mem_readb,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const slavio_diag_mem_write[3] = {
-    slavio_diag_mem_writeb,
-    NULL,
-    NULL,
+static const MemoryRegionOps slavio_diag_mem_ops = {
+    .read = slavio_diag_mem_readb,
+    .write = slavio_diag_mem_writeb,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static void slavio_mdm_mem_writeb(void *opaque, target_phys_addr_t addr,
@@ -433,10 +433,9 @@ static int slavio_misc_init1(SysBusDevice *dev)
     sysbus_init_mmio_region(dev, &s->cfg_iomem);
 
     /* Diagnostics */
-    io = cpu_register_io_memory(slavio_diag_mem_read,
-                                slavio_diag_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, MISC_SIZE, io);
+    memory_region_init_io(&s->diag_iomem, &slavio_diag_mem_ops, s,
+                          "diagnostic", MISC_SIZE);
+    sysbus_init_mmio_region(dev, &s->diag_iomem);
 
     /* Modem control */
     io = cpu_register_io_memory(slavio_mdm_mem_read,
commit dd703aae47479075a01acde3980d45f2fb2edf74
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Tue Nov 15 12:13:52 2011 +0100

    slavio_misc: convert configuration to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index 7d427f7..7b98f11 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -36,6 +36,7 @@
 
 typedef struct MiscState {
     SysBusDevice busdev;
+    MemoryRegion cfg_iomem;
     qemu_irq irq;
     qemu_irq fdc_tc;
     uint32_t dummy;
@@ -101,7 +102,7 @@ static void slavio_set_power_fail(void *opaque, int irq, int power_failing)
 }
 
 static void slavio_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                  uint32_t val)
+                                  uint64_t val, unsigned size)
 {
     MiscState *s = opaque;
 
@@ -110,7 +111,8 @@ static void slavio_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
     slavio_misc_update_irq(s);
 }
 
-static uint32_t slavio_cfg_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_cfg_mem_readb(void *opaque, target_phys_addr_t addr,
+                                     unsigned size)
 {
     MiscState *s = opaque;
     uint32_t ret = 0;
@@ -120,16 +122,14 @@ static uint32_t slavio_cfg_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static CPUReadMemoryFunc * const slavio_cfg_mem_read[3] = {
-    slavio_cfg_mem_readb,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const slavio_cfg_mem_write[3] = {
-    slavio_cfg_mem_writeb,
-    NULL,
-    NULL,
+static const MemoryRegionOps slavio_cfg_mem_ops = {
+    .read = slavio_cfg_mem_readb,
+    .write = slavio_cfg_mem_writeb,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static void slavio_diag_mem_writeb(void *opaque, target_phys_addr_t addr,
@@ -428,10 +428,9 @@ static int slavio_misc_init1(SysBusDevice *dev)
 
     /* 8 bit registers */
     /* Slavio control */
-    io = cpu_register_io_memory(slavio_cfg_mem_read,
-                                slavio_cfg_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, MISC_SIZE, io);
+    memory_region_init_io(&s->cfg_iomem, &slavio_cfg_mem_ops, s,
+                          "configuration", MISC_SIZE);
+    sysbus_init_mmio_region(dev, &s->cfg_iomem);
 
     /* Diagnostics */
     io = cpu_register_io_memory(slavio_diag_mem_read,
commit 9c48dee672522b1364c40b6afbcc76832a8077ef
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Tue Nov 15 12:13:51 2011 +0100

    slavio_misc: convert apc to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index 1f5a2d7..7d427f7 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -48,6 +48,7 @@ typedef struct MiscState {
 
 typedef struct APCState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     qemu_irq cpu_halt;
 } APCState;
 
@@ -270,7 +271,8 @@ static CPUWriteMemoryFunc * const slavio_aux2_mem_write[3] = {
     NULL,
 };
 
-static void apc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void apc_mem_writeb(void *opaque, target_phys_addr_t addr,
+                           uint64_t val, unsigned size)
 {
     APCState *s = opaque;
 
@@ -278,7 +280,8 @@ static void apc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
     qemu_irq_raise(s->cpu_halt);
 }
 
-static uint32_t apc_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t apc_mem_readb(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     uint32_t ret = 0;
 
@@ -286,16 +289,14 @@ static uint32_t apc_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static CPUReadMemoryFunc * const apc_mem_read[3] = {
-    apc_mem_readb,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const apc_mem_write[3] = {
-    apc_mem_writeb,
-    NULL,
-    NULL,
+static const MemoryRegionOps apc_mem_ops = {
+    .read = apc_mem_readb,
+    .write = apc_mem_writeb,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    }
 };
 
 static uint32_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr)
@@ -407,14 +408,13 @@ static const VMStateDescription vmstate_misc = {
 static int apc_init1(SysBusDevice *dev)
 {
     APCState *s = FROM_SYSBUS(APCState, dev);
-    int io;
 
     sysbus_init_irq(dev, &s->cpu_halt);
 
     /* Power management (APC) XXX: not a Slavio device */
-    io = cpu_register_io_memory(apc_mem_read, apc_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, MISC_SIZE, io);
+    memory_region_init_io(&s->iomem, &apc_mem_ops, s,
+                          "apc", MISC_SIZE);
+    sysbus_init_mmio_region(dev, &s->iomem);
     return 0;
 }
 
commit 0dc31f3b32bda31efce68eb4239b84d1036f5bcd
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Nov 15 12:26:54 2011 +0200

    xilinx_axienet: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index b875aad..a69874b 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -308,6 +308,7 @@ struct TEMAC  {
 
 struct XilinxAXIEnet {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     qemu_irq irq;
     void *dmach;
     NICState *nic;
@@ -411,7 +412,7 @@ static void enet_update_irq(struct XilinxAXIEnet *s)
     qemu_set_irq(s->irq, !!s->regs[R_IP]);
 }
 
-static uint32_t enet_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t enet_read(void *opaque, target_phys_addr_t addr, unsigned size)
 {
     struct XilinxAXIEnet *s = opaque;
     uint32_t r = 0;
@@ -502,8 +503,8 @@ static uint32_t enet_readl(void *opaque, target_phys_addr_t addr)
     return r;
 }
 
-static void
-enet_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void enet_write(void *opaque, target_phys_addr_t addr,
+                       uint64_t value, unsigned size)
 {
     struct XilinxAXIEnet *s = opaque;
     struct TEMAC *t = &s->TEMAC;
@@ -596,7 +597,7 @@ enet_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
 
         default:
             DENET(qemu_log("%s addr=" TARGET_FMT_plx " v=%x\n",
-                           __func__, addr * 4, value));
+                           __func__, addr * 4, (unsigned)value));
             if (addr < ARRAY_SIZE(s->regs)) {
                 s->regs[addr] = value;
             }
@@ -605,16 +606,10 @@ enet_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
     enet_update_irq(s);
 }
 
-static CPUReadMemoryFunc * const enet_read[] = {
-    &enet_readl,
-    &enet_readl,
-    &enet_readl,
-};
-
-static CPUWriteMemoryFunc * const enet_write[] = {
-    &enet_writel,
-    &enet_writel,
-    &enet_writel,
+static const MemoryRegionOps enet_ops = {
+    .read = enet_read,
+    .write = enet_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static int eth_can_rx(VLANClientState *nc)
@@ -847,7 +842,6 @@ static NetClientInfo net_xilinx_enet_info = {
 static int xilinx_enet_init(SysBusDevice *dev)
 {
     struct XilinxAXIEnet *s = FROM_SYSBUS(typeof(*s), dev);
-    int enet_regs;
 
     sysbus_init_irq(dev, &s->irq);
 
@@ -857,9 +851,8 @@ static int xilinx_enet_init(SysBusDevice *dev)
 
     xlx_dma_connect_client(s->dmach, s, axienet_stream_push);
 
-    enet_regs = cpu_register_io_memory(enet_read, enet_write, s,
-                                       DEVICE_LITTLE_ENDIAN);
-    sysbus_init_mmio(dev, 0x40000, enet_regs);
+    memory_region_init_io(&s->iomem, &enet_ops, s, "enet", 0x40000);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     s->nic = qemu_new_nic(&net_xilinx_enet_info, &s->conf,
commit f810bc4ab6847e7ad997fb6045329a30bcf2d0fa
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Nov 15 12:26:54 2011 +0200

    xilinx_axidma: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index 571a5b0..2fd360e 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -91,6 +91,7 @@ struct AXIStream {
 
 struct XilinxAXIDMA {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t freqhz;
     void *dmach;
 
@@ -362,7 +363,8 @@ void axidma_push(void *opaque, unsigned char *buf, size_t len, uint32_t *app)
     stream_update_irq(s);
 }
 
-static uint32_t axidma_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t axidma_read(void *opaque, target_phys_addr_t addr,
+                            unsigned size)
 {
     struct XilinxAXIDMA *d = opaque;
     struct AXIStream *s;
@@ -396,8 +398,8 @@ static uint32_t axidma_readl(void *opaque, target_phys_addr_t addr)
 
 }
 
-static void
-axidma_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void axidma_write(void *opaque, target_phys_addr_t addr,
+                         uint64_t value, unsigned size)
 {
     struct XilinxAXIDMA *d = opaque;
     struct AXIStream *s;
@@ -449,22 +451,15 @@ axidma_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
     stream_update_irq(s);
 }
 
-static CPUReadMemoryFunc * const axidma_read[] = {
-    &axidma_readl,
-    &axidma_readl,
-    &axidma_readl,
-};
-
-static CPUWriteMemoryFunc * const axidma_write[] = {
-    &axidma_writel,
-    &axidma_writel,
-    &axidma_writel,
+static const MemoryRegionOps axidma_ops = {
+    .read = axidma_read,
+    .write = axidma_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int xilinx_axidma_init(SysBusDevice *dev)
 {
     struct XilinxAXIDMA *s = FROM_SYSBUS(typeof(*s), dev);
-    int axidma_regs;
     int i;
 
     sysbus_init_irq(dev, &s->streams[1].irq);
@@ -476,9 +471,9 @@ static int xilinx_axidma_init(SysBusDevice *dev)
 
     xlx_dma_connect_dma(s->dmach, s, axidma_push);
 
-    axidma_regs = cpu_register_io_memory(axidma_read, axidma_write, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4 * 2, axidma_regs);
+    memory_region_init_io(&s->iomem, &axidma_ops, s,
+                          "axidma", R_MAX * 4 * 2);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     for (i = 0; i < 2; i++) {
         stream_reset(&s->streams[i]);
commit 1ce2c9cdfe6e4a687d824f0f3649b843c9942b62
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Nov 15 11:56:16 2011 +0200

    sun4c_intctl: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/sun4c_intctl.c b/hw/sun4c_intctl.c
index 5c7fdef..f4dbf5d 100644
--- a/hw/sun4c_intctl.c
+++ b/hw/sun4c_intctl.c
@@ -46,6 +46,7 @@
 
 typedef struct Sun4c_INTCTLState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
 #ifdef DEBUG_IRQ_COUNT
     uint64_t irq_count;
 #endif
@@ -60,7 +61,8 @@ typedef struct Sun4c_INTCTLState {
 
 static void sun4c_check_interrupts(void *opaque);
 
-static uint32_t sun4c_intctl_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t sun4c_intctl_mem_read(void *opaque, target_phys_addr_t addr,
+                                      unsigned size)
 {
     Sun4c_INTCTLState *s = opaque;
     uint32_t ret;
@@ -71,27 +73,25 @@ static uint32_t sun4c_intctl_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static void sun4c_intctl_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                    uint32_t val)
+static void sun4c_intctl_mem_write(void *opaque, target_phys_addr_t addr,
+                                   uint64_t val, unsigned size)
 {
     Sun4c_INTCTLState *s = opaque;
 
-    DPRINTF("write reg 0x" TARGET_FMT_plx " = %x\n", addr, val);
+    DPRINTF("write reg 0x" TARGET_FMT_plx " = %x\n", addr, (unsigned)val);
     val &= 0xbf;
     s->reg = val;
     sun4c_check_interrupts(s);
 }
 
-static CPUReadMemoryFunc * const sun4c_intctl_mem_read[3] = {
-    sun4c_intctl_mem_readb,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const sun4c_intctl_mem_write[3] = {
-    sun4c_intctl_mem_writeb,
-    NULL,
-    NULL,
+static const MemoryRegionOps sun4c_intctl_mem_ops = {
+    .read = sun4c_intctl_mem_read,
+    .write = sun4c_intctl_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 void sun4c_pic_info(Monitor *mon, void *opaque)
@@ -192,13 +192,11 @@ static void sun4c_intctl_reset(DeviceState *d)
 static int sun4c_intctl_init1(SysBusDevice *dev)
 {
     Sun4c_INTCTLState *s = FROM_SYSBUS(Sun4c_INTCTLState, dev);
-    int io_memory;
     unsigned int i;
 
-    io_memory = cpu_register_io_memory(sun4c_intctl_mem_read,
-                                       sun4c_intctl_mem_write, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, INTCTL_SIZE, io_memory);
+    memory_region_init_io(&s->iomem, &sun4c_intctl_mem_ops, s,
+                          "intctl", INTCTL_SIZE);
+    sysbus_init_mmio_region(dev, &s->iomem);
     qdev_init_gpio_in(&dev->qdev, sun4c_set_irq, 8);
 
     for (i = 0; i < MAX_PILS; i++) {
commit d224136c7b11b17ffda325d411f09429f9893edf
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Nov 15 11:56:16 2011 +0200

    sun4m_iommu: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/sun4m_iommu.c b/hw/sun4m_iommu.c
index 6eeadfa..8ba7e75 100644
--- a/hw/sun4m_iommu.c
+++ b/hw/sun4m_iommu.c
@@ -128,13 +128,15 @@
 
 typedef struct IOMMUState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t regs[IOMMU_NREGS];
     target_phys_addr_t iostart;
     qemu_irq irq;
     uint32_t version;
 } IOMMUState;
 
-static uint32_t iommu_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t iommu_mem_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     IOMMUState *s = opaque;
     target_phys_addr_t saddr;
@@ -155,8 +157,8 @@ static uint32_t iommu_mem_readl(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static void iommu_mem_writel(void *opaque, target_phys_addr_t addr,
-                             uint32_t val)
+static void iommu_mem_write(void *opaque, target_phys_addr_t addr,
+                            uint64_t val, unsigned size)
 {
     IOMMUState *s = opaque;
     target_phys_addr_t saddr;
@@ -237,16 +239,14 @@ static void iommu_mem_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const iommu_mem_read[3] = {
-    NULL,
-    NULL,
-    iommu_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const iommu_mem_write[3] = {
-    NULL,
-    NULL,
-    iommu_mem_writel,
+static const MemoryRegionOps iommu_mem_ops = {
+    .read = iommu_mem_read,
+    .write = iommu_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static uint32_t iommu_page_get_flags(IOMMUState *s, target_phys_addr_t addr)
@@ -347,13 +347,12 @@ static void iommu_reset(DeviceState *d)
 static int iommu_init1(SysBusDevice *dev)
 {
     IOMMUState *s = FROM_SYSBUS(IOMMUState, dev);
-    int io;
 
     sysbus_init_irq(dev, &s->irq);
 
-    io = cpu_register_io_memory(iommu_mem_read, iommu_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, IOMMU_NREGS * sizeof(uint32_t), io);
+    memory_region_init_io(&s->iomem, &iommu_mem_ops, s, "iommu",
+                          IOMMU_NREGS * sizeof(uint32_t));
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     return 0;
 }
commit 847b52c107b7f426e9224b6dda41b1ab72bec1bc
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Nov 14 14:23:17 2011 +0200

    grlib_irqmp: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/grlib_irqmp.c b/hw/grlib_irqmp.c
index 9490a78..dce0bbb 100644
--- a/hw/grlib_irqmp.c
+++ b/hw/grlib_irqmp.c
@@ -49,6 +49,7 @@ typedef struct IRQMPState IRQMPState;
 
 typedef struct IRQMP {
     SysBusDevice busdev;
+    MemoryRegion iomem;
 
     void *set_pil_in;
     void *set_pil_in_opaque;
@@ -161,7 +162,8 @@ void grlib_irqmp_set_irq(void *opaque, int irq, int level)
     }
 }
 
-static uint32_t grlib_irqmp_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t grlib_irqmp_read(void *opaque, target_phys_addr_t addr,
+                                 unsigned size)
 {
     IRQMP      *irqmp = opaque;
     IRQMPState *state;
@@ -224,8 +226,8 @@ static uint32_t grlib_irqmp_readl(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
-static void
-grlib_irqmp_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void grlib_irqmp_write(void *opaque, target_phys_addr_t addr,
+                              uint64_t value, unsigned size)
 {
     IRQMP      *irqmp = opaque;
     IRQMPState *state;
@@ -311,12 +313,14 @@ grlib_irqmp_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
     trace_grlib_irqmp_writel_unknown(addr, value);
 }
 
-static CPUReadMemoryFunc * const grlib_irqmp_read[] = {
-    NULL, NULL, &grlib_irqmp_readl,
-};
-
-static CPUWriteMemoryFunc * const grlib_irqmp_write[] = {
-    NULL, NULL, &grlib_irqmp_writel,
+static const MemoryRegionOps grlib_irqmp_ops = {
+    .read = grlib_irqmp_read,
+    .write = grlib_irqmp_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static void grlib_irqmp_reset(DeviceState *d)
@@ -332,7 +336,6 @@ static void grlib_irqmp_reset(DeviceState *d)
 static int grlib_irqmp_init(SysBusDevice *dev)
 {
     IRQMP *irqmp = FROM_SYSBUS(typeof(*irqmp), dev);
-    int    irqmp_regs;
 
     assert(irqmp != NULL);
 
@@ -341,17 +344,12 @@ static int grlib_irqmp_init(SysBusDevice *dev)
         return -1;
     }
 
-    irqmp_regs = cpu_register_io_memory(grlib_irqmp_read,
-                                        grlib_irqmp_write,
-                                        irqmp, DEVICE_NATIVE_ENDIAN);
+    memory_region_init_io(&irqmp->iomem, &grlib_irqmp_ops, irqmp,
+                          "irqmp", IRQMP_REG_SIZE);
 
     irqmp->state = g_malloc0(sizeof *irqmp->state);
 
-    if (irqmp_regs < 0) {
-        return -1;
-    }
-
-    sysbus_init_mmio(dev, IRQMP_REG_SIZE, irqmp_regs);
+    sysbus_init_mmio_region(dev, &irqmp->iomem);
 
     return 0;
 }
commit cde844fa76b2e3f35b814a73d8d43688283ce8b4
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Nov 14 14:23:17 2011 +0200

    grlib_gptimer: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/grlib_gptimer.c b/hw/grlib_gptimer.c
index 85869b9..c142a5b 100644
--- a/hw/grlib_gptimer.c
+++ b/hw/grlib_gptimer.c
@@ -68,6 +68,7 @@ struct GPTimer {
 
 struct GPTimerUnit {
     SysBusDevice  busdev;
+    MemoryRegion iomem;
 
     uint32_t nr_timers;         /* Number of timers available */
     uint32_t freq_hz;           /* System frequency */
@@ -153,7 +154,8 @@ static void grlib_gptimer_hit(void *opaque)
     }
 }
 
-static uint32_t grlib_gptimer_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t grlib_gptimer_read(void *opaque, target_phys_addr_t addr,
+                                   unsigned size)
 {
     GPTimerUnit        *unit  = opaque;
     target_phys_addr_t  timer_addr;
@@ -211,8 +213,8 @@ static uint32_t grlib_gptimer_readl(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
-static void
-grlib_gptimer_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void grlib_gptimer_write(void *opaque, target_phys_addr_t addr,
+                                uint64_t value, unsigned size)
 {
     GPTimerUnit        *unit = opaque;
     target_phys_addr_t  timer_addr;
@@ -299,12 +301,14 @@ grlib_gptimer_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
     trace_grlib_gptimer_writel(-1, addr, value);
 }
 
-static CPUReadMemoryFunc * const grlib_gptimer_read[] = {
-    NULL, NULL, grlib_gptimer_readl,
-};
-
-static CPUWriteMemoryFunc * const grlib_gptimer_write[] = {
-    NULL, NULL, grlib_gptimer_writel,
+static const MemoryRegionOps grlib_gptimer_ops = {
+    .read = grlib_gptimer_read,
+    .write = grlib_gptimer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static void grlib_gptimer_reset(DeviceState *d)
@@ -340,7 +344,6 @@ static int grlib_gptimer_init(SysBusDevice *dev)
 {
     GPTimerUnit  *unit = FROM_SYSBUS(typeof(*unit), dev);
     unsigned int  i;
-    int           timer_regs;
 
     assert(unit->nr_timers > 0);
     assert(unit->nr_timers <= GPTIMER_MAX_TIMERS);
@@ -361,15 +364,10 @@ static int grlib_gptimer_init(SysBusDevice *dev)
         ptimer_set_freq(timer->ptimer, unit->freq_hz);
     }
 
-    timer_regs = cpu_register_io_memory(grlib_gptimer_read,
-                                        grlib_gptimer_write,
-                                        unit, DEVICE_NATIVE_ENDIAN);
-    if (timer_regs < 0) {
-        return -1;
-    }
+    memory_region_init_io(&unit->iomem, &grlib_gptimer_ops, unit, "gptimer",
+                          UNIT_REG_SIZE + GPTIMER_REG_SIZE * unit->nr_timers);
 
-    sysbus_init_mmio(dev, UNIT_REG_SIZE + GPTIMER_REG_SIZE * unit->nr_timers,
-                     timer_regs);
+    sysbus_init_mmio_region(dev, &unit->iomem);
     return 0;
 }
 
commit 6281f7d11fa6bfb6da3926359fbe70684e582cb1
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Nov 14 13:10:13 2011 +0200

    grlib_apbuart: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
index c90b810..12dbca0 100644
--- a/hw/grlib_apbuart.c
+++ b/hw/grlib_apbuart.c
@@ -67,7 +67,7 @@
 
 typedef struct UART {
     SysBusDevice busdev;
-
+    MemoryRegion iomem;
     qemu_irq irq;
 
     CharDriverState *chr;
@@ -103,7 +103,8 @@ static void grlib_apbuart_event(void *opaque, int event)
 }
 
 static void
-grlib_apbuart_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
+grlib_apbuart_write(void *opaque, target_phys_addr_t addr,
+                    uint64_t value, unsigned size)
 {
     UART          *uart = opaque;
     unsigned char  c    = 0;
@@ -136,18 +137,21 @@ grlib_apbuart_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
     trace_grlib_apbuart_writel_unknown(addr, value);
 }
 
-static CPUReadMemoryFunc * const grlib_apbuart_read[] = {
-    NULL, NULL, NULL,
-};
+static bool grlib_apbuart_accepts(void *opaque, target_phys_addr_t addr,
+                                  unsigned size, bool is_write)
+{
+    return is_write && size == 4;
+}
 
-static CPUWriteMemoryFunc * const grlib_apbuart_write[] = {
-    NULL, NULL, grlib_apbuart_writel,
+static const MemoryRegionOps grlib_apbuart_ops = {
+    .write = grlib_apbuart_write,
+    .valid.accepts = grlib_apbuart_accepts,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int grlib_apbuart_init(SysBusDevice *dev)
 {
     UART *uart      = FROM_SYSBUS(typeof(*uart), dev);
-    int   uart_regs = 0;
 
     qemu_chr_add_handlers(uart->chr,
                           grlib_apbuart_can_receive,
@@ -157,14 +161,10 @@ static int grlib_apbuart_init(SysBusDevice *dev)
 
     sysbus_init_irq(dev, &uart->irq);
 
-    uart_regs = cpu_register_io_memory(grlib_apbuart_read,
-                                       grlib_apbuart_write,
-                                       uart, DEVICE_NATIVE_ENDIAN);
-    if (uart_regs < 0) {
-        return -1;
-    }
+    memory_region_init_io(&uart->iomem, &grlib_apbuart_ops, uart,
+                          "uart", UART_REG_SIZE);
 
-    sysbus_init_mmio(dev, UART_REG_SIZE, uart_regs);
+    sysbus_init_mmio_region(dev, &uart->iomem);
 
     return 0;
 }
commit 4f5c947982137fb235b08b60f63e286ae5680be8
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Nov 14 12:59:29 2011 +0200

    musicpal: avoid call to sysbus_init_mmio()
    
    Instead of calling sysbus_init_mmio() with a null region,
    create a dummy region using the memory API.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/musicpal.c b/hw/musicpal.c
index 20553b5..23acc1d 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1315,6 +1315,7 @@ static SysBusDeviceInfo musicpal_gpio_info = {
 
 typedef struct musicpal_key_state {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t kbd_extended;
     uint32_t pressed_keys;
     qemu_irq out[8];
@@ -1401,7 +1402,8 @@ static int musicpal_key_init(SysBusDevice *dev)
 {
     musicpal_key_state *s = FROM_SYSBUS(musicpal_key_state, dev);
 
-    sysbus_init_mmio(dev, 0x0, 0);
+    memory_region_init(&s->iomem, "dummy", 0);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     s->kbd_extended = 0;
     s->pressed_keys = 0;
commit cffac71b7cc30cc510a5644a7436e6a49e1ecb46
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Nov 14 12:59:29 2011 +0200

    bitbang_i2c: avoid call to sysbus_init_mmio()
    
    Instead of calling sysbus_init_mmio() with a null region,
    create a dummy region using the memory API.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/bitbang_i2c.c b/hw/bitbang_i2c.c
index 431359d..71dd595 100644
--- a/hw/bitbang_i2c.c
+++ b/hw/bitbang_i2c.c
@@ -184,6 +184,7 @@ bitbang_i2c_interface *bitbang_i2c_init(i2c_bus *bus)
 /* GPIO interface.  */
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion dummy_iomem;
     bitbang_i2c_interface *bitbang;
     int last_level;
     qemu_irq out;
@@ -205,7 +206,8 @@ static int gpio_i2c_init(SysBusDevice *dev)
     GPIOI2CState *s = FROM_SYSBUS(GPIOI2CState, dev);
     i2c_bus *bus;
 
-    sysbus_init_mmio(dev, 0x0, 0);
+    memory_region_init(&s->dummy_iomem, "gpio_i2c", 0);
+    sysbus_init_mmio_region(dev, &s->dummy_iomem);
 
     bus = i2c_init_bus(&dev->qdev, "i2c");
     s->bitbang = bitbang_i2c_init(bus);
commit d6c5f066ab6b81f82dfdac6082e5d4176783e5c9
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Nov 14 11:55:27 2011 +0200

    sparc32_dma: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c
index e75694b..7878820 100644
--- a/hw/sparc32_dma.c
+++ b/hw/sparc32_dma.c
@@ -64,6 +64,7 @@ typedef struct DMAState DMAState;
 
 struct DMAState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t dmaregs[DMA_REGS];
     qemu_irq irq;
     void *iommu;
@@ -164,7 +165,8 @@ void espdma_memory_write(void *opaque, uint8_t *buf, int len)
     s->dmaregs[1] += len;
 }
 
-static uint32_t dma_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t dma_mem_read(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
 {
     DMAState *s = opaque;
     uint32_t saddr;
@@ -180,7 +182,8 @@ static uint32_t dma_mem_readl(void *opaque, target_phys_addr_t addr)
     return s->dmaregs[saddr];
 }
 
-static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void dma_mem_write(void *opaque, target_phys_addr_t addr,
+                          uint64_t val, unsigned size)
 {
     DMAState *s = opaque;
     uint32_t saddr;
@@ -234,16 +237,14 @@ static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
-static CPUReadMemoryFunc * const dma_mem_read[3] = {
-    NULL,
-    NULL,
-    dma_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const dma_mem_write[3] = {
-    NULL,
-    NULL,
-    dma_mem_writel,
+static const MemoryRegionOps dma_mem_ops = {
+    .read = dma_mem_read,
+    .write = dma_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static void dma_reset(DeviceState *d)
@@ -268,15 +269,13 @@ static const VMStateDescription vmstate_dma = {
 static int sparc32_dma_init1(SysBusDevice *dev)
 {
     DMAState *s = FROM_SYSBUS(DMAState, dev);
-    int dma_io_memory;
     int reg_size;
 
     sysbus_init_irq(dev, &s->irq);
 
-    dma_io_memory = cpu_register_io_memory(dma_mem_read, dma_mem_write, s,
-                                           DEVICE_NATIVE_ENDIAN);
     reg_size = s->is_ledma ? DMA_ETH_SIZE : DMA_SIZE;
-    sysbus_init_mmio(dev, reg_size, dma_io_memory);
+    memory_region_init_io(&s->iomem, &dma_mem_ops, s, "dma", reg_size);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     qdev_init_gpio_in(&dev->qdev, dma_set_irq, 1);
     qdev_init_gpio_out(&dev->qdev, s->gpio, 2);
commit 00049a1221d755904817c2b79a06d4ac30150cbf
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Nov 14 11:55:27 2011 +0200

    pxa2xx_dma: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c
index 07ec2db..b5d1d61 100644
--- a/hw/pxa2xx_dma.c
+++ b/hw/pxa2xx_dma.c
@@ -28,6 +28,7 @@ typedef struct {
 
 typedef struct PXA2xxDMAState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     qemu_irq irq;
 
     uint32_t stopintr;
@@ -250,11 +251,17 @@ static void pxa2xx_dma_run(PXA2xxDMAState *s)
     }
 }
 
-static uint32_t pxa2xx_dma_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pxa2xx_dma_read(void *opaque, target_phys_addr_t offset,
+                                unsigned size)
 {
     PXA2xxDMAState *s = (PXA2xxDMAState *) opaque;
     unsigned int channel;
 
+    if (size != 4) {
+        hw_error("%s: Bad access width\n", __FUNCTION__);
+        return 5;
+    }
+
     switch (offset) {
     case DRCMR64 ... DRCMR74:
         offset -= DRCMR64 - DRCMR0 - (64 << 2);
@@ -303,12 +310,17 @@ static uint32_t pxa2xx_dma_read(void *opaque, target_phys_addr_t offset)
     return 7;
 }
 
-static void pxa2xx_dma_write(void *opaque,
-                 target_phys_addr_t offset, uint32_t value)
+static void pxa2xx_dma_write(void *opaque, target_phys_addr_t offset,
+                             uint64_t value, unsigned size)
 {
     PXA2xxDMAState *s = (PXA2xxDMAState *) opaque;
     unsigned int channel;
 
+    if (size != 4) {
+        hw_error("%s: Bad access width\n", __FUNCTION__);
+        return;
+    }
+
     switch (offset) {
     case DRCMR64 ... DRCMR74:
         offset -= DRCMR64 - DRCMR0 - (64 << 2);
@@ -319,7 +331,7 @@ static void pxa2xx_dma_write(void *opaque,
         if (value & DRCMR_MAPVLD)
             if ((value & DRCMR_CHLNUM) > s->channels)
                 hw_error("%s: Bad DMA channel %i\n",
-                         __FUNCTION__, value & DRCMR_CHLNUM);
+                         __FUNCTION__, (unsigned)value & DRCMR_CHLNUM);
 
         s->req[channel] = value;
         break;
@@ -402,28 +414,10 @@ static void pxa2xx_dma_write(void *opaque,
     }
 }
 
-static uint32_t pxa2xx_dma_readbad(void *opaque, target_phys_addr_t offset)
-{
-    hw_error("%s: Bad access width\n", __FUNCTION__);
-    return 5;
-}
-
-static void pxa2xx_dma_writebad(void *opaque,
-                 target_phys_addr_t offset, uint32_t value)
-{
-    hw_error("%s: Bad access width\n", __FUNCTION__);
-}
-
-static CPUReadMemoryFunc * const pxa2xx_dma_readfn[] = {
-    pxa2xx_dma_readbad,
-    pxa2xx_dma_readbad,
-    pxa2xx_dma_read
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_dma_writefn[] = {
-    pxa2xx_dma_writebad,
-    pxa2xx_dma_writebad,
-    pxa2xx_dma_write
+static const MemoryRegionOps pxa2xx_dma_ops = {
+    .read = pxa2xx_dma_read,
+    .write = pxa2xx_dma_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void pxa2xx_dma_request(void *opaque, int req_num, int on)
@@ -453,7 +447,7 @@ static void pxa2xx_dma_request(void *opaque, int req_num, int on)
 
 static int pxa2xx_dma_init(SysBusDevice *dev)
 {
-    int i, iomemtype;
+    int i;
     PXA2xxDMAState *s;
     s = FROM_SYSBUS(PXA2xxDMAState, dev);
 
@@ -471,9 +465,9 @@ static int pxa2xx_dma_init(SysBusDevice *dev)
 
     qdev_init_gpio_in(&dev->qdev, pxa2xx_dma_request, PXA2XX_DMA_NUM_REQUESTS);
 
-    iomemtype = cpu_register_io_memory(pxa2xx_dma_readfn,
-                    pxa2xx_dma_writefn, s, DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x00010000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_dma_ops, s,
+                          "pxa2xx.dma", 0x00010000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
     return 0;
commit 838335ecf3a4eeae938d34b334601da06687ceb5
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Nov 14 11:17:21 2011 +0200

    axis_dev88: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 73eb39d..c5405ce 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -39,6 +39,7 @@
 struct nand_state_t
 {
     DeviceState *nand;
+    MemoryRegion iomem;
     unsigned int rdy:1;
     unsigned int ale:1;
     unsigned int cle:1;
@@ -46,7 +47,7 @@ struct nand_state_t
 };
 
 static struct nand_state_t nand_state;
-static uint32_t nand_readl (void *opaque, target_phys_addr_t addr)
+static uint64_t nand_read(void *opaque, target_phys_addr_t addr, unsigned size)
 {
     struct nand_state_t *s = opaque;
     uint32_t r;
@@ -61,31 +62,25 @@ static uint32_t nand_readl (void *opaque, target_phys_addr_t addr)
 }
 
 static void
-nand_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+nand_write(void *opaque, target_phys_addr_t addr, uint64_t value,
+           unsigned size)
 {
     struct nand_state_t *s = opaque;
     int rdy;
 
-    DNAND(printf("%s addr=%x v=%x\n", __func__, addr, value));
+    DNAND(printf("%s addr=%x v=%x\n", __func__, addr, (unsigned)value));
     nand_setpins(s->nand, s->cle, s->ale, s->ce, 1, 0);
     nand_setio(s->nand, value);
     nand_getpins(s->nand, &rdy);
     s->rdy = rdy;
 }
 
-static CPUReadMemoryFunc * const nand_read[] = {
-    &nand_readl,
-    &nand_readl,
-    &nand_readl,
+static const MemoryRegionOps nand_ops = {
+    .read = nand_read,
+    .write = nand_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const nand_write[] = {
-    &nand_writel,
-    &nand_writel,
-    &nand_writel,
-};
-
-
 struct tempsensor_t
 {
     unsigned int shiftreg;
@@ -165,12 +160,13 @@ static void tempsensor_clkedge(struct tempsensor_t *s,
 
 static struct gpio_state_t
 {
+    MemoryRegion iomem;
     struct nand_state_t *nand;
     struct tempsensor_t tempsensor;
     uint32_t regs[0x5c / 4];
 } gpio_state;
 
-static uint32_t gpio_readl (void *opaque, target_phys_addr_t addr)
+static uint64_t gpio_read(void *opaque, target_phys_addr_t addr, unsigned size)
 {
     struct gpio_state_t *s = opaque;
     uint32_t r = 0;
@@ -199,10 +195,11 @@ static uint32_t gpio_readl (void *opaque, target_phys_addr_t addr)
     D(printf("%s %x=%x\n", __func__, addr, r));
 }
 
-static void gpio_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+static void gpio_write(void *opaque, target_phys_addr_t addr, uint64_t value,
+                       unsigned size)
 {
     struct gpio_state_t *s = opaque;
-    D(printf("%s %x=%x\n", __func__, addr, value));
+    D(printf("%s %x=%x\n", __func__, addr, (unsigned)value));
 
     addr >>= 2;
     switch (addr)
@@ -230,14 +227,14 @@ static void gpio_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
     }
 }
 
-static CPUReadMemoryFunc * const gpio_read[] = {
-    NULL, NULL,
-    &gpio_readl,
-};
-
-static CPUWriteMemoryFunc * const gpio_write[] = {
-    NULL, NULL,
-    &gpio_writel,
+static const MemoryRegionOps gpio_ops = {
+    .read = gpio_read,
+    .write = gpio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 #define INTMEM_SIZE (128 * 1024)
@@ -258,8 +255,6 @@ void axisdev88_init (ram_addr_t ram_size,
     void *etraxfs_dmac;
     struct etraxfs_dma_client *dma_eth;
     int i;
-    int nand_regs;
-    int gpio_regs;
     MemoryRegion *address_space_mem = get_system_memory();
     MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
     MemoryRegion *phys_intmem = g_new(MemoryRegion, 1);
@@ -283,14 +278,16 @@ void axisdev88_init (ram_addr_t ram_size,
     nand = drive_get(IF_MTD, 0, 0);
     nand_state.nand = nand_init(nand ? nand->bdrv : NULL,
                                 NAND_MFR_STMICRO, 0x39);
-    nand_regs = cpu_register_io_memory(nand_read, nand_write, &nand_state,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(0x10000000, 0x05000000, nand_regs);
+    memory_region_init_io(&nand_state.iomem, &nand_ops, &nand_state,
+                          "nand", 0x05000000);
+    memory_region_add_subregion(address_space_mem, 0x10000000,
+                                &nand_state.iomem);
 
     gpio_state.nand = &nand_state;
-    gpio_regs = cpu_register_io_memory(gpio_read, gpio_write, &gpio_state,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(0x3001a000, 0x5c, gpio_regs);
+    memory_region_init_io(&gpio_state.iomem, &gpio_ops, &gpio_state,
+                          "gpio", 0x5c);
+    memory_region_add_subregion(address_space_mem, 0x3001a000,
+                                &gpio_state.iomem);
 
 
     cpu_irq = cris_pic_init_cpu(env);
commit 7ef57cca574422ec9a40a489cac646c28a9606e2
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Nov 14 11:17:21 2011 +0200

    eccmemctl: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/eccmemctl.c b/hw/eccmemctl.c
index 2bda87b..56cac25 100644
--- a/hw/eccmemctl.c
+++ b/hw/eccmemctl.c
@@ -122,13 +122,15 @@
 
 typedef struct ECCState {
     SysBusDevice busdev;
+    MemoryRegion iomem, iomem_diag;
     qemu_irq irq;
     uint32_t regs[ECC_NREGS];
     uint8_t diag[ECC_DIAG_SIZE];
     uint32_t version;
 } ECCState;
 
-static void ecc_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void ecc_mem_write(void *opaque, target_phys_addr_t addr, uint64_t val,
+                          unsigned size)
 {
     ECCState *s = opaque;
 
@@ -170,7 +172,8 @@ static void ecc_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
-static uint32_t ecc_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t ecc_mem_read(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
 {
     ECCState *s = opaque;
     uint32_t ret = 0;
@@ -216,20 +219,18 @@ static uint32_t ecc_mem_readl(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static CPUReadMemoryFunc * const ecc_mem_read[3] = {
-    NULL,
-    NULL,
-    ecc_mem_readl,
+static const MemoryRegionOps ecc_mem_ops = {
+    .read = ecc_mem_read,
+    .write = ecc_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
-static CPUWriteMemoryFunc * const ecc_mem_write[3] = {
-    NULL,
-    NULL,
-    ecc_mem_writel,
-};
-
-static void ecc_diag_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                uint32_t val)
+static void ecc_diag_mem_write(void *opaque, target_phys_addr_t addr,
+                               uint64_t val, unsigned size)
 {
     ECCState *s = opaque;
 
@@ -237,7 +238,8 @@ static void ecc_diag_mem_writeb(void *opaque, target_phys_addr_t addr,
     s->diag[addr & ECC_DIAG_MASK] = val;
 }
 
-static uint32_t ecc_diag_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t ecc_diag_mem_read(void *opaque, target_phys_addr_t addr,
+                                  unsigned size)
 {
     ECCState *s = opaque;
     uint32_t ret = s->diag[(int)addr];
@@ -246,16 +248,14 @@ static uint32_t ecc_diag_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static CPUReadMemoryFunc * const ecc_diag_mem_read[3] = {
-    ecc_diag_mem_readb,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const ecc_diag_mem_write[3] = {
-    ecc_diag_mem_writeb,
-    NULL,
-    NULL,
+static const MemoryRegionOps ecc_diag_mem_ops = {
+    .read = ecc_diag_mem_read,
+    .write = ecc_diag_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static const VMStateDescription vmstate_ecc = {
@@ -292,20 +292,17 @@ static void ecc_reset(DeviceState *d)
 
 static int ecc_init1(SysBusDevice *dev)
 {
-    int ecc_io_memory;
     ECCState *s = FROM_SYSBUS(ECCState, dev);
 
     sysbus_init_irq(dev, &s->irq);
     s->regs[0] = s->version;
-    ecc_io_memory = cpu_register_io_memory(ecc_mem_read, ecc_mem_write, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, ECC_SIZE, ecc_io_memory);
+    memory_region_init_io(&s->iomem, &ecc_mem_ops, s, "ecc", ECC_SIZE);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     if (s->version == ECC_MCC) { // SS-600MP only
-        ecc_io_memory = cpu_register_io_memory(ecc_diag_mem_read,
-                                               ecc_diag_mem_write, s,
-                                               DEVICE_NATIVE_ENDIAN);
-        sysbus_init_mmio(dev, ECC_DIAG_SIZE, ecc_io_memory);
+        memory_region_init_io(&s->iomem_diag, &ecc_diag_mem_ops, s,
+                              "ecc.diag", ECC_DIAG_SIZE);
+        sysbus_init_mmio_region(dev, &s->iomem_diag);
     }
 
     return 0;
commit b0a941b02a071574b959b7614f17eb8d366ce863
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 13 15:19:29 2011 +0200

    empty_slot: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/empty_slot.c b/hw/empty_slot.c
index da8adc4..626ba69 100644
--- a/hw/empty_slot.c
+++ b/hw/empty_slot.c
@@ -24,31 +24,27 @@
 
 typedef struct EmptySlot {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint64_t size;
 } EmptySlot;
 
-static uint32_t empty_slot_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t empty_slot_read(void *opaque, target_phys_addr_t addr,
+                                unsigned size)
 {
     DPRINTF("read from " TARGET_FMT_plx "\n", addr);
     return 0;
 }
 
-static void empty_slot_writel(void *opaque, target_phys_addr_t addr,
-                              uint32_t val)
+static void empty_slot_write(void *opaque, target_phys_addr_t addr,
+                             uint64_t val, unsigned size)
 {
-    DPRINTF("write 0x%x to " TARGET_FMT_plx "\n", val, addr);
+    DPRINTF("write 0x%x to " TARGET_FMT_plx "\n", (unsigned)val, addr);
 }
 
-CPUReadMemoryFunc * const empty_slot_read[3] = {
-    empty_slot_readl,
-    empty_slot_readl,
-    empty_slot_readl,
-};
-
-static CPUWriteMemoryFunc * const empty_slot_write[3] = {
-    empty_slot_writel,
-    empty_slot_writel,
-    empty_slot_writel,
+static const MemoryRegionOps empty_slot_ops = {
+    .read = empty_slot_read,
+    .write = empty_slot_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 void empty_slot_init(target_phys_addr_t addr, uint64_t slot_size)
@@ -73,12 +69,10 @@ void empty_slot_init(target_phys_addr_t addr, uint64_t slot_size)
 static int empty_slot_init1(SysBusDevice *dev)
 {
     EmptySlot *s = FROM_SYSBUS(EmptySlot, dev);
-    ram_addr_t empty_slot_offset;
 
-    empty_slot_offset = cpu_register_io_memory(empty_slot_read,
-                                               empty_slot_write, s,
-                                               DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, s->size, empty_slot_offset | IO_MEM_RAM);
+    memory_region_init_io(&s->iomem, &empty_slot_ops, s,
+                          "empty-slot", s->size);
+    sysbus_init_mmio_region(dev, &s->iomem);
     return 0;
 }
 
commit 1c7af35f9612de2078b4309e9fbfa732886b0668
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 13 15:05:28 2011 +0200

    mpc8544_guts: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/mpc8544_guts.c b/hw/mpc8544_guts.c
index c685f3e..00637f6 100644
--- a/hw/mpc8544_guts.c
+++ b/hw/mpc8544_guts.c
@@ -53,11 +53,13 @@
 
 struct GutsState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
 };
 
 typedef struct GutsState GutsState;
 
-static uint32_t mpc8544_guts_read32(void *opaque, target_phys_addr_t addr)
+static uint64_t mpc8544_guts_read(void *opaque, target_phys_addr_t addr,
+                                  unsigned size)
 {
     uint32_t value = 0;
     CPUState *env = cpu_single_env;
@@ -78,14 +80,8 @@ static uint32_t mpc8544_guts_read32(void *opaque, target_phys_addr_t addr)
     return value;
 }
 
-static CPUReadMemoryFunc * const mpc8544_guts_read[] = {
-    NULL,
-    NULL,
-    &mpc8544_guts_read32,
-};
-
-static void mpc8544_guts_write32(void *opaque, target_phys_addr_t addr,
-                              uint32_t value)
+static void mpc8544_guts_write(void *opaque, target_phys_addr_t addr,
+                               uint64_t value, unsigned size)
 {
     addr &= MPC8544_GUTS_MMIO_SIZE - 1;
 
@@ -97,27 +93,30 @@ static void mpc8544_guts_write32(void *opaque, target_phys_addr_t addr,
         break;
     default:
         fprintf(stderr, "guts: Unknown register write: %x = %x\n",
-                (int)addr, value);
+                (int)addr, (unsigned)value);
         break;
     }
 }
 
-static CPUWriteMemoryFunc * const mpc8544_guts_write[] = {
-    NULL,
-    NULL,
-    &mpc8544_guts_write32,
+static const MemoryRegionOps mpc8544_guts_ops = {
+    .read = mpc8544_guts_read,
+    .write = mpc8544_guts_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static int mpc8544_guts_initfn(SysBusDevice *dev)
 {
     GutsState *s;
-    int iomem;
 
     s = FROM_SYSBUS(GutsState, sysbus_from_qdev(dev));
 
-    iomem = cpu_register_io_memory(mpc8544_guts_read, mpc8544_guts_write, s,
-                                   DEVICE_BIG_ENDIAN);
-    sysbus_init_mmio(dev, MPC8544_GUTS_MMIO_SIZE, iomem);
+    memory_region_init_io(&s->iomem, &mpc8544_guts_ops, s,
+                          "mpc6544.guts", MPC8544_GUTS_MMIO_SIZE);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     return 0;
 }
commit 561e182755fe1f994ab43d5e2b95d732b343b407
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 13 15:05:28 2011 +0200

    fw_cfg: convert to memory API
    
    Because the new API doesn't allow overlapping regions with just different
    access sizes, we have to create a new "combined" region for both control
    and data, when the two share an ioport offset.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
index dbcb888..449f6d9 100644
--- a/hw/fw_cfg.c
+++ b/hw/fw_cfg.c
@@ -39,6 +39,7 @@
 #endif
 
 #define FW_CFG_SIZE 2
+#define FW_CFG_DATA_SIZE 1
 
 typedef struct FWCfgEntry {
     uint32_t len;
@@ -49,6 +50,7 @@ typedef struct FWCfgEntry {
 
 struct FWCfgState {
     SysBusDevice busdev;
+    MemoryRegion ctl_iomem, data_iomem, comb_iomem;
     uint32_t ctl_iobase, data_iobase;
     FWCfgEntry entries[2][FW_CFG_MAX_ENTRY];
     FWCfgFiles *files;
@@ -232,60 +234,76 @@ static uint8_t fw_cfg_read(FWCfgState *s)
     return ret;
 }
 
-static uint32_t fw_cfg_io_readb(void *opaque, uint32_t addr)
+static uint64_t fw_cfg_data_mem_read(void *opaque, target_phys_addr_t addr,
+                                     unsigned size)
 {
     return fw_cfg_read(opaque);
 }
 
-static void fw_cfg_io_writeb(void *opaque, uint32_t addr, uint32_t value)
+static void fw_cfg_data_mem_write(void *opaque, target_phys_addr_t addr,
+                                  uint64_t value, unsigned size)
 {
     fw_cfg_write(opaque, (uint8_t)value);
 }
 
-static void fw_cfg_io_writew(void *opaque, uint32_t addr, uint32_t value)
+static void fw_cfg_ctl_mem_write(void *opaque, target_phys_addr_t addr,
+                                 uint64_t value, unsigned size)
 {
     fw_cfg_select(opaque, (uint16_t)value);
 }
 
-static uint32_t fw_cfg_mem_readb(void *opaque, target_phys_addr_t addr)
+static bool fw_cfg_ctl_mem_valid(void *opaque, target_phys_addr_t addr,
+                                 unsigned size, bool is_write)
 {
-    return fw_cfg_read(opaque);
+    return is_write && size == 2;
 }
 
-static void fw_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
-                              uint32_t value)
+static uint64_t fw_cfg_comb_read(void *opaque, target_phys_addr_t addr,
+                                 unsigned size)
 {
-    fw_cfg_write(opaque, (uint8_t)value);
+    return fw_cfg_read(opaque);
 }
 
-static void fw_cfg_mem_writew(void *opaque, target_phys_addr_t addr,
-                              uint32_t value)
+static void fw_cfg_comb_write(void *opaque, target_phys_addr_t addr,
+                              uint64_t value, unsigned size)
 {
-    fw_cfg_select(opaque, (uint16_t)value);
+    switch (size) {
+    case 1:
+        fw_cfg_write(opaque, (uint8_t)value);
+        break;
+    case 2:
+        fw_cfg_select(opaque, (uint16_t)value);
+        break;
+    }
 }
 
-static CPUReadMemoryFunc * const fw_cfg_ctl_mem_read[3] = {
-    NULL,
-    NULL,
-    NULL,
-};
+static bool fw_cfg_comb_valid(void *opaque, target_phys_addr_t addr,
+                                  unsigned size, bool is_write)
+{
+    return (size == 1) || (is_write && size == 2);
+}
 
-static CPUWriteMemoryFunc * const fw_cfg_ctl_mem_write[3] = {
-    NULL,
-    fw_cfg_mem_writew,
-    NULL,
+static const MemoryRegionOps fw_cfg_ctl_mem_ops = {
+    .write = fw_cfg_ctl_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid.accepts = fw_cfg_ctl_mem_valid,
 };
 
-static CPUReadMemoryFunc * const fw_cfg_data_mem_read[3] = {
-    fw_cfg_mem_readb,
-    NULL,
-    NULL,
+static const MemoryRegionOps fw_cfg_data_mem_ops = {
+    .read = fw_cfg_data_mem_read,
+    .write = fw_cfg_data_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
-static CPUWriteMemoryFunc * const fw_cfg_data_mem_write[3] = {
-    fw_cfg_mem_writeb,
-    NULL,
-    NULL,
+static const MemoryRegionOps fw_cfg_comb_mem_ops = {
+    .read = fw_cfg_comb_read,
+    .write = fw_cfg_comb_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid.accepts = fw_cfg_comb_valid,
 };
 
 static void fw_cfg_reset(DeviceState *d)
@@ -489,24 +507,26 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
 static int fw_cfg_init1(SysBusDevice *dev)
 {
     FWCfgState *s = FROM_SYSBUS(FWCfgState, dev);
-    int io_ctl_memory, io_data_memory;
-
-    io_ctl_memory = cpu_register_io_memory(fw_cfg_ctl_mem_read,
-                                           fw_cfg_ctl_mem_write, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, FW_CFG_SIZE, io_ctl_memory);
 
-    io_data_memory = cpu_register_io_memory(fw_cfg_data_mem_read,
-                                            fw_cfg_data_mem_write, s,
-                                            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, FW_CFG_SIZE, io_data_memory);
-
-    if (s->ctl_iobase) {
-        register_ioport_write(s->ctl_iobase, 2, 2, fw_cfg_io_writew, s);
-    }
-    if (s->data_iobase) {
-        register_ioport_read(s->data_iobase, 1, 1, fw_cfg_io_readb, s);
-        register_ioport_write(s->data_iobase, 1, 1, fw_cfg_io_writeb, s);
+    memory_region_init_io(&s->ctl_iomem, &fw_cfg_ctl_mem_ops, s,
+                          "fwcfg.ctl", FW_CFG_SIZE);
+    sysbus_init_mmio_region(dev, &s->ctl_iomem);
+    memory_region_init_io(&s->data_iomem, &fw_cfg_data_mem_ops, s,
+                          "fwcfg.data", FW_CFG_DATA_SIZE);
+    sysbus_init_mmio_region(dev, &s->data_iomem);
+    /* In case ctl and data overlap: */
+    memory_region_init_io(&s->comb_iomem, &fw_cfg_comb_mem_ops, s,
+                          "fwcfg", FW_CFG_SIZE);
+
+    if (s->ctl_iobase + 1 == s->data_iobase) {
+        sysbus_add_io(dev, s->ctl_iobase, &s->comb_iomem);
+    } else {
+        if (s->ctl_iobase) {
+            sysbus_add_io(dev, s->ctl_iobase, &s->ctl_iomem);
+        }
+        if (s->data_iobase) {
+            sysbus_add_io(dev, s->data_iobase, &s->data_iomem);
+        }
     }
     return 0;
 }
commit 67bb53149fcef7fda33ec904ee0f50d3d7913dd4
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 13 13:07:04 2011 +0200

    esp: convert to memory API
    
    [benoit: fix]
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/esp.c b/hw/esp.c
index b698a43..9ab41ba 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -45,6 +45,7 @@ typedef struct ESPState ESPState;
 
 struct ESPState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint8_t rregs[ESP_REGS];
     uint8_t wregs[ESP_REGS];
     qemu_irq irq;
@@ -504,7 +505,8 @@ static void esp_gpio_demux(void *opaque, int irq, int level)
     }
 }
 
-static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t esp_mem_read(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
 {
     ESPState *s = opaque;
     uint32_t saddr, old_val;
@@ -545,7 +547,8 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
     return s->rregs[saddr];
 }
 
-static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void esp_mem_write(void *opaque, target_phys_addr_t addr,
+                          uint64_t val, unsigned size)
 {
     ESPState *s = opaque;
     uint32_t saddr;
@@ -641,7 +644,7 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
             s->rregs[ESP_RINTR] = 0;
             break;
         default:
-            ESP_ERROR("Unhandled ESP command (%2.2x)\n", val);
+            ESP_ERROR("Unhandled ESP command (%2.2x)\n", (unsigned)val);
             break;
         }
         break;
@@ -656,22 +659,23 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
         s->rregs[saddr] = val;
         break;
     default:
-        ESP_ERROR("invalid write of 0x%02x at [0x%x]\n", val, saddr);
+        ESP_ERROR("invalid write of 0x%02x at [0x%x]\n", (unsigned)val, saddr);
         return;
     }
     s->wregs[saddr] = val;
 }
 
-static CPUReadMemoryFunc * const esp_mem_read[3] = {
-    esp_mem_readb,
-    NULL,
-    NULL,
-};
+static bool esp_mem_accepts(void *opaque, target_phys_addr_t addr,
+                            unsigned size, bool is_write)
+{
+    return (size == 1) || (is_write && size == 4);
+}
 
-static CPUWriteMemoryFunc * const esp_mem_write[3] = {
-    esp_mem_writeb,
-    NULL,
-    esp_mem_writeb,
+static const MemoryRegionOps esp_mem_ops = {
+    .read = esp_mem_read,
+    .write = esp_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid.accepts = esp_mem_accepts,
 };
 
 static const VMStateDescription vmstate_esp = {
@@ -735,14 +739,13 @@ static const struct SCSIBusInfo esp_scsi_info = {
 static int esp_init1(SysBusDevice *dev)
 {
     ESPState *s = FROM_SYSBUS(ESPState, dev);
-    int esp_io_memory;
 
     sysbus_init_irq(dev, &s->irq);
     assert(s->it_shift != -1);
 
-    esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, ESP_REGS << s->it_shift, esp_io_memory);
+    memory_region_init_io(&s->iomem, &esp_mem_ops, s,
+                          "esp", ESP_REGS << s->it_shift);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2);
 
commit 897fa7cff21a98b260a5b3e73eae39273fa60272
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 13 13:05:27 2011 +0200

    memory: add MemoryRegionOps::valid.accepts
    
    MemoryRegionOps::valid tries to declaratively specify which transactions
    are accepted by the device/bus, however it is not completely generic.  Add
    a callback for special cases.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/memory.c b/memory.c
index 7c20a07..adfdf14 100644
--- a/memory.c
+++ b/memory.c
@@ -831,8 +831,14 @@ void memory_region_init(MemoryRegion *mr,
 
 static bool memory_region_access_valid(MemoryRegion *mr,
                                        target_phys_addr_t addr,
-                                       unsigned size)
+                                       unsigned size,
+                                       bool is_write)
 {
+    if (mr->ops->valid.accepts
+        && !mr->ops->valid.accepts(mr->opaque, addr, size, is_write)) {
+        return false;
+    }
+
     if (!mr->ops->valid.unaligned && (addr & (size - 1))) {
         return false;
     }
@@ -856,7 +862,7 @@ static uint32_t memory_region_read_thunk_n(void *_mr,
     MemoryRegion *mr = _mr;
     uint64_t data = 0;
 
-    if (!memory_region_access_valid(mr, addr, size)) {
+    if (!memory_region_access_valid(mr, addr, size, false)) {
         return -1U; /* FIXME: better signalling */
     }
 
@@ -880,7 +886,7 @@ static void memory_region_write_thunk_n(void *_mr,
 {
     MemoryRegion *mr = _mr;
 
-    if (!memory_region_access_valid(mr, addr, size)) {
+    if (!memory_region_access_valid(mr, addr, size, true)) {
         return; /* FIXME: better signalling */
     }
 
diff --git a/memory.h b/memory.h
index 7fb36d1..53bf261 100644
--- a/memory.h
+++ b/memory.h
@@ -71,6 +71,13 @@ struct MemoryRegionOps {
          * accesses throw machine checks.
          */
          bool unaligned;
+        /*
+         * If present, and returns #false, the transaction is not accepted
+         * by the device (and results in machine dependent behaviour such
+         * as a machine check exception).
+         */
+        bool (*accepts)(void *opaque, target_phys_addr_t addr,
+                        unsigned size, bool is_write);
     } valid;
     /* Internal implementation constraints: */
     struct {
commit 5a31cd68bad16103beb6d3d4e65d5c401d8e5ff9
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 13 12:16:07 2011 +0200

    m48t59: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/m48t59.c b/hw/m48t59.c
index a77937e..06a3974 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -52,6 +52,7 @@
 struct M48t59State {
     /* Hardware parameters */
     qemu_irq IRQ;
+    MemoryRegion iomem;
     uint32_t io_base;
     uint32_t size;
     /* RTC management */
@@ -573,16 +574,12 @@ static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
     return retval;
 }
 
-static CPUWriteMemoryFunc * const nvram_write[] = {
-    &nvram_writeb,
-    &nvram_writew,
-    &nvram_writel,
-};
-
-static CPUReadMemoryFunc * const nvram_read[] = {
-    &nvram_readb,
-    &nvram_readw,
-    &nvram_readl,
+static const MemoryRegionOps nvram_ops = {
+    .old_mmio = {
+        .read = { nvram_readb, nvram_readw, nvram_readl, },
+        .write = { nvram_writeb, nvram_writew, nvram_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_m48t59 = {
@@ -712,13 +709,11 @@ static int m48t59_init1(SysBusDevice *dev)
 {
     M48t59SysBusState *d = FROM_SYSBUS(M48t59SysBusState, dev);
     M48t59State *s = &d->state;
-    int mem_index;
 
     sysbus_init_irq(dev, &s->IRQ);
 
-    mem_index = cpu_register_io_memory(nvram_read, nvram_write, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, s->size, mem_index);
+    memory_region_init_io(&s->iomem, &nvram_ops, s, "m48t59.nvram", s->size);
+    sysbus_init_mmio_region(dev, &s->iomem);
     m48t59_init_common(s);
 
     return 0;
commit 871321acb35d671afc3eb36c2d88519c2c03d017
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Nov 10 11:24:24 2011 +0200

    ds1225y: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/ds1225y.c b/hw/ds1225y.c
index 6852a61..a93fbe6 100644
--- a/hw/ds1225y.c
+++ b/hw/ds1225y.c
@@ -27,13 +27,14 @@
 
 typedef struct {
     DeviceState qdev;
+    MemoryRegion iomem;
     uint32_t chip_size;
     char *filename;
     FILE *file;
     uint8_t *contents;
 } NvRamState;
 
-static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
+static uint64_t nvram_read(void *opaque, target_phys_addr_t addr, unsigned size)
 {
     NvRamState *s = opaque;
     uint32_t val;
@@ -43,25 +44,8 @@ static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
     return val;
 }
 
-static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-    v = nvram_readb(opaque, addr);
-    v |= nvram_readb(opaque, addr + 1) << 8;
-    return v;
-}
-
-static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-    v = nvram_readb(opaque, addr);
-    v |= nvram_readb(opaque, addr + 1) << 8;
-    v |= nvram_readb(opaque, addr + 2) << 16;
-    v |= nvram_readb(opaque, addr + 3) << 24;
-    return v;
-}
-
-static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t val)
+static void nvram_write(void *opaque, target_phys_addr_t addr, uint64_t val,
+                        unsigned size)
 {
     NvRamState *s = opaque;
 
@@ -76,30 +60,14 @@ static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
-static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    nvram_writeb(opaque, addr, val & 0xff);
-    nvram_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    nvram_writeb(opaque, addr, val & 0xff);
-    nvram_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    nvram_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    nvram_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
-static CPUReadMemoryFunc * const nvram_read[] = {
-    &nvram_readb,
-    &nvram_readw,
-    &nvram_readl,
-};
-
-static CPUWriteMemoryFunc * const nvram_write[] = {
-    &nvram_writeb,
-    &nvram_writew,
-    &nvram_writel,
+static const MemoryRegionOps nvram_ops = {
+    .read = nvram_read,
+    .write = nvram_write,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static int nvram_post_load(void *opaque, int version_id)
@@ -146,13 +114,11 @@ static int nvram_sysbus_initfn(SysBusDevice *dev)
 {
     NvRamState *s = &FROM_SYSBUS(SysBusNvRamState, dev)->nvram;
     FILE *file;
-    int s_io;
 
     s->contents = g_malloc0(s->chip_size);
 
-    s_io = cpu_register_io_memory(nvram_read, nvram_write, s,
-                                  DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, s->chip_size, s_io);
+    memory_region_init_io(&s->iomem, &nvram_ops, s, "nvram", s->chip_size);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     /* Read current file */
     file = fopen(s->filename, "rb");
commit 024e5bb664bda54b393e405f425f10fa9d3fbd1a
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Nov 9 18:22:37 2011 +0200

    dp8393x: convert to memory API
    
    Fixes address space leak on hotunplug.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/dp8393x.c b/hw/dp8393x.c
index f66844b..54f5864 100644
--- a/hw/dp8393x.c
+++ b/hw/dp8393x.c
@@ -156,7 +156,8 @@ typedef struct dp8393xState {
     int64_t wt_last_update;
     NICConf conf;
     NICState *nic;
-    int mmio_index;
+    MemoryRegion *address_space;
+    MemoryRegion mmio;
 
     /* Registers */
     uint8_t cam[16][6];
@@ -664,16 +665,12 @@ static void dp8393x_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     dp8393x_writew(opaque, addr + 2, (val >> 16) & 0xffff);
 }
 
-static CPUReadMemoryFunc * const dp8393x_read[3] = {
-    dp8393x_readb,
-    dp8393x_readw,
-    dp8393x_readl,
-};
-
-static CPUWriteMemoryFunc * const dp8393x_write[3] = {
-    dp8393x_writeb,
-    dp8393x_writew,
-    dp8393x_writel,
+static const MemoryRegionOps dp8393x_ops = {
+    .old_mmio = {
+        .read = { dp8393x_readb, dp8393x_readw, dp8393x_readl, },
+        .write = { dp8393x_writeb, dp8393x_writew, dp8393x_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int nic_can_receive(VLANClientState *nc)
@@ -865,7 +862,8 @@ static void nic_cleanup(VLANClientState *nc)
 {
     dp8393xState *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
-    cpu_unregister_io_memory(s->mmio_index);
+    memory_region_del_subregion(s->address_space, &s->mmio);
+    memory_region_destroy(&s->mmio);
 
     qemu_del_timer(s->watchdog);
     qemu_free_timer(s->watchdog);
@@ -882,6 +880,7 @@ static NetClientInfo net_dp83932_info = {
 };
 
 void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift,
+                  MemoryRegion *address_space,
                   qemu_irq irq, void* mem_opaque,
                   void (*memory_rw)(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write))
 {
@@ -891,6 +890,7 @@ void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift,
 
     s = g_malloc0(sizeof(dp8393xState));
 
+    s->address_space = address_space;
     s->mem_opaque = mem_opaque;
     s->memory_rw = memory_rw;
     s->it_shift = it_shift;
@@ -908,7 +908,7 @@ void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift,
     qemu_register_reset(nic_reset, s);
     nic_reset(s);
 
-    s->mmio_index = cpu_register_io_memory(dp8393x_read, dp8393x_write, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x40 << it_shift, s->mmio_index);
+    memory_region_init_io(&s->mmio, &dp8393x_ops, s,
+                          "dp8393x", 0x40 << it_shift);
+    memory_region_add_subregion(address_space, base, &s->mmio);
 }
diff --git a/hw/mips.h b/hw/mips.h
index 84f4006..22156fc 100644
--- a/hw/mips.h
+++ b/hw/mips.h
@@ -25,6 +25,7 @@ void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
 
 /* dp8393x.c */
 void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift,
+                  MemoryRegion *address_space,
                   qemu_irq irq, void* mem_opaque,
                   void (*memory_rw)(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write));
 
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index e1db841..358de59 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -227,7 +227,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
         if (!nd->model)
             nd->model = g_strdup("dp83932");
         if (strcmp(nd->model, "dp83932") == 0) {
-            dp83932_init(nd, 0x80001000, 2, rc4030[4],
+            dp83932_init(nd, 0x80001000, 2, get_system_memory(), rc4030[4],
                          rc4030_opaque, rc4030_dma_memory_rw);
             break;
         } else if (strcmp(nd->model, "?") == 0) {
commit df182043ab53bb67445b8108b0253bd26995dc8d
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Nov 9 16:10:07 2011 +0200

    cs4321: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/cs4231.c b/hw/cs4231.c
index a65b697..0349838 100644
--- a/hw/cs4231.c
+++ b/hw/cs4231.c
@@ -35,6 +35,7 @@
 
 typedef struct CSState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     qemu_irq irq;
     uint32_t regs[CS_REGS];
     uint8_t dregs[CS_DREGS];
@@ -54,7 +55,8 @@ static void cs_reset(DeviceState *d)
     s->dregs[25] = CS_VER;
 }
 
-static uint32_t cs_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t cs_mem_read(void *opaque, target_phys_addr_t addr,
+                            unsigned size)
 {
     CSState *s = opaque;
     uint32_t saddr, ret;
@@ -80,7 +82,8 @@ static uint32_t cs_mem_readl(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static void cs_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void cs_mem_write(void *opaque, target_phys_addr_t addr,
+                         uint64_t val, unsigned size)
 {
     CSState *s = opaque;
     uint32_t saddr;
@@ -119,16 +122,10 @@ static void cs_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
-static CPUReadMemoryFunc * const cs_mem_read[3] = {
-    cs_mem_readl,
-    cs_mem_readl,
-    cs_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const cs_mem_write[3] = {
-    cs_mem_writel,
-    cs_mem_writel,
-    cs_mem_writel,
+static const MemoryRegionOps cs_mem_ops = {
+    .read = cs_mem_read,
+    .write = cs_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_cs4231 = {
@@ -145,12 +142,10 @@ static const VMStateDescription vmstate_cs4231 = {
 
 static int cs4231_init1(SysBusDevice *dev)
 {
-    int io;
     CSState *s = FROM_SYSBUS(CSState, dev);
 
-    io = cpu_register_io_memory(cs_mem_read, cs_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, CS_SIZE, io);
+    memory_region_init_io(&s->iomem, &cs_mem_ops, s, "cs4321", CS_SIZE);
+    sysbus_init_mmio_region(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
     return 0;
commit 9d7f1b9aa5392a761ee8b84560a7ec0bb61b7ab4
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Nov 9 16:10:07 2011 +0200

    ide/mmio: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/ide.h b/hw/ide.h
index 9059aae..f9f6bd8 100644
--- a/hw/ide.h
+++ b/hw/ide.h
@@ -3,6 +3,7 @@
 
 #include "isa.h"
 #include "pci.h"
+#include "memory.h"
 
 #define MAX_IDE_DEVS	2
 
@@ -24,6 +25,7 @@ MemoryRegion *pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
 
 /* ide-mmio.c */
 void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
+                    MemoryRegion *address_space,
                     qemu_irq irq, int shift,
                     DriveInfo *hd0, DriveInfo *hd1);
 
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
index 2ec21b0..fcfb09e 100644
--- a/hw/ide/mmio.c
+++ b/hw/ide/mmio.c
@@ -37,6 +37,7 @@
 typedef struct {
     IDEBus bus;
     int shift;
+    MemoryRegion iomem1, iomem2;
 } MMIOState;
 
 static void mmio_ide_reset(void *opaque)
@@ -46,7 +47,8 @@ static void mmio_ide_reset(void *opaque)
     ide_bus_reset(&s->bus);
 }
 
-static uint32_t mmio_ide_read (void *opaque, target_phys_addr_t addr)
+static uint64_t mmio_ide_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     MMIOState *s = opaque;
     addr >>= s->shift;
@@ -56,8 +58,8 @@ static uint32_t mmio_ide_read (void *opaque, target_phys_addr_t addr)
         return ide_data_readw(&s->bus, 0);
 }
 
-static void mmio_ide_write (void *opaque, target_phys_addr_t addr,
-	uint32_t val)
+static void mmio_ide_write(void *opaque, target_phys_addr_t addr,
+                           uint64_t val, unsigned size)
 {
     MMIOState *s = opaque;
     addr >>= s->shift;
@@ -67,41 +69,30 @@ static void mmio_ide_write (void *opaque, target_phys_addr_t addr,
         ide_data_writew(&s->bus, 0, val);
 }
 
-static CPUReadMemoryFunc * const mmio_ide_reads[] = {
-    mmio_ide_read,
-    mmio_ide_read,
-    mmio_ide_read,
+static const MemoryRegionOps mmio_ide_ops = {
+    .read = mmio_ide_read,
+    .write = mmio_ide_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const mmio_ide_writes[] = {
-    mmio_ide_write,
-    mmio_ide_write,
-    mmio_ide_write,
-};
-
-static uint32_t mmio_ide_status_read (void *opaque, target_phys_addr_t addr)
+static uint64_t mmio_ide_status_read(void *opaque, target_phys_addr_t addr,
+                                     unsigned size)
 {
     MMIOState *s= opaque;
     return ide_status_read(&s->bus, 0);
 }
 
-static void mmio_ide_cmd_write (void *opaque, target_phys_addr_t addr,
-	uint32_t val)
+static void mmio_ide_cmd_write(void *opaque, target_phys_addr_t addr,
+                               uint64_t val, unsigned size)
 {
     MMIOState *s = opaque;
     ide_cmd_write(&s->bus, 0, val);
 }
 
-static CPUReadMemoryFunc * const mmio_ide_status[] = {
-    mmio_ide_status_read,
-    mmio_ide_status_read,
-    mmio_ide_status_read,
-};
-
-static CPUWriteMemoryFunc * const mmio_ide_cmd[] = {
-    mmio_ide_cmd_write,
-    mmio_ide_cmd_write,
-    mmio_ide_cmd_write,
+static const MemoryRegionOps mmio_ide_cs_ops = {
+    .read = mmio_ide_status_read,
+    .write = mmio_ide_cmd_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_ide_mmio = {
@@ -117,22 +108,22 @@ static const VMStateDescription vmstate_ide_mmio = {
 };
 
 void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
+                    MemoryRegion *address_space,
                     qemu_irq irq, int shift,
                     DriveInfo *hd0, DriveInfo *hd1)
 {
     MMIOState *s = g_malloc0(sizeof(MMIOState));
-    int mem1, mem2;
 
     ide_init2_with_non_qdev_drives(&s->bus, hd0, hd1, irq);
 
     s->shift = shift;
 
-    mem1 = cpu_register_io_memory(mmio_ide_reads, mmio_ide_writes, s,
-                                  DEVICE_NATIVE_ENDIAN);
-    mem2 = cpu_register_io_memory(mmio_ide_status, mmio_ide_cmd, s,
-                                  DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(membase, 16 << shift, mem1);
-    cpu_register_physical_memory(membase2, 2 << shift, mem2);
+    memory_region_init_io(&s->iomem1, &mmio_ide_ops, s,
+                          "ide-mmio.1", 16 << shift);
+    memory_region_init_io(&s->iomem2, &mmio_ide_cs_ops, s,
+                          "ide-mmio.2", 2 << shift);
+    memory_region_add_subregion(address_space, membase, &s->iomem1);
+    memory_region_add_subregion(address_space, membase2, &s->iomem2);
     vmstate_register(NULL, 0, &vmstate_ide_mmio, s);
     qemu_register_reset(mmio_ide_reset, s);
 }
diff --git a/hw/r2d.c b/hw/r2d.c
index b65fd42..a9aefa2 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -260,7 +260,7 @@ static void r2d_init(ram_addr_t ram_size,
 
     /* onboard CF (True IDE mode, Master only). */
     dinfo = drive_get(IF_IDE, 0, 0);
-    mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1,
+    mmio_ide_init(0x14001000, 0x1400080c, address_space_mem, irq[CF_IDE], 1,
                   dinfo, NULL);
 
     /* onboard flash memory */
commit e977aa37043e842e5b398014833e8a78975a8a36
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Nov 9 16:10:07 2011 +0200

    hpet: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/hpet.c b/hw/hpet.c
index 6e6ea52..382b257 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -59,6 +59,7 @@ typedef struct HPETTimer {  /* timers */
 
 typedef struct HPETState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint64_t hpet_offset;
     qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
     uint32_t flags;
@@ -354,7 +355,8 @@ static uint32_t hpet_ram_readw(void *opaque, target_phys_addr_t addr)
 }
 #endif
 
-static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t hpet_ram_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     HPETState *s = opaque;
     uint64_t cur_tick, index;
@@ -425,24 +427,8 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
-#ifdef HPET_DEBUG
-static void hpet_ram_writeb(void *opaque, target_phys_addr_t addr,
-                            uint32_t value)
-{
-    printf("qemu: invalid hpet_write b at %" PRIx64 " = %#x\n",
-           addr, value);
-}
-
-static void hpet_ram_writew(void *opaque, target_phys_addr_t addr,
-                            uint32_t value)
-{
-    printf("qemu: invalid hpet_write w at %" PRIx64 " = %#x\n",
-           addr, value);
-}
-#endif
-
-static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
-                            uint32_t value)
+static void hpet_ram_write(void *opaque, target_phys_addr_t addr,
+                           uint64_t value, unsigned size)
 {
     int i;
     HPETState *s = opaque;
@@ -450,7 +436,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
 
     DPRINTF("qemu: Enter hpet_ram_writel at %" PRIx64 " = %#x\n", addr, value);
     index = addr;
-    old_val = hpet_ram_readl(opaque, addr);
+    old_val = hpet_ram_read(opaque, addr, 4);
     new_val = value;
 
     /*address range of all TN regs*/
@@ -605,26 +591,14 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const hpet_ram_read[] = {
-#ifdef HPET_DEBUG
-    hpet_ram_readb,
-    hpet_ram_readw,
-#else
-    NULL,
-    NULL,
-#endif
-    hpet_ram_readl,
-};
-
-static CPUWriteMemoryFunc * const hpet_ram_write[] = {
-#ifdef HPET_DEBUG
-    hpet_ram_writeb,
-    hpet_ram_writew,
-#else
-    NULL,
-    NULL,
-#endif
-    hpet_ram_writel,
+static const MemoryRegionOps hpet_ram_ops = {
+    .read = hpet_ram_read,
+    .write = hpet_ram_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void hpet_reset(DeviceState *d)
@@ -677,7 +651,7 @@ static void hpet_handle_rtc_irq(void *opaque, int n, int level)
 static int hpet_init(SysBusDevice *dev)
 {
     HPETState *s = FROM_SYSBUS(HPETState, dev);
-    int i, iomemtype;
+    int i;
     HPETTimer *timer;
 
     if (hpet_cfg.count == UINT8_MAX) {
@@ -716,10 +690,8 @@ static int hpet_init(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, hpet_handle_rtc_irq, 1);
 
     /* HPET Area */
-    iomemtype = cpu_register_io_memory(hpet_ram_read,
-                                       hpet_ram_write, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x400, iomemtype);
+    memory_region_init_io(&s->iomem, &hpet_ram_ops, s, "hpet", 0x400);
+    sysbus_init_mmio_region(dev, &s->iomem);
     return 0;
 }
 
commit 3054434d61fa6345cff8c4976b2a1480160f4e96
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 6 19:30:48 2011 +0200

    rc4030: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/mips.h b/hw/mips.h
index 0d4bf25..84f4006 100644
--- a/hw/mips.h
+++ b/hw/mips.h
@@ -20,7 +20,8 @@ void rc4030_dma_read(void *dma, uint8_t *buf, int len);
 void rc4030_dma_write(void *dma, uint8_t *buf, int len);
 
 void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
-                  qemu_irq **irqs, rc4030_dma **dmas);
+                  qemu_irq **irqs, rc4030_dma **dmas,
+                  MemoryRegion *sysmem);
 
 /* dp8393x.c */
 void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift,
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index f6e3316..e1db841 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -177,7 +177,8 @@ static void mips_jazz_init(MemoryRegion *address_space,
     cpu_mips_clock_init(env);
 
     /* Chipset */
-    rc4030_opaque = rc4030_init(env->irq[6], env->irq[3], &rc4030, &dmas);
+    rc4030_opaque = rc4030_init(env->irq[6], env->irq[3], &rc4030, &dmas,
+                                address_space);
     memory_region_init_io(dma_dummy, &dma_dummy_ops, NULL, "dummy_dma", 0x1000);
     memory_region_add_subregion(address_space, 0x8000d000, dma_dummy);
 
diff --git a/hw/rc4030.c b/hw/rc4030.c
index 33e1070..9f39b30 100644
--- a/hw/rc4030.c
+++ b/hw/rc4030.c
@@ -95,6 +95,9 @@ typedef struct rc4030State
 
     qemu_irq timer_irq;
     qemu_irq jazz_bus_irq;
+
+    MemoryRegion iomem_chipset;
+    MemoryRegion iomem_jazzio;
 } rc4030State;
 
 static void set_next_tick(rc4030State *s)
@@ -419,16 +422,12 @@ static void rc4030_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
     rc4030_writel(opaque, addr & ~0x3, val);
 }
 
-static CPUReadMemoryFunc * const rc4030_read[3] = {
-    rc4030_readb,
-    rc4030_readw,
-    rc4030_readl,
-};
-
-static CPUWriteMemoryFunc * const rc4030_write[3] = {
-    rc4030_writeb,
-    rc4030_writew,
-    rc4030_writel,
+static const MemoryRegionOps rc4030_ops = {
+    .old_mmio = {
+        .read = { rc4030_readb, rc4030_readw, rc4030_readl, },
+        .write = { rc4030_writeb, rc4030_writew, rc4030_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void update_jazz_irq(rc4030State *s)
@@ -573,16 +572,12 @@ static void jazzio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     jazzio_writew(opaque, addr + 2, (val >> 16) & 0xffff);
 }
 
-static CPUReadMemoryFunc * const jazzio_read[3] = {
-    jazzio_readb,
-    jazzio_readw,
-    jazzio_readl,
-};
-
-static CPUWriteMemoryFunc * const jazzio_write[3] = {
-    jazzio_writeb,
-    jazzio_writew,
-    jazzio_writel,
+static const MemoryRegionOps jazzio_ops = {
+    .old_mmio = {
+        .read = { jazzio_readb, jazzio_readw, jazzio_readl, },
+        .write = { jazzio_writeb, jazzio_writew, jazzio_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void rc4030_reset(void *opaque)
@@ -801,10 +796,10 @@ static rc4030_dma *rc4030_allocate_dmas(void *opaque, int n)
 }
 
 void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
-                  qemu_irq **irqs, rc4030_dma **dmas)
+                  qemu_irq **irqs, rc4030_dma **dmas,
+                  MemoryRegion *sysmem)
 {
     rc4030State *s;
-    int s_chipset, s_jazzio;
 
     s = g_malloc0(sizeof(rc4030State));
 
@@ -819,12 +814,12 @@ void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
     register_savevm(NULL, "rc4030", 0, 2, rc4030_save, rc4030_load, s);
     rc4030_reset(s);
 
-    s_chipset = cpu_register_io_memory(rc4030_read, rc4030_write, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(0x80000000, 0x300, s_chipset);
-    s_jazzio = cpu_register_io_memory(jazzio_read, jazzio_write, s,
-                                      DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(0xf0000000, 0x00001000, s_jazzio);
+    memory_region_init_io(&s->iomem_chipset, &rc4030_ops, s,
+                          "rc4030.chipset", 0x300);
+    memory_region_add_subregion(sysmem, 0x80000000, &s->iomem_chipset);
+    memory_region_init_io(&s->iomem_jazzio, &jazzio_ops, s,
+                          "rc4030.jazzio", 0x00001000);
+    memory_region_add_subregion(sysmem, 0xf0000000, &s->iomem_jazzio);
 
     return s;
 }
commit 5a6fdd91ce72785593449a0a49e61102f6213c3f
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Sun Oct 30 14:50:19 2011 +0100

    pxa2xx_lcd: convert to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pxa.h b/hw/pxa.h
index 15ac760..e778739 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -78,8 +78,8 @@ DeviceState *pxa27x_dma_init(target_phys_addr_t base, qemu_irq irq);
 
 /* pxa2xx_lcd.c */
 typedef struct PXA2xxLCDState PXA2xxLCDState;
-PXA2xxLCDState *pxa2xx_lcdc_init(target_phys_addr_t base,
-                qemu_irq irq);
+PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
+                target_phys_addr_t base, qemu_irq irq);
 void pxa2xx_lcd_vsync_notifier(PXA2xxLCDState *s, qemu_irq handler);
 void pxa2xx_lcdc_oritentation(void *opaque, int angle);
 
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 5b047aa..668b2b3 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2094,7 +2094,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
                         qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_ICP),
                         serial_hds[i]);
 
-    s->lcd = pxa2xx_lcdc_init(0x44000000,
+    s->lcd = pxa2xx_lcdc_init(address_space, 0x44000000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_LCD));
 
     s->cm_base = 0x41300000;
@@ -2223,7 +2223,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
                         qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_ICP),
                         serial_hds[i]);
 
-    s->lcd = pxa2xx_lcdc_init(0x44000000,
+    s->lcd = pxa2xx_lcdc_init(address_space, 0x44000000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_LCD));
 
     s->cm_base = 0x41300000;
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index b73290c..fd23d63 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -30,6 +30,7 @@ struct DMAChannel {
 };
 
 struct PXA2xxLCDState {
+    MemoryRegion iomem;
     qemu_irq irq;
     int irqlevel;
 
@@ -315,7 +316,8 @@ static void pxa2xx_descriptor_load(PXA2xxLCDState *s)
     }
 }
 
-static uint32_t pxa2xx_lcdc_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pxa2xx_lcdc_read(void *opaque, target_phys_addr_t offset,
+                                 unsigned size)
 {
     PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
     int ch;
@@ -408,8 +410,8 @@ static uint32_t pxa2xx_lcdc_read(void *opaque, target_phys_addr_t offset)
     return 0;
 }
 
-static void pxa2xx_lcdc_write(void *opaque,
-                target_phys_addr_t offset, uint32_t value)
+static void pxa2xx_lcdc_write(void *opaque, target_phys_addr_t offset,
+                              uint64_t value, unsigned size)
 {
     PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
     int ch;
@@ -561,16 +563,10 @@ static void pxa2xx_lcdc_write(void *opaque,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_lcdc_readfn[] = {
-    pxa2xx_lcdc_read,
-    pxa2xx_lcdc_read,
-    pxa2xx_lcdc_read
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_lcdc_writefn[] = {
-    pxa2xx_lcdc_write,
-    pxa2xx_lcdc_write,
-    pxa2xx_lcdc_write
+static const MemoryRegionOps pxa2xx_lcdc_ops = {
+    .read = pxa2xx_lcdc_read,
+    .write = pxa2xx_lcdc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 /* Load new palette for a given DMA channel, convert to internal format */
@@ -981,9 +977,9 @@ static const VMStateDescription vmstate_pxa2xx_lcdc = {
 #define BITS 32
 #include "pxa2xx_template.h"
 
-PXA2xxLCDState *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq)
+PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
+                                 target_phys_addr_t base, qemu_irq irq)
 {
-    int iomemtype;
     PXA2xxLCDState *s;
 
     s = (PXA2xxLCDState *) g_malloc0(sizeof(PXA2xxLCDState));
@@ -992,9 +988,9 @@ PXA2xxLCDState *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq)
 
     pxa2xx_lcdc_orientation(s, graphic_rotate);
 
-    iomemtype = cpu_register_io_memory(pxa2xx_lcdc_readfn,
-                    pxa2xx_lcdc_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x00100000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_lcdc_ops, s,
+                          "pxa2xx-lcd-controller", 0x00100000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     s->ds = graphic_console_init(pxa2xx_update_display,
                                  pxa2xx_invalidate_display,
commit 2bf90458a0eb8c56e331daa61cc0311fc24fcd94
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Sun Oct 30 14:50:18 2011 +0100

    pxa2xx_mmci: convert to memory API
    
    Convert mechanicaly; the access size of the old_mmio fields
    seems odd.
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pxa.h b/hw/pxa.h
index 2732f8f..15ac760 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -85,7 +85,8 @@ void pxa2xx_lcdc_oritentation(void *opaque, int angle);
 
 /* pxa2xx_mmci.c */
 typedef struct PXA2xxMMCIState PXA2xxMMCIState;
-PXA2xxMMCIState *pxa2xx_mmci_init(target_phys_addr_t base,
+PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
+                target_phys_addr_t base,
                 BlockDriverState *bd, qemu_irq irq,
                 qemu_irq rx_dma, qemu_irq tx_dma);
 void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly,
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index cb3c18c..5b047aa 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2072,7 +2072,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
         fprintf(stderr, "qemu: missing SecureDigital device\n");
         exit(1);
     }
-    s->mmc = pxa2xx_mmci_init(0x41100000, dinfo->bdrv,
+    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
                     qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
                     qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
@@ -2201,7 +2201,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
         fprintf(stderr, "qemu: missing SecureDigital device\n");
         exit(1);
     }
-    s->mmc = pxa2xx_mmci_init(0x41100000, dinfo->bdrv,
+    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
                     qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
                     qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
diff --git a/hw/pxa2xx_mmci.c b/hw/pxa2xx_mmci.c
index 1de4979..f47c79c 100644
--- a/hw/pxa2xx_mmci.c
+++ b/hw/pxa2xx_mmci.c
@@ -13,6 +13,7 @@
 #include "qdev.h"
 
 struct PXA2xxMMCIState {
+    MemoryRegion iomem;
     qemu_irq irq;
     qemu_irq rx_dma;
     qemu_irq tx_dma;
@@ -403,12 +404,6 @@ static uint32_t pxa2xx_mmci_readw(void *opaque, target_phys_addr_t offset)
     return pxa2xx_mmci_read(opaque, offset);
 }
 
-static CPUReadMemoryFunc * const pxa2xx_mmci_readfn[] = {
-    pxa2xx_mmci_readb,
-    pxa2xx_mmci_readh,
-    pxa2xx_mmci_readw
-};
-
 static void pxa2xx_mmci_writeb(void *opaque,
                 target_phys_addr_t offset, uint32_t value)
 {
@@ -433,10 +428,16 @@ static void pxa2xx_mmci_writew(void *opaque,
     pxa2xx_mmci_write(opaque, offset, value);
 }
 
-static CPUWriteMemoryFunc * const pxa2xx_mmci_writefn[] = {
-    pxa2xx_mmci_writeb,
-    pxa2xx_mmci_writeh,
-    pxa2xx_mmci_writew
+static const MemoryRegionOps pxa2xx_mmci_ops = {
+    .old_mmio = {
+        .read = { pxa2xx_mmci_readb,
+                  pxa2xx_mmci_readh,
+                  pxa2xx_mmci_readw, },
+        .write = { pxa2xx_mmci_writeb,
+                   pxa2xx_mmci_writeh,
+                   pxa2xx_mmci_writew, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void pxa2xx_mmci_save(QEMUFile *f, void *opaque)
@@ -517,11 +518,11 @@ static int pxa2xx_mmci_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-PXA2xxMMCIState *pxa2xx_mmci_init(target_phys_addr_t base,
+PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
+                target_phys_addr_t base,
                 BlockDriverState *bd, qemu_irq irq,
                 qemu_irq rx_dma, qemu_irq tx_dma)
 {
-    int iomemtype;
     PXA2xxMMCIState *s;
 
     s = (PXA2xxMMCIState *) g_malloc0(sizeof(PXA2xxMMCIState));
@@ -529,9 +530,9 @@ PXA2xxMMCIState *pxa2xx_mmci_init(target_phys_addr_t base,
     s->rx_dma = rx_dma;
     s->tx_dma = tx_dma;
 
-    iomemtype = cpu_register_io_memory(pxa2xx_mmci_readfn,
-                    pxa2xx_mmci_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x00100000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_mmci_ops, s,
+                          "pxa2xx-mmci", 0x00100000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     /* Instantiate the actual storage */
     s->card = sd_init(bd, 0);
commit 90e8e5a32cfe5337f440ed031db2fc5c8ec4c799
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Sun Oct 30 14:50:17 2011 +0100

    pxa2xx_pic: convert to memory API
    
    The ARM documentation say transfers between the cpu and the
    coprocessor are 32 bits wide.
    Use 4 as size for coprocessor read and writes.
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index bdd82e6..13f96a9 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -33,6 +33,7 @@
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     CPUState *cpu_env;
     uint32_t int_enabled[2];
     uint32_t int_pending[2];
@@ -115,7 +116,8 @@ static inline uint32_t pxa2xx_pic_highest(PXA2xxPICState *s) {
     return ichp;
 }
 
-static uint32_t pxa2xx_pic_mem_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pxa2xx_pic_mem_read(void *opaque, target_phys_addr_t offset,
+                                    unsigned size)
 {
     PXA2xxPICState *s = (PXA2xxPICState *) opaque;
 
@@ -155,7 +157,7 @@ static uint32_t pxa2xx_pic_mem_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pxa2xx_pic_mem_write(void *opaque, target_phys_addr_t offset,
-                uint32_t value)
+                                 uint64_t value, unsigned size)
 {
     PXA2xxPICState *s = (PXA2xxPICState *) opaque;
 
@@ -214,7 +216,7 @@ static uint32_t pxa2xx_pic_cp_read(void *opaque, int op2, int reg, int crm)
     }
 
     offset = pxa2xx_cp_reg_map[reg];
-    return pxa2xx_pic_mem_read(opaque, offset);
+    return pxa2xx_pic_mem_read(opaque, offset, 4);
 }
 
 static void pxa2xx_pic_cp_write(void *opaque, int op2, int reg, int crm,
@@ -228,19 +230,13 @@ static void pxa2xx_pic_cp_write(void *opaque, int op2, int reg, int crm,
     }
 
     offset = pxa2xx_cp_reg_map[reg];
-    pxa2xx_pic_mem_write(opaque, offset, value);
+    pxa2xx_pic_mem_write(opaque, offset, value, 4);
 }
 
-static CPUReadMemoryFunc * const pxa2xx_pic_readfn[] = {
-    pxa2xx_pic_mem_read,
-    pxa2xx_pic_mem_read,
-    pxa2xx_pic_mem_read,
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_pic_writefn[] = {
-    pxa2xx_pic_mem_write,
-    pxa2xx_pic_mem_write,
-    pxa2xx_pic_mem_write,
+static const MemoryRegionOps pxa2xx_pic_ops = {
+    .read = pxa2xx_pic_mem_read,
+    .write = pxa2xx_pic_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int pxa2xx_pic_post_load(void *opaque, int version_id)
@@ -252,7 +248,6 @@ static int pxa2xx_pic_post_load(void *opaque, int version_id)
 DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env)
 {
     DeviceState *dev = qdev_create(NULL, "pxa2xx_pic");
-    int iomemtype;
     PXA2xxPICState *s = FROM_SYSBUS(PXA2xxPICState, sysbus_from_qdev(dev));
 
     s->cpu_env = env;
@@ -269,9 +264,9 @@ DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env)
     qdev_init_gpio_in(dev, pxa2xx_pic_set_irq, PXA2XX_PIC_SRCS);
 
     /* Enable IC memory-mapped registers access.  */
-    iomemtype = cpu_register_io_memory(pxa2xx_pic_readfn,
-                    pxa2xx_pic_writefn, s, DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(sysbus_from_qdev(dev), 0x00100000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_pic_ops, s,
+                          "pxa2xx-pic", 0x00100000);
+    sysbus_init_mmio_region(sysbus_from_qdev(dev), &s->iomem);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
 
     /* Enable IC coprocessor access.  */
commit b755bde386144866c02e1db29b054fbe0058996b
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Sun Oct 30 14:50:16 2011 +0100

    pxa2xx_timer: convert to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index 4235e42..0c8e0d3 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -81,6 +81,7 @@ typedef struct {
 
 struct PXA2xxTimerInfo {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t flags;
 
     int32_t clock;
@@ -148,7 +149,8 @@ static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
     qemu_mod_timer(s->tm4[n].tm.qtimer, new_qemu);
 }
 
-static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset,
+                                  unsigned size)
 {
     PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
     int tm = 0;
@@ -226,7 +228,7 @@ static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
-                uint32_t value)
+                               uint64_t value, unsigned size)
 {
     int i, tm = 0;
     PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
@@ -325,16 +327,10 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_timer_readfn[] = {
-    pxa2xx_timer_read,
-    pxa2xx_timer_read,
-    pxa2xx_timer_read,
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_timer_writefn[] = {
-    pxa2xx_timer_write,
-    pxa2xx_timer_write,
-    pxa2xx_timer_write,
+static const MemoryRegionOps pxa2xx_timer_ops = {
+    .read = pxa2xx_timer_read,
+    .write = pxa2xx_timer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void pxa2xx_timer_tick(void *opaque)
@@ -387,7 +383,6 @@ static int pxa25x_timer_post_load(void *opaque, int version_id)
 static int pxa2xx_timer_init(SysBusDevice *dev)
 {
     int i;
-    int iomemtype;
     PXA2xxTimerInfo *s;
 
     s = FROM_SYSBUS(PXA2xxTimerInfo, dev);
@@ -419,9 +414,9 @@ static int pxa2xx_timer_init(SysBusDevice *dev)
         }
     }
 
-    iomemtype = cpu_register_io_memory(pxa2xx_timer_readfn,
-                    pxa2xx_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x00001000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_timer_ops, s,
+                          "pxa2xx-timer", 0x00001000);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     return 0;
 }
commit 6cd816b83f07ef31d39f42165dc5967625a0cc6a
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Sun Oct 30 14:50:15 2011 +0100

    pxa2xx_keypad: convert to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pxa.h b/hw/pxa.h
index fe99a50..2732f8f 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -105,8 +105,9 @@ struct  keymap {
     int row;
 };
 typedef struct PXA2xxKeyPadState PXA2xxKeyPadState;
-PXA2xxKeyPadState *pxa27x_keypad_init(target_phys_addr_t base,
-                qemu_irq irq);
+PXA2xxKeyPadState *pxa27x_keypad_init(MemoryRegion *sysmem,
+                                      target_phys_addr_t base,
+                                      qemu_irq irq);
 void pxa27x_register_keypad(PXA2xxKeyPadState *kp, struct keymap *map,
                 int size);
 
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 70711b3..cb3c18c 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2149,7 +2149,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
                     qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_I2S),
                     qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_I2S));
 
-    s->kp = pxa27x_keypad_init(0x41500000,
+    s->kp = pxa27x_keypad_init(address_space, 0x41500000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_KEYPAD));
 
     /* GPIO1 resets the processor */
diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c
index e33959d..f86323f 100644
--- a/hw/pxa2xx_keypad.c
+++ b/hw/pxa2xx_keypad.c
@@ -80,6 +80,7 @@
 #define PXAKBD_MAXCOL   8
 
 struct PXA2xxKeyPadState {
+    MemoryRegion iomem;
     qemu_irq    irq;
     struct  keymap *map;
     int         pressed_cnt;
@@ -174,7 +175,8 @@ out:
     return;
 }
 
-static uint32_t pxa2xx_keypad_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pxa2xx_keypad_read(void *opaque, target_phys_addr_t offset,
+                                   unsigned size)
 {
     PXA2xxKeyPadState *s = (PXA2xxKeyPadState *) opaque;
     uint32_t tmp;
@@ -235,8 +237,8 @@ static uint32_t pxa2xx_keypad_read(void *opaque, target_phys_addr_t offset)
     return 0;
 }
 
-static void pxa2xx_keypad_write(void *opaque,
-                target_phys_addr_t offset, uint32_t value)
+static void pxa2xx_keypad_write(void *opaque, target_phys_addr_t offset,
+                                uint64_t value, unsigned size)
 {
     PXA2xxKeyPadState *s = (PXA2xxKeyPadState *) opaque;
 
@@ -277,16 +279,10 @@ static void pxa2xx_keypad_write(void *opaque,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_keypad_readfn[] = {
-    pxa2xx_keypad_read,
-    pxa2xx_keypad_read,
-    pxa2xx_keypad_read
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_keypad_writefn[] = {
-    pxa2xx_keypad_write,
-    pxa2xx_keypad_write,
-    pxa2xx_keypad_write
+static const MemoryRegionOps pxa2xx_keypad_ops = {
+    .read = pxa2xx_keypad_read,
+    .write = pxa2xx_keypad_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_pxa2xx_keypad = {
@@ -306,18 +302,18 @@ static const VMStateDescription vmstate_pxa2xx_keypad = {
     }
 };
 
-PXA2xxKeyPadState *pxa27x_keypad_init(target_phys_addr_t base,
-        qemu_irq irq)
+PXA2xxKeyPadState *pxa27x_keypad_init(MemoryRegion *sysmem,
+                                      target_phys_addr_t base,
+                                      qemu_irq irq)
 {
-    int iomemtype;
     PXA2xxKeyPadState *s;
 
     s = (PXA2xxKeyPadState *) g_malloc0(sizeof(PXA2xxKeyPadState));
     s->irq = irq;
 
-    iomemtype = cpu_register_io_memory(pxa2xx_keypad_readfn,
-                    pxa2xx_keypad_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x00100000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_keypad_ops, s,
+                          "pxa2xx-keypad", 0x00100000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     vmstate_register(NULL, 0, &vmstate_pxa2xx_keypad, s);
 
commit 59aee13c8289652c888b29c0374f76b39b14cca5
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Sun Oct 30 14:50:14 2011 +0100

    pxa2xx_pcmcia.c: convert io memory space to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pxa2xx_pcmcia.c b/hw/pxa2xx_pcmcia.c
index e5277ad..dc522dc 100644
--- a/hw/pxa2xx_pcmcia.c
+++ b/hw/pxa2xx_pcmcia.c
@@ -17,6 +17,7 @@ struct PXA2xxPCMCIAState {
     PCMCIACardState *card;
     MemoryRegion common_iomem;
     MemoryRegion attr_iomem;
+    MemoryRegion iomem;
 
     qemu_irq irq;
     qemu_irq cd_irq;
@@ -66,8 +67,8 @@ static void pxa2xx_pcmcia_attr_write(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static uint32_t pxa2xx_pcmcia_io_read(void *opaque,
-                target_phys_addr_t offset)
+static uint64_t pxa2xx_pcmcia_io_read(void *opaque,
+                target_phys_addr_t offset, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
 
@@ -78,8 +79,8 @@ static uint32_t pxa2xx_pcmcia_io_read(void *opaque,
     return 0;
 }
 
-static void pxa2xx_pcmcia_io_write(void *opaque,
-                target_phys_addr_t offset, uint32_t value)
+static void pxa2xx_pcmcia_io_write(void *opaque, target_phys_addr_t offset,
+                                   uint64_t value, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
 
@@ -100,16 +101,10 @@ static const MemoryRegionOps pxa2xx_pcmcia_attr_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN
 };
 
-static CPUReadMemoryFunc * const pxa2xx_pcmcia_io_readfn[] = {
-    pxa2xx_pcmcia_io_read,
-    pxa2xx_pcmcia_io_read,
-    pxa2xx_pcmcia_io_read,
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_pcmcia_io_writefn[] = {
-    pxa2xx_pcmcia_io_write,
-    pxa2xx_pcmcia_io_write,
-    pxa2xx_pcmcia_io_write,
+static const MemoryRegionOps pxa2xx_pcmcia_io_ops = {
+    .read = pxa2xx_pcmcia_io_read,
+    .write = pxa2xx_pcmcia_io_write,
+    .endianness = DEVICE_NATIVE_ENDIAN
 };
 
 static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
@@ -124,16 +119,16 @@ static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
 PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
                                       target_phys_addr_t base)
 {
-    int iomemtype;
     PXA2xxPCMCIAState *s;
 
     s = (PXA2xxPCMCIAState *)
             g_malloc0(sizeof(PXA2xxPCMCIAState));
 
     /* Socket I/O Memory Space */
-    iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_io_readfn,
-                    pxa2xx_pcmcia_io_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base | 0x00000000, 0x04000000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_pcmcia_io_ops, s,
+                          "pxa2xx-pcmcia-io", 0x04000000);
+    memory_region_add_subregion(sysmem, base | 0x00000000,
+                                &s->iomem);
 
     /* Then next 64 MB is reserved */
 
commit 4beeaa718cebb9e1f29b1d02b07430cae9cc5520
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Sun Oct 30 14:50:13 2011 +0100

    pxa2xx_pcmcia.c: convert attribute memory space to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pxa2xx_pcmcia.c b/hw/pxa2xx_pcmcia.c
index 6d1e96c..e5277ad 100644
--- a/hw/pxa2xx_pcmcia.c
+++ b/hw/pxa2xx_pcmcia.c
@@ -11,10 +11,12 @@
 #include "pcmcia.h"
 #include "pxa.h"
 
+
 struct PXA2xxPCMCIAState {
     PCMCIASocket slot;
     PCMCIACardState *card;
     MemoryRegion common_iomem;
+    MemoryRegion attr_iomem;
 
     qemu_irq irq;
     qemu_irq cd_irq;
@@ -42,8 +44,8 @@ static void pxa2xx_pcmcia_common_write(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static uint32_t pxa2xx_pcmcia_attr_read(void *opaque,
-                target_phys_addr_t offset)
+static uint64_t pxa2xx_pcmcia_attr_read(void *opaque,
+                target_phys_addr_t offset, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
 
@@ -54,8 +56,8 @@ static uint32_t pxa2xx_pcmcia_attr_read(void *opaque,
     return 0;
 }
 
-static void pxa2xx_pcmcia_attr_write(void *opaque,
-                target_phys_addr_t offset, uint32_t value)
+static void pxa2xx_pcmcia_attr_write(void *opaque, target_phys_addr_t offset,
+                                     uint64_t value, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
 
@@ -92,16 +94,10 @@ static const MemoryRegionOps pxa2xx_pcmcia_common_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN
 };
 
-static CPUReadMemoryFunc * const pxa2xx_pcmcia_attr_readfn[] = {
-    pxa2xx_pcmcia_attr_read,
-    pxa2xx_pcmcia_attr_read,
-    pxa2xx_pcmcia_attr_read,
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_pcmcia_attr_writefn[] = {
-    pxa2xx_pcmcia_attr_write,
-    pxa2xx_pcmcia_attr_write,
-    pxa2xx_pcmcia_attr_write,
+static const MemoryRegionOps pxa2xx_pcmcia_attr_ops = {
+    .read = pxa2xx_pcmcia_attr_read,
+    .write = pxa2xx_pcmcia_attr_write,
+    .endianness = DEVICE_NATIVE_ENDIAN
 };
 
 static CPUReadMemoryFunc * const pxa2xx_pcmcia_io_readfn[] = {
@@ -142,9 +138,10 @@ PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
     /* Then next 64 MB is reserved */
 
     /* Socket Attribute Memory Space */
-    iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_attr_readfn,
-                    pxa2xx_pcmcia_attr_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base | 0x08000000, 0x04000000, iomemtype);
+    memory_region_init_io(&s->attr_iomem, &pxa2xx_pcmcia_attr_ops, s,
+                          "pxa2xx-pcmcia-attribute", 0x04000000);
+    memory_region_add_subregion(sysmem, base | 0x08000000,
+                                &s->attr_iomem);
 
     /* Socket Common Memory Space */
     memory_region_init_io(&s->common_iomem, &pxa2xx_pcmcia_common_ops, s,
commit 354a8c0676f5f11da0d54098946d195ed8954172
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Sun Oct 30 14:50:12 2011 +0100

    pxa2xx_pcmcia.c: convert common memory space to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pxa.h b/hw/pxa.h
index 7e98384..fe99a50 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -93,7 +93,8 @@ void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly,
 
 /* pxa2xx_pcmcia.c */
 typedef struct PXA2xxPCMCIAState PXA2xxPCMCIAState;
-PXA2xxPCMCIAState *pxa2xx_pcmcia_init(target_phys_addr_t base);
+PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
+                                      target_phys_addr_t base);
 int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card);
 int pxa2xx_pcmcia_dettach(void *opaque);
 void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq);
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index e9a507e..70711b3 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2133,8 +2133,8 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
                         qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
     }
 
-    s->pcmcia[0] = pxa2xx_pcmcia_init(0x20000000);
-    s->pcmcia[1] = pxa2xx_pcmcia_init(0x30000000);
+    s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
+    s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
 
     sysbus_create_simple("pxa2xx_rtc", 0x40900000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_RTCALARM));
@@ -2262,8 +2262,8 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
                         qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
     }
 
-    s->pcmcia[0] = pxa2xx_pcmcia_init(0x20000000);
-    s->pcmcia[1] = pxa2xx_pcmcia_init(0x30000000);
+    s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
+    s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
 
     sysbus_create_simple("pxa2xx_rtc", 0x40900000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_RTCALARM));
diff --git a/hw/pxa2xx_pcmcia.c b/hw/pxa2xx_pcmcia.c
index 74c6817..6d1e96c 100644
--- a/hw/pxa2xx_pcmcia.c
+++ b/hw/pxa2xx_pcmcia.c
@@ -14,13 +14,14 @@
 struct PXA2xxPCMCIAState {
     PCMCIASocket slot;
     PCMCIACardState *card;
+    MemoryRegion common_iomem;
 
     qemu_irq irq;
     qemu_irq cd_irq;
 };
 
-static uint32_t pxa2xx_pcmcia_common_read(void *opaque,
-                target_phys_addr_t offset)
+static uint64_t pxa2xx_pcmcia_common_read(void *opaque,
+                target_phys_addr_t offset, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
 
@@ -31,8 +32,8 @@ static uint32_t pxa2xx_pcmcia_common_read(void *opaque,
     return 0;
 }
 
-static void pxa2xx_pcmcia_common_write(void *opaque,
-                target_phys_addr_t offset, uint32_t value)
+static void pxa2xx_pcmcia_common_write(void *opaque, target_phys_addr_t offset,
+                                       uint64_t value, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
 
@@ -85,16 +86,10 @@ static void pxa2xx_pcmcia_io_write(void *opaque,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_pcmcia_common_readfn[] = {
-    pxa2xx_pcmcia_common_read,
-    pxa2xx_pcmcia_common_read,
-    pxa2xx_pcmcia_common_read,
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_pcmcia_common_writefn[] = {
-    pxa2xx_pcmcia_common_write,
-    pxa2xx_pcmcia_common_write,
-    pxa2xx_pcmcia_common_write,
+static const MemoryRegionOps pxa2xx_pcmcia_common_ops = {
+    .read = pxa2xx_pcmcia_common_read,
+    .write = pxa2xx_pcmcia_common_write,
+    .endianness = DEVICE_NATIVE_ENDIAN
 };
 
 static CPUReadMemoryFunc * const pxa2xx_pcmcia_attr_readfn[] = {
@@ -130,7 +125,8 @@ static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
     qemu_set_irq(s->irq, level);
 }
 
-PXA2xxPCMCIAState *pxa2xx_pcmcia_init(target_phys_addr_t base)
+PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
+                                      target_phys_addr_t base)
 {
     int iomemtype;
     PXA2xxPCMCIAState *s;
@@ -151,9 +147,10 @@ PXA2xxPCMCIAState *pxa2xx_pcmcia_init(target_phys_addr_t base)
     cpu_register_physical_memory(base | 0x08000000, 0x04000000, iomemtype);
 
     /* Socket Common Memory Space */
-    iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_common_readfn,
-                    pxa2xx_pcmcia_common_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base | 0x0c000000, 0x04000000, iomemtype);
+    memory_region_init_io(&s->common_iomem, &pxa2xx_pcmcia_common_ops, s,
+                          "pxa2xx-pcmcia-common", 0x04000000);
+    memory_region_add_subregion(sysmem, base | 0x0c000000,
+                                &s->common_iomem);
 
     if (base == 0x30000000)
         s->slot.slot_string = "PXA PC Card Socket 1";
commit 55a8b801a4be764b3d7a24c4807501a5ec9e323b
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Sun Oct 30 14:50:11 2011 +0100

    pxa2xx_gpio: convert to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index 200b0cf..aed3d4c 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -16,6 +16,7 @@
 typedef struct PXA2xxGPIOInfo PXA2xxGPIOInfo;
 struct PXA2xxGPIOInfo {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     qemu_irq irq0, irq1, irqX;
     int lines;
     int ncpu;
@@ -137,7 +138,8 @@ static void pxa2xx_gpio_handler_update(PXA2xxGPIOInfo *s) {
     }
 }
 
-static uint32_t pxa2xx_gpio_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pxa2xx_gpio_read(void *opaque, target_phys_addr_t offset,
+                                 unsigned size)
 {
     PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
     uint32_t ret;
@@ -188,8 +190,8 @@ static uint32_t pxa2xx_gpio_read(void *opaque, target_phys_addr_t offset)
     return 0;
 }
 
-static void pxa2xx_gpio_write(void *opaque,
-                target_phys_addr_t offset, uint32_t value)
+static void pxa2xx_gpio_write(void *opaque, target_phys_addr_t offset,
+                              uint64_t value, unsigned size)
 {
     PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
     int bank;
@@ -240,16 +242,10 @@ static void pxa2xx_gpio_write(void *opaque,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_gpio_readfn[] = {
-    pxa2xx_gpio_read,
-    pxa2xx_gpio_read,
-    pxa2xx_gpio_read
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_gpio_writefn[] = {
-    pxa2xx_gpio_write,
-    pxa2xx_gpio_write,
-    pxa2xx_gpio_write
+static const MemoryRegionOps pxa_gpio_ops = {
+    .read = pxa2xx_gpio_read,
+    .write = pxa2xx_gpio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
@@ -275,7 +271,6 @@ DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
 
 static int pxa2xx_gpio_initfn(SysBusDevice *dev)
 {
-    int iomemtype;
     PXA2xxGPIOInfo *s;
 
     s = FROM_SYSBUS(PXA2xxGPIOInfo, dev);
@@ -285,10 +280,8 @@ static int pxa2xx_gpio_initfn(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, pxa2xx_gpio_set, s->lines);
     qdev_init_gpio_out(&dev->qdev, s->handler, s->lines);
 
-    iomemtype = cpu_register_io_memory(pxa2xx_gpio_readfn,
-                    pxa2xx_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
-
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa_gpio_ops, s, "pxa2xx-gpio", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq0);
     sysbus_init_irq(dev, &s->irq1);
     sysbus_init_irq(dev, &s->irqX);
commit af687ddc61cfec01ce3d23681d64294dc9aeca20
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Oct 24 22:38:28 2011 +0200

    syborg_virtio: convert to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
index 00c7be8..af0c370 100644
--- a/hw/syborg_virtio.c
+++ b/hw/syborg_virtio.c
@@ -62,6 +62,7 @@ enum {
 typedef struct {
     SysBusDevice busdev;
     VirtIODevice *vdev;
+    MemoryRegion iomem;
     qemu_irq irq;
     uint32_t int_enable;
     uint32_t id;
@@ -223,16 +224,12 @@ static void syborg_virtio_writeb(void *opaque, target_phys_addr_t offset,
     BADF("Bad byte write offset 0x%x\n", (int)offset);
 }
 
-static CPUReadMemoryFunc * const syborg_virtio_readfn[] = {
-     syborg_virtio_readb,
-     syborg_virtio_readw,
-     syborg_virtio_readl
-};
-
-static CPUWriteMemoryFunc * const syborg_virtio_writefn[] = {
-     syborg_virtio_writeb,
-     syborg_virtio_writew,
-     syborg_virtio_writel
+static const MemoryRegionOps syborg_virtio_ops = {
+    .old_mmio = {
+        .read = { syborg_virtio_readb, syborg_virtio_readw, syborg_virtio_readl },
+        .write = { syborg_virtio_writeb, syborg_virtio_writew, syborg_virtio_writel },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void syborg_virtio_update_irq(void *opaque, uint16_t vector)
@@ -258,17 +255,14 @@ static VirtIOBindings syborg_virtio_bindings = {
 
 static int syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)
 {
-    int iomemtype;
-
     proxy->vdev = vdev;
 
     /* Don't support multiple vectors */
     proxy->vdev->nvectors = 0;
     sysbus_init_irq(&proxy->busdev, &proxy->irq);
-    iomemtype = cpu_register_io_memory(syborg_virtio_readfn,
-                                       syborg_virtio_writefn, proxy,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(&proxy->busdev, 0x1000, iomemtype);
+    memory_region_init_io(&proxy->iomem, &syborg_virtio_ops, proxy,
+                          "virtio", 0x1000);
+    sysbus_init_mmio_region(&proxy->busdev, &proxy->iomem);
 
     proxy->id = ((uint32_t)0x1af4 << 16) | vdev->device_id;
 
commit 7d5ebaf00245d41cefda7e5ab5b5a7e3c3df14bb
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Oct 24 22:38:27 2011 +0200

    syborg_timer: convert to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c
index 50c813e..dfee457 100644
--- a/hw/syborg_timer.c
+++ b/hw/syborg_timer.c
@@ -53,6 +53,7 @@ enum {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     ptimer_state *timer;
     int running;
     int oneshot;
@@ -83,7 +84,8 @@ static void syborg_timer_tick(void *opaque)
     syborg_timer_update(s);
 }
 
-static uint32_t syborg_timer_read(void *opaque, target_phys_addr_t offset)
+static uint64_t syborg_timer_read(void *opaque, target_phys_addr_t offset,
+                                  unsigned size)
 {
     SyborgTimerState *s = (SyborgTimerState *)opaque;
 
@@ -114,7 +116,7 @@ static uint32_t syborg_timer_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void syborg_timer_write(void *opaque, target_phys_addr_t offset,
-                               uint32_t value)
+                               uint64_t value, unsigned size)
 {
     SyborgTimerState *s = (SyborgTimerState *)opaque;
 
@@ -162,16 +164,10 @@ static void syborg_timer_write(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static CPUReadMemoryFunc * const syborg_timer_readfn[] = {
-    syborg_timer_read,
-    syborg_timer_read,
-    syborg_timer_read
-};
-
-static CPUWriteMemoryFunc * const syborg_timer_writefn[] = {
-    syborg_timer_write,
-    syborg_timer_write,
-    syborg_timer_write
+static const MemoryRegionOps syborg_timer_ops = {
+    .read = syborg_timer_read,
+    .write = syborg_timer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_syborg_timer = {
@@ -194,17 +190,14 @@ static int syborg_timer_init(SysBusDevice *dev)
 {
     SyborgTimerState *s = FROM_SYSBUS(SyborgTimerState, dev);
     QEMUBH *bh;
-    int iomemtype;
 
     if (s->freq == 0) {
         fprintf(stderr, "syborg_timer: Zero/unset frequency\n");
         exit(1);
     }
     sysbus_init_irq(dev, &s->irq);
-    iomemtype = cpu_register_io_memory(syborg_timer_readfn,
-                                       syborg_timer_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &syborg_timer_ops, s, "timer", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     bh = qemu_bh_new(syborg_timer_tick, s);
     s->timer = ptimer_init(bh);
commit a8a008223cd8e194cd98c049dfaeaaec2ca9f68c
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Oct 24 22:38:26 2011 +0200

    syborg_serial: convert to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
index c83f82c..b73a009 100644
--- a/hw/syborg_serial.c
+++ b/hw/syborg_serial.c
@@ -58,6 +58,7 @@ enum {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t int_enable;
     uint32_t fifo_size;
     uint32_t *read_fifo;
@@ -152,7 +153,8 @@ static void dma_rx_start(SyborgSerialState *s, uint32_t len)
     syborg_serial_update(s);
 }
 
-static uint32_t syborg_serial_read(void *opaque, target_phys_addr_t offset)
+static uint64_t syborg_serial_read(void *opaque, target_phys_addr_t offset,
+                                   unsigned size)
 {
     SyborgSerialState *s = (SyborgSerialState *)opaque;
     uint32_t c;
@@ -192,7 +194,7 @@ static uint32_t syborg_serial_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void syborg_serial_write(void *opaque, target_phys_addr_t offset,
-                                uint32_t value)
+                                uint64_t value, unsigned size)
 {
     SyborgSerialState *s = (SyborgSerialState *)opaque;
     unsigned char ch;
@@ -261,16 +263,10 @@ static void syborg_serial_event(void *opaque, int event)
     /* TODO: Report BREAK events?  */
 }
 
-static CPUReadMemoryFunc * const syborg_serial_readfn[] = {
-     syborg_serial_read,
-     syborg_serial_read,
-     syborg_serial_read
-};
-
-static CPUWriteMemoryFunc * const syborg_serial_writefn[] = {
-     syborg_serial_write,
-     syborg_serial_write,
-     syborg_serial_write
+static const MemoryRegionOps syborg_serial_ops = {
+    .read = syborg_serial_read,
+    .write = syborg_serial_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_syborg_serial = {
@@ -295,13 +291,11 @@ static const VMStateDescription vmstate_syborg_serial = {
 static int syborg_serial_init(SysBusDevice *dev)
 {
     SyborgSerialState *s = FROM_SYSBUS(SyborgSerialState, dev);
-    int iomemtype;
 
     sysbus_init_irq(dev, &s->irq);
-    iomemtype = cpu_register_io_memory(syborg_serial_readfn,
-                                       syborg_serial_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &syborg_serial_ops, s,
+                          "serial", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     s->chr = qdev_init_chardev(&dev->qdev);
     if (s->chr) {
         qemu_chr_add_handlers(s->chr, syborg_serial_can_receive,
commit 43b8c30da260d6f37eb9c580ad9b7e0b33df5a0e
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Oct 24 22:38:25 2011 +0200

    syborg_rtc: convert to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/syborg_rtc.c b/hw/syborg_rtc.c
index 69f6ccf..375664f 100644
--- a/hw/syborg_rtc.c
+++ b/hw/syborg_rtc.c
@@ -35,12 +35,14 @@ enum {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     int64_t offset;
     int64_t data;
     qemu_irq irq;
 } SyborgRTCState;
 
-static uint32_t syborg_rtc_read(void *opaque, target_phys_addr_t offset)
+static uint64_t syborg_rtc_read(void *opaque, target_phys_addr_t offset,
+                                unsigned size)
 {
     SyborgRTCState *s = (SyborgRTCState *)opaque;
     offset &= 0xfff;
@@ -58,7 +60,8 @@ static uint32_t syborg_rtc_read(void *opaque, target_phys_addr_t offset)
     }
 }
 
-static void syborg_rtc_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+static void syborg_rtc_write(void *opaque, target_phys_addr_t offset,
+                             uint64_t value, unsigned size)
 {
     SyborgRTCState *s = (SyborgRTCState *)opaque;
     uint64_t now;
@@ -90,16 +93,10 @@ static void syborg_rtc_write(void *opaque, target_phys_addr_t offset, uint32_t v
     }
 }
 
-static CPUReadMemoryFunc * const syborg_rtc_readfn[] = {
-    syborg_rtc_read,
-    syborg_rtc_read,
-    syborg_rtc_read
-};
-
-static CPUWriteMemoryFunc * const syborg_rtc_writefn[] = {
-    syborg_rtc_write,
-    syborg_rtc_write,
-    syborg_rtc_write
+static const MemoryRegionOps syborg_rtc_ops = {
+    .read = syborg_rtc_read,
+    .write = syborg_rtc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_syborg_rtc = {
@@ -118,12 +115,9 @@ static int syborg_rtc_init(SysBusDevice *dev)
 {
     SyborgRTCState *s = FROM_SYSBUS(SyborgRTCState, dev);
     struct tm tm;
-    int iomemtype;
 
-    iomemtype = cpu_register_io_memory(syborg_rtc_readfn,
-                                       syborg_rtc_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &syborg_rtc_ops, s, "rtc", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     qemu_get_timedate(&tm, 0);
     s->offset = (uint64_t)mktime(&tm) * 1000000000;
commit 9ca9e358e2279acd579bd8c91119db3fd6ee2eea
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Oct 24 22:38:24 2011 +0200

    syborg_pointer: convert to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/syborg_pointer.c b/hw/syborg_pointer.c
index b91214d..a0f8b32 100644
--- a/hw/syborg_pointer.c
+++ b/hw/syborg_pointer.c
@@ -44,6 +44,7 @@ typedef struct {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     int int_enabled;
     uint32_t fifo_size;
     event_data *event_fifo;
@@ -57,7 +58,8 @@ static void syborg_pointer_update(SyborgPointerState *s)
     qemu_set_irq(s->irq, s->read_count && s->int_enabled);
 }
 
-static uint32_t syborg_pointer_read(void *opaque, target_phys_addr_t offset)
+static uint64_t syborg_pointer_read(void *opaque, target_phys_addr_t offset,
+                                    unsigned size)
 {
     SyborgPointerState *s = (SyborgPointerState *)opaque;
 
@@ -87,7 +89,7 @@ static uint32_t syborg_pointer_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void syborg_pointer_write(void *opaque, target_phys_addr_t offset,
-                                 uint32_t value)
+                                 uint64_t value, unsigned size)
 {
     SyborgPointerState *s = (SyborgPointerState *)opaque;
 
@@ -110,16 +112,10 @@ static void syborg_pointer_write(void *opaque, target_phys_addr_t offset,
     syborg_pointer_update(s);
 }
 
-static CPUReadMemoryFunc * const syborg_pointer_readfn[] = {
-   syborg_pointer_read,
-   syborg_pointer_read,
-   syborg_pointer_read
-};
-
-static CPUWriteMemoryFunc * const syborg_pointer_writefn[] = {
-   syborg_pointer_write,
-   syborg_pointer_write,
-   syborg_pointer_write
+static const MemoryRegionOps syborg_pointer_ops = {
+    .read = syborg_pointer_read,
+    .write = syborg_pointer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void syborg_pointer_event(void *opaque, int dx, int dy, int dz,
@@ -186,13 +182,11 @@ static const VMStateDescription vmstate_syborg_pointer = {
 static int syborg_pointer_init(SysBusDevice *dev)
 {
     SyborgPointerState *s = FROM_SYSBUS(SyborgPointerState, dev);
-    int iomemtype;
 
     sysbus_init_irq(dev, &s->irq);
-    iomemtype = cpu_register_io_memory(syborg_pointer_readfn,
-				       syborg_pointer_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &syborg_pointer_ops, s,
+                          "pointer", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     if (s->fifo_size <= 0) {
         fprintf(stderr, "syborg_pointer: fifo too small\n");
commit 6620cb3cc58793752bbbf4ec37fa2810acdeaebf
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Oct 24 22:38:23 2011 +0200

    syborg_keyboard: convert to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c
index 82b9dc0..03d2183 100644
--- a/hw/syborg_keyboard.c
+++ b/hw/syborg_keyboard.c
@@ -51,6 +51,7 @@ enum {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t int_enabled;
     int extension_bit;
     uint32_t fifo_size;
@@ -66,7 +67,8 @@ static void syborg_keyboard_update(SyborgKeyboardState *s)
     qemu_set_irq(s->irq, level);
 }
 
-static uint32_t syborg_keyboard_read(void *opaque, target_phys_addr_t offset)
+static uint64_t syborg_keyboard_read(void *opaque, target_phys_addr_t offset,
+                                    unsigned size)
 {
     SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
     int c;
@@ -104,7 +106,7 @@ static uint32_t syborg_keyboard_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void syborg_keyboard_write(void *opaque, target_phys_addr_t offset,
-                                  uint32_t value)
+                                  uint64_t value, unsigned size)
 {
     SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
 
@@ -121,16 +123,10 @@ static void syborg_keyboard_write(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static CPUReadMemoryFunc * const syborg_keyboard_readfn[] = {
-     syborg_keyboard_read,
-     syborg_keyboard_read,
-     syborg_keyboard_read
-};
-
-static CPUWriteMemoryFunc * const syborg_keyboard_writefn[] = {
-     syborg_keyboard_write,
-     syborg_keyboard_write,
-     syborg_keyboard_write
+static const MemoryRegionOps syborg_keyboard_ops = {
+    .read = syborg_keyboard_read,
+    .write = syborg_keyboard_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void syborg_keyboard_event(void *opaque, int keycode)
@@ -184,13 +180,11 @@ static const VMStateDescription vmstate_syborg_keyboard = {
 static int syborg_keyboard_init(SysBusDevice *dev)
 {
     SyborgKeyboardState *s = FROM_SYSBUS(SyborgKeyboardState, dev);
-    int iomemtype;
 
     sysbus_init_irq(dev, &s->irq);
-    iomemtype = cpu_register_io_memory(syborg_keyboard_readfn,
-                                       syborg_keyboard_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &syborg_keyboard_ops, s,
+                              "keyboard", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     if (s->fifo_size <= 0) {
         fprintf(stderr, "syborg_keyboard: fifo too small\n");
         s->fifo_size = 16;
commit 9cc600761a5ac79bc72983d5b4c91943eada3043
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Oct 24 22:38:22 2011 +0200

    syborg_interrupt: convert to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/syborg_interrupt.c b/hw/syborg_interrupt.c
index 1b0f3bb..512910a 100644
--- a/hw/syborg_interrupt.c
+++ b/hw/syborg_interrupt.c
@@ -55,6 +55,7 @@ typedef struct {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     int pending_count;
     uint32_t num_irqs;
     syborg_int_flags *flags;
@@ -84,7 +85,8 @@ static void syborg_int_set_irq(void *opaque, int irq, int level)
     }
 }
 
-static uint32_t syborg_int_read(void *opaque, target_phys_addr_t offset)
+static uint64_t syborg_int_read(void *opaque, target_phys_addr_t offset,
+                                unsigned size)
 {
     SyborgIntState *s = (SyborgIntState *)opaque;
     int i;
@@ -114,7 +116,8 @@ static uint32_t syborg_int_read(void *opaque, target_phys_addr_t offset)
     }
 }
 
-static void syborg_int_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+static void syborg_int_write(void *opaque, target_phys_addr_t offset,
+                             uint64_t value, unsigned size)
 {
     SyborgIntState *s = (SyborgIntState *)opaque;
     int i;
@@ -156,16 +159,10 @@ static void syborg_int_write(void *opaque, target_phys_addr_t offset, uint32_t v
     syborg_int_update(s);
 }
 
-static CPUReadMemoryFunc * const syborg_int_readfn[] = {
-    syborg_int_read,
-    syborg_int_read,
-    syborg_int_read
-};
-
-static CPUWriteMemoryFunc * const syborg_int_writefn[] = {
-    syborg_int_write,
-    syborg_int_write,
-    syborg_int_write
+static const MemoryRegionOps syborg_int_ops = {
+    .read = syborg_int_read,
+    .write = syborg_int_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void syborg_int_save(QEMUFile *f, void *opaque)
@@ -205,14 +202,12 @@ static int syborg_int_load(QEMUFile *f, void *opaque, int version_id)
 static int syborg_int_init(SysBusDevice *dev)
 {
     SyborgIntState *s = FROM_SYSBUS(SyborgIntState, dev);
-    int iomemtype;
 
     sysbus_init_irq(dev, &s->parent_irq);
     qdev_init_gpio_in(&dev->qdev, syborg_int_set_irq, s->num_irqs);
-    iomemtype = cpu_register_io_memory(syborg_int_readfn,
-                                       syborg_int_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &syborg_int_ops, s,
+                          "interrupt", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     s->flags = g_malloc0(s->num_irqs * sizeof(syborg_int_flags));
 
     register_savevm(&dev->qdev, "syborg_int", -1, 1, syborg_int_save,
commit 0520a049691fb3f55bfb739a470e0c204c9dbb9a
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Oct 24 22:38:21 2011 +0200

    syborg_fb: convert to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/syborg_fb.c b/hw/syborg_fb.c
index ae3e0eb..3b71c72 100644
--- a/hw/syborg_fb.c
+++ b/hw/syborg_fb.c
@@ -65,6 +65,7 @@ enum {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     DisplayState *ds;
     /*QEMUConsole *console;*/
     uint32_t need_update : 1;
@@ -294,7 +295,8 @@ static void syborg_fb_invalidate_display(void * opaque)
     s->need_update = 1;
 }
 
-static uint32_t syborg_fb_read(void *opaque, target_phys_addr_t offset)
+static uint64_t syborg_fb_read(void *opaque, target_phys_addr_t offset,
+                               unsigned size)
 {
     SyborgFBState *s = opaque;
 
@@ -366,7 +368,7 @@ static uint32_t syborg_fb_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void syborg_fb_write(void *opaque, target_phys_addr_t offset,
-                            uint32_t val)
+                            uint64_t val, unsigned size)
 {
     SyborgFBState *s = opaque;
 
@@ -454,16 +456,10 @@ static void syborg_fb_write(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static CPUReadMemoryFunc * const syborg_fb_readfn[] = {
-    syborg_fb_read,
-    syborg_fb_read,
-    syborg_fb_read
-};
-
-static CPUWriteMemoryFunc * const syborg_fb_writefn[] = {
-    syborg_fb_write,
-    syborg_fb_write,
-    syborg_fb_write
+static const MemoryRegionOps syborg_fb_ops = {
+    .read = syborg_fb_read,
+    .write = syborg_fb_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void syborg_fb_save(QEMUFile *f, void *opaque)
@@ -515,13 +511,11 @@ static int syborg_fb_load(QEMUFile *f, void *opaque, int version_id)
 static int syborg_fb_init(SysBusDevice *dev)
 {
     SyborgFBState *s = FROM_SYSBUS(SyborgFBState, dev);
-    int iomemtype;
 
     sysbus_init_irq(dev, &s->irq);
-    iomemtype = cpu_register_io_memory(syborg_fb_readfn,
-                                       syborg_fb_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &syborg_fb_ops, s,
+                          "framebuffer", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     s->ds = graphic_console_init(syborg_fb_update_display,
                                  syborg_fb_invalidate_display,
commit b9441ebbfffc1b37519043fe67ee011d2f60cc67
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Oct 24 22:38:20 2011 +0200

    mst_fpga: convert to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index 7bcd5d7..cf9957b 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -34,6 +34,7 @@
 
 typedef struct mst_irq_state{
 	SysBusDevice busdev;
+	MemoryRegion iomem;
 
 	qemu_irq parent;
 
@@ -86,8 +87,8 @@ mst_fpga_set_irq(void *opaque, int irq, int level)
 }
 
 
-static uint32_t
-mst_fpga_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t
+mst_fpga_readb(void *opaque, target_phys_addr_t addr, unsigned size)
 {
 	mst_irq_state *s = (mst_irq_state *) opaque;
 
@@ -124,7 +125,8 @@ mst_fpga_readb(void *opaque, target_phys_addr_t addr)
 }
 
 static void
-mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
+mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint64_t value,
+		unsigned size)
 {
 	mst_irq_state *s = (mst_irq_state *) opaque;
 	value &= 0xffffffff;
@@ -175,17 +177,11 @@ mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
 	}
 }
 
-static CPUReadMemoryFunc * const mst_fpga_readfn[] = {
-	mst_fpga_readb,
-	mst_fpga_readb,
-	mst_fpga_readb,
+static const MemoryRegionOps mst_fpga_ops = {
+	.read = mst_fpga_readb,
+	.write = mst_fpga_writeb,
+	.endianness = DEVICE_NATIVE_ENDIAN,
 };
-static CPUWriteMemoryFunc * const mst_fpga_writefn[] = {
-	mst_fpga_writeb,
-	mst_fpga_writeb,
-	mst_fpga_writeb,
-};
-
 
 static int mst_fpga_post_load(void *opaque, int version_id)
 {
@@ -198,7 +194,6 @@ static int mst_fpga_post_load(void *opaque, int version_id)
 static int mst_fpga_init(SysBusDevice *dev)
 {
 	mst_irq_state *s;
-	int iomemtype;
 
 	s = FROM_SYSBUS(mst_irq_state, dev);
 
@@ -210,9 +205,9 @@ static int mst_fpga_init(SysBusDevice *dev)
 	/* alloc the external 16 irqs */
 	qdev_init_gpio_in(&dev->qdev, mst_fpga_set_irq, MST_NUM_IRQS);
 
-	iomemtype = cpu_register_io_memory(mst_fpga_readfn,
-		mst_fpga_writefn, s, DEVICE_NATIVE_ENDIAN);
-	sysbus_init_mmio(dev, 0x00100000, iomemtype);
+	memory_region_init_io(&s->iomem, &mst_fpga_ops, s,
+			    "fpga", 0x00100000);
+	sysbus_init_mmio_region(dev, &s->iomem);
 	return 0;
 }
 
commit e2ba99e9cd34a22e6d21ceb9783d0395b0a1d606
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Tue Oct 25 12:32:35 2011 +0200

    marvell_88x8618_audio: convert to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/marvell_88w8618_audio.c b/hw/marvell_88w8618_audio.c
index f8c5242..6982352 100644
--- a/hw/marvell_88w8618_audio.c
+++ b/hw/marvell_88w8618_audio.c
@@ -36,6 +36,7 @@
 
 typedef struct mv88w8618_audio_state {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     qemu_irq irq;
     uint32_t playback_mode;
     uint32_t status;
@@ -134,7 +135,8 @@ static void mv88w8618_audio_clock_update(mv88w8618_audio_state *s)
     wm8750_set_bclk_in(s->wm, rate);
 }
 
-static uint32_t mv88w8618_audio_read(void *opaque, target_phys_addr_t offset)
+static uint64_t mv88w8618_audio_read(void *opaque, target_phys_addr_t offset,
+                                    unsigned size)
 {
     mv88w8618_audio_state *s = opaque;
 
@@ -160,7 +162,7 @@ static uint32_t mv88w8618_audio_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void mv88w8618_audio_write(void *opaque, target_phys_addr_t offset,
-                                 uint32_t value)
+                                  uint64_t value, unsigned size)
 {
     mv88w8618_audio_state *s = opaque;
 
@@ -227,31 +229,23 @@ static void mv88w8618_audio_reset(DeviceState *d)
     s->phys_buf = 0;
 }
 
-static CPUReadMemoryFunc * const mv88w8618_audio_readfn[] = {
-    mv88w8618_audio_read,
-    mv88w8618_audio_read,
-    mv88w8618_audio_read
-};
-
-static CPUWriteMemoryFunc * const mv88w8618_audio_writefn[] = {
-    mv88w8618_audio_write,
-    mv88w8618_audio_write,
-    mv88w8618_audio_write
+static const MemoryRegionOps mv88w8618_audio_ops = {
+    .read = mv88w8618_audio_read,
+    .write = mv88w8618_audio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int mv88w8618_audio_init(SysBusDevice *dev)
 {
     mv88w8618_audio_state *s = FROM_SYSBUS(mv88w8618_audio_state, dev);
-    int iomemtype;
 
     sysbus_init_irq(dev, &s->irq);
 
     wm8750_data_req_set(s->wm, mv88w8618_audio_callback, s);
 
-    iomemtype = cpu_register_io_memory(mv88w8618_audio_readfn,
-                                       mv88w8618_audio_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, MP_AUDIO_SIZE, iomemtype);
+    memory_region_init_io(&s->iomem, &mv88w8618_audio_ops, s,
+                          "audio", MP_AUDIO_SIZE);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     return 0;
 }
commit 2443fa274c49a1134625e892cd5f98f3f943ef74
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Oct 17 17:28:32 2011 +0200

    stellaris: convert gptm to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/stellaris.c b/hw/stellaris.c
index 533d9c1..2ab7ec7 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -45,6 +45,7 @@ typedef const struct {
 
 typedef struct gptm_state {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t config;
     uint32_t mode[2];
     uint32_t control;
@@ -140,7 +141,8 @@ static void gptm_tick(void *opaque)
     gptm_update_irq(s);
 }
 
-static uint32_t gptm_read(void *opaque, target_phys_addr_t offset)
+static uint64_t gptm_read(void *opaque, target_phys_addr_t offset,
+                          unsigned size)
 {
     gptm_state *s = (gptm_state *)opaque;
 
@@ -188,7 +190,8 @@ static uint32_t gptm_read(void *opaque, target_phys_addr_t offset)
     }
 }
 
-static void gptm_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+static void gptm_write(void *opaque, target_phys_addr_t offset,
+                       uint64_t value, unsigned size)
 {
     gptm_state *s = (gptm_state *)opaque;
     uint32_t oldval;
@@ -268,16 +271,10 @@ static void gptm_write(void *opaque, target_phys_addr_t offset, uint32_t value)
     gptm_update_irq(s);
 }
 
-static CPUReadMemoryFunc * const gptm_readfn[] = {
-   gptm_read,
-   gptm_read,
-   gptm_read
-};
-
-static CPUWriteMemoryFunc * const gptm_writefn[] = {
-   gptm_write,
-   gptm_write,
-   gptm_write
+static const MemoryRegionOps gptm_ops = {
+    .read = gptm_read,
+    .write = gptm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_stellaris_gptm = {
@@ -305,16 +302,14 @@ static const VMStateDescription vmstate_stellaris_gptm = {
 
 static int stellaris_gptm_init(SysBusDevice *dev)
 {
-    int iomemtype;
     gptm_state *s = FROM_SYSBUS(gptm_state, dev);
 
     sysbus_init_irq(dev, &s->irq);
     qdev_init_gpio_out(&dev->qdev, &s->trigger, 1);
 
-    iomemtype = cpu_register_io_memory(gptm_readfn,
-                                       gptm_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &gptm_ops, s,
+                          "gptm", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     s->opaque[0] = s->opaque[1] = s;
     s->timer[0] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[0]);
commit 71a2df0557380bd81678f9cd80d7fc41b3a9d5dc
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Oct 17 17:28:31 2011 +0200

    stellaris: convert adc to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/stellaris.c b/hw/stellaris.c
index f55b1f3..533d9c1 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -892,6 +892,7 @@ static int stellaris_i2c_init(SysBusDevice * dev)
 typedef struct
 {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t actss;
     uint32_t ris;
     uint32_t im;
@@ -992,7 +993,8 @@ static void stellaris_adc_reset(stellaris_adc_state *s)
     }
 }
 
-static uint32_t stellaris_adc_read(void *opaque, target_phys_addr_t offset)
+static uint64_t stellaris_adc_read(void *opaque, target_phys_addr_t offset,
+                                   unsigned size)
 {
     stellaris_adc_state *s = (stellaris_adc_state *)opaque;
 
@@ -1040,7 +1042,7 @@ static uint32_t stellaris_adc_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void stellaris_adc_write(void *opaque, target_phys_addr_t offset,
-                                uint32_t value)
+                                uint64_t value, unsigned size)
 {
     stellaris_adc_state *s = (stellaris_adc_state *)opaque;
 
@@ -1054,7 +1056,7 @@ static void stellaris_adc_write(void *opaque, target_phys_addr_t offset,
             return;
         case 0x04: /* SSCTL */
             if (value != 6) {
-                hw_error("ADC: Unimplemented sequence %x\n",
+                hw_error("ADC: Unimplemented sequence %" PRIx64 "\n",
                           value);
             }
             s->ssctl[n] = value;
@@ -1097,16 +1099,10 @@ static void stellaris_adc_write(void *opaque, target_phys_addr_t offset,
     stellaris_adc_update(s);
 }
 
-static CPUReadMemoryFunc * const stellaris_adc_readfn[] = {
-   stellaris_adc_read,
-   stellaris_adc_read,
-   stellaris_adc_read
-};
-
-static CPUWriteMemoryFunc * const stellaris_adc_writefn[] = {
-   stellaris_adc_write,
-   stellaris_adc_write,
-   stellaris_adc_write
+static const MemoryRegionOps stellaris_adc_ops = {
+    .read = stellaris_adc_read,
+    .write = stellaris_adc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_stellaris_adc = {
@@ -1147,17 +1143,15 @@ static const VMStateDescription vmstate_stellaris_adc = {
 static int stellaris_adc_init(SysBusDevice *dev)
 {
     stellaris_adc_state *s = FROM_SYSBUS(stellaris_adc_state, dev);
-    int iomemtype;
     int n;
 
     for (n = 0; n < 4; n++) {
         sysbus_init_irq(dev, &s->irq[n]);
     }
 
-    iomemtype = cpu_register_io_memory(stellaris_adc_readfn,
-                                       stellaris_adc_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &stellaris_adc_ops, s,
+                          "adc", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     stellaris_adc_reset(s);
     qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1);
     vmstate_register(&dev->qdev, -1, &vmstate_stellaris_adc, s);
commit 8ea72f384ac8733520e47db685d6f0b122eb8186
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Oct 17 17:28:30 2011 +0200

    stellaris: convert i2c to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/stellaris.c b/hw/stellaris.c
index 6f9146a..f55b1f3 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -687,6 +687,7 @@ typedef struct {
     SysBusDevice busdev;
     i2c_bus *bus;
     qemu_irq irq;
+    MemoryRegion iomem;
     uint32_t msa;
     uint32_t mcs;
     uint32_t mdr;
@@ -704,7 +705,8 @@ typedef struct {
 #define STELLARIS_I2C_MCS_IDLE    0x20
 #define STELLARIS_I2C_MCS_BUSBSY  0x40
 
-static uint32_t stellaris_i2c_read(void *opaque, target_phys_addr_t offset)
+static uint64_t stellaris_i2c_read(void *opaque, target_phys_addr_t offset,
+                                   unsigned size)
 {
     stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
 
@@ -741,7 +743,7 @@ static void stellaris_i2c_update(stellaris_i2c_state *s)
 }
 
 static void stellaris_i2c_write(void *opaque, target_phys_addr_t offset,
-                                uint32_t value)
+                                uint64_t value, unsigned size)
 {
     stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
 
@@ -832,16 +834,10 @@ static void stellaris_i2c_reset(stellaris_i2c_state *s)
     stellaris_i2c_update(s);
 }
 
-static CPUReadMemoryFunc * const stellaris_i2c_readfn[] = {
-   stellaris_i2c_read,
-   stellaris_i2c_read,
-   stellaris_i2c_read
-};
-
-static CPUWriteMemoryFunc * const stellaris_i2c_writefn[] = {
-   stellaris_i2c_write,
-   stellaris_i2c_write,
-   stellaris_i2c_write
+static const MemoryRegionOps stellaris_i2c_ops = {
+    .read = stellaris_i2c_read,
+    .write = stellaris_i2c_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_stellaris_i2c = {
@@ -865,16 +861,14 @@ static int stellaris_i2c_init(SysBusDevice * dev)
 {
     stellaris_i2c_state *s = FROM_SYSBUS(stellaris_i2c_state, dev);
     i2c_bus *bus;
-    int iomemtype;
 
     sysbus_init_irq(dev, &s->irq);
     bus = i2c_init_bus(&dev->qdev, "i2c");
     s->bus = bus;
 
-    iomemtype = cpu_register_io_memory(stellaris_i2c_readfn,
-                                       stellaris_i2c_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &stellaris_i2c_ops, s,
+                          "i2c", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     /* ??? For now we only implement the master interface.  */
     stellaris_i2c_reset(s);
     vmstate_register(&dev->qdev, -1, &vmstate_stellaris_i2c, s);
commit 5699301fe269dc1ef1598ba26e3ced638cd59a7a
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Oct 17 17:28:29 2011 +0200

    stellaris: convert sys to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/stellaris.c b/hw/stellaris.c
index 2bf1c23..6f9146a 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -327,6 +327,7 @@ static int stellaris_gptm_init(SysBusDevice *dev)
 /* System controller.  */
 
 typedef struct {
+    MemoryRegion iomem;
     uint32_t pborctl;
     uint32_t ldopctl;
     uint32_t int_status;
@@ -414,7 +415,8 @@ static int ssys_board_class(const ssys_state *s)
     }
 }
 
-static uint32_t ssys_read(void *opaque, target_phys_addr_t offset)
+static uint64_t ssys_read(void *opaque, target_phys_addr_t offset,
+                          unsigned size)
 {
     ssys_state *s = (ssys_state *)opaque;
 
@@ -518,7 +520,8 @@ static void ssys_calculate_system_clock(ssys_state *s)
     }
 }
 
-static void ssys_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+static void ssys_write(void *opaque, target_phys_addr_t offset,
+                       uint64_t value, unsigned size)
 {
     ssys_state *s = (ssys_state *)opaque;
 
@@ -602,16 +605,10 @@ static void ssys_write(void *opaque, target_phys_addr_t offset, uint32_t value)
     ssys_update(s);
 }
 
-static CPUReadMemoryFunc * const ssys_readfn[] = {
-   ssys_read,
-   ssys_read,
-   ssys_read
-};
-
-static CPUWriteMemoryFunc * const ssys_writefn[] = {
-   ssys_write,
-   ssys_write,
-   ssys_write
+static const MemoryRegionOps ssys_ops = {
+    .read = ssys_read,
+    .write = ssys_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void ssys_reset(void *opaque)
@@ -667,7 +664,6 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq,
                               stellaris_board_info * board,
                               uint8_t *macaddr)
 {
-    int iomemtype;
     ssys_state *s;
 
     s = (ssys_state *)g_malloc0(sizeof(ssys_state));
@@ -677,10 +673,8 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq,
     s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16);
     s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16);
 
-    iomemtype = cpu_register_io_memory(ssys_readfn,
-                                       ssys_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x00001000, iomemtype);
+    memory_region_init_io(&s->iomem, &ssys_ops, s, "ssys", 0x00001000);
+    memory_region_add_subregion(get_system_memory(), base, &s->iomem);
     ssys_reset(s);
     vmstate_register(NULL, -1, &vmstate_stellaris_sys, s);
     return 0;
commit 0c36493e51064f851e3b0405660151532ff46a66
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Oct 17 17:28:28 2011 +0200

    integratorcp: convert control to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index c7d6596..7f79560 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -392,7 +392,9 @@ static int icp_pic_init(SysBusDevice *dev)
 }
 
 /* CP control registers.  */
-static uint32_t icp_control_read(void *opaque, target_phys_addr_t offset)
+
+static uint64_t icp_control_read(void *opaque, target_phys_addr_t offset,
+                                 unsigned size)
 {
     switch (offset >> 2) {
     case 0: /* CP_IDFIELD */
@@ -410,7 +412,7 @@ static uint32_t icp_control_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void icp_control_write(void *opaque, target_phys_addr_t offset,
-                          uint32_t value)
+                          uint64_t value, unsigned size)
 {
     switch (offset >> 2) {
     case 1: /* CP_FLASHPROG */
@@ -422,26 +424,21 @@ static void icp_control_write(void *opaque, target_phys_addr_t offset,
         hw_error("icp_control_write: Bad offset %x\n", (int)offset);
     }
 }
-static CPUReadMemoryFunc * const icp_control_readfn[] = {
-   icp_control_read,
-   icp_control_read,
-   icp_control_read
-};
 
-static CPUWriteMemoryFunc * const icp_control_writefn[] = {
-   icp_control_write,
-   icp_control_write,
-   icp_control_write
+static const MemoryRegionOps icp_control_ops = {
+    .read = icp_control_read,
+    .write = icp_control_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void icp_control_init(uint32_t base)
+static void icp_control_init(target_phys_addr_t base)
 {
-    int iomemtype;
+    MemoryRegion *io;
 
-    iomemtype = cpu_register_io_memory(icp_control_readfn,
-                                       icp_control_writefn, NULL,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x00800000, iomemtype);
+    io = (MemoryRegion *)g_malloc0(sizeof(MemoryRegion));
+    memory_region_init_io(io, &icp_control_ops, NULL,
+                          "control", 0x00800000);
+    memory_region_add_subregion(get_system_memory(), base, io);
     /* ??? Save/restore.  */
 }
 
commit 61074e46de5606764c8833aa818e5d923398a0cf
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Oct 17 17:28:27 2011 +0200

    integratorcp: convert icp pic to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index 0dc84c4..c7d6596 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -279,6 +279,7 @@ static int integratorcm_init(SysBusDevice *dev)
 typedef struct icp_pic_state
 {
   SysBusDevice busdev;
+  MemoryRegion iomem;
   uint32_t level;
   uint32_t irq_enabled;
   uint32_t fiq_enabled;
@@ -306,7 +307,8 @@ static void icp_pic_set_irq(void *opaque, int irq, int level)
     icp_pic_update(s);
 }
 
-static uint32_t icp_pic_read(void *opaque, target_phys_addr_t offset)
+static uint64_t icp_pic_read(void *opaque, target_phys_addr_t offset,
+                             unsigned size)
 {
     icp_pic_state *s = (icp_pic_state *)opaque;
 
@@ -335,7 +337,7 @@ static uint32_t icp_pic_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void icp_pic_write(void *opaque, target_phys_addr_t offset,
-                          uint32_t value)
+                          uint64_t value, unsigned size)
 {
     icp_pic_state *s = (icp_pic_state *)opaque;
 
@@ -371,30 +373,21 @@ static void icp_pic_write(void *opaque, target_phys_addr_t offset,
     icp_pic_update(s);
 }
 
-static CPUReadMemoryFunc * const icp_pic_readfn[] = {
-   icp_pic_read,
-   icp_pic_read,
-   icp_pic_read
-};
-
-static CPUWriteMemoryFunc * const icp_pic_writefn[] = {
-   icp_pic_write,
-   icp_pic_write,
-   icp_pic_write
+static const MemoryRegionOps icp_pic_ops = {
+    .read = icp_pic_read,
+    .write = icp_pic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int icp_pic_init(SysBusDevice *dev)
 {
     icp_pic_state *s = FROM_SYSBUS(icp_pic_state, dev);
-    int iomemtype;
 
     qdev_init_gpio_in(&dev->qdev, icp_pic_set_irq, 32);
     sysbus_init_irq(dev, &s->parent_irq);
     sysbus_init_irq(dev, &s->parent_fiq);
-    iomemtype = cpu_register_io_memory(icp_pic_readfn,
-                                       icp_pic_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x00800000, iomemtype);
+    memory_region_init_io(&s->iomem, &icp_pic_ops, s, "icp-pic", 0x00800000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     return 0;
 }
 
commit 71d9bc50ce643e7efbcc8f0094e90e5df9201917
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Mon Oct 17 17:28:26 2011 +0200

    integratorcp: convert core to memory API
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index 9a289b4..0dc84c4 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -18,6 +18,7 @@
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t memsz;
     MemoryRegion flash;
     bool flash_mapped;
@@ -39,7 +40,8 @@ static uint8_t integrator_spd[128] = {
    0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
 };
 
-static uint32_t integratorcm_read(void *opaque, target_phys_addr_t offset)
+static uint64_t integratorcm_read(void *opaque, target_phys_addr_t offset,
+                                  unsigned size)
 {
     integratorcm_state *s = (integratorcm_state *)opaque;
     if (offset >= 0x100 && offset < 0x200) {
@@ -152,7 +154,7 @@ static void integratorcm_update(integratorcm_state *s)
 }
 
 static void integratorcm_write(void *opaque, target_phys_addr_t offset,
-                               uint32_t value)
+                               uint64_t value, unsigned size)
 {
     integratorcm_state *s = (integratorcm_state *)opaque;
     switch (offset >> 2) {
@@ -228,21 +230,14 @@ static void integratorcm_write(void *opaque, target_phys_addr_t offset,
 
 /* Integrator/CM control registers.  */
 
-static CPUReadMemoryFunc * const integratorcm_readfn[] = {
-   integratorcm_read,
-   integratorcm_read,
-   integratorcm_read
-};
-
-static CPUWriteMemoryFunc * const integratorcm_writefn[] = {
-   integratorcm_write,
-   integratorcm_write,
-   integratorcm_write
+static const MemoryRegionOps integratorcm_ops = {
+    .read = integratorcm_read,
+    .write = integratorcm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int integratorcm_init(SysBusDevice *dev)
 {
-    int iomemtype;
     integratorcm_state *s = FROM_SYSBUS(integratorcm_state, dev);
 
     s->cm_osc = 0x01000048;
@@ -269,10 +264,10 @@ static int integratorcm_init(SysBusDevice *dev)
     memory_region_init_ram(&s->flash, NULL, "integrator.flash", 0x100000);
     s->flash_mapped = false;
 
-    iomemtype = cpu_register_io_memory(integratorcm_readfn,
-                                       integratorcm_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x00800000, iomemtype);
+    memory_region_init_io(&s->iomem, &integratorcm_ops, s,
+                          "integratorcm", 0x00800000);
+    sysbus_init_mmio_region(dev, &s->iomem);
+
     integratorcm_do_remap(s, 1);
     /* ??? Save/restore.  */
     return 0;
commit 4d5bf5f6517d836e05557531781b53c1608786eb
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Oct 17 13:11:27 2011 +0200

    ioapic: Convert to memory API
    
    This maintains the old imprecise access size handling.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/ioapic.c b/hw/ioapic.c
index 347536e..eb75766 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -86,6 +86,7 @@ typedef struct IOAPICState IOAPICState;
 
 struct IOAPICState {
     SysBusDevice busdev;
+    MemoryRegion io_memory;
     uint8_t id;
     uint8_t ioregsel;
     uint32_t irr;
@@ -195,7 +196,8 @@ void ioapic_eoi_broadcast(int vector)
     }
 }
 
-static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t
+ioapic_mem_read(void *opaque, target_phys_addr_t addr, unsigned int size)
 {
     IOAPICState *s = opaque;
     int index;
@@ -237,7 +239,8 @@ static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
 }
 
 static void
-ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+ioapic_mem_write(void *opaque, target_phys_addr_t addr, uint64_t val,
+                 unsigned int size)
 {
     IOAPICState *s = opaque;
     int index;
@@ -315,32 +318,23 @@ static void ioapic_reset(DeviceState *d)
     }
 }
 
-static CPUReadMemoryFunc * const ioapic_mem_read[3] = {
-    ioapic_mem_readl,
-    ioapic_mem_readl,
-    ioapic_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const ioapic_mem_write[3] = {
-    ioapic_mem_writel,
-    ioapic_mem_writel,
-    ioapic_mem_writel,
+static const MemoryRegionOps ioapic_io_ops = {
+    .read = ioapic_mem_read,
+    .write = ioapic_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int ioapic_init1(SysBusDevice *dev)
 {
     IOAPICState *s = FROM_SYSBUS(IOAPICState, dev);
-    int io_memory;
     static int ioapic_no;
 
     if (ioapic_no >= MAX_IOAPICS) {
         return -1;
     }
 
-    io_memory = cpu_register_io_memory(ioapic_mem_read,
-                                       ioapic_mem_write, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, io_memory);
+    memory_region_init_io(&s->io_memory, &ioapic_io_ops, s, "ioapic", 0x1000);
+    sysbus_init_mmio_region(dev, &s->io_memory);
 
     qdev_init_gpio_in(&dev->qdev, ioapic_set_irq, IOAPIC_NUM_PINS);
 
commit 1a440963b9b3d76f0a9ba8d5cf7c9cdfa7a1ef06
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Oct 17 13:11:29 2011 +0200

    ioapic: Reject non-dword accesses to IOWIN register
    
    Aligns the model with the spec.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/ioapic.c b/hw/ioapic.c
index 61991d7..347536e 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -206,6 +206,9 @@ static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
         val = s->ioregsel;
         break;
     case IOAPIC_IOWIN:
+        if (size != 4) {
+            break;
+        }
         switch (s->ioregsel) {
         case IOAPIC_REG_ID:
             val = s->id << IOAPIC_ID_SHIFT;
@@ -244,6 +247,9 @@ ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
         s->ioregsel = val;
         break;
     case IOAPIC_IOWIN:
+        if (size != 4) {
+            break;
+        }
         DPRINTF("write: %08x = %08x\n", s->ioregsel, val);
         switch (s->ioregsel) {
         case IOAPIC_REG_ID:
commit cfee758cc768ba29ab5e8c4a68b4433df4422cc9
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Oct 16 16:11:06 2011 +0200

    sbi: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/sbi.c b/hw/sbi.c
index 53f66f2..2f64d59 100644
--- a/hw/sbi.c
+++ b/hw/sbi.c
@@ -39,6 +39,7 @@
 
 typedef struct SBIState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t regs[SBI_NREGS];
     uint32_t intreg_pending[MAX_CPUS];
     qemu_irq cpu_irqs[MAX_CPUS];
@@ -51,7 +52,8 @@ static void sbi_set_irq(void *opaque, int irq, int level)
 {
 }
 
-static uint32_t sbi_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t sbi_mem_read(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
 {
     SBIState *s = opaque;
     uint32_t saddr, ret;
@@ -67,13 +69,14 @@ static uint32_t sbi_mem_readl(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static void sbi_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void sbi_mem_write(void *opaque, target_phys_addr_t addr,
+                          uint64_t val, unsigned dize)
 {
     SBIState *s = opaque;
     uint32_t saddr;
 
     saddr = addr >> 2;
-    DPRINTF("write system reg 0x" TARGET_FMT_plx " = %x\n", addr, val);
+    DPRINTF("write system reg 0x" TARGET_FMT_plx " = %x\n", addr, (int)val);
     switch (saddr) {
     default:
         s->regs[saddr] = val;
@@ -81,16 +84,14 @@ static void sbi_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
-static CPUReadMemoryFunc * const sbi_mem_read[3] = {
-    NULL,
-    NULL,
-    sbi_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const sbi_mem_write[3] = {
-    NULL,
-    NULL,
-    sbi_mem_writel,
+static const MemoryRegionOps sbi_mem_ops = {
+    .read = sbi_mem_read,
+    .write = sbi_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static const VMStateDescription vmstate_sbi = {
@@ -117,7 +118,6 @@ static void sbi_reset(DeviceState *d)
 static int sbi_init1(SysBusDevice *dev)
 {
     SBIState *s = FROM_SYSBUS(SBIState, dev);
-    int sbi_io_memory;
     unsigned int i;
 
     qdev_init_gpio_in(&dev->qdev, sbi_set_irq, 32 + MAX_CPUS);
@@ -125,9 +125,8 @@ static int sbi_init1(SysBusDevice *dev)
         sysbus_init_irq(dev, &s->cpu_irqs[i]);
     }
 
-    sbi_io_memory = cpu_register_io_memory(sbi_mem_read, sbi_mem_write, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, SBI_SIZE, sbi_io_memory);
+    memory_region_init_io(&s->iomem, &sbi_mem_ops, s, "sbi", SBI_SIZE);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     return 0;
 }
commit dc6c1b37328998daff6db8876734afc9d252dc39
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Oct 11 15:52:48 2011 +0200

    fdc: convert to memory API
    
    FIXME: instance ID for migration
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/fdc.c b/hw/fdc.c
index ecaad09..a3329c9 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -373,6 +373,7 @@ enum {
 #define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT)
 
 struct FDCtrl {
+    MemoryRegion iomem;
     qemu_irq irq;
     /* Controller state */
     QEMUTimer *result_timer;
@@ -491,39 +492,32 @@ static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
     }
 }
 
-static uint32_t fdctrl_read_mem (void *opaque, target_phys_addr_t reg)
+static uint64_t fdctrl_read_mem (void *opaque, target_phys_addr_t reg,
+                                 unsigned ize)
 {
     return fdctrl_read(opaque, (uint32_t)reg);
 }
 
-static void fdctrl_write_mem (void *opaque,
-                              target_phys_addr_t reg, uint32_t value)
+static void fdctrl_write_mem (void *opaque, target_phys_addr_t reg,
+                              uint64_t value, unsigned size)
 {
     fdctrl_write(opaque, (uint32_t)reg, value);
 }
 
-static CPUReadMemoryFunc * const fdctrl_mem_read[3] = {
-    fdctrl_read_mem,
-    fdctrl_read_mem,
-    fdctrl_read_mem,
+static const MemoryRegionOps fdctrl_mem_ops = {
+    .read = fdctrl_read_mem,
+    .write = fdctrl_write_mem,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const fdctrl_mem_write[3] = {
-    fdctrl_write_mem,
-    fdctrl_write_mem,
-    fdctrl_write_mem,
-};
-
-static CPUReadMemoryFunc * const fdctrl_mem_read_strict[3] = {
-    fdctrl_read_mem,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const fdctrl_mem_write_strict[3] = {
-    fdctrl_write_mem,
-    NULL,
-    NULL,
+static const MemoryRegionOps fdctrl_mem_strict_ops = {
+    .read = fdctrl_read_mem,
+    .write = fdctrl_write_mem,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static bool fdrive_media_changed_needed(void *opaque)
@@ -1914,17 +1908,15 @@ static int sysbus_fdc_init1(SysBusDevice *dev)
 {
     FDCtrlSysBus *sys = DO_UPCAST(FDCtrlSysBus, busdev, dev);
     FDCtrl *fdctrl = &sys->state;
-    int io;
     int ret;
 
-    io = cpu_register_io_memory(fdctrl_mem_read, fdctrl_mem_write, fdctrl,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x08, io);
+    memory_region_init_io(&fdctrl->iomem, &fdctrl_mem_ops, fdctrl, "fdc", 0x08);
+    sysbus_init_mmio_region(dev, &fdctrl->iomem);
     sysbus_init_irq(dev, &fdctrl->irq);
     qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1);
     fdctrl->dma_chann = -1;
 
-    qdev_set_legacy_instance_id(&dev->qdev, io, 2);
+    qdev_set_legacy_instance_id(&dev->qdev, 0 /* io */, 2); /* FIXME */
     ret = fdctrl_init_common(fdctrl);
 
     return ret;
@@ -1933,17 +1925,15 @@ static int sysbus_fdc_init1(SysBusDevice *dev)
 static int sun4m_fdc_init1(SysBusDevice *dev)
 {
     FDCtrl *fdctrl = &(FROM_SYSBUS(FDCtrlSysBus, dev)->state);
-    int io;
 
-    io = cpu_register_io_memory(fdctrl_mem_read_strict,
-                                fdctrl_mem_write_strict, fdctrl,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x08, io);
+    memory_region_init_io(&fdctrl->iomem, &fdctrl_mem_strict_ops, fdctrl,
+                          "fdctrl", 0x08);
+    sysbus_init_mmio_region(dev, &fdctrl->iomem);
     sysbus_init_irq(dev, &fdctrl->irq);
     qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1);
 
     fdctrl->sun4m = 1;
-    qdev_set_legacy_instance_id(&dev->qdev, io, 2);
+    qdev_set_legacy_instance_id(&dev->qdev, 0 /* io */, 2); /* FIXME */
     return fdctrl_init_common(fdctrl);
 }
 
commit 7f8293bf63c1d420b7527763f891643b4eb2aa43
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Oct 11 13:54:48 2011 +0200

    pl190: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pl190.c b/hw/pl190.c
index 8dc7e42..a3d008d 100644
--- a/hw/pl190.c
+++ b/hw/pl190.c
@@ -17,6 +17,7 @@
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t level;
     uint32_t soft_level;
     uint32_t irq_enable;
@@ -84,7 +85,8 @@ static void pl190_update_vectors(pl190_state *s)
     pl190_update(s);
 }
 
-static uint32_t pl190_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl190_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl190_state *s = (pl190_state *)opaque;
     int i;
@@ -140,7 +142,8 @@ static uint32_t pl190_read(void *opaque, target_phys_addr_t offset)
     }
 }
 
-static void pl190_write(void *opaque, target_phys_addr_t offset, uint32_t val)
+static void pl190_write(void *opaque, target_phys_addr_t offset,
+                        uint64_t val, unsigned size)
 {
     pl190_state *s = (pl190_state *)opaque;
 
@@ -199,16 +202,10 @@ static void pl190_write(void *opaque, target_phys_addr_t offset, uint32_t val)
     pl190_update(s);
 }
 
-static CPUReadMemoryFunc * const pl190_readfn[] = {
-   pl190_read,
-   pl190_read,
-   pl190_read
-};
-
-static CPUWriteMemoryFunc * const pl190_writefn[] = {
-   pl190_write,
-   pl190_write,
-   pl190_write
+static const MemoryRegionOps pl190_ops = {
+    .read = pl190_read,
+    .write = pl190_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void pl190_reset(DeviceState *d)
@@ -230,12 +227,9 @@ static void pl190_reset(DeviceState *d)
 static int pl190_init(SysBusDevice *dev)
 {
     pl190_state *s = FROM_SYSBUS(pl190_state, dev);
-    int iomemtype;
 
-    iomemtype = cpu_register_io_memory(pl190_readfn,
-                                       pl190_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &pl190_ops, s, "pl190", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     qdev_init_gpio_in(&dev->qdev, pl190_set_irq, 32);
     sysbus_init_irq(dev, &s->irq);
     sysbus_init_irq(dev, &s->fiq);
commit ca45842ab6b2b962c4c8515f6c4ebba229d1b1e4
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Oct 11 13:54:48 2011 +0200

    pl181: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pl181.c b/hw/pl181.c
index 0943c09..e13ea8e 100644
--- a/hw/pl181.c
+++ b/hw/pl181.c
@@ -24,6 +24,7 @@ do { printf("pl181: " fmt , ## __VA_ARGS__); } while (0)
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     SDState *card;
     uint32_t clock;
     uint32_t power;
@@ -259,7 +260,8 @@ static void pl181_fifo_run(pl181_state *s)
     }
 }
 
-static uint32_t pl181_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl181_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl181_state *s = (pl181_state *)opaque;
     uint32_t tmp;
@@ -342,7 +344,7 @@ static uint32_t pl181_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pl181_write(void *opaque, target_phys_addr_t offset,
-                          uint32_t value)
+                        uint64_t value, unsigned size)
 {
     pl181_state *s = (pl181_state *)opaque;
 
@@ -412,16 +414,10 @@ static void pl181_write(void *opaque, target_phys_addr_t offset,
     pl181_update(s);
 }
 
-static CPUReadMemoryFunc * const pl181_readfn[] = {
-   pl181_read,
-   pl181_read,
-   pl181_read
-};
-
-static CPUWriteMemoryFunc * const pl181_writefn[] = {
-   pl181_write,
-   pl181_write,
-   pl181_write
+static const MemoryRegionOps pl181_ops = {
+    .read = pl181_read,
+    .write = pl181_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void pl181_reset(void *opaque)
@@ -453,13 +449,11 @@ static void pl181_reset(void *opaque)
 
 static int pl181_init(SysBusDevice *dev)
 {
-    int iomemtype;
     pl181_state *s = FROM_SYSBUS(pl181_state, dev);
     DriveInfo *dinfo;
 
-    iomemtype = cpu_register_io_memory(pl181_readfn, pl181_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &pl181_ops, s, "pl181", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq[0]);
     sysbus_init_irq(dev, &s->irq[1]);
     qdev_init_gpio_out(&s->busdev.qdev, s->cardstatus, 2);
commit 1a6b31cec7db551e8d274d2a474858258da8b2ba
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Oct 10 17:18:44 2011 +0200

    pl110: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pl110.c b/hw/pl110.c
index 4ac710a..fbbcb2e 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -40,6 +40,7 @@ enum pl110_version
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     DisplayState *ds;
 
     int version;
@@ -301,7 +302,8 @@ static void pl110_update(pl110_state *s)
   /* TODO: Implement interrupts.  */
 }
 
-static uint32_t pl110_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl110_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl110_state *s = (pl110_state *)opaque;
 
@@ -350,7 +352,7 @@ static uint32_t pl110_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pl110_write(void *opaque, target_phys_addr_t offset,
-                        uint32_t val)
+                        uint64_t val, unsigned size)
 {
     pl110_state *s = (pl110_state *)opaque;
     int n;
@@ -416,16 +418,10 @@ static void pl110_write(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static CPUReadMemoryFunc * const pl110_readfn[] = {
-   pl110_read,
-   pl110_read,
-   pl110_read
-};
-
-static CPUWriteMemoryFunc * const pl110_writefn[] = {
-   pl110_write,
-   pl110_write,
-   pl110_write
+static const MemoryRegionOps pl110_ops = {
+    .read = pl110_read,
+    .write = pl110_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void pl110_mux_ctrl_set(void *opaque, int line, int level)
@@ -437,12 +433,9 @@ static void pl110_mux_ctrl_set(void *opaque, int line, int level)
 static int pl110_init(SysBusDevice *dev)
 {
     pl110_state *s = FROM_SYSBUS(pl110_state, dev);
-    int iomemtype;
 
-    iomemtype = cpu_register_io_memory(pl110_readfn,
-                                       pl110_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &pl110_ops, s, "pl110", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     qdev_init_gpio_in(&s->busdev.qdev, pl110_mux_ctrl_set, 1);
     s->ds = graphic_console_init(pl110_update_display,
commit 63b02e041b91e824091af27559ae4b3e92a3d6c7
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Oct 10 17:18:44 2011 +0200

    pl080: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pl080.c b/hw/pl080.c
index 5ba3b08..1efd3bd 100644
--- a/hw/pl080.c
+++ b/hw/pl080.c
@@ -37,6 +37,7 @@ typedef struct {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint8_t tc_int;
     uint8_t tc_mask;
     uint8_t err_int;
@@ -217,7 +218,8 @@ again:
     }
 }
 
-static uint32_t pl080_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl080_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl080_state *s = (pl080_state *)opaque;
     uint32_t i;
@@ -285,7 +287,7 @@ static uint32_t pl080_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pl080_write(void *opaque, target_phys_addr_t offset,
-                          uint32_t value)
+                        uint64_t value, unsigned size)
 {
     pl080_state *s = (pl080_state *)opaque;
     int i;
@@ -344,27 +346,18 @@ static void pl080_write(void *opaque, target_phys_addr_t offset,
     pl080_update(s);
 }
 
-static CPUReadMemoryFunc * const pl080_readfn[] = {
-   pl080_read,
-   pl080_read,
-   pl080_read
-};
-
-static CPUWriteMemoryFunc * const pl080_writefn[] = {
-   pl080_write,
-   pl080_write,
-   pl080_write
+static const MemoryRegionOps pl080_ops = {
+    .read = pl080_read,
+    .write = pl080_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int pl08x_init(SysBusDevice *dev, int nchannels)
 {
-    int iomemtype;
     pl080_state *s = FROM_SYSBUS(pl080_state, dev);
 
-    iomemtype = cpu_register_io_memory(pl080_readfn,
-                                       pl080_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &pl080_ops, s, "pl080", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     s->nchannels = nchannels;
     return 0;
commit 3cf89f8a2797c4bf892d49a13abb99f4e2a2168e
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Oct 10 17:18:44 2011 +0200

    pl061: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pl061.c b/hw/pl061.c
index cf5adbe..0e16e8a 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -30,6 +30,7 @@ static const uint8_t pl061_id_luminary[12] =
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t locked;
     uint32_t data;
     uint32_t old_data;
@@ -112,7 +113,8 @@ static void pl061_update(pl061_state *s)
     /* FIXME: Implement input interrupts.  */
 }
 
-static uint32_t pl061_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl061_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl061_state *s = (pl061_state *)opaque;
 
@@ -168,7 +170,7 @@ static uint32_t pl061_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pl061_write(void *opaque, target_phys_addr_t offset,
-                        uint32_t value)
+                        uint64_t value, unsigned size)
 {
     pl061_state *s = (pl061_state *)opaque;
     uint8_t mask;
@@ -262,27 +264,18 @@ static void pl061_set_irq(void * opaque, int irq, int level)
     }
 }
 
-static CPUReadMemoryFunc * const pl061_readfn[] = {
-   pl061_read,
-   pl061_read,
-   pl061_read
-};
-
-static CPUWriteMemoryFunc * const pl061_writefn[] = {
-   pl061_write,
-   pl061_write,
-   pl061_write
+static const MemoryRegionOps pl061_ops = {
+    .read = pl061_read,
+    .write = pl061_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int pl061_init(SysBusDevice *dev, const unsigned char *id)
 {
-    int iomemtype;
     pl061_state *s = FROM_SYSBUS(pl061_state, dev);
     s->id = id;
-    iomemtype = cpu_register_io_memory(pl061_readfn,
-                                       pl061_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &pl061_ops, s, "pl061", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     qdev_init_gpio_in(&dev->qdev, pl061_set_irq, 8);
     qdev_init_gpio_out(&dev->qdev, s->out, 8);
commit b8f7a73878cdd7c1f892c5a3360f64d2a2ca040f
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Oct 10 17:18:44 2011 +0200

    pl050: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pl050.c b/hw/pl050.c
index f7fa2e2..dedd622 100644
--- a/hw/pl050.c
+++ b/hw/pl050.c
@@ -12,6 +12,7 @@
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     void *dev;
     uint32_t cr;
     uint32_t clk;
@@ -57,7 +58,8 @@ static void pl050_update(void *opaque, int level)
     qemu_set_irq(s->irq, raise);
 }
 
-static uint32_t pl050_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl050_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl050_state *s = (pl050_state *)opaque;
     if (offset >= 0xfe0 && offset < 0x1000)
@@ -99,7 +101,7 @@ static uint32_t pl050_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pl050_write(void *opaque, target_phys_addr_t offset,
-                          uint32_t value)
+                        uint64_t value, unsigned size)
 {
     pl050_state *s = (pl050_state *)opaque;
     switch (offset >> 2) {
@@ -124,27 +126,18 @@ static void pl050_write(void *opaque, target_phys_addr_t offset,
         hw_error("pl050_write: Bad offset %x\n", (int)offset);
     }
 }
-static CPUReadMemoryFunc * const pl050_readfn[] = {
-   pl050_read,
-   pl050_read,
-   pl050_read
-};
-
-static CPUWriteMemoryFunc * const pl050_writefn[] = {
-   pl050_write,
-   pl050_write,
-   pl050_write
+static const MemoryRegionOps pl050_ops = {
+    .read = pl050_read,
+    .write = pl050_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int pl050_init(SysBusDevice *dev, int is_mouse)
 {
     pl050_state *s = FROM_SYSBUS(pl050_state, dev);
-    int iomemtype;
 
-    iomemtype = cpu_register_io_memory(pl050_readfn,
-                                       pl050_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &pl050_ops, s, "pl050", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     s->is_mouse = is_mouse;
     if (s->is_mouse)
commit 9edbe481bf38e0eb91a38a6ba44317a5ad15f6e6
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Oct 10 17:18:44 2011 +0200

    pl031: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pl031.c b/hw/pl031.c
index 017a313..4ff96f9 100644
--- a/hw/pl031.c
+++ b/hw/pl031.c
@@ -32,6 +32,7 @@ do { printf("pl031: " fmt , ## __VA_ARGS__); } while (0)
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     QEMUTimer *timer;
     qemu_irq irq;
 
@@ -105,7 +106,8 @@ static void pl031_set_alarm(pl031_state *s)
     }
 }
 
-static uint32_t pl031_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl031_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl031_state *s = (pl031_state *)opaque;
 
@@ -141,7 +143,7 @@ static uint32_t pl031_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pl031_write(void * opaque, target_phys_addr_t offset,
-                        uint32_t value)
+                        uint64_t value, unsigned size)
 {
     pl031_state *s = (pl031_state *)opaque;
 
@@ -186,31 +188,19 @@ static void pl031_write(void * opaque, target_phys_addr_t offset,
     }
 }
 
-static CPUWriteMemoryFunc * const  pl031_writefn[] = {
-    pl031_write,
-    pl031_write,
-    pl031_write
-};
-
-static CPUReadMemoryFunc * const  pl031_readfn[] = {
-    pl031_read,
-    pl031_read,
-    pl031_read
+static const MemoryRegionOps pl031_ops = {
+    .read = pl031_read,
+    .write = pl031_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int pl031_init(SysBusDevice *dev)
 {
-    int iomemtype;
     pl031_state *s = FROM_SYSBUS(pl031_state, dev);
     struct tm tm;
 
-    iomemtype = cpu_register_io_memory(pl031_readfn, pl031_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    if (iomemtype == -1) {
-        hw_error("pl031_init: Can't register I/O memory\n");
-    }
-
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &pl031_ops, s, "pl031", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     sysbus_init_irq(dev, &s->irq);
     /* ??? We assume vm_clock is zero at this point.  */
commit 02a59c37b42db108e68ecfcfd5c1f3b285758052
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Oct 10 17:15:47 2011 +0200

    pl022: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pl022.c b/hw/pl022.c
index 9a1cb71..e0cf2b0 100644
--- a/hw/pl022.c
+++ b/hw/pl022.c
@@ -42,6 +42,7 @@ do { fprintf(stderr, "pl022: error: " fmt , ## __VA_ARGS__);} while (0)
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t cr0;
     uint32_t cr1;
     uint32_t bitmask;
@@ -130,7 +131,8 @@ static void pl022_xfer(pl022_state *s)
     pl022_update(s);
 }
 
-static uint32_t pl022_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl022_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl022_state *s = (pl022_state *)opaque;
     int val;
@@ -173,7 +175,7 @@ static uint32_t pl022_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pl022_write(void *opaque, target_phys_addr_t offset,
-                        uint32_t value)
+                        uint64_t value, unsigned size)
 {
     pl022_state *s = (pl022_state *)opaque;
 
@@ -193,7 +195,7 @@ static void pl022_write(void *opaque, target_phys_addr_t offset,
         break;
     case 0x08: /* DR */
         if (s->tx_fifo_len < 8) {
-            DPRINTF("TX %02x\n", value);
+            DPRINTF("TX %02x\n", (unsigned)value);
             s->tx_fifo[s->tx_fifo_head] = value & s->bitmask;
             s->tx_fifo_head = (s->tx_fifo_head + 1) & 7;
             s->tx_fifo_len++;
@@ -227,16 +229,10 @@ static void pl022_reset(pl022_state *s)
     s->sr = PL022_SR_TFE | PL022_SR_TNF;
 }
 
-static CPUReadMemoryFunc * const pl022_readfn[] = {
-   pl022_read,
-   pl022_read,
-   pl022_read
-};
-
-static CPUWriteMemoryFunc * const pl022_writefn[] = {
-   pl022_write,
-   pl022_write,
-   pl022_write
+static const MemoryRegionOps pl022_ops = {
+    .read = pl022_read,
+    .write = pl022_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_pl022 = {
@@ -279,12 +275,9 @@ static const VMStateDescription vmstate_pl022 = {
 static int pl022_init(SysBusDevice *dev)
 {
     pl022_state *s = FROM_SYSBUS(pl022_state, dev);
-    int iomemtype;
 
-    iomemtype = cpu_register_io_memory(pl022_readfn,
-                                       pl022_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &pl022_ops, s, "pl022", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     s->ssi = ssi_create_bus(&dev->qdev, "ssi");
     pl022_reset(s);
commit 484847579417855b1640f7786064bf25d8324226
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Oct 10 17:08:49 2011 +0200

    pl011: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pl011.c b/hw/pl011.c
index 707a161..9cf6dea 100644
--- a/hw/pl011.c
+++ b/hw/pl011.c
@@ -12,6 +12,7 @@
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t readbuff;
     uint32_t flags;
     uint32_t lcr;
@@ -53,7 +54,8 @@ static void pl011_update(pl011_state *s)
     qemu_set_irq(s->irq, flags != 0);
 }
 
-static uint32_t pl011_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl011_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl011_state *s = (pl011_state *)opaque;
     uint32_t c;
@@ -123,7 +125,7 @@ static void pl011_set_read_trigger(pl011_state *s)
 }
 
 static void pl011_write(void *opaque, target_phys_addr_t offset,
-                          uint32_t value)
+                        uint64_t value, unsigned size)
 {
     pl011_state *s = (pl011_state *)opaque;
     unsigned char ch;
@@ -223,16 +225,10 @@ static void pl011_event(void *opaque, int event)
         pl011_put_fifo(opaque, 0x400);
 }
 
-static CPUReadMemoryFunc * const pl011_readfn[] = {
-   pl011_read,
-   pl011_read,
-   pl011_read
-};
-
-static CPUWriteMemoryFunc * const pl011_writefn[] = {
-   pl011_write,
-   pl011_write,
-   pl011_write
+static const MemoryRegionOps pl011_ops = {
+    .read = pl011_read,
+    .write = pl011_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_pl011 = {
@@ -262,13 +258,10 @@ static const VMStateDescription vmstate_pl011 = {
 
 static int pl011_init(SysBusDevice *dev, const unsigned char *id)
 {
-    int iomemtype;
     pl011_state *s = FROM_SYSBUS(pl011_state, dev);
 
-    iomemtype = cpu_register_io_memory(pl011_readfn,
-                                       pl011_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000,iomemtype);
+    memory_region_init_io(&s->iomem, &pl011_ops, s, "pl011", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     s->id = id;
     s->chr = qdev_init_chardev(&dev->qdev);
commit e71ceafc7d5792438639a4ecf87227c997e349f2
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Oct 6 17:37:49 2011 +0200

    zaurus: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/zaurus.c b/hw/zaurus.c
index 0eeacf7..3c27cd8 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -28,6 +28,7 @@ typedef struct ScoopInfo ScoopInfo;
 struct ScoopInfo {
     SysBusDevice busdev;
     qemu_irq handler[16];
+    MemoryRegion iomem;
     uint16_t status;
     uint16_t power;
     uint32_t gpio_level;
@@ -67,7 +68,8 @@ static inline void scoop_gpio_handler_update(ScoopInfo *s) {
     s->prev_level = level;
 }
 
-static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t scoop_read(void *opaque, target_phys_addr_t addr,
+                           unsigned size)
 {
     ScoopInfo *s = (ScoopInfo *) opaque;
 
@@ -100,7 +102,8 @@ static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
-static void scoop_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void scoop_write(void *opaque, target_phys_addr_t addr,
+                        uint64_t value, unsigned size)
 {
     ScoopInfo *s = (ScoopInfo *) opaque;
     value &= 0xffff;
@@ -143,15 +146,10 @@ static void scoop_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
     }
 }
 
-static CPUReadMemoryFunc * const scoop_readfn[] = {
-    scoop_readb,
-    scoop_readb,
-    scoop_readb,
-};
-static CPUWriteMemoryFunc * const scoop_writefn[] = {
-    scoop_writeb,
-    scoop_writeb,
-    scoop_writeb,
+static const MemoryRegionOps scoop_ops = {
+    .read = scoop_read,
+    .write = scoop_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void scoop_gpio_set(void *opaque, int line, int level)
@@ -167,15 +165,13 @@ static void scoop_gpio_set(void *opaque, int line, int level)
 static int scoop_init(SysBusDevice *dev)
 {
     ScoopInfo *s = FROM_SYSBUS(ScoopInfo, dev);
-    int iomemtype;
 
     s->status = 0x02;
     qdev_init_gpio_out(&s->busdev.qdev, s->handler, 16);
     qdev_init_gpio_in(&s->busdev.qdev, scoop_gpio_set, 16);
-    iomemtype = cpu_register_io_memory(scoop_readfn,
-                    scoop_writefn, s, DEVICE_NATIVE_ENDIAN);
+    memory_region_init_io(&s->iomem, &scoop_ops, s, "scoop", 0x1000);
 
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     return 0;
 }
commit 63858cd99244aeb819f92a6f8f9a23a5719c4824
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Oct 6 16:44:26 2011 +0200

    parallel: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 6e657dd..f6e3316 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -274,7 +274,8 @@ static void mips_jazz_init(MemoryRegion *address_space,
 
     /* Parallel port */
     if (parallel_hds[0])
-        parallel_mm_init(0x80008000, 0, rc4030[0], parallel_hds[0]);
+        parallel_mm_init(address_space, 0x80008000, 0, rc4030[0],
+                         parallel_hds[0]);
 
     /* Sound card */
     /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */
diff --git a/hw/parallel.c b/hw/parallel.c
index 8494d94..c4c5dbe 100644
--- a/hw/parallel.c
+++ b/hw/parallel.c
@@ -65,6 +65,7 @@
 #define PARA_CTR_SIGNAL (PARA_CTR_SELECT|PARA_CTR_INIT|PARA_CTR_AUTOLF|PARA_CTR_STROBE)
 
 typedef struct ParallelState {
+    MemoryRegion iomem;
     uint8_t dataw;
     uint8_t datar;
     uint8_t status;
@@ -555,24 +556,20 @@ static void parallel_mm_writel (void *opaque,
     parallel_ioport_write_sw(s, addr >> s->it_shift, value);
 }
 
-static CPUReadMemoryFunc * const parallel_mm_read_sw[] = {
-    &parallel_mm_readb,
-    &parallel_mm_readw,
-    &parallel_mm_readl,
-};
-
-static CPUWriteMemoryFunc * const parallel_mm_write_sw[] = {
-    &parallel_mm_writeb,
-    &parallel_mm_writew,
-    &parallel_mm_writel,
+static const MemoryRegionOps parallel_mm_ops = {
+    .old_mmio = {
+        .read = { parallel_mm_readb, parallel_mm_readw, parallel_mm_readl },
+        .write = { parallel_mm_writeb, parallel_mm_writew, parallel_mm_writel },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 /* If fd is zero, it means that the parallel device uses the console */
-bool parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
+bool parallel_mm_init(MemoryRegion *address_space,
+                      target_phys_addr_t base, int it_shift, qemu_irq irq,
                       CharDriverState *chr)
 {
     ParallelState *s;
-    int io_sw;
 
     s = g_malloc0(sizeof(ParallelState));
     s->irq = irq;
@@ -580,9 +577,9 @@ bool parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
     s->it_shift = it_shift;
     qemu_register_reset(parallel_reset, s);
 
-    io_sw = cpu_register_io_memory(parallel_mm_read_sw, parallel_mm_write_sw,
-                                   s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 8 << it_shift, io_sw);
+    memory_region_init_io(&s->iomem, &parallel_mm_ops, s,
+                          "parallel", 8 << it_shift);
+    memory_region_add_subregion(address_space, base, &s->iomem);
     return true;
 }
 
diff --git a/hw/pc.h b/hw/pc.h
index 4515006..b7b7e40 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -55,7 +55,8 @@ static inline bool parallel_init(int index, CharDriverState *chr)
     return true;
 }
 
-bool parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
+bool parallel_mm_init(MemoryRegion *address_space,
+                      target_phys_addr_t base, int it_shift, qemu_irq irq,
                       CharDriverState *chr);
 
 /* i8259.c */
commit c601785091d72dc95b13a40c09e4fd6a3ccc3197
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Oct 6 16:34:39 2011 +0200

    jazz_led: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/jazz_led.c b/hw/jazz_led.c
index eb472a0..6fab334 100644
--- a/hw/jazz_led.c
+++ b/hw/jazz_led.c
@@ -43,6 +43,7 @@ typedef enum {
 } screen_state_t;
 
 typedef struct LedState {
+    MemoryRegion iomem;
     uint8_t segments;
     DisplayState *ds;
     screen_state_t state;
@@ -140,16 +141,12 @@ static void led_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
 #endif
 }
 
-static CPUReadMemoryFunc * const led_read[3] = {
-    led_readb,
-    led_readw,
-    led_readl,
-};
-
-static CPUWriteMemoryFunc * const led_write[3] = {
-    led_writeb,
-    led_writew,
-    led_writel,
+static const MemoryRegionOps led_ops = {
+    .old_mmio = {
+        .read = { led_readb, led_readw, led_readl, },
+        .write = { led_writeb, led_writew, led_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 /***********************************************************/
@@ -307,18 +304,16 @@ static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
     dpy_update(s->ds, 0, 0, 2, 1);
 }
 
-void jazz_led_init(target_phys_addr_t base)
+void jazz_led_init(MemoryRegion *address_space, target_phys_addr_t base)
 {
     LedState *s;
-    int io;
 
     s = g_malloc0(sizeof(LedState));
 
     s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND;
 
-    io = cpu_register_io_memory(led_read, led_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 1, io);
+    memory_region_init_io(&s->iomem, &led_ops, s, "led", 1);
+    memory_region_add_subregion(address_space, base, &s->iomem);
 
     s->ds = graphic_console_init(jazz_led_update_display,
                                  jazz_led_invalidate_display,
diff --git a/hw/mips.h b/hw/mips.h
index 6fa9a3a..0d4bf25 100644
--- a/hw/mips.h
+++ b/hw/mips.h
@@ -2,6 +2,8 @@
 #define HW_MIPS_H
 /* Definitions for mips board emulation.  */
 
+#include "memory.h"
+
 /* gt64xxx.c */
 PCIBus *gt64120_register(qemu_irq *pic);
 
@@ -9,7 +11,7 @@ PCIBus *gt64120_register(qemu_irq *pic);
 PCIBus *bonito_init(qemu_irq *pic);
 
 /* jazz_led.c */
-void jazz_led_init(target_phys_addr_t base);
+void jazz_led_init(MemoryRegion *address_space, target_phys_addr_t base);
 
 /* rc4030.c */
 typedef struct rc4030DMAState *rc4030_dma;
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 14beea2..6e657dd 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -287,7 +287,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
     sysbus_mmio_map(sysbus, 0, 0x80009000);
 
     /* LED indicator */
-    jazz_led_init(0x8000f000);
+    jazz_led_init(address_space, 0x8000f000);
 }
 
 static
commit 0af58e58a106eda29d21a6a32ae0f81909444fe4
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Oct 6 12:52:27 2011 +0200

    shix: convert to memory API
    
    RAM wasn't actually allocated, only used, so fix that as well.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/shix.c b/hw/shix.c
index dbf4764..670ddb5 100644
--- a/hw/shix.c
+++ b/hw/shix.c
@@ -32,6 +32,7 @@
 #include "sysemu.h"
 #include "boards.h"
 #include "loader.h"
+#include "exec-memory.h"
 
 #define BIOS_FILENAME "shix_bios.bin"
 #define BIOS_ADDRESS 0xA0000000
@@ -44,6 +45,9 @@ static void shix_init(ram_addr_t ram_size,
     int ret;
     CPUState *env;
     struct SH7750State *s;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *rom = g_new(MemoryRegion, 1);
+    MemoryRegion *sdram = g_new(MemoryRegion, 2);
     
     if (!cpu_model)
         cpu_model = "any";
@@ -53,11 +57,15 @@ static void shix_init(ram_addr_t ram_size,
 
     /* Allocate memory space */
     printf("Allocating ROM\n");
-    cpu_register_physical_memory(0x00000000, 0x00004000, IO_MEM_ROM);
+    memory_region_init_ram(rom, NULL, "shix.rom", 0x4000);
+    memory_region_set_readonly(rom, true);
+    memory_region_add_subregion(sysmem, 0x00000000, rom);
     printf("Allocating SDRAM 1\n");
-    cpu_register_physical_memory(0x08000000, 0x01000000, 0x00004000);
+    memory_region_init_ram(&sdram[0], NULL, "shix.sdram1", 0x01000000);
+    memory_region_add_subregion(sysmem, 0x08000000, &sdram[0]);
     printf("Allocating SDRAM 2\n");
-    cpu_register_physical_memory(0x0c000000, 0x01000000, 0x01004000);
+    memory_region_init_ram(&sdram[1], NULL, "shix.sdram2", 0x01000000);
+    memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]);
 
     /* Load BIOS in 0 (and access it through P2, 0xA0000000) */
     if (bios_name == NULL)
commit 333b13fc3c6b6172d0645aa4986257824e5c5745
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Oct 5 18:51:29 2011 +0200

    virtex_ml507: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
index 5ea0e60..6ffb896 100644
--- a/hw/virtex_ml507.c
+++ b/hw/virtex_ml507.c
@@ -192,7 +192,7 @@ static void virtex_init(ram_addr_t ram_size,
     CPUState *env;
     target_phys_addr_t ram_base = 0;
     DriveInfo *dinfo;
-    ram_addr_t phys_ram;
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
     qemu_irq irq[32], *cpu_irq;
     int kernel_size;
     int i;
@@ -205,8 +205,8 @@ static void virtex_init(ram_addr_t ram_size,
     env = ppc440_init_xilinx(&ram_size, 1, cpu_model, 400000000);
     qemu_register_reset(main_cpu_reset, env);
 
-    phys_ram = qemu_ram_alloc(NULL, "ram", ram_size);
-    cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM);
+    memory_region_init_ram(phys_ram, NULL, "ram", ram_size);
+    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi01_register(0xfc000000, NULL, "virtex.flash", FLASH_SIZE,
commit e6d17b056de3691748ff047c1b5baf012799fef8
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Oct 5 18:49:54 2011 +0200

    vexpress: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/vexpress.c b/hw/vexpress.c
index 0940a26..08c93d5 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -25,6 +25,7 @@
 #include "net.h"
 #include "sysemu.h"
 #include "boards.h"
+#include "exec-memory.h"
 
 #define SMP_BOOT_ADDR 0xe0000000
 
@@ -40,7 +41,12 @@ static void vexpress_a9_init(ram_addr_t ram_size,
                      const char *initrd_filename, const char *cpu_model)
 {
     CPUState *env = NULL;
-    ram_addr_t ram_offset, vram_offset, sram_offset;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *lowram = g_new(MemoryRegion, 1);
+    MemoryRegion *vram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    MemoryRegion *hackram = g_new(MemoryRegion, 1);
     DeviceState *dev, *sysctl, *pl041;
     SysBusDevice *busdev;
     qemu_irq *irqp;
@@ -71,7 +77,7 @@ static void vexpress_a9_init(ram_addr_t ram_size,
         exit(1);
     }
 
-    ram_offset = qemu_ram_alloc(NULL, "vexpress.highmem", ram_size);
+    memory_region_init_ram(ram, NULL, "vexpress.highmem", ram_size);
     low_ram_size = ram_size;
     if (low_ram_size > 0x4000000) {
         low_ram_size = 0x4000000;
@@ -80,9 +86,9 @@ static void vexpress_a9_init(ram_addr_t ram_size,
      * address space should in theory be remappable to various
      * things including ROM or RAM; we always map the RAM there.
      */
-    cpu_register_physical_memory(0x0, low_ram_size, ram_offset | IO_MEM_RAM);
-    cpu_register_physical_memory(0x60000000, ram_size,
-                                 ram_offset | IO_MEM_RAM);
+    memory_region_init_alias(lowram, "vexpress.lowmem", ram, 0, low_ram_size);
+    memory_region_add_subregion(sysmem, 0x0, lowram);
+    memory_region_add_subregion(sysmem, 0x60000000, ram);
 
     /* 0x1e000000 A9MPCore (SCU) private memory region */
     dev = qdev_create(NULL, "a9mpcore_priv");
@@ -175,17 +181,15 @@ static void vexpress_a9_init(ram_addr_t ram_size,
     /* CS4: NOR1 flash          : 0x44000000 .. 0x48000000 */
     /* CS2: SRAM                : 0x48000000 .. 0x4a000000 */
     sram_size = 0x2000000;
-    sram_offset = qemu_ram_alloc(NULL, "vexpress.sram", sram_size);
-    cpu_register_physical_memory(0x48000000, sram_size,
-                                 sram_offset | IO_MEM_RAM);
+    memory_region_init_ram(sram, NULL, "vexpress.sram", sram_size);
+    memory_region_add_subregion(sysmem, 0x48000000, sram);
 
     /* CS3: USB, ethernet, VRAM : 0x4c000000 .. 0x50000000 */
 
     /* 0x4c000000 Video RAM */
     vram_size = 0x800000;
-    vram_offset = qemu_ram_alloc(NULL, "vexpress.vram", vram_size);
-    cpu_register_physical_memory(0x4c000000, vram_size,
-                                 vram_offset | IO_MEM_RAM);
+    memory_region_init_ram(vram, NULL, "vexpress.vram", vram_size);
+    memory_region_add_subregion(sysmem, 0x4c000000, vram);
 
     /* 0x4e000000 LAN9118 Ethernet */
     if (nd_table[0].vlan) {
@@ -198,9 +202,8 @@ static void vexpress_a9_init(ram_addr_t ram_size,
        startup code.  I guess this works on real hardware because the
        BootROM happens to be in ROM/flash or in memory that isn't clobbered
        until after Linux boots the secondary CPUs.  */
-    ram_offset = qemu_ram_alloc(NULL, "vexpress.hack", 0x1000);
-    cpu_register_physical_memory(SMP_BOOT_ADDR, 0x1000,
-                                 ram_offset | IO_MEM_RAM);
+    memory_region_init_ram(hackram, NULL, "vexpress.hack", 0x1000);
+    memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, hackram);
 
     vexpress_binfo.ram_size = ram_size;
     vexpress_binfo.kernel_filename = kernel_filename;
commit 62ceeb2c223e297603931b292fd6539f05e764fb
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Oct 5 18:41:32 2011 +0200

    versatilepb: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 6370600..e4aeea4 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -17,12 +17,14 @@
 #include "usb-ohci.h"
 #include "boards.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 /* Primary interrupt controller.  */
 
 typedef struct vpb_sic_state
 {
   SysBusDevice busdev;
+  MemoryRegion iomem;
   uint32_t level;
   uint32_t mask;
   uint32_t pic_enable;
@@ -75,7 +77,8 @@ static void vpb_sic_set_irq(void *opaque, int irq, int level)
     vpb_sic_update(s);
 }
 
-static uint32_t vpb_sic_read(void *opaque, target_phys_addr_t offset)
+static uint64_t vpb_sic_read(void *opaque, target_phys_addr_t offset,
+                             unsigned size)
 {
     vpb_sic_state *s = (vpb_sic_state *)opaque;
 
@@ -97,7 +100,7 @@ static uint32_t vpb_sic_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void vpb_sic_write(void *opaque, target_phys_addr_t offset,
-                          uint32_t value)
+                          uint64_t value, unsigned size)
 {
     vpb_sic_state *s = (vpb_sic_state *)opaque;
 
@@ -131,22 +134,15 @@ static void vpb_sic_write(void *opaque, target_phys_addr_t offset,
     vpb_sic_update(s);
 }
 
-static CPUReadMemoryFunc * const vpb_sic_readfn[] = {
-   vpb_sic_read,
-   vpb_sic_read,
-   vpb_sic_read
-};
-
-static CPUWriteMemoryFunc * const vpb_sic_writefn[] = {
-   vpb_sic_write,
-   vpb_sic_write,
-   vpb_sic_write
+static const MemoryRegionOps vpb_sic_ops = {
+    .read = vpb_sic_read,
+    .write = vpb_sic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int vpb_sic_init(SysBusDevice *dev)
 {
     vpb_sic_state *s = FROM_SYSBUS(vpb_sic_state, dev);
-    int iomemtype;
     int i;
 
     qdev_init_gpio_in(&dev->qdev, vpb_sic_set_irq, 32);
@@ -154,10 +150,8 @@ static int vpb_sic_init(SysBusDevice *dev)
         sysbus_init_irq(dev, &s->parent[i]);
     }
     s->irq = 31;
-    iomemtype = cpu_register_io_memory(vpb_sic_readfn,
-                                       vpb_sic_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &vpb_sic_ops, s, "vpb-sic", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     return 0;
 }
 
@@ -176,7 +170,8 @@ static void versatile_init(ram_addr_t ram_size,
                      int board_id)
 {
     CPUState *env;
-    ram_addr_t ram_offset;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
     qemu_irq *cpu_pic;
     qemu_irq pic[32];
     qemu_irq sic[32];
@@ -195,10 +190,10 @@ static void versatile_init(ram_addr_t ram_size,
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    ram_offset = qemu_ram_alloc(NULL, "versatile.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "versatile.ram", ram_size);
     /* ??? RAM should repeat to fill physical memory space.  */
     /* SDRAM at address zero.  */
-    cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
+    memory_region_add_subregion(sysmem, 0, ram);
 
     sysctl = qdev_create(NULL, "realview_sysctl");
     qdev_prop_set_uint32(sysctl, "sys_id", 0x41007004);
commit 04d66689978ba9098bed6210bf4d1befd448b179
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Oct 5 18:29:06 2011 +0200

    tosa: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/tosa.c b/hw/tosa.c
index b992b99..67a71fe 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -208,6 +208,7 @@ static void tosa_init(ram_addr_t ram_size,
                 const char *initrd_filename, const char *cpu_model)
 {
     MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *rom = g_new(MemoryRegion, 1);
     PXA2xxState *cpu;
     TC6393xbState *tmio;
     DeviceState *scp0, *scp1;
@@ -217,8 +218,9 @@ static void tosa_init(ram_addr_t ram_size,
 
     cpu = pxa255_init(address_space_mem, tosa_binfo.ram_size);
 
-    cpu_register_physical_memory(0, TOSA_ROM,
-                    qemu_ram_alloc(NULL, "tosa.rom", TOSA_ROM) | IO_MEM_ROM);
+    memory_region_init_ram(rom, NULL, "tosa.rom", TOSA_ROM);
+    memory_region_set_readonly(rom, true);
+    memory_region_add_subregion(address_space_mem, 0, rom);
 
     tmio = tc6393xb_init(address_space_mem, 0x10000000,
             qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_TC6393XB_INT));
commit c7662daaa2898fa5a9a39bc51985cd1dd08af988
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Nov 16 12:37:17 2011 +0100

    usb-host: add usb_host_do_reset function.
    
    Add a special function to reset the host usb device.  It tracks the time
    needed by the USBDEVFS_RESET ioctl and prints a warning in case it needs
    too long.  Usually it should be finished in 200 - 300 miliseconds.
    Warning threshold is one second.
    
    Intention is to help troubleshooting by indicating that the usb device
    stopped responding even to a reset request and is possibly broken.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/usb-linux.c b/usb-linux.c
index d4426ea..ab4c693 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -148,6 +148,25 @@ 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_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;
@@ -606,7 +625,7 @@ static void usb_host_handle_reset(USBDevice *dev)
 
     trace_usb_host_reset(s->bus_num, s->addr);
 
-    ioctl(s->fd, USBDEVFS_RESET);
+    usb_host_do_reset(s);;
 
     usb_host_claim_interfaces(s, 0);
     usb_linux_update_endp_table(s);
@@ -1370,7 +1389,7 @@ static int usb_host_close(USBHostDevice *dev)
     if (dev->dev.attached) {
         usb_device_detach(&dev->dev);
     }
-    ioctl(dev->fd, USBDEVFS_RESET);
+    usb_host_do_reset(dev);
     close(dev->fd);
     dev->fd = -1;
     return 0;
@@ -1381,7 +1400,7 @@ static void usb_host_exit_notifier(struct Notifier *n, void *data)
     USBHostDevice *s = container_of(n, USBHostDevice, exit);
 
     if (s->fd != -1) {
-        ioctl(s->fd, USBDEVFS_RESET);
+        usb_host_do_reset(s);;
     }
 }
 
commit 5bb1cbac4fdb1ca28f33c8d68538d03e3db7c160
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Nov 23 11:38:01 2011 +0100

    vpc: Add missing error handling in alloc_block
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/vpc.c b/block/vpc.c
index 75d7d4a..89a5ee2 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -362,8 +362,11 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num)
 
     // Initialize the block's bitmap
     memset(bitmap, 0xff, s->bitmap_size);
-    bdrv_pwrite_sync(bs->file, s->free_data_block_offset, bitmap,
+    ret = bdrv_pwrite_sync(bs->file, s->free_data_block_offset, bitmap,
         s->bitmap_size);
+    if (ret < 0) {
+        return ret;
+    }
 
     // Write new footer (the old one will be overwritten)
     s->free_data_block_offset += s->block_size + s->bitmap_size;
commit 6ac5f3881fd9880f55e30c5f5bd9984d9d47fd62
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Nov 22 16:57:34 2011 +0100

    vdi: Fix memory leak
    
    The block map is allocated in vdi_open, but was never freed.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vdi.c b/block/vdi.c
index 7dda522..02da6b4 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -949,6 +949,9 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
 static void vdi_close(BlockDriverState *bs)
 {
     BDRVVdiState *s = bs->opaque;
+
+    g_free(s->bmap);
+
     migrate_del_blocker(s->migration_blocker);
     error_free(s->migration_blocker);
 }
commit 3397f0cb483b40785678d2328da584c8a35c358c
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Nov 22 16:52:13 2011 +0100

    vvfat: Add migration blocker
    
    vvfat caches more or less everything when in writable mode. For migration
    to work, it would have to be invalidated. Block migration for now when
    in writable mode (default is readonly).
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vvfat.c b/block/vvfat.c
index 131680f..a310ce8 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -27,6 +27,7 @@
 #include "qemu-common.h"
 #include "block_int.h"
 #include "module.h"
+#include "migration.h"
 
 #ifndef S_IWGRP
 #define S_IWGRP 0
@@ -350,6 +351,8 @@ typedef struct BDRVVVFATState {
     array_t commits;
     const char* path;
     int downcase_short_names;
+
+    Error *migration_blocker;
 } BDRVVVFATState;
 
 /* take the sector position spos and convert it to Cylinder/Head/Sector position
@@ -1073,6 +1076,15 @@ DLOG(if (stderr == NULL) {
 
     //    assert(is_consistent(s));
     qemu_co_mutex_init(&s->lock);
+
+    /* Disable migration when vvfat is used rw */
+    if (s->qcow) {
+        error_set(&s->migration_blocker,
+                  QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+                  "vvfat (rw)", bs->device_name, "live migration");
+        migrate_add_blocker(s->migration_blocker);
+    }
+
     return 0;
 }
 
@@ -2829,6 +2841,11 @@ static void vvfat_close(BlockDriverState *bs)
     array_free(&(s->directory));
     array_free(&(s->mapping));
     g_free(s->cluster_buffer);
+
+    if (s->qcow) {
+        migrate_del_blocker(s->migration_blocker);
+        error_free(s->migration_blocker);
+    }
 }
 
 static BlockDriver bdrv_vvfat = {
commit 612ff3d8876a6df0484aa6ebb5cae4575f7514c5
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Nov 22 16:51:12 2011 +0100

    vpc: Add migration blocker
    
    vpc caches the BAT. For migration to work, it would have to be
    invalidated. Block migration for now.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vpc.c b/block/vpc.c
index 39a3247..75d7d4a 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -25,6 +25,7 @@
 #include "qemu-common.h"
 #include "block_int.h"
 #include "module.h"
+#include "migration.h"
 
 /**************************************************************/
 
@@ -128,6 +129,8 @@ typedef struct BDRVVPCState {
 
     uint64_t last_bitmap;
 #endif
+
+    Error *migration_blocker;
 } BDRVVPCState;
 
 static uint32_t vpc_checksum(uint8_t* buf, size_t size)
@@ -228,6 +231,13 @@ static int vpc_open(BlockDriverState *bs, int flags)
 #endif
 
     qemu_co_mutex_init(&s->lock);
+
+    /* Disable migration when VHD images are used */
+    error_set(&s->migration_blocker,
+              QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+              "vpc", bs->device_name, "live migration");
+    migrate_add_blocker(s->migration_blocker);
+
     return 0;
  fail:
     return err;
@@ -651,6 +661,9 @@ static void vpc_close(BlockDriverState *bs)
 #ifdef CACHE
     g_free(s->pageentry_u8);
 #endif
+
+    migrate_del_blocker(s->migration_blocker);
+    error_free(s->migration_blocker);
 }
 
 static QEMUOptionParameter vpc_create_options[] = {
commit 2bc3166c22aeeb5cd7b8f21104f4744f08c7a288
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Nov 22 16:50:27 2011 +0100

    vmdk: Add migration blocker
    
    VMDK caches L2 tables. For migration to work, they would have to be
    invalidated. Block migration for now.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index 96f7d5d..f544159 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -26,6 +26,7 @@
 #include "qemu-common.h"
 #include "block_int.h"
 #include "module.h"
+#include "migration.h"
 #include <zlib.h>
 
 #define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
@@ -97,6 +98,7 @@ typedef struct BDRVVmdkState {
     int num_extents;
     /* Extent array with num_extents entries, ascend ordered by address */
     VmdkExtent *extents;
+    Error *migration_blocker;
 } BDRVVmdkState;
 
 typedef struct VmdkMetaData {
@@ -659,7 +661,14 @@ static int vmdk_open(BlockDriverState *bs, int flags)
     }
     s->parent_cid = vmdk_read_cid(bs, 1);
     qemu_co_mutex_init(&s->lock);
-    return ret;
+
+    /* Disable migration when VMDK images are used */
+    error_set(&s->migration_blocker,
+              QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+              "vmdk", bs->device_name, "live migration");
+    migrate_add_blocker(s->migration_blocker);
+
+    return 0;
 
 fail:
     vmdk_free_extents(bs);
@@ -1504,7 +1513,12 @@ exit:
 
 static void vmdk_close(BlockDriverState *bs)
 {
+    BDRVVmdkState *s = bs->opaque;
+
     vmdk_free_extents(bs);
+
+    migrate_del_blocker(s->migration_blocker);
+    error_free(s->migration_blocker);
 }
 
 static coroutine_fn int vmdk_co_flush(BlockDriverState *bs)
commit fc9d106c8dfe1c4afe0e127dfcd2764e63f0efb0
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Nov 22 16:46:26 2011 +0100

    vdi: Add migration blocker
    
    vdi caches the block map. For migration to work, it would have to be
    invalidated. Block migration for now.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vdi.c b/block/vdi.c
index 684a4a8..7dda522 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -52,6 +52,7 @@
 #include "qemu-common.h"
 #include "block_int.h"
 #include "module.h"
+#include "migration.h"
 
 #if defined(CONFIG_UUID)
 #include <uuid/uuid.h>
@@ -203,6 +204,8 @@ typedef struct {
     uint32_t bmap_sector;
     /* VDI header (converted to host endianness). */
     VdiHeader header;
+
+    Error *migration_blocker;
 } BDRVVdiState;
 
 /* Change UUID from little endian (IPRT = VirtualBox format) to big endian
@@ -454,6 +457,12 @@ static int vdi_open(BlockDriverState *bs, int flags)
         goto fail_free_bmap;
     }
 
+    /* Disable migration when vdi images are used */
+    error_set(&s->migration_blocker,
+              QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+              "vdi", bs->device_name, "live migration");
+    migrate_add_blocker(s->migration_blocker);
+
     return 0;
 
  fail_free_bmap:
@@ -939,6 +948,9 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
 
 static void vdi_close(BlockDriverState *bs)
 {
+    BDRVVdiState *s = bs->opaque;
+    migrate_del_blocker(s->migration_blocker);
+    error_free(s->migration_blocker);
 }
 
 static coroutine_fn int vdi_co_flush(BlockDriverState *bs)
commit fd9f102c3e38ac606ef8ee2a5ba0130f7c87422f
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Nov 22 16:44:45 2011 +0100

    qcow: Add migration blocker
    
    qcow caches L2 tables. For migration to work, they would have to be
    invalidated. Block migration for now.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow.c b/block/qcow.c
index adecee0..4814ed0 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -26,6 +26,7 @@
 #include "module.h"
 #include <zlib.h>
 #include "aes.h"
+#include "migration.h"
 
 /**************************************************************/
 /* QEMU COW block driver with compression and encryption support */
@@ -74,6 +75,7 @@ typedef struct BDRVQcowState {
     AES_KEY aes_encrypt_key;
     AES_KEY aes_decrypt_key;
     CoMutex lock;
+    Error *migration_blocker;
 } BDRVQcowState;
 
 static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
@@ -160,6 +162,12 @@ static int qcow_open(BlockDriverState *bs, int flags)
         bs->backing_file[len] = '\0';
     }
 
+    /* Disable migration when qcow images are used */
+    error_set(&s->migration_blocker,
+              QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+              "qcow", bs->device_name, "live migration");
+    migrate_add_blocker(s->migration_blocker);
+
     qemu_co_mutex_init(&s->lock);
     return 0;
 
@@ -604,10 +612,14 @@ static int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
 static void qcow_close(BlockDriverState *bs)
 {
     BDRVQcowState *s = bs->opaque;
+
     g_free(s->l1_table);
     g_free(s->l2_cache);
     g_free(s->cluster_cache);
     g_free(s->cluster_data);
+
+    migrate_del_blocker(s->migration_blocker);
+    error_free(s->migration_blocker);
 }
 
 static int qcow_create(const char *filename, QEMUOptionParameter *options)
commit 335b8d2068cbc56ce86b3c89b0fcd1c1eb4b61e2
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Nov 18 10:49:25 2011 +0100

    usb-ehci: add register names
    
    The mmio register name list only had the names for four port status
    registers.  We emulate a EHCI adapter with six ports though, the last
    two ones are listed as "unknown" in traces.  Fix it.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 2609aba..a946e1d 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -467,6 +467,8 @@ static const char *ehci_mmio_names[] = {
     [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",
 };
 
commit aac882e7ce52f12f1b0712534c2456acea4f03d7
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Nov 18 10:48:47 2011 +0100

    usb-ehci: codestyle fixups
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 3eea94d..2609aba 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -437,37 +437,37 @@ struct EHCIState {
     } 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",
+    [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",
-    [ CONFIGFLAG ]       = "CONFIGFLAG",
+    [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",
+    [CONFIGFLAG]        = "CONFIGFLAG",
 };
 
 static const char *nr2str(const char **n, size_t len, uint32_t nr)
commit 20d183b6f0e14424d245493e7bc6fd6d14a08436
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Nov 23 13:31:08 2011 +0100

    usb-hub: implement reset
    
    based on a patch from hkran at linux.vnet.ibm.com
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 5b48763..e195937 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -222,7 +222,22 @@ static void usb_hub_complete(USBPort *port, USBPacket *packet)
 
 static void usb_hub_handle_reset(USBDevice *dev)
 {
-    /* XXX: do it */
+    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,
@@ -497,9 +512,8 @@ static int usb_hub_initfn(USBDevice *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);
-        port->wPortStatus = PORT_STAT_POWER;
-        port->wPortChange = 0;
     }
+    usb_hub_handle_reset(dev);
     return 0;
 }
 
commit be85c90b74f56dca51782fa3080fcdf88593e045
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Tue Nov 22 17:27:15 2011 +0000

    fix out of tree build
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/Makefile b/Makefile
index 7c93739..b06599c 100644
--- a/Makefile
+++ b/Makefile
@@ -168,7 +168,7 @@ check-qjson: check-qjson.o $(qobject-obj-y) $(tools-obj-y)
 test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(tools-obj-y)
 
 $(qapi-obj-y): $(GENERATED_HEADERS)
-qapi-dir := qapi-generated
+qapi-dir := $(SRC_PATH)/qapi-generated
 test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
 
commit 4abf12f4ea866779b493ecf4606bd0b6d35f8348
Author: Julian Pidancet <julian.pidancet at gmail.com>
Date:   Wed Nov 23 01:03:15 2011 +0000

    rtl8139: Fix invalid IO access alignment
    
    This patch makes iPXE work with the rtl8139 emulation. The rtl8139
    driver in iPXE issues a 16bit access on the ChipCmd register
    (offset 0x37) to check the status of the rx buffer. The offset of the
    ioport access was getting fixed up to 0x36 in qemu, causing the value
    read in iPXE to be invalid.
    
    This fixes an issue with iPXE reporting timeouts during TFTP transfers.
    
    Reposting this here because it is trivial enough and the original post
    on qemu-devel didn't attract much attention.
    
    Also, the inw() which was causing the issue has been replaced with an
    inb() in upstream iPXE:
    https://git.ipxe.org/ipxe.git/commit/91dd64ad25baa27954a7518e73df4fca8a2d0c93
    
    Signed-off-by: Julian Pidancet <julian.pidancet at gmail.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 4c37993..aa8ed0a 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -1971,7 +1971,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
     cplus_tx_ring_desc += 16 * descriptor;
 
     DPRINTF("+++ C+ mode reading TX descriptor %d from host memory at "
-        "%08x0x%08x = 0x"DMA_ADDR_FMT"\n", descriptor, s->TxAddr[1],
+        "%08x %08x = 0x"DMA_ADDR_FMT"\n", descriptor, s->TxAddr[1],
         s->TxAddr[0], cplus_tx_ring_desc);
 
     uint32_t val, txdw0,txdw1,txbufLO,txbufHI;
@@ -2713,8 +2713,6 @@ static void rtl8139_io_writeb(void *opaque, uint8_t addr, uint32_t val)
 {
     RTL8139State *s = opaque;
 
-    addr &= 0xff;
-
     switch (addr)
     {
         case MAC0 ... MAC0+5:
@@ -2800,8 +2798,6 @@ static void rtl8139_io_writew(void *opaque, uint8_t addr, uint32_t val)
 {
     RTL8139State *s = opaque;
 
-    addr &= 0xfe;
-
     switch (addr)
     {
         case IntrMask:
@@ -2900,8 +2896,6 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val)
 {
     RTL8139State *s = opaque;
 
-    addr &= 0xfc;
-
     switch (addr)
     {
         case RxMissed:
@@ -2969,8 +2963,6 @@ static uint32_t rtl8139_io_readb(void *opaque, uint8_t addr)
     RTL8139State *s = opaque;
     int ret;
 
-    addr &= 0xff;
-
     switch (addr)
     {
         case MAC0 ... MAC0+5:
@@ -3043,8 +3035,6 @@ static uint32_t rtl8139_io_readw(void *opaque, uint8_t addr)
     RTL8139State *s = opaque;
     uint32_t ret;
 
-    addr &= 0xfe; /* mask lower bit */
-
     switch (addr)
     {
         case IntrMask:
@@ -3120,8 +3110,6 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr)
     RTL8139State *s = opaque;
     uint32_t ret;
 
-    addr &= 0xfc; /* also mask low 2 bits */
-
     switch (addr)
     {
         case RxMissed:
commit be35cbbc8802eeba750c300c35339d69929989a6
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Nov 22 13:20:14 2011 +0100

    usb-hub: wakeup on detach too.
    
    When detaching devices from the usb hub we must wakeup too,
    otherwise the host misses the detach event.
    
    Commit 4a33a9ea06f6fbb08d8311a7cfed72975344f9ab does the
    same for device attach.
    
    Found by hkran at linux.vnet.ibm.com
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 3eb0f1a..5b48763 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -171,6 +171,8 @@ static void usb_hub_detach(USBPort *port1)
     USBHubState *s = port1->opaque;
     USBHubPort *port = &s->ports[port1->index];
 
+    usb_wakeup(&s->dev);
+
     /* Let upstream know the device on this port is gone */
     s->dev.port->ops->child_detach(s->dev.port, port1->dev);
 
commit f462141f18ffdd75847f6459ef83d90b831d12c0
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Nov 22 12:48:14 2011 +0100

    usb: fix usb_qdev_init error handling.
    
    qdev doesn't call the ->exit callback on ->init failures, so we have to
    take care ourself that we cleanup property on errors.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index f8b9807..8cafb76 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -9,6 +9,7 @@ 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",
@@ -75,12 +76,23 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
     dev->auto_attach = 1;
     QLIST_INIT(&dev->strings);
     rc = usb_claim_port(dev);
-    if (rc == 0) {
-        rc = dev->info->init(dev);
+    if (rc != 0) {
+        goto err;
     }
-    if (rc == 0 && dev->auto_attach) {
+    rc = dev->info->init(dev);
+    if (rc != 0) {
+        goto err;
+    }
+    if (dev->auto_attach) {
         rc = usb_device_attach(dev);
+        if (rc != 0) {
+            goto err;
+        }
     }
+    return 0;
+
+err:
+    usb_qdev_exit(qdev);
     return rc;
 }
 
commit 2af2a1b8d05a1a64c5005ed930137632b9d5aa22
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Nov 22 12:39:58 2011 +0100

    usb: make usb_create_simple catch and pass up errors.
    
    Use qdev_init() instead of qdev_init_nofail(), usb device initialization
    can fail, most common case being port and device speed mismatch.  Handle
    failures correctly and pass up NULL pointers then.
    
    Also fixup usb_create_simple() callers (only one was buggy) to properly
    check for NULL pointers before referncing the usb_create_simple() return
    value.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index 529fa33..f30eec1 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -528,6 +528,9 @@ USBDevice *usb_bt_init(HCIInfo *hci)
     if (!hci)
         return NULL;
     dev = usb_create_simple(NULL /* FIXME */, "usb-bt-dongle");
+    if (!dev) {
+        return NULL;
+    }
     s = DO_UPCAST(struct USBBtState, dev, dev);
     s->dev.opaque = s;
 
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 93f640d..f8b9807 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -139,10 +139,17 @@ USBDevice *usb_create(USBBus *bus, const char *name)
 USBDevice *usb_create_simple(USBBus *bus, const char *name)
 {
     USBDevice *dev = usb_create(bus, name);
+    int rc;
+
     if (!dev) {
-        hw_error("Failed to create USB device '%s'\n", name);
+        error_report("Failed to create USB device '%s'\n", name);
+        return NULL;
+    }
+    rc = qdev_init(&dev->qdev);
+    if (rc < 0) {
+        error_report("Failed to initialize USB device '%s'\n", name);
+        return NULL;
     }
-    qdev_init_nofail(&dev->qdev);
     return dev;
 }
 
commit e30e5eb6136aa3311dad4ca90f6546e05ae98f92
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Nov 16 15:45:59 2011 +0100

    slirp: Clean up net_slirp_hostfwd_remove()'s use of get_str_sep()
    
    get_str_sep() can fail, but net_slirp_hostfwd_remove() doesn't check.
    Works, because it initializes buf[] to "", which get_str_sep() doesn't
    touch when it fails.  Coverity doesn't like it, and neither do I.
    
    Change it to work exactly like slirp_hostfwd().
    
    Acked-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/net/slirp.c b/net/slirp.c
index c6cda5d..6646ecb 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -305,7 +305,7 @@ void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict)
 {
     struct in_addr host_addr = { .s_addr = INADDR_ANY };
     int host_port;
-    char buf[256] = "";
+    char buf[256];
     const char *src_str, *p;
     SlirpState *s;
     int is_udp = 0;
@@ -325,11 +325,10 @@ void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict)
         return;
     }
 
-    if (!src_str || !src_str[0])
-        goto fail_syntax;
-
     p = src_str;
-    get_str_sep(buf, sizeof(buf), &p, ':');
+    if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+        goto fail_syntax;
+    }
 
     if (!strcmp(buf, "tcp") || buf[0] == '\0') {
         is_udp = 0;
commit c3fecea50dc0f27198b8658a0c9c4fbfdd0f95db
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Tue Nov 22 10:56:58 2011 +0800

    sheepdog: Avoid deadlock in error path
    
    s->lock should be unlocked before leaving add_aio_request.
    
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index 9f80609..62f1f3a 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -1116,6 +1116,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
     /* send a header */
     ret = do_write(s->fd, &hdr, sizeof(hdr));
     if (ret) {
+        qemu_co_mutex_unlock(&s->lock);
         error_report("failed to send a req, %s", strerror(errno));
         return -EIO;
     }
@@ -1123,6 +1124,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
     if (wlen) {
         ret = do_writev(s->fd, iov, wlen, aio_req->iov_offset);
         if (ret) {
+            qemu_co_mutex_unlock(&s->lock);
             error_report("failed to send a data, %s", strerror(errno));
             return -EIO;
         }
commit 28b77657cfb44cdcc379997340701d73432b9007
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Nov 18 16:32:02 2011 +0100

    scsi-generic: add as boot device
    
    There is no reason why a scsi-generic device cannot boot if it has
    the right type, and indeed it provides already a bootindex property.
    So register those devices too.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 9594cc1..e62044f 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -413,6 +413,10 @@ static int scsi_generic_initfn(SCSIDevice *s)
     /* define device state */
     s->type = scsiid.scsi_type;
     DPRINTF("device type %d\n", s->type);
+    if (s->type == TYPE_DISK || s->type == TYPE_ROM) {
+        add_boot_device_path(s->conf.bootindex, &s->qdev, NULL);
+    }
+
     switch (s->type) {
     case TYPE_TAPE:
         s->blocksize = get_stream_blocksize(s->conf.bs);
@@ -459,6 +463,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
 
 static SCSIDeviceInfo scsi_generic_info = {
     .qdev.name    = "scsi-generic",
+    .qdev.fw_name = "disk",
     .qdev.desc    = "pass through generic scsi device (/dev/sg*)",
     .qdev.size    = sizeof(SCSIDevice),
     .qdev.reset   = scsi_generic_reset,
commit 795928f61daff10b06bb21e837bc5bf0227cf076
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Nov 18 17:03:45 2011 +0100

    scsi: fix fw path
    
    The pre-1.0 firmware path for SCSI devices already included the LUN
    using the suffix argument to add_boot_device_path.  Avoid that it is
    included twice, and convert the colons to commas for consistency with
    other kinds of devices
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 2feeaa2..64e709e 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -1370,8 +1370,8 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
     SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev);
     char path[100];
 
-    snprintf(path, sizeof(path), "%s@%d,%d,%d", qdev_fw_name(dev),
-             d->channel, d->id, d->lun);
+    snprintf(path, sizeof(path), "channel@%x/%s@%x,%x", d->channel,
+             qdev_fw_name(dev), d->id, d->lun);
 
     return strdup(path);
 }
commit ce4e7e4661af433674f349ccdd5709b4b7a8b2fd
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Nov 18 16:32:00 2011 +0100

    usb-msd: do not register twice in the boot order
    
    USB mass storage devices are registered twice in the boot order.
    To avoid having to keep the two paths in sync, pass the bootindex
    property down to the scsi-disk device and let it register itself.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index b59be2a..12f61fe 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -91,7 +91,8 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
      */
     dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
     dinfo->bus = scsibus->busnr;
-    scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, false);
+    scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit,
+                                        false, -1);
     if (!scsidev) {
         return -1;
     }
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 3a2a7bb..2feeaa2 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -162,7 +162,7 @@ void scsi_qdev_register(SCSIDeviceInfo *info)
 
 /* handle legacy '-drive if=scsi,...' cmd line args */
 SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
-                                      int unit, bool removable)
+                                      int unit, bool removable, int bootindex)
 {
     const char *driver;
     DeviceState *dev;
@@ -170,6 +170,9 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
     driver = bdrv_is_sg(bdrv) ? "scsi-generic" : "scsi-disk";
     dev = qdev_create(&bus->qbus, driver);
     qdev_prop_set_uint32(dev, "scsi-id", unit);
+    if (bootindex >= 0) {
+        qdev_prop_set_int32(dev, "bootindex", bootindex);
+    }
     if (qdev_prop_exists(dev, "removable")) {
         qdev_prop_set_bit(dev, "removable", removable);
     }
@@ -195,7 +198,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
             continue;
         }
         qemu_opts_loc_restore(dinfo->opts);
-        if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false)) {
+        if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1)) {
             res = -1;
             break;
         }
diff --git a/hw/scsi.h b/hw/scsi.h
index 61c64d5..ab6e952 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -128,7 +128,7 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
 }
 
 SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
-                                      int unit, bool removable);
+                                      int unit, bool removable, int bootindex);
 int scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
 
 /*
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 68e3756..4c06950 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -546,7 +546,8 @@ static int usb_msd_initfn(USBDevice *dev)
 
     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->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable,
+                                            s->conf.bootindex);
     if (!s->scsi_dev) {
         return -1;
     }
@@ -562,7 +563,6 @@ static int usb_msd_initfn(USBDevice *dev)
         }
     }
 
-    add_boot_device_path(s->conf.bootindex, &dev->qdev, "/disk at 0,0");
     return 0;
 }
 
commit 3a395142ba99197429a2378930d3c1551fc053cc
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Nov 18 16:31:59 2011 +0100

    virtio-blk: fix cross-endian config space
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 19e89e7..d6d1f87 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -485,6 +485,7 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
     struct virtio_blk_config blkcfg;
     uint64_t capacity;
     int cylinders, heads, secs;
+    int blk_size = s->conf->logical_block_size;
 
     bdrv_get_geometry(s->bs, &capacity);
     bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs);
@@ -492,14 +493,14 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
     stq_raw(&blkcfg.capacity, capacity);
     stl_raw(&blkcfg.seg_max, 128 - 2);
     stw_raw(&blkcfg.cylinders, cylinders);
+    stl_raw(&blkcfg.blk_size, blk_size);
+    stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
+    stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
     blkcfg.heads = heads;
     blkcfg.sectors = secs & ~s->sector_mask;
-    blkcfg.blk_size = s->conf->logical_block_size;
     blkcfg.size_max = 0;
     blkcfg.physical_block_exp = get_physical_block_exp(s->conf);
     blkcfg.alignment_offset = 0;
-    blkcfg.min_io_size = s->conf->min_io_size / blkcfg.blk_size;
-    blkcfg.opt_io_size = s->conf->opt_io_size / blkcfg.blk_size;
     memcpy(config, &blkcfg, sizeof(struct virtio_blk_config));
 }
 
commit 40897c9c160393df922dfdb59cfa210048d3071d
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Nov 21 14:59:11 2011 -0600

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

diff --git a/VERSION b/VERSION
index 75a7da4..82fd641 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.15.92
+0.15.93
commit 3439eec34f8c0ded2ff08da08b058804382a3736
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Mon Nov 21 04:54:58 2011 +0400

    configure: check for EFD_NONBLOCK | EFD_CLOEXEC flags
    
    Add check for the EFD_NONBLOCK and EFD_CLOEXEC flags to the
    CONFIG_EVENTFD test.
    This fixes the following build failure on Fedora 9:
    
          CC    event_notifier.o
        event_notifier.c: In function `event_notifier_init':
        event_notifier.c:21: error: `EFD_NONBLOCK' undeclared (first use in this function)
        event_notifier.c:21: error: (Each undeclared identifier is reported only once
        event_notifier.c:21: error: for each function it appears in.)
        event_notifier.c:21: error: `EFD_CLOEXEC' undeclared (first use in this function)
        make: *** [event_notifier.o] Error 1
    
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index 75e1f10..f033438 100755
--- a/configure
+++ b/configure
@@ -2241,7 +2241,7 @@ cat > $TMPC << EOF
 
 int main(void)
 {
-    int efd = eventfd(0, 0);
+    int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
     return 0;
 }
 EOF
commit 40d6444e91c6ab17e5e8ab01d4eece90cbc4afed
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Nov 15 20:12:17 2011 +0200

    configure: build position independent executables on x86-Linux hosts
    
    Change the default on x86 Linux hosts to building PIE (position
    independent executables); instead of restricting the option to
    user-only targets, apply it to all targets.
    
    In addition, set the relocation sections to read-only (relro) when
    available; this reduces the attack surface by disallowing changes to
    relocation tables at runtime.
    
    While PIE reduces performance and relro increases load time, it
    greatly improves security, with the potential to reduce a code
    execution vulnerability to a self denial of service.
    
    Non-x86 are not changed, as they require TCG changes; neither are
    non-Linux, due to lack of test coverage.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index 6c77fbb..75e1f10 100755
--- a/configure
+++ b/configure
@@ -172,7 +172,7 @@ aix="no"
 blobs="yes"
 pkgversion=""
 check_utests=""
-user_pie="no"
+pie=""
 zero_malloc=""
 trace_backend="nop"
 trace_file="trace"
@@ -701,9 +701,9 @@ for opt do
   ;;
   --disable-guest-base) guest_base="no"
   ;;
-  --enable-user-pie) user_pie="yes"
+  --enable-pie) pie="yes"
   ;;
-  --disable-user-pie) user_pie="no"
+  --disable-pie) pie="no"
   ;;
   --enable-uname-release=*) uname_release="$optarg"
   ;;
@@ -1031,8 +1031,8 @@ echo "  --disable-bsd-user       disable all BSD usermode emulation targets"
 echo "  --enable-guest-base      enable GUEST_BASE support for usermode"
 echo "                           emulation targets"
 echo "  --disable-guest-base     disable GUEST_BASE support"
-echo "  --enable-user-pie        build usermode emulation targets as PIE"
-echo "  --disable-user-pie       do not build usermode emulation targets as PIE"
+echo "  --enable-pie             build Position Independent Executables"
+echo "  --disable-pie            do not build Position Independent Executables"
 echo "  --fmod-lib               path to FMOD library"
 echo "  --fmod-inc               path to FMOD includes"
 echo "  --oss-lib                path to OSS library"
@@ -1099,6 +1099,47 @@ for flag in $gcc_flags; do
     fi
 done
 
+if test "$static" = "yes" ; then
+  if test "$pie" = "yes" ; then
+    echo "static and pie are mutually incompatible"
+    exit 1
+  else
+    pie="no"
+  fi
+fi
+
+if test "$pie" = ""; then
+  case "$cpu-$targetos" in
+    i386-Linux|x86_64-Linux)
+      ;;
+    *)
+      pie="no"
+      ;;
+  esac
+fi
+
+if test "$pie" != "no" ; then
+  cat > $TMPC << EOF
+int main(void) { return 0; }
+EOF
+  if compile_prog "-fPIE -DPIE" "-pie"; then
+    QEMU_CFLAGS="-fPIE -DPIE $QEMU_CFLAGS"
+    LDFLAGS="-pie $LDFLAGS"
+    pie="yes"
+    if compile_prog "" "-Wl,-z,relro -Wl,-z,now" ; then
+      LDFLAGS="-Wl,-z,relro -Wl,-z,now $LDFLAGS"
+    fi
+  else
+    if test "$pie" = "yes"; then
+      echo "PIE not available due to missing toolchain support"
+      exit 1
+    else
+      echo "Disabling PIE due to missing toolchain support"
+      pie="no"
+    fi
+  fi
+fi
+
 #
 # Solaris specific configure tool chain decisions
 #
@@ -2765,7 +2806,7 @@ echo "Documentation     $docs"
 echo "uname -r          $uname_release"
 echo "NPTL support      $nptl"
 echo "GUEST_BASE        $guest_base"
-echo "PIE user targets  $user_pie"
+echo "PIE               $pie"
 echo "vde support       $vde"
 echo "Linux AIO support $linux_aio"
 echo "ATTR/XATTR support $attr"
@@ -3225,9 +3266,6 @@ for d in libdis libdis-user; do
     symlink $source_path/Makefile.dis $d/Makefile
     echo > $d/config.mak
 done
-if test "$static" = "no" -a "$user_pie" = "yes" ; then
-  echo "QEMU_CFLAGS+=-fpie" > libdis-user/config.mak
-fi
 
 for target in $target_list; do
 target_dir="$target"
@@ -3646,12 +3684,6 @@ if test "$target_softmmu" = "yes" ; then
   esac
 fi
 
-if test "$target_user_only" = "yes" -a "$static" = "no" -a \
-	"$user_pie" = "yes" ; then
-  cflags="-fpie $cflags"
-  ldflags="-pie $ldflags"
-fi
-
 if test "$target_softmmu" = "yes" -a \( \
         "$TARGET_ARCH" = "microblaze" -o \
         "$TARGET_ARCH" = "cris" \) ; then
@@ -3775,9 +3807,6 @@ d=libuser
 mkdir -p $d
 mkdir -p $d/trace
 symlink $source_path/Makefile.user $d/Makefile
-if test "$static" = "no" -a "$user_pie" = "yes" ; then
-  echo "QEMU_CFLAGS+=-fpie" > $d/config.mak
-fi
 
 if test "$docs" = "yes" ; then
   mkdir -p QMP
commit ff51a738cf487811a7890d5292c38bc30eb54e45
Author: Hongyong Zang <zanghongyong at huawei.com>
Date:   Mon Nov 21 18:56:18 2011 +0800

    ivshmem: fix PCI BAR2 registration during initialization
    
    Ivshmem cannot work, and the command lspci cannot show ivshmem BAR2 in the guest.
    As for pci_register_bar(), parameter MemoryRegion should be s->bar instead of s->ivshmem.
    
    Reviewed-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Hongyong Zang <zanghongyong at huawei.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index a3a0e98..7b4dbf6 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -699,7 +699,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
         s->peers = g_malloc0(s->nb_peers * sizeof(Peer));
 
         pci_register_bar(&s->dev, 2,
-                         PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ivshmem);
+                         PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar);
 
         s->eventfd_chr = g_malloc0(s->vectors * sizeof(CharDriverState *));
 
commit ae392c416c69a020226c768d9c3af08b29dd6d96
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Nov 21 18:57:50 2011 +0200

    msix: avoid mask updates if mask is unchanged
    
    Check pending bit only if vector mask status changed.
    This is not really important for qemu.git but helps
    fix a bug in qemu-kvm.git.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/msix.c b/hw/msix.c
index 2969601..149eed2 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -118,17 +118,25 @@ static void msix_clr_pending(PCIDevice *dev, int vector)
     *msix_pending_byte(dev, vector) &= ~msix_pending_mask(vector);
 }
 
-static int msix_is_masked(PCIDevice *dev, int vector)
+static bool msix_vector_masked(PCIDevice *dev, int vector, bool fmask)
 {
-    unsigned offset =
-        vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL;
-    return dev->msix_function_masked ||
-	   dev->msix_table_page[offset] & PCI_MSIX_ENTRY_CTRL_MASKBIT;
+    unsigned offset = vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL;
+    return fmask || dev->msix_table_page[offset] & PCI_MSIX_ENTRY_CTRL_MASKBIT;
 }
 
-static void msix_handle_mask_update(PCIDevice *dev, int vector)
+static bool msix_is_masked(PCIDevice *dev, int vector)
 {
-    if (!msix_is_masked(dev, vector) && msix_is_pending(dev, vector)) {
+    return msix_vector_masked(dev, vector, dev->msix_function_masked);
+}
+
+static void msix_handle_mask_update(PCIDevice *dev, int vector, bool was_masked)
+{
+    bool is_masked = msix_is_masked(dev, vector);
+    if (is_masked == was_masked) {
+        return;
+    }
+
+    if (!is_masked && msix_is_pending(dev, vector)) {
         msix_clr_pending(dev, vector);
         msix_notify(dev, vector);
     }
@@ -166,7 +174,8 @@ void msix_write_config(PCIDevice *dev, uint32_t addr,
     }
 
     for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
-        msix_handle_mask_update(dev, vector);
+        msix_handle_mask_update(dev, vector,
+                                msix_vector_masked(dev, vector, was_masked));
     }
 }
 
@@ -176,14 +185,16 @@ static void msix_mmio_write(void *opaque, target_phys_addr_t addr,
     PCIDevice *dev = opaque;
     unsigned int offset = addr & (MSIX_PAGE_SIZE - 1) & ~0x3;
     int vector = offset / PCI_MSIX_ENTRY_SIZE;
+    bool was_masked;
 
     /* MSI-X page includes a read-only PBA and a writeable Vector Control. */
     if (vector >= dev->msix_entries_nr) {
         return;
     }
 
+    was_masked = msix_is_masked(dev, vector);
     pci_set_long(dev->msix_table_page + offset, val);
-    msix_handle_mask_update(dev, vector);
+    msix_handle_mask_update(dev, vector, was_masked);
 }
 
 static const MemoryRegionOps msix_mmio_ops = {
commit 9a93b61730e3b46ef1c01ca522c6abe80ec13832
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Nov 21 18:57:31 2011 +0200

    msix: Prevent bogus mask updates on MMIO accesses
    
    >From: Jan Kiszka <jan.kiszka at siemens.com>
    
    Only accesses to the MSI-X table must trigger a call to
    msix_handle_mask_update, otherwise the vector
    value might be out of range.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/msix.c b/hw/msix.c
index 63b41b9..2969601 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -176,6 +176,12 @@ static void msix_mmio_write(void *opaque, target_phys_addr_t addr,
     PCIDevice *dev = opaque;
     unsigned int offset = addr & (MSIX_PAGE_SIZE - 1) & ~0x3;
     int vector = offset / PCI_MSIX_ENTRY_SIZE;
+
+    /* MSI-X page includes a read-only PBA and a writeable Vector Control. */
+    if (vector >= dev->msix_entries_nr) {
+        return;
+    }
+
     pci_set_long(dev->msix_table_page + offset, val);
     msix_handle_mask_update(dev, vector);
 }
commit 50322249fdfa3fb8bc6a67c50aebb0f9c36bafb6
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Nov 21 18:57:21 2011 +0200

    msix: track function masked in pci device state
    
    Only go over the table when function is masked.
    This is not really important for qemu.git but helps
    fix a bug in qemu-kvm.git.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/msix.c b/hw/msix.c
index b15bafc..63b41b9 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -79,6 +79,7 @@ static int msix_add_config(struct PCIDevice *pdev, unsigned short nentries,
     /* Make flags bit writable. */
     pdev->wmask[config_offset + MSIX_CONTROL_OFFSET] |= MSIX_ENABLE_MASK |
 	    MSIX_MASKALL_MASK;
+    pdev->msix_function_masked = true;
     return 0;
 }
 
@@ -117,16 +118,11 @@ static void msix_clr_pending(PCIDevice *dev, int vector)
     *msix_pending_byte(dev, vector) &= ~msix_pending_mask(vector);
 }
 
-static int msix_function_masked(PCIDevice *dev)
-{
-    return dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & MSIX_MASKALL_MASK;
-}
-
 static int msix_is_masked(PCIDevice *dev, int vector)
 {
     unsigned offset =
         vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL;
-    return msix_function_masked(dev) ||
+    return dev->msix_function_masked ||
 	   dev->msix_table_page[offset] & PCI_MSIX_ENTRY_CTRL_MASKBIT;
 }
 
@@ -138,24 +134,34 @@ static void msix_handle_mask_update(PCIDevice *dev, int vector)
     }
 }
 
+static void msix_update_function_masked(PCIDevice *dev)
+{
+    dev->msix_function_masked = !msix_enabled(dev) ||
+        (dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & MSIX_MASKALL_MASK);
+}
+
 /* Handle MSI-X capability config write. */
 void msix_write_config(PCIDevice *dev, uint32_t addr,
                        uint32_t val, int len)
 {
     unsigned enable_pos = dev->msix_cap + MSIX_CONTROL_OFFSET;
     int vector;
+    bool was_masked;
 
     if (!range_covers_byte(addr, len, enable_pos)) {
         return;
     }
 
+    was_masked = dev->msix_function_masked;
+    msix_update_function_masked(dev);
+
     if (!msix_enabled(dev)) {
         return;
     }
 
     pci_device_deassert_intx(dev);
 
-    if (msix_function_masked(dev)) {
+    if (dev->msix_function_masked == was_masked) {
         return;
     }
 
@@ -300,6 +306,7 @@ void msix_load(PCIDevice *dev, QEMUFile *f)
     msix_free_irq_entries(dev);
     qemu_get_buffer(f, dev->msix_table_page, n * PCI_MSIX_ENTRY_SIZE);
     qemu_get_buffer(f, dev->msix_table_page + MSIX_PAGE_PENDING, (n + 7) / 8);
+    msix_update_function_masked(dev);
 }
 
 /* Does device support MSI-X? */
diff --git a/hw/pci.h b/hw/pci.h
index 4b2e785..625e717 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -178,6 +178,8 @@ struct PCIDevice {
     unsigned *msix_entry_used;
     /* Region including the MSI-X table */
     uint32_t msix_bar_size;
+    /* MSIX function mask set or MSIX disabled */
+    bool msix_function_masked;
     /* Version id needed for VMState */
     int32_t version_id;
 
commit 2923d34fdc5014a6219bfb3f9fab3795a8f4512f
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Nov 20 12:34:30 2011 +0100

    Include zlib.h using #include <>
    
    zlib.h is not a local include file, therefore it should be included
    using <> instead of "".
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index e53a2f0..96f7d5d 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -26,7 +26,7 @@
 #include "qemu-common.h"
 #include "block_int.h"
 #include "module.h"
-#include "zlib.h"
+#include <zlib.h>
 
 #define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
 #define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
commit 930b588395b8f5864e10688075482e421af7b43d
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Nov 18 17:35:38 2011 +0100

    9p: pass dotl flags to the unlinkat method
    
    AT_REMOVEDIR is not defined on all systems.  Pass the raw flags from the
    9p protocol, which are always there.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c
index 27889d8..7644ae5 100644
--- a/hw/9pfs/virtio-9p-handle.c
+++ b/hw/9pfs/virtio-9p-handle.c
@@ -65,6 +65,9 @@ struct rpl_file_handle {
 };
 #define file_handle rpl_file_handle
 
+#ifndef AT_REMOVEDIR
+#define AT_REMOVEDIR    0x200
+#endif
 #ifndef AT_EMPTY_PATH
 #define AT_EMPTY_PATH   0x1000  /* Allow empty relative pathname */
 #endif
@@ -575,13 +578,20 @@ static int handle_unlinkat(FsContext *ctx, V9fsPath *dir,
 {
     int dirfd, ret;
     struct handle_data *data = (struct handle_data *)ctx->private;
+    int rflags;
 
     dirfd = open_by_handle(data->mountfd, dir->data, O_PATH);
     if (dirfd < 0) {
         return dirfd;
     }
 
-    ret = unlinkat(dirfd, name, flags);
+    rflags = 0;
+    if (flags & P9_DOTL_AT_REMOVEDIR) {
+        rflags |= AT_REMOVEDIR;
+    }
+
+    ret = unlinkat(dirfd, name, rflags);
+
     close(dirfd);
     return ret;
 }
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 01cf337..1b2fc5d 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -74,15 +74,6 @@ static int omode_to_uflags(int8_t mode)
     return ret;
 }
 
-static int dotl_to_at_flags(int flags)
-{
-    int rflags = 0;
-    if (flags & P9_DOTL_AT_REMOVEDIR) {
-        rflags |= AT_REMOVEDIR;
-    }
-    return rflags;
-}
-
 struct dotl_openflag_map {
     int dotl_flag;
     int open_flag;
@@ -2444,7 +2435,6 @@ static void v9fs_unlinkat(void *opaque)
     V9fsPDU *pdu = opaque;
 
     pdu_unmarshal(pdu, offset, "dsd", &dfid, &name, &flags);
-    flags = dotl_to_at_flags(flags);
 
     dfidp = get_fid(pdu, dfid);
     if (dfidp == NULL) {
commit f5654039497b7c5a2d3fe38d0fcf7898596b21f7
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Nov 18 17:35:37 2011 +0100

    9p: allow compiling the dummy virtio-9p-handle.c code on Linux
    
    Avoid a conflict on the definition of struct file_handle by
    using a replacement name.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c
index 0a778b4..27889d8 100644
--- a/hw/9pfs/virtio-9p-handle.c
+++ b/hw/9pfs/virtio-9p-handle.c
@@ -58,11 +58,12 @@ static inline int open_by_handle(int mountfd, const char *fh, int flags)
 }
 #else
 
-struct file_handle {
+struct rpl_file_handle {
     unsigned int handle_bytes;
     int handle_type;
     unsigned char handle[0];
 };
+#define file_handle rpl_file_handle
 
 #ifndef AT_EMPTY_PATH
 #define AT_EMPTY_PATH   0x1000  /* Allow empty relative pathname */
commit 1ed520c66e3f3b57b88d201c08558ec1616bf69d
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Nov 14 15:09:47 2011 -0600

    qed: add migration blocker (v2)
    
    Now when you try to migrate with qed, you get:
    
    (qemu) migrate tcp:localhost:1025
    Block format 'qed' used by device 'ide0-hd0' does not support feature 'live migration'
    (qemu)
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/block/qed.c b/block/qed.c
index d032a45..7e22e77 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -16,6 +16,7 @@
 #include "trace.h"
 #include "qed.h"
 #include "qerror.h"
+#include "migration.h"
 
 static void qed_aio_cancel(BlockDriverAIOCB *blockacb)
 {
@@ -504,6 +505,12 @@ static int bdrv_qed_open(BlockDriverState *bs, int flags)
     s->need_check_timer = qemu_new_timer_ns(vm_clock,
                                             qed_need_check_timer_cb, s);
 
+    error_set(&s->migration_blocker,
+              QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+              "qed", bs->device_name, "live migration");
+    migrate_add_blocker(s->migration_blocker);
+
+
 out:
     if (ret) {
         qed_free_l2_cache(&s->l2_cache);
@@ -516,6 +523,9 @@ static void bdrv_qed_close(BlockDriverState *bs)
 {
     BDRVQEDState *s = bs->opaque;
 
+    migrate_del_blocker(s->migration_blocker);
+    error_free(s->migration_blocker);
+
     qed_cancel_need_check_timer(s);
     qemu_free_timer(s->need_check_timer);
 
diff --git a/block/qed.h b/block/qed.h
index 388fdb3..62cbd3b 100644
--- a/block/qed.h
+++ b/block/qed.h
@@ -164,6 +164,8 @@ typedef struct {
 
     /* Periodic flush and clear need check flag */
     QEMUTimer *need_check_timer;
+
+    Error *migration_blocker;
 } BDRVQEDState;
 
 enum {
diff --git a/qemu-tool.c b/qemu-tool.c
index e9f7fe1..5df7279 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -15,6 +15,7 @@
 #include "monitor.h"
 #include "qemu-timer.h"
 #include "qemu-log.h"
+#include "migration.h"
 
 #include <sys/time.h>
 
@@ -92,3 +93,11 @@ int64_t qemu_get_clock_ns(QEMUClock *clock)
 {
     return 0;
 }
+
+void migrate_add_blocker(Error *reason)
+{
+}
+
+void migrate_del_blocker(Error *reason)
+{
+}
diff --git a/qerror.c b/qerror.c
index 8e30e2d..fdf62b9 100644
--- a/qerror.c
+++ b/qerror.c
@@ -49,6 +49,10 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Device '%(device)' can't go on a %(bad_bus_type) bus",
     },
     {
+        .error_fmt = QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+        .desc      = "Block format '%(format)' used by device '%(name)' does not support feature '%(feature)'",
+    },
+    {
         .error_fmt = QERR_BUS_NOT_FOUND,
         .desc      = "Bus '%(bus)' not found",
     },
diff --git a/qerror.h b/qerror.h
index 7e2eebf..2d3d43b 100644
--- a/qerror.h
+++ b/qerror.h
@@ -54,6 +54,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_BAD_BUS_FOR_DEVICE \
     "{ 'class': 'BadBusForDevice', 'data': { 'device': %s, 'bad_bus_type': %s } }"
 
+#define QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED \
+    "{ 'class': 'BlockFormatFeatureNotSupported', 'data': { 'format': %s, 'name': %s, 'feature': %s } }"
+
 #define QERR_BUS_NOT_FOUND \
     "{ 'class': 'BusNotFound', 'data': { 'bus': %s } }"
 
commit 06d9260ffa9dfa0e96e015501e43480ab66f96f6
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Nov 14 15:09:46 2011 -0600

    qcow2: implement bdrv_invalidate_cache (v2)
    
    We don't reopen the actual file, but instead invoke the close and open routines.
    We specifically ignore the backing file since it's contents are read-only and
    therefore immutable.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 5c784ee..d7805ce 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -240,6 +240,7 @@ static int qcow2_open(BlockDriverState *bs, int flags)
     s->cluster_data = qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size
                                   + 512);
     s->cluster_cache_offset = -1;
+    s->flags = flags;
 
     ret = qcow2_refcount_init(bs);
     if (ret != 0) {
@@ -632,6 +633,37 @@ static void qcow2_close(BlockDriverState *bs)
     qcow2_refcount_close(bs);
 }
 
+static void qcow2_invalidate_cache(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+    int flags = s->flags;
+    AES_KEY aes_encrypt_key;
+    AES_KEY aes_decrypt_key;
+    uint32_t crypt_method = 0;
+
+    /*
+     * Backing files are read-only which makes all of their metadata immutable,
+     * that means we don't have to worry about reopening them here.
+     */
+
+    if (s->crypt_method) {
+        crypt_method = s->crypt_method;
+        memcpy(&aes_encrypt_key, &s->aes_encrypt_key, sizeof(aes_encrypt_key));
+        memcpy(&aes_decrypt_key, &s->aes_decrypt_key, sizeof(aes_decrypt_key));
+    }
+
+    qcow2_close(bs);
+
+    memset(s, 0, sizeof(BDRVQcowState));
+    qcow2_open(bs, flags);
+
+    if (crypt_method) {
+        s->crypt_method = crypt_method;
+        memcpy(&s->aes_encrypt_key, &aes_encrypt_key, sizeof(aes_encrypt_key));
+        memcpy(&s->aes_decrypt_key, &aes_decrypt_key, sizeof(aes_decrypt_key));
+    }
+}
+
 /*
  * Updates the variable length parts of the qcow2 header, i.e. the backing file
  * name and all extensions. qcow2 was not designed to allow such changes, so if
@@ -1269,6 +1301,8 @@ static BlockDriver bdrv_qcow2 = {
 
     .bdrv_change_backing_file   = qcow2_change_backing_file,
 
+    .bdrv_invalidate_cache      = qcow2_invalidate_cache,
+
     .create_options = qcow2_create_options,
     .bdrv_check = qcow2_check,
 };
diff --git a/block/qcow2.h b/block/qcow2.h
index 531af39..4e44eea 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -125,6 +125,8 @@ typedef struct BDRVQcowState {
     int snapshots_size;
     int nb_snapshots;
     QCowSnapshot *snapshots;
+
+    int flags;
 } BDRVQcowState;
 
 /* XXX: use std qcow open function ? */
commit 0f15423c3234335ca0dbeeae6d19db4699faca07
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Nov 14 15:09:45 2011 -0600

    block: allow migration to work with image files (v3)
    
    Image files have two types of data: immutable data that describes things like
    image size, backing files, etc. and mutable data that includes offset and
    reference count tables.
    
    Today, image formats aggressively cache mutable data to improve performance.  In
    some cases, this happens before a guest even starts.  When dealing with live
    migration, since a file is open on two machines, the caching of meta data can
    lead to data corruption.
    
    This patch addresses this by introducing a mechanism to invalidate any cached
    mutable data a block driver may have which is then used by the live migration
    code.
    
    NB, this still requires coherent shared storage.  Addressing migration without
    coherent shared storage (i.e. NFS) requires additional work.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/block.c b/block.c
index 86910b0..d015887 100644
--- a/block.c
+++ b/block.c
@@ -2839,6 +2839,22 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
     }
 }
 
+void bdrv_invalidate_cache(BlockDriverState *bs)
+{
+    if (bs->drv && bs->drv->bdrv_invalidate_cache) {
+        bs->drv->bdrv_invalidate_cache(bs);
+    }
+}
+
+void bdrv_invalidate_cache_all(void)
+{
+    BlockDriverState *bs;
+
+    QTAILQ_FOREACH(bs, &bdrv_states, list) {
+        bdrv_invalidate_cache(bs);
+    }
+}
+
 int bdrv_flush(BlockDriverState *bs)
 {
     Coroutine *co;
diff --git a/block.h b/block.h
index 051a25d..a826059 100644
--- a/block.h
+++ b/block.h
@@ -197,6 +197,10 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
         unsigned long int req, void *buf,
         BlockDriverCompletionFunc *cb, void *opaque);
 
+/* Invalidate any cached metadata used by image formats */
+void bdrv_invalidate_cache(BlockDriverState *bs);
+void bdrv_invalidate_cache_all(void);
+
 /* Ensure contents are flushed to disk.  */
 int bdrv_flush(BlockDriverState *bs);
 int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
diff --git a/block_int.h b/block_int.h
index 1ec4921..77c0187 100644
--- a/block_int.h
+++ b/block_int.h
@@ -88,6 +88,11 @@ struct BlockDriver {
         int64_t sector_num, int nb_sectors);
 
     /*
+     * Invalidate any cached meta-data.
+     */
+    void (*bdrv_invalidate_cache)(BlockDriverState *bs);
+
+    /*
      * Flushes all data that was already written to the OS all the way down to
      * the disk (for example raw-posix calls fsync()).
      */
diff --git a/migration.c b/migration.c
index 6764d3a..8280d71 100644
--- a/migration.c
+++ b/migration.c
@@ -89,6 +89,9 @@ void process_incoming_migration(QEMUFile *f)
     qemu_announce_self();
     DPRINTF("successfully loaded vm state\n");
 
+    /* Make sure all file formats flush their mutable metadata */
+    bdrv_invalidate_cache_all();
+
     if (autostart) {
         vm_start();
     } else {
commit 38e0735eb76a1479917ef3501a208d4f70998494
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Nov 14 15:09:44 2011 -0600

    ivshmem: use migration blockers to prevent live migration in peer mode (v2)
    
    Now when you try to migrate with ivshmem, you get a proper QMP error:
    
    (qemu) migrate tcp:localhost:1025
    Migration is disabled when using feature 'peer mode' in device 'ivshmem'
    (qemu)
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index 242fbea..a3a0e98 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -18,6 +18,8 @@
 #include "pci.h"
 #include "msix.h"
 #include "kvm.h"
+#include "migration.h"
+#include "qerror.h"
 
 #include <sys/mman.h>
 #include <sys/types.h>
@@ -78,6 +80,8 @@ typedef struct IVShmemState {
     uint32_t features;
     EventfdEntry *eventfd_table;
 
+    Error *migration_blocker;
+
     char * shmobj;
     char * sizearg;
     char * role;
@@ -646,7 +650,8 @@ static int pci_ivshmem_init(PCIDevice *dev)
     }
 
     if (s->role_val == IVSHMEM_PEER) {
-        register_device_unmigratable(&s->dev.qdev, "ivshmem", s);
+        error_set(&s->migration_blocker, QERR_DEVICE_FEATURE_BLOCKS_MIGRATION, "ivshmem", "peer mode");
+        migrate_add_blocker(s->migration_blocker);
     }
 
     pci_conf = s->dev.config;
@@ -741,6 +746,11 @@ static int pci_ivshmem_uninit(PCIDevice *dev)
 {
     IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev);
 
+    if (s->migration_blocker) {
+        migrate_del_blocker(s->migration_blocker);
+        error_free(s->migration_blocker);
+    }
+
     memory_region_destroy(&s->ivshmem_mmio);
     memory_region_del_subregion(&s->bar, &s->ivshmem);
     memory_region_destroy(&s->ivshmem);
diff --git a/qerror.c b/qerror.c
index 4b48b39..8e30e2d 100644
--- a/qerror.c
+++ b/qerror.c
@@ -73,6 +73,10 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Device '%(device)' is in use",
     },
     {
+        .error_fmt = QERR_DEVICE_FEATURE_BLOCKS_MIGRATION,
+        .desc      = "Migration is disabled when using feature '%(feature)' in device '%(device)'",
+    },
+    {
         .error_fmt = QERR_DEVICE_LOCKED,
         .desc      = "Device '%(device)' is locked",
     },
diff --git a/qerror.h b/qerror.h
index d4bfcfd..7e2eebf 100644
--- a/qerror.h
+++ b/qerror.h
@@ -72,6 +72,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_DEVICE_IN_USE \
     "{ 'class': 'DeviceInUse', 'data': { 'device': %s } }"
 
+#define QERR_DEVICE_FEATURE_BLOCKS_MIGRATION \
+    "{ 'class': 'DeviceFeatureBlocksMigration', 'data': { 'device': %s, 'feature': %s } }"
+
 #define QERR_DEVICE_LOCKED \
     "{ 'class': 'DeviceLocked', 'data': { 'device': %s } }"
 
diff --git a/savevm.c b/savevm.c
index bee16c0..f53cd4c 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1255,31 +1255,6 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
     }
 }
 
-/* mark a device as not to be migrated, that is the device should be
-   unplugged before migration */
-void register_device_unmigratable(DeviceState *dev, const char *idstr,
-                                                            void *opaque)
-{
-    SaveStateEntry *se;
-    char id[256] = "";
-
-    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
-        char *path = dev->parent_bus->info->get_dev_path(dev);
-        if (path) {
-            pstrcpy(id, sizeof(id), path);
-            pstrcat(id, sizeof(id), "/");
-            g_free(path);
-        }
-    }
-    pstrcat(id, sizeof(id), idstr);
-
-    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
-        if (strcmp(se->idstr, id) == 0 && se->opaque == opaque) {
-            se->no_migrate = 1;
-        }
-    }
-}
-
 int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
                                    const VMStateDescription *vmsd,
                                    void *opaque, int alias_id,
commit fa2756b71b73e8cd94f7d8964ad5e2aca4d2691c
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Nov 14 15:09:43 2011 -0600

    migrate: add migration blockers
    
    This lets different subsystems register an Error that is thrown whenever
    migration is attempted.  This works nicely because it gracefully supports
    things like hotplug.
    
    Right now, if multiple errors are registered, only one of them is reported.
    I expect that for 1.1, we'll extend query-migrate to return all of the reasons
    why migration is disabled at any given point in time.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration.c b/migration.c
index 41c3c24..6764d3a 100644
--- a/migration.c
+++ b/migration.c
@@ -398,6 +398,18 @@ static MigrationState *migrate_init(Monitor *mon, int detach, int blk, int inc)
     return s;
 }
 
+static GSList *migration_blockers;
+
+void migrate_add_blocker(Error *reason)
+{
+    migration_blockers = g_slist_prepend(migration_blockers, reason);
+}
+
+void migrate_del_blocker(Error *reason)
+{
+    migration_blockers = g_slist_remove(migration_blockers, reason);
+}
+
 int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     MigrationState *s = migrate_get_current();
@@ -417,6 +429,12 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
         return -1;
     }
 
+    if (migration_blockers) {
+        Error *err = migration_blockers->data;
+        qerror_report_err(err);
+        return -1;
+    }
+
     s = migrate_init(mon, detach, blk, inc);
 
     if (strstart(uri, "tcp:", &p)) {
diff --git a/migration.h b/migration.h
index 1b8ee58..0682179 100644
--- a/migration.h
+++ b/migration.h
@@ -17,6 +17,7 @@
 #include "qdict.h"
 #include "qemu-common.h"
 #include "notify.h"
+#include "error.h"
 
 typedef struct MigrationState MigrationState;
 
@@ -89,4 +90,18 @@ int ram_load(QEMUFile *f, void *opaque, int version_id);
 
 extern int incoming_expected;
 
+/**
+ * @migrate_add_blocker - prevent migration from proceeding
+ *
+ * @reason - an error to be returned whenever migration is attempted
+ */
+void migrate_add_blocker(Error *reason);
+
+/**
+ * @migrate_del_blocker - remove a blocking error from migration
+ *
+ * @reason - the error blocking migration
+ */
+void migrate_del_blocker(Error *reason);
+
 #endif
commit a3baf1be673221752c82015b4b9157f23dfc6fd6
Merge: 1571b6c... 0cd0fd0...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Nov 21 14:44:04 2011 -0600

    Merge remote-tracking branch 'kraxel/usb.31' into staging

commit 1571b6cba25df6d000b2539b8ba399839d15f9b6
Merge: 54dcd0b... bc42689...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Nov 21 14:36:55 2011 -0600

    Merge remote-tracking branch 'origin/master' into staging

commit 0cd0fd0867005a0344d06c01fff8f8a66b3d2ecb
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Nov 11 17:14:15 2011 +0100

    usb-linux: fix /proc/bus/usb/devices scan
    
    Commit 0c402e5abb8c2755390eee864b43a98280fc2453 is incomplete
    and misses one of the two function pointer calls in
    usb_host_scan_dev().  Add the additional port handling logic
    to the other call too.
    
    Spotted by Coverity.
    
    Cc: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/usb-linux.c b/usb-linux.c
index f086d57..d4426ea 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -1568,7 +1568,12 @@ static int usb_host_scan_dev(void *opaque, USBScanFunc *func)
         if (line[0] == 'T' && line[1] == ':') {
             if (device_count && (vendor_id || product_id)) {
                 /* New device.  Add the previously discovered device.  */
-                ret = func(opaque, bus_num, addr, 0, class_id, vendor_id,
+                if (port > 0) {
+                    snprintf(buf, sizeof(buf), "%d", port);
+                } else {
+                    snprintf(buf, sizeof(buf), "?");
+                }
+                ret = func(opaque, bus_num, addr, buf, class_id, vendor_id,
                            product_id, product_name, speed);
                 if (ret) {
                     goto the_end;
commit b246721614e316ce948d058dbe45702447998b5f
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Nov 9 12:20:20 2011 +0100

    ehci: add assert
    
    Coverity thinks q could be NULL there and warns.
    I believe it can't be NULL there.
    Add assert to prove it.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index cdd5aae..3eea94d 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -2046,6 +2046,7 @@ static void ehci_advance_state(EHCIState *ehci,
             break;
 
         case EST_WRITEBACK:
+            assert(q != NULL);
             again = ehci_state_writeback(q, async);
             break;
 
commit 59310659073d85745854f2f10c4292555c5a1c51
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Nov 21 14:01:26 2011 +0100

    usb-storage: don't try to send the status early.
    
    Until recently all scsi commands sent to scsi-disk did either transfer
    data or finished instantly.  The correct implementation of
    SYNCRONIZE_CACHE changed the picture though, and usb-storage needs
    a fix to handle that case correctly.

diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 6f32a0e..68e3756 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -378,9 +378,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             s->scsi_len = 0;
             s->req = scsi_req_new(s->scsi_dev, tag, 0, cbw.cmd, NULL);
             scsi_req_enqueue(s->req);
-            /* ??? Should check that USB and SCSI data transfer
-               directions match.  */
-            if (s->mode != USB_MSDM_CSW && s->residue == 0) {
+            if (s->req && s->req->cmd.xfer != SCSI_XFER_NONE) {
                 scsi_req_continue(s->req);
             }
             ret = p->result;
@@ -439,9 +437,15 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
                 goto fail;
             }
 
-            usb_msd_send_status(s, p);
-            s->mode = USB_MSDM_CBW;
-            ret = 13;
+            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:
commit 414c460431036bdadea8120d056c7e493bb60fb9
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Nov 21 11:41:30 2011 +0100

    usb-storage: drop result from device state.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 089c23c..6f32a0e 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -59,7 +59,6 @@ typedef struct {
     char *serial;
     SCSIDevice *scsi_dev;
     uint32_t removable;
-    int result;
     /* For async completion.  */
     USBPacket *packet;
 } MSDState;
@@ -231,12 +230,11 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status)
 
     DPRINTF("Command complete %d tag 0x%x\n", status, req->tag);
     s->residue = s->data_len;
-    s->result = status != 0;
 
     s->csw.sig = cpu_to_le32(0x53425355);
     s->csw.tag = cpu_to_le32(req->tag);
     s->csw.residue = s->residue;
-    s->csw.status = s->result;
+    s->csw.status = status != 0;
 
     if (s->packet) {
         if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {
commit 7b863f41de0c0089c2735e3caa8952bb3b0a5a7c
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Nov 21 11:36:17 2011 +0100

    usb-storage: drop tag from device state.
    
    scsi keeps track of the tag in SCSIRequest,
    no need to store a separate copy.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 5dc4afc..089c23c 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -52,7 +52,6 @@ typedef struct {
     uint8_t *scsi_buf;
     uint32_t data_len;
     uint32_t residue;
-    uint32_t tag;
     struct usb_msd_csw csw;
     SCSIRequest *req;
     SCSIBus bus;
@@ -230,12 +229,12 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status)
     MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
     USBPacket *p = s->packet;
 
-    DPRINTF("Command complete %d\n", status);
+    DPRINTF("Command complete %d tag 0x%x\n", status, req->tag);
     s->residue = s->data_len;
     s->result = status != 0;
 
     s->csw.sig = cpu_to_le32(0x53425355);
-    s->csw.tag = cpu_to_le32(s->tag);
+    s->csw.tag = cpu_to_le32(req->tag);
     s->csw.residue = s->residue;
     s->csw.status = s->result;
 
@@ -260,7 +259,6 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status)
     } else if (s->data_len == 0) {
         s->mode = USB_MSDM_CSW;
     }
-
     scsi_req_unref(req);
     s->req = NULL;
 }
@@ -340,6 +338,7 @@ static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p)
 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->devep;
@@ -366,7 +365,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
                 fprintf(stderr, "usb-msd: Bad LUN %d\n", cbw.lun);
                 goto fail;
             }
-            s->tag = le32_to_cpu(cbw.tag);
+            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;
@@ -376,10 +375,10 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
                 s->mode = USB_MSDM_DATAOUT;
             }
             DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
-                    s->tag, cbw.flags, cbw.cmd_len, s->data_len);
+                    tag, cbw.flags, cbw.cmd_len, s->data_len);
             s->residue = 0;
             s->scsi_len = 0;
-            s->req = scsi_req_new(s->scsi_dev, s->tag, 0, cbw.cmd, NULL);
+            s->req = scsi_req_new(s->scsi_dev, tag, 0, cbw.cmd, NULL);
             scsi_req_enqueue(s->req);
             /* ??? Should check that USB and SCSI data transfer
                directions match.  */
commit 92a114f6f8487b8b256340cac5a5a10498e220c1
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Nov 21 11:29:27 2011 +0100

    usb-storage: fill status in complete callback.
    
    Put status word into device state, fill it in command_complete, have
    usb_msd_send_status just send it out.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 8dde421..5dc4afc 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -38,6 +38,13 @@ enum USBMSDMode {
     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;
@@ -46,6 +53,7 @@ typedef struct {
     uint32_t data_len;
     uint32_t residue;
     uint32_t tag;
+    struct usb_msd_csw csw;
     SCSIRequest *req;
     SCSIBus bus;
     BlockConf conf;
@@ -67,13 +75,6 @@ struct usb_msd_cbw {
     uint8_t cmd[16];
 };
 
-struct usb_msd_csw {
-    uint32_t sig;
-    uint32_t tag;
-    uint32_t residue;
-    uint8_t status;
-};
-
 enum {
     STR_MANUFACTURER = 1,
     STR_PRODUCT,
@@ -191,19 +192,15 @@ static void usb_msd_copy_data(MSDState *s, USBPacket *p)
 
 static void usb_msd_send_status(MSDState *s, USBPacket *p)
 {
-    struct usb_msd_csw csw;
     int len;
 
     DPRINTF("Command status %d tag 0x%x, len %zd\n",
-            s->result, s->tag, p->iov.size);
-    csw.sig = cpu_to_le32(0x53425355);
-    csw.tag = cpu_to_le32(s->tag);
-    csw.residue = s->residue;
-    csw.status = s->result;
-
-    len = MIN(sizeof(csw), p->iov.size);
-    usb_packet_copy(p, &csw, len);
-    p->result = len;
+            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)
@@ -236,6 +233,12 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status)
     DPRINTF("Command complete %d\n", status);
     s->residue = s->data_len;
     s->result = status != 0;
+
+    s->csw.sig = cpu_to_le32(0x53425355);
+    s->csw.tag = cpu_to_le32(s->tag);
+    s->csw.residue = s->residue;
+    s->csw.status = s->result;
+
     if (s->packet) {
         if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {
             /* A deferred packet with no write data remaining must be
@@ -257,6 +260,7 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status)
     } else if (s->data_len == 0) {
         s->mode = USB_MSDM_CSW;
     }
+
     scsi_req_unref(req);
     s->req = NULL;
 }
commit e04da7c3d15d746be86898b4ce059b365d61dbc3
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Nov 21 11:17:59 2011 +0100

    usb-storage: move status debug message to usb_msd_send_status.
    
    usb_msd_send_status can be called from different code paths, move the
    debug message into the function to make sure it is printed
    unconditionally.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index b734177..8dde421 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -194,6 +194,8 @@ static void usb_msd_send_status(MSDState *s, USBPacket *p)
     struct usb_msd_csw csw;
     int len;
 
+    DPRINTF("Command status %d tag 0x%x, len %zd\n",
+            s->result, s->tag, p->iov.size);
     csw.sig = cpu_to_le32(0x53425355);
     csw.tag = cpu_to_le32(s->tag);
     csw.residue = s->residue;
@@ -432,8 +434,6 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             break;
 
         case USB_MSDM_CSW:
-            DPRINTF("Command status %d tag 0x%x, len %zd\n",
-                    s->result, s->tag, p->iov.size);
             if (p->iov.size < 13) {
                 goto fail;
             }
commit bc4268998d154b9b3cc86a7b6bd932cc974591c9
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Nov 13 11:11:52 2011 +0000

    x86: fix pcmpestrm and pcmpistrm
    
    Fix obvious typos (decrement and off-by-one error) in pcmpestrm and pcmpistrm
    which resulted in infinite loop. Reported by Frank Mehnert,
    spotted also by Coverity (bug 84752853).
    
    Reported-by: Frank Mehnert <frank.mehnert at oracle.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index aa41d25..47dde78 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -1996,11 +1996,13 @@ void glue(helper_pcmpestrm, SUFFIX) (Reg *d, Reg *s, uint32_t ctrl)
 
     if ((ctrl >> 6) & 1) {
         if (ctrl & 1)
-            for (i = 0; i <= 8; i--, res >>= 1)
+            for (i = 0; i < 8; i++, res >>= 1) {
                 d->W(i) = (res & 1) ? ~0 : 0;
+            }
         else
-            for (i = 0; i <= 16; i--, res >>= 1)
+            for (i = 0; i < 16; i++, res >>= 1) {
                 d->B(i) = (res & 1) ? ~0 : 0;
+            }
     } else {
         d->Q(1) = 0;
         d->Q(0) = res;
@@ -2028,11 +2030,13 @@ void glue(helper_pcmpistrm, SUFFIX) (Reg *d, Reg *s, uint32_t ctrl)
 
     if ((ctrl >> 6) & 1) {
         if (ctrl & 1)
-            for (i = 0; i <= 8; i--, res >>= 1)
+            for (i = 0; i < 8; i++, res >>= 1) {
                 d->W(i) = (res & 1) ? ~0 : 0;
+            }
         else
-            for (i = 0; i <= 16; i--, res >>= 1)
+            for (i = 0; i < 16; i++, res >>= 1) {
                 d->B(i) = (res & 1) ? ~0 : 0;
+            }
     } else {
         d->Q(1) = 0;
         d->Q(0) = res;
commit 725e14e91f80b6b2c07b75b66b7b042a9fa9340c
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Nov 16 19:41:56 2011 +0100

    loader: Fix read_targphys() to behave when read() fails
    
    Happily passes (size_t)-1 to rom_add_blob_fixed(), which promptly dies
    attempting to malloc that much.  Spotted by Coverity.
    
    Bonus fix for ROMs larger than INT_MAX bytes: return ssize_t instead
    of int.  Bug can't bite, because the only user load_aout() limits ROM
    size to an int value.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/loader.c b/hw/loader.c
index 5676c18..9bbcddd 100644
--- a/hw/loader.c
+++ b/hw/loader.c
@@ -85,11 +85,11 @@ int load_image(const char *filename, uint8_t *addr)
 }
 
 /* read()-like version */
-int read_targphys(const char *name,
-                  int fd, target_phys_addr_t dst_addr, size_t nbytes)
+ssize_t read_targphys(const char *name,
+                      int fd, target_phys_addr_t dst_addr, size_t nbytes)
 {
     uint8_t *buf;
-    size_t did;
+    ssize_t did;
 
     buf = g_malloc(nbytes);
     did = read(fd, buf, nbytes);
@@ -176,7 +176,8 @@ static void bswap_ahdr(struct exec *e)
 int load_aout(const char *filename, target_phys_addr_t addr, int max_sz,
               int bswap_needed, target_phys_addr_t target_page_size)
 {
-    int fd, size, ret;
+    int fd;
+    ssize_t size, ret;
     struct exec e;
     uint32_t magic;
 
diff --git a/hw/loader.h b/hw/loader.h
index fc6bdff..fbcaba9 100644
--- a/hw/loader.h
+++ b/hw/loader.h
@@ -14,8 +14,8 @@ int load_aout(const char *filename, target_phys_addr_t addr, int max_sz,
 int load_uimage(const char *filename, target_phys_addr_t *ep,
                 target_phys_addr_t *loadaddr, int *is_linux);
 
-int read_targphys(const char *name,
-                  int fd, target_phys_addr_t dst_addr, size_t nbytes);
+ssize_t read_targphys(const char *name,
+                      int fd, target_phys_addr_t dst_addr, size_t nbytes);
 void pstrcpy_targphys(const char *name,
                       target_phys_addr_t dest, int buf_size,
                       const char *source);
commit 96d922a654f4b5a806af43d6dc6fa7c1becbbac6
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Thu Nov 3 16:10:04 2011 +0100

    Improve "ta 0" shutdown
    
    This patch replace the previous implementation with this simplified and
    more complete version (no shutdown when psret == 1).
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 18609c4..037a72c 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -34,13 +34,6 @@ void helper_debug(CPUState *env)
     cpu_loop_exit(env);
 }
 
-void helper_shutdown(void)
-{
-#if !defined(CONFIG_USER_ONLY)
-    qemu_system_shutdown_request();
-#endif
-}
-
 #ifdef TARGET_SPARC64
 target_ulong helper_popc(target_ulong val)
 {
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index faaf8dc..1f67b08 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -79,7 +79,6 @@ DEF_HELPER_1(fcmpeq_fcc2, void, env)
 DEF_HELPER_1(fcmpeq_fcc3, void, env)
 #endif
 DEF_HELPER_2(raise_exception, void, env, int)
-DEF_HELPER_0(shutdown, void)
 #define F_HELPER_0_1(name) DEF_HELPER_1(f ## name, void, env)
 
 DEF_HELPER_3(faddd, f64, env, f64, f64)
diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c
index 3a749bf..ac9d01e 100644
--- a/target-sparc/int32_helper.c
+++ b/target-sparc/int32_helper.c
@@ -19,6 +19,7 @@
 
 #include "cpu.h"
 #include "trace.h"
+#include "sysemu.h"
 
 //#define DEBUG_PCALL
 
@@ -100,8 +101,13 @@ void do_interrupt(CPUState *env)
 #endif
 #if !defined(CONFIG_USER_ONLY)
     if (env->psret == 0) {
-        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
-                  env->exception_index);
+        if (env->exception_index == 0x80 &&
+            env->def->features & CPU_FEATURE_TA0_SHUTDOWN) {
+            qemu_system_shutdown_request();
+        } else {
+            cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
+                      env->exception_index);
+        }
         return;
     }
 #endif
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 9318540..d261112 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2518,15 +2518,8 @@ static void disas_sparc_insn(DisasContext * dc)
                         tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK);
                     tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP);
                     tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
+                    gen_helper_raise_exception(cpu_env, cpu_tmp32);
 
-                    if (rs2 == 0 &&
-                        dc->def->features & CPU_FEATURE_TA0_SHUTDOWN) {
-
-                        gen_helper_shutdown();
-
-                    } else {
-                        gen_helper_raise_exception(cpu_env, cpu_tmp32);
-                    }
                 } else if (cond != 0) {
                     TCGv r_cond = tcg_temp_new();
                     int l1;
commit 9643c25f8d67646857159d6fc021b07e7a659192
Author: Stefan Weil <sw at weilnetz.de>
Date:   Tue Oct 18 22:25:38 2011 +0200

    gdbstub: Fix memory leak
    
    cppcheck report:
      gdbstub.c:1781: error: Memory leak: s
    
    Rearranging of the code avoids the leak.
    
    v2:
    Replace the g_malloc0() by g_new0() (suggested by Stuart Brady).
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/gdbstub.c b/gdbstub.c
index a25f404..640cf4e 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1781,12 +1781,6 @@ void gdb_register_coprocessor(CPUState * env,
     GDBRegisterState **p;
     static int last_reg = NUM_CORE_REGS;
 
-    s = (GDBRegisterState *)g_malloc0(sizeof(GDBRegisterState));
-    s->base_reg = last_reg;
-    s->num_regs = num_regs;
-    s->get_reg = get_reg;
-    s->set_reg = set_reg;
-    s->xml = xml;
     p = &env->gdb_regs;
     while (*p) {
         /* Check for duplicates.  */
@@ -1794,6 +1788,14 @@ void gdb_register_coprocessor(CPUState * env,
             return;
         p = &(*p)->next;
     }
+
+    s = g_new0(GDBRegisterState, 1);
+    s->base_reg = last_reg;
+    s->num_regs = num_regs;
+    s->get_reg = get_reg;
+    s->set_reg = set_reg;
+    s->xml = xml;
+
     /* Add to end of list.  */
     last_reg += num_regs;
     *p = s;
commit b08d26b76d51fb2695912373ded53b628ec96320
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Nov 9 10:03:35 2011 -0800

    tcg-sparc: Fix set-but-not used warnings.
    
    In both cases, val is computed, but then not used in the
    subsequent line, which then re-computes the quantity in
    a different type (int32_t vs unsigned long).
    
    Keep the computation type that's been working so far.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index b96312b..5cd5a3b 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -473,11 +473,9 @@ static inline void tcg_out_nop(TCGContext *s)
 
 static void tcg_out_branch_i32(TCGContext *s, int opc, int label_index)
 {
-    int32_t val;
     TCGLabel *l = &s->labels[label_index];
 
     if (l->has_value) {
-        val = l->u.value - (tcg_target_long)s->code_ptr;
         tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2)
                       | INSN_OFF22(l->u.value - (unsigned long)s->code_ptr)));
     } else {
@@ -489,11 +487,9 @@ static void tcg_out_branch_i32(TCGContext *s, int opc, int label_index)
 #if TCG_TARGET_REG_BITS == 64
 static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index)
 {
-    int32_t val;
     TCGLabel *l = &s->labels[label_index];
 
     if (l->has_value) {
-        val = l->u.value - (tcg_target_long)s->code_ptr;
         tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) |
                       (0x5 << 19) |
                       INSN_OFF19(l->u.value - (unsigned long)s->code_ptr)));
commit 25cc4a768d91817bc3b4bf9b3a270c4791509cd7
Merge: 05a86f2... 326384d...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Nov 19 11:17:58 2011 +0000

    Merge branch 's390-1.0' of git://repo.or.cz/qemu/agraf
    
    * 's390-1.0' of git://repo.or.cz/qemu/agraf:
      s390x: initialize virtio dev region
      tcg: Use TCGReg for standard tcg-target entry points.
      tcg: Standardize on TCGReg as the enum for hard registers
      s390x: Add shutdown for TCG s390-virtio machine
      s390: Fix cpu shutdown for KVM
      s390: fix short kernel command lines
      s390: fix reset hypercall to reset the status
      s390x: implement SIGP restart and shutdown
      s390x: implement rrbe instruction properly
      s390x: update R and C bits in storage key
      s390x: make ipte 31-bit aware
      s390x: add ldeb instruction

commit 05a86f23e5ca83348eface349429341cefb8697b
Merge: 15d4a72... 1e34d85...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Nov 19 11:17:11 2011 +0000

    Merge branch 'ppc-1.0' of git://repo.or.cz/qemu/agraf
    
    * 'ppc-1.0' of git://repo.or.cz/qemu/agraf:
      pseries: Fix qdev.id handling in the VIO bus code
      pseries: Allow kernel's early debug output to work
      pseries: Default reg for vty should be SPAPR_VTY_BASE_ADDRESS
      pseries: Check we have a chardev in spapr_vty_init()
      pseries: Fix buggy spapr_vio_find_by_reg()
      pseries: Correct RAM size check for SLOF
      PPC: Fix for the gdb single step problem on an rfi instruction
      tcg-ppc64: Fix compile errors for userspace only builds with gcc 4.6
      pseries: Fix initialization of sPAPREnvironment structure

commit 54dcd0b37e3e4e9fb25cb4e9965d6ba45eb0d2b4
Merge: 7197390... 33ebad1...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Nov 18 13:30:08 2011 -0600

    Merge remote-tracking branch 'kwolf/block-stable' into staging

commit 7197390a0b6e38017af94135b6055d8b7c6c2370
Merge: c951d9a... 1b14254...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Nov 18 13:23:38 2011 -0600

    Merge remote-tracking branch 'qmp/queue/qmp-1.0' into staging

commit 15d4a723381bb57dc31007ca46661f42eb67a100
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Nov 18 18:16:20 2011 +0100

    fmodaudio: Remove unused variable 'bits16' (reported by cppcheck)
    
    The variable is assigned a value which is never used,
    so remove variable and assignment.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: malc <av1474 at comtv.ru>

diff --git a/audio/fmodaudio.c b/audio/fmodaudio.c
index c34cf53..fabf84d 100644
--- a/audio/fmodaudio.c
+++ b/audio/fmodaudio.c
@@ -343,7 +343,7 @@ static void fmod_fini_out (HWVoiceOut *hw)
 
 static int fmod_init_out (HWVoiceOut *hw, struct audsettings *as)
 {
-    int bits16, mode, channel;
+    int mode, channel;
     FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
     struct audsettings obt_as = *as;
 
@@ -374,7 +374,6 @@ static int fmod_init_out (HWVoiceOut *hw, struct audsettings *as)
     /* FMOD always operates on little endian frames? */
     obt_as.endianness = 0;
     audio_pcm_init_info (&hw->info, &obt_as);
-    bits16 = (mode & FSOUND_16BITS) != 0;
     hw->samples = conf.nb_samples;
     return 0;
 }
@@ -405,7 +404,7 @@ static int fmod_ctl_out (HWVoiceOut *hw, int cmd, ...)
 
 static int fmod_init_in (HWVoiceIn *hw, struct audsettings *as)
 {
-    int bits16, mode;
+    int mode;
     FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
     struct audsettings obt_as = *as;
 
@@ -432,7 +431,6 @@ static int fmod_init_in (HWVoiceIn *hw, struct audsettings *as)
     /* FMOD always operates on little endian frames? */
     obt_as.endianness = 0;
     audio_pcm_init_info (&hw->info, &obt_as);
-    bits16 = (mode & FSOUND_16BITS) != 0;
     hw->samples = conf.nb_samples;
     return 0;
 }
commit 1e34d859d01a408dc8479b1858bb103aa3b4f9a7
Author: Michael Ellerman <michael at ellerman.id.au>
Date:   Tue Nov 15 18:53:13 2011 +0000

    pseries: Fix qdev.id handling in the VIO bus code
    
    When the user creates a device on the command line with -device, they
    can specify the id, using id=foo. Currently the VIO bus code overwrites
    this id with it's own value. We should only set qdev.id if it is not
    already set by the user.
    
    The device tree code uses qdev.id for the device tree node name, however
    we can't rely on the user specifiying the id using proper device tree
    syntax, ie. device at reg. So separate the device tree node name from the
    qdev.id, but use the same syntax, so they will match by default.
    
    Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index b7b3ddd..2dcc036 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -73,20 +73,39 @@ VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
     return NULL;
 }
 
+static char *vio_format_dev_name(VIOsPAPRDevice *dev)
+{
+    VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)dev->qdev.info;
+    char *name;
+
+    /* Device tree style name device at reg */
+    if (asprintf(&name, "%s@%x", info->dt_name, dev->reg) < 0) {
+        return NULL;
+    }
+
+    return name;
+}
+
 #ifdef CONFIG_FDT
 static int vio_make_devnode(VIOsPAPRDevice *dev,
                             void *fdt)
 {
     VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)dev->qdev.info;
-    int vdevice_off, node_off;
-    int ret;
+    int vdevice_off, node_off, ret;
+    char *dt_name;
 
     vdevice_off = fdt_path_offset(fdt, "/vdevice");
     if (vdevice_off < 0) {
         return vdevice_off;
     }
 
-    node_off = fdt_add_subnode(fdt, vdevice_off, dev->qdev.id);
+    dt_name = vio_format_dev_name(dev);
+    if (!dt_name) {
+        return -ENOMEM;
+    }
+
+    node_off = fdt_add_subnode(fdt, vdevice_off, dt_name);
+    free(dt_name);
     if (node_off < 0) {
         return node_off;
     }
@@ -608,12 +627,15 @@ static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
     VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
     char *id;
 
-    if (asprintf(&id, "%s@%x", info->dt_name, dev->reg) < 0) {
-        return -1;
+    /* Don't overwrite ids assigned on the command line */
+    if (!dev->qdev.id) {
+        id = vio_format_dev_name(dev);
+        if (!id) {
+            return -1;
+        }
+        dev->qdev.id = id;
     }
 
-    dev->qdev.id = id;
-
     dev->qirq = spapr_allocate_irq(dev->vio_irq_num, &dev->vio_irq_num);
     if (!dev->qirq) {
         return -1;
commit 3feef8ad17af7307373b9e88b9d7ecb98eeb99da
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Sun Nov 13 17:19:01 2011 +0000

    pseries: Allow kernel's early debug output to work
    
    The PAPR specification defines a virtual TTY/console interface for guest
    OSes to use via the H_PUT_TERM_CHAR and H_GET_TERM_CHAR hypercalls.  There
    can be multiple virtual ttys, so these take a "termno" parameter.  This
    encodes which vty to use as the 'reg' property on the device tree node
    associated with that vty.
    
    However, with the early debug options enabled, the Linux kernel will
    attempt debugging output through the vty very early, before it has read
    the device tree.  In this case it always uses a termno of 0.  This works
    on the existing PowerVM hypervisor, so we assume there must be a hack /
    feature in there which interprets termno==0 to mean the default primary
    console.
    
    To help with debugging kernels, including existing distribution kernels,
    this patch implements a similar feature / hack in qemu.  If termno==0
    is supplied to H_{GET,PUT}_TERM_CHAR, they use the first available vty
    device instead.
    
    We need to be careful in the case that the user has manually created
    an spapr-vty at address 0. So first we search for the specified reg and
    only if that doesn't match do we fall back.
    
    Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
    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_vty.c b/hw/spapr_vty.c
index 8150395..f23cc36 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -69,6 +69,9 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev)
     return 0;
 }
 
+/* Forward declaration */
+static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg);
+
 static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr,
                                     target_ulong opcode, target_ulong *args)
 {
@@ -76,9 +79,10 @@ static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr,
     target_ulong len = args[1];
     target_ulong char0_7 = args[2];
     target_ulong char8_15 = args[3];
-    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    VIOsPAPRDevice *sdev;
     uint8_t buf[16];
 
+    sdev = vty_lookup(spapr, reg);
     if (!sdev) {
         return H_PARAMETER;
     }
@@ -102,9 +106,10 @@ static target_ulong h_get_term_char(CPUState *env, sPAPREnvironment *spapr,
     target_ulong *len = args + 0;
     target_ulong *char0_7 = args + 1;
     target_ulong *char8_15 = args + 2;
-    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    VIOsPAPRDevice *sdev;
     uint8_t buf[16];
 
+    sdev = vty_lookup(spapr, reg);
     if (!sdev) {
         return H_PARAMETER;
     }
@@ -151,6 +156,29 @@ static VIOsPAPRDeviceInfo spapr_vty = {
     },
 };
 
+static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
+{
+    VIOsPAPRDevice *sdev;
+
+    sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    if (!sdev && reg == 0) {
+        DeviceState *qdev;
+
+        /* Hack for kernel early debug, which always specifies reg==0.
+         * We search all VIO devices, and grab the first available vty
+         * device.  This attempts to mimic existing PowerVM behaviour
+         * (early debug does work there, despite having no vty with
+         * reg==0. */
+        QTAILQ_FOREACH(qdev, &spapr->vio_bus->bus.children, sibling) {
+            if (qdev->info == &spapr_vty.qdev) {
+                return DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
+            }
+        }
+    }
+
+    return sdev;
+}
+
 static void spapr_vty_register(void)
 {
     spapr_vio_bus_register_withprop(&spapr_vty);
commit 5afdec404e73a578c37221b9ea226d582814acb5
Author: Michael Ellerman <michael at ellerman.id.au>
Date:   Sun Nov 13 17:19:00 2011 +0000

    pseries: Default reg for vty should be SPAPR_VTY_BASE_ADDRESS
    
    In commit b4a78527359a4540d84d4cdf629d01cbb262f698 ("Place pseries vty
    devices at addresses more similar to existing machines"), we changed the
    default reg for the vty to 0x30000000, however we didn't update the default
    value for a user specified vty device. Fix that.
    
    Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
    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_vty.c b/hw/spapr_vty.c
index f4f3ee3..8150395 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -145,7 +145,7 @@ static VIOsPAPRDeviceInfo spapr_vty = {
     .qdev.name = "spapr-vty",
     .qdev.size = sizeof(VIOsPAPRVTYDevice),
     .qdev.props = (Property[]) {
-        DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, 0, 0),
+        DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, SPAPR_VTY_BASE_ADDRESS, 0),
         DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev),
         DEFINE_PROP_END_OF_LIST(),
     },
commit 57285302af51a8bae334c03e1f8243e935373953
Author: Michael Ellerman <michael at ellerman.id.au>
Date:   Sun Nov 13 17:18:59 2011 +0000

    pseries: Check we have a chardev in spapr_vty_init()
    
    If qemu is run like:
    
     qemu-system-ppc64 -nodefaults -device spapr-vty
    
    We end up in spapr_vty_init() with dev->chardev == NULL. Currently
    that leads to a segfault because we unconditionally call
    qemu_chr_add_handlers().
    
    Although we could make that call conditional, I think a spapr-vty
    without a chardev is basically useless so fail the init. This is
    similar to what the serial code does for example.
    
    Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
    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_vty.c b/hw/spapr_vty.c
index a9d4b03..f4f3ee3 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -58,6 +58,11 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev)
 {
     VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
 
+    if (!dev->chardev) {
+        fprintf(stderr, "spapr-vty: Can't create vty without a chardev!\n");
+        exit(1);
+    }
+
     qemu_chr_add_handlers(dev->chardev, vty_can_receive,
                           vty_receive, NULL, dev);
 
commit 5435352ce6abfb8a7540ae7d47e981d329120cca
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Sun Nov 13 17:18:58 2011 +0000

    pseries: Fix buggy spapr_vio_find_by_reg()
    
    The spapr_vio_find_by_reg() function in hw/spapr_vio.c is supposed to find
    the device structure for a PAPR virtual IO device with the given reg value,
    and return NULL if none exists.
    
    It does the first ok, but if no device with that reg exists, it just
    returns the last device traversed in the list.  This patch fixes it.
    
    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_vio.c b/hw/spapr_vio.c
index 25cfc9d..b7b3ddd 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -66,11 +66,11 @@ VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
     QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
         dev = (VIOsPAPRDevice *)qdev;
         if (dev->reg == reg) {
-            break;
+            return dev;
         }
     }
 
-    return dev;
+    return NULL;
 }
 
 #ifdef CONFIG_FDT
commit 92c93a816a8c04071264f9fb47cbc90a5e1ae5d8
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Sun Nov 13 17:18:57 2011 +0000

    pseries: Correct RAM size check for SLOF
    
    The SLOF firmware used on the pseries machine needs a reasonable amount of
    (guest) RAM in order to run, so we have a check in the machine init
    function to check that this is available.  However, SLOF runs in real mode
    (MMU off) which means it can only actually access the RMA (Real Mode Area),
    not all of RAM.  In many cases the RMA is the same as all RAM, but when
    running with Book3S HV KVM on PowerPC 970, the RMA must be especially
    allocated to be (host) physically contiguous.  In this case, the RMA size
    is determined by what the host admin allocated at boot time, and will
    usually be less than the whole guest RAM size.
    
    This patch corrects the test to see if SLOF has enough memory for this
    case.
    
    In addition, more recent versions of SLOF that were committed earlier don't
    need quite as much memory as earlier versions.  Therefore, this patch also
    reduces the amount of RAM we require to run SLOF.
    
    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 40cfc9b..2b901f1 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -57,7 +57,7 @@
 #define FW_MAX_SIZE             0x400000
 #define FW_FILE_NAME            "slof.bin"
 
-#define MIN_RAM_SLOF		512UL
+#define MIN_RMA_SLOF		128UL
 
 #define TIMEBASE_FREQ           512000000ULL
 
@@ -562,9 +562,9 @@ static void ppc_spapr_init(ram_addr_t ram_size,
 
         spapr->entry_point = KERNEL_LOAD_ADDR;
     } else {
-        if (ram_size < (MIN_RAM_SLOF << 20)) {
+        if (rma_size < (MIN_RMA_SLOF << 20)) {
             fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
-                    "%ldM guest RAM\n", MIN_RAM_SLOF);
+                    "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF);
             exit(1);
         }
         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME);
commit 33ebad12637a2e1503247fbb4d2960eaaff084ee
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Nov 14 14:31:52 2011 +0100

    scsi-block: always use SG_IO for MMC devices
    
    CD burning messes up the state of the host page cache and host block
    device.  Just pass all operations down to the device, even though that
    might have slightly worse performance.  Everything else just is not
    reliable in combination with burning.
    
    Reported-by: Thomas Schmitt <scdbackup at gmx.net>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index e3690ec..673948c 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1703,8 +1703,20 @@ static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
     case WRITE_VERIFY_10:
     case WRITE_VERIFY_12:
     case WRITE_VERIFY_16:
-        return scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun,
-                              hba_private);
+        /* MMC writing cannot be done via pread/pwrite, because it sometimes
+         * involves writing beyond the maximum LBA or to negative LBA (lead-in).
+         * And once you do these writes, reading from the block device is
+         * unreliable, too.  It is even possible that reads deliver random data
+         * from the host page cache (this is probably a Linux bug).
+         *
+         * We might use scsi_disk_reqops as long as no writing commands are
+         * seen, but performance usually isn't paramount on optical media.  So,
+         * just make scsi-block operate the same as scsi-generic for them.
+         */
+        if (s->qdev.type != TYPE_ROM) {
+            return scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun,
+                                  hba_private);
+        }
     }
 
     return scsi_req_alloc(&scsi_generic_req_ops, &s->qdev, tag, lun,
commit f3b338ef4afaba105357f62143491e51d35c5b42
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Nov 14 14:31:51 2011 +0100

    scsi: pass down REQUEST SENSE to the device when there is no stored sense
    
    This will let scsi-block/scsi-generic report progress on long
    operations.
    
    Reported-by: Thomas Schmitt <scdbackup at gmxbackup.net>
    Tested-by: Thomas Schmitt <scdbackup at gmxbackup.net>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 4d9ff35..3a2a7bb 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -9,8 +9,6 @@
 static char *scsibus_get_fw_dev_path(DeviceState *dev);
 static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
 static void scsi_req_dequeue(SCSIRequest *req);
-static int scsi_build_sense(uint8_t *in_buf, int in_len,
-                            uint8_t *buf, int len, bool fixed);
 
 static struct BusInfo scsi_bus_info = {
     .name  = "SCSI",
@@ -502,7 +500,7 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
                                  hba_private);
         } else if (lun != d->lun ||
             buf[0] == REPORT_LUNS ||
-            buf[0] == REQUEST_SENSE) {
+            (buf[0] == REQUEST_SENSE && (d->sense_len || cmd.xfer < 4))) {
             req = scsi_req_alloc(&reqops_target_command, d, tag, lun,
                                  hba_private);
         } else {
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 9dd2be8..e3690ec 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1179,6 +1179,11 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
         outbuf[7] = 0;
         buflen = 8;
         break;
+    case REQUEST_SENSE:
+        /* Just return "NO SENSE".  */
+        buflen = scsi_build_sense(NULL, 0, outbuf, r->buflen,
+                                  (req->cmd.buf[1] & 1) == 0);
+        break;
     case MECHANISM_STATUS:
         buflen = scsi_emulate_mechanism_status(s, outbuf);
         if (buflen < 0) {
@@ -1313,6 +1318,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
     case GET_EVENT_STATUS_NOTIFICATION:
     case MECHANISM_STATUS:
     case SERVICE_ACTION_IN_16:
+    case REQUEST_SENSE:
     case VERIFY_10:
         rc = scsi_disk_emulate_command(r);
         if (rc < 0) {
@@ -1407,8 +1413,6 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
         }
 
         break;
-    case REQUEST_SENSE:
-        abort();
     default:
         DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
         scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
diff --git a/hw/scsi.h b/hw/scsi.h
index ff8fdd0..61c64d5 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -179,6 +179,8 @@ extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET;
 #define SENSE_CODE(x) sense_code_ ## x
 
 int scsi_sense_valid(SCSISense sense);
+int scsi_build_sense(uint8_t *in_buf, int in_len,
+                     uint8_t *buf, int len, bool fixed);
 
 SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
                             uint32_t tag, uint32_t lun, void *hba_private);
commit 0fd76ff40b43f5c9f02086a8d53c6157fc0d94a0
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Nov 14 14:31:50 2011 +0100

    scsi: remove block descriptors from CDs
    
    Reported-by: Thomas Schmitt <scdbackup at gmx.net>
    Tested-by: Thomas Schmitt <scdbackup at gmx.net>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 0b06fef..9dd2be8 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -956,8 +956,9 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
         p += 8;
     }
 
+    /* MMC prescribes that CD/DVD drives have no block descriptors.  */
     bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
-    if (!dbd && nb_sectors) {
+    if (!dbd && s->qdev.type == TYPE_DISK && nb_sectors) {
         if (r->req.cmd.buf[0] == MODE_SENSE) {
             outbuf[3] = 8; /* Block descriptor length  */
         } else { /* MODE_SENSE_10 */
commit 06b863577e960413466560d44e2e38eaaca1257e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Nov 14 14:31:49 2011 +0100

    scsi: fix parsing of allocation length field
    
    - several MMC commands were parsed wrong by QEMU because their allocation
    length/parameter list length is placed in a non-standard position in
    the CDB (i.e. it is different from most commands with the same value in
    bits 5-7).
    
    - SEND VOLUME TAG length was multiplied by 40 which is not in SMC.  The
    parameter list length is between 32 and 40 bytes.  Same for MEDIUM SCAN
    (spec found at http://ldkelley.com/SCSI2/SCSI2-16.html but not in any of
    the PDFs I have here).
    
    - READ_POSITION (SSC) conflicts with PRE_FETCH (SBC).  READ_POSITION's
    transfer length is not hardcoded to 20 in SSC; for PRE_FETCH cmd->xfer
    should be 0.  Both fixed.
    
    - FORMAT MEDIUM (the SSC name for FORMAT UNIT) was missing.  The FORMAT
    UNIT command is still somewhat broken for block devices because its
    parameter list length is not in the CDB.  However it works for CD/DVD
    drives, which mandate the length of the payload.
    
    - fixed wrong sign-extensions for 32-bit fields (for the LBA field,
    this affects disks >1 TB).
    
    - several other SBC or SSC commands were missing or parsed wrong.
    
    - some commands were not in the list of "write" commands.
    
    Reported-by: Thomas Schmitt <scdbackup at gmx.net>
    Tested-by: Thomas Schmitt <scdbackup at gmx.net> (MMC bits only)
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 7efcbd8..4d9ff35 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -649,6 +649,31 @@ static void scsi_req_dequeue(SCSIRequest *req)
     }
 }
 
+static int scsi_get_performance_length(int num_desc, int type, int data_type)
+{
+    /* MMC-6, paragraph 6.7.  */
+    switch (type) {
+    case 0:
+        if ((data_type & 3) == 0) {
+            /* Each descriptor is as in Table 295 - Nominal performance.  */
+            return 16 * num_desc + 8;
+        } else {
+            /* Each descriptor is as in Table 296 - Exceptions.  */
+            return 6 * num_desc + 8;
+        }
+    case 1:
+    case 4:
+    case 5:
+        return 8 * num_desc + 8;
+    case 2:
+        return 2048 * num_desc + 8;
+    case 3:
+        return 16 * num_desc + 8;
+    default:
+        return 8;
+    }
+}
+
 static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
 {
     switch (buf[0] >> 5) {
@@ -666,11 +691,11 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
         cmd->len = 10;
         break;
     case 4:
-        cmd->xfer = ldl_be_p(&buf[10]);
+        cmd->xfer = ldl_be_p(&buf[10]) & 0xffffffffULL;
         cmd->len = 16;
         break;
     case 5:
-        cmd->xfer = ldl_be_p(&buf[6]);
+        cmd->xfer = ldl_be_p(&buf[6]) & 0xffffffffULL;
         cmd->len = 12;
         break;
     default:
@@ -683,6 +708,7 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
     case START_STOP:
     case SET_CAPACITY:
     case WRITE_FILEMARKS:
+    case WRITE_FILEMARKS_16:
     case SPACE:
     case RESERVE:
     case RELEASE:
@@ -691,6 +717,8 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
     case VERIFY_10:
     case SEEK_10:
     case SYNCHRONIZE_CACHE:
+    case SYNCHRONIZE_CACHE_16:
+    case LOCATE_16:
     case LOCK_UNLOCK_CACHE:
     case LOAD_UNLOAD:
     case SET_CD_SPEED:
@@ -698,6 +726,11 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
     case WRITE_LONG_10:
     case MOVE_MEDIUM:
     case UPDATE_BLOCK:
+    case RESERVE_TRACK:
+    case SET_READ_AHEAD:
+    case PRE_FETCH:
+    case PRE_FETCH_16:
+    case ALLOW_OVERWRITE:
         cmd->xfer = 0;
         break;
     case MODE_SENSE:
@@ -711,14 +744,13 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
     case READ_BLOCK_LIMITS:
         cmd->xfer = 6;
         break;
-    case READ_POSITION:
-        cmd->xfer = 20;
-        break;
     case SEND_VOLUME_TAG:
-        cmd->xfer *= 40;
-        break;
-    case MEDIUM_SCAN:
-        cmd->xfer *= 8;
+        /* GPCMD_SET_STREAMING from multimedia commands.  */
+        if (dev->type == TYPE_ROM) {
+            cmd->xfer = buf[10] | (buf[9] << 8);
+        } else {
+            cmd->xfer = buf[9] | (buf[8] << 8);
+        }
         break;
     case WRITE_10:
     case WRITE_VERIFY_10:
@@ -737,9 +769,39 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
     case READ_16:
         cmd->xfer *= dev->blocksize;
         break;
+    case FORMAT_UNIT:
+        /* MMC mandates the parameter list to be 12-bytes long.  Parameters
+         * for block devices are restricted to the header right now.  */
+        if (dev->type == TYPE_ROM && (buf[1] & 16)) {
+            cmd->xfer = 12;
+        } else {
+            cmd->xfer = (buf[1] & 16) == 0 ? 0 : (buf[1] & 32 ? 8 : 4);
+        }
+        break;
     case INQUIRY:
+    case RECEIVE_DIAGNOSTIC:
+    case SEND_DIAGNOSTIC:
         cmd->xfer = buf[4] | (buf[3] << 8);
         break;
+    case READ_CD:
+    case READ_BUFFER:
+    case WRITE_BUFFER:
+    case SEND_CUE_SHEET:
+        cmd->xfer = buf[8] | (buf[7] << 8) | (buf[6] << 16);
+        break;
+    case PERSISTENT_RESERVE_OUT:
+        cmd->xfer = ldl_be_p(&buf[5]) & 0xffffffffULL;
+        break;
+    case ERASE_12:
+        if (dev->type == TYPE_ROM) {
+            /* MMC command GET PERFORMANCE.  */
+            cmd->xfer = scsi_get_performance_length(buf[9] | (buf[8] << 8),
+                                                    buf[10], buf[1] & 0x1f);
+        }
+        break;
+    case MECHANISM_STATUS:
+    case READ_DVD_STRUCTURE:
+    case SEND_DVD_STRUCTURE:
     case MAINTENANCE_OUT:
     case MAINTENANCE_IN:
         if (dev->type == TYPE_ROM) {
@@ -755,6 +817,10 @@ static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *bu
 {
     switch (buf[0]) {
     /* stream commands */
+    case ERASE_12:
+    case ERASE_16:
+        cmd->xfer = 0;
+        break;
     case READ_6:
     case READ_REVERSE:
     case RECOVER_BUFFERED_DATA:
@@ -770,6 +836,15 @@ static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *bu
         cmd->len = 6;
         cmd->xfer = 0;
         break;
+    case SPACE_16:
+        cmd->xfer = buf[13] | (buf[12] << 8);
+        break;
+    case READ_POSITION:
+        cmd->xfer = buf[8] | (buf[7] << 8);
+        break;
+    case FORMAT_UNIT:
+        cmd->xfer = buf[4] | (buf[3] << 8);
+        break;
     /* generic commands */
     default:
         return scsi_req_length(cmd, dev, buf);
@@ -809,6 +884,8 @@ static void scsi_cmd_xfer_mode(SCSICommand *cmd)
     case SEARCH_LOW_12:
     case MEDIUM_SCAN:
     case SEND_VOLUME_TAG:
+    case SEND_CUE_SHEET:
+    case SEND_DVD_STRUCTURE:
     case PERSISTENT_RESERVE_OUT:
     case MAINTENANCE_OUT:
         cmd->mode = SCSI_XFER_TO_DEV;
@@ -835,7 +912,7 @@ static uint64_t scsi_cmd_lba(SCSICommand *cmd)
     case 1:
     case 2:
     case 5:
-        lba = ldl_be_p(&buf[2]);
+        lba = ldl_be_p(&buf[2]) & 0xffffffffULL;
         break;
     case 4:
         lba = ldq_be_p(&buf[2]);
commit 00a01ad47ae471a88cb64ccac6ed648c5c70d5f3
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Nov 14 14:31:48 2011 +0100

    scsi: update list of commands
    
    Add more commands and their names, and remove SEEK(6) which is obsolete.
    Instead, use SET_CAPACITY which is still in SSC.
    
    Tested-by: Thomas Schmitt <scdbackup at gmx.net>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 07419b8..7efcbd8 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -681,7 +681,7 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
     case TEST_UNIT_READY:
     case REWIND:
     case START_STOP:
-    case SEEK_6:
+    case SET_CAPACITY:
     case WRITE_FILEMARKS:
     case SPACE:
     case RESERVE:
@@ -1036,7 +1036,7 @@ static const char *scsi_command_name(uint8_t cmd)
         [ REASSIGN_BLOCKS          ] = "REASSIGN_BLOCKS",
         [ READ_6                   ] = "READ_6",
         [ WRITE_6                  ] = "WRITE_6",
-        [ SEEK_6                   ] = "SEEK_6",
+        [ SET_CAPACITY             ] = "SET_CAPACITY",
         [ READ_REVERSE             ] = "READ_REVERSE",
         [ WRITE_FILEMARKS          ] = "WRITE_FILEMARKS",
         [ SPACE                    ] = "SPACE",
@@ -1064,7 +1064,7 @@ static const char *scsi_command_name(uint8_t cmd)
         [ SEARCH_EQUAL             ] = "SEARCH_EQUAL",
         [ SEARCH_LOW               ] = "SEARCH_LOW",
         [ SET_LIMITS               ] = "SET_LIMITS",
-        [ PRE_FETCH                ] = "PRE_FETCH",
+        [ PRE_FETCH                ] = "PRE_FETCH/READ_POSITION",
         /* READ_POSITION and PRE_FETCH use the same operation code */
         [ SYNCHRONIZE_CACHE        ] = "SYNCHRONIZE_CACHE",
         [ LOCK_UNLOCK_CACHE        ] = "LOCK_UNLOCK_CACHE",
@@ -1101,9 +1101,11 @@ static const char *scsi_command_name(uint8_t cmd)
         [ WRITE_16                 ] = "WRITE_16",
         [ WRITE_VERIFY_16          ] = "WRITE_VERIFY_16",
         [ VERIFY_16                ] = "VERIFY_16",
-        [ SYNCHRONIZE_CACHE_16     ] = "SYNCHRONIZE_CACHE_16",
+        [ PRE_FETCH_16             ] = "PRE_FETCH_16",
+        [ SYNCHRONIZE_CACHE_16     ] = "SPACE_16/SYNCHRONIZE_CACHE_16",
+        /* SPACE_16 and SYNCHRONIZE_CACHE_16 use the same operation code */
         [ LOCATE_16                ] = "LOCATE_16",
-        [ WRITE_SAME_16            ] = "WRITE_SAME_16",
+        [ WRITE_SAME_16            ] = "ERASE_16/WRITE_SAME_16",
         /* ERASE_16 and WRITE_SAME_16 use the same operation code */
         [ SERVICE_ACTION_IN_16     ] = "SERVICE_ACTION_IN_16",
         [ WRITE_LONG_16            ] = "WRITE_LONG_16",
@@ -1113,6 +1115,8 @@ static const char *scsi_command_name(uint8_t cmd)
         [ LOAD_UNLOAD              ] = "LOAD_UNLOAD",
         [ READ_12                  ] = "READ_12",
         [ WRITE_12                 ] = "WRITE_12",
+        [ ERASE_12                 ] = "ERASE_12/GET_PERFORMANCE",
+        /* ERASE_12 and GET_PERFORMANCE use the same operation code */
         [ SERVICE_ACTION_IN_12     ] = "SERVICE_ACTION_IN_12",
         [ WRITE_VERIFY_12          ] = "WRITE_VERIFY_12",
         [ VERIFY_12                ] = "VERIFY_12",
@@ -1120,9 +1124,18 @@ static const char *scsi_command_name(uint8_t cmd)
         [ SEARCH_EQUAL_12          ] = "SEARCH_EQUAL_12",
         [ SEARCH_LOW_12            ] = "SEARCH_LOW_12",
         [ READ_ELEMENT_STATUS      ] = "READ_ELEMENT_STATUS",
-        [ SEND_VOLUME_TAG          ] = "SEND_VOLUME_TAG",
+        [ SEND_VOLUME_TAG          ] = "SEND_VOLUME_TAG/SET_STREAMING",
+        /* SEND_VOLUME_TAG and SET_STREAMING use the same operation code */
+        [ READ_CD                  ] = "READ_CD",
         [ READ_DEFECT_DATA_12      ] = "READ_DEFECT_DATA_12",
+        [ READ_DVD_STRUCTURE       ] = "READ_DVD_STRUCTURE",
+        [ RESERVE_TRACK            ] = "RESERVE_TRACK",
+        [ SEND_CUE_SHEET           ] = "SEND_CUE_SHEET",
+        [ SEND_DVD_STRUCTURE       ] = "SEND_DVD_STRUCTURE",
         [ SET_CD_SPEED             ] = "SET_CD_SPEED",
+        [ SET_READ_AHEAD           ] = "SET_READ_AHEAD",
+        [ ALLOW_OVERWRITE          ] = "ALLOW_OVERWRITE",
+        [ MECHANISM_STATUS         ] = "MECHANISM_STATUS",
     };
 
     if (cmd >= ARRAY_SIZE(names) || names[cmd] == NULL)
diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
index d0a467a..354ed7b 100644
--- a/hw/scsi-defs.h
+++ b/hw/scsi-defs.h
@@ -32,7 +32,7 @@
 #define REASSIGN_BLOCKS       0x07
 #define READ_6                0x08
 #define WRITE_6               0x0a
-#define SEEK_6                0x0b
+#define SET_CAPACITY          0x0b
 #define READ_REVERSE          0x0f
 #define WRITE_FILEMARKS       0x10
 #define SPACE                 0x11
@@ -81,14 +81,17 @@
 #define GET_EVENT_STATUS_NOTIFICATION 0x4a
 #define LOG_SELECT            0x4c
 #define LOG_SENSE             0x4d
+#define RESERVE_TRACK         0x53
 #define MODE_SELECT_10        0x55
 #define RESERVE_10            0x56
 #define RELEASE_10            0x57
 #define MODE_SENSE_10         0x5a
+#define SEND_CUE_SHEET        0x5d
 #define PERSISTENT_RESERVE_IN 0x5e
 #define PERSISTENT_RESERVE_OUT 0x5f
 #define VARLENGTH_CDB         0x7f
 #define WRITE_FILEMARKS_16    0x80
+#define ALLOW_OVERWRITE       0x82
 #define EXTENDED_COPY         0x83
 #define ATA_PASSTHROUGH       0x85
 #define ACCESS_CONTROL_IN     0x86
@@ -98,6 +101,8 @@
 #define WRITE_16              0x8a
 #define WRITE_VERIFY_16       0x8e
 #define VERIFY_16             0x8f
+#define PRE_FETCH_16          0x90
+#define SPACE_16              0x91
 #define SYNCHRONIZE_CACHE_16  0x91
 #define LOCATE_16             0x92
 #define WRITE_SAME_16         0x93
@@ -110,9 +115,11 @@
 #define MAINTENANCE_OUT       0xa4
 #define MOVE_MEDIUM           0xa5
 #define LOAD_UNLOAD           0xa6
+#define SET_READ_AHEAD        0xa7
 #define READ_12               0xa8
 #define WRITE_12              0xaa
 #define SERVICE_ACTION_IN_12  0xab
+#define ERASE_12              0xac
 #define READ_DVD_STRUCTURE    0xad
 #define WRITE_VERIFY_12       0xae
 #define VERIFY_12             0xaf
@@ -125,6 +132,7 @@
 #define SET_CD_SPEED          0xbb
 #define MECHANISM_STATUS      0xbd
 #define READ_CD               0xbe
+#define SEND_DVD_STRUCTURE    0xbf
 
 /*
  * SERVICE ACTION IN subcodes
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 73de0f6..0b06fef 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1374,10 +1374,8 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
             goto fail;
         }
         break;
-    case SEEK_6:
     case SEEK_10:
-        DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10,
-                r->req.cmd.lba);
+        DPRINTF("Seek(10) (sector %" PRId64 ")\n", r->req.cmd.lba);
         if (r->req.cmd.lba > s->qdev.max_lba) {
             goto illegal_lba;
         }
commit 2c20ae11adcfab94441da31460e86c6e15719084
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Nov 14 14:31:47 2011 +0100

    atapi: kill MODE SENSE(6), fix MODE SENSE(10)
    
    Mode page 2A of emulated ATAPI DVD-ROM should have page length 0x14
    like SCSI CD-ROM, rather than 0x12.
    
    Mode page length is off by 8, as it should contain the length of the
    payload after the first two bytes.
    
    MODE SENSE(6) should be thrown out of ATAPI DVD-ROM emulation.  It is
    not specified in the ATAPI list of MMC-2, and MMC-5 prescribes to use
    MODE SENSE(10).  Anyway, its implementation is wrong.
    
    Reported-by: Thomas Schmitt <scdbackup at gmx.net>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
index 1fed359..8af1cfd 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -695,12 +695,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
     int action, code;
     int max_len;
 
-    if (buf[0] == GPCMD_MODE_SENSE_10) {
-        max_len = ube16_to_cpu(buf + 7);
-    } else {
-        max_len = buf[4];
-    }
-
+    max_len = ube16_to_cpu(buf + 7);
     action = buf[2] >> 6;
     code = buf[2] & 0x3f;
 
@@ -708,7 +703,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
     case 0: /* current values */
         switch(code) {
         case MODE_PAGE_R_W_ERROR: /* error recovery */
-            cpu_to_ube16(&buf[0], 16 + 6);
+            cpu_to_ube16(&buf[0], 16 - 2);
             buf[2] = 0x70;
             buf[3] = 0;
             buf[4] = 0;
@@ -727,7 +722,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
             ide_atapi_cmd_reply(s, 16, max_len);
             break;
         case MODE_PAGE_AUDIO_CTL:
-            cpu_to_ube16(&buf[0], 24 + 6);
+            cpu_to_ube16(&buf[0], 24 - 2);
             buf[2] = 0x70;
             buf[3] = 0;
             buf[4] = 0;
@@ -746,7 +741,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
             ide_atapi_cmd_reply(s, 24, max_len);
             break;
         case MODE_PAGE_CAPABILITIES:
-            cpu_to_ube16(&buf[0], 28 + 6);
+            cpu_to_ube16(&buf[0], 30 - 2);
             buf[2] = 0x70;
             buf[3] = 0;
             buf[4] = 0;
@@ -755,7 +750,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
             buf[7] = 0;
 
             buf[8] = MODE_PAGE_CAPABILITIES;
-            buf[9] = 28 - 10;
+            buf[9] = 30 - 10;
             buf[10] = 0x3b; /* read CDR/CDRW/DVDROM/DVDR/DVDRAM */
             buf[11] = 0x00;
 
@@ -777,7 +772,9 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
             buf[25] = 0;
             buf[26] = 0;
             buf[27] = 0;
-            ide_atapi_cmd_reply(s, 28, max_len);
+            buf[28] = 0;
+            buf[29] = 0;
+            ide_atapi_cmd_reply(s, 30, max_len);
             break;
         default:
             goto error_cmd;
@@ -1043,7 +1040,6 @@ static const struct {
     [ 0x00 ] = { cmd_test_unit_ready,               CHECK_READY },
     [ 0x03 ] = { cmd_request_sense,                 ALLOW_UA },
     [ 0x12 ] = { cmd_inquiry,                       ALLOW_UA },
-    [ 0x1a ] = { cmd_mode_sense, /* (6) */          0 },
     [ 0x1b ] = { cmd_start_stop_unit,               0 }, /* [1] */
     [ 0x1e ] = { cmd_prevent_allow_medium_removal,  0 },
     [ 0x25 ] = { cmd_read_cdvd_capacity,            CHECK_READY },
commit 245d0049475206995ed39e36ecb95b0ca08878e6
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Nov 15 16:57:50 2011 +0100

    scsi-disk: guess geometry
    
    Old operating systems rely on correct geometry to convert from CHS
    addresses to LBA.  Providing correct data is necessary for them to boot.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index cc4f9ef..73de0f6 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -797,7 +797,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
             break;
         }
         /* if a geometry hint is available, use it */
-        bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
+        bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs);
         p[2] = (cylinders >> 16) & 0xff;
         p[3] = (cylinders >> 8) & 0xff;
         p[4] = cylinders & 0xff;
@@ -831,7 +831,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
         p[2] = 5000 >> 8;
         p[3] = 5000 & 0xff;
         /* if a geometry hint is available, use it */
-        bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
+        bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs);
         p[4] = heads & 0xff;
         p[5] = secs & 0xff;
         p[6] = s->qdev.blocksize >> 8;
commit 7082826eb41887da7795b3135eaeda1726647987
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Nov 15 17:36:38 2011 +0100

    scsi: fix fw path
    
    The pre-1.0 firmware path for SCSI devices already included the LUN
    using the suffix argument to add_boot_device_path.  I missed that when
    making channel and LUN customizable.  Avoid that it is included twice, and
    convert the colons to commas for consistency with other kinds of devices
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index e6ebbd5..07419b8 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -1279,7 +1279,7 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
     SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev);
     char path[100];
 
-    snprintf(path, sizeof(path), "%s@%d:%d:%d", qdev_fw_name(dev),
+    snprintf(path, sizeof(path), "%s@%d,%d,%d", qdev_fw_name(dev),
              d->channel, d->id, d->lun);
 
     return strdup(path);
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 62f538f..cc4f9ef 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1553,7 +1553,7 @@ static int scsi_initfn(SCSIDevice *dev)
     bdrv_set_buffer_alignment(s->qdev.conf.bs, s->qdev.blocksize);
 
     bdrv_iostatus_enable(s->qdev.conf.bs);
-    add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, ",0");
+    add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL);
     return 0;
 }
 
commit 00984e395363bd924627f8c332ca08007c861a1e
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Sat Nov 12 11:06:30 2011 +1100

    Documentation: Add section about iSCSI LUNS to qemu-doc
    
    Add a new section about using iSCSI LUNs with qemu
    and provide a short example on how to set up a target and access it
    using the built-in initiator
    
    Signed-off-by: Ronnie Sahlberg <ronniesahlberg at gmail.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-doc.texi b/qemu-doc.texi
index 149e9bd..1abba98 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -421,6 +421,7 @@ snapshots.
 * disk_images_fat_images::    Virtual FAT disk images
 * disk_images_nbd::           NBD access
 * disk_images_sheepdog::      Sheepdog disk images
+* disk_images_iscsi::         iSCSI LUNs
 @end menu
 
 @node disk_images_quickstart
@@ -695,6 +696,61 @@ qemu-img create sheepdog:@var{hostname}:@var{port}:@var{image} @var{size}
 qemu sheepdog:@var{hostname}:@var{port}:@var{image}
 @end example
 
+ at node disk_images_iscsi
+ at subsection iSCSI LUNs
+
+iSCSI is a popular protocol used to access SCSI devices across a computer
+network.
+
+There are two different ways iSCSI devices can be used by QEMU.
+
+The first method is to mount the iSCSI LUN on the host, and make it appear as
+any other ordinary SCSI device on the host and then to access this device as a
+/dev/sd device from QEMU. How to do this differs between host OSes.
+
+The second method involves using the iSCSI initiator that is built into
+QEMU. This provides a mechanism that works the same way regardless of which
+host OS you are running QEMU on. This section will describe this second method
+of using iSCSI together with QEMU.
+
+In QEMU, iSCSI devices are described using special iSCSI URLs
+
+ at example
+URL syntax:
+iscsi://[<username>[%<password>]@@]<host>[:<port>]/<target-iqn-name>/<lun>
+ at end example
+
+Username and password are optional and only used if your target is set up
+using CHAP authentication for access control.
+Alternatively the username and password can also be set via environment
+variables to have these not show up in the process list
+
+ at example
+export LIBISCSI_CHAP_USERNAME=<username>
+export LIBISCSI_CHAP_PASSWORD=<password>
+iscsi://<host>/<target-iqn-name>/<lun>
+ at end example
+
+Howto set up a simple iSCSI target on loopback and accessing it via QEMU:
+ at example
+This example shows how to set up an iSCSI target with one CDROM and one DISK
+using the Linux STGT software target. This target is available on Red Hat based
+systems as the package 'scsi-target-utils'.
+
+tgtd --iscsi portal=127.0.0.1:3260
+tgtadm --lld iscsi --op new --mode target --tid 1 -T iqn.qemu.test
+tgtadm --lld iscsi --mode logicalunit --op new --tid 1 --lun 1 \
+    -b /IMAGES/disk.img --device-type=disk
+tgtadm --lld iscsi --mode logicalunit --op new --tid 1 --lun 2 \
+    -b /IMAGES/cd.iso --device-type=cd
+tgtadm --lld iscsi --op bind --mode target --tid 1 -I ALL
+
+qemu-system-i386 -boot d -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \
+    -cdrom iscsi://127.0.0.1/iqn.qemu.test/2
+ at end example
+
+
+
 @node pcsys_network
 @section Network emulation
 
commit 1b14254b4815a0ddf9c5b6094b6f6fccd7203fca
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Nov 16 23:58:31 2011 +0200

    Makefile: fix qga dependencies
    
    .c files include .h files, so .o depends on .h,
    and the linked result depends on .o.
    We got it wrong for qga rules, fix it up.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/Makefile b/Makefile
index c7f2cbd..7c93739 100644
--- a/Makefile
+++ b/Makefile
@@ -208,11 +208,12 @@ test-visitor: test-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qap
 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
 
-QGALIB_GEN=$(addprefix $(qapi-dir)/, qga-qapi-types.c qga-qapi-types.h qga-qapi-visit.c qga-qmp-marshal.c qga-qmp-commands.h)
-$(QGALIB_GEN): $(GENERATED_HEADERS)
-$(qga-obj-y) qemu-ga.o: $(QGALIB_GEN)
+QGALIB_OBJ=$(addprefix $(qapi-dir)/, qga-qapi-types.o qga-qapi-visit.o qga-qmp-marshal.o)
+QGALIB_GEN=$(addprefix $(qapi-dir)/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
+$(QGALIB_OBJ): $(QGALIB_GEN) $(GENERATED_HEADERS)
+$(qga-obj-y) qemu-ga.o: $(QGALIB_GEN) $(GENERATED_HEADERS)
 
-qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qobject-obj-y) $(version-obj-y) $(addprefix $(qapi-dir)/, qga-qapi-visit.o qga-qapi-types.o qga-qmp-marshal.o)
+qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qobject-obj-y) $(version-obj-y) $(QGALIB_OBJ)
 
 QEMULIBS=libhw32 libhw64 libuser libdis libdis-user
 
commit b1beac3db243b67711740340c3e3a3ac311aa76b
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Nov 16 23:58:24 2011 +0200

    Makefile: dependency fix
    
    qga/guest-agent-commands.c includes qga-qmp-commands.h,
    but it was missing in its dependencies. Add it in QGALIB_GEN.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/Makefile b/Makefile
index a3c4bb4..c7f2cbd 100644
--- a/Makefile
+++ b/Makefile
@@ -208,7 +208,7 @@ test-visitor: test-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qap
 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
 
-QGALIB_GEN=$(addprefix $(qapi-dir)/, qga-qapi-types.c qga-qapi-types.h qga-qapi-visit.c qga-qmp-marshal.c)
+QGALIB_GEN=$(addprefix $(qapi-dir)/, qga-qapi-types.c qga-qapi-types.h qga-qapi-visit.c qga-qmp-marshal.c qga-qmp-commands.h)
 $(QGALIB_GEN): $(GENERATED_HEADERS)
 $(qga-obj-y) qemu-ga.o: $(QGALIB_GEN)
 
commit 599825c565f4e5f0790ff61ef14574b463e3b710
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Nov 16 23:58:18 2011 +0200

    Makefile: fix dependencies for generated .h, .c
    
    We have a single rule generating .c and .h files,
    so .h doesn't depend on .c: both depend on the
    source schema.
    
    Fix Makefile to reflect that - without this,
    if .c is there and .h is missing, Makefile does
    not know how to remake .h and assumes it's
    a dummy target, triggering endless rebuilds.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/Makefile b/Makefile
index b335f2a..a3c4bb4 100644
--- a/Makefile
+++ b/Makefile
@@ -172,34 +172,34 @@ qapi-dir := qapi-generated
 test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
 
-$(qapi-dir)/test-qapi-types.c: $(qapi-dir)/test-qapi-types.h
-$(qapi-dir)/test-qapi-types.h: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
+$(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
+$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
-$(qapi-dir)/test-qapi-visit.c: $(qapi-dir)/test-qapi-visit.h
-$(qapi-dir)/test-qapi-visit.h: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py
+$(qapi-dir)/test-qapi-visit.c $(qapi-dir)/test-qapi-visit.h :\
+$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
-$(qapi-dir)/test-qmp-commands.h: $(qapi-dir)/test-qmp-marshal.c
-$(qapi-dir)/test-qmp-marshal.c: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
+$(qapi-dir)/test-qmp-commands.h $(qapi-dir)/test-qmp-marshal.c :\
+$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
 	    $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
 
-$(qapi-dir)/qga-qapi-types.c: $(qapi-dir)/qga-qapi-types.h
-$(qapi-dir)/qga-qapi-types.h: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-types.py
+$(qapi-dir)/qga-qapi-types.c $(qapi-dir)/qga-qapi-types.h :\
+$(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-types.py
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py -o "$(qapi-dir)" -p "qga-" < $<, "  GEN   $@")
-$(qapi-dir)/qga-qapi-visit.c: $(qapi-dir)/qga-qapi-visit.h
-$(qapi-dir)/qga-qapi-visit.h: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-visit.py
+$(qapi-dir)/qga-qapi-visit.c $(qapi-dir)/qga-qapi-visit.h :\
+$(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-visit.py
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "qga-" < $<, "  GEN   $@")
-$(qapi-dir)/qga-qmp-commands.h: $(qapi-dir)/qga-qmp-marshal.c
-$(qapi-dir)/qga-qmp-marshal.c: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-commands.py
+$(qapi-dir)/qga-qmp-commands.h $(qapi-dir)/qga-qmp-marshal.c :\
+$(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-commands.py
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "qga-" < $<, "  GEN   $@")
 
-qapi-types.c: qapi-types.h
-qapi-types.h: $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py
+qapi-types.c qapi-types.h :\
+$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py -o "." < $<, "  GEN   $@")
-qapi-visit.c: qapi-visit.h
-qapi-visit.h: $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py
+qapi-visit.c qapi-visit.h :\
+$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py -o "."  < $<, "  GEN   $@")
-qmp-commands.h: qmp-marshal.c
-qmp-marshal.c: $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py
+qmp-commands.h qmp-marshal.c :\
+$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -m -o "." < $<, "  GEN   $@")
 
 test-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
commit 611b727374ad76fb0078ea65bc1387194913980e
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Nov 16 23:58:46 2011 +0200

    Makefile: remove more generated files on clean
    
    make clean missed the source qmp files generated
    by python. Fix that.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/Makefile b/Makefile
index 168093c..b335f2a 100644
--- a/Makefile
+++ b/Makefile
@@ -8,6 +8,7 @@ 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
 
 ifneq ($(wildcard config-host.mak),)
 # Put the all: rule here so that config-host.mak can contain dependencies.
@@ -227,6 +228,7 @@ clean:
 	rm -f trace.c trace.h trace.c-timestamp trace.h-timestamp
 	rm -f trace-dtrace.dtrace trace-dtrace.dtrace-timestamp
 	rm -f trace-dtrace.h trace-dtrace.h-timestamp
+	rm -f $(GENERATED_SOURCES)
 	rm -rf $(qapi-dir)
 	$(MAKE) -C tests clean
 	for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard; do \
commit 54d50be688aba80e0fd5ba53f23a074a0ce2e381
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon Nov 14 11:25:09 2011 -0200

    qapi: Check for negative enum values
    
    We don't currently check for negative enum values in qmp_output_type_enum(),
    this will very likely generate a segfault when triggered.
    
    However, it _seems_ that no code in tree can trigger this today.
    
    Acked-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qapi/qmp-output-visitor.c b/qapi/qmp-output-visitor.c
index d67724e..f76d015 100644
--- a/qapi/qmp-output-visitor.c
+++ b/qapi/qmp-output-visitor.c
@@ -190,7 +190,7 @@ static void qmp_output_type_enum(Visitor *v, int *obj, const char *strings[],
 
     assert(strings);
     while (strings[i++] != NULL);
-    if (value >= i - 1) {
+    if (value < 0 || value >= i - 1) {
         error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
         return;
     }
commit c951d9a6751576a076ac80a5e5145ceb8d794d38
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Nov 16 15:43:47 2011 +0100

    monitor: Fix file_completion() to check for stat() failure
    
    stat() can fail for a file name just read with readdir().  Easiest way
    to trigger is a dangling symbolic link --- look ma, no race!  When it
    fails, file_completion() uses sb.st_mode uninitialized.  If the
    directory bit happens to be set, it appends a "/" to the completed
    name.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/monitor.c b/monitor.c
index 5ea35de..1be222e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4207,9 +4207,9 @@ static void file_completion(const char *input)
             /* stat the file to find out if it's a directory.
              * In that case add a slash to speed up typing long paths
              */
-            stat(file, &sb);
-            if(S_ISDIR(sb.st_mode))
+            if (stat(file, &sb) == 0 && S_ISDIR(sb.st_mode)) {
                 pstrcat(file, sizeof(file), "/");
+            }
             readline_add_completion(cur_mon->rs, file);
         }
     }
commit e6d89f8c2518763b4d84f05a10d3fca02b9c8182
Author: Matthias Brugger <matthias.bgg at gmail.com>
Date:   Tue Nov 15 11:57:14 2011 +0000

    Fixing some spelling in docs/libcacard.txt
    
    Reviewed-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Matthias Brugger <matthias.bgg at gmail.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/docs/libcacard.txt b/docs/libcacard.txt
index 296706a..f7d7519 100644
--- a/docs/libcacard.txt
+++ b/docs/libcacard.txt
@@ -170,7 +170,7 @@ public entry point:
                                int cert_count);
 
   The parameters for this are:
-  card       - the virtual card structure which will prepresent this card.
+  card       - the virtual card structure which will represent this card.
   flags      - option flags that may be specific to this card type.
   cert       - array of binary certificates.
   cert_len   - array of lengths of each of the certificates specified in cert.
@@ -179,7 +179,7 @@ public entry point:
   cert_count - number of entries in cert, cert_len, and key arrays.
 
   Any cert, cert_len, or key with the same index are matching sets. That is
-  cert[0] is cert_len[0] long and has the corresponsing private key of key[0].
+  cert[0] is cert_len[0] long and has the corresponding private key of key[0].
 
 The card type emulator is expected to own the VCardKeys, but it should copy
 any raw cert data it wants to save. It can create new applets and add them to
@@ -261,7 +261,7 @@ Prior to processing calling the card type emulator's VCardProcessAPDU function,
    apdu->a_Le   - The expected length of any returned data.
    apdu->a_cla  - The raw apdu class.
    apdu->a_channel - The channel (decoded from the class).
-   apdu->a_secure_messaging_type - The decoded secure messagin type
+   apdu->a_secure_messaging_type - The decoded secure messaging type
                                    (from class).
    apdu->a_type - The decode class type.
    apdu->a_gen_type - the generic class type (7816, PROPRIETARY, RFU, PTS).
@@ -273,7 +273,7 @@ Creating a Response --
 
 The expected result of any APDU call is a response. The card type emulator must
 set *response with an appropriate VCardResponse value if it returns VCARD_DONE.
-Reponses could be as simple as returning a 2 byte status word response, to as
+Responses could be as simple as returning a 2 byte status word response, to as
 complex as returning a block of data along with a 2 byte response. Which is
 returned will depend on the semantics of the APDU. The following functions will
 create card responses.
@@ -282,12 +282,12 @@ create card responses.
 
     This is the most basic function to get a response. This function will
     return a response the consists solely one 2 byte status code. If that status
-    code is defined in card_7816t.h, then this function is guarrenteed to
+    code is defined in card_7816t.h, then this function is guaranteed to
     return a response with that status. If a cart type specific status code
     is passed and vcard_make_response fails to allocate the appropriate memory
     for that response, then vcard_make_response will return a VCardResponse
     of VCARD7816_STATUS_EXC_ERROR_MEMORY. In any case, this function is
-    guarrenteed to return a valid VCardResponse.
+    guaranteed to return a valid VCardResponse.
 
         VCardResponse *vcard_response_new(unsigned char *buf, int len,
                                           VCard7816Status status);
commit 126197214e24b51a76fa6b0559e45b025b77e752
Author: Vagrant Cascadian <vagrant at freegeek.org>
Date:   Mon Nov 14 14:06:23 2011 -0800

    Fix typo: runnning -> running
    
    One n too many for running, need we say more.
    
    Signed-Off-By: Vagrant Cascadian <vagrant at freegeek.org>
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index ddd115c..5bfc21f 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1845,7 +1845,7 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
                 code);
         if (host_supports_vmx() && code == VMX_INVALID_GUEST_STATE) {
             fprintf(stderr,
-                    "\nIf you're runnning a guest on an Intel machine without "
+                    "\nIf you're running a guest on an Intel machine without "
                         "unrestricted mode\n"
                     "support, the failure can be most likely due to the guest "
                         "entering an invalid\n"
commit 4238e26416c3b5ece9a823de9ab8f6cdfaff8f99
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Nov 13 22:24:27 2011 +0100

    Fix some spelling bugs in documentation and comments
    
    These errors were detected by codespell:
    
    remaing -> remaining
    soley -> solely
    virutal -> virtual
    seperate -> separate
    
    libcacard.txt still needs some more patches.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block-migration.c b/block-migration.c
index 0bff075..5f10486 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -521,7 +521,7 @@ static int is_stage2_completed(void)
 
         if ((remaining_dirty / bwidth) <=
             migrate_max_downtime()) {
-            /* finish stage2 because we think that we can finish remaing work
+            /* finish stage2 because we think that we can finish remaining work
                below max_downtime */
 
             return 1;
diff --git a/docs/libcacard.txt b/docs/libcacard.txt
index ae010d2..296706a 100644
--- a/docs/libcacard.txt
+++ b/docs/libcacard.txt
@@ -281,7 +281,7 @@ create card responses.
         VCardResponse *vcard_make_response(VCard7816Status status);
 
     This is the most basic function to get a response. This function will
-    return a response the consists soley one 2 byte status code. If that status
+    return a response the consists solely one 2 byte status code. If that status
     code is defined in card_7816t.h, then this function is guarrenteed to
     return a response with that status. If a cart type specific status code
     is passed and vcard_make_response fails to allocate the appropriate memory
@@ -327,7 +327,7 @@ and applet.
 
         int vcard_emul_get_login_count(VCard *card);
 
-    This function returns the the number of remaing login attempts for this
+    This function returns the the number of remaining login attempts for this
     card. If the card emulator does not know, or the card does not have a
     way of giving this information, this function returns -1.
 
@@ -373,7 +373,7 @@ functions:
 
   The options structure is built by another function in the virtual card
   interface where a string of virtual card emulator specific strings are
-  mapped to the options. The actual structure is defined by the virutal card
+  mapped to the options. The actual structure is defined by the virtual card
   emulator and is used to determine the configuration of soft cards, or to
   determine which physical cards to present to the guest.
 
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index c0a9325..5831e37 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -14,7 +14,7 @@ To map QMP-defined interfaces to the native C QAPI implementations,
 a JSON-based schema is used to define types and function
 signatures, and a set of scripts is used to generate types/signatures,
 and marshaling/dispatch code. The QEMU Guest Agent also uses these
-scripts, paired with a seperate schema, to generate
+scripts, paired with a separate schema, to generate
 marshaling/dispatch code for the guest agent server running in the
 guest.
 
commit b5e4946f9642b077fb07269a5542ec22564b3394
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Nov 13 22:24:26 2011 +0100

    Fix spelling in documentation and comments (similiar -> similar)
    
    This bug was detected by codespell.
    In mips_mipssim.c a grammatical error was fixed, too.
    
    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 5dee6fa..ae010d2 100644
--- a/docs/libcacard.txt
+++ b/docs/libcacard.txt
@@ -399,7 +399,7 @@ functions:
       This function will automatically generate the appropriate new reader
       events and add the reader to the list.
 
-  To create a new card, the virtual card emulator will call a similiar
+  To create a new card, the virtual card emulator will call a similar
   function.
 
            VCard *vcard_new(VCardEmul *card_emul,
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index 7407158..b56cba6 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -1,7 +1,7 @@
 /*
  * QEMU/mipssim emulation
  *
- * Emulates a very simple machine model similiar to the one use by the
+ * Emulates a very simple machine model similar to the one used by the
  * proprietary MIPS emulator.
  * 
  * Copyright (c) 2007 Thiemo Seufer
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 149e9bd..154b82d 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -1749,7 +1749,7 @@ PC Keyboard
 IDE controller
 @end itemize
 
-The mipssim pseudo board emulation provides an environment similiar
+The mipssim pseudo board emulation provides an environment similar
 to what the proprietary MIPS emulator uses for running Linux.
 It supports:
 
@@ -2141,7 +2141,7 @@ Xtensa emulator pseudo board "sim"
 Avnet LX60/LX110/LX200 board
 @end itemize
 
-The sim pseudo board emulation provides an environment similiar
+The sim pseudo board emulation provides an environment similar
 to one provided by the proprietary Tensilica ISS.
 It supports:
 
commit 3f5bd4e1b874590d3d76e031530799a4610da6dc
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Nov 14 11:02:38 2011 -0600

    Update version to 1.0-rc2
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/VERSION b/VERSION
index 4a15714..75a7da4 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.15.91
+0.15.92
commit 3827cdb1c3aa17a792d1658161195b9d7173c26b
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Nov 13 15:27:51 2011 +0200

    pc_piix: set qxl revision to 2 for pc-0.14
    
    The default is still 3, and I didn't change older machine types.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 27ea570..970f43c 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -311,6 +311,18 @@ static QEMUMachine pc_machine_v0_14 = {
     .desc = "Standard PC",
     .init = pc_init_pci,
     .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        {
+            .driver   = "qxl",
+            .property = "revision",
+            .value    = stringify(2),
+        },{
+            .driver   = "qxl-vga",
+            .property = "revision",
+            .value    = stringify(2),
+        },
+        { /* end of list */ }
+    },
 };
 
 static QEMUMachine pc_machine_v0_13 = {
commit e1556ad5b8143a15c26067c3862fe20631c0053f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Nov 7 13:25:45 2011 +0000

    hw/omap_gpio: Fix infinite recursion when doing 8/16 bit reads
    
    Fix a long-standing bug which meant that any attempt to do an
    8 or 16 bit read from the OMAP GPIO module would cause qemu to
    crash due to an infinite recursion.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/omap_gpio.c b/hw/omap_gpio.c
index 42e59c3..30630a8 100644
--- a/hw/omap_gpio.c
+++ b/hw/omap_gpio.c
@@ -510,7 +510,7 @@ static void omap2_gpio_module_write(void *opaque, target_phys_addr_t addr,
 
 static uint32_t omap2_gpio_module_readp(void *opaque, target_phys_addr_t addr)
 {
-    return omap2_gpio_module_readp(opaque, addr) >> ((addr & 3) << 3);
+    return omap2_gpio_module_read(opaque, addr & ~3) >> ((addr & 3) << 3);
 }
 
 static void omap2_gpio_module_writep(void *opaque, target_phys_addr_t addr,
commit 371572dff4d4dae128a03b30d623b7d212238a70
Author: Andrzej Zaborowski <andrew.zaborowski at intel.com>
Date:   Mon Nov 14 18:17:59 2011 +0100

    Revert bugfix e7852674d5 until tested or until after the release.
    
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/usb-net.c b/hw/usb-net.c
index f91fa32..a8b7c8d 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1268,9 +1268,8 @@ static ssize_t usbnet_receive(VLANClientState *nc, const uint8_t *buf, size_t si
 
     if (is_rndis(s)) {
         msg = (struct rndis_packet_msg_type *) s->in_buf;
-        if (s->rndis_state != RNDIS_DATA_INITIALIZED) {
+        if (!s->rndis_state == RNDIS_DATA_INITIALIZED)
             return -1;
-        }
         if (size + sizeof(struct rndis_packet_msg_type) > sizeof(s->in_buf))
             return -1;
 
@@ -1303,7 +1302,7 @@ 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) {
+    if (is_rndis(s) && !s->rndis_state == RNDIS_DATA_INITIALIZED) {
         return 1;
     }
 
commit 326384d5b6dcea69ca44695ee807f8b50234ab71
Author: Alexander Graf <agraf at suse.de>
Date:   Thu Nov 10 01:59:23 2011 +0100

    s390x: initialize virtio dev region
    
    When running the s390x virtio machine we can potentially use uninitialized
    memory for the virtio device backing ram. That can lead to weird breakge.
    
    So let's better initialize it to 0 properly.
    
    Reported-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>
    
    ---
    
    v1 -> v2:
    
      - use target_phys_addr_t

diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 37945d5..61b67e8 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -165,6 +165,9 @@ static void s390_init(ram_addr_t my_ram_size,
     ram_addr_t initrd_size = 0;
     int shift = 0;
     uint8_t *storage_keys;
+    void *virtio_region;
+    target_phys_addr_t virtio_region_len;
+    target_phys_addr_t virtio_region_start;
     int i;
 
     /* s390x ram size detection needs a 16bit multiplier + an increment. So
@@ -184,6 +187,15 @@ static void s390_init(ram_addr_t my_ram_size,
     memory_region_init_ram(ram, NULL, "s390.ram", my_ram_size);
     memory_region_add_subregion(sysmem, 0, ram);
 
+    /* clear virtio region */
+    virtio_region_len = my_ram_size - ram_size;
+    virtio_region_start = ram_size;
+    virtio_region = cpu_physical_memory_map(virtio_region_start,
+                                            &virtio_region_len, true);
+    memset(virtio_region, 0, virtio_region_len);
+    cpu_physical_memory_unmap(virtio_region, virtio_region_len, 1,
+                              virtio_region_len);
+
     /* allocate storage keys */
     storage_keys = g_malloc0(my_ram_size / TARGET_PAGE_SIZE);
 
commit 2a534aff30b29f7e504451c6ed04658e850144ba
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Nov 9 08:03:34 2011 +0000

    tcg: Use TCGReg for standard tcg-target entry points.
    
    Including tcg_out_ld, tcg_out_st, tcg_out_mov, tcg_out_movi.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index ce4760d..e05a64f 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1808,25 +1808,26 @@ static void tcg_target_init(TCGContext *s)
                   CPU_TEMP_BUF_NLONGS * sizeof(long));
 }
 
-static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
-                int arg1, tcg_target_long arg2)
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
+                              TCGReg arg1, tcg_target_long arg2)
 {
     tcg_out_ld32u(s, COND_AL, arg, arg1, arg2);
 }
 
-static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
-                int arg1, tcg_target_long arg2)
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
+                              TCGReg arg1, tcg_target_long arg2)
 {
     tcg_out_st32(s, COND_AL, arg, arg1, arg2);
 }
 
-static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type,
+                               TCGReg ret, TCGReg arg)
 {
     tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0));
 }
 
 static inline void tcg_out_movi(TCGContext *s, TCGType type,
-                int ret, tcg_target_long arg)
+                                TCGReg ret, tcg_target_long arg)
 {
     tcg_out_movi32(s, COND_AL, ret, arg);
 }
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 71d9677..59d4d12 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -338,7 +338,7 @@ static int tcg_target_const_match(tcg_target_long val,
 /* supplied by libgcc */
 extern void *__canonicalize_funcptr_for_compare(void *);
 
-static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
+static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
 {
     /* PA1.1 defines COPY as OR r,0,t; PA2.0 defines COPY as LDO 0(r),t
        but hppa-dis.c is unaware of this definition */
@@ -349,7 +349,7 @@ static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
 }
 
 static void tcg_out_movi(TCGContext *s, TCGType type,
-                         int ret, tcg_target_long arg)
+                         TCGReg ret, tcg_target_long arg)
 {
     if (check_fit_tl(arg, 14)) {
         tcg_out32(s, INSN_LDO | INSN_R1(ret)
@@ -393,15 +393,15 @@ static void tcg_out_ldst(TCGContext *s, int ret, int addr,
 }
 
 /* This function is required by tcg.c.  */
-static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
-                              int arg1, tcg_target_long arg2)
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
+                              TCGReg arg1, tcg_target_long arg2)
 {
     tcg_out_ldst(s, ret, arg1, arg2, INSN_LDW);
 }
 
 /* This function is required by tcg.c.  */
-static inline void tcg_out_st(TCGContext *s, TCGType type, int ret,
-                              int arg1, tcg_target_long arg2)
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg ret,
+                              TCGReg arg1, tcg_target_long arg2)
 {
     tcg_out_ldst(s, ret, arg1, arg2, INSN_STW);
 }
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 3069e53..dc81572 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -518,7 +518,8 @@ static inline void tgen_arithr(TCGContext *s, int subop, int dest, int src)
     tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3) + ext, dest, src);
 }
 
-static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type,
+                               TCGReg ret, TCGReg arg)
 {
     if (arg != ret) {
         int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
@@ -527,7 +528,7 @@ static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
 }
 
 static void tcg_out_movi(TCGContext *s, TCGType type,
-                         int ret, tcg_target_long arg)
+                         TCGReg ret, tcg_target_long arg)
 {
     if (arg == 0) {
         tgen_arithr(s, ARITH_XOR, ret, ret);
@@ -568,15 +569,15 @@ static inline void tcg_out_pop(TCGContext *s, int reg)
     tcg_out_opc(s, OPC_POP_r32 + LOWREGMASK(reg), 0, reg, 0);
 }
 
-static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
-                              int arg1, tcg_target_long arg2)
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
+                              TCGReg arg1, tcg_target_long arg2)
 {
     int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
     tcg_out_modrm_offset(s, opc, ret, arg1, arg2);
 }
 
-static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
-                              int arg1, tcg_target_long arg2)
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
+                              TCGReg arg1, tcg_target_long arg2)
 {
     int opc = OPC_MOVL_EvGv + (type == TCG_TYPE_I64 ? P_REXW : 0);
     tcg_out_modrm_offset(s, opc, arg, arg1, arg2);
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index bb22b9a..e3de79f 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -830,7 +830,7 @@ static inline void tcg_out_bundle(TCGContext *s, int template,
 }
 
 static inline void tcg_out_mov(TCGContext *s, TCGType type,
-                               TCGArg ret, TCGArg arg)
+                               TCGReg ret, TCGReg arg)
 {
     tcg_out_bundle(s, mmI,
                    tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
@@ -839,7 +839,7 @@ static inline void tcg_out_mov(TCGContext *s, TCGType type,
 }
 
 static inline void tcg_out_movi(TCGContext *s, TCGType type,
-                                TCGArg reg, tcg_target_long arg)
+                                TCGReg reg, tcg_target_long arg)
 {
     tcg_out_bundle(s, mLX,
                    tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
@@ -972,8 +972,8 @@ static inline void tcg_out_st_rel(TCGContext *s, uint64_t opc_m4, TCGArg arg,
     }
 }
 
-static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGArg arg,
-                              TCGArg arg1, tcg_target_long arg2)
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
+                              TCGReg arg1, tcg_target_long arg2)
 {
     if (type == TCG_TYPE_I32) {
         tcg_out_ld_rel(s, OPC_LD4_M1, arg, arg1, arg2);
@@ -982,8 +982,8 @@ static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGArg arg,
     }
 }
 
-static inline void tcg_out_st(TCGContext *s, TCGType type, TCGArg arg,
-                              TCGArg arg1, tcg_target_long arg2)
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
+                              TCGReg arg1, tcg_target_long arg2)
 {
     if (type == TCG_TYPE_I32) {
         tcg_out_st_rel(s, OPC_ST4_M4, arg, arg1, arg2);
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index a33d21f..c5c3282 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -379,13 +379,14 @@ static inline void tcg_out_nop(TCGContext *s)
     tcg_out32(s, 0);
 }
 
-static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type,
+                               TCGReg ret, TCGReg arg)
 {
     tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
 }
 
 static inline void tcg_out_movi(TCGContext *s, TCGType type,
-                                int reg, int32_t arg)
+                                TCGReg reg, tcg_target_long arg)
 {
     if (arg == (int16_t)arg) {
         tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
@@ -480,14 +481,14 @@ static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
     }
 }
 
-static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
-                              int arg1, tcg_target_long arg2)
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
+                              TCGReg arg1, tcg_target_long arg2)
 {
     tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
 }
 
-static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
-                              int arg1, tcg_target_long arg2)
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
+                              TCGReg arg1, tcg_target_long arg2)
 {
     tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
 }
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 87cc117..f5d9bf3 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -436,13 +436,13 @@ static const uint32_t tcg_to_bc[10] = {
     [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
 };
 
-static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
+static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
 {
     tcg_out32 (s, OR | SAB (arg, ret, arg));
 }
 
 static void tcg_out_movi(TCGContext *s, TCGType type,
-                         int ret, tcg_target_long arg)
+                         TCGReg ret, tcg_target_long arg)
 {
     if (arg == (int16_t) arg)
         tcg_out32 (s, ADDI | RT (ret) | RA (0) | (arg & 0xffff));
@@ -961,13 +961,13 @@ static void tcg_target_qemu_prologue (TCGContext *s)
     tcg_out32 (s, BCLR | BO_ALWAYS);
 }
 
-static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
+static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
                         tcg_target_long arg2)
 {
     tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
 }
 
-static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1,
+static void tcg_out_st (TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
                         tcg_target_long arg2)
 {
     tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 3d24cd4..4800977 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -435,7 +435,7 @@ static const uint32_t tcg_to_bc[10] = {
     [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
 };
 
-static void tcg_out_mov (TCGContext *s, TCGType type, int ret, int arg)
+static void tcg_out_mov (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
 {
     tcg_out32 (s, OR | SAB (arg, ret, arg));
 }
@@ -459,7 +459,7 @@ static void tcg_out_movi32 (TCGContext *s, int ret, int32_t arg)
 }
 
 static void tcg_out_movi (TCGContext *s, TCGType type,
-                          int ret, tcg_target_long arg)
+                          TCGReg ret, tcg_target_long arg)
 {
     int32_t arg32 = arg;
     arg = type == TCG_TYPE_I32 ? arg & 0xffffffff : arg;
@@ -930,7 +930,7 @@ static void tcg_target_qemu_prologue (TCGContext *s)
     tcg_out32 (s, BCLR | BO_ALWAYS);
 }
 
-static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
+static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
                         tcg_target_long arg2)
 {
     if (type == TCG_TYPE_I32)
@@ -939,7 +939,7 @@ static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
         tcg_out_ldsta (s, ret, arg1, arg2, LD, LDX);
 }
 
-static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1,
+static void tcg_out_st (TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
                         tcg_target_long arg2)
 {
     if (type == TCG_TYPE_I32)
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index fc3fd7f..b96312b 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -306,7 +306,8 @@ static void tcg_out_arithc(TCGContext *s, int rd, int rs1,
               | (val2const ? INSN_IMM13(val2) : INSN_RS2(val2)));
 }
 
-static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type,
+                               TCGReg ret, TCGReg arg)
 {
     tcg_out_arith(s, ret, arg, TCG_REG_G0, ARITH_OR);
 }
@@ -333,7 +334,7 @@ static inline void tcg_out_movi_imm32(TCGContext *s, int ret, uint32_t arg)
 }
 
 static inline void tcg_out_movi(TCGContext *s, TCGType type,
-                                int ret, tcg_target_long arg)
+                                TCGReg ret, tcg_target_long arg)
 {
     /* All 32-bit constants, as well as 64-bit constants with
        no high bits set go through movi_imm32.  */
@@ -398,8 +399,8 @@ static inline void tcg_out_ldst_asi(TCGContext *s, int ret, int addr,
               INSN_ASI(asi) | INSN_RS2(addr));
 }
 
-static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
-                              int arg1, tcg_target_long arg2)
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
+                              TCGReg arg1, tcg_target_long arg2)
 {
     if (type == TCG_TYPE_I32)
         tcg_out_ldst(s, ret, arg1, arg2, LDUW);
@@ -407,8 +408,8 @@ static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
         tcg_out_ldst(s, ret, arg1, arg2, LDX);
 }
 
-static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
-                              int arg1, tcg_target_long arg2)
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
+                              TCGReg arg1, tcg_target_long arg2)
 {
     if (type == TCG_TYPE_I32)
         tcg_out_ldst(s, arg, arg1, arg2, STW);
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 6b27d7b..77bd6ef 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -71,14 +71,14 @@ static void patch_reloc(uint8_t *code_ptr, int type,
 
 /* Forward declarations for functions declared and used in tcg-target.c. */
 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str);
-static void tcg_out_ld(TCGContext *s, TCGType type, int ret, int arg1,
+static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
                        tcg_target_long arg2);
-static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg);
+static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
 static void tcg_out_movi(TCGContext *s, TCGType type,
-                         int ret, tcg_target_long arg);
+                         TCGReg ret, tcg_target_long arg);
 static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
                        const int *const_args);
-static void tcg_out_st(TCGContext *s, TCGType type, int arg, int arg1,
+static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
                        tcg_target_long arg2);
 static int tcg_target_const_match(tcg_target_long val,
                                   const TCGArgConstraint *arg_ct);
diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c
index e373e2a..942910e 100644
--- a/tcg/tci/tcg-target.c
+++ b/tcg/tci/tcg-target.c
@@ -495,7 +495,7 @@ static void tci_out_label(TCGContext *s, TCGArg arg)
     }
 }
 
-static void tcg_out_ld(TCGContext *s, TCGType type, int ret, int arg1,
+static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
                        tcg_target_long arg2)
 {
     uint8_t *old_code_ptr = s->code_ptr;
@@ -519,7 +519,7 @@ static void tcg_out_ld(TCGContext *s, TCGType type, int ret, int arg1,
     old_code_ptr[1] = s->code_ptr - old_code_ptr;
 }
 
-static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
+static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
 {
     uint8_t *old_code_ptr = s->code_ptr;
     assert(ret != arg);
@@ -534,7 +534,7 @@ static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
 }
 
 static void tcg_out_movi(TCGContext *s, TCGType type,
-                         int t0, tcg_target_long arg)
+                         TCGReg t0, tcg_target_long arg)
 {
     uint8_t *old_code_ptr = s->code_ptr;
     uint32_t arg32 = arg;
@@ -834,7 +834,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
     old_code_ptr[1] = s->code_ptr - old_code_ptr;
 }
 
-static void tcg_out_st(TCGContext *s, TCGType type, int arg, int arg1,
+static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
                        tcg_target_long arg2)
 {
     uint8_t *old_code_ptr = s->code_ptr;
commit 771142c2a7d67d491962fdf8e94d27513849d5b3
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Nov 9 08:03:33 2011 +0000

    tcg: Standardize on TCGReg as the enum for hard registers
    
    Most targets did not name the enum; tci used TCGRegister.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 33afd97..48586c3 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -27,7 +27,7 @@
 #undef TCG_TARGET_WORDS_BIGENDIAN
 #undef TCG_TARGET_STACK_GROWSUP
 
-enum {
+typedef enum {
     TCG_REG_R0 = 0,
     TCG_REG_R1,
     TCG_REG_R2,
@@ -44,7 +44,7 @@ enum {
     TCG_REG_R13,
     TCG_REG_R14,
     TCG_REG_PC,
-};
+} TCGReg;
 
 #define TCG_TARGET_NB_REGS 16
 
diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h
index ec9a7bf..7f3c4cc 100644
--- a/tcg/hppa/tcg-target.h
+++ b/tcg/hppa/tcg-target.h
@@ -32,7 +32,7 @@
 
 #define TCG_TARGET_NB_REGS 32
 
-enum {
+typedef enum {
     TCG_REG_R0 = 0,
     TCG_REG_R1,
     TCG_REG_RP,
@@ -65,7 +65,7 @@ enum {
     TCG_REG_RET1,
     TCG_REG_SP,
     TCG_REG_R31,
-};
+} TCGReg;
 
 #define TCG_CT_CONST_0    0x0100
 #define TCG_CT_CONST_S5   0x0200
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index b9c9d4e..7756e7b 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -36,7 +36,7 @@
 # define TCG_TARGET_NB_REGS 8
 #endif
 
-enum {
+typedef enum {
     TCG_REG_EAX = 0,
     TCG_REG_ECX,
     TCG_REG_EDX,
@@ -64,7 +64,7 @@ enum {
     TCG_REG_RBP = TCG_REG_EBP,
     TCG_REG_RSI = TCG_REG_ESI,
     TCG_REG_RDI = TCG_REG_EDI,
-};
+} TCGReg;
 
 #define TCG_CT_CONST_S32 0x100
 #define TCG_CT_CONST_U32 0x200
diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h
index 578cf29..c388089 100644
--- a/tcg/ia64/tcg-target.h
+++ b/tcg/ia64/tcg-target.h
@@ -26,7 +26,7 @@
 
 /* We only map the first 64 registers */
 #define TCG_TARGET_NB_REGS 64
-enum {
+typedef enum {
     TCG_REG_R0 = 0,
     TCG_REG_R1,
     TCG_REG_R2,
@@ -91,7 +91,7 @@ enum {
     TCG_REG_R61,
     TCG_REG_R62,
     TCG_REG_R63,
-};
+} TCGReg;
 
 #define TCG_CT_CONST_ZERO 0x100
 #define TCG_CT_CONST_S22 0x200
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index e2a2571..477bc38 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -31,7 +31,7 @@
 
 #define TCG_TARGET_NB_REGS 32
 
-enum {
+typedef enum {
     TCG_REG_ZERO = 0,
     TCG_REG_AT,
     TCG_REG_V0,
@@ -64,7 +64,7 @@ enum {
     TCG_REG_SP,
     TCG_REG_FP,
     TCG_REG_RA,
-};
+} TCGReg;
 
 #define TCG_CT_CONST_ZERO 0x100
 #define TCG_CT_CONST_U16  0x200
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index 25a6ea4..3f22aaa 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -26,7 +26,7 @@
 #define TCG_TARGET_WORDS_BIGENDIAN
 #define TCG_TARGET_NB_REGS 32
 
-enum {
+typedef enum {
     TCG_REG_R0 = 0,
     TCG_REG_R1,
     TCG_REG_R2,
@@ -59,7 +59,7 @@ enum {
     TCG_REG_R29,
     TCG_REG_R30,
     TCG_REG_R31
-};
+} TCGReg;
 
 /* used for function call generation */
 #define TCG_REG_CALL_STACK TCG_REG_R1
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
index 8d1fb73..97eec08 100644
--- a/tcg/ppc64/tcg-target.h
+++ b/tcg/ppc64/tcg-target.h
@@ -26,7 +26,7 @@
 #define TCG_TARGET_WORDS_BIGENDIAN
 #define TCG_TARGET_NB_REGS 32
 
-enum {
+typedef enum {
     TCG_REG_R0 = 0,
     TCG_REG_R1,
     TCG_REG_R2,
@@ -59,7 +59,7 @@ enum {
     TCG_REG_R29,
     TCG_REG_R30,
     TCG_REG_R31
-};
+} TCGReg;
 
 /* used for function call generation */
 #define TCG_REG_CALL_STACK TCG_REG_R1
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
index 1464ef4..c3fe131 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -27,7 +27,7 @@
 
 #define TCG_TARGET_NB_REGS 32
 
-enum {
+typedef enum {
     TCG_REG_G0 = 0,
     TCG_REG_G1,
     TCG_REG_G2,
@@ -60,7 +60,7 @@ enum {
     TCG_REG_I5,
     TCG_REG_I6,
     TCG_REG_I7,
-};
+} TCGReg;
 
 #define TCG_CT_CONST_S11 0x100
 #define TCG_CT_CONST_S13 0x200
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
index 81ded86..cb5858c 100644
--- a/tcg/tci/tcg-target.h
+++ b/tcg/tci/tcg-target.h
@@ -150,7 +150,7 @@ typedef enum {
 #endif
     /* Special value UINT8_MAX is used by TCI to encode constant values. */
     TCG_CONST = UINT8_MAX
-} TCGRegister;
+} TCGReg;
 
 void tci_disas(uint8_t opc);
 
diff --git a/tci.c b/tci.c
index f17785d..a20a714 100644
--- a/tci.c
+++ b/tci.c
@@ -63,90 +63,90 @@ void *tci_tb_ptr;
 
 static tcg_target_ulong tci_reg[TCG_TARGET_NB_REGS];
 
-static tcg_target_ulong tci_read_reg(TCGRegister index)
+static tcg_target_ulong tci_read_reg(TCGReg index)
 {
     assert(index < ARRAY_SIZE(tci_reg));
     return tci_reg[index];
 }
 
 #if TCG_TARGET_HAS_ext8s_i32 || TCG_TARGET_HAS_ext8s_i64
-static int8_t tci_read_reg8s(TCGRegister index)
+static int8_t tci_read_reg8s(TCGReg index)
 {
     return (int8_t)tci_read_reg(index);
 }
 #endif
 
 #if TCG_TARGET_HAS_ext16s_i32 || TCG_TARGET_HAS_ext16s_i64
-static int16_t tci_read_reg16s(TCGRegister index)
+static int16_t tci_read_reg16s(TCGReg index)
 {
     return (int16_t)tci_read_reg(index);
 }
 #endif
 
 #if TCG_TARGET_REG_BITS == 64
-static int32_t tci_read_reg32s(TCGRegister index)
+static int32_t tci_read_reg32s(TCGReg index)
 {
     return (int32_t)tci_read_reg(index);
 }
 #endif
 
-static uint8_t tci_read_reg8(TCGRegister index)
+static uint8_t tci_read_reg8(TCGReg index)
 {
     return (uint8_t)tci_read_reg(index);
 }
 
-static uint16_t tci_read_reg16(TCGRegister index)
+static uint16_t tci_read_reg16(TCGReg index)
 {
     return (uint16_t)tci_read_reg(index);
 }
 
-static uint32_t tci_read_reg32(TCGRegister index)
+static uint32_t tci_read_reg32(TCGReg index)
 {
     return (uint32_t)tci_read_reg(index);
 }
 
 #if TCG_TARGET_REG_BITS == 64
-static uint64_t tci_read_reg64(TCGRegister index)
+static uint64_t tci_read_reg64(TCGReg index)
 {
     return tci_read_reg(index);
 }
 #endif
 
-static void tci_write_reg(TCGRegister index, tcg_target_ulong value)
+static void tci_write_reg(TCGReg index, tcg_target_ulong value)
 {
     assert(index < ARRAY_SIZE(tci_reg));
     assert(index != TCG_AREG0);
     tci_reg[index] = value;
 }
 
-static void tci_write_reg8s(TCGRegister index, int8_t value)
+static void tci_write_reg8s(TCGReg index, int8_t value)
 {
     tci_write_reg(index, value);
 }
 
-static void tci_write_reg16s(TCGRegister index, int16_t value)
+static void tci_write_reg16s(TCGReg index, int16_t value)
 {
     tci_write_reg(index, value);
 }
 
 #if TCG_TARGET_REG_BITS == 64
-static void tci_write_reg32s(TCGRegister index, int32_t value)
+static void tci_write_reg32s(TCGReg index, int32_t value)
 {
     tci_write_reg(index, value);
 }
 #endif
 
-static void tci_write_reg8(TCGRegister index, uint8_t value)
+static void tci_write_reg8(TCGReg index, uint8_t value)
 {
     tci_write_reg(index, value);
 }
 
-static void tci_write_reg16(TCGRegister index, uint16_t value)
+static void tci_write_reg16(TCGReg index, uint16_t value)
 {
     tci_write_reg(index, value);
 }
 
-static void tci_write_reg32(TCGRegister index, uint32_t value)
+static void tci_write_reg32(TCGReg index, uint32_t value)
 {
     tci_write_reg(index, value);
 }
@@ -159,7 +159,7 @@ static void tci_write_reg64(uint32_t high_index, uint32_t low_index,
     tci_write_reg(high_index, value >> 32);
 }
 #elif TCG_TARGET_REG_BITS == 64
-static void tci_write_reg64(TCGRegister index, uint64_t value)
+static void tci_write_reg64(TCGReg index, uint64_t value)
 {
     tci_write_reg(index, value);
 }
@@ -290,7 +290,7 @@ static target_ulong tci_read_ulong(uint8_t **tb_ptr)
 static tcg_target_ulong tci_read_ri(uint8_t **tb_ptr)
 {
     tcg_target_ulong value;
-    TCGRegister r = **tb_ptr;
+    TCGReg r = **tb_ptr;
     *tb_ptr += 1;
     if (r == TCG_CONST) {
         value = tci_read_i(tb_ptr);
@@ -304,7 +304,7 @@ static tcg_target_ulong tci_read_ri(uint8_t **tb_ptr)
 static uint32_t tci_read_ri32(uint8_t **tb_ptr)
 {
     uint32_t value;
-    TCGRegister r = **tb_ptr;
+    TCGReg r = **tb_ptr;
     *tb_ptr += 1;
     if (r == TCG_CONST) {
         value = tci_read_i32(tb_ptr);
@@ -326,7 +326,7 @@ static uint64_t tci_read_ri64(uint8_t **tb_ptr)
 static uint64_t tci_read_ri64(uint8_t **tb_ptr)
 {
     uint64_t value;
-    TCGRegister r = **tb_ptr;
+    TCGReg r = **tb_ptr;
     *tb_ptr += 1;
     if (r == TCG_CONST) {
         value = tci_read_i64(tb_ptr);
commit ef81522bc18e234485282a6fa01671d1960bc0f2
Author: Alexander Graf <agraf at suse.de>
Date:   Fri Oct 7 09:51:50 2011 +0200

    s390x: Add shutdown for TCG s390-virtio machine
    
    Now that we have code in place to do refcounting of online CPUs, we
    can drag the TCG code along and implement shutdown for that one too,
    so it doesn't feel left out by its KVM counterpart.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index a66aa01..202c098 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -315,6 +315,15 @@ unsigned s390_del_running_cpu(CPUState *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 unsigned s390_del_running_cpu(CPUState *env)
+{
+    return 0;
+}
 #endif
 void cpu_lock(void);
 void cpu_unlock(void);
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 4145104..10cc9dd 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -26,6 +26,9 @@
 #include "gdbstub.h"
 #include "qemu-common.h"
 #include "qemu-timer.h"
+#ifndef CONFIG_USER_ONLY
+#include "sysemu.h"
+#endif
 
 //#define DEBUG_S390
 //#define DEBUG_S390_PTE
@@ -131,6 +134,7 @@ void cpu_reset(CPUS390XState *env)
     memset(env, 0, offsetof(CPUS390XState, breakpoints));
     /* FIXME: reset vector? */
     tlb_flush(env, 1);
+    s390_add_running_cpu(env);
 }
 
 #ifndef CONFIG_USER_ONLY
@@ -466,11 +470,15 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong vaddr)
 void load_psw(CPUState *env, uint64_t mask, uint64_t addr)
 {
     if (mask & PSW_MASK_WAIT) {
-        env->halted = 1;
-        env->exception_index = EXCP_HLT;
         if (!(mask & (PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK))) {
-            /* XXX disabled wait state - CPU is dead */
+            if (s390_del_running_cpu(env) == 0) {
+#ifndef CONFIG_USER_ONLY
+                qemu_system_shutdown_request();
+#endif
+            }
         }
+        env->halted = 1;
+        env->exception_index = EXCP_HLT;
     }
 
     env->psw.addr = addr;
@@ -599,6 +607,7 @@ void do_interrupt (CPUState *env)
     qemu_log("%s: %d at pc=%" PRIx64 "\n", __FUNCTION__, env->exception_index,
              env->psw.addr);
 
+    s390_add_running_cpu(env);
     /* handle external interrupts */
     if ((env->psw.mask & PSW_MASK_EXT) &&
         env->exception_index == -1) {
commit 854e42f3e8d3dcaf35b018cf56618fbcd15082d9
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Tue Oct 4 05:20:59 2011 +0000

    s390: Fix cpu shutdown for KVM
    
    On s390 a shutdown is the state of all CPUs being either stopped
    or disabled (for interrupts) waiting. We have to track the overall
    number of running CPUs to call the shutdown sequence accordingly.
    This patch implements the counting and shutdown handling for the
    kvm path in qemu.
    Lets also wrap changes to env->halted and env->exception_index.
    
    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 ee850f0..37945d5 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -121,6 +121,34 @@ int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall)
     return r;
 }
 
+/*
+ * The number of running CPUs. On s390 a shutdown is the state of all CPUs
+ * being either stopped or disabled (for interrupts) waiting. We have to
+ * track this number to call the shutdown sequence accordingly. This
+ * number is modified either on startup or while holding the big qemu lock.
+ */
+static unsigned s390_running_cpus;
+
+void s390_add_running_cpu(CPUState *env)
+{
+    if (env->halted) {
+        s390_running_cpus++;
+        env->halted = 0;
+        env->exception_index = -1;
+    }
+}
+
+unsigned s390_del_running_cpu(CPUState *env)
+{
+    if (env->halted == 0) {
+        assert(s390_running_cpus >= 1);
+        s390_running_cpus--;
+        env->halted = 1;
+        env->exception_index = EXCP_HLT;
+    }
+    return s390_running_cpus;
+}
+
 /* PC hardware initialisation */
 static void s390_init(ram_addr_t my_ram_size,
                       const char *boot_device,
@@ -179,8 +207,8 @@ static void s390_init(ram_addr_t my_ram_size,
         tmp_env->storage_keys = storage_keys;
     }
 
-    env->halted = 0;
-    env->exception_index = 0;
+    /* One CPU has to run */
+    s390_add_running_cpu(env);
 
     if (kernel_filename) {
         kernel_size = load_image(kernel_filename, qemu_get_ram_ptr(0));
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 95abe59..a66aa01 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -309,6 +309,8 @@ static inline void kvm_s390_interrupt_internal(CPUState *env, int type,
 }
 #endif
 CPUState *s390_cpu_addr2state(uint16_t cpu_addr);
+void s390_add_running_cpu(CPUState *env);
+unsigned s390_del_running_cpu(CPUState *env);
 
 /* from s390-virtio-bus */
 extern const target_phys_addr_t virtio_size;
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 4beb794..40b0ab1 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -185,8 +185,7 @@ void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
         return;
     }
 
-    env->halted = 0;
-    env->exception_index = -1;
+    s390_add_running_cpu(env);
     qemu_cpu_kick(env);
 
     kvmint.type = type;
@@ -299,8 +298,7 @@ static int handle_diag(CPUState *env, struct kvm_run *run, int ipb_code)
 static int s390_cpu_restart(CPUState *env)
 {
     kvm_s390_interrupt(env, KVM_S390_RESTART, 0);
-    env->halted = 0;
-    env->exception_index = -1;
+    s390_add_running_cpu(env);
     qemu_cpu_kick(env);
     dprintf("DONE: SIGP cpu restart: %p\n", env);
     return 0;
@@ -425,17 +423,16 @@ static int handle_intercept(CPUState *env)
             r = handle_instruction(env, run);
             break;
         case ICPT_WAITPSW:
-            /* XXX What to do on system shutdown? */
-            env->halted = 1;
-            env->exception_index = EXCP_HLT;
+        case ICPT_CPU_STOP:
+            if (s390_del_running_cpu(env) == 0) {
+                qemu_system_shutdown_request();
+            }
+            r = EXCP_HALTED;
             break;
         case ICPT_SOFT_INTERCEPT:
             fprintf(stderr, "KVM unimplemented icpt SOFT\n");
             exit(1);
             break;
-        case ICPT_CPU_STOP:
-            qemu_system_shutdown_request();
-            break;
         case ICPT_IO:
             fprintf(stderr, "KVM unimplemented icpt IO\n");
             exit(1);
@@ -468,8 +465,6 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
 
     if (ret == 0) {
         ret = EXCP_INTERRUPT;
-    } else if (ret > 0) {
-        ret = 0;
     }
     return ret;
 }
commit 13449a6e0ecf6c73e34657100566a471f0c26bbb
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Fri Sep 23 03:38:12 2011 +0000

    s390: fix short kernel command lines
    
    The default kernel command line for s390 is
    "root=/dev/ram0 ro"
    
    When overriding this line, we have to ensure to also copy the \0 to
    avoid false lines, for example, -append "root=/dev/vda" will result in
    "root=/dev/vda0 ro" with the current code.
    
    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 003d5ab..ee850f0 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -230,7 +230,7 @@ static void s390_init(ram_addr_t my_ram_size,
 
     if (kernel_cmdline) {
         cpu_physical_memory_write(KERN_PARM_AREA, kernel_cmdline,
-                                  strlen(kernel_cmdline));
+                                  strlen(kernel_cmdline) + 1);
     }
 
     /* Create VirtIO network adapters */
commit e9d86b760cca52dc35c7716873c342eb03c22b61
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Wed Sep 14 22:22:19 2011 +0000

    s390: fix reset hypercall to reset the status
    
    This patch fixes the reset hypercall which is supposed to also
    reset the device status in device memory.
    This fixes the following bug:
    
    [root at localhost driver]# echo virtio0 > unbind
    [   35.056966] ------------[ cut here ]------------
    [   35.057054] kernel BUG at drivers/virtio/virtio.c:157!
    [   35.057113] illegal operation: 0001 [#1] SMP
    [   35.057181] Modules linked in:
    [   35.057243] CPU: 0 Not tainted 3.0.0-rc1-00180-g0792644-dirty #51
    [   35.057323] Process bash (pid: 497, task: 000000003e58c538, ksp: 000000003ef43978)
    [   35.057409] Krnl PSW : 0704100180000000 00000000003d46f8 (virtio_check_driver_offered_feature+0x0/0x38)
    [   35.057528]            R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:0 CC:1 PM:0 EA:3
    [   35.057616] Krnl GPRS: 0000000000000000 0000000040000000 0000000000000007 0000000000000000
    [   35.057716]            00000000003b3be4 0000000000000001 000000003ef4d380 000000003f1cff00
    [   35.057805]            000000003ef43f18 00000000005ca620 0000000000000008 0000000000838e88
    [   35.057919]            000000000083c860 000000003f7c2e00 00000000003d46b0 000000003ef43d10
    [   35.058027] Krnl Code: 00000000003d46e8: f0b00004ebcf	srp	4(12,%r0),3023(%r14),0
    [   35.058115]            00000000003d46ee: f0a0000407f4	srp	4(11,%r0),2036,0
    [   35.058207]            00000000003d46f4: a7f40001		brc	15,3d46f6
    [   35.058295]           >00000000003d46f8: e31020900004	lg	%r1,144(%r2)
    [   35.058383]            00000000003d46fe: bf2f1080		icm	%r2,15,128(%r1)
    [   35.058470]            00000000003d4702: a784000d		brc	8,3d471c
    [   35.058557]            00000000003d4706: e32010780004	lg	%r2,120(%r1)
    [   35.058645]            00000000003d470c: 59302000		c	%r3,0(%r2)
    [   35.058748] Call Trace:
    [   35.058777] ([<00000000003d469e>] virtio_dev_remove+0x36/0x90)
    [   35.058852]  [<00000000003f3a40>] __device_release_driver+0x7c/0xec
    [   35.058936]  [<00000000003f3ae8>] device_release_driver+0x38/0x48
    [   35.059023]  [<00000000003f2a98>] driver_unbind+0xa4/0xc4
    [   35.059111]  [<00000000002acb70>] sysfs_write_file+0xe8/0x19c
    [   35.059226]  [<000000000022e7a4>] vfs_write+0xb0/0x18c
    [   35.059317]  [<000000000022eb18>] SyS_write+0x58/0xb4
    [   35.059398]  [<000000000057e674>] sysc_noemu+0x16/0x1c
    [   35.059475]  [<000003fffd44b6c0>] 0x3fffd44b6c0
    [   35.059531] Last Breaking-Event-Address:
    [   35.059576]  [<00000000003d46f4>] virtio_dev_remove+0x8c/0x90
    [   35.059646]
    [   35.059661] ---[ end trace 9b1959188f21ee11 ]---
    
    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 60c66e9..003d5ab 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -97,6 +97,7 @@ int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall)
 
         dev = s390_virtio_bus_find_mem(s390_bus, mem);
         virtio_reset(dev->vdev);
+        stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0);
         s390_virtio_device_sync(dev);
         break;
     }
commit 1864b94abb20fec2fbc4b99c764bc427141d79f0
Author: Alexander Graf <agraf at suse.de>
Date:   Thu Jul 14 11:52:08 2011 +0200

    s390x: implement SIGP restart and shutdown
    
    An s390x OS does reboot and shutdown triggers through hypercalls that
    we didn't implement on the TCG backend yet. That means that so far we
    couldn't shut down virtual machines for example, having them hang on
    shutdown when not using KVM.
    
    With this patch, this restriction is gone. We can now shut down and
    reboot s390x virtual machines even when using the TCG backend.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index 364b100..137bae7 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -29,6 +29,10 @@
 #include <linux/kvm.h>
 #endif
 
+#if !defined (CONFIG_USER_ONLY)
+#include "sysemu.h"
+#endif
+
 /*****************************************************************************/
 /* Softmmu support */
 #if !defined (CONFIG_USER_ONLY)
@@ -2901,6 +2905,16 @@ uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
         env->regs[r1] &= 0xffffffff00000000ULL;
         cc = 1;
         break;
+#if !defined (CONFIG_USER_ONLY)
+    case SIGP_RESTART:
+        qemu_system_reset_request();
+        cpu_loop_exit(env);
+        break;
+    case SIGP_STOP:
+        qemu_system_shutdown_request();
+        cpu_loop_exit(env);
+        break;
+#endif
     default:
         /* unknown sigp */
         fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code);
commit 17bb18ce16b45e61248c5238074fa9cf8bc547bf
Author: Alexander Graf <agraf at suse.de>
Date:   Thu Jul 14 11:50:33 2011 +0200

    s390x: implement rrbe instruction properly
    
    The rrbe instruction resets the reference bit in the given storage key.
    So far, we merely made it a nop and also returned an invalid CC value,
    so that the kernel never knew if a page actually got accessed.
    
    This patch implements it properly, flushing the R bit and returning the
    correct CC value.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index 440e871..364b100 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -2779,14 +2779,15 @@ void HELPER(sske)(uint32_t r1, uint64_t r2)
 /* reset reference bit extended */
 uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2)
 {
+    uint8_t re;
+    uint8_t key;
     if (r2 > ram_size) {
         return 0;
     }
 
-    /* XXX implement */
-#if 0
-    env->storage_keys[r2 / TARGET_PAGE_SIZE] &= ~SK_REFERENCED;
-#endif
+    key = env->storage_keys[r2 / TARGET_PAGE_SIZE];
+    re = key & (SK_R | SK_C);
+    env->storage_keys[r2 / TARGET_PAGE_SIZE] = (key & ~SK_R);
 
     /*
      * cc
@@ -2796,7 +2797,8 @@ uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2)
      * 2  Reference bit one; change bit zero
      * 3  Reference bit one; change bit one
      */
-    return 0;
+
+    return re >> 1;
 }
 
 /* compare and swap and purge */
commit b995913853b98812845b1b82ac5f61ab31d2d7b0
Author: Alexander Graf <agraf at suse.de>
Date:   Thu Jul 14 11:49:08 2011 +0200

    s390x: update R and C bits in storage key
    
    When the s390x maps a page or writes happen to a page, the R and C
    bits get updated. The easiest way to implement this in qemu is to
    simply update them whenever we map a TLB translation and act according
    to the permissions.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index e192b50..95abe59 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -819,6 +819,10 @@ struct sysib_322 {
 #define _PAGE_RO        0x200            /* HW read-only bit  */
 #define _PAGE_INVALID   0x400            /* HW invalid bit    */
 
+#define SK_C                    (0x1 << 1)
+#define SK_R                    (0x1 << 2)
+#define SK_F                    (0x1 << 3)
+#define SK_ACC_MASK             (0xf << 4)
 
 
 /* EBCDIC handling */
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 96dd867..4145104 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -348,6 +348,7 @@ int mmu_translate(CPUState *env, target_ulong vaddr, int rw, uint64_t asc,
                   target_ulong *raddr, int *flags)
 {
     int r = -1;
+    uint8_t *sk;
 
     *flags = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
     vaddr &= TARGET_PAGE_MASK;
@@ -390,6 +391,17 @@ out:
         *raddr = *raddr + env->psa;
     }
 
+    if (*raddr <= ram_size) {
+        sk = &env->storage_keys[*raddr / TARGET_PAGE_SIZE];
+        if (*flags & PAGE_READ) {
+            *sk |= SK_R;
+        }
+
+        if (*flags & PAGE_WRITE) {
+            *sk |= SK_C;
+        }
+    }
+
     return r;
 }
 
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index 2f46bdd..440e871 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -2761,7 +2761,6 @@ uint64_t HELPER(iske)(uint64_t r2)
         return 0;
     }
 
-    /* XXX maybe use qemu's internal keys? */
     return env->storage_keys[addr / TARGET_PAGE_SIZE];
 }
 
commit 09ed75f7848522f5d6f7ccca4bc9d0ab76006142
Author: Alexander Graf <agraf at suse.de>
Date:   Thu Jul 14 11:45:07 2011 +0200

    s390x: make ipte 31-bit aware
    
    When running 31-bit code we can potentially map the same virtual
    address twice - once as 0x0yyyyyyy and once as 0x8yyyyyyy, because
    the upper bit gets ignored.
    
    This also should be reflected in the tlb invalidation path, so we
    really invalidate also the transparently created tlb entries.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index e594118..2f46bdd 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -2950,6 +2950,13 @@ void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr)
     /* XXX we exploit the fact that Linux passes the exact virtual
            address here - it's not obliged to! */
     tlb_flush_page(env, page);
+
+    /* XXX 31-bit hack */
+    if (page & 0x80000000) {
+        tlb_flush_page(env, page & ~0x80000000);
+    } else {
+        tlb_flush_page(env, page | 0x80000000);
+    }
 }
 
 /* flush local tlb */
commit 27b5979d9d5dbc5f2ef21a96481f766bf3959b57
Author: Alexander Graf <agraf at suse.de>
Date:   Thu Jul 14 11:44:11 2011 +0200

    s390x: add ldeb instruction
    
    While running perl, we encountered the ldeb instruction to be used,
    so we implement it :).
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/helpers.h b/target-s390x/helpers.h
index 6ca48eb..01c8d0e 100644
--- a/target-s390x/helpers.h
+++ b/target-s390x/helpers.h
@@ -102,6 +102,7 @@ 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)
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index cd57678..e594118 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -1631,6 +1631,15 @@ void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2)
                                          &env->fpu_status);
 }
 
+/* convert 32-bit float to 64-bit float */
+void HELPER(ldeb)(uint32_t f1, uint64_t a2)
+{
+    uint32_t v2;
+    v2 = ldl(a2);
+    env->fregs[f1].d = float32_to_float64(v2,
+                                          &env->fpu_status);
+}
+
 /* convert 64-bit float to 128-bit float */
 void HELPER(lxdb)(uint32_t f1, uint64_t a2)
 {
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 6a22fde..ee15672 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2214,6 +2214,10 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
     addr = get_address(s, x2, b2, d2);
     tmp_r1 = tcg_const_i32(r1);
     switch (op) {
+    case 0x4: /* LDEB R1,D2(X2,B2) [RXE] */
+        potential_page_fault(s);
+        gen_helper_ldeb(tmp_r1, addr);
+        break;
     case 0x5: /* LXDB R1,D2(X2,B2) [RXE] */
         potential_page_fault(s);
         gen_helper_lxdb(tmp_r1, addr);
commit a3efecb847dd89886f7cd3f71661b2d79ec68072
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Thu Oct 20 14:53:35 2011 +0200

    hw/onenand: reject read-only drives
    
    Signed-off-by: Juha Riihimäki <juha.riihimaki at nokia.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/onenand.c b/hw/onenand.c
index 6f68f70..7898da9 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -26,6 +26,7 @@
 #include "memory.h"
 #include "exec-memory.h"
 #include "sysbus.h"
+#include "qemu-error.h"
 
 /* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
 #define PAGE_SHIFT	11
@@ -772,6 +773,10 @@ static int onenand_initfn(SysBusDevice *dev)
         s->image = memset(g_malloc(size + (size >> 5)),
                           0xff, size + (size >> 5));
     } else {
+        if (bdrv_is_read_only(s->bdrv)) {
+            error_report("Can't use a read-only drive");
+            return -1;
+        }
         s->bdrv_cur = s->bdrv;
     }
     s->otp = memset(g_malloc((64 + 2) << PAGE_SHIFT),
commit 3fc3abf7ecc5b27fa4f6014b44101072134ea0e4
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Thu Oct 20 14:53:34 2011 +0200

    hw/nand: reject read-only drives
    
    also gracefully fail on nand_device_init() for unsupported block
    size instead of aborting.
    
    Signed-off-by: Juha Riihimäki <juha.riihimaki at nokia.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/nand.c b/hw/nand.c
index c27783e..7f25814 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -19,6 +19,7 @@
 # include "flash.h"
 # include "blockdev.h"
 # include "sysbus.h"
+#include "qemu-error.h"
 
 # define NAND_CMD_READ0		0x00
 # define NAND_CMD_READ1		0x01
@@ -384,18 +385,23 @@ static int nand_device_init(SysBusDevice *dev)
         nand_init_2048(s);
         break;
     default:
-        hw_error("%s: Unsupported NAND block size.\n", __func__);
+        error_report("Unsupported NAND block size");
+        return -1;
     }
 
     pagesize = 1 << s->oob_shift;
     s->mem_oob = 1;
-    if (s->bdrv && bdrv_getlength(s->bdrv) >=
-            (s->pages << s->page_shift) + (s->pages << s->oob_shift)) {
-        pagesize = 0;
-        s->mem_oob = 0;
-    }
-
-    if (!s->bdrv) {
+    if (s->bdrv) {
+        if (bdrv_is_read_only(s->bdrv)) {
+            error_report("Can't use a read-only drive");
+            return -1;
+        }
+        if (bdrv_getlength(s->bdrv) >=
+                (s->pages << s->page_shift) + (s->pages << s->oob_shift)) {
+            pagesize = 0;
+            s->mem_oob = 0;
+        }
+    } else {
         pagesize += 1 << s->page_shift;
     }
     if (pagesize) {
commit b2887c43eeec4b8e7697e18dfac071fd9cb4f0c0
Author: Jean-Christophe DUBOIS <jcd at tribudubois.net>
Date:   Mon Nov 14 03:09:20 2011 +0100

    hw/arm_sysctl: Fix RESETCTL for realview-pb-a8 and -pbx-a9
    
    Depending on the considered baseboard the bit used to
    reset the platform is different.
    
    Here is the list of considered Realview/Versatile platforms:
    
    Realview/Versatile AB for ARM926EJ-S: BOARD_ID = 0x100 = BOARD_ID_PB9
    http://infocenter.arm.com/help/topic/com.arm.doc.dui0225d/CACCIFGI.html
    
    RealView Emulation Baseboard: BOARD_ID = 0x140 = BOARD_ID_EB
    No reset register
    
    RealView PB for Cortex-A8: BOARD_ID = 0x178 = BOARD_ID_PBA8
    http://infocenter.arm.com/help/topic/com.arm.doc.dui0417d/BBACIGAD.html
    
    RealView PB for Cortex-A9: BOARD_ID = 0x182 = BOARD_ID_PBX
    http://infocenter.arm.com/help/topic/com.arm.doc.dui0440b/CACCHBFB.html
    
    Motherboard Express =C2=B5ATX: BOARD_ID = 0x190 = BOARD_ID_VEXPRESS
    No reset register
    
    Signed-off-by: Jean-Christophe DUBOIS <jcd at tribudubois.net>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index 17cf6f7..477fc6f 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -231,15 +231,30 @@ static void arm_sysctl_write(void *opaque, target_phys_addr_t offset,
         s->nvflags &= ~val;
         break;
     case 0x40: /* RESETCTL */
-        if (board_id(s) == BOARD_ID_VEXPRESS) {
+        switch (board_id(s)) {
+        case BOARD_ID_PB926:
+            if (s->lockval == LOCK_VALUE) {
+                s->resetlevel = val;
+                if (val & 0x100) {
+                    qemu_system_reset_request();
+                }
+            }
+            break;
+        case BOARD_ID_PBX:
+        case BOARD_ID_PBA8:
+            if (s->lockval == LOCK_VALUE) {
+                s->resetlevel = val;
+                if (val & 0x04) {
+                    qemu_system_reset_request();
+                }
+            }
+            break;
+        case BOARD_ID_VEXPRESS:
+        case BOARD_ID_EB:
+        default:
             /* reserved: RAZ/WI */
             break;
         }
-        if (s->lockval == LOCK_VALUE) {
-            s->resetlevel = val;
-            if (val & 0x100)
-                qemu_system_reset_request ();
-        }
         break;
     case 0x44: /* PCICTL */
         /* nothing to do.  */
commit 7c64d297f988f6ee2136f29fac010db2c8fc352c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Nov 13 14:18:39 2011 +0000

    hw/pxa2xx.c: Fix handling of RW bits in PMCR
    
    Fix an error in commit afd4a6522 which meant that writing a zero
    to the RW bits in the PMCR wouldn't actually clear them. (Error
    spotted by Andrzej Zaborowski.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index d38b922..e9a507e 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -117,6 +117,7 @@ static void pxa2xx_pm_write(void *opaque, target_phys_addr_t addr,
         /* Clear the write-one-to-clear bits... */
         s->pm_regs[addr >> 2] &= ~(value & 0x2a);
         /* ...and set the plain r/w bits */
+        s->pm_regs[addr >> 2] &= ~0x15;
         s->pm_regs[addr >> 2] |= value & 0x15;
         break;
 
commit e7852674d5013bffd0bb8e822a7521f76677a60b
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 9 21:09:23 2011 +0000

    hw/usb-net.c: Fix precedence bug when checking rndis_state
    
    "!X == 2" is always false (spotted by Coverity), so the checks
    for whether rndis is in the correct state would never fire.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/usb-net.c b/hw/usb-net.c
index a8b7c8d..f91fa32 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1268,8 +1268,9 @@ static ssize_t usbnet_receive(VLANClientState *nc, const uint8_t *buf, size_t si
 
     if (is_rndis(s)) {
         msg = (struct rndis_packet_msg_type *) s->in_buf;
-        if (!s->rndis_state == RNDIS_DATA_INITIALIZED)
+        if (s->rndis_state != RNDIS_DATA_INITIALIZED) {
             return -1;
+        }
         if (size + sizeof(struct rndis_packet_msg_type) > sizeof(s->in_buf))
             return -1;
 
@@ -1302,7 +1303,7 @@ 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) {
+    if (is_rndis(s) && s->rndis_state != RNDIS_DATA_INITIALIZED) {
         return 1;
     }
 
commit 88365e47dd19da8776252a94ed5fa0b7242ea9e9
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 13 12:00:55 2011 +0200

    memory: fix 'info mtree' segfaults
    
    'info mtree' accesses invalid memory in two cases, both due to incorrect
    (and unsafe) usage of QTAILQ_FOREACH_SAFE().
    
    Reported-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/memory.c b/memory.c
index c0c1d12..7c20a07 100644
--- a/memory.c
+++ b/memory.c
@@ -1401,7 +1401,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
                        alias_print_queue);
     }
 
-    QTAILQ_FOREACH_SAFE(next_ml, &submr_print_queue, queue, ml) {
+    QTAILQ_FOREACH_SAFE(ml, &submr_print_queue, queue, next_ml) {
         g_free(ml);
     }
 }
@@ -1425,7 +1425,7 @@ void mtree_info(fprintf_function mon_printf, void *f)
     }
 
     QTAILQ_FOREACH_SAFE(ml, &ml_head, queue, ml2) {
-        g_free(ml2);
+        g_free(ml);
     }
 
     if (address_space_io.root &&
commit 74d33d5ce4d70125fa7ff476145276a44372e9d5
Merge: 0abe905... ca71636...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Nov 11 17:26:37 2011 -0600

    Merge remote-tracking branch 'kwolf/block-stable' into staging

commit 0abe905d29f556128c5fb2ea8d93e982e94aaa67
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Thu Nov 10 15:38:42 2011 +0400

    vl.c: prohibit simultaneous use of -icount with kvm or xen
    
    With -icount, The vm_clock is updated with help from TCG (it counts
    instructions at 2^ICOUNT ns/instructions). With KVM, the instruction
    count is not available so KVM cannot provide this help.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index 16fa222..f5afed4 100644
--- a/vl.c
+++ b/vl.c
@@ -3231,6 +3231,11 @@ int main(int argc, char **argv, char **envp)
         fprintf(stderr, "could not initialize alarm timer\n");
         exit(1);
     }
+
+    if (icount_option && (kvm_enabled() || xen_enabled())) {
+        fprintf(stderr, "-icount is not allowed with kvm or xen\n");
+        exit(1);
+    }
     configure_icount(icount_option);
 
     if (net_init_clients() < 0) {
commit ee71c984342408a357a74f65915bf66484ba445a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Nov 11 13:30:15 2011 +0000

    hw/arm_timer.c: Fix bounds check for Integrator timer accesses
    
    There are only three counter/timers on the integrator board:
    correct the bounds check to avoid an array overrun. (Spotted
    by Coverity, see bug 887883).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 09a4b24..66db81d 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -269,7 +269,7 @@ static uint64_t icp_pit_read(void *opaque, target_phys_addr_t offset,
 
     /* ??? Don't know the PrimeCell ID for this device.  */
     n = offset >> 8;
-    if (n > 3) {
+    if (n > 2) {
         hw_error("sp804_read: Bad timer %d\n", n);
     }
 
@@ -283,7 +283,7 @@ static void icp_pit_write(void *opaque, target_phys_addr_t offset,
     int n;
 
     n = offset >> 8;
-    if (n > 3) {
+    if (n > 2) {
         hw_error("sp804_write: Bad timer %d\n", n);
     }
 
commit afd4a65225318ec7900871ed69a46ce992637ef2
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 9 20:46:35 2011 +0000

    hw/pxa2xx.c: Fix handling of R/WC bits in PMCR
    
    Fix a bug in handling the write-one-to-clear bits in the PMCR
    which meant that we would always clear the bit even if the
    value written was a zero. Spotted by Coverity (see bug 887883).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index bfc28a9..d38b922 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -114,7 +114,9 @@ static void pxa2xx_pm_write(void *opaque, target_phys_addr_t addr,
 
     switch (addr) {
     case PMCR:
-        s->pm_regs[addr >> 2] &= 0x15 & ~(value & 0x2a);
+        /* Clear the write-one-to-clear bits... */
+        s->pm_regs[addr >> 2] &= ~(value & 0x2a);
+        /* ...and set the plain r/w bits */
         s->pm_regs[addr >> 2] |= value & 0x15;
         break;
 
commit b78c2b3aad2b42084265c89f93a92733d68e9003
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 9 20:04:54 2011 +0000

    hw/pl061: Remove pointless comparison of array to null
    
    Remove a pointless comparison of an array to null. (There is
    no need to check whether s->out[i] is non-null as qemu_set_irq
    will do that for us.) Spotted by Coverity (see bug 887883).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pl061.c b/hw/pl061.c
index d13746c..cf5adbe 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -103,7 +103,7 @@ static void pl061_update(pl061_state *s)
     s->old_data = out;
     for (i = 0; i < 8; i++) {
         mask = 1 << i;
-        if ((changed & mask) && s->out) {
+        if (changed & mask) {
             DPRINTF("Set output %d = %d\n", i, (out & mask) != 0);
             qemu_set_irq(s->out[i], (out & mask) != 0);
         }
commit 35914dc7240f7d81e22219217cfa826c2c383e7b
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 9 19:34:28 2011 +0000

    hw/tc58128.c: Remove unnecessary check for g_malloc failure
    
    Remove a check for g_malloc failing: this never happens.
    Also use g_malloc rather than g_malloc0 as we immediately
    memset the entire region and so zero-initialising it is pointless.
    Spotted by Coverity (see bug 887883).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/tc58128.c b/hw/tc58128.c
index ee3ecad..4ce80b1 100644
--- a/hw/tc58128.c
+++ b/hw/tc58128.c
@@ -30,12 +30,8 @@ static void init_dev(tc58128_dev * dev, const char *filename)
     int ret, blocks;
 
     dev->state = WAIT;
-    dev->flash_contents = g_malloc0(FLASH_SIZE);
+    dev->flash_contents = g_malloc(FLASH_SIZE);
     memset(dev->flash_contents, 0xff, FLASH_SIZE);
-    if (!dev->flash_contents) {
-	fprintf(stderr, "could not alloc memory for flash\n");
-	exit(1);
-    }
     if (filename) {
 	/* Load flash image skipping the first block */
 	ret = load_image(filename, dev->flash_contents + 528 * 32);
commit 7dd47667b9b0b23807fc1a550644fc2427462f41
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 9 19:22:11 2011 +0000

    linux-user/elfload.c: Don't memset(NULL..) if malloc() failed
    
    If a malloc() in copy_elf_strings() failed we would call memset()
    before the "did malloc fail?" check. Fix this by moving to the
    glib alloc/free routines for this memory so we can use g_try_malloc0
    rather than having a separate memset(). Spotted by Coverity (see
    bug 887883).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index a413976..4635bb2 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1105,8 +1105,7 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
                 offset = p % TARGET_PAGE_SIZE;
                 pag = (char *)page[p/TARGET_PAGE_SIZE];
                 if (!pag) {
-                    pag = (char *)malloc(TARGET_PAGE_SIZE);
-                    memset(pag, 0, TARGET_PAGE_SIZE);
+                    pag = g_try_malloc0(TARGET_PAGE_SIZE);
                     page[p/TARGET_PAGE_SIZE] = pag;
                     if (!pag)
                         return 0;
@@ -1164,7 +1163,7 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
             info->rss++;
             /* FIXME - check return value of memcpy_to_target() for failure */
             memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
-            free(bprm->page[i]);
+            g_free(bprm->page[i]);
         }
         stack_base += TARGET_PAGE_SIZE;
     }
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index 62ebc7e..b47025f 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -178,7 +178,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
 
     /* Something went wrong, return the inode and free the argument pages*/
     for (i=0 ; i<MAX_ARG_PAGES ; i++) {
-        free(bprm->page[i]);
+        g_free(bprm->page[i]);
     }
     return(retval);
 }
commit 096685fc2a955ea17d5363ab452e301be2b43873
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 9 18:45:38 2011 +0000

    hw/omap_intc.c: Avoid crash on access to nonexistent banked registers
    
    Avoid a crash due to null pointer dereference if a guest attempts
    to access banked registers for a nonexistent bank. Spotted by
    Coverity (see bug 887883).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/omap_intc.c b/hw/omap_intc.c
index 0f7fd9d..45efa25 100644
--- a/hw/omap_intc.c
+++ b/hw/omap_intc.c
@@ -398,6 +398,9 @@ static uint64_t omap2_inth_read(void *opaque, target_phys_addr_t addr,
         if (bank_no < s->nbanks) {
             offset &= ~0x60;
             bank = &s->bank[bank_no];
+        } else {
+            OMAP_BAD_REG(addr);
+            return 0;
         }
     }
 
@@ -476,6 +479,9 @@ static void omap2_inth_write(void *opaque, target_phys_addr_t addr,
         if (bank_no < s->nbanks) {
             offset &= ~0x60;
             bank = &s->bank[bank_no];
+        } else {
+            OMAP_BAD_REG(addr);
+            return;
         }
     }
 
commit 1bbd1592c89a433e1a0501d582652d54d367ca53
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Nov 11 10:40:09 2011 +0100

    os-posix: Plug fd leak in qemu_create_pidfile()
    
    Spotted by Coverity.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/os-posix.c b/os-posix.c
index dbf3b24..dc4a6bb 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -372,13 +372,16 @@ int qemu_create_pidfile(const char *filename)
         return -1;
     }
     if (lockf(fd, F_TLOCK, 0) == -1) {
+        close(fd);
         return -1;
     }
     len = snprintf(buffer, sizeof(buffer), FMT_pid "\n", getpid());
     if (write(fd, buffer, len) != len) {
+        close(fd);
         return -1;
     }
 
+    close(fd);
     return 0;
 }
 
commit 095ed5be7b61b7168020f0b807c9789b277a3956
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Nov 11 10:40:08 2011 +0100

    posix-aio-compat: Plug memory leak on paio_init() error path
    
    Spotted by Coverity.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/posix-aio-compat.c b/posix-aio-compat.c
index d3c1174..0c0035c 100644
--- a/posix-aio-compat.c
+++ b/posix-aio-compat.c
@@ -667,6 +667,7 @@ int paio_init(void)
     s->first_aio = NULL;
     if (qemu_pipe(fds) == -1) {
         fprintf(stderr, "failed to create pipe\n");
+        g_free(s);
         return -1;
     }
 
commit 9d9474726274d0e1c420f055849a0e3058cad0e4
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Nov 11 10:40:07 2011 +0100

    qemu-sockets: Plug fd leak on unix_connect_opts() error path
    
    Spotted by Coverity.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-sockets.c b/qemu-sockets.c
index 183a9cb..61b2247 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -572,6 +572,7 @@ int unix_connect_opts(QemuOpts *opts)
     snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
     if (connect(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
         fprintf(stderr, "connect(unix:%s): %s\n", path, strerror(errno));
+        close(sock);
 	return -1;
     }
 
commit f2d3476eba17486c42357ba25c36bd26e627d1d7
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Nov 11 10:40:06 2011 +0100

    ui: Plug memory leaks on parse_keyboard_layout() error path
    
    Spotted by Coverity.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/keymaps.c b/ui/keymaps.c
index f54a114..f55a2aa 100644
--- a/ui/keymaps.c
+++ b/ui/keymaps.c
@@ -92,15 +92,17 @@ static kbd_layout_t *parse_keyboard_layout(const name2keysym_t *table,
     int len;
 
     filename = qemu_find_file(QEMU_FILE_TYPE_KEYMAP, language);
-
-    if (!k)
-	k = g_malloc0(sizeof(kbd_layout_t));
-    if (!(filename && (f = fopen(filename, "r")))) {
+    f = filename ? fopen(filename, "r") : NULL;
+    g_free(filename);
+    if (!f) {
 	fprintf(stderr,
 		"Could not read keymap file: '%s'\n", language);
 	return NULL;
     }
-    g_free(filename);
+
+    if (!k)
+	k = g_malloc0(sizeof(kbd_layout_t));
+
     for(;;) {
 	if (fgets(line, 1024, f) == NULL)
             break;
commit a4e26048526d8d5b181f9a0a7d4f82b8441c5dfd
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Nov 11 10:40:05 2011 +0100

    qemu-char: Plug memory leak on qemu_chr_open_pty() error path
    
    Spotted by Coverity.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index 9fd94d1..b562bf8 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -985,7 +985,7 @@ static int qemu_chr_open_pty(QemuOpts *opts, CharDriverState **_chr)
     CharDriverState *chr;
     PtyCharDriver *s;
     struct termios tty;
-    int slave_fd, len;
+    int master_fd, slave_fd, len;
 #if defined(__OpenBSD__) || defined(__DragonFly__)
     char pty_name[PATH_MAX];
 #define q_ptsname(x) pty_name
@@ -994,10 +994,7 @@ static int qemu_chr_open_pty(QemuOpts *opts, CharDriverState **_chr)
 #define q_ptsname(x) ptsname(x)
 #endif
 
-    chr = g_malloc0(sizeof(CharDriverState));
-    s = g_malloc0(sizeof(PtyCharDriver));
-
-    if (openpty(&s->fd, &slave_fd, pty_name, NULL, NULL) < 0) {
+    if (openpty(&master_fd, &slave_fd, pty_name, NULL, NULL) < 0) {
         return -errno;
     }
 
@@ -1007,17 +1004,21 @@ static int qemu_chr_open_pty(QemuOpts *opts, CharDriverState **_chr)
     tcsetattr(slave_fd, TCSAFLUSH, &tty);
     close(slave_fd);
 
-    len = strlen(q_ptsname(s->fd)) + 5;
+    chr = g_malloc0(sizeof(CharDriverState));
+
+    len = strlen(q_ptsname(master_fd)) + 5;
     chr->filename = g_malloc(len);
-    snprintf(chr->filename, len, "pty:%s", q_ptsname(s->fd));
-    qemu_opt_set(opts, "path", q_ptsname(s->fd));
-    fprintf(stderr, "char device redirected to %s\n", q_ptsname(s->fd));
+    snprintf(chr->filename, len, "pty:%s", q_ptsname(master_fd));
+    qemu_opt_set(opts, "path", q_ptsname(master_fd));
+    fprintf(stderr, "char device redirected to %s\n", q_ptsname(master_fd));
 
+    s = g_malloc0(sizeof(PtyCharDriver));
     chr->opaque = s;
     chr->chr_write = pty_chr_write;
     chr->chr_update_read_handler = pty_chr_update_read_handler;
     chr->chr_close = pty_chr_close;
 
+    s->fd = master_fd;
     s->timer = qemu_new_timer_ms(rt_clock, pty_chr_timer, chr);
 
     *_chr = chr;
commit 1299c63168e9f3d47b681b8c505d39f577ddd253
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Nov 9 21:29:01 2011 +0100

    migration: fix detached migration with fd
    
    Migration with fd uses s->mon to pass the fd.  But we only assign the
    s->mon for !detached migration.  Fix it.  Once there add a comment
    indicating that s->mon has two uses.
    
    Bug reported by:  Wen Congyang <wency at cn.fujitsu.com>
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    CC:  Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration.c b/migration.c
index 4b17566..41c3c24 100644
--- a/migration.c
+++ b/migration.c
@@ -155,7 +155,6 @@ MigrationInfo *qmp_query_migrate(Error **errp)
 
 static void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon)
 {
-    s->mon = mon;
     if (monitor_suspend(mon) == 0) {
         DPRINTF("suspending monitor\n");
     } else {
@@ -383,7 +382,12 @@ static MigrationState *migrate_init(Monitor *mon, int detach, int blk, int inc)
     s->bandwidth_limit = bandwidth_limit;
     s->blk = blk;
     s->shared = inc;
-    s->mon = NULL;
+
+    /* s->mon is used for two things:
+       - pass fd in fd migration
+       - suspend/resume monitor for not detached migration
+    */
+    s->mon = mon;
     s->bandwidth_limit = bandwidth_limit;
     s->state = MIG_STATE_SETUP;
 
@@ -435,6 +439,10 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
         return ret;
     }
 
+    if (detach) {
+        s->mon = NULL;
+    }
+
     notifier_list_notify(&migration_state_notifiers, s);
     return 0;
 }
commit f2338fb48a3bca830aa1d694a117fe90751c3978
Author: Pavel Borzenkov <pavel.borzenkov at gmail.com>
Date:   Fri Nov 11 00:26:59 2011 +0400

    configure: Do not use 'sed -i'
    
    'sed -i' is not defined in POSIX. It doesn't work on Mac OS X the way
    it's used in configure (without suffix argument). This patch implements
    Peter Maydell's idea of xattr.h detection.
    
    Cc: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Pavel Borzenkov <pavel.borzenkov at gmail.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index 8d85d23..6c77fbb 100755
--- a/configure
+++ b/configure
@@ -1963,13 +1963,17 @@ if test "$attr" != "no" ; then
   cat > $TMPC <<EOF
 #include <stdio.h>
 #include <sys/types.h>
+#ifdef CONFIG_LIBATTR
+#include <attr/xattr.h>
+#else
 #include <sys/xattr.h>
+#endif
 int main(void) { getxattr(NULL, NULL, NULL, 0); setxattr(NULL, NULL, NULL, 0, 0); return 0; }
 EOF
   if compile_prog "" "" ; then
     attr=yes
   # Older distros have <attr/xattr.h>, and need -lattr:
-  elif sed -i s,sys/xattr,attr/xattr, $TMPC && compile_prog "" "-lattr" ; then
+  elif compile_prog "-DCONFIG_LIBATTR" "-lattr" ; then
     attr=yes
     LIBS="-lattr $LIBS"
     libattr=yes
commit ee2b39946312952f5aa99cf9b7bab238cd5b6329
Author: Sebastian Bauer <mail at sebastianbauer.info>
Date:   Wed Aug 10 01:41:48 2011 +0000

    PPC: Fix for the gdb single step problem on an rfi instruction
    
    When using gdb to single step a ppc interrupt routine, the execution
    flow passes the rfi instruction without actually returning from the
    interrupt.
    
    The patch fixes this by avoiding to update the nip when the debug
    exception is raised and a previous POWERPC_EXCP_SYNC was set.
    
    The latter is the case only, if code for rfi or a related instruction
    was generated.
    
    Signed-off-by: Sebastian Bauer <mail at sebastianbauer.info>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 99e995c..66eae30 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -298,8 +298,10 @@ static inline void gen_debug_exception(DisasContext *ctx)
 {
     TCGv_i32 t0;
 
-    if (ctx->exception != POWERPC_EXCP_BRANCH)
+    if ((ctx->exception != POWERPC_EXCP_BRANCH) &&
+        (ctx->exception != POWERPC_EXCP_SYNC)) {
         gen_update_nip(ctx, ctx->nip);
+    }
     t0 = tcg_const_i32(EXCP_DEBUG);
     gen_helper_raise_exception(t0);
     tcg_temp_free_i32(t0);
commit 9df3b45dd4e6e5a856a08e5c7799a3434e9e5ccf
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Sun Oct 30 19:57:33 2011 +0000

    tcg-ppc64: Fix compile errors for userspace only builds with gcc 4.6
    
    tcg/ppc64/tcg-target.c has a couple of places where variables are set
    unconditionally, but otherwise used only for softmmu builds, not
    userspace only builds.  This causes compiler warnings (which are fatal
    by default) when compiling for a ppc64 host with gcc 4.6.  This patch
    fixes the problem by moving the code which defines and sets the
    variables into the CONFIG_SOFTMMU guarded regions.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 3d24cd4..41f1e85 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -616,18 +616,19 @@ static void tcg_out_tlb_read (TCGContext *s, int r0, int r1, int r2,
 
 static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
 {
-    int addr_reg, data_reg, r0, r1, rbase, mem_index, s_bits, bswap;
+    int addr_reg, data_reg, r0, r1, rbase, bswap;
 #ifdef CONFIG_SOFTMMU
-    int r2;
+    int r2, mem_index, s_bits;
     void *label1_ptr, *label2_ptr;
 #endif
 
     data_reg = *args++;
     addr_reg = *args++;
+
+#ifdef CONFIG_SOFTMMU
     mem_index = *args;
     s_bits = opc & 3;
 
-#ifdef CONFIG_SOFTMMU
     r0 = 3;
     r1 = 4;
     r2 = 0;
@@ -763,17 +764,18 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
 
 static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
 {
-    int addr_reg, r0, r1, rbase, data_reg, mem_index, bswap;
+    int addr_reg, r0, r1, rbase, data_reg, bswap;
 #ifdef CONFIG_SOFTMMU
-    int r2;
+    int r2, mem_index;
     void *label1_ptr, *label2_ptr;
 #endif
 
     data_reg = *args++;
     addr_reg = *args++;
-    mem_index = *args;
 
 #ifdef CONFIG_SOFTMMU
+    mem_index = *args;
+
     r0 = 3;
     r1 = 4;
     r2 = 0;
commit d43b45e220ae82081e389ae113f6f03d9294fdcf
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Nov 1 16:49:05 2011 +0000

    pseries: Fix initialization of sPAPREnvironment structure
    
    Since we added PCI support to the pseries machine, we include a qlist of
    PCI host bridges in the sPAPREnvironment structure.  However this list
    was never properly initialized it.  Somehow we got away with this until
    some other recent change broke it, and we now segfault immediately on
    startup.
    
    This patch adds the required QLIST_INIT(), and while we're at it makes sure
    we initialize the rest of the sPAPREnvironment structure to 0, to avoid
    future nasty surprises.
    
    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 bdaa938..40cfc9b 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -407,7 +407,9 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     long pteg_shift = 17;
     char *filename;
 
-    spapr = g_malloc(sizeof(*spapr));
+    spapr = g_malloc0(sizeof(*spapr));
+    QLIST_INIT(&spapr->phbs);
+
     cpu_ppc_hypercall = emulate_spapr_hypercall;
 
     /* Allocate RMA if necessary */
commit d423675c94442dadb4bd751dac876385960ce109
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Thu Nov 10 16:35:32 2011 +0100

    vl.c: Fail gracefully if no machine is found
    
    machine defaults to find_default_machine(),
    then gets overridden via -M and machine_parse().
    
    If no -M is specified and find_default_machine() returns NULL
    (when no machine compiled in), exit with an error.
    
    Avoids a segfault when setting machine->max_cpus.
    
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index f169aac..16fa222 100644
--- a/vl.c
+++ b/vl.c
@@ -3089,6 +3089,11 @@ int main(int argc, char **argv, char **envp)
         data_dir = CONFIG_QEMU_DATADIR;
     }
 
+    if (machine == NULL) {
+        fprintf(stderr, "No machine found.\n");
+        exit(1);
+    }
+
     /*
      * Default to max_cpus = smp_cpus, in case the user doesn't
      * specify a max_cpus value.
commit ca716364f045da710ddef7fc6420bd6760e45b56
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Nov 10 18:13:59 2011 +0100

    block: Make cache=unsafe flush to the OS
    
    cache=unsafe completely ignored bdrv_flush, because flushing the host disk
    costs a lot of performance. However, this means that qcow2 images (and
    potentially any other format) can lose data even after the guest has issued a
    flush if the qemu process crashes/is killed. In case of a host crash, data loss
    is certainly expected with cache=unsafe, but if just the qemu process dies this
    is a bit too unsafe.
    
    Now that we have two separate flush functions, we can choose to flush
    everythign to the OS, but don't enforce that it's physically written to the
    disk.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index b1a4629..86910b0 100644
--- a/block.c
+++ b/block.c
@@ -2791,12 +2791,11 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
 {
     int ret;
 
-    if (bs->open_flags & BDRV_O_NO_FLUSH) {
-        return 0;
-    } else if (!bs->drv) {
+    if (!bs->drv) {
         return 0;
     }
 
+    /* Write back cached data to the OS even with cache=unsafe */
     if (bs->drv->bdrv_co_flush_to_os) {
         ret = bs->drv->bdrv_co_flush_to_os(bs);
         if (ret < 0) {
@@ -2804,6 +2803,11 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
         }
     }
 
+    /* But don't actually force it to the disk with cache=unsafe */
+    if (bs->open_flags & BDRV_O_NO_FLUSH) {
+        return 0;
+    }
+
     if (bs->drv->bdrv_co_flush_to_disk) {
         return bs->drv->bdrv_co_flush_to_disk(bs);
     } else if (bs->drv->bdrv_aio_flush) {
commit eb489bb1eceea0d710cd5f5122d37213300ceef6
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Nov 10 18:10:11 2011 +0100

    block: Introduce bdrv_co_flush_to_os
    
    qcow2 has a writeback metadata cache, so flushing a qcow2 image actually
    consists of writing back that cache to the protocol and only then flushes the
    protocol in order to get everything stable on disk.
    
    This introduces a separate bdrv_co_flush_to_os to reflect the split.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 6521eaa..b1a4629 100644
--- a/block.c
+++ b/block.c
@@ -2789,11 +2789,22 @@ static void coroutine_fn bdrv_flush_co_entry(void *opaque)
 
 int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
 {
+    int ret;
+
     if (bs->open_flags & BDRV_O_NO_FLUSH) {
         return 0;
     } else if (!bs->drv) {
         return 0;
-    } else if (bs->drv->bdrv_co_flush_to_disk) {
+    }
+
+    if (bs->drv->bdrv_co_flush_to_os) {
+        ret = bs->drv->bdrv_co_flush_to_os(bs);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    if (bs->drv->bdrv_co_flush_to_disk) {
         return bs->drv->bdrv_co_flush_to_disk(bs);
     } else if (bs->drv->bdrv_aio_flush) {
         BlockDriverAIOCB *acb;
diff --git a/block/qcow2.c b/block/qcow2.c
index f7f73fe..5c784ee 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1105,7 +1105,7 @@ fail:
     return ret;
 }
 
-static int qcow2_co_flush(BlockDriverState *bs)
+static int qcow2_co_flush_to_os(BlockDriverState *bs)
 {
     BDRVQcowState *s = bs->opaque;
     int ret;
@@ -1124,6 +1124,11 @@ static int qcow2_co_flush(BlockDriverState *bs)
     }
     qemu_co_mutex_unlock(&s->lock);
 
+    return 0;
+}
+
+static int qcow2_co_flush_to_disk(BlockDriverState *bs)
+{
     return bdrv_co_flush(bs->file);
 }
 
@@ -1245,7 +1250,8 @@ static BlockDriver bdrv_qcow2 = {
 
     .bdrv_co_readv          = qcow2_co_readv,
     .bdrv_co_writev         = qcow2_co_writev,
-    .bdrv_co_flush_to_disk  = qcow2_co_flush,
+    .bdrv_co_flush_to_os    = qcow2_co_flush_to_os,
+    .bdrv_co_flush_to_disk  = qcow2_co_flush_to_disk,
 
     .bdrv_co_discard        = qcow2_co_discard,
     .bdrv_truncate          = qcow2_truncate,
diff --git a/block_int.h b/block_int.h
index 5aadc1f..1ec4921 100644
--- a/block_int.h
+++ b/block_int.h
@@ -93,6 +93,13 @@ struct BlockDriver {
      */
     int coroutine_fn (*bdrv_co_flush_to_disk)(BlockDriverState *bs);
 
+    /*
+     * Flushes all internal caches to the OS. The data may still sit in a
+     * writeback cache of the host OS, but it will survive a crash of the qemu
+     * process.
+     */
+    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,
commit c68b89acd636ff545bc7cb92739c41999291ce3c
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Nov 10 17:25:44 2011 +0100

    block: Rename bdrv_co_flush to bdrv_co_flush_to_disk
    
    There are two different types of flush that you can do: Flushing one level up
    to the OS (i.e. writing data to the host page cache) or flushing it all the way
    down to the disk. The existing functions flush to the disk, reflect this in the
    function name.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 5c30c9d..6521eaa 100644
--- a/block.c
+++ b/block.c
@@ -2793,8 +2793,8 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
         return 0;
     } else if (!bs->drv) {
         return 0;
-    } else if (bs->drv->bdrv_co_flush) {
-        return bs->drv->bdrv_co_flush(bs);
+    } else if (bs->drv->bdrv_co_flush_to_disk) {
+        return bs->drv->bdrv_co_flush_to_disk(bs);
     } else if (bs->drv->bdrv_aio_flush) {
         BlockDriverAIOCB *acb;
         CoroutineIOCompletion co = {
diff --git a/block/cow.c b/block/cow.c
index 707c0aa..089d395 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -326,16 +326,18 @@ static QEMUOptionParameter cow_create_options[] = {
 };
 
 static BlockDriver bdrv_cow = {
-    .format_name	= "cow",
-    .instance_size	= sizeof(BDRVCowState),
-    .bdrv_probe		= cow_probe,
-    .bdrv_open		= cow_open,
-    .bdrv_read          = cow_co_read,
-    .bdrv_write         = cow_co_write,
-    .bdrv_close		= cow_close,
-    .bdrv_create	= cow_create,
-    .bdrv_co_flush      = cow_co_flush,
-    .bdrv_is_allocated	= cow_is_allocated,
+    .format_name    = "cow",
+    .instance_size  = sizeof(BDRVCowState),
+
+    .bdrv_probe     = cow_probe,
+    .bdrv_open      = cow_open,
+    .bdrv_close     = cow_close,
+    .bdrv_create    = cow_create,
+
+    .bdrv_read              = cow_co_read,
+    .bdrv_write             = cow_co_write,
+    .bdrv_co_flush_to_disk  = cow_co_flush,
+    .bdrv_is_allocated      = cow_is_allocated,
 
     .create_options = cow_create_options,
 };
diff --git a/block/qcow.c b/block/qcow.c
index 35e21eb..adecee0 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -828,14 +828,16 @@ static BlockDriver bdrv_qcow = {
     .bdrv_open		= qcow_open,
     .bdrv_close		= qcow_close,
     .bdrv_create	= qcow_create,
-    .bdrv_is_allocated	= qcow_is_allocated,
-    .bdrv_set_key	= qcow_set_key,
-    .bdrv_make_empty	= qcow_make_empty,
-    .bdrv_co_readv      = qcow_co_readv,
-    .bdrv_co_writev     = qcow_co_writev,
-    .bdrv_co_flush      = qcow_co_flush,
-    .bdrv_write_compressed = qcow_write_compressed,
-    .bdrv_get_info	= qcow_get_info,
+
+    .bdrv_co_readv          = qcow_co_readv,
+    .bdrv_co_writev         = qcow_co_writev,
+    .bdrv_co_flush_to_disk  = qcow_co_flush,
+    .bdrv_is_allocated      = qcow_is_allocated,
+
+    .bdrv_set_key           = qcow_set_key,
+    .bdrv_make_empty        = qcow_make_empty,
+    .bdrv_write_compressed  = qcow_write_compressed,
+    .bdrv_get_info          = qcow_get_info,
 
     .create_options = qcow_create_options,
 };
diff --git a/block/qcow2.c b/block/qcow2.c
index ef057d3..f7f73fe 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1243,9 +1243,9 @@ static BlockDriver bdrv_qcow2 = {
     .bdrv_set_key       = qcow2_set_key,
     .bdrv_make_empty    = qcow2_make_empty,
 
-    .bdrv_co_readv      = qcow2_co_readv,
-    .bdrv_co_writev     = qcow2_co_writev,
-    .bdrv_co_flush      = qcow2_co_flush,
+    .bdrv_co_readv          = qcow2_co_readv,
+    .bdrv_co_writev         = qcow2_co_writev,
+    .bdrv_co_flush_to_disk  = qcow2_co_flush,
 
     .bdrv_co_discard        = qcow2_co_discard,
     .bdrv_truncate          = qcow2_truncate,
diff --git a/block/raw-win32.c b/block/raw-win32.c
index f5f73bc..e4b0b75 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -281,9 +281,11 @@ static BlockDriver bdrv_file = {
     .bdrv_file_open	= raw_open,
     .bdrv_close		= raw_close,
     .bdrv_create	= raw_create,
-    .bdrv_co_flush      = raw_flush,
-    .bdrv_read		= raw_read,
-    .bdrv_write		= raw_write,
+
+    .bdrv_read              = raw_read,
+    .bdrv_write             = raw_write,
+    .bdrv_co_flush_to_disk  = raw_flush,
+
     .bdrv_truncate	= raw_truncate,
     .bdrv_getlength	= raw_getlength,
     .bdrv_get_allocated_file_size
@@ -409,11 +411,12 @@ static BlockDriver bdrv_host_device = {
     .bdrv_probe_device	= hdev_probe_device,
     .bdrv_file_open	= hdev_open,
     .bdrv_close		= raw_close,
-    .bdrv_co_flush      = raw_flush,
     .bdrv_has_zero_init = hdev_has_zero_init,
 
-    .bdrv_read		= raw_read,
-    .bdrv_write	        = raw_write,
+    .bdrv_read              = raw_read,
+    .bdrv_write             = raw_write,
+    .bdrv_co_flush_to_disk  = raw_flush,
+
     .bdrv_getlength	= raw_getlength,
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
diff --git a/block/raw.c b/block/raw.c
index 33cc471..6098070 100644
--- a/block/raw.c
+++ b/block/raw.c
@@ -111,10 +111,10 @@ static BlockDriver bdrv_raw = {
     .bdrv_open          = raw_open,
     .bdrv_close         = raw_close,
 
-    .bdrv_co_readv      = raw_co_readv,
-    .bdrv_co_writev     = raw_co_writev,
-    .bdrv_co_flush      = raw_co_flush,
-    .bdrv_co_discard    = raw_co_discard,
+    .bdrv_co_readv          = raw_co_readv,
+    .bdrv_co_writev         = raw_co_writev,
+    .bdrv_co_flush_to_disk  = raw_co_flush,
+    .bdrv_co_discard        = raw_co_discard,
 
     .bdrv_probe         = raw_probe,
     .bdrv_getlength     = raw_getlength,
diff --git a/block/rbd.c b/block/rbd.c
index c684e0c..9088c52 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -851,18 +851,18 @@ static BlockDriver bdrv_rbd = {
     .bdrv_file_open     = qemu_rbd_open,
     .bdrv_close         = qemu_rbd_close,
     .bdrv_create        = qemu_rbd_create,
-    .bdrv_co_flush      = qemu_rbd_co_flush,
     .bdrv_get_info      = qemu_rbd_getinfo,
     .create_options     = qemu_rbd_create_options,
     .bdrv_getlength     = qemu_rbd_getlength,
     .bdrv_truncate      = qemu_rbd_truncate,
     .protocol_name      = "rbd",
 
-    .bdrv_aio_readv     = qemu_rbd_aio_readv,
-    .bdrv_aio_writev    = qemu_rbd_aio_writev,
+    .bdrv_aio_readv         = qemu_rbd_aio_readv,
+    .bdrv_aio_writev        = qemu_rbd_aio_writev,
+    .bdrv_co_flush_to_disk  = qemu_rbd_co_flush,
 
-    .bdrv_snapshot_create = qemu_rbd_snap_create,
-    .bdrv_snapshot_list = qemu_rbd_snap_list,
+    .bdrv_snapshot_create   = qemu_rbd_snap_create,
+    .bdrv_snapshot_list     = qemu_rbd_snap_list,
 };
 
 static void bdrv_rbd_init(void)
diff --git a/block/vdi.c b/block/vdi.c
index 523a640..684a4a8 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -980,7 +980,7 @@ static BlockDriver bdrv_vdi = {
     .bdrv_open = vdi_open,
     .bdrv_close = vdi_close,
     .bdrv_create = vdi_create,
-    .bdrv_co_flush = vdi_co_flush,
+    .bdrv_co_flush_to_disk = vdi_co_flush,
     .bdrv_is_allocated = vdi_is_allocated,
     .bdrv_make_empty = vdi_make_empty,
 
diff --git a/block/vmdk.c b/block/vmdk.c
index 985006e..e53a2f0 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1581,8 +1581,8 @@ static BlockDriver bdrv_vmdk = {
     .bdrv_write     = vmdk_co_write,
     .bdrv_close     = vmdk_close,
     .bdrv_create    = vmdk_create,
-    .bdrv_co_flush  = vmdk_co_flush,
-    .bdrv_is_allocated  = vmdk_is_allocated,
+    .bdrv_co_flush_to_disk  = vmdk_co_flush,
+    .bdrv_is_allocated      = vmdk_is_allocated,
     .bdrv_get_allocated_file_size  = vmdk_get_allocated_file_size,
 
     .create_options = vmdk_create_options,
diff --git a/block/vpc.c b/block/vpc.c
index 54633b6..39a3247 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -665,14 +665,16 @@ static QEMUOptionParameter vpc_create_options[] = {
 static BlockDriver bdrv_vpc = {
     .format_name    = "vpc",
     .instance_size  = sizeof(BDRVVPCState),
+
     .bdrv_probe     = vpc_probe,
     .bdrv_open      = vpc_open,
-    .bdrv_read      = vpc_co_read,
-    .bdrv_write     = vpc_co_write,
-    .bdrv_co_flush  = vpc_co_flush,
     .bdrv_close     = vpc_close,
     .bdrv_create    = vpc_create,
 
+    .bdrv_read              = vpc_co_read,
+    .bdrv_write             = vpc_co_write,
+    .bdrv_co_flush_to_disk  = vpc_co_flush,
+
     .create_options = vpc_create_options,
 };
 
diff --git a/block_int.h b/block_int.h
index f4547f6..5aadc1f 100644
--- a/block_int.h
+++ b/block_int.h
@@ -84,10 +84,15 @@ struct BlockDriver {
         int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
     int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs,
         int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
-    int coroutine_fn (*bdrv_co_flush)(BlockDriverState *bs);
     int coroutine_fn (*bdrv_co_discard)(BlockDriverState *bs,
         int64_t sector_num, int nb_sectors);
 
+    /*
+     * Flushes all data that was already written to the OS all the way down to
+     * the disk (for example raw-posix calls fsync()).
+     */
+    int coroutine_fn (*bdrv_co_flush_to_disk)(BlockDriverState *bs);
+
     int (*bdrv_aio_multiwrite)(BlockDriverState *bs, BlockRequest *reqs,
         int num_reqs);
     int (*bdrv_merge_requests)(BlockDriverState *bs, BlockRequest* a,
commit 980bda8ba2322f665934913fbe6c4c202d61a9f9
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 9 21:59:50 2011 +0000

    hw/pc.c: Fix use-while-uninitialized of fd_type[]
    
    Fix a use-while-uninitialized of the fd_type[] array (introduced
    in commit 34d4260e1, noticed by Coverity). This is more theoretical
    than practical, since it's quite hard to get here with floppy==NULL
    (the qdev_try_create() of the isa-fdc device has to fail).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/pc.c b/hw/pc.c
index 3015671..33778fe 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -335,7 +335,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
                   ISADevice *s)
 {
     int val, nb, nb_heads, max_track, last_sect, i;
-    FDriveType fd_type[2];
+    FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
     BlockDriverState *fd[MAX_FD];
     static pc_cmos_init_late_arg arg;
 
@@ -385,8 +385,6 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
                 bdrv_get_floppy_geometry_hint(fd[i], &nb_heads, &max_track,
                                               &last_sect, FDRIVE_DRV_NONE,
                                               &fd_type[i]);
-            } else {
-                fd_type[i] = FDRIVE_DRV_NONE;
             }
         }
     }
commit 78439f6af1caa3e8bdafc9fc2d62aeefa53ed63a
Author: Charles Arnold <carnold at suse.com>
Date:   Wed Nov 9 09:32:25 2011 -0700

    block: Fix vpc initialization of the Dynamic Disk Header
    
    The Data Offset field in the Dynamic Disk Header is an 8 byte field.
    Although the specification (2006-10-11) gives an example of initializing
    only the first 4 bytes, images generated by Microsoft on Windows initialize
    all 8 bytes.
    
    Failure to initialize all 8 bytes results in errors from utilities
    like Citrix's vhd-util which checks specifically for the proper Data
    Offset field initialization.
    
    Signed-off-by: Charles Arnold <carnold at suse.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vpc.c b/block/vpc.c
index 79be7d0..54633b6 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -617,7 +617,11 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
 
     memcpy(dyndisk_header->magic, "cxsparse", 8);
 
-    dyndisk_header->data_offset = be64_to_cpu(0xFFFFFFFF);
+    /*
+     * Note: The spec is actually wrong here for data_offset, it says
+     * 0xFFFFFFFF, but MS tools expect all 64 bits to be set.
+     */
+    dyndisk_header->data_offset = be64_to_cpu(0xFFFFFFFFFFFFFFFFULL);
     dyndisk_header->table_offset = be64_to_cpu(3 * 512);
     dyndisk_header->version = be32_to_cpu(0x00010000);
     dyndisk_header->block_size = be32_to_cpu(block_size);
commit 802ddc375acabf06c0cb5a2716ca3573bc9ca89f
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Nov 4 15:51:24 2011 +0100

    qemu-nbd: open the block device after starting the client thread
    
    This is cleaner, because we do not need to close the block device when
    there is an error opening /dev/nbdX.  It was done this way only to
    print errors before daemonizing.
    
    At the same time, use atexit to ensure that the block device is closed
    whenever we exit.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-nbd.c b/qemu-nbd.c
index 6f84ad0..291cba2 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -460,22 +460,6 @@ int main(int argc, char **argv)
         }
     }
 
-    bdrv_init();
-
-    bs = bdrv_new("hda");
-
-    srcpath = argv[optind];
-    if ((ret = bdrv_open(bs, srcpath, flags, NULL)) < 0) {
-        errno = -ret;
-        err(EXIT_FAILURE, "Failed to bdrv_open '%s'", srcpath);
-    }
-
-    fd_size = bs->total_sectors * 512;
-
-    if (partition != -1 &&
-        find_partition(bs, partition, &dev_offset, &fd_size))
-        err(EXIT_FAILURE, "Could not find partition %d", partition);
-
     if (device) {
         /* Open before spawning new threads.  In the future, we may
          * drop privileges after opening.
@@ -491,6 +475,23 @@ int main(int argc, char **argv)
         }
     }
 
+    bdrv_init();
+    atexit(bdrv_close_all);
+
+    bs = bdrv_new("hda");
+    srcpath = argv[optind];
+    if ((ret = bdrv_open(bs, srcpath, flags, NULL)) < 0) {
+        errno = -ret;
+        err(EXIT_FAILURE, "Failed to bdrv_open '%s'", argv[optind]);
+    }
+
+    fd_size = bs->total_sectors * 512;
+
+    if (partition != -1 &&
+        find_partition(bs, partition, &dev_offset, &fd_size)) {
+        err(EXIT_FAILURE, "Could not find partition %d", partition);
+    }
+
     sharing_fds = g_malloc((shared + 1) * sizeof(int));
 
     if (sockpath) {
@@ -568,7 +569,6 @@ int main(int argc, char **argv)
     qemu_vfree(data);
 
     close(sharing_fds[0]);
-    bdrv_close(bs);
     g_free(sharing_fds);
     if (sockpath) {
         unlink(sockpath);
commit f1ef5555c24914f8ad4051a20571a5c62022d928
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Nov 4 15:51:23 2011 +0100

    qemu-nbd: fix socket creation race
    
    Now that the client and server are in the same process, there is
    no need to race on the creation of the socket.  We can open the
    listening socket before starting the client thread.
    
    This avoids that "qemu-nbd -v -c" prints this once before connecting
    successfully to the socket:
    
        connect(unix:/var/lock/qemu-nbd-nbd0): No such file or directory
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-nbd.c b/qemu-nbd.c
index b330d8d..6f84ad0 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -205,10 +205,7 @@ static void *nbd_client_thread(void *arg)
     do {
         sock = unix_socket_outgoing(sockpath);
         if (sock == -1) {
-            if (errno != ENOENT && errno != ECONNREFUSED) {
-                goto out;
-            }
-            sleep(1);  /* wait parent */
+            goto out;
         }
     } while (sock == -1);
 
@@ -480,8 +477,6 @@ int main(int argc, char **argv)
         err(EXIT_FAILURE, "Could not find partition %d", partition);
 
     if (device) {
-        int ret;
-
         /* Open before spawning new threads.  In the future, we may
          * drop privileges after opening.
          */
@@ -494,15 +489,6 @@ int main(int argc, char **argv)
             sockpath = g_malloc(128);
             snprintf(sockpath, 128, SOCKET_PATH, basename(device));
         }
-
-        ret = pthread_create(&client_thread, NULL, nbd_client_thread, &fd);
-        if (ret != 0) {
-            errx(EXIT_FAILURE, "Failed to create client thread: %s",
-                 strerror(ret));
-        }
-    } else {
-        /* Shut up GCC warnings.  */
-        memset(&client_thread, 0, sizeof(client_thread));
     }
 
     sharing_fds = g_malloc((shared + 1) * sizeof(int));
@@ -515,6 +501,20 @@ int main(int argc, char **argv)
 
     if (sharing_fds[0] == -1)
         return 1;
+
+    if (device) {
+        int ret;
+
+        ret = pthread_create(&client_thread, NULL, nbd_client_thread, &fd);
+        if (ret != 0) {
+            errx(EXIT_FAILURE, "Failed to create client thread: %s",
+                 strerror(ret));
+        }
+    } else {
+        /* Shut up GCC warnings.  */
+        memset(&client_thread, 0, sizeof(client_thread));
+    }
+
     max_fd = sharing_fds[0];
     nb_fds++;
 
commit c1f8fdc3620781c87a0bc519edb691af975c6356
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Nov 4 15:51:22 2011 +0100

    qemu-nbd: print error messages from the daemon through a pipe
    
    In order to get nice error messages, keep the qemu-nbd process running
    until before issuing NBD_DO_IT and connected to the daemon with a pipe.
    This lets the qemu-nbd process relay error messages from the daemon and
    exit with a nonzero status if appropriate.
    
    Suggested-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-nbd.c b/qemu-nbd.c
index ffc2a8a..b330d8d 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -226,8 +226,13 @@ static void *nbd_client_thread(void *arg)
     /* update partition table */
     pthread_create(&show_parts_thread, NULL, show_parts, NULL);
 
-    fprintf(stderr, "NBD device %s is now connected to %s\n",
-            device, srcpath);
+    if (verbose) {
+        fprintf(stderr, "NBD device %s is now connected to %s\n",
+                device, srcpath);
+    } else {
+        /* Close stderr so that the qemu-nbd process exits.  */
+        dup2(STDOUT_FILENO, STDERR_FILENO);
+    }
 
     ret = nbd_client(fd);
     if (ret) {
@@ -406,6 +411,58 @@ int main(int argc, char **argv)
 	return 0;
     }
 
+    if (device && !verbose) {
+        int stderr_fd[2];
+        pid_t pid;
+        int ret;
+
+        if (qemu_pipe(stderr_fd) == -1) {
+            err(EXIT_FAILURE, "Error setting up communication pipe");
+        }
+
+        /* Now daemonize, but keep a communication channel open to
+         * print errors and exit with the proper status code.
+         */
+        pid = fork();
+        if (pid == 0) {
+            close(stderr_fd[0]);
+            ret = qemu_daemon(0, 0);
+
+            /* Temporarily redirect stderr to the parent's pipe...  */
+            dup2(stderr_fd[1], STDERR_FILENO);
+            if (ret == -1) {
+                err(EXIT_FAILURE, "Failed to daemonize");
+            }
+
+            /* ... close the descriptor we inherited and go on.  */
+            close(stderr_fd[1]);
+        } else {
+            bool errors = false;
+            char *buf;
+
+            /* In the parent.  Print error messages from the child until
+             * it closes the pipe.
+             */
+            close(stderr_fd[1]);
+            buf = g_malloc(1024);
+            while ((ret = read(stderr_fd[0], buf, 1024)) > 0) {
+                errors = true;
+                ret = qemu_write_full(STDERR_FILENO, buf, ret);
+                if (ret == -1) {
+                    exit(EXIT_FAILURE);
+                }
+            }
+            if (ret == -1) {
+                err(EXIT_FAILURE, "Cannot read from daemon");
+            }
+
+            /* Usually the daemon should not print any message.
+             * Exit with zero status in that case.
+             */
+            exit(errors);
+        }
+    }
+
     bdrv_init();
 
     bs = bdrv_new("hda");
@@ -433,13 +490,6 @@ int main(int argc, char **argv)
             err(EXIT_FAILURE, "Failed to open %s", device);
         }
 
-        if (!verbose) {
-            /* detach client and server */
-            if (qemu_daemon(0, 0) == -1) {
-                err(EXIT_FAILURE, "Failed to daemonize");
-            }
-        }
-
         if (sockpath == NULL) {
             sockpath = g_malloc(128);
             snprintf(sockpath, 128, SOCKET_PATH, basename(device));
commit a517e88baa9bef2b5c54a11d62b2b2ab2a5c4ab7
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Nov 4 15:51:21 2011 +0100

    qemu-nbd: move client to a thread
    
    This avoids that qemu-nbd uses both forking and threads, which do
    not behave well together.
    
    qemu-nbd is already Unix only, and there is no qemu_thread_join,
    so for now use pthreads.
    
    Since the parent and child no longer have separate file descriptors,
    we can open the NBD device before daemonizing, instead of checking
    with access(2) and restricting the open to the client only.
    
    Reported-by: Pierre Riteau <pierre.riteau at irisa.fr>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-nbd.c b/qemu-nbd.c
index 20b69c1..ffc2a8a 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -31,6 +31,7 @@
 #include <arpa/inet.h>
 #include <signal.h>
 #include <libgen.h>
+#include <pthread.h>
 
 #define SOCKET_PATH    "/var/lock/qemu-nbd-%s"
 
@@ -38,6 +39,9 @@
 
 static int sigterm_wfd;
 static int verbose;
+static char *device;
+static char *srcpath;
+static char *sockpath;
 
 static void usage(const char *name)
 {
@@ -172,21 +176,70 @@ static void termsig_handler(int signum)
     }
 }
 
-static void show_parts(const char *device)
+static void *show_parts(void *arg)
 {
-    if (fork() == 0) {
-        int nbd;
+    int nbd;
+
+    /* linux just needs an open() to trigger
+     * the partition table update
+     * but remember to load the module with max_part != 0 :
+     *     modprobe nbd max_part=63
+     */
+    nbd = open(device, O_RDWR);
+    if (nbd != -1) {
+        close(nbd);
+    }
+    return NULL;
+}
 
-        /* linux just needs an open() to trigger
-         * the partition table update
-         * but remember to load the module with max_part != 0 :
-         *     modprobe nbd max_part=63
-         */
-        nbd = open(device, O_RDWR);
-        if (nbd != -1)
-              close(nbd);
-        exit(0);
+static void *nbd_client_thread(void *arg)
+{
+    int fd = *(int *)arg;
+    off_t size;
+    size_t blocksize;
+    uint32_t nbdflags;
+    int sock;
+    int ret;
+    pthread_t show_parts_thread;
+
+    do {
+        sock = unix_socket_outgoing(sockpath);
+        if (sock == -1) {
+            if (errno != ENOENT && errno != ECONNREFUSED) {
+                goto out;
+            }
+            sleep(1);  /* wait parent */
+        }
+    } while (sock == -1);
+
+    ret = nbd_receive_negotiate(sock, NULL, &nbdflags,
+                                &size, &blocksize);
+    if (ret == -1) {
+        goto out;
+    }
+
+    ret = nbd_init(fd, sock, nbdflags, size, blocksize);
+    if (ret == -1) {
+        goto out;
+    }
+
+    /* update partition table */
+    pthread_create(&show_parts_thread, NULL, show_parts, NULL);
+
+    fprintf(stderr, "NBD device %s is now connected to %s\n",
+            device, srcpath);
+
+    ret = nbd_client(fd);
+    if (ret) {
+        goto out;
     }
+    close(fd);
+    kill(getpid(), SIGTERM);
+    return (void *) EXIT_SUCCESS;
+
+out:
+    kill(getpid(), SIGTERM);
+    return (void *) EXIT_FAILURE;
 }
 
 int main(int argc, char **argv)
@@ -201,8 +254,6 @@ int main(int argc, char **argv)
     struct sockaddr_in addr;
     socklen_t addr_len = sizeof(addr);
     off_t fd_size;
-    char *device = NULL;
-    char *sockpath = NULL;
     const char *sopt = "hVb:o:p:rsnP:c:dvk:e:t";
     struct option lopt[] = {
         { "help", 0, NULL, 'h' },
@@ -238,8 +289,11 @@ int main(int argc, char **argv)
     int nb_fds = 0;
     int max_fd;
     int persistent = 0;
+    pthread_t client_thread;
 
-    /* Set up a SIGTERM handler so that we exit with a nice status code.  */
+    /* The client thread uses SIGTERM to interrupt the server.  A signal
+     * handler ensures that "qemu-nbd -v -c" exits with a nice status code.
+     */
     struct sigaction sa_sigterm;
     int sigterm_fd[2];
     if (qemu_pipe(sigterm_fd) == -1) {
@@ -356,9 +410,10 @@ int main(int argc, char **argv)
 
     bs = bdrv_new("hda");
 
-    if ((ret = bdrv_open(bs, argv[optind], flags, NULL)) < 0) {
+    srcpath = argv[optind];
+    if ((ret = bdrv_open(bs, srcpath, flags, NULL)) < 0) {
         errno = -ret;
-        err(EXIT_FAILURE, "Failed to bdrv_open '%s'", argv[optind]);
+        err(EXIT_FAILURE, "Failed to bdrv_open '%s'", srcpath);
     }
 
     fd_size = bs->total_sectors * 512;
@@ -368,12 +423,14 @@ int main(int argc, char **argv)
         err(EXIT_FAILURE, "Could not find partition %d", partition);
 
     if (device) {
-        pid_t pid;
-        int sock;
+        int ret;
 
-        /* want to fail before daemonizing */
-        if (access(device, R_OK|W_OK) == -1) {
-            err(EXIT_FAILURE, "Could not access '%s'", device);
+        /* Open before spawning new threads.  In the future, we may
+         * drop privileges after opening.
+         */
+        fd = open(device, O_RDWR);
+        if (fd == -1) {
+            err(EXIT_FAILURE, "Failed to open %s", device);
         }
 
         if (!verbose) {
@@ -388,64 +445,14 @@ int main(int argc, char **argv)
             snprintf(sockpath, 128, SOCKET_PATH, basename(device));
         }
 
-        pid = fork();
-        if (pid < 0)
-            return 1;
-        if (pid != 0) {
-            off_t size;
-            size_t blocksize;
-
-            ret = 0;
-            bdrv_close(bs);
-
-            do {
-                sock = unix_socket_outgoing(sockpath);
-                if (sock == -1) {
-                    if (errno != ENOENT && errno != ECONNREFUSED) {
-                        ret = 1;
-                        goto out;
-                    }
-                    sleep(1);	/* wait children */
-                }
-            } while (sock == -1);
-
-            fd = open(device, O_RDWR);
-            if (fd == -1) {
-                ret = 1;
-                goto out;
-            }
-
-            ret = nbd_receive_negotiate(sock, NULL, &nbdflags,
-                                        &size, &blocksize);
-            if (ret == -1) {
-                ret = 1;
-                goto out;
-            }
-
-            ret = nbd_init(fd, sock, nbdflags, size, blocksize);
-            if (ret == -1) {
-                ret = 1;
-                goto out;
-            }
-
-            printf("NBD device %s is now connected to file %s\n",
-                    device, argv[optind]);
-
-	    /* update partition table */
-
-            show_parts(device);
-
-            ret = nbd_client(fd);
-            if (ret) {
-                ret = 1;
-            }
-            close(fd);
- out:
-            kill(pid, SIGTERM);
-
-            return ret;
+        ret = pthread_create(&client_thread, NULL, nbd_client_thread, &fd);
+        if (ret != 0) {
+            errx(EXIT_FAILURE, "Failed to create client thread: %s",
+                 strerror(ret));
         }
-        /* children */
+    } else {
+        /* Shut up GCC warnings.  */
+        memset(&client_thread, 0, sizeof(client_thread));
     }
 
     sharing_fds = g_malloc((shared + 1) * sizeof(int));
@@ -517,5 +524,11 @@ int main(int argc, char **argv)
         unlink(sockpath);
     }
 
-    return 0;
+    if (device) {
+        void *ret;
+        pthread_join(client_thread, &ret);
+        exit(ret != NULL);
+    } else {
+        exit(EXIT_SUCCESS);
+    }
 }
commit b32f6c28d5c753a8c667453f6300a2650bc52a47
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Nov 4 15:51:20 2011 +0100

    qemu-nbd: rename socket variable
    
    It will be moved to a global variable by the next patch, and it
    would conflict with the socket function.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-nbd.c b/qemu-nbd.c
index d997bb0..20b69c1 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -202,8 +202,7 @@ int main(int argc, char **argv)
     socklen_t addr_len = sizeof(addr);
     off_t fd_size;
     char *device = NULL;
-    char *socket = NULL;
-    char sockpath[128];
+    char *sockpath = NULL;
     const char *sopt = "hVb:o:p:rsnP:c:dvk:e:t";
     struct option lopt[] = {
         { "help", 0, NULL, 'h' },
@@ -294,8 +293,8 @@ int main(int argc, char **argv)
                 errx(EXIT_FAILURE, "Invalid partition %d", partition);
             break;
         case 'k':
-            socket = optarg;
-            if (socket[0] != '/')
+            sockpath = optarg;
+            if (sockpath[0] != '/')
                 errx(EXIT_FAILURE, "socket path must be absolute\n");
             break;
         case 'd':
@@ -384,10 +383,9 @@ int main(int argc, char **argv)
             }
         }
 
-        if (socket == NULL) {
-            snprintf(sockpath, sizeof(sockpath), SOCKET_PATH,
-                     basename(device));
-            socket = sockpath;
+        if (sockpath == NULL) {
+            sockpath = g_malloc(128);
+            snprintf(sockpath, 128, SOCKET_PATH, basename(device));
         }
 
         pid = fork();
@@ -401,7 +399,7 @@ int main(int argc, char **argv)
             bdrv_close(bs);
 
             do {
-                sock = unix_socket_outgoing(socket);
+                sock = unix_socket_outgoing(sockpath);
                 if (sock == -1) {
                     if (errno != ENOENT && errno != ECONNREFUSED) {
                         ret = 1;
@@ -452,8 +450,8 @@ int main(int argc, char **argv)
 
     sharing_fds = g_malloc((shared + 1) * sizeof(int));
 
-    if (socket) {
-        sharing_fds[0] = unix_socket_incoming(socket);
+    if (sockpath) {
+        sharing_fds[0] = unix_socket_incoming(sockpath);
     } else {
         sharing_fds[0] = tcp_socket_incoming(bindto, port);
     }
@@ -515,8 +513,9 @@ int main(int argc, char **argv)
     close(sharing_fds[0]);
     bdrv_close(bs);
     g_free(sharing_fds);
-    if (socket)
-        unlink(socket);
+    if (sockpath) {
+        unlink(sockpath);
+    }
 
     return 0;
 }
commit bb345110f091af3aac32038a45a8776fc9fb505d
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Nov 4 15:51:19 2011 +0100

    qemu-nbd: trap SIGTERM
    
    The client process right now uses SIGTERM to interrupt the server side.
    This does not affect the exit status of "qemu-nbd -v -c" because the
    server is a child process.  This will change when both sides will be
    in the same process, and anyway cleaning up things nicely upon SIGTERM
    is good practice.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-nbd.c b/qemu-nbd.c
index d8d3e15..d997bb0 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -36,6 +36,7 @@
 
 #define NBD_BUFFER_SIZE (1024*1024)
 
+static int sigterm_wfd;
 static int verbose;
 
 static void usage(const char *name)
@@ -163,6 +164,14 @@ static int find_partition(BlockDriverState *bs, int partition,
     return -1;
 }
 
+static void termsig_handler(int signum)
+{
+    static int sigterm_reported;
+    if (!sigterm_reported) {
+        sigterm_reported = (write(sigterm_wfd, "", 1) == 1);
+    }
+}
+
 static void show_parts(const char *device)
 {
     if (fork() == 0) {
@@ -231,6 +240,18 @@ int main(int argc, char **argv)
     int max_fd;
     int persistent = 0;
 
+    /* Set up a SIGTERM handler so that we exit with a nice status code.  */
+    struct sigaction sa_sigterm;
+    int sigterm_fd[2];
+    if (qemu_pipe(sigterm_fd) == -1) {
+        err(EXIT_FAILURE, "Error setting up communication pipe");
+    }
+
+    sigterm_wfd = sigterm_fd[1];
+    memset(&sa_sigterm, 0, sizeof(sa_sigterm));
+    sa_sigterm.sa_handler = termsig_handler;
+    sigaction(SIGTERM, &sa_sigterm, NULL);
+
     while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
         switch (ch) {
         case 's':
@@ -423,7 +444,6 @@ int main(int argc, char **argv)
             close(fd);
  out:
             kill(pid, SIGTERM);
-            unlink(socket);
 
             return ret;
         }
@@ -444,18 +464,22 @@ int main(int argc, char **argv)
     nb_fds++;
 
     data = qemu_blockalign(bs, NBD_BUFFER_SIZE);
-    if (data == NULL)
+    if (data == NULL) {
         errx(EXIT_FAILURE, "Cannot allocate data buffer");
+    }
 
     do {
-
         FD_ZERO(&fds);
+        FD_SET(sigterm_fd[0], &fds);
         for (i = 0; i < nb_fds; i++)
             FD_SET(sharing_fds[i], &fds);
 
-        ret = select(max_fd + 1, &fds, NULL, NULL, NULL);
-        if (ret == -1)
+        do {
+            ret = select(max_fd + 1, &fds, NULL, NULL, NULL);
+        } while (ret == -1 && errno == EINTR);
+        if (ret == -1 || FD_ISSET(sigterm_fd[0], &fds)) {
             break;
+        }
 
         if (FD_ISSET(sharing_fds[0], &fds))
             ret--;
commit 74624688b3c003d1ed2763953aaf59974965fa22
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Nov 4 15:51:18 2011 +0100

    nbd: treat EPIPE from NBD_DO_IT as success
    
    This can be seen with "qemu-nbd -v -c", which returns 1 instead of 0
    when you disconnect with "qemu-nbd -d".
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/nbd.c b/nbd.c
index fb5e424..e6c931c 100644
--- a/nbd.c
+++ b/nbd.c
@@ -425,6 +425,13 @@ int nbd_client(int fd)
     TRACE("Doing NBD loop");
 
     ret = ioctl(fd, NBD_DO_IT);
+    if (ret == -1 && errno == EPIPE) {
+        /* NBD_DO_IT normally returns EPIPE when someone has disconnected
+         * the socket via NBD_DISCONNECT.  We do not want to return 1 in
+         * that case.
+         */
+        ret = 0;
+    }
     serrno = errno;
 
     TRACE("NBD loop returned %d: %s", ret, strerror(serrno));
commit 4480de19d9b62c20e8cae0bcb6c2d00a954615a3
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Oct 25 12:53:40 2011 +0200

    scsi-disk: implement eject requests
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 1c04872..62f538f 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -65,6 +65,7 @@ struct SCSIDiskState
     uint32_t removable;
     bool media_changed;
     bool media_event;
+    bool eject_request;
     QEMUBH *bh;
     char *version;
     char *serial;
@@ -671,9 +672,14 @@ static int scsi_event_status_media(SCSIDiskState *s, uint8_t *outbuf)
 
     /* Event notification descriptor */
     event_code = MEC_NO_CHANGE;
-    if (media_status != MS_TRAY_OPEN && s->media_event) {
-        event_code = MEC_NEW_MEDIA;
-        s->media_event = false;
+    if (media_status != MS_TRAY_OPEN) {
+        if (s->media_event) {
+            event_code = MEC_NEW_MEDIA;
+            s->media_event = false;
+        } else if (s->eject_request) {
+            event_code = MEC_EJECT_REQUESTED;
+            s->eject_request = false;
+        }
     }
 
     outbuf[0] = event_code;
@@ -1470,6 +1476,17 @@ static void scsi_cd_change_media_cb(void *opaque, bool load)
     s->tray_open = !load;
     s->qdev.unit_attention = SENSE_CODE(UNIT_ATTENTION_NO_MEDIUM);
     s->media_event = true;
+    s->eject_request = false;
+}
+
+static void scsi_cd_eject_request_cb(void *opaque, bool force)
+{
+    SCSIDiskState *s = opaque;
+
+    s->eject_request = true;
+    if (force) {
+        s->tray_locked = false;
+    }
 }
 
 static bool scsi_cd_is_tray_open(void *opaque)
@@ -1484,6 +1501,7 @@ static bool scsi_cd_is_medium_locked(void *opaque)
 
 static const BlockDevOps scsi_cd_block_ops = {
     .change_media_cb = scsi_cd_change_media_cb,
+    .eject_request_cb = scsi_cd_eject_request_cb,
     .is_tray_open = scsi_cd_is_tray_open,
     .is_medium_locked = scsi_cd_is_medium_locked,
 };
commit 2df0a3a3085adfde93505bc73c938310b0820c36
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Oct 25 12:53:39 2011 +0200

    atapi: implement eject requests
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
index 90b6729..1fed359 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -516,9 +516,14 @@ static unsigned int event_status_media(IDEState *s,
 
     /* Event notification descriptor */
     event_code = MEC_NO_CHANGE;
-    if (media_status != MS_TRAY_OPEN && s->events.new_media) {
-        event_code = MEC_NEW_MEDIA;
-        s->events.new_media = false;
+    if (media_status != MS_TRAY_OPEN) {
+        if (s->events.new_media) {
+            event_code = MEC_NEW_MEDIA;
+            s->events.new_media = false;
+        } else if (s->events.eject_request) {
+            event_code = MEC_EJECT_REQUESTED;
+            s->events.eject_request = false;
+        }
     }
 
     buf[4] = event_code;
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 9a2fd30..93a1a68 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -804,6 +804,18 @@ static void ide_cd_change_cb(void *opaque, bool load)
      */
     s->cdrom_changed = 1;
     s->events.new_media = true;
+    s->events.eject_request = false;
+    ide_set_irq(s->bus);
+}
+
+static void ide_cd_eject_request_cb(void *opaque, bool force)
+{
+    IDEState *s = opaque;
+
+    s->events.eject_request = true;
+    if (force) {
+        s->tray_locked = false;
+    }
     ide_set_irq(s->bus);
 }
 
@@ -1811,6 +1823,7 @@ static bool ide_cd_is_medium_locked(void *opaque)
 
 static const BlockDevOps ide_cd_block_ops = {
     .change_media_cb = ide_cd_change_cb,
+    .eject_request_cb = ide_cd_eject_request_cb,
     .is_tray_open = ide_cd_is_tray_open,
     .is_medium_locked = ide_cd_is_medium_locked,
 };
commit 025ccaa7f9d2f54a79567599d3eb402100bed7a4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Nov 7 17:50:13 2011 +0100

    block: add eject request callback
    
    Recent versions of udev always keep the tray locked so that the kernel
    can observe "eject request" events (aka tray button presses) even on
    discs that aren't mounted.  Add support for these events in the ATAPI
    and SCSI cd drive device models.
    
    To let management cope with the behavior of udev, an event should also
    be added for "tray opened/closed".  This way, after issuing an "eject"
    command, management can poll until the guests actually reacts to the
    command.  They can then issue the "change" command after the tray has been
    opened, or try with "eject -f" after a (configurable?) timeout.  However,
    with this patch and the corresponding support in the device models,
    at least it is possible to do a manual two-step eject+change sequence.
    
    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 9bb236c..5c30c9d 100644
--- a/block.c
+++ b/block.c
@@ -816,6 +816,13 @@ bool bdrv_dev_has_removable_media(BlockDriverState *bs)
     return !bs->dev || (bs->dev_ops && bs->dev_ops->change_media_cb);
 }
 
+void bdrv_dev_eject_request(BlockDriverState *bs, bool force)
+{
+    if (bs->dev_ops && bs->dev_ops->eject_request_cb) {
+        bs->dev_ops->eject_request_cb(bs->dev_opaque, force);
+    }
+}
+
 bool bdrv_dev_is_tray_open(BlockDriverState *bs)
 {
     if (bs->dev_ops && bs->dev_ops->is_tray_open) {
diff --git a/block.h b/block.h
index 38cd748..051a25d 100644
--- a/block.h
+++ b/block.h
@@ -39,6 +39,15 @@ typedef struct BlockDevOps {
      */
     void (*change_media_cb)(void *opaque, bool load);
     /*
+     * Runs when an eject request is issued from the monitor, the tray
+     * is closed, and the medium is locked.
+     * Device models that do not implement is_medium_locked will not need
+     * this callback.  Device models that can lock the medium or tray might
+     * want to implement the callback and unlock the tray when "force" is
+     * true, even if they do not support eject requests.
+     */
+    void (*eject_request_cb)(void *opaque, bool force);
+    /*
      * Is the virtual tray open?
      * Device models implement this only when the device has a tray.
      */
@@ -111,6 +120,7 @@ void bdrv_detach_dev(BlockDriverState *bs, void *dev);
 void *bdrv_get_attached_dev(BlockDriverState *bs);
 void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops,
                       void *opaque);
+void bdrv_dev_eject_request(BlockDriverState *bs, bool force);
 bool bdrv_dev_has_removable_media(BlockDriverState *bs);
 bool bdrv_dev_is_tray_open(BlockDriverState *bs);
 bool bdrv_dev_is_medium_locked(BlockDriverState *bs);
diff --git a/blockdev.c b/blockdev.c
index 0827bf7..2228186 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -635,10 +635,12 @@ static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
         qerror_report(QERR_DEVICE_NOT_REMOVABLE, bdrv_get_device_name(bs));
         return -1;
     }
-    if (!force && !bdrv_dev_is_tray_open(bs)
-        && bdrv_dev_is_medium_locked(bs)) {
-        qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
-        return -1;
+    if (bdrv_dev_is_medium_locked(bs) && !bdrv_dev_is_tray_open(bs)) {
+        bdrv_dev_eject_request(bs, force);
+        if (!force) {
+            qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
+            return -1;
+        }
     }
     bdrv_close(bs);
     return 0;
commit 7704df98b09f886a9cf1d42aa6aa9a776ad1be3c
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Nov 8 10:50:12 2011 +0100

    vvfat: Fix read-write mode
    
    vvfat used to directly call into the qcow2 block driver instead of using the
    block.c wrappers. With the coroutine conversion, this stopped working.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/vvfat.c b/block/vvfat.c
index 8511fe5..131680f 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -1254,15 +1254,15 @@ static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
 	   return -1;
 	if (s->qcow) {
 	    int n;
-	    if (s->qcow->drv->bdrv_is_allocated(s->qcow,
-			sector_num, nb_sectors-i, &n)) {
+            if (bdrv_is_allocated(s->qcow, sector_num, nb_sectors-i, &n)) {
 DLOG(fprintf(stderr, "sectors %d+%d allocated\n", (int)sector_num, n));
-		if (s->qcow->drv->bdrv_read(s->qcow, sector_num, buf+i*0x200, n))
-		    return -1;
-		i += n - 1;
-		sector_num += n - 1;
-		continue;
-	    }
+                if (bdrv_read(s->qcow, sector_num, buf + i*0x200, n)) {
+                    return -1;
+                }
+                i += n - 1;
+                sector_num += n - 1;
+                continue;
+            }
 DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
 	}
 	if(sector_num<s->faked_sectors) {
@@ -1516,7 +1516,7 @@ static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
 	return 0;
 
     for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
-	was_modified = s->qcow->drv->bdrv_is_allocated(s->qcow,
+	was_modified = bdrv_is_allocated(s->qcow,
 		cluster2sector(s, cluster_num) + i, 1, &dummy);
 
     return was_modified;
@@ -1665,16 +1665,16 @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
 		int64_t offset = cluster2sector(s, cluster_num);
 
 		vvfat_close_current_file(s);
-		for (i = 0; i < s->sectors_per_cluster; i++)
-		    if (!s->qcow->drv->bdrv_is_allocated(s->qcow,
-				offset + i, 1, &dummy)) {
-			if (vvfat_read(s->bs,
-				    offset, s->cluster_buffer, 1))
-			    return -1;
-			if (s->qcow->drv->bdrv_write(s->qcow,
-				    offset, s->cluster_buffer, 1))
-			    return -2;
-		    }
+                for (i = 0; i < s->sectors_per_cluster; i++) {
+                    if (!bdrv_is_allocated(s->qcow, offset + i, 1, &dummy)) {
+                        if (vvfat_read(s->bs, offset, s->cluster_buffer, 1)) {
+                            return -1;
+                        }
+                        if (bdrv_write(s->qcow, offset, s->cluster_buffer, 1)) {
+                            return -2;
+                        }
+                    }
+                }
 	    }
 	}
 
@@ -2619,7 +2619,9 @@ static int do_commit(BDRVVVFATState* s)
 	return ret;
     }
 
-    s->qcow->drv->bdrv_make_empty(s->qcow);
+    if (s->qcow->drv->bdrv_make_empty) {
+        s->qcow->drv->bdrv_make_empty(s->qcow);
+    }
 
     memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
 
@@ -2714,7 +2716,7 @@ DLOG(checkpoint());
      * Use qcow backend. Commit later.
      */
 DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
-    ret = s->qcow->drv->bdrv_write(s->qcow, sector_num, buf, nb_sectors);
+    ret = bdrv_write(s->qcow, sector_num, buf, nb_sectors);
     if (ret < 0) {
 	fprintf(stderr, "Error writing to qcow backend\n");
 	return ret;
commit 0e3b800e71cb7759d099eabbd8ad4c4fe848e381
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 9 18:59:54 2011 +0000

    hw/lan9118.c: Add missing 'break' to fix buffer overrun
    
    Add a missing 'break' statement to fix a buffer overrun when
    executing the EEPROM write-all command. Spotted by Coverity
    (see bug 887883).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/lan9118.c b/hw/lan9118.c
index 634b88e..f8149e6 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -863,6 +863,7 @@ static void lan9118_eeprom_cmd(lan9118_state *s, int cmd, int addr)
         } else {
             DPRINTF("EEPROM Write All (ignored)\n");
         }
+        break;
     case 5: /* ERASE */
         if (s->eeprom_writable) {
             s->eeprom[addr] = 0xff;
commit 04c5b17a74c9d6c309181079f8949665b43b0164
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Nov 8 15:36:50 2011 +0100

    x86/cpuid: Fix crash on -cpu ""
    
    Spotted by Coverity.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 99cff65..21e5896 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -594,9 +594,9 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
     uint32_t numvalue;
 
     for (def = x86_defs; def; def = def->next)
-        if (!strcmp(name, def->name))
+        if (name && !strcmp(name, def->name))
             break;
-    if (kvm_enabled() && strcmp(name, "host") == 0) {
+    if (kvm_enabled() && name && strcmp(name, "host") == 0) {
         cpu_x86_fill_host(x86_cpu_def);
     } else if (!def) {
         goto error;
commit 99e1dec06f343cefecae9baeec0aae2f99f552d5
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Nov 8 15:36:49 2011 +0100

    x86/cpuid: Plug memory leak in cpudef_setfield()
    
    To reproduce the leak, put two name options into the same [cpudef]
    section of target-x86_64.conf.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 352c390..99cff65 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -950,6 +950,7 @@ static int cpudef_setfield(const char *name, const char *str, void *opaque)
     int err = 0;
 
     if (!strcmp(name, "name")) {
+        g_free((void *)def->name);
         def->name = g_strdup(str);
     } else if (!strcmp(name, "model_id")) {
         strncpy(def->model_id, str, sizeof (def->model_id));
commit d3c481b357ee6f78d3df10ee30407fa05d85b76c
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Nov 8 15:36:48 2011 +0100

    x86/cpuid: Convert remaining strdup() to g_strdup()
    
    Fixes missing error checking.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index edac377..352c390 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -581,7 +581,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
     unsigned int i;
     x86_def_t *def;
 
-    char *s = strdup(cpu_model);
+    char *s = g_strdup(cpu_model);
     char *featurestr, *name = strtok(s, ",");
     /* Features to be added*/
     uint32_t plus_features = 0, plus_ext_features = 0;
@@ -727,11 +727,11 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
         if (check_features_against_host(x86_cpu_def) && enforce_cpuid)
             goto error;
     }
-    free(s);
+    g_free(s);
     return 0;
 
 error:
-    free(s);
+    g_free(s);
     return -1;
 }
 
@@ -950,7 +950,7 @@ static int cpudef_setfield(const char *name, const char *str, void *opaque)
     int err = 0;
 
     if (!strcmp(name, "name")) {
-        def->name = strdup(str);
+        def->name = g_strdup(str);
     } else if (!strcmp(name, "model_id")) {
         strncpy(def->model_id, str, sizeof (def->model_id));
     } else if (!strcmp(name, "level")) {
commit 302d9d6fd8cb34e393cc9bb101a1748bd53899d3
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Nov 8 13:45:21 2011 +0100

    ui/vnc: Convert sasl.mechlist to g_malloc() & friends
    
    Fixes protocol_client_auth_sasl_mechname() not to crash when malloc()
    fails.  Spotted by Coverity.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c
index 23b1bf5..e2045fc 100644
--- a/ui/vnc-auth-sasl.c
+++ b/ui/vnc-auth-sasl.c
@@ -35,7 +35,7 @@ void vnc_sasl_client_cleanup(VncState *vs)
         vs->sasl.encodedLength = vs->sasl.encodedOffset = 0;
         vs->sasl.encoded = NULL;
         g_free(vs->sasl.username);
-        free(vs->sasl.mechlist);
+        g_free(vs->sasl.mechlist);
         vs->sasl.username = vs->sasl.mechlist = NULL;
         sasl_dispose(&vs->sasl.conn);
         vs->sasl.conn = NULL;
@@ -430,11 +430,7 @@ static int protocol_client_auth_sasl_start_len(VncState *vs, uint8_t *data, size
 
 static int protocol_client_auth_sasl_mechname(VncState *vs, uint8_t *data, size_t len)
 {
-    char *mechname = malloc(len + 1);
-    if (!mechname) {
-        VNC_DEBUG("Out of memory reading mechname\n");
-        vnc_client_error(vs);
-    }
+    char *mechname = g_malloc(len + 1);
     strncpy(mechname, (char*)data, len);
     mechname[len] = '\0';
     VNC_DEBUG("Got client mechname '%s' check against '%s'\n",
@@ -460,7 +456,7 @@ static int protocol_client_auth_sasl_mechname(VncState *vs, uint8_t *data, size_
         }
     }
 
-    free(vs->sasl.mechlist);
+    g_free(vs->sasl.mechlist);
     vs->sasl.mechlist = mechname;
 
     VNC_DEBUG("Validated mechname '%s'\n", mechname);
@@ -469,7 +465,7 @@ static int protocol_client_auth_sasl_mechname(VncState *vs, uint8_t *data, size_
 
  fail:
     vnc_client_error(vs);
-    free(mechname);
+    g_free(mechname);
     return -1;
 }
 
@@ -608,12 +604,7 @@ void start_auth_sasl(VncState *vs)
     }
     VNC_DEBUG("Available mechanisms for client: '%s'\n", mechlist);
 
-    if (!(vs->sasl.mechlist = strdup(mechlist))) {
-        VNC_DEBUG("Out of memory");
-        sasl_dispose(&vs->sasl.conn);
-        vs->sasl.conn = NULL;
-        goto authabort;
-    }
+    vs->sasl.mechlist = g_strdup(mechlist);
     mechlistlen = strlen(mechlist);
     vnc_write_u32(vs, mechlistlen);
     vnc_write(vs, mechlist, mechlistlen);
commit 542379f42642179cea33571c2799ca6fd03bf452
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Nov 8 11:00:38 2011 +0100

    qdev: Fix crash on -device '?=x'
    
    Spotted by Coverity.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 50976dd..106407f 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -186,7 +186,7 @@ int qdev_device_help(QemuOpts *opts)
         return 1;
     }
 
-    if (!qemu_opt_get(opts, "?")) {
+    if (!driver || !qemu_opt_get(opts, "?")) {
         return 0;
     }
 
commit 235e510cfddf2a5585f5f7ad5bcf65b6a4d7f221
Author: 陳韋任 <chenwj at iis.sinica.edu.tw>
Date:   Mon Nov 7 17:42:05 2011 +0800

    configure: Show --cpu option on the help list
    
    Signed-off-by: Chen Wen-Ren (陳韋任) <chenwj at iis.sinica.edu.tw>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/configure b/configure
index 401d9a6..8d85d23 100755
--- a/configure
+++ b/configure
@@ -1037,6 +1037,7 @@ echo "  --fmod-lib               path to FMOD library"
 echo "  --fmod-inc               path to FMOD includes"
 echo "  --oss-lib                path to OSS library"
 echo "  --enable-uname-release=R Return R for uname -r in usermode emulation"
+echo "  --cpu=CPU                Build for host CPU [$cpu]"
 echo "  --sparc_cpu=V            Build qemu for Sparc architecture v7, v8, v8plus, v8plusa, v9"
 echo "  --disable-uuid           disable uuid support"
 echo "  --enable-uuid            enable uuid support"
commit 27c8efcb5d0dcd0e3232c396a0280a10c78e89a1
Author: 陳韋任 <chenwj at iis.sinica.edu.tw>
Date:   Sat Nov 5 01:14:44 2011 +0800

    qemu-tech.texi: Update default code cache size
    
      Update the document since the default code cache size is 32 MB now.
    
    Signed-off-by: chenwj <chenwj at cs.nctu.edu.tw>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/qemu-tech.texi b/qemu-tech.texi
index 397b070..62afe45 100644
--- a/qemu-tech.texi
+++ b/qemu-tech.texi
@@ -435,7 +435,7 @@ generate an addition for the segment base.
 @node Translation cache
 @section Translation cache
 
-A 16 MByte cache holds the most recently used translations. For
+A 32 MByte cache holds the most recently used translations. For
 simplicity, it is completely flushed when it is full. A translation unit
 contains just a single basic block (a block of x86 instructions
 terminated by a jump or by a virtual CPU state change which the
commit 4f61927a41a098d06e642ffdea5fc285dc3a0e6b
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Wed Nov 9 05:18:09 2011 +0400

    hpet: fix infinite loop in qemu_run_timers with -icount enabled
    
    hpet_timer timer callback rearms itself based on difference between
    current HPET tick counter and comparator value. Difference calculated by
    the hpet_calculate_diff function is limited to non-negative values.
    
    cur_tick is calculated via hpet_get_ticks that uses qemu_get_clock_ns(vm_clock).
    
    With -icount enabled vm_clock doesn't advance during qemu_run_timers
    loop thus once difference is zero, qemu_run_timers loops forever
    handling hpet_timer.
    
    Limit hpet_calculate_diff results to positive only values to avoid that
    infinite loop.
    
    This fixes the following qemu-system-x86_64 hang when it reaches
    timer_irq_works() in the linux bootup:
    
    [    0.000000] Fast TSC calibration using PIT
    [    0.000000] Detected 1000.054 MHz processor.
    [    0.000031] Calibrating delay loop (skipped), value calculated using timer frequency.. 2000.10 BogoMIPS (lpj=10000540)
    [    0.000404] pid_max: default: 32768 minimum: 301
    [    0.001138] Mount-cache hash table entries: 256
    [    0.003883] Initializing cgroup subsys ns
    [    0.004035] Initializing cgroup subsys cpuacct
    [    0.004280] Initializing cgroup subsys freezer
    [    0.004790] Performance Events: AMD PMU driver.
    [    0.004985] ... version:                0
    [    0.005134] ... bit width:              48
    [    0.005285] ... generic registers:      4
    [    0.005437] ... value mask:             0000ffffffffffff
    [    0.005625] ... max period:             00007fffffffffff
    [    0.005807] ... fixed-purpose events:   0
    [    0.005957] ... event mask:             000000000000000f
    [    0.006275] SMP alternatives: switching to UP code
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/hpet.c b/hw/hpet.c
index 12bd64d..6e6ea52 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -157,14 +157,14 @@ static inline uint64_t hpet_calculate_diff(HPETTimer *t, uint64_t current)
 
         cmp = (uint32_t)t->cmp;
         diff = cmp - (uint32_t)current;
-        diff = (int32_t)diff > 0 ? diff : (uint32_t)0;
+        diff = (int32_t)diff > 0 ? diff : (uint32_t)1;
         return (uint64_t)diff;
     } else {
         uint64_t diff, cmp;
 
         cmp = t->cmp;
         diff = cmp - current;
-        diff = (int64_t)diff > 0 ? diff : (uint64_t)0;
+        diff = (int64_t)diff > 0 ? diff : (uint64_t)1;
         return diff;
     }
 }
commit c0465d1a1d4c9562cfa7e91f6c31ea1bce22052c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 9 17:42:23 2011 +0000

    hw/omap_gpmc.c: Add missing 'break's to fix 8 bit NAND writes
    
    Add missing 'break' statements which would have meant that writing
    to an 8 bit NAND device was broken. Spotted by Coverity (see bug
    887883).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/omap_gpmc.c b/hw/omap_gpmc.c
index 7fc82a2..414f9f5 100644
--- a/hw/omap_gpmc.c
+++ b/hw/omap_gpmc.c
@@ -180,6 +180,7 @@ static void omap_nand_setio(DeviceState *dev, uint64_t value,
             nand_setio(dev, (value >> 24) & 0xff);
             break;
         }
+        break;
     case OMAP_GPMC_16BIT:
         switch (size) {
         case 1:
@@ -195,6 +196,7 @@ static void omap_nand_setio(DeviceState *dev, uint64_t value,
             nand_setio(dev, (value >> 16) & 0xffff);
             break;
         }
+        break;
     }
 }
 
commit 95117be5a337d15555b69b7059d4e0791ce8063d
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 9 17:20:06 2011 +0000

    hw/omap_dss.c: Fix !-vs-~ bug in handling DISPC_CONTROL
    
    Fix a bug revealed by a coverity scan (see bug 887883) which meant
    that we would never print the warning about unpredictable behaviour
    if a nonexistent overlay is enabled.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/omap_dss.c b/hw/omap_dss.c
index c8387a8..b4a8b4c 100644
--- a/hw/omap_dss.c
+++ b/hw/omap_dss.c
@@ -389,10 +389,11 @@ static void omap_disc_write(void *opaque, target_phys_addr_t addr,
         s->dig.enable = (value >> 1) & 1;
         s->lcd.enable = (value >> 0) & 1;
         if (value & (1 << 12))			/* OVERLAY_OPTIMIZATION */
-            if (~((s->dispc.l[1].attr | s->dispc.l[2].attr) & 1))
-                 fprintf(stderr, "%s: Overlay Optimization when no overlay "
-                                 "region effectively exists leads to "
-                                 "unpredictable behaviour!\n", __FUNCTION__);
+            if (!((s->dispc.l[1].attr | s->dispc.l[2].attr) & 1)) {
+                fprintf(stderr, "%s: Overlay Optimization when no overlay "
+                        "region effectively exists leads to "
+                        "unpredictable behaviour!\n", __func__);
+            }
         if (value & (1 << 6)) {				/* GODIGITAL */
             /* XXX: Shadowed fields are:
              * s->dispc.config
commit 66e3dd9282141b5ae75637c9676002cf3ceeb988
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Nov 9 15:44:36 2011 +0200

    i386: derive '-cpu host' from KVM_GET_SUPPORTED_CPUID
    
    The fact that a host cpu supports a feature doesn't mean that QEMU and KVM
    will also support it, yet -cpuid host brings host features wholesale.
    
    We need to whitelist each feature separately to make sure we support it.
    This patch adds KVM whitelisting (by simply using KVM_GET_SUPPORTED_CPUID
    instead of the CPUID instruction).
    
    Signed-off-by: Avi Kivity <avi 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 1e8bcff..edac377 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -107,33 +107,14 @@ void host_cpuid(uint32_t function, uint32_t count,
                 uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
 {
 #if defined(CONFIG_KVM)
-    uint32_t vec[4];
-
-#ifdef __x86_64__
-    asm volatile("cpuid"
-                 : "=a"(vec[0]), "=b"(vec[1]),
-                   "=c"(vec[2]), "=d"(vec[3])
-                 : "0"(function), "c"(count) : "cc");
-#else
-    asm volatile("pusha \n\t"
-                 "cpuid \n\t"
-                 "mov %%eax, 0(%2) \n\t"
-                 "mov %%ebx, 4(%2) \n\t"
-                 "mov %%ecx, 8(%2) \n\t"
-                 "mov %%edx, 12(%2) \n\t"
-                 "popa"
-                 : : "a"(function), "c"(count), "S"(vec)
-                 : "memory", "cc");
-#endif
-
     if (eax)
-        *eax = vec[0];
+        *eax = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_EAX);
     if (ebx)
-        *ebx = vec[1];
+        *ebx = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_EBX);
     if (ecx)
-        *ecx = vec[2];
+        *ecx = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_ECX);
     if (edx)
-        *edx = vec[3];
+        *edx = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_EDX);
 #endif
 }
 
commit 4f26f2b6f2fba52b13f4c2ad1790f46c96a0923e
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Nov 9 14:44:52 2011 +0200

    configure: fix detection for xattr.h on modern distributions
    
    Modern distributions place xattr.h in /usr/include/sys, and fold
    libattr.so into libc.  They also don't have an ENOATTR.
    
    Make configure detect this, and add a qemu-xattr.h file that
    directs the #include to the right place.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index 9e5da44..401d9a6 100755
--- a/configure
+++ b/configure
@@ -129,6 +129,7 @@ xen=""
 xen_ctrl_version=""
 linux_aio=""
 attr=""
+libattr=""
 xfs=""
 
 vhost_net="no"
@@ -1961,12 +1962,16 @@ if test "$attr" != "no" ; then
   cat > $TMPC <<EOF
 #include <stdio.h>
 #include <sys/types.h>
-#include <attr/xattr.h>
+#include <sys/xattr.h>
 int main(void) { getxattr(NULL, NULL, NULL, 0); setxattr(NULL, NULL, NULL, 0, 0); return 0; }
 EOF
-  if compile_prog "" "-lattr" ; then
+  if compile_prog "" "" ; then
+    attr=yes
+  # Older distros have <attr/xattr.h>, and need -lattr:
+  elif sed -i s,sys/xattr,attr/xattr, $TMPC && compile_prog "" "-lattr" ; then
     attr=yes
     LIBS="-lattr $LIBS"
+    libattr=yes
   else
     if test "$attr" = "yes" ; then
       feature_not_found "ATTR"
@@ -3032,6 +3037,9 @@ fi
 if test "$attr" = "yes" ; then
   echo "CONFIG_ATTR=y" >> $config_host_mak
 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
diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c
index c38e0e7..0a778b4 100644
--- a/hw/9pfs/virtio-9p-handle.c
+++ b/hw/9pfs/virtio-9p-handle.c
@@ -19,7 +19,7 @@
 #include <grp.h>
 #include <sys/socket.h>
 #include <sys/un.h>
-#include <attr/xattr.h>
+#include "qemu-xattr.h"
 #include <unistd.h>
 #include <linux/fs.h>
 #ifdef CONFIG_LINUX_MAGIC_H
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 782dc0a..7f1c089 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -19,7 +19,7 @@
 #include <grp.h>
 #include <sys/socket.h>
 #include <sys/un.h>
-#include <attr/xattr.h>
+#include "qemu-xattr.h"
 #include <linux/fs.h>
 #ifdef CONFIG_LINUX_MAGIC_H
 #include <linux/magic.h>
diff --git a/hw/9pfs/virtio-9p-posix-acl.c b/hw/9pfs/virtio-9p-posix-acl.c
index f5b392e..a1948e3 100644
--- a/hw/9pfs/virtio-9p-posix-acl.c
+++ b/hw/9pfs/virtio-9p-posix-acl.c
@@ -12,7 +12,7 @@
  */
 
 #include <sys/types.h>
-#include <attr/xattr.h>
+#include "qemu-xattr.h"
 #include "hw/virtio.h"
 #include "virtio-9p.h"
 #include "fsdev/file-op-9p.h"
diff --git a/hw/9pfs/virtio-9p-xattr.h b/hw/9pfs/virtio-9p-xattr.h
index 247e414..9437280 100644
--- a/hw/9pfs/virtio-9p-xattr.h
+++ b/hw/9pfs/virtio-9p-xattr.h
@@ -13,7 +13,7 @@
 #ifndef _QEMU_VIRTIO_9P_XATTR_H
 #define _QEMU_VIRTIO_9P_XATTR_H
 
-#include <attr/xattr.h>
+#include "qemu-xattr.h"
 
 typedef struct xattr_operations
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 9f5da36..f227097 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -71,7 +71,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
 #include <sys/epoll.h>
 #endif
 #ifdef CONFIG_ATTR
-#include <attr/xattr.h>
+#include "qemu-xattr.h"
 #endif
 
 #define termios host_termios
diff --git a/qemu-xattr.h b/qemu-xattr.h
new file mode 100644
index 0000000..f910d96
--- /dev/null
+++ b/qemu-xattr.h
@@ -0,0 +1,30 @@
+/*
+ * Host xattr.h abstraction
+ *
+ * Copyright 2011 Red Hat Inc. and/or its affiliates
+ *
+ * Authors:
+ *  Avi Kivity <avi at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2, or any
+ * later version.  See the COPYING file in the top-level directory.
+ *
+ */
+#ifndef QEMU_XATTR_H
+#define QEMU_XATTR_H
+
+/*
+ * Modern distributions (e.g. Fedora 15, have no libattr.so, place attr.h
+ * in /usr/include/sys, and don't have ENOATTR.
+ */
+
+#include "config-host.h"
+
+#ifdef CONFIG_LIBATTR
+#  include <attr/xattr.h>
+#else
+#  define ENOATTR ENODATA
+#  include <sys/xattr.h>
+#endif
+
+#endif
commit 1bf6ccd372aeb8e1a36da35fa15cf24e42f7e0b7
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Nov 8 10:58:00 2011 +0100

    Clean up assertion in get_boot_devices_list()
    
    g_strdup() can't fail, remove assertion.  Assert its argument can't be
    null, because that's not obvious (add_boot_device_path() ensures it).
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index 641629b..f169aac 100644
--- a/vl.c
+++ b/vl.c
@@ -915,8 +915,8 @@ char *get_boot_devices_list(uint32_t *size)
         } else if (devpath) {
             bootpath = devpath;
         } else {
+            assert(i->suffix);
             bootpath = g_strdup(i->suffix);
-            assert(bootpath);
         }
 
         if (total) {
commit bfc763fcfa80d89d31c4f801c2a82130dd92c708
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Mon Nov 7 15:36:14 2011 +0100

    Replace WriteFileEx with WriteFile in qemu_create_pidfile
    
    The function that writes pidfile for win32 uses WriteFileEx which is an
    asynchronous IO function. The arguments given to WriteFileEx are allocated on
    the stack and one of them is "in out". When the IO operation is actually
    executed the calling function has already returned, so the arguments are no
    longer allocated or allocated to another frame.
    
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/os-win32.c b/os-win32.c
index 7909401..8ad5fa1 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -130,14 +130,15 @@ int qemu_create_pidfile(const char *filename)
     memset(&overlap, 0, sizeof(overlap));
 
     file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
-		      OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+                      OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
 
     if (file == INVALID_HANDLE_VALUE) {
         return -1;
     }
     len = snprintf(buffer, sizeof(buffer), "%d\n", getpid());
-    ret = WriteFileEx(file, (LPCVOID)buffer, (DWORD)len,
-		      &overlap, NULL);
+    ret = WriteFile(file, (LPCVOID)buffer, (DWORD)len,
+                    NULL, &overlap);
+    CloseHandle(file);
     if (ret == 0) {
         return -1;
     }
commit cca5de7389ff850ab19d4458da6a0c22ccbac976
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Nov 9 12:46:56 2011 +0100

    win32: remove broken timers
    
    The non-dynticks timer variations are broken, so they can be
    removed.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index f11a28d..cd026c6 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -183,10 +183,8 @@ static struct qemu_alarm_timer alarm_timers[] = {
 #endif
     {"unix", unix_start_timer, unix_stop_timer, unix_rearm_timer},
 #else
-    {"mmtimer", mm_start_timer, mm_stop_timer, NULL},
-    {"mmtimer2", mm_start_timer, mm_stop_timer, mm_rearm_timer},
+    {"mmtimer", mm_start_timer, mm_stop_timer, mm_rearm_timer},
     {"dynticks", win32_start_timer, win32_stop_timer, win32_rearm_timer},
-    {"win32", win32_start_timer, win32_stop_timer, NULL},
 #endif
     {NULL, }
 };
commit 9770b912522023fba61d65b03ed06ae71f939845
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Tue Nov 8 00:00:55 2011 +0100

    virtex: Remove memset of clk_setup
    
    clk_setup is now a function. Fixes a segfault.
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
index d31a204..5ea0e60 100644
--- a/hw/virtex_ml507.c
+++ b/hw/virtex_ml507.c
@@ -202,7 +202,6 @@ static void virtex_init(ram_addr_t ram_size,
         cpu_model = "440-Xilinx";
     }
 
-    memset(clk_setup, 0, sizeof(clk_setup));
     env = ppc440_init_xilinx(&ram_size, 1, cpu_model, 400000000);
     qemu_register_reset(main_cpu_reset, env);
 
commit 1d769ceda65eef76bad3356f5b7b0ce8a61e5d76
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Nov 7 10:57:45 2011 -0600

    Update version for v1.0-rc1
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/VERSION b/VERSION
index c78227b..4a15714 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.15.90
+0.15.91
commit 439229c7cb97f6c4cddd3965c3e9d2b8319fe83c
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Nov 4 10:38:29 2011 +0100

    console: Fix rendering of VGA underline
    
    vga_putcharxy()'s underline code sets font_data to 0xffff instead of
    0xff.  vga_putcharxy() then reads dmask16[0xffff >> 4] and
    dmask4[0xffff >> 6].  In practice, these out-of-bounds subscripts
    "only" put a few crap bits into the display surface.
    
    For 32 bit pixels, there's no array access.  font_data's extra bits go
    straight into the display surface.
    
    Broken when commit 6d6f7c28 implemented underline.
    
    Spotted by Coverity.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/console.c b/console.c
index e43de92..f6fe441 100644
--- a/console.c
+++ b/console.c
@@ -467,7 +467,7 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
             font_data = *font_ptr++;
             if (t_attrib->uline
                 && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
-                font_data = 0xFFFF;
+                font_data = 0xFF;
             }
             ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
             ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
@@ -480,7 +480,7 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
             font_data = *font_ptr++;
             if (t_attrib->uline
                 && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
-                font_data = 0xFFFF;
+                font_data = 0xFF;
             }
             ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
             ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
@@ -493,7 +493,7 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
         for(i = 0; i < FONT_HEIGHT; i++) {
             font_data = *font_ptr++;
             if (t_attrib->uline && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
-                font_data = 0xFFFF;
+                font_data = 0xFF;
             }
             ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
             ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
commit f54c556c08c57a317ad54f5d2d9ad549b931cda2
Author: Gleb Natapov <gleb at redhat.com>
Date:   Sun Nov 6 18:00:22 2011 +0200

    qemu_timedate_diff() shouldn't modify its argument.
    
    The caller of qemu_timedate_diff() does not expect that tm it passes to
    the function will be modified, but mktime() is destructive and modifies
    its argument. Pass a copy of tm to it and set tm_isdst so that mktime()
    will not rely on it since its value may be outdated.
    
    Signed-off-by: Gleb Natapov <gleb at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index 624da0f..641629b 100644
--- a/vl.c
+++ b/vl.c
@@ -460,8 +460,11 @@ int qemu_timedate_diff(struct tm *tm)
     if (rtc_date_offset == -1)
         if (rtc_utc)
             seconds = mktimegm(tm);
-        else
-            seconds = mktime(tm);
+        else {
+            struct tm tmp = *tm;
+            tmp.tm_isdst = -1; /* use timezone to figure it out */
+            seconds = mktime(&tmp);
+	}
     else
         seconds = mktimegm(tm) + rtc_date_offset;
 
commit 47113ab6b8c5659ad94c69aacca572f731ebb0ac
Author: Wen Congyang <wency at cn.fujitsu.com>
Date:   Fri Nov 4 10:45:58 2011 +0800

    reenable vm_clock when resuming all vcpus
    
    We disable vm_clock when pausing all vcpus, but we forget to
    reenable it when resuming all vcpus. It will cause that the
    guest can not be rebooted.
    
    Tested-by: Zhi Yong Wu <zwu.kernel at gmai.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/cpus.c b/cpus.c
index 6aff425..82530c4 100644
--- a/cpus.c
+++ b/cpus.c
@@ -891,6 +891,7 @@ void resume_all_vcpus(void)
 {
     CPUState *penv = first_cpu;
 
+    qemu_clock_enable(vm_clock, true);
     while (penv) {
         penv->stop = 0;
         penv->stopped = 0;
commit f67ab77a43cbaca27a39c69223ec6d5dc850f22d
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Nov 3 18:21:54 2011 +0100

    qxl: fix vga port initialization.
    
    Commit 0a039dc70096b768d3810afa50ba1d214768aaf4 broke vga modes for
    qxl-vga by loosing vga_ioport_read windup.  qxl needs to hook into
    vga port writes only and used to realize that by letting vga_init() do
    the work for both reads and writes, then overwrite the write function.
    That little detail was missed while doing the conversion ...
    
    This patch fixes it.  It also switch qxl vga ioport registration to
    portio lists while being at it.
    
    Cc: Hans de Goede <hdegoede at redhat.com>
    Acked-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index 84ffd45..41500e9 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -896,6 +896,20 @@ static void qxl_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
     vga_ioport_write(opaque, addr, val);
 }
 
+static const MemoryRegionPortio qxl_vga_portio_list[] = {
+    { 0x04,  2, 1, .read  = vga_ioport_read,
+                   .write = qxl_vga_ioport_write }, /* 3b4 */
+    { 0x0a,  1, 1, .read  = vga_ioport_read,
+                   .write = qxl_vga_ioport_write }, /* 3ba */
+    { 0x10, 16, 1, .read  = vga_ioport_read,
+                   .write = qxl_vga_ioport_write }, /* 3c0 */
+    { 0x24,  2, 1, .read  = vga_ioport_read,
+                   .write = qxl_vga_ioport_write }, /* 3d4 */
+    { 0x2a,  1, 1, .read  = vga_ioport_read,
+                   .write = qxl_vga_ioport_write }, /* 3da */
+    PORTIO_END_OF_LIST(),
+};
+
 static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
                             qxl_async_io async)
 {
@@ -1595,6 +1609,7 @@ static int qxl_init_primary(PCIDevice *dev)
     PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
     VGACommonState *vga = &qxl->vga;
     ram_addr_t ram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
+    PortioList *qxl_vga_port_list = g_new(PortioList, 1);
 
     qxl->id = 0;
 
@@ -1603,11 +1618,8 @@ static int qxl_init_primary(PCIDevice *dev)
     }
     vga_common_init(vga, ram_size);
     vga_init(vga, pci_address_space(dev), pci_address_space_io(dev), false);
-    register_ioport_write(0x3c0, 16, 1, qxl_vga_ioport_write, vga);
-    register_ioport_write(0x3b4,  2, 1, qxl_vga_ioport_write, vga);
-    register_ioport_write(0x3d4,  2, 1, qxl_vga_ioport_write, vga);
-    register_ioport_write(0x3ba,  1, 1, qxl_vga_ioport_write, vga);
-    register_ioport_write(0x3da,  1, 1, qxl_vga_ioport_write, vga);
+    portio_list_init(qxl_vga_port_list, qxl_vga_portio_list, vga, "vga");
+    portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0);
 
     vga->ds = graphic_console_init(qxl_hw_update, qxl_hw_invalidate,
                                    qxl_hw_screen_dump, qxl_hw_text_update, qxl);
commit 25a21c94c0055e078acb7f7455e66c8a15f32385
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Nov 7 16:33:09 2011 +0100

    ac97: don't override the pci subsystem id
    
    This patch removes the code lines which set the subsystem id for the
    emulated ac97 card to 8086:0000.  Due to the device id being zero the
    subsystem id isn't vaild anyway.  With the patch applied the sound card
    gets the default qemu subsystem id (1af4:1100) instead.
    
    [ v2: old & broken id is maintained for -M pc-$oldqemuversion ]
    
    Cc: Takashi Iwai <tiwai at suse.de>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ac97.c b/hw/ac97.c
index 6800af4..0dbba3b 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -150,6 +150,7 @@ typedef struct AC97BusMasterRegs {
 typedef struct AC97LinkState {
     PCIDevice dev;
     QEMUSoundCard card;
+    uint32_t use_broken_id;
     uint32_t glob_cnt;
     uint32_t glob_sta;
     uint32_t cas;
@@ -1305,11 +1306,12 @@ static int ac97_initfn (PCIDevice *dev)
     c[PCI_BASE_ADDRESS_0 + 6] = 0x00;
     c[PCI_BASE_ADDRESS_0 + 7] = 0x00;
 
-    c[PCI_SUBSYSTEM_VENDOR_ID] = 0x86;      /* svid subsystem vendor id rwo */
-    c[PCI_SUBSYSTEM_VENDOR_ID + 1] = 0x80;
-
-    c[PCI_SUBSYSTEM_ID] = 0x00;      /* sid subsystem id rwo */
-    c[PCI_SUBSYSTEM_ID + 1] = 0x00;
+    if (s->use_broken_id) {
+        c[PCI_SUBSYSTEM_VENDOR_ID] = 0x86;
+        c[PCI_SUBSYSTEM_VENDOR_ID + 1] = 0x80;
+        c[PCI_SUBSYSTEM_ID] = 0x00;
+        c[PCI_SUBSYSTEM_ID + 1] = 0x00;
+    }
 
     c[PCI_INTERRUPT_LINE] = 0x00;      /* intr_ln interrupt line rw */
     c[PCI_INTERRUPT_PIN] = 0x01;      /* intr_pn interrupt pin ro */
@@ -1350,6 +1352,10 @@ static PCIDeviceInfo ac97_info = {
     .device_id    = PCI_DEVICE_ID_INTEL_82801AA_5,
     .revision     = 0x01,
     .class_id     = PCI_CLASS_MULTIMEDIA_AUDIO,
+    .qdev.props   = (Property[]) {
+        DEFINE_PROP_UINT32("use_broken_id", AC97LinkState, use_broken_id, 0),
+        DEFINE_PROP_END_OF_LIST(),
+    }
 };
 
 static void ac97_register (void)
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 93e40d0..27ea570 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -347,6 +347,10 @@ static QEMUMachine pc_machine_v0_13 = {
             .driver   = "virtio-net-pci",
             .property = "event_idx",
             .value    = "off",
+        },{
+            .driver   = "AC97",
+            .property = "use_broken_id",
+            .value    = stringify(1),
         },
         { /* end of list */ }
     },
@@ -390,6 +394,10 @@ static QEMUMachine pc_machine_v0_12 = {
             .driver   = "virtio-net-pci",
             .property = "event_idx",
             .value    = "off",
+        },{
+            .driver   = "AC97",
+            .property = "use_broken_id",
+            .value    = stringify(1),
         },
         { /* end of list */ }
     }
@@ -441,6 +449,10 @@ static QEMUMachine pc_machine_v0_11 = {
             .driver   = "virtio-net-pci",
             .property = "event_idx",
             .value    = "off",
+        },{
+            .driver   = "AC97",
+            .property = "use_broken_id",
+            .value    = stringify(1),
         },
         { /* end of list */ }
     }
@@ -504,6 +516,10 @@ static QEMUMachine pc_machine_v0_10 = {
             .driver   = "virtio-net-pci",
             .property = "event_idx",
             .value    = "off",
+        },{
+            .driver   = "AC97",
+            .property = "use_broken_id",
+            .value    = stringify(1),
         },
         { /* end of list */ }
     },
commit 19857e625a8dc299b3fdfb8acdcbe1569745e290
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Nov 7 16:33:08 2011 +0100

    pc: add 1.0 machine type
    
    This patch adds a pc-1.0 machine type.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 8c7f2b7..93e40d0 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -297,8 +297,8 @@ static void pc_xen_hvm_init(ram_addr_t ram_size,
 }
 #endif
 
-static QEMUMachine pc_machine = {
-    .name = "pc-0.14",
+static QEMUMachine pc_machine_v1_0 = {
+    .name = "pc-1.0",
     .alias = "pc",
     .desc = "Standard PC",
     .init = pc_init_pci,
@@ -306,6 +306,13 @@ static QEMUMachine pc_machine = {
     .is_default = 1,
 };
 
+static QEMUMachine pc_machine_v0_14 = {
+    .name = "pc-0.14",
+    .desc = "Standard PC",
+    .init = pc_init_pci,
+    .max_cpus = 255,
+};
+
 static QEMUMachine pc_machine_v0_13 = {
     .name = "pc-0.13",
     .desc = "Standard PC",
@@ -521,7 +528,8 @@ static QEMUMachine xenfv_machine = {
 
 static void pc_machine_init(void)
 {
-    qemu_register_machine(&pc_machine);
+    qemu_register_machine(&pc_machine_v1_0);
+    qemu_register_machine(&pc_machine_v0_14);
     qemu_register_machine(&pc_machine_v0_13);
     qemu_register_machine(&pc_machine_v0_12);
     qemu_register_machine(&pc_machine_v0_11);
commit 6023d832480e6713e5ae81d3b74f53e6306f3a1b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Nov 3 16:00:22 2011 +0100

    disable automatic loading of sgabios when -nographic
    
    sgabios hasn't gotten a lot of coverage since it was not shipped.  For 1.0,
    let's disable the automatic loading of the option ROM in -nographic
    mode.  We can put it back for 1.1.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pc.c b/hw/pc.c
index 25bfa85..3015671 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1103,15 +1103,6 @@ void pc_vga_init(PCIBus *pci_bus)
             isa_vga_init();
         }
     }
-
-    /*
-     * sga does not suppress normal vga output. So a machine can have both a
-     * vga card and sga manually enabled. Output will be seen on both.
-     * For nographic case, sga is enabled at all times
-     */
-    if (display_type == DT_NOGRAPHIC) {
-        isa_create_simple("sga");
-    }
 }
 
 static void cpu_request_exit(void *opaque, int irq, int level)
commit 6329866f818db89645ca39fdf21a90f9d059be16
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Nov 3 15:14:00 2011 +0100

    add sgabios blob and submodule
    
    The rom was not added together with the sgabios device and is
    not installed.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/.gitmodules b/.gitmodules
index 2a43dbc..eca876f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -16,3 +16,6 @@
 [submodule "roms/qemu-palcode"]
 	path = roms/qemu-palcode
 	url = git://repo.or.cz/qemu-palcode.git
+[submodule "roms/sgabios"]
+	path = roms/sgabios
+	url = git://git.qemu.org/sgabios.git
diff --git a/Makefile b/Makefile
index 4f6eaa4..168093c 100644
--- a/Makefile
+++ b/Makefile
@@ -253,7 +253,7 @@ ar      de     en-us  fi  fr-be  hr     it  lv  nl         pl  ru     th \
 common  de-ch  es     fo  fr-ca  hu     ja  mk  nl-be      pt  sl     tr
 
 ifdef INSTALL_BLOBS
-BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin \
+BLOBS=bios.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \
 vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \
 ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc \
 pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
diff --git a/pc-bios/README b/pc-bios/README
index 0668559..1cebbbc 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -19,6 +19,12 @@
   https://github.com/dgibson/SLOF, and the image currently in qemu is
   built from git tag qemu-slof-20111013.
 
+- sgabios (the Serial Graphics Adapter option ROM) provides a means for
+  legacy x86 software to communicate with an attached serial console as
+  if a video card were attached.  The master sources reside in a subversion
+  repository at http://sgabios.googlecode.com/svn/trunk.  A git mirror is
+  available at git://git.qemu.org/sgabios.git.
+
 - The PXE roms come from the iPXE project. Built with BANNER_TIME 0.
   Sources available at http://ipxe.org.  Vendor:Device ID -> ROM mapping:
 
diff --git a/pc-bios/sgabios.bin b/pc-bios/sgabios.bin
new file mode 100755
index 0000000..c3da4c3
Binary files /dev/null and b/pc-bios/sgabios.bin differ
diff --git a/roms/sgabios b/roms/sgabios
new file mode 160000
index 0000000..23d4749
--- /dev/null
+++ b/roms/sgabios
@@ -0,0 +1 @@
+Subproject commit 23d474943dcd55d0550a3d20b3d30e9040a4f15b
commit 2963e65a4e195737256d849166981ea24a337b2e
Merge: ca062aa... 273e4e0...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Nov 7 10:57:27 2011 -0600

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

commit ca062aaed0b88060914ffb58442e12fde08db26d
Merge: 41bf234... e7b48c9...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Nov 7 10:56:38 2011 -0600

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging

commit e7b48c97fe7ea0b8149e1e3a20be88a908c2bfcd
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Fri Nov 4 15:35:11 2011 +0000

    xen-platform: Fix IO port read/write functions
    
    Somehow, the read/write functions handle an offset that does not exist anymore.
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/xen_platform.c b/hw/xen_platform.c
index 6e3ba8b..5e792f5 100644
--- a/hw/xen_platform.c
+++ b/hw/xen_platform.c
@@ -113,7 +113,7 @@ static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t v
 {
     PCIXenPlatformState *s = opaque;
 
-    switch (addr - XEN_PLATFORM_IOPORT) {
+    switch (addr) {
     case 0:
         /* Unplug devices.  Value is a bitmask of which devices to
            unplug, with bit 0 the IDE devices, bit 1 the network
@@ -152,7 +152,7 @@ static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t v
 static void platform_fixed_ioport_writel(void *opaque, uint32_t addr,
                                          uint32_t val)
 {
-    switch (addr - XEN_PLATFORM_IOPORT) {
+    switch (addr) {
     case 0:
         /* PV driver version */
         break;
@@ -163,7 +163,7 @@ static void platform_fixed_ioport_writeb(void *opaque, uint32_t addr, uint32_t v
 {
     PCIXenPlatformState *s = opaque;
 
-    switch (addr - XEN_PLATFORM_IOPORT) {
+    switch (addr) {
     case 0: /* Platform flags */ {
         hvmmem_type_t mem_type = (val & PFFLAG_ROM_LOCK) ?
             HVMMEM_ram_ro : HVMMEM_ram_rw;
@@ -186,7 +186,7 @@ static uint32_t platform_fixed_ioport_readw(void *opaque, uint32_t addr)
 {
     PCIXenPlatformState *s = opaque;
 
-    switch (addr - XEN_PLATFORM_IOPORT) {
+    switch (addr) {
     case 0:
         if (s->drivers_blacklisted) {
             /* The drivers will recognise this magic number and refuse
@@ -205,7 +205,7 @@ static uint32_t platform_fixed_ioport_readb(void *opaque, uint32_t addr)
 {
     PCIXenPlatformState *s = opaque;
 
-    switch (addr - XEN_PLATFORM_IOPORT) {
+    switch (addr) {
     case 0:
         /* Platform flags */
         return s->flags;
@@ -221,7 +221,7 @@ static void platform_fixed_ioport_reset(void *opaque)
 {
     PCIXenPlatformState *s = opaque;
 
-    platform_fixed_ioport_writeb(s, XEN_PLATFORM_IOPORT, 0);
+    platform_fixed_ioport_writeb(s, 0, 0);
 }
 
 const MemoryRegionPortio xen_platform_ioport[] = {
@@ -251,7 +251,7 @@ static void platform_fixed_ioport_init(PCIXenPlatformState* s)
 static uint32_t xen_platform_ioport_readb(void *opaque, uint32_t addr)
 {
     if (addr == 0) {
-        return platform_fixed_ioport_readb(opaque, XEN_PLATFORM_IOPORT);
+        return platform_fixed_ioport_readb(opaque, 0);
     } else {
         return ~0u;
     }
@@ -263,7 +263,7 @@ static void xen_platform_ioport_writeb(void *opaque, uint32_t addr, uint32_t val
 
     switch (addr) {
     case 0: /* Platform flags */
-        platform_fixed_ioport_writeb(opaque, XEN_PLATFORM_IOPORT, val);
+        platform_fixed_ioport_writeb(opaque, 0, val);
         break;
     case 8:
         log_writeb(s, val);
@@ -321,7 +321,7 @@ static int xen_platform_post_load(void *opaque, int version_id)
 {
     PCIXenPlatformState *s = opaque;
 
-    platform_fixed_ioport_writeb(s, XEN_PLATFORM_IOPORT, s->flags);
+    platform_fixed_ioport_writeb(s, 0, s->flags);
 
     return 0;
 }
commit 8af42882a51c632a14d77277df0740f1aa8c958a
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Nov 4 11:10:01 2011 +0100

    readline: Fix buffer overrun on re-add to history
    
    readline_hist_add() moves the history entry to the end of history.  It
    uses memmove() to move rs->history[idx + 1..] to rs->history[idx..].
    However, its size argument is off by two array elements, so it writes
    one element beyond rs->history[], and reads two.
    
    On my system, this clobbers rs->hist_entry and the hole right after
    it.  Since the function assigns to rs->hist_entry in time, the bug has
    no ill effects for me.
    
    Spotted by Coverity.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/readline.c b/readline.c
index 6a3160a..a6c0039 100644
--- a/readline.c
+++ b/readline.c
@@ -236,7 +236,7 @@ static void readline_hist_add(ReadLineState *rs, const char *cmdline)
 	    new_entry = hist_entry;
 	    /* Put this entry at the end of history */
 	    memmove(&rs->history[idx], &rs->history[idx + 1],
-		    (READLINE_MAX_CMDS - idx + 1) * sizeof(char *));
+		    (READLINE_MAX_CMDS - (idx + 1)) * sizeof(char *));
 	    rs->history[READLINE_MAX_CMDS - 1] = NULL;
 	    for (; idx < READLINE_MAX_CMDS; idx++) {
 		if (rs->history[idx] == NULL)
commit 47e8dd8fe9d83e8b51d40c2b87d7983bd0a78206
Author: Pavel Borzenkov <pavel.borzenkov at gmail.com>
Date:   Mon Oct 31 22:53:38 2011 +0400

    cmd: Fix potential memory leak
    
    Signed-off-by: Pavel Borzenkov <pavel.borzenkov at gmail.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/cmd.c b/cmd.c
index 75415d8..0806e18 100644
--- a/cmd.c
+++ b/cmd.c
@@ -329,16 +329,21 @@ char **breakline(char *input, int *count)
     int c = 0;
     char *p;
     char **rval = calloc(sizeof(char *), 1);
+    char **tmp;
 
     while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
         if (!*p) {
             continue;
         }
         c++;
-        rval = realloc(rval, sizeof(*rval) * (c + 1));
-        if (!rval) {
+        tmp = realloc(rval, sizeof(*rval) * (c + 1));
+        if (!tmp) {
+            free(rval);
+            rval = NULL;
             c = 0;
             break;
+        } else {
+            rval = tmp;
         }
         rval[c - 1] = p;
         rval[c] = NULL;
commit ba7806ad92a2f6b1625cfa67d44dc1b71e3be44e
Author: Pavel Borzenkov <pavel.borzenkov at gmail.com>
Date:   Mon Oct 31 22:53:37 2011 +0400

    cmd: Fix potential NULL pointer dereference
    
    Signed-off-by: Pavel Borzenkov <pavel.borzenkov at gmail.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/cmd.c b/cmd.c
index a6e3ef4..75415d8 100644
--- a/cmd.c
+++ b/cmd.c
@@ -47,7 +47,7 @@ compare(const void *a, const void *b)
 
 void add_command(const cmdinfo_t *ci)
 {
-    cmdtab = realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab));
+    cmdtab = g_realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab));
     cmdtab[ncmds - 1] = *ci;
     qsort(cmdtab, ncmds, sizeof(*cmdtab), compare);
 }
@@ -122,12 +122,7 @@ find_command(
 
 void add_user_command(char *optarg)
 {
-    ncmdline++;
-    cmdline = realloc(cmdline, ncmdline * sizeof(char *));
-    if (!cmdline) {
-        perror("realloc");
-        exit(1);
-    }
+    cmdline = g_realloc(cmdline, ++ncmdline * sizeof(char *));
     cmdline[ncmdline-1] = optarg;
 }
 
@@ -190,7 +185,7 @@ void command_loop(void)
         doneline(input, v);
     }
     if (cmdline) {
-        free(cmdline);
+        g_free(cmdline);
         return;
     }
 
commit 81beeec429f6bb8b0323e418a6aeef1a17b0cefa
Author: Pavel Borzenkov <pavel.borzenkov at gmail.com>
Date:   Mon Oct 31 22:53:36 2011 +0400

    cmd: Fix coding style in cmd.c
    
    Before the next patches, fix coding style of the affected functions.
    
    Signed-off-by: Pavel Borzenkov <pavel.borzenkov at gmail.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/cmd.c b/cmd.c
index f77897e..a6e3ef4 100644
--- a/cmd.c
+++ b/cmd.c
@@ -45,13 +45,11 @@ compare(const void *a, const void *b)
 		      ((const cmdinfo_t *)b)->name);
 }
 
-void
-add_command(
-	const cmdinfo_t	*ci)
+void add_command(const cmdinfo_t *ci)
 {
-	cmdtab = realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab));
-	cmdtab[ncmds - 1] = *ci;
-	qsort(cmdtab, ncmds, sizeof(*cmdtab), compare);
+    cmdtab = realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab));
+    cmdtab[ncmds - 1] = *ci;
+    qsort(cmdtab, ncmds, sizeof(*cmdtab), compare);
 }
 
 static int
@@ -122,16 +120,15 @@ find_command(
 	return NULL;
 }
 
-void
-add_user_command(char *optarg)
+void add_user_command(char *optarg)
 {
-	ncmdline++;
-	cmdline = realloc(cmdline, sizeof(char*) * (ncmdline));
-	if (!cmdline) {
-		perror("realloc");
-		exit(1);
-	}
-	cmdline[ncmdline-1] = optarg;
+    ncmdline++;
+    cmdline = realloc(cmdline, ncmdline * sizeof(char *));
+    if (!cmdline) {
+        perror("realloc");
+        exit(1);
+    }
+    cmdline[ncmdline-1] = optarg;
 }
 
 static int
@@ -160,45 +157,44 @@ static void prep_fetchline(void *opaque)
 
 static char *get_prompt(void);
 
-void
-command_loop(void)
+void command_loop(void)
 {
-	int		c, i, j = 0, done = 0, fetchable = 0, prompted = 0;
-	char		*input;
-	char		**v;
-	const cmdinfo_t	*ct;
-
-	for (i = 0; !done && i < ncmdline; i++) {
-		input = strdup(cmdline[i]);
-		if (!input) {
-			fprintf(stderr,
-				_("cannot strdup command '%s': %s\n"),
-				cmdline[i], strerror(errno));
-			exit(1);
-		}
-		v = breakline(input, &c);
-		if (c) {
-			ct = find_command(v[0]);
-			if (ct) {
-				if (ct->flags & CMD_FLAG_GLOBAL)
-					done = command(ct, c, v);
-				else {
-					j = 0;
-					while (!done && (j = args_command(j)))
-						done = command(ct, c, v);
-				}
-			} else
-				fprintf(stderr, _("command \"%s\" not found\n"),
-					v[0]);
-		}
-		doneline(input, v);
-	}
-	if (cmdline) {
-		free(cmdline);
-		return;
+    int c, i, j = 0, done = 0, fetchable = 0, prompted = 0;
+    char *input;
+    char **v;
+    const cmdinfo_t *ct;
+
+    for (i = 0; !done && i < ncmdline; i++) {
+        input = strdup(cmdline[i]);
+        if (!input) {
+            fprintf(stderr, _("cannot strdup command '%s': %s\n"),
+                    cmdline[i], strerror(errno));
+            exit(1);
+        }
+        v = breakline(input, &c);
+        if (c) {
+            ct = find_command(v[0]);
+            if (ct) {
+                if (ct->flags & CMD_FLAG_GLOBAL) {
+                    done = command(ct, c, v);
+                } else {
+                    j = 0;
+                    while (!done && (j = args_command(j))) {
+                        done = command(ct, c, v);
+                    }
+                }
+            } else {
+                fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
+            }
 	}
+        doneline(input, v);
+    }
+    if (cmdline) {
+        free(cmdline);
+        return;
+    }
 
-	while (!done) {
+    while (!done) {
         if (!prompted) {
             printf("%s", get_prompt());
             fflush(stdout);
@@ -212,22 +208,24 @@ command_loop(void)
         if (!fetchable) {
             continue;
         }
-		if ((input = fetchline()) == NULL)
-			break;
-		v = breakline(input, &c);
-		if (c) {
-			ct = find_command(v[0]);
-			if (ct)
-				done = command(ct, c, v);
-			else
-				fprintf(stderr, _("command \"%s\" not found\n"),
-					v[0]);
-		}
-		doneline(input, v);
+        input = fetchline();
+        if (input == NULL) {
+            break;
+        }
+        v = breakline(input, &c);
+        if (c) {
+            ct = find_command(v[0]);
+            if (ct) {
+                done = command(ct, c, v);
+            } else {
+                fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
+            }
+        }
+        doneline(input, v);
 
         prompted = 0;
         fetchable = 0;
-	}
+    }
     qemu_aio_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL, NULL, NULL);
 }
 
@@ -331,29 +329,27 @@ static char *qemu_strsep(char **input, const char *delim)
     return result;
 }
 
-char **
-breakline(
-	char	*input,
-	int	*count)
+char **breakline(char *input, int *count)
 {
-	int	c = 0;
-	char	*p;
-	char	**rval = calloc(sizeof(char *), 1);
-
-	while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
-		if (!*p)
-			continue;
-		c++;
-		rval = realloc(rval, sizeof(*rval) * (c + 1));
-		if (!rval) {
-			c = 0;
-			break;
-		}
-		rval[c - 1] = p;
-		rval[c] = NULL;
-	}
-	*count = c;
-	return rval;
+    int c = 0;
+    char *p;
+    char **rval = calloc(sizeof(char *), 1);
+
+    while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
+        if (!*p) {
+            continue;
+        }
+        c++;
+        rval = realloc(rval, sizeof(*rval) * (c + 1));
+        if (!rval) {
+            c = 0;
+            break;
+        }
+        rval[c - 1] = p;
+        rval[c] = NULL;
+    }
+    *count = c;
+    return rval;
 }
 
 void
commit 41bf234d8e35e9273290df278e2aeb88c0c50a4f
Author: Rabin Vincent <rabin at rab.in>
Date:   Sun Nov 6 16:01:08 2011 +0000

    arm_gic: handle banked enable bits for per-cpu interrupts
    
    The first enable set/clear register (which controls the PPIs and SGIs)
    is supposed to be banked for each processor.  Currently it is just
    handled globally and this prevents recent SMP Linux kernels from
    booting, because CPU0 stops receiving localtimer interrupts when CPU1
    disables them locally.
    
    To fix this, allow the enable bits to be enabled per-cpu.  For SPIs,
    always enable/disable ALL_CPU_MASK.
    
    Signed-off-by: Rabin Vincent <rabin at rab.in>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 8dd8742..f3f3516 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -37,9 +37,8 @@ static const uint8_t gic_id[] =
 
 typedef struct gic_irq_state
 {
-    /* ??? The documentation seems to imply the enable bits are global, even
-       for per-cpu interrupts.  This seems strange.  */
-    unsigned enabled:1;
+    /* The enable bits are only banked for per-cpu interrupts.  */
+    unsigned enabled:NCPU;
     unsigned pending:NCPU;
     unsigned active:NCPU;
     unsigned level:NCPU;
@@ -54,9 +53,9 @@ typedef struct gic_irq_state
 #define NUM_CPU(s) 1
 #endif
 
-#define GIC_SET_ENABLED(irq) s->irq_state[irq].enabled = 1
-#define GIC_CLEAR_ENABLED(irq) s->irq_state[irq].enabled = 0
-#define GIC_TEST_ENABLED(irq) s->irq_state[irq].enabled
+#define GIC_SET_ENABLED(irq, cm) s->irq_state[irq].enabled |= (cm)
+#define GIC_CLEAR_ENABLED(irq, cm) s->irq_state[irq].enabled &= ~(cm)
+#define GIC_TEST_ENABLED(irq, cm) ((s->irq_state[irq].enabled & (cm)) != 0)
 #define GIC_SET_PENDING(irq, cm) s->irq_state[irq].pending |= (cm)
 #define GIC_CLEAR_PENDING(irq, cm) s->irq_state[irq].pending &= ~(cm)
 #define GIC_TEST_PENDING(irq, cm) ((s->irq_state[irq].pending & (cm)) != 0)
@@ -128,7 +127,7 @@ static void gic_update(gic_state *s)
         best_prio = 0x100;
         best_irq = 1023;
         for (irq = 0; irq < GIC_NIRQ; irq++) {
-            if (GIC_TEST_ENABLED(irq) && GIC_TEST_PENDING(irq, cm)) {
+            if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) {
                 if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
                     best_prio = GIC_GET_PRIORITY(irq, cpu);
                     best_irq = irq;
@@ -171,7 +170,7 @@ static void gic_set_irq(void *opaque, int irq, int level)
 
     if (level) {
         GIC_SET_LEVEL(irq, ALL_CPU_MASK);
-        if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq)) {
+        if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq, ALL_CPU_MASK)) {
             DPRINTF("Set %d pending mask %x\n", irq, GIC_TARGET(irq));
             GIC_SET_PENDING(irq, GIC_TARGET(irq));
         }
@@ -221,7 +220,7 @@ static void gic_complete_irq(gic_state * s, int cpu, int irq)
     if (irq != 1023) {
         /* Mark level triggered interrupts as pending if they are still
            raised.  */
-        if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq)
+        if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm)
                 && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
             DPRINTF("Set %d pending mask %x\n", irq, cm);
             GIC_SET_PENDING(irq, cm);
@@ -280,7 +279,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 8; i++) {
-            if (GIC_TEST_ENABLED(irq + i)) {
+            if (GIC_TEST_ENABLED(irq + i, cm)) {
                 res |= (1 << i);
             }
         }
@@ -412,9 +411,12 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
         for (i = 0; i < 8; i++) {
             if (value & (1 << i)) {
                 int mask = (irq < 32) ? (1 << cpu) : GIC_TARGET(irq);
-                if (!GIC_TEST_ENABLED(irq + i))
+                int cm = (irq < 32) ? (1 << cpu) : ALL_CPU_MASK;
+
+                if (!GIC_TEST_ENABLED(irq + i, cm)) {
                     DPRINTF("Enabled IRQ %d\n", irq + i);
-                GIC_SET_ENABLED(irq + i);
+                }
+                GIC_SET_ENABLED(irq + i, cm);
                 /* If a raised level triggered IRQ enabled then mark
                    is as pending.  */
                 if (GIC_TEST_LEVEL(irq + i, mask)
@@ -433,9 +435,12 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
           value = 0;
         for (i = 0; i < 8; i++) {
             if (value & (1 << i)) {
-                if (GIC_TEST_ENABLED(irq + i))
+                int cm = (irq < 32) ? (1 << cpu) : ALL_CPU_MASK;
+
+                if (GIC_TEST_ENABLED(irq + i, cm)) {
                     DPRINTF("Disabled IRQ %d\n", irq + i);
-                GIC_CLEAR_ENABLED(irq + i);
+                }
+                GIC_CLEAR_ENABLED(irq + i, cm);
             }
         }
     } else if (offset < 0x280) {
@@ -638,7 +643,7 @@ static void gic_reset(gic_state *s)
 #endif
     }
     for (i = 0; i < 16; i++) {
-        GIC_SET_ENABLED(i);
+        GIC_SET_ENABLED(i, ALL_CPU_MASK);
         GIC_SET_TRIGGER(i);
     }
 #ifdef NVIC
commit 273e4e03b3413fd489601cd9d8ba407ccb3b4130
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Nov 4 17:21:53 2011 +0100

    vvfat: reorganize computation of disk geometry
    
    First determine FAT12/16/32, then compute geometry from that for both
    FDD and HDD.  For 1.44MB floppies, and 2.88MB floppies using FAT16,
    change to 1 sector/cluster.  The default remains 2.88MB with FAT12
    and 2 sectors/cluster.  Both DOS and mkdosfs by default format a 2.88MB
    floppy as FAT12.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vvfat.c b/block/vvfat.c
index faf2947..8511fe5 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -982,7 +982,6 @@ static int is_consistent(BDRVVVFATState *s);
 static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
 {
     BDRVVVFATState *s = bs->opaque;
-    int floppy = 0;
     int i;
 
 #ifdef DEBUG
@@ -996,11 +995,8 @@ DLOG(if (stderr == NULL) {
 
     s->bs = bs;
 
-    s->fat_type=16;
     /* LATER TODO: if FAT32, adjust */
     s->sectors_per_cluster=0x10;
-    /* 504MB disk*/
-    bs->cyls=1024; bs->heads=16; bs->secs=63;
 
     s->current_cluster=0xffffffff;
 
@@ -1015,14 +1011,6 @@ DLOG(if (stderr == NULL) {
     if (!strstart(dirname, "fat:", NULL))
 	return -1;
 
-    if (strstr(dirname, ":floppy:")) {
-	floppy = 1;
-	s->fat_type = 12;
-	s->first_sectors_number = 1;
-	s->sectors_per_cluster=2;
-	bs->cyls = 80; bs->heads = 2; bs->secs = 36;
-    }
-
     if (strstr(dirname, ":32:")) {
 	fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n");
 	s->fat_type = 32;
@@ -1030,7 +1018,27 @@ DLOG(if (stderr == NULL) {
 	s->fat_type = 16;
     } else if (strstr(dirname, ":12:")) {
 	s->fat_type = 12;
-	bs->secs = 18;
+    }
+
+    if (strstr(dirname, ":floppy:")) {
+	/* 1.44MB or 2.88MB floppy.  2.88MB can be FAT12 (default) or FAT16. */
+	if (!s->fat_type) {
+	    s->fat_type = 12;
+	    bs->secs = 36;
+	    s->sectors_per_cluster=2;
+	} else {
+	    bs->secs=(s->fat_type == 12 ? 18 : 36);
+	    s->sectors_per_cluster=1;
+	}
+	s->first_sectors_number = 1;
+	bs->cyls=80; bs->heads=2;
+    } else {
+	/* 32MB or 504MB disk*/
+	if (!s->fat_type) {
+	    s->fat_type = 16;
+	}
+	bs->cyls=(s->fat_type == 12 ? 64 : 1024);
+	bs->heads=16; bs->secs=63;
     }
 
     s->sector_count=bs->cyls*bs->heads*bs->secs-(s->first_sectors_number-1);
@@ -1058,10 +1066,10 @@ DLOG(if (stderr == NULL) {
 
     if(s->first_sectors_number==0x40)
 	init_mbr(s);
-
-    /* for some reason or other, MS-DOS does not like to know about CHS... */
-    if (floppy)
+    else {
+        /* MS-DOS does not like to know about CHS (?). */
 	bs->heads = bs->cyls = bs->secs = 0;
+    }
 
     //    assert(is_consistent(s));
     qemu_co_mutex_init(&s->lock);
commit d71cff42e4cd614986e2d0b8ded7aa3acaf28d92
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Oct 5 09:12:07 2011 +0200

    vvfat: do not hardcode sector counts in error message
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vvfat.c b/block/vvfat.c
index 3e7b407..faf2947 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -916,11 +916,8 @@ static int init_directories(BDRVVVFATState* s,
 	cluster = mapping->end;
 
 	if(cluster > s->cluster_count) {
-	    fprintf(stderr,"Directory does not fit in FAT%d (capacity %s)\n",
-		    s->fat_type,
-		    s->fat_type == 12 ? s->sector_count == 2880 ? "1.44 MB"
-								: "2.88 MB"
-				      : "504MB");
+	    fprintf(stderr,"Directory does not fit in FAT%d (capacity %.2f MB)\n",
+		    s->fat_type, s->sector_count / 2000.0);
 	    return -EINVAL;
 	}
 
commit 5a742b55576c044a6fe07b42937272e553503ddd
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Oct 5 09:12:06 2011 +0200

    vvfat: unify and correct computation of sector count
    
    The sector count is stored in the partition and hence must not include the
    sectors before its start.  At the same time, remove the useless special
    casing for 1.44 MB floppies.  This fixes fsck on VVFAT hard disks,
    which otherwise tries to seek past the end of the disk.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vvfat.c b/block/vvfat.c
index 1f7cc48..3e7b407 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -1026,8 +1026,6 @@ DLOG(if (stderr == NULL) {
 	bs->cyls = 80; bs->heads = 2; bs->secs = 36;
     }
 
-    s->sector_count=bs->cyls*bs->heads*bs->secs;
-
     if (strstr(dirname, ":32:")) {
 	fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n");
 	s->fat_type = 32;
@@ -1035,9 +1033,11 @@ DLOG(if (stderr == NULL) {
 	s->fat_type = 16;
     } else if (strstr(dirname, ":12:")) {
 	s->fat_type = 12;
-	s->sector_count=2880;
+	bs->secs = 18;
     }
 
+    s->sector_count=bs->cyls*bs->heads*bs->secs-(s->first_sectors_number-1);
+
     if (strstr(dirname, ":rw:")) {
 	if (enable_write_target(s))
 	    return -1;
commit aad37c06dda2cd6ab950648435b24ef7776574b0
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Oct 5 09:12:05 2011 +0200

    vvfat: need to use first_sectors_number to distinguish fdd/hdd
    
    This is consistent with what "real" floppies have, so file(1)
    now actually recognizes the VVFAT image as a 1.44 MB floppy.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vvfat.c b/block/vvfat.c
index 9f851b0..1f7cc48 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -954,7 +954,7 @@ static int init_directories(BDRVVVFATState* s,
     bootsector->number_of_fats=0x2; /* number of FATs */
     bootsector->root_entries=cpu_to_le16(s->sectors_of_root_directory*0x10);
     bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count);
-    bootsector->media_type=(s->fat_type!=12?0xf8:s->sector_count==5760?0xf9:0xf8); /* media descriptor */
+    bootsector->media_type=(s->first_sectors_number>1?0xf8:0xf0); /* media descriptor (f8=hd, f0=3.5 fd)*/
     s->fat.pointer[0] = bootsector->media_type;
     bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
     bootsector->sectors_per_track=cpu_to_le16(s->bs->secs);
@@ -963,7 +963,7 @@ static int init_directories(BDRVVVFATState* s,
     bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0);
 
     /* LATER TODO: if FAT32, this is wrong */
-    bootsector->u.fat16.drive_number=s->fat_type==12?0:0x80; /* assume this is hda (TODO) */
+    bootsector->u.fat16.drive_number=s->first_sectors_number==1?0:0x80; /* fda=0, hda=0x80 */
     bootsector->u.fat16.current_head=0;
     bootsector->u.fat16.signature=0x29;
     bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
commit e654bfe4c1211754d52b324a505ac46c2bfe2069
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Oct 5 09:12:04 2011 +0200

    vvfat: do not fail if the disk has spare sectors
    
    If the number of "faked sectors" + the number of sectors that are
    part of a cluster does not sum up to the total number of sectors,
    qemu-img convert fails.  Read these spare sectors as all zeros.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vvfat.c b/block/vvfat.c
index 75d0dc0..9f851b0 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -1245,7 +1245,7 @@ static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
     int i;
 
     for(i=0;i<nb_sectors;i++,sector_num++) {
-	if (sector_num >= s->sector_count)
+	if (sector_num >= bs->total_sectors)
 	   return -1;
 	if (s->qcow) {
 	    int n;
@@ -1271,7 +1271,7 @@ DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
 	    uint32_t sector=sector_num-s->faked_sectors,
 	    sector_offset_in_cluster=(sector%s->sectors_per_cluster),
 	    cluster_num=sector/s->sectors_per_cluster;
-	    if(read_cluster(s, cluster_num) != 0) {
+	    if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
 		/* LATER TODO: strict: return -1; */
 		memset(buf+i*0x200,0,0x200);
 		continue;
commit 2b6a43a835e5082dedc6a5eea39a59463f97c81c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Oct 5 09:12:03 2011 +0200

    vvfat: fix out of bounds array_get usage
    
    When reading the address of the first free entry, you cannot
    use array_get without first marking all entries as occupied.
    
    This is visible if you change the sectors per cluster on a
    floppy from 2 to 1.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vvfat.c b/block/vvfat.c
index e1fcdbc..75d0dc0 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -799,6 +799,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
 	/* root directory */
 	int cur = s->directory.next;
 	array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1);
+	s->directory.next = ROOT_ENTRIES;
 	memset(array_get(&(s->directory), cur), 0,
 		(ROOT_ENTRIES - cur) * sizeof(direntry_t));
     }
commit 756f51e408febecdaff041f096527b820e857762
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Wed Nov 2 16:36:21 2011 +0800

    block/cloop: Use g_free instead of free
    
    Fix mismatching allocation and deallocation: g_free should be used to pair with
    g_malloc.
    
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Reviewed_by: Ray Wang <raywang at linux.vnet.ibm.com>
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/cloop.c b/block/cloop.c
index 799b6c2..7570eb8 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -171,10 +171,10 @@ static void cloop_close(BlockDriverState *bs)
 {
     BDRVCloopState *s = bs->opaque;
     if (s->n_blocks > 0) {
-        free(s->offsets);
+        g_free(s->offsets);
     }
-    free(s->compressed_block);
-    free(s->uncompressed_block);
+    g_free(s->compressed_block);
+    g_free(s->uncompressed_block);
     inflateEnd(&s->zstream);
 }
 
commit 5b47b7c3d38e2fe23948313a8a6af227ba6d46a5
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Wed Nov 2 16:36:20 2011 +0800

    block/cloop: Fix coding style
    
    Fix coding style in block/cloop.c.
    
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Reviewed_by: Ray Wang <raywang at linux.vnet.ibm.com>
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/cloop.c b/block/cloop.c
index 775f8a9..799b6c2 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -30,7 +30,7 @@ typedef struct BDRVCloopState {
     CoMutex lock;
     uint32_t block_size;
     uint32_t n_blocks;
-    uint64_t* offsets;
+    uint64_t *offsets;
     uint32_t sectors_per_block;
     uint32_t current_block;
     uint8_t *compressed_block;
@@ -40,21 +40,23 @@ typedef struct BDRVCloopState {
 
 static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
 {
-    const char* magic_version_2_0="#!/bin/sh\n"
-	"#V2.0 Format\n"
-	"modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n";
-    int length=strlen(magic_version_2_0);
-    if(length>buf_size)
-	length=buf_size;
-    if(!memcmp(magic_version_2_0,buf,length))
-	return 2;
+    const char *magic_version_2_0 = "#!/bin/sh\n"
+        "#V2.0 Format\n"
+        "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n";
+    int length = strlen(magic_version_2_0);
+    if (length > buf_size) {
+        length = buf_size;
+    }
+    if (!memcmp(magic_version_2_0, buf, length)) {
+        return 2;
+    }
     return 0;
 }
 
 static int cloop_open(BlockDriverState *bs, int flags)
 {
     BDRVCloopState *s = bs->opaque;
-    uint32_t offsets_size,max_compressed_block_size=1,i;
+    uint32_t offsets_size, max_compressed_block_size = 1, i;
 
     bs->read_only = 1;
 
@@ -74,26 +76,28 @@ static int cloop_open(BlockDriverState *bs, int flags)
     s->offsets = g_malloc(offsets_size);
     if (bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size) <
             offsets_size) {
-	goto cloop_close;
+        goto cloop_close;
     }
     for(i=0;i<s->n_blocks;i++) {
-	s->offsets[i]=be64_to_cpu(s->offsets[i]);
-	if(i>0) {
-	    uint32_t size=s->offsets[i]-s->offsets[i-1];
-	    if(size>max_compressed_block_size)
-		max_compressed_block_size=size;
-	}
+        s->offsets[i] = be64_to_cpu(s->offsets[i]);
+        if (i > 0) {
+            uint32_t size = s->offsets[i] - s->offsets[i - 1];
+            if (size > max_compressed_block_size) {
+                max_compressed_block_size = size;
+            }
+        }
     }
 
     /* initialize zlib engine */
-    s->compressed_block = g_malloc(max_compressed_block_size+1);
+    s->compressed_block = g_malloc(max_compressed_block_size + 1);
     s->uncompressed_block = g_malloc(s->block_size);
-    if(inflateInit(&s->zstream) != Z_OK)
-	goto cloop_close;
-    s->current_block=s->n_blocks;
+    if (inflateInit(&s->zstream) != Z_OK) {
+        goto cloop_close;
+    }
+    s->current_block = s->n_blocks;
 
     s->sectors_per_block = s->block_size/512;
-    bs->total_sectors = s->n_blocks*s->sectors_per_block;
+    bs->total_sectors = s->n_blocks * s->sectors_per_block;
     qemu_co_mutex_init(&s->lock);
     return 0;
 
@@ -105,27 +109,30 @@ static inline int cloop_read_block(BlockDriverState *bs, int block_num)
 {
     BDRVCloopState *s = bs->opaque;
 
-    if(s->current_block != block_num) {
-	int ret;
-        uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num];
+    if (s->current_block != block_num) {
+        int ret;
+        uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num];
 
         ret = bdrv_pread(bs->file, s->offsets[block_num], s->compressed_block,
                          bytes);
-        if (ret != bytes)
+        if (ret != bytes) {
             return -1;
+        }
+
+        s->zstream.next_in = s->compressed_block;
+        s->zstream.avail_in = bytes;
+        s->zstream.next_out = s->uncompressed_block;
+        s->zstream.avail_out = s->block_size;
+        ret = inflateReset(&s->zstream);
+        if (ret != Z_OK) {
+            return -1;
+        }
+        ret = inflate(&s->zstream, Z_FINISH);
+        if (ret != Z_STREAM_END || s->zstream.total_out != s->block_size) {
+            return -1;
+        }
 
-	s->zstream.next_in = s->compressed_block;
-	s->zstream.avail_in = bytes;
-	s->zstream.next_out = s->uncompressed_block;
-	s->zstream.avail_out = s->block_size;
-	ret = inflateReset(&s->zstream);
-	if(ret != Z_OK)
-	    return -1;
-	ret = inflate(&s->zstream, Z_FINISH);
-	if(ret != Z_STREAM_END || s->zstream.total_out != s->block_size)
-	    return -1;
-
-	s->current_block = block_num;
+        s->current_block = block_num;
     }
     return 0;
 }
@@ -136,12 +143,15 @@ static int cloop_read(BlockDriverState *bs, int64_t sector_num,
     BDRVCloopState *s = bs->opaque;
     int i;
 
-    for(i=0;i<nb_sectors;i++) {
-	uint32_t sector_offset_in_block=((sector_num+i)%s->sectors_per_block),
-	    block_num=(sector_num+i)/s->sectors_per_block;
-	if(cloop_read_block(bs, block_num) != 0)
-	    return -1;
-	memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512);
+    for (i = 0; i < nb_sectors; i++) {
+        uint32_t sector_offset_in_block =
+            ((sector_num + i) % s->sectors_per_block),
+            block_num = (sector_num + i) / s->sectors_per_block;
+        if (cloop_read_block(bs, block_num) != 0) {
+            return -1;
+        }
+        memcpy(buf + i * 512,
+            s->uncompressed_block + sector_offset_in_block * 512, 512);
     }
     return 0;
 }
@@ -160,20 +170,21 @@ static coroutine_fn int cloop_co_read(BlockDriverState *bs, int64_t sector_num,
 static void cloop_close(BlockDriverState *bs)
 {
     BDRVCloopState *s = bs->opaque;
-    if(s->n_blocks>0)
-	free(s->offsets);
+    if (s->n_blocks > 0) {
+        free(s->offsets);
+    }
     free(s->compressed_block);
     free(s->uncompressed_block);
     inflateEnd(&s->zstream);
 }
 
 static BlockDriver bdrv_cloop = {
-    .format_name	= "cloop",
-    .instance_size	= sizeof(BDRVCloopState),
-    .bdrv_probe		= cloop_probe,
-    .bdrv_open		= cloop_open,
-    .bdrv_read          = cloop_co_read,
-    .bdrv_close		= cloop_close,
+    .format_name    = "cloop",
+    .instance_size  = sizeof(BDRVCloopState),
+    .bdrv_probe     = cloop_probe,
+    .bdrv_open      = cloop_open,
+    .bdrv_read      = cloop_co_read,
+    .bdrv_close     = cloop_close,
 };
 
 static void bdrv_cloop_init(void)
commit acae6f1c4c1dae1b7e059751347ca4225b01a391
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Oct 28 05:28:13 2011 -0400

    dma: Avoid reentrancy in DMA transfer handlers
    
    With the conversion of the block layer to coroutines, bdrv_read/write
    have changed to run a nested event loop that calls qemu_bh_poll.
    Consequently a scheduled BH can be called while a DMA transfer handler
    runs and this means that DMA_run becomes reentrant.
    
    Devices haven't been designed to cope with that, so instead of running a
    nested transfer handler just wait for the next invocation of the BH from the
    main loop.
    
    This fixes some problems with the floppy device.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/dma.c b/hw/dma.c
index 8a7302a..0a9322d 100644
--- a/hw/dma.c
+++ b/hw/dma.c
@@ -358,6 +358,14 @@ static void DMA_run (void)
     struct dma_cont *d;
     int icont, ichan;
     int rearm = 0;
+    static int running = 0;
+
+    if (running) {
+        rearm = 1;
+        goto out;
+    } else {
+        running = 1;
+    }
 
     d = dma_controllers;
 
@@ -374,6 +382,8 @@ static void DMA_run (void)
         }
     }
 
+    running = 0;
+out:
     if (rearm)
         qemu_bh_schedule_idle(dma_bh);
 }
commit 67403dbba76fb294fb3a2317227f4b77037145cc
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Oct 31 11:49:21 2011 +0100

    qemu-io: Fix multiwrite_f error handling
    
    Without this fix, some qiovs can be leaked if an error occurs. Also a semicolon
    at the end of the command line would make the code walk beyond the end of argv.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-io.c b/qemu-io.c
index 1c49d44..de26422 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -960,21 +960,21 @@ static int multiwrite_f(int argc, char **argv)
     buf = g_malloc0(nr_reqs * sizeof(*buf));
     qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
 
-    for (i = 0; i < nr_reqs; i++) {
+    for (i = 0; i < nr_reqs && optind < argc; i++) {
         int j;
 
         /* Read the offset of the request */
         offset = cvtnum(argv[optind]);
         if (offset < 0) {
             printf("non-numeric offset argument -- %s\n", argv[optind]);
-            return 0;
+            goto out;
         }
         optind++;
 
         if (offset & 0x1ff) {
             printf("offset %lld is not sector aligned\n",
                    (long long)offset);
-            return 0;
+            goto out;
         }
 
         if (i == 0) {
@@ -1005,6 +1005,9 @@ static int multiwrite_f(int argc, char **argv)
         pattern++;
     }
 
+    /* If there were empty requests at the end, ignore them */
+    nr_reqs = i;
+
     gettimeofday(&t1, NULL);
     cnt = do_aio_multiwrite(reqs, nr_reqs, &total);
     gettimeofday(&t2, NULL);
commit f2360620fbebc24a0e2d58d0038ed3a007d28521
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Oct 31 11:36:32 2011 +0100

    qemu-io: Handle create_iovec errors
    
    Callers of create_iovec() didn't check for failure and continued with
    uninitialised data in error cases. This patch adds checks to each call.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-io.c b/qemu-io.c
index 5af887e..1c49d44 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -596,6 +596,9 @@ static int readv_f(int argc, char **argv)
 
     nr_iov = argc - optind;
     buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
+    if (buf == NULL) {
+        return 0;
+    }
 
     gettimeofday(&t1, NULL);
     cnt = do_aio_readv(&qiov, offset, &total);
@@ -850,6 +853,9 @@ static int writev_f(int argc, char **argv)
 
     nr_iov = argc - optind;
     buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
+    if (buf == NULL) {
+        return 0;
+    }
 
     gettimeofday(&t1, NULL);
     cnt = do_aio_writev(&qiov, offset, &total);
@@ -950,8 +956,8 @@ static int multiwrite_f(int argc, char **argv)
         }
     }
 
-    reqs = g_malloc(nr_reqs * sizeof(*reqs));
-    buf = g_malloc(nr_reqs * sizeof(*buf));
+    reqs = g_malloc0(nr_reqs * sizeof(*reqs));
+    buf = g_malloc0(nr_reqs * sizeof(*buf));
     qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
 
     for (i = 0; i < nr_reqs; i++) {
@@ -985,8 +991,12 @@ static int multiwrite_f(int argc, char **argv)
         nr_iov = j - optind;
 
         /* Build request */
+        buf[i] = create_iovec(&qiovs[i], &argv[optind], nr_iov, pattern);
+        if (buf[i] == NULL) {
+            goto out;
+        }
+
         reqs[i].qiov = &qiovs[i];
-        buf[i] = create_iovec(reqs[i].qiov, &argv[optind], nr_iov, pattern);
         reqs[i].sector = offset >> 9;
         reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
 
@@ -1014,7 +1024,9 @@ static int multiwrite_f(int argc, char **argv)
 out:
     for (i = 0; i < nr_reqs; i++) {
         qemu_io_free(buf[i]);
-        qemu_iovec_destroy(&qiovs[i]);
+        if (reqs[i].qiov != NULL) {
+            qemu_iovec_destroy(&qiovs[i]);
+        }
     }
     g_free(buf);
     g_free(reqs);
@@ -1185,6 +1197,10 @@ static int aio_read_f(int argc, char **argv)
 
     nr_iov = argc - optind;
     ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
+    if (ctx->buf == NULL) {
+        free(ctx);
+        return 0;
+    }
 
     gettimeofday(&ctx->t1, NULL);
     acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
@@ -1280,6 +1296,10 @@ static int aio_write_f(int argc, char **argv)
 
     nr_iov = argc - optind;
     ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
+    if (ctx->buf == NULL) {
+        free(ctx);
+        return 0;
+    }
 
     gettimeofday(&ctx->t1, NULL);
     acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
commit 932eacc158c064935c7bab920c88a93a629e1ca4
Merge: c51d9cb... 556ba66...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Wed Nov 2 20:52:23 2011 +0000

    Merge branch 'xtensa' of git://jcmvbkbc.spb.ru/dumb/qemu-xtensa
    
    * 'xtensa' of git://jcmvbkbc.spb.ru/dumb/qemu-xtensa:
      xtensa_lx60: fix build date code and change memory region names
      xtensa_lx60: pass kernel arguments from -append
      xtensa_lx60: add FLASH support
      target-xtensa: raise an exception for invalid and reserved opcodes
      target-xtensa: handle cache options in the overlay tool
      target-xtensa: mask out undefined bits of WINDOWSTART SR

commit c51d9cb5b6e2fde9878d2be23dab389c2882de93
Merge: 42dfb09... 9195b2c...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Wed Nov 2 20:52:13 2011 +0000

    Merge branch 'tci' of git://qemu.weilnetz.de/qemu
    
    * 'tci' of git://qemu.weilnetz.de/qemu:
      tcg: Add tcg interpreter to configure / make
      tcg: Add tci disassembler
      tcg: Add interpreter for bytecode
      tcg: Add bytecode generator for tcg interpreter
      tcg: Make ARRAY_SIZE(tcg_op_defs) globally available
      tcg: TCG targets may define tcg_qemu_tb_exec

commit 42dfb09510fa8725bc75b48a4825eaf66b21958a
Merge: 0e9a2ea... 779b5b0...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Nov 2 12:30:00 2011 -0500

    Merge remote-tracking branch 'aneesh/for-upstream-8' into staging

commit 0e9a2ea2e4c27d0a122a74b96f38a5c0c4c3c2a9
Merge: f2209eb... 08dafab...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Nov 2 12:28:59 2011 -0500

    Merge remote-tracking branch 'qemu-kvm-tmp/memory/int128' into staging

commit f2209eb854a016eabc444b45f6d6b1636949141f
Author: Bharata B Rao <bharata.rao at gmail.com>
Date:   Wed Nov 2 14:16:08 2011 +0530

    Fix X86 CPU topology in KVM mode
    
    apic id returned to guest kernel in ebx for cpuid(function=1) depends on
    CPUX86State->cpuid_apic_id which gets populated after the cpuid information
    is cached in the host kernel. This results in broken CPU topology in guest.
    
    Fix this by setting cpuid_apic_id before cpuid information is passed to
    the host kernel. This is done by moving the setting of cpuid_apic_id
    to cpu_x86_init() where it will work for both KVM as well as TCG modes.
    
    Acked-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Bharata B Rao <bharata.rao at gmail.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pc.c b/hw/pc.c
index eb4c2d8..25bfa85 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -941,7 +941,6 @@ static CPUState *pc_new_cpu(const char *cpu_model)
         exit(1);
     }
     if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) {
-        env->cpuid_apic_id = env->cpu_index;
         env->apic_state = apic_init(env, env->cpuid_apic_id);
     }
     qemu_register_reset(pc_cpu_reset, env);
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 6c6a167..2586aff 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1257,6 +1257,7 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
         cpu_x86_close(env);
         return NULL;
     }
+    env->cpuid_apic_id = env->cpu_index;
     mce_init(env);
 
     qemu_init_vcpu(env);
commit 18ebcc86f2e21c83efe26b09218c859234876465
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Nov 2 12:56:14 2011 +0100

    intel-hda: fix stream search
    
    commit ba43d28916c4f51c19bd7366089155ce81bee058 introduces a bug:
    The stream-not-found case doesn't error out any more, instead the
    code silently uses the first stream.  Fix it.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index 02def4c..10769e0 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -402,7 +402,7 @@ static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output,
             break;
         }
     }
-    if (st == NULL) {
+    if (s == 4) {
         return false;
     }
     if (st->bpl == NULL) {
commit 5bb23927761db0d48507c60f56c4e28f72f3c2a7
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Nov 2 13:19:40 2011 +0100

    virtio-blk: pass full status to the guest
    
    When SCSI passthrough is being used by the guest with virtio-blk, the
    guest is not able to detect disk failures.  This is because the status
    field is expected by the guest driver to include also the msg_status,
    host_status and driver_status fields, but the device is only passing
    down the SCSI status.
    
    The patch fixes this, and also makes sure that the guest always sees a
    CHECK_CONDITION status when there is valid sense data.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 2a5d1a9..19e89e7 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -16,6 +16,7 @@
 #include "trace.h"
 #include "blockdev.h"
 #include "virtio-blk.h"
+#include "scsi-defs.h"
 #ifdef __linux__
 # include <scsi/sg.h>
 #endif
@@ -231,7 +232,20 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
         status = VIRTIO_BLK_S_OK;
     }
 
-    stl_p(&req->scsi->errors, hdr.status);
+    /*
+     * From SCSI-Generic-HOWTO: "Some lower level drivers (e.g. ide-scsi)
+     * clear the masked_status field [hence status gets cleared too, see
+     * block/scsi_ioctl.c] even when a CHECK_CONDITION or COMMAND_TERMINATED
+     * status has occurred.  However they do set DRIVER_SENSE in driver_status
+     * field. Also a (sb_len_wr > 0) indicates there is a sense buffer.
+     */
+    if (hdr.status == 0 && hdr.sb_len_wr > 0) {
+        hdr.status = CHECK_CONDITION;
+    }
+
+    stl_p(&req->scsi->errors,
+          hdr.status | (hdr.msg_status << 8) |
+          (hdr.host_status << 16) | (hdr.driver_status << 24));
     stl_p(&req->scsi->residual, hdr.resid);
     stl_p(&req->scsi->sense_len, hdr.sb_len_wr);
     stl_p(&req->scsi->data_len, hdr.dxfer_len);
commit 779b5b04fd00c424ec181f3a7fa3ff61015ad7dc
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Nov 2 12:57:15 2011 +0530

    hw/9pfs: use g_vasprintf() instead of rolling our own
    
    Markus Armbruster <armbru at redhat.com> sent fixes for va_list vararg
    issues in v9fs_string_alloc_printf().  It turns out the function
    duplicates g_vasprintf() and can therefore be eliminated entirely.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    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 0777ece..01cf337 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -11,6 +11,9 @@
  *
  */
 
+#include <glib.h>
+#include <glib/gprintf.h>
+
 #include "hw/virtio.h"
 #include "hw/pc.h"
 #include "qemu_socket.h"
@@ -161,114 +164,16 @@ void v9fs_string_null(V9fsString *str)
     v9fs_string_free(str);
 }
 
-static int number_to_string(void *arg, char type)
-{
-    unsigned int ret = 0;
-
-    switch (type) {
-    case 'u': {
-        unsigned int num = *(unsigned int *)arg;
-
-        do {
-            ret++;
-            num = num/10;
-        } while (num);
-        break;
-    }
-    case 'U': {
-        unsigned long num = *(unsigned long *)arg;
-        do {
-            ret++;
-            num = num/10;
-        } while (num);
-        break;
-    }
-    default:
-        printf("Number_to_string: Unknown number format\n");
-        return -1;
-    }
-
-    return ret;
-}
-
-static int GCC_FMT_ATTR(2, 0)
-v9fs_string_alloc_printf(char **strp, const char *fmt, va_list ap)
-{
-    va_list ap2;
-    char *iter = (char *)fmt;
-    int len = 0;
-    int nr_args = 0;
-    char *arg_char_ptr;
-    unsigned int arg_uint;
-    unsigned long arg_ulong;
-
-    /* Find the number of %'s that denotes an argument */
-    for (iter = strstr(iter, "%"); iter; iter = strstr(iter, "%")) {
-        nr_args++;
-        iter++;
-    }
-
-    len = strlen(fmt) - 2*nr_args;
-
-    if (!nr_args) {
-        goto alloc_print;
-    }
-
-    va_copy(ap2, ap);
-
-    iter = (char *)fmt;
-
-    /* Now parse the format string */
-    for (iter = strstr(iter, "%"); iter; iter = strstr(iter, "%")) {
-        iter++;
-        switch (*iter) {
-        case 'u':
-            arg_uint = va_arg(ap2, unsigned int);
-            len += number_to_string((void *)&arg_uint, 'u');
-            break;
-        case 'l':
-            if (*++iter == 'u') {
-                arg_ulong = va_arg(ap2, unsigned long);
-                len += number_to_string((void *)&arg_ulong, 'U');
-            } else {
-                return -1;
-            }
-            break;
-        case 's':
-            arg_char_ptr = va_arg(ap2, char *);
-            len += strlen(arg_char_ptr);
-            break;
-        case 'c':
-            len += 1;
-            break;
-        default:
-            fprintf(stderr,
-		    "v9fs_string_alloc_printf:Incorrect format %c", *iter);
-            return -1;
-        }
-        iter++;
-    }
-
-alloc_print:
-    *strp = g_malloc((len + 1) * sizeof(**strp));
-
-    return vsprintf(*strp, fmt, ap);
-}
-
 void GCC_FMT_ATTR(2, 3)
 v9fs_string_sprintf(V9fsString *str, const char *fmt, ...)
 {
     va_list ap;
-    int err;
 
     v9fs_string_free(str);
 
     va_start(ap, fmt);
-    err = v9fs_string_alloc_printf(&str->data, fmt, ap);
-    BUG_ON(err == -1);
+    str->size = g_vasprintf(&str->data, fmt, ap);
     va_end(ap);
-
-    str->size = err;
 }
 
 void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
commit 556ba6684547f5f0aae60aaa2a16e39e43f9739d
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Oct 30 21:18:27 2011 +0400

    xtensa_lx60: fix build date code and change memory region names
    
    Fix date code to uses MMDDYYYY notation.
    Change memory region names to reflect specification that defines them.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c
index 069b21c..8947157 100644
--- a/hw/xtensa_lx60.c
+++ b/hw/xtensa_lx60.c
@@ -63,7 +63,7 @@ static uint64_t lx60_fpga_read(void *opaque, target_phys_addr_t addr,
 
     switch (addr) {
     case 0x0: /*build date code*/
-        return 0x27092011;
+        return 0x09272011;
 
     case 0x4: /*processor clock frequency, Hz*/
         return 10000000;
@@ -107,7 +107,7 @@ static Lx60FpgaState *lx60_fpga_init(MemoryRegion *address_space,
     Lx60FpgaState *s = g_malloc(sizeof(Lx60FpgaState));
 
     memory_region_init_io(&s->iomem, &lx60_fpga_ops, s,
-            "lx60-fpga", 0x10000);
+            "lx60.fpga", 0x10000);
     memory_region_add_subregion(address_space, base, &s->iomem);
     lx60_fpga_reset(s);
     qemu_register_reset(lx60_fpga_reset, s);
@@ -186,11 +186,11 @@ static void lx_init(const LxBoardDesc *board,
     }
 
     ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, NULL, "xtensa.sram", ram_size);
+    memory_region_init_ram(ram, NULL, "lx60.dram", ram_size);
     memory_region_add_subregion(system_memory, 0, ram);
 
     system_io = g_malloc(sizeof(*system_io));
-    memory_region_init(system_io, "system.io", 224 * 1024 * 1024);
+    memory_region_init(system_io, "lx60.io", 224 * 1024 * 1024);
     memory_region_add_subregion(system_memory, 0xf0000000, system_io);
     lx60_fpga_init(system_io, 0x0d020000);
     if (nd_table[0].vlan) {
commit 292627bb5e45007eb99d1a7915075eb16dea14ff
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Oct 30 21:24:26 2011 +0400

    xtensa_lx60: pass kernel arguments from -append
    
    Create boot parameters in the end of SRAM region, insert kernel
    arguments specified in -append there.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/hw/xtensa_bootparam.h b/hw/xtensa_bootparam.h
new file mode 100644
index 0000000..38ef32b
--- /dev/null
+++ b/hw/xtensa_bootparam.h
@@ -0,0 +1,25 @@
+#ifndef HW_XTENSA_BOOTPARAM
+#define HW_XTENSA_BOOTPARAM
+
+typedef struct BpTag {
+    uint16_t tag;
+    uint16_t size;
+} BpTag;
+
+static inline ram_addr_t put_tag(ram_addr_t addr, uint16_t tag,
+        size_t size, const void *data)
+{
+    BpTag bp_tag = {
+        .tag = tswap16(tag),
+        .size = tswap16((size + 3) & ~3),
+    };
+
+    cpu_physical_memory_write(addr, &bp_tag, sizeof(bp_tag));
+    addr += sizeof(bp_tag);
+    cpu_physical_memory_write(addr, data, size);
+    addr += (size + 3) & ~3;
+
+    return addr;
+}
+
+#endif
diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c
index cb047d2..069b21c 100644
--- a/hw/xtensa_lx60.c
+++ b/hw/xtensa_lx60.c
@@ -34,6 +34,7 @@
 #include "pc.h"
 #include "sysbus.h"
 #include "flash.h"
+#include "xtensa_bootparam.h"
 
 typedef struct LxBoardDesc {
     size_t flash_size;
@@ -188,10 +189,6 @@ static void lx_init(const LxBoardDesc *board,
     memory_region_init_ram(ram, NULL, "xtensa.sram", ram_size);
     memory_region_add_subregion(system_memory, 0, ram);
 
-    rom = g_malloc(sizeof(*rom));
-    memory_region_init_ram(rom, NULL, "xtensa.rom", 0x1000);
-    memory_region_add_subregion(system_memory, 0xfe000000, rom);
-
     system_io = g_malloc(sizeof(*system_io));
     memory_region_init(system_io, "system.io", 224 * 1024 * 1024);
     memory_region_add_subregion(system_memory, 0xf0000000, system_io);
@@ -223,6 +220,25 @@ static void lx_init(const LxBoardDesc *board,
 
     /* Use presence of kernel file name as 'boot from SRAM' switch. */
     if (kernel_filename) {
+        rom = g_malloc(sizeof(*rom));
+        memory_region_init_ram(rom, NULL, "lx60.sram", board->sram_size);
+        memory_region_add_subregion(system_memory, 0xfe000000, rom);
+
+        /* Put kernel bootparameters to the end of that SRAM */
+        if (kernel_cmdline) {
+            size_t cmdline_size = strlen(kernel_cmdline) + 1;
+            size_t bp_size = sizeof(BpTag[4]) + cmdline_size;
+            uint32_t tagptr = (0xfe000000 + board->sram_size - bp_size) & ~0xff;
+
+            env->regs[2] = tagptr;
+
+            tagptr = put_tag(tagptr, 0x7b0b, 0, NULL);
+            if (cmdline_size > 1) {
+                tagptr = put_tag(tagptr, 0x1001,
+                        cmdline_size, kernel_cmdline);
+            }
+            tagptr = put_tag(tagptr, 0x7e0b, 0, NULL);
+        }
         uint64_t elf_entry;
         uint64_t elf_lowaddr;
         int success = load_elf(kernel_filename, translate_phys_addr, env,
commit 82b25dc8b04766fde3982fec448ebfd48233f4d4
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Oct 30 21:21:15 2011 +0400

    xtensa_lx60: add FLASH support
    
    LX60 carry 4 Mbyte FLASH and 128 Kbyte SRAM, LX200 carry 16 Mbyte FLASH
    and 32 Mbyte SRAM. Either of these memories may be mapped to the system
    ROM region.
    
    Select boot from FLASH if -kernel option is not specified, otherwise
    boot from SRAM.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/default-configs/xtensa-softmmu.mak b/default-configs/xtensa-softmmu.mak
index 7f0df34..9d8899c 100644
--- a/default-configs/xtensa-softmmu.mak
+++ b/default-configs/xtensa-softmmu.mak
@@ -2,3 +2,4 @@
 
 CONFIG_SERIAL=y
 CONFIG_OPENCORES_ETH=y
+CONFIG_PFLASH_CFI01=y
diff --git a/default-configs/xtensaeb-softmmu.mak b/default-configs/xtensaeb-softmmu.mak
index 7f0df34..9d8899c 100644
--- a/default-configs/xtensaeb-softmmu.mak
+++ b/default-configs/xtensaeb-softmmu.mak
@@ -2,3 +2,4 @@
 
 CONFIG_SERIAL=y
 CONFIG_OPENCORES_ETH=y
+CONFIG_PFLASH_CFI01=y
diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c
index 3cebca1..cb047d2 100644
--- a/hw/xtensa_lx60.c
+++ b/hw/xtensa_lx60.c
@@ -33,6 +33,13 @@
 #include "exec-memory.h"
 #include "pc.h"
 #include "sysbus.h"
+#include "flash.h"
+
+typedef struct LxBoardDesc {
+    size_t flash_size;
+    size_t flash_sector_size;
+    size_t sram_size;
+} LxBoardDesc;
 
 typedef struct Lx60FpgaState {
     MemoryRegion iomem;
@@ -142,8 +149,8 @@ static void lx60_reset(void *env)
     cpu_reset(env);
 }
 
-static void lx60_init(ram_addr_t ram_size,
-        const char *boot_device,
+static void lx_init(const LxBoardDesc *board,
+        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)
 {
@@ -155,8 +162,14 @@ static void lx60_init(ram_addr_t ram_size,
     MemoryRegion *system_memory = get_system_memory();
     CPUState *env = NULL;
     MemoryRegion *ram, *rom, *system_io;
+    DriveInfo *dinfo;
+    pflash_t *flash = NULL;
     int n;
 
+    if (!cpu_model) {
+        cpu_model = "dc232b";
+    }
+
     for (n = 0; n < smp_cpus; n++) {
         env = cpu_init(cpu_model);
         if (!env) {
@@ -195,6 +208,20 @@ static void lx60_init(ram_addr_t ram_size,
     serial_mm_init(system_io, 0x0d050020, 2, xtensa_get_extint(env, 0),
             115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
 
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (dinfo) {
+        flash = pflash_cfi01_register(0xf8000000,
+                NULL, "lx60.io.flash", board->flash_size,
+                dinfo->bdrv, board->flash_sector_size,
+                board->flash_size / board->flash_sector_size,
+                4, 0x0000, 0x0000, 0x0000, 0x0000, be);
+        if (flash == NULL) {
+            fprintf(stderr, "Unable to mount pflash\n");
+            exit(1);
+        }
+    }
+
+    /* Use presence of kernel file name as 'boot from SRAM' switch. */
     if (kernel_filename) {
         uint64_t elf_entry;
         uint64_t elf_lowaddr;
@@ -203,6 +230,16 @@ static void lx60_init(ram_addr_t ram_size,
         if (success > 0) {
             env->pc = elf_entry;
         }
+    } else {
+        if (flash) {
+            MemoryRegion *flash_mr = pflash_cfi01_get_memory(flash);
+            MemoryRegion *flash_io = g_malloc(sizeof(*flash_io));
+
+            memory_region_init_alias(flash_io, "lx60.flash",
+                    flash_mr, 0, board->flash_size);
+            memory_region_add_subregion(system_memory, 0xfe000000,
+                    flash_io);
+        }
     }
 }
 
@@ -211,10 +248,28 @@ static void xtensa_lx60_init(ram_addr_t ram_size,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)
 {
-    if (!cpu_model) {
-        cpu_model = "dc232b";
-    }
-    lx60_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
+    static const LxBoardDesc lx60_board = {
+        .flash_size = 0x400000,
+        .flash_sector_size = 0x10000,
+        .sram_size = 0x20000,
+    };
+    lx_init(&lx60_board, ram_size, boot_device,
+            kernel_filename, kernel_cmdline,
+            initrd_filename, cpu_model);
+}
+
+static void xtensa_lx200_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)
+{
+    static const LxBoardDesc lx200_board = {
+        .flash_size = 0x1000000,
+        .flash_sector_size = 0x20000,
+        .sram_size = 0x2000000,
+    };
+    lx_init(&lx200_board, ram_size, boot_device,
+            kernel_filename, kernel_cmdline,
             initrd_filename, cpu_model);
 }
 
@@ -225,9 +280,17 @@ static QEMUMachine xtensa_lx60_machine = {
     .max_cpus = 4,
 };
 
-static void xtensa_lx60_machine_init(void)
+static QEMUMachine xtensa_lx200_machine = {
+    .name = "lx200",
+    .desc = "lx200 EVB (dc232b)",
+    .init = xtensa_lx200_init,
+    .max_cpus = 4,
+};
+
+static void xtensa_lx_machines_init(void)
 {
     qemu_register_machine(&xtensa_lx60_machine);
+    qemu_register_machine(&xtensa_lx200_machine);
 }
 
-machine_init(xtensa_lx60_machine_init);
+machine_init(xtensa_lx_machines_init);
commit 6b814719b4ef3d69c61ec0c1d580006110b04b04
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Tue Oct 25 18:24:09 2011 +0400

    target-xtensa: raise an exception for invalid and reserved opcodes
    
    This includes opcodes from disabled features and those marked reserved in the ISA.
    Also end TB on opcodes that definitely generate an exception: illegal
    instructions, syscall and privileged instructions.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index b724d46..c81450d 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -266,6 +266,10 @@ static void gen_exception_cause(DisasContext *dc, uint32_t cause)
     gen_helper_exception_cause(tpc, tcause);
     tcg_temp_free(tpc);
     tcg_temp_free(tcause);
+    if (cause == ILLEGAL_INSTRUCTION_CAUSE ||
+            cause == SYSCALL_CAUSE) {
+        dc->is_jmp = DISAS_UPDATE;
+    }
 }
 
 static void gen_exception_cause_vaddr(DisasContext *dc, uint32_t cause,
@@ -283,6 +287,7 @@ static void gen_check_privilege(DisasContext *dc)
 {
     if (dc->cring) {
         gen_exception_cause(dc, PRIVILEGED_CAUSE);
+        dc->is_jmp = DISAS_UPDATE;
     }
 }
 
@@ -2378,7 +2383,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
 invalid_opcode:
     qemu_log("INVALID(pc = %08x)\n", dc->pc);
-    dc->pc = dc->next_pc;
+    gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
 #undef HAS_OPTION
 }
 
commit 0c852e171b3b6073f5b05b66d8df94eda23f6dee
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Mon Oct 24 04:22:47 2011 +0400

    target-xtensa: handle cache options in the overlay tool
    
    Cache options must be enabled for the cores that have cache to avoid
    illegal instruction exceptions.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/target-xtensa/overlay_tool.h b/target-xtensa/overlay_tool.h
index 060e8e5..9cef27d 100644
--- a/target-xtensa/overlay_tool.h
+++ b/target-xtensa/overlay_tool.h
@@ -71,6 +71,12 @@
         XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT) | \
     XCHAL_OPTION(XCHAL_HAVE_CCOUNT, XTENSA_OPTION_TIMER_INTERRUPT) | \
     /* Local memory, TODO */ \
+    XCHAL_OPTION(XCHAL_ICACHE_WAYS, XTENSA_OPTION_ICACHE) | \
+    XCHAL_OPTION(XCHAL_ICACHE_LINE_LOCKABLE, \
+            XTENSA_OPTION_ICACHE_INDEX_LOCK) | \
+    XCHAL_OPTION(XCHAL_DCACHE_WAYS, XTENSA_OPTION_DCACHE) | \
+    XCHAL_OPTION(XCHAL_DCACHE_LINE_LOCKABLE, \
+            XTENSA_OPTION_DCACHE_INDEX_LOCK) | \
     XCHAL_OPTION(XCHAL_UNALIGNED_LOAD_HW, XTENSA_OPTION_HW_ALIGNMENT) | \
     /* Memory protection and translation */ \
     XCHAL_OPTION(XCHAL_HAVE_MIMIC_CACHEATTR, \
commit 53a72dfda584c8d54df61f7c1aea9f9ff86b138c
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Tue Nov 1 01:51:02 2011 +0400

    target-xtensa: mask out undefined bits of WINDOWSTART SR
    
    According to ISA, table 5-156, bits 32:NAREG/4 of the WINDOWSTART SR
    must be zero.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 1688bb2..b724d46 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -466,7 +466,7 @@ static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 
 static void gen_wsr_windowstart(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
-    tcg_gen_mov_i32(cpu_SR[sr], v);
+    tcg_gen_andi_i32(cpu_SR[sr], v, (1 << dc->config->nareg / 4) - 1);
     reset_used_window(dc);
 }
 
commit e072ea2fd8fdceef64159b9596d3c15ce01bea91
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Nov 1 19:37:01 2011 -0500

    Bump version to 1.0-rc0
    
    Look out 1.0, here we come!
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/VERSION b/VERSION
index e653127..c78227b 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.15.50
+0.15.90
commit b0eb8449f2cb32ef96dfd4df3261088463ebfaa7
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Nov 1 19:32:21 2011 -0500

    Revert "virtio: Add PCI memory BAR in addition to PIO BAR"
    
    This reverts commit 46d95bfec7f9429d5228078219413d7e33496d65.

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 83a4b35..ca5923c 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -654,8 +654,6 @@ void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev)
                           "virtio-pci", size);
     pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO,
                      &proxy->bar);
-    pci_register_bar(&proxy->pci_dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY,
-                     &proxy->bar);
 
     if (!kvm_has_many_ioeventfds()) {
         proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
commit 8aceefd77c2bb5af02759d11eb836c42ad9e720d
Merge: ef26ee0... 13766eb...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Nov 1 17:29:24 2011 -0500

    Merge remote-tracking branch 'afaerber/cocoa-for-upstream' into staging

commit ef26ee0e6c67d415f8b22850f9f13a972ada8be1
Merge: dd7b25b... e1c2008...
Author: malc <av1474 at comtv.ru>
Date:   Wed Nov 2 02:16:34 2011 +0400

    Merge branch 'master' of git://git.qemu.org/qemu

commit dd7b25b5b47df8aaf5580faaf3f60b2a1b779c37
Merge: 0756e71... 7f76236...
Author: malc <av1474 at comtv.ru>
Date:   Wed Nov 2 02:14:19 2011 +0400

    Merge branch 'master' of git://git.qemu.org/qemu

commit 0756e71c3f4327f4d2ad3c6099cdafc23de14fcf
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Nov 1 15:06:43 2011 -0700

    tcg: Fix whitespace in tcg-op.h.
    
    Removing the only tabs in the file.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: malc <av1474 at comtv.ru>

diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 8637fe8..82e04e7 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -2042,8 +2042,8 @@ static inline void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
 }
 
 static inline void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1,
-				       TCGv_i32 arg2, unsigned int ofs,
-				       unsigned int len)
+                                       TCGv_i32 arg2, unsigned int ofs,
+                                       unsigned int len)
 {
     uint32_t mask;
     TCGv_i32 t1;
@@ -2073,8 +2073,8 @@ static inline void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1,
 }
 
 static inline void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1,
-				       TCGv_i64 arg2, unsigned int ofs,
-				       unsigned int len)
+                                       TCGv_i64 arg2, unsigned int ofs,
+                                       unsigned int len)
 {
     uint64_t mask;
     TCGv_i64 t1;
commit 2f98c9db0b657e198ab106139654bd408f59636c
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Nov 1 15:06:42 2011 -0700

    tcg: Fix regression in tcg_gen_deposit_i64.
    
    The error being caused by the failure to copy the other half of
    the input to the output after having narrowed the deposit operation.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: malc <av1474 at comtv.ru>

diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 24ec7fc..8637fe8 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -2090,6 +2090,7 @@ static inline void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1,
 
 #if TCG_TARGET_REG_BITS == 32
     if (ofs >= 32) {
+        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
         tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1),
                             TCGV_LOW(arg2), ofs - 32, len);
         return;
@@ -2097,6 +2098,7 @@ static inline void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1,
     if (ofs + len <= 32) {
         tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(arg1),
                             TCGV_LOW(arg2), ofs, len);
+        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
         return;
     }
 #endif
commit e1c2008af64487e7d3cec615612b7f467ebe9bc8
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 12:27:25 2011 +0200

    pcnet: Add link state support
    
    Update lnkst on link state changes so that guests can obtain this
    information via reading back the LED output pin. Works for Linux but
    not for guests that depend on the missing PHY.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/lance.c b/hw/lance.c
index d83e7f5..93d5fda 100644
--- a/hw/lance.c
+++ b/hw/lance.c
@@ -97,6 +97,7 @@ static NetClientInfo net_lance_info = {
     .size = sizeof(NICState),
     .can_receive = pcnet_can_receive,
     .receive = pcnet_receive,
+    .link_status_changed = pcnet_set_link_status,
     .cleanup = lance_cleanup,
 };
 
diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c
index ea5dfde..4e164da 100644
--- a/hw/pcnet-pci.c
+++ b/hw/pcnet-pci.c
@@ -288,6 +288,7 @@ static NetClientInfo net_pci_pcnet_info = {
     .size = sizeof(NICState),
     .can_receive = pcnet_can_receive,
     .receive = pcnet_receive,
+    .link_status_changed = pcnet_set_link_status,
     .cleanup = pci_pcnet_cleanup,
 };
 
diff --git a/hw/pcnet.c b/hw/pcnet.c
index add3ec2..cba253b 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -1197,6 +1197,13 @@ ssize_t pcnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size_)
     return size_;
 }
 
+void pcnet_set_link_status(VLANClientState *nc)
+{
+    PCNetState *d = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    d->lnkst = nc->link_down ? 0 : 0x40;
+}
+
 static void pcnet_transmit(PCNetState *s)
 {
     target_phys_addr_t xmit_cxda = 0;
diff --git a/hw/pcnet.h b/hw/pcnet.h
index 52cc52e..edc81c9 100644
--- a/hw/pcnet.h
+++ b/hw/pcnet.h
@@ -58,6 +58,7 @@ uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr);
 uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
 int pcnet_can_receive(VLANClientState *nc);
 ssize_t pcnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size_);
+void pcnet_set_link_status(VLANClientState *nc);
 void pcnet_common_cleanup(PCNetState *d);
 int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info);
 extern const VMStateDescription vmstate_pcnet;
commit 7ba7974197090285fdb413c6e1c41aaacd44b9c4
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Sep 26 19:01:45 2011 +0200

    pcnet-pci: Fix PIO word access to PROM
    
    Implement the various IO access widths according to the spec. This
    specifically unbreaks word and dword access to the PROM area that is
    mapped into IO space. It also drops redundant upper limit checks and
    spurious "return void".
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c
index 4f97f96..ea5dfde 100644
--- a/hw/pcnet-pci.c
+++ b/hw/pcnet-pci.c
@@ -76,12 +76,24 @@ static uint64_t pcnet_ioport_read(void *opaque, target_phys_addr_t addr,
 {
     PCNetState *d = opaque;
 
-    if (addr < 16 && size == 1) {
-        return pcnet_aprom_readb(d, addr);
-    } else if (addr >= 0x10 && addr < 0x20 && size == 2) {
-        return pcnet_ioport_readw(d, addr);
-    } else if (addr >= 0x10 && addr < 0x20 && size == 4) {
-        return pcnet_ioport_readl(d, addr);
+    if (addr < 0x10) {
+        if (!BCR_DWIO(d) && size == 1) {
+            return pcnet_aprom_readb(d, addr);
+        } else if (!BCR_DWIO(d) && (addr & 1) == 0 && size == 2) {
+            return pcnet_aprom_readb(d, addr) |
+                   (pcnet_aprom_readb(d, addr + 1) << 8);
+        } else if (BCR_DWIO(d) && (addr & 3) == 0 && size == 4) {
+            return pcnet_aprom_readb(d, addr) |
+                   (pcnet_aprom_readb(d, addr + 1) << 8) |
+                   (pcnet_aprom_readb(d, addr + 2) << 16) |
+                   (pcnet_aprom_readb(d, addr + 3) << 24);
+        }
+    } else {
+        if (size == 2) {
+            return pcnet_ioport_readw(d, addr);
+        } else if (size == 4) {
+            return pcnet_ioport_readl(d, addr);
+        }
     }
     return ((uint64_t)1 << (size * 8)) - 1;
 }
@@ -91,12 +103,24 @@ static void pcnet_ioport_write(void *opaque, target_phys_addr_t addr,
 {
     PCNetState *d = opaque;
 
-    if (addr < 16 && size == 1) {
-        return pcnet_aprom_writeb(d, addr, data);
-    } else if (addr >= 0x10 && addr < 0x20 && size == 2) {
-        return pcnet_ioport_writew(d, addr, data);
-    } else if (addr >= 0x10 && addr < 0x20 && size == 4) {
-        return pcnet_ioport_writel(d, addr, data);
+    if (addr < 0x10) {
+        if (!BCR_DWIO(d) && size == 1) {
+            pcnet_aprom_writeb(d, addr, data);
+        } else if (!BCR_DWIO(d) && (addr & 1) == 0 && size == 2) {
+            pcnet_aprom_writeb(d, addr, data & 0xff);
+            pcnet_aprom_writeb(d, addr + 1, data >> 8);
+        } else if (BCR_DWIO(d) && (addr & 3) == 0 && size == 4) {
+            pcnet_aprom_writeb(d, addr, data & 0xff);
+            pcnet_aprom_writeb(d, addr + 1, (data >> 8) & 0xff);
+            pcnet_aprom_writeb(d, addr + 2, (data >> 16) & 0xff);
+            pcnet_aprom_writeb(d, addr + 3, data >> 24);
+        }
+    } else {
+        if (size == 2) {
+            pcnet_ioport_writew(d, addr, data);
+        } else if (size == 4) {
+            pcnet_ioport_writel(d, addr, data);
+        }
     }
 }
 
commit 488a1a5dfe9a9ba57fa6c6b6b98136ea494e0296
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Sep 26 19:01:44 2011 +0200

    pcnet: Move BCR defines to header
    
    This moves BCR defines to the common header and immediately makes use of
    them to add BCR_APROMWE, replacing the open-coded write check in
    pcnet_aprom_writeb.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c
index 41a6e07..4f97f96 100644
--- a/hw/pcnet-pci.c
+++ b/hw/pcnet-pci.c
@@ -56,9 +56,9 @@ static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
 #ifdef PCNET_DEBUG
     printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val);
 #endif
-    /* Check APROMWE bit to enable write access */
-    if (pcnet_bcr_readw(s,2) & 0x100)
+    if (BCR_APROMWE(s)) {
         s->prom[addr & 15] = val;
+    }
 }
 
 static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
diff --git a/hw/pcnet.c b/hw/pcnet.c
index cf16fd4..add3ec2 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -58,24 +58,6 @@ struct qemu_ether_header {
     uint16_t ether_type;
 };
 
-/* BUS CONFIGURATION REGISTERS */
-#define BCR_MSRDA    0
-#define BCR_MSWRA    1
-#define BCR_MC       2
-#define BCR_LNKST    4
-#define BCR_LED1     5
-#define BCR_LED2     6
-#define BCR_LED3     7
-#define BCR_FDC      9
-#define BCR_BSBC     18
-#define BCR_EECAS    19
-#define BCR_SWS      20
-#define BCR_PLAT     22
-
-#define BCR_DWIO(S)      !!((S)->bcr[BCR_BSBC] & 0x0080)
-#define BCR_SSIZE32(S)   !!((S)->bcr[BCR_SWS ] & 0x0100)
-#define BCR_SWSTYLE(S)     ((S)->bcr[BCR_SWS ] & 0x00FF)
-
 #define CSR_INIT(S)      !!(((S)->csr[0])&0x0001)
 #define CSR_STRT(S)      !!(((S)->csr[0])&0x0002)
 #define CSR_STOP(S)      !!(((S)->csr[0])&0x0004)
diff --git a/hw/pcnet.h b/hw/pcnet.h
index cd86bde..52cc52e 100644
--- a/hw/pcnet.h
+++ b/hw/pcnet.h
@@ -6,6 +6,25 @@
 
 #include "memory.h"
 
+/* BUS CONFIGURATION REGISTERS */
+#define BCR_MSRDA    0
+#define BCR_MSWRA    1
+#define BCR_MC       2
+#define BCR_LNKST    4
+#define BCR_LED1     5
+#define BCR_LED2     6
+#define BCR_LED3     7
+#define BCR_FDC      9
+#define BCR_BSBC     18
+#define BCR_EECAS    19
+#define BCR_SWS      20
+#define BCR_PLAT     22
+
+#define BCR_APROMWE(S)   !!((S)->bcr[BCR_MC  ] & 0x0100)
+#define BCR_DWIO(S)      !!((S)->bcr[BCR_BSBC] & 0x0080)
+#define BCR_SSIZE32(S)   !!((S)->bcr[BCR_SWS ] & 0x0100)
+#define BCR_SWSTYLE(S)     ((S)->bcr[BCR_SWS ] & 0x00FF)
+
 typedef struct PCNetState_st PCNetState;
 
 struct PCNetState_st {
commit 816f89256ef36c8fd20e70ac393110cf2322e223
Author: Wayne Xia <xiawenc at linux.vnet.ibm.com>
Date:   Wed Oct 12 11:32:41 2011 +0800

    Sort the help info shown in monitor at runtime
    
    This patch would try sort the command list in monitor at runtime. As a result,
    command help and help info would show a more friendly sorted command list.
    For eg:
    (qemu)help
    acl_add
    acl_policy
    acl_remove
    acl_reset
    acl_show
    balloon
    block_passwd
    ...
    the command list is sorted.
    
    v3: using qsort function to sort the command list.
    
    Tested-by: Wenyi Gao <wenyi at linux.vnet.ibm.com>
    Signed-off-by: Wayne Xia <xiawenc at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/monitor.c b/monitor.c
index 7c2a9b9..5ea35de 100644
--- a/monitor.c
+++ b/monitor.c
@@ -199,8 +199,8 @@ static inline int mon_print_count_get(const Monitor *mon) { return 0; }
 
 static QLIST_HEAD(mon_list, Monitor) mon_list;
 
-static const mon_cmd_t mon_cmds[];
-static const mon_cmd_t info_cmds[];
+static mon_cmd_t mon_cmds[];
+static mon_cmd_t info_cmds[];
 
 static const mon_cmd_t qmp_cmds[];
 
@@ -2591,13 +2591,14 @@ int monitor_get_fd(Monitor *mon, const char *fdname)
     return -1;
 }
 
-static const mon_cmd_t mon_cmds[] = {
+/* mon_cmds and info_cmds would be sorted at runtime */
+static mon_cmd_t mon_cmds[] = {
 #include "hmp-commands.h"
     { NULL, NULL, },
 };
 
 /* Please update hmp-commands.hx when adding or changing commands */
-static const mon_cmd_t info_cmds[] = {
+static mon_cmd_t info_cmds[] = {
     {
         .name       = "version",
         .args_type  = "",
@@ -4832,6 +4833,25 @@ static void monitor_event(void *opaque, int event)
     }
 }
 
+static int
+compare_mon_cmd(const void *a, const void *b)
+{
+    return strcmp(((const mon_cmd_t *)a)->name,
+            ((const mon_cmd_t *)b)->name);
+}
+
+static void sortcmdlist(void)
+{
+    int array_num;
+    int elem_size = sizeof(mon_cmd_t);
+
+    array_num = sizeof(mon_cmds)/elem_size-1;
+    qsort((void *)mon_cmds, array_num, elem_size, compare_mon_cmd);
+
+    array_num = sizeof(info_cmds)/elem_size-1;
+    qsort((void *)info_cmds, array_num, elem_size, compare_mon_cmd);
+}
+
 
 /*
  * Local variables:
@@ -4874,6 +4894,8 @@ void monitor_init(CharDriverState *chr, int flags)
     QLIST_INSERT_HEAD(&mon_list, mon, entry);
     if (!default_mon || (flags & MONITOR_IS_DEFAULT))
         default_mon = mon;
+
+    sortcmdlist();
 }
 
 static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
commit 2284451019a796eb2a37d70544e19d686de7f8c0
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Sep 27 17:26:23 2011 +0300

    event_notifier: move to top-level directory
    
    Has no business in hw/.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/event_notifier.c b/event_notifier.c
new file mode 100644
index 0000000..2c73555
--- /dev/null
+++ b/event_notifier.c
@@ -0,0 +1,61 @@
+/*
+ * event notifier support
+ *
+ * Copyright Red Hat, Inc. 2010
+ *
+ * Authors:
+ *  Michael S. Tsirkin <mst at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "event_notifier.h"
+#ifdef CONFIG_EVENTFD
+#include <sys/eventfd.h>
+#endif
+
+int event_notifier_init(EventNotifier *e, int active)
+{
+#ifdef CONFIG_EVENTFD
+    int fd = eventfd(!!active, EFD_NONBLOCK | EFD_CLOEXEC);
+    if (fd < 0)
+        return -errno;
+    e->fd = fd;
+    return 0;
+#else
+    return -ENOSYS;
+#endif
+}
+
+void event_notifier_cleanup(EventNotifier *e)
+{
+    close(e->fd);
+}
+
+int event_notifier_get_fd(EventNotifier *e)
+{
+    return e->fd;
+}
+
+int event_notifier_test_and_clear(EventNotifier *e)
+{
+    uint64_t value;
+    int r = read(e->fd, &value, sizeof(value));
+    return r == sizeof(value);
+}
+
+int event_notifier_test(EventNotifier *e)
+{
+    uint64_t value;
+    int r = read(e->fd, &value, sizeof(value));
+    if (r == sizeof(value)) {
+        /* restore previous value. */
+        int s = write(e->fd, &value, sizeof(value));
+        /* never blocks because we use EFD_SEMAPHORE.
+         * If we didn't we'd get EAGAIN on overflow
+         * and we'd have to write code to ignore it. */
+        assert(s == sizeof(value));
+    }
+    return r == sizeof(value);
+}
diff --git a/event_notifier.h b/event_notifier.h
new file mode 100644
index 0000000..24117ea
--- /dev/null
+++ b/event_notifier.h
@@ -0,0 +1,16 @@
+#ifndef QEMU_EVENT_NOTIFIER_H
+#define QEMU_EVENT_NOTIFIER_H
+
+#include "qemu-common.h"
+
+struct EventNotifier {
+	int fd;
+};
+
+int event_notifier_init(EventNotifier *, int active);
+void event_notifier_cleanup(EventNotifier *);
+int event_notifier_get_fd(EventNotifier *);
+int event_notifier_test_and_clear(EventNotifier *);
+int event_notifier_test(EventNotifier *);
+
+#endif
diff --git a/hw/event_notifier.c b/hw/event_notifier.c
deleted file mode 100644
index 13f3656..0000000
--- a/hw/event_notifier.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * event notifier support
- *
- * Copyright Red Hat, Inc. 2010
- *
- * Authors:
- *  Michael S. Tsirkin <mst at redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
- */
-
-#include "hw.h"
-#include "event_notifier.h"
-#ifdef CONFIG_EVENTFD
-#include <sys/eventfd.h>
-#endif
-
-int event_notifier_init(EventNotifier *e, int active)
-{
-#ifdef CONFIG_EVENTFD
-    int fd = eventfd(!!active, EFD_NONBLOCK | EFD_CLOEXEC);
-    if (fd < 0)
-        return -errno;
-    e->fd = fd;
-    return 0;
-#else
-    return -ENOSYS;
-#endif
-}
-
-void event_notifier_cleanup(EventNotifier *e)
-{
-    close(e->fd);
-}
-
-int event_notifier_get_fd(EventNotifier *e)
-{
-    return e->fd;
-}
-
-int event_notifier_test_and_clear(EventNotifier *e)
-{
-    uint64_t value;
-    int r = read(e->fd, &value, sizeof(value));
-    return r == sizeof(value);
-}
-
-int event_notifier_test(EventNotifier *e)
-{
-    uint64_t value;
-    int r = read(e->fd, &value, sizeof(value));
-    if (r == sizeof(value)) {
-        /* restore previous value. */
-        int s = write(e->fd, &value, sizeof(value));
-        /* never blocks because we use EFD_SEMAPHORE.
-         * If we didn't we'd get EAGAIN on overflow
-         * and we'd have to write code to ignore it. */
-        assert(s == sizeof(value));
-    }
-    return r == sizeof(value);
-}
diff --git a/hw/event_notifier.h b/hw/event_notifier.h
deleted file mode 100644
index 24117ea..0000000
--- a/hw/event_notifier.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef QEMU_EVENT_NOTIFIER_H
-#define QEMU_EVENT_NOTIFIER_H
-
-#include "qemu-common.h"
-
-struct EventNotifier {
-	int fd;
-};
-
-int event_notifier_init(EventNotifier *, int active);
-void event_notifier_cleanup(EventNotifier *);
-int event_notifier_get_fd(EventNotifier *);
-int event_notifier_test_and_clear(EventNotifier *);
-int event_notifier_test(EventNotifier *);
-
-#endif
commit 443916d1d9f1094a43d28c6b8cc60e3e7e27eb36
Author: Stefan Berger <stefanb at linux.vnet.ibm.com>
Date:   Wed Sep 28 06:41:32 2011 -0400

    Move filedescriptor parsing code from net.c into qemu_parse_fd()
    
    Move the parsing of a filedescriptor into a common function
    qemu_parse_fd() so others can use it as well. Have net.c call this
    function.
    
    v2:
     - moving qemu_parse_fd into cutils.c
    
    Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/cutils.c b/cutils.c
index c91f887..5d995bc 100644
--- a/cutils.c
+++ b/cutils.c
@@ -415,3 +415,15 @@ int64_t strtosz(const char *nptr, char **end)
 {
     return strtosz_suffix(nptr, end, STRTOSZ_DEFSUFFIX_MB);
 }
+
+int qemu_parse_fd(const char *param)
+{
+    int fd;
+    char *endptr = NULL;
+
+    fd = strtol(param, &endptr, 10);
+    if (*endptr || (fd == 0 && param == endptr)) {
+        return -1;
+    }
+    return fd;
+}
diff --git a/net.c b/net.c
index d05930c..cb52050 100644
--- a/net.c
+++ b/net.c
@@ -733,12 +733,7 @@ int net_handle_fd_param(Monitor *mon, const char *param)
             return -1;
         }
     } else {
-        char *endptr = NULL;
-
-        fd = strtol(param, &endptr, 10);
-        if (*endptr || (fd == 0 && param == endptr)) {
-            return -1;
-        }
+        fd = qemu_parse_fd(param);
     }
 
     return fd;
diff --git a/qemu-common.h b/qemu-common.h
index 1c15cb1..2ce47aa 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -129,6 +129,7 @@ time_t mktimegm(struct tm *tm);
 int qemu_fls(int i);
 int qemu_fdatasync(int fd);
 int fcntl_setfl(int fd, int flag);
+int qemu_parse_fd(const char *param);
 
 /*
  * strtosz() suffixes used to specify the default treatment of an
commit f809c0d66bf1d9a8a4282b5a089b7eead45428fc
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Nov 1 18:32:55 2011 +0000

    configure: Suppress messages from pkg_config probe for check
    
    Suppress confusing messages from pkg_config when probing for
    'check' by sending them to /dev/null as we do with other
    similar probes.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index 850efc0..254b801 100755
--- a/configure
+++ b/configure
@@ -1828,7 +1828,7 @@ if test "$check_utests" != "no" ; then
 #include <check.h>
 int main(void) { suite_create("qemu test"); return 0; }
 EOF
-  check_libs=`$pkg_config --libs check`
+  check_libs=`$pkg_config --libs check 2>/dev/null`
   if compile_prog "" $check_libs ; then
     check_utests=yes
     libs_tools="$check_libs $libs_tools"
commit 46d95bfec7f9429d5228078219413d7e33496d65
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Sep 30 15:26:16 2011 +1000

    virtio: Add PCI memory BAR in addition to PIO BAR
    
    Currently, virtio devices are usually presented to the guest as an
    emulated PCI device, virtio_pci.  Although the actual IO operations
    are done through system memory, the configuration of the virtio device
    is done through the one PCI IO space BAR that virtio_pci presents.
    
    But PCI IO space (aka PIO) is deprecated for modern PCI devices, and
    on some systems with many PCI domains accessing PIO space can be
    problematic.  For example on the existing PowerVM implementation of
    the PAPR spec, PCI PIO access is not supported at all.  We're hoping
    that our KVM implementation will support PCI PIO (once we support PCI
    at all), but it will probably have some irritating limitations.
    
    This patch, therefore, extends the virtio_pci device to have a PCI
    memory space (MMIO) BAR as well as the IO BAR.  The MMIO BAR contains
    exactly the same registers, in exactly the same layout as the existing
    PIO BAR.
    
    Because the PIO BAR is still present, existing guest drivers should
    still work fine.  With this change in place, future guest drivers can
    check for an MMIO BAR and use that if present (falling back to PIO
    when possible to support older qemu versions).
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index ca5923c..83a4b35 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -654,6 +654,8 @@ void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev)
                           "virtio-pci", size);
     pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO,
                      &proxy->bar);
+    pci_register_bar(&proxy->pci_dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY,
+                     &proxy->bar);
 
     if (!kvm_has_many_ioeventfds()) {
         proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
commit fff23ee9a5de74ab111b3cea9eec56782e7d7c50
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Oct 31 17:06:58 2011 +1100

    usb-uhci: Use PCI DMA stub functions
    
    This updates the usb-uhci device emulation to use the explicit PCI DMA
    wrapper to initialize its scatter/gathjer structure.  This means this
    driver should not need further changes when the sglist interface is
    extended to support IOMMUs.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 171d787..f9e3ea5 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -178,7 +178,7 @@ static UHCIAsync *uhci_async_alloc(UHCIState *s)
     async->done  = 0;
     async->isoc  = 0;
     usb_packet_init(&async->packet);
-    qemu_sglist_init(&async->sgl, 1);
+    pci_dma_sglist_init(&async->sgl, &s->dev, 1);
 
     return async;
 }
@@ -876,7 +876,7 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet)
         uint32_t link = async->td;
         uint32_t int_mask = 0, val;
 
-        cpu_physical_memory_read(link & ~0xf, (uint8_t *) &td, sizeof(td));
+        pci_dma_read(&s->dev, link & ~0xf, (uint8_t *) &td, sizeof(td));
         le32_to_cpus(&td.link);
         le32_to_cpus(&td.ctrl);
         le32_to_cpus(&td.token);
@@ -888,8 +888,8 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet)
 
         /* update the status bits of the TD */
         val = cpu_to_le32(td.ctrl);
-        cpu_physical_memory_write((link & ~0xf) + 4,
-                                  (const uint8_t *)&val, sizeof(val));
+        pci_dma_write(&s->dev, (link & ~0xf) + 4,
+                      (const uint8_t *)&val, sizeof(val));
         uhci_async_free(s, async);
     } else {
         async->done = 1;
@@ -952,7 +952,7 @@ static void uhci_process_frame(UHCIState *s)
 
     DPRINTF("uhci: processing frame %d addr 0x%x\n" , s->frnum, frame_addr);
 
-    cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);
+    pci_dma_read(&s->dev, frame_addr, (uint8_t *)&link, 4);
     le32_to_cpus(&link);
 
     int_mask = 0;
@@ -976,7 +976,7 @@ static void uhci_process_frame(UHCIState *s)
                 break;
             }
 
-            cpu_physical_memory_read(link & ~0xf, (uint8_t *) &qh, sizeof(qh));
+            pci_dma_read(&s->dev, link & ~0xf, (uint8_t *) &qh, sizeof(qh));
             le32_to_cpus(&qh.link);
             le32_to_cpus(&qh.el_link);
 
@@ -996,7 +996,7 @@ static void uhci_process_frame(UHCIState *s)
         }
 
         /* TD */
-        cpu_physical_memory_read(link & ~0xf, (uint8_t *) &td, sizeof(td));
+        pci_dma_read(&s->dev, link & ~0xf, (uint8_t *) &td, sizeof(td));
         le32_to_cpus(&td.link);
         le32_to_cpus(&td.ctrl);
         le32_to_cpus(&td.token);
@@ -1010,8 +1010,8 @@ static void uhci_process_frame(UHCIState *s)
         if (old_td_ctrl != td.ctrl) {
             /* update the status bits of the TD */
             val = cpu_to_le32(td.ctrl);
-            cpu_physical_memory_write((link & ~0xf) + 4,
-                                      (const uint8_t *)&val, sizeof(val));
+            pci_dma_write(&s->dev, (link & ~0xf) + 4,
+                          (const uint8_t *)&val, sizeof(val));
         }
 
         if (ret < 0) {
@@ -1039,8 +1039,8 @@ static void uhci_process_frame(UHCIState *s)
 	    /* update QH element link */
             qh.el_link = link;
             val = cpu_to_le32(qh.el_link);
-            cpu_physical_memory_write((curr_qh & ~0xf) + 4,
-                                          (const uint8_t *)&val, sizeof(val));
+            pci_dma_write(&s->dev, (curr_qh & ~0xf) + 4,
+                          (const uint8_t *)&val, sizeof(val));
 
             if (!depth_first(link)) {
                /* done with this QH */
commit 68d553587c0aa271c3eb2902921b503740d775b6
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Oct 31 17:06:57 2011 +1100

    usb-ehci: Use PCI DMA stub functions
    
    This updates the usb-ehci device emulation to use the explicit PCI DMA
    wrapper to initialize its scatter/gathjer structure.  This means this
    driver should not need further changes when the sglist interface is
    extended to support IOMMUs.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index bd374c1..cdd5aae 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1101,12 +1101,13 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
 // TODO : Put in common header file, duplication from usb-ohci.c
 
 /* Get an array of dwords from main memory */
-static inline int get_dwords(uint32_t addr, uint32_t *buf, int num)
+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)) {
-        cpu_physical_memory_rw(addr,(uint8_t *)buf, sizeof(*buf), 0);
+        pci_dma_read(&ehci->dev, addr, (uint8_t *)buf, sizeof(*buf));
         *buf = le32_to_cpu(*buf);
     }
 
@@ -1114,13 +1115,14 @@ static inline int get_dwords(uint32_t addr, uint32_t *buf, int num)
 }
 
 /* Put an array of dwords in to main memory */
-static inline int put_dwords(uint32_t addr, uint32_t *buf, int num)
+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);
-        cpu_physical_memory_rw(addr,(uint8_t *)&tmp, sizeof(tmp), 1);
+        pci_dma_write(&ehci->dev, addr, (uint8_t *)&tmp, sizeof(tmp));
     }
 
     return 1;
@@ -1169,7 +1171,8 @@ static int ehci_qh_do_overlay(EHCIQueue *q)
     q->qh.bufptr[1] &= ~BUFPTR_CPROGMASK_MASK;
     q->qh.bufptr[2] &= ~BUFPTR_FRAMETAG_MASK;
 
-    put_dwords(NLPTR_GET(q->qhaddr), (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2);
+    put_dwords(q->ehci, NLPTR_GET(q->qhaddr), (uint32_t *) &q->qh,
+               sizeof(EHCIqh) >> 2);
 
     return 0;
 }
@@ -1177,12 +1180,12 @@ static int ehci_qh_do_overlay(EHCIQueue *q)
 static int ehci_init_transfer(EHCIQueue *q)
 {
     uint32_t cpage, offset, bytes, plen;
-    target_phys_addr_t page;
+    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;
-    qemu_sglist_init(&q->sgl, 5);
+    pci_dma_sglist_init(&q->sgl, &q->ehci->dev, 5);
 
     while (bytes > 0) {
         if (cpage > 4) {
@@ -1428,7 +1431,7 @@ static int ehci_process_itd(EHCIState *ehci,
                 return USB_RET_PROCERR;
             }
 
-            qemu_sglist_init(&ehci->isgl, 2);
+            pci_dma_sglist_init(&ehci->isgl, &ehci->dev, 2);
             if (off + len > 4096) {
                 /* transfer crosses page border */
                 uint32_t len2 = off + len - 4096;
@@ -1532,7 +1535,8 @@ static int ehci_state_waitlisthead(EHCIState *ehci,  int async)
 
     /*  Find the head of the list (4.9.1.1) */
     for(i = 0; i < MAX_QH; i++) {
-        get_dwords(NLPTR_GET(entry), (uint32_t *) &qh, sizeof(EHCIqh) >> 2);
+        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) {
@@ -1629,7 +1633,8 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
         goto out;
     }
 
-    get_dwords(NLPTR_GET(q->qhaddr), (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2);
+    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) {
@@ -1698,7 +1703,7 @@ static int ehci_state_fetchitd(EHCIState *ehci, int async)
     assert(!async);
     entry = ehci_get_fetch_addr(ehci, async);
 
-    get_dwords(NLPTR_GET(entry),(uint32_t *) &itd,
+    get_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &itd,
                sizeof(EHCIitd) >> 2);
     ehci_trace_itd(ehci, entry, &itd);
 
@@ -1706,8 +1711,8 @@ static int ehci_state_fetchitd(EHCIState *ehci, int async)
         return -1;
     }
 
-    put_dwords(NLPTR_GET(entry), (uint32_t *) &itd,
-                sizeof(EHCIitd) >> 2);
+    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);
 
@@ -1722,7 +1727,7 @@ static int ehci_state_fetchsitd(EHCIState *ehci, int async)
     assert(!async);
     entry = ehci_get_fetch_addr(ehci, async);
 
-    get_dwords(NLPTR_GET(entry), (uint32_t *)&sitd,
+    get_dwords(ehci, NLPTR_GET(entry), (uint32_t *)&sitd,
                sizeof(EHCIsitd) >> 2);
     ehci_trace_sitd(ehci, entry, &sitd);
 
@@ -1784,7 +1789,8 @@ static int ehci_state_fetchqtd(EHCIQueue *q, int async)
 {
     int again = 0;
 
-    get_dwords(NLPTR_GET(q->qtdaddr),(uint32_t *) &q->qtd, sizeof(EHCIqtd) >> 2);
+    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) {
@@ -1827,7 +1833,7 @@ static void ehci_flush_qh(EHCIQueue *q)
     uint32_t dwords = sizeof(EHCIqh) >> 2;
     uint32_t addr = NLPTR_GET(q->qhaddr);
 
-    put_dwords(addr + 3 * sizeof(uint32_t), qh + 3, dwords - 3);
+    put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qh + 3, dwords - 3);
 }
 
 static int ehci_state_execute(EHCIQueue *q, int async)
@@ -1947,8 +1953,8 @@ static int ehci_state_writeback(EHCIQueue *q, int async)
 
     /*  Write back the QTD from the QH area */
     ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), (EHCIqtd*) &q->qh.next_qtd);
-    put_dwords(NLPTR_GET(q->qtdaddr),(uint32_t *) &q->qh.next_qtd,
-                sizeof(EHCIqtd) >> 2);
+    put_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &q->qh.next_qtd,
+               sizeof(EHCIqtd) >> 2);
 
     /*
      * EHCI specs say go horizontal here.
@@ -2148,7 +2154,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
         }
         list |= ((ehci->frindex & 0x1ff8) >> 1);
 
-        cpu_physical_memory_rw(list, (uint8_t *) &entry, sizeof entry, 0);
+        pci_dma_read(&ehci->dev, list, (uint8_t *) &entry, sizeof entry);
         entry = le32_to_cpu(entry);
 
         DPRINTF("PERIODIC state adv fr=%d.  [%08X] -> %08X\n",
commit 552908fef5b67ad9d96b76d7cb8371ebc26c9bc8
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Oct 31 17:06:56 2011 +1100

    PCI IDE: Use PCI DMA stub functions
    
    This updates the PCI IDE device emulation to use the explicit PCI DMA
    wrapper to initialize its scatter/gathjer structure.  This means this
    driver should not need further changes when the sglist interface is
    extended to support IOMMUs.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index f133c42..49b823d 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -62,7 +62,8 @@ static int bmdma_prepare_buf(IDEDMA *dma, int is_write)
     } prd;
     int l, len;
 
-    qemu_sglist_init(&s->sg, s->nsector / (BMDMA_PAGE_SIZE / 512) + 1);
+    pci_dma_sglist_init(&s->sg, &bm->pci_dev->dev,
+                        s->nsector / (BMDMA_PAGE_SIZE / 512) + 1);
     s->io_buffer_size = 0;
     for(;;) {
         if (bm->cur_prd_len == 0) {
@@ -70,7 +71,7 @@ static int bmdma_prepare_buf(IDEDMA *dma, int is_write)
             if (bm->cur_prd_last ||
                 (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE)
                 return s->io_buffer_size != 0;
-            cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8);
+            pci_dma_read(&bm->pci_dev->dev, bm->cur_addr, (uint8_t *)&prd, 8);
             bm->cur_addr += 8;
             prd.addr = le32_to_cpu(prd.addr);
             prd.size = le32_to_cpu(prd.size);
@@ -112,7 +113,7 @@ static int bmdma_rw_buf(IDEDMA *dma, int is_write)
             if (bm->cur_prd_last ||
                 (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE)
                 return 0;
-            cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8);
+            pci_dma_read(&bm->pci_dev->dev, bm->cur_addr, (uint8_t *)&prd, 8);
             bm->cur_addr += 8;
             prd.addr = le32_to_cpu(prd.addr);
             prd.size = le32_to_cpu(prd.size);
@@ -127,11 +128,11 @@ static int bmdma_rw_buf(IDEDMA *dma, int is_write)
             l = bm->cur_prd_len;
         if (l > 0) {
             if (is_write) {
-                cpu_physical_memory_write(bm->cur_prd_addr,
-                                          s->io_buffer + s->io_buffer_index, l);
+                pci_dma_write(&bm->pci_dev->dev, bm->cur_prd_addr,
+                              s->io_buffer + s->io_buffer_index, l);
             } else {
-                cpu_physical_memory_read(bm->cur_prd_addr,
-                                          s->io_buffer + s->io_buffer_index, l);
+                pci_dma_read(&bm->pci_dev->dev, bm->cur_prd_addr,
+                             s->io_buffer + s->io_buffer_index, l);
             }
             bm->cur_prd_addr += l;
             bm->cur_prd_len -= l;
@@ -326,7 +327,7 @@ void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val)
     bm->cmd = val & 0x09;
 }
 
-static uint64_t bmdma_addr_read(void *opaque, target_phys_addr_t addr,
+static uint64_t bmdma_addr_read(void *opaque, dma_addr_t addr,
                                 unsigned width)
 {
     BMDMAState *bm = opaque;
@@ -340,7 +341,7 @@ static uint64_t bmdma_addr_read(void *opaque, target_phys_addr_t addr,
     return data;
 }
 
-static void bmdma_addr_write(void *opaque, target_phys_addr_t addr,
+static void bmdma_addr_write(void *opaque, dma_addr_t addr,
                              uint64_t data, unsigned width)
 {
     BMDMAState *bm = opaque;
commit fa0ce55c7157f6fd1cf385d1f59f87baea1d9704
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Oct 31 17:06:55 2011 +1100

    intel-hda: Use PCI DMA stub functions
    
    This updates the intel-hda device emulation to use the explicit PCI DMA
    functions, instead of directly calling physical memory access functions.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index 675b659..02def4c 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -24,6 +24,7 @@
 #include "audiodev.h"
 #include "intel-hda.h"
 #include "intel-hda-defs.h"
+#include "dma.h"
 
 /* --------------------------------------------------------------------- */
 /* hda bus                                                               */
@@ -328,7 +329,7 @@ static void intel_hda_corb_run(IntelHDAState *d)
 
         rp = (d->corb_rp + 1) & 0xff;
         addr = intel_hda_addr(d->corb_lbase, d->corb_ubase);
-        verb = ldl_le_phys(addr + 4*rp);
+        verb = ldl_le_pci_dma(&d->pci, addr + 4*rp);
         d->corb_rp = rp;
 
         dprint(d, 2, "%s: [rp 0x%x] verb 0x%08x\n", __FUNCTION__, rp, verb);
@@ -360,8 +361,8 @@ static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t res
     ex = (solicited ? 0 : (1 << 4)) | dev->cad;
     wp = (d->rirb_wp + 1) & 0xff;
     addr = intel_hda_addr(d->rirb_lbase, d->rirb_ubase);
-    stl_le_phys(addr + 8*wp, response);
-    stl_le_phys(addr + 8*wp + 4, ex);
+    stl_le_pci_dma(&d->pci, addr + 8*wp, response);
+    stl_le_pci_dma(&d->pci, addr + 8*wp + 4, ex);
     d->rirb_wp = wp;
 
     dprint(d, 2, "%s: [wp 0x%x] response 0x%x, extra 0x%x\n",
@@ -426,8 +427,7 @@ static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output,
         dprint(d, 3, "dma: entry %d, pos %d/%d, copy %d\n",
                st->be, st->bp, st->bpl[st->be].len, copy);
 
-        cpu_physical_memory_rw(st->bpl[st->be].addr + st->bp,
-                               buf, copy, !output);
+        pci_dma_rw(&d->pci, st->bpl[st->be].addr + st->bp, buf, copy, !output);
         st->lpib += copy;
         st->bp += copy;
         buf += copy;
@@ -449,7 +449,7 @@ static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output,
     }
     if (d->dp_lbase & 0x01) {
         addr = intel_hda_addr(d->dp_lbase & ~0x01, d->dp_ubase);
-        stl_le_phys(addr + 8*s, st->lpib);
+        stl_le_pci_dma(&d->pci, addr + 8*s, st->lpib);
     }
     dprint(d, 3, "dma: --\n");
 
@@ -471,7 +471,7 @@ static void intel_hda_parse_bdl(IntelHDAState *d, IntelHDAStream *st)
     g_free(st->bpl);
     st->bpl = g_malloc(sizeof(bpl) * st->bentries);
     for (i = 0; i < st->bentries; i++, addr += 16) {
-        cpu_physical_memory_read(addr, buf, 16);
+        pci_dma_read(&d->pci, addr, buf, 16);
         st->bpl[i].addr  = le64_to_cpu(*(uint64_t *)buf);
         st->bpl[i].len   = le32_to_cpu(*(uint32_t *)(buf + 8));
         st->bpl[i].flags = le32_to_cpu(*(uint32_t *)(buf + 12));
commit 14fecf26d06de52658a343cf78077a80c60cc121
Author: Eduard - Gabriel Munteanu <eduard.munteanu at linux360.ro>
Date:   Mon Oct 31 17:06:54 2011 +1100

    pcnet-pci: Use PCI DMA stub functions
    
    This updates the pcnet-pci device emulation to use the explicit PCI DMA
    functions, instead of directly calling physical memory access functions.
    
    Signed-off-by: Eduard - Gabriel Munteanu <eduard.munteanu at linux360.ro>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c
index fb2a00c..41a6e07 100644
--- a/hw/pcnet-pci.c
+++ b/hw/pcnet-pci.c
@@ -31,6 +31,7 @@
 #include "net.h"
 #include "loader.h"
 #include "qemu-timer.h"
+#include "dma.h"
 
 #include "pcnet.h"
 
@@ -230,13 +231,13 @@ static const MemoryRegionOps pcnet_mmio_ops = {
 static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr,
                                       uint8_t *buf, int len, int do_bswap)
 {
-    cpu_physical_memory_write(addr, buf, len);
+    pci_dma_write(dma_opaque, addr, buf, len);
 }
 
 static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr,
                                      uint8_t *buf, int len, int do_bswap)
 {
-    cpu_physical_memory_read(addr, buf, len);
+    pci_dma_read(dma_opaque, addr, buf, len);
 }
 
 static void pci_pcnet_cleanup(VLANClientState *nc)
@@ -302,6 +303,7 @@ static int pci_pcnet_init(PCIDevice *pci_dev)
     s->irq = pci_dev->irq[0];
     s->phys_mem_read = pci_physical_memory_read;
     s->phys_mem_write = pci_physical_memory_write;
+    s->dma_opaque = pci_dev;
 
     if (!pci_dev->qdev.hotplugged) {
         static int loaded = 0;
commit 9ba4524cda1348cbe741535f77815dca6a57da05
Author: Eduard - Gabriel Munteanu <eduard.munteanu at linux360.ro>
Date:   Mon Oct 31 17:06:53 2011 +1100

    lsi53c895a: Use PCI DMA stub functions
    
    This updates the lsi53c895a device emulation to use the explicit PCI DMA
    functions, instead of directly calling physical memory access functions.
    
    Signed-off-by: Eduard - Gabriel Munteanu <eduard.munteanu at linux360.ro>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 2984cea..fcc27d7 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -15,6 +15,8 @@
 #include "hw.h"
 #include "pci.h"
 #include "scsi.h"
+#include "block_int.h"
+#include "dma.h"
 
 //#define DEBUG_LSI
 //#define DEBUG_LSI_REG
@@ -390,10 +392,7 @@ static inline uint32_t read_dword(LSIState *s, uint32_t addr)
 {
     uint32_t buf;
 
-    /* XXX: an optimization here used to fast-path the read from scripts
-     * memory.  But that bypasses any iommu.
-     */
-    cpu_physical_memory_read(addr, (uint8_t *)&buf, 4);
+    pci_dma_read(&s->dev, addr, (uint8_t *)&buf, 4);
     return cpu_to_le32(buf);
 }
 
@@ -532,7 +531,7 @@ static void lsi_bad_selection(LSIState *s, uint32_t id)
 static void lsi_do_dma(LSIState *s, int out)
 {
     uint32_t count;
-    target_phys_addr_t addr;
+    dma_addr_t addr;
     SCSIDevice *dev;
 
     assert(s->current);
@@ -558,7 +557,7 @@ static void lsi_do_dma(LSIState *s, int out)
     else if (s->sbms)
         addr |= ((uint64_t)s->sbms << 32);
 
-    DPRINTF("DMA addr=0x" TARGET_FMT_plx " len=%d\n", addr, count);
+    DPRINTF("DMA addr=0x" DMA_ADDR_FMT " len=%d\n", addr, count);
     s->csbc += count;
     s->dnad += count;
     s->dbc -= count;
@@ -567,9 +566,9 @@ static void lsi_do_dma(LSIState *s, int out)
     }
     /* ??? Set SFBR to first data byte.  */
     if (out) {
-        cpu_physical_memory_read(addr, s->current->dma_buf, count);
+        pci_dma_read(&s->dev, addr, s->current->dma_buf, count);
     } else {
-        cpu_physical_memory_write(addr, s->current->dma_buf, count);
+        pci_dma_write(&s->dev, addr, s->current->dma_buf, count);
     }
     s->current->dma_len -= count;
     if (s->current->dma_len == 0) {
@@ -762,7 +761,7 @@ static void lsi_do_command(LSIState *s)
     DPRINTF("Send command len=%d\n", s->dbc);
     if (s->dbc > 16)
         s->dbc = 16;
-    cpu_physical_memory_read(s->dnad, buf, s->dbc);
+    pci_dma_read(&s->dev, s->dnad, buf, s->dbc);
     s->sfbr = buf[0];
     s->command_complete = 0;
 
@@ -813,7 +812,7 @@ static void lsi_do_status(LSIState *s)
     s->dbc = 1;
     status = s->status;
     s->sfbr = status;
-    cpu_physical_memory_write(s->dnad, &status, 1);
+    pci_dma_write(&s->dev, s->dnad, &status, 1);
     lsi_set_phase(s, PHASE_MI);
     s->msg_action = 1;
     lsi_add_msg_byte(s, 0); /* COMMAND COMPLETE */
@@ -827,7 +826,7 @@ static void lsi_do_msgin(LSIState *s)
     len = s->msg_len;
     if (len > s->dbc)
         len = s->dbc;
-    cpu_physical_memory_write(s->dnad, s->msg, len);
+    pci_dma_write(&s->dev, s->dnad, s->msg, len);
     /* Linux drivers rely on the last byte being in the SIDL.  */
     s->sidl = s->msg[len - 1];
     s->msg_len -= len;
@@ -859,7 +858,7 @@ static void lsi_do_msgin(LSIState *s)
 static uint8_t lsi_get_msgbyte(LSIState *s)
 {
     uint8_t data;
-    cpu_physical_memory_read(s->dnad, &data, 1);
+    pci_dma_read(&s->dev, s->dnad, &data, 1);
     s->dnad++;
     s->dbc--;
     return data;
@@ -1011,8 +1010,8 @@ static void lsi_memcpy(LSIState *s, uint32_t dest, uint32_t src, int count)
     DPRINTF("memcpy dest 0x%08x src 0x%08x count %d\n", dest, src, count);
     while (count) {
         n = (count > LSI_BUF_SIZE) ? LSI_BUF_SIZE : count;
-        cpu_physical_memory_read(src, buf, n);
-        cpu_physical_memory_write(dest, buf, n);
+        pci_dma_read(&s->dev, src, buf, n);
+        pci_dma_write(&s->dev, dest, buf, n);
         src += n;
         dest += n;
         count -= n;
@@ -1080,7 +1079,7 @@ again:
 
             /* 32-bit Table indirect */
             offset = sxt24(addr);
-            cpu_physical_memory_read(s->dsa + offset, (uint8_t *)buf, 8);
+            pci_dma_read(&s->dev, s->dsa + offset, (uint8_t *)buf, 8);
             /* byte count is stored in bits 0:23 only */
             s->dbc = cpu_to_le32(buf[0]) & 0xffffff;
             s->rbc = s->dbc;
@@ -1439,7 +1438,7 @@ again:
             n = (insn & 7);
             reg = (insn >> 16) & 0xff;
             if (insn & (1 << 24)) {
-                cpu_physical_memory_read(addr, data, n);
+                pci_dma_read(&s->dev, addr, data, n);
                 DPRINTF("Load reg 0x%x size %d addr 0x%08x = %08x\n", reg, n,
                         addr, *(int *)data);
                 for (i = 0; i < n; i++) {
@@ -1450,7 +1449,7 @@ again:
                 for (i = 0; i < n; i++) {
                     data[i] = lsi_reg_readb(s, reg + i);
                 }
-                cpu_physical_memory_write(addr, data, n);
+                pci_dma_write(&s->dev, addr, data, n);
             }
         }
     }
commit 62ecbd353d25e62c4a6c327ea88ba5404e13507a
Author: Eduard - Gabriel Munteanu <eduard.munteanu at linux360.ro>
Date:   Mon Oct 31 17:06:52 2011 +1100

    e1000: Use PCI DMA stub functions
    
    This updates the e1000 device emulation to use the explicit PCI DMA
    functions, instead of directly calling physical memory access functions.
    
    Signed-off-by: Eduard - Gabriel Munteanu <eduard.munteanu at linux360.ro>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/e1000.c b/hw/e1000.c
index ce8fc8b..986ed9c 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -31,6 +31,7 @@
 #include "net/checksum.h"
 #include "loader.h"
 #include "sysemu.h"
+#include "dma.h"
 
 #include "e1000_hw.h"
 
@@ -465,7 +466,7 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
             bytes = split_size;
             if (tp->size + bytes > msh)
                 bytes = msh - tp->size;
-            cpu_physical_memory_read(addr, tp->data + tp->size, bytes);
+            pci_dma_read(&s->dev, addr, tp->data + tp->size, bytes);
             if ((sz = tp->size + bytes) >= hdr && tp->size < hdr)
                 memmove(tp->header, tp->data, hdr);
             tp->size = sz;
@@ -480,7 +481,7 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
         // context descriptor TSE is not set, while data descriptor TSE is set
         DBGOUT(TXERR, "TCP segmentaion Error\n");
     } else {
-        cpu_physical_memory_read(addr, tp->data + tp->size, split_size);
+        pci_dma_read(&s->dev, addr, tp->data + tp->size, split_size);
         tp->size += split_size;
     }
 
@@ -496,7 +497,7 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
 }
 
 static uint32_t
-txdesc_writeback(target_phys_addr_t base, struct e1000_tx_desc *dp)
+txdesc_writeback(E1000State *s, dma_addr_t base, struct e1000_tx_desc *dp)
 {
     uint32_t txd_upper, txd_lower = le32_to_cpu(dp->lower.data);
 
@@ -505,8 +506,8 @@ txdesc_writeback(target_phys_addr_t base, struct e1000_tx_desc *dp)
     txd_upper = (le32_to_cpu(dp->upper.data) | E1000_TXD_STAT_DD) &
                 ~(E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | E1000_TXD_STAT_TU);
     dp->upper.data = cpu_to_le32(txd_upper);
-    cpu_physical_memory_write(base + ((char *)&dp->upper - (char *)dp),
-                              (void *)&dp->upper, sizeof(dp->upper));
+    pci_dma_write(&s->dev, base + ((char *)&dp->upper - (char *)dp),
+                  (void *)&dp->upper, sizeof(dp->upper));
     return E1000_ICR_TXDW;
 }
 
@@ -521,7 +522,7 @@ static uint64_t tx_desc_base(E1000State *s)
 static void
 start_xmit(E1000State *s)
 {
-    target_phys_addr_t base;
+    dma_addr_t base;
     struct e1000_tx_desc desc;
     uint32_t tdh_start = s->mac_reg[TDH], cause = E1000_ICS_TXQE;
 
@@ -533,14 +534,14 @@ start_xmit(E1000State *s)
     while (s->mac_reg[TDH] != s->mac_reg[TDT]) {
         base = tx_desc_base(s) +
                sizeof(struct e1000_tx_desc) * s->mac_reg[TDH];
-        cpu_physical_memory_read(base, (void *)&desc, sizeof(desc));
+        pci_dma_read(&s->dev, base, (void *)&desc, sizeof(desc));
 
         DBGOUT(TX, "index %d: %p : %x %x\n", s->mac_reg[TDH],
                (void *)(intptr_t)desc.buffer_addr, desc.lower.data,
                desc.upper.data);
 
         process_tx_desc(s, &desc);
-        cause |= txdesc_writeback(base, &desc);
+        cause |= txdesc_writeback(s, base, &desc);
 
         if (++s->mac_reg[TDH] * sizeof(desc) >= s->mac_reg[TDLEN])
             s->mac_reg[TDH] = 0;
@@ -668,7 +669,7 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
 {
     E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque;
     struct e1000_rx_desc desc;
-    target_phys_addr_t base;
+    dma_addr_t base;
     unsigned int n, rdt;
     uint32_t rdh_start;
     uint16_t vlan_special = 0;
@@ -713,7 +714,7 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
             desc_size = s->rxbuf_size;
         }
         base = rx_desc_base(s) + sizeof(desc) * s->mac_reg[RDH];
-        cpu_physical_memory_read(base, (void *)&desc, sizeof(desc));
+        pci_dma_read(&s->dev, base, (void *)&desc, sizeof(desc));
         desc.special = vlan_special;
         desc.status |= (vlan_status | E1000_RXD_STAT_DD);
         if (desc.buffer_addr) {
@@ -722,9 +723,9 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
                 if (copy_size > s->rxbuf_size) {
                     copy_size = s->rxbuf_size;
                 }
-                cpu_physical_memory_write(le64_to_cpu(desc.buffer_addr),
-                                          (void *)(buf + desc_offset + vlan_offset),
-                                          copy_size);
+                pci_dma_write(&s->dev, le64_to_cpu(desc.buffer_addr),
+                                 (void *)(buf + desc_offset + vlan_offset),
+                                 copy_size);
             }
             desc_offset += desc_size;
             desc.length = cpu_to_le16(desc_size);
@@ -738,7 +739,7 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
         } else { // as per intel docs; skip descriptors with null buf addr
             DBGOUT(RX, "Null RX descriptor!!\n");
         }
-        cpu_physical_memory_write(base, (void *)&desc, sizeof(desc));
+        pci_dma_write(&s->dev, base, (void *)&desc, sizeof(desc));
 
         if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN])
             s->mac_reg[RDH] = 0;
commit 3204db98de7dd0bd25a2223fd324313c610cc029
Author: Eduard - Gabriel Munteanu <eduard.munteanu at linux360.ro>
Date:   Mon Oct 31 17:06:51 2011 +1100

    es1370: Use PCI DMA stub functions
    
    This updates the es1370 device emulation to use the explicit PCI DMA
    functions, instead of directly calling physical memory access functions.
    
    Signed-off-by: Eduard - Gabriel Munteanu <eduard.munteanu at linux360.ro>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/es1370.c b/hw/es1370.c
index 2daadde..c5c16b0 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -30,6 +30,7 @@
 #include "audiodev.h"
 #include "audio/audio.h"
 #include "pci.h"
+#include "dma.h"
 
 /* Missing stuff:
    SCTRL_P[12](END|ST)INC
@@ -802,7 +803,7 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel,
             if (!acquired)
                 break;
 
-            cpu_physical_memory_write (addr, tmpbuf, acquired);
+            pci_dma_write (&s->dev, addr, tmpbuf, acquired);
 
             temp -= acquired;
             addr += acquired;
@@ -816,7 +817,7 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel,
             int copied, to_copy;
 
             to_copy = audio_MIN ((size_t) temp, sizeof (tmpbuf));
-            cpu_physical_memory_read (addr, tmpbuf, to_copy);
+            pci_dma_read (&s->dev, addr, tmpbuf, to_copy);
             copied = AUD_write (voice, tmpbuf, to_copy);
             if (!copied)
                 break;
commit 93f43c48887a4e5b651965955eedd8e838e53db3
Author: Eduard - Gabriel Munteanu <eduard.munteanu at linux360.ro>
Date:   Mon Oct 31 17:06:50 2011 +1100

    ac97: Use PCI DMA stub functions
    
    This updates the ac97 device emulation to use the explicit PCI DMA
    functions, instead of directly calling physical memory access functions.
    
    Signed-off-by: Eduard - Gabriel Munteanu <eduard.munteanu at linux360.ro>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ac97.c b/hw/ac97.c
index bc69d4e..6800af4 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -18,6 +18,7 @@
 #include "audiodev.h"
 #include "audio/audio.h"
 #include "pci.h"
+#include "dma.h"
 
 enum {
     AC97_Reset                     = 0x00,
@@ -224,7 +225,7 @@ static void fetch_bd (AC97LinkState *s, AC97BusMasterRegs *r)
 {
     uint8_t b[8];
 
-    cpu_physical_memory_read (r->bdbar + r->civ * 8, b, 8);
+    pci_dma_read (&s->dev, r->bdbar + r->civ * 8, b, 8);
     r->bd_valid = 1;
     r->bd.addr = le32_to_cpu (*(uint32_t *) &b[0]) & ~3;
     r->bd.ctl_len = le32_to_cpu (*(uint32_t *) &b[4]);
@@ -973,7 +974,7 @@ static int write_audio (AC97LinkState *s, AC97BusMasterRegs *r,
     while (temp) {
         int copied;
         to_copy = audio_MIN (temp, sizeof (tmpbuf));
-        cpu_physical_memory_read (addr, tmpbuf, to_copy);
+        pci_dma_read (&s->dev, addr, tmpbuf, to_copy);
         copied = AUD_write (s->voice_po, tmpbuf, to_copy);
         dolog ("write_audio max=%x to_copy=%x copied=%x\n",
                max, to_copy, copied);
@@ -1054,7 +1055,7 @@ static int read_audio (AC97LinkState *s, AC97BusMasterRegs *r,
             *stop = 1;
             break;
         }
-        cpu_physical_memory_write (addr, tmpbuf, acquired);
+        pci_dma_write (&s->dev, addr, tmpbuf, acquired);
         temp -= acquired;
         addr += acquired;
         nread += acquired;
commit 16ef60c9a8eeee269f7cbc95219a431b1d7cbf29
Author: Eduard - Gabriel Munteanu <eduard.munteanu at linux360.ro>
Date:   Mon Oct 31 17:06:49 2011 +1100

    eepro100: Use PCI DMA stub functions
    
    This updates the eepro100 device emulation to use the explicit PCI DMA
    functions, instead of directly calling physical memory access functions.
    
    Signed-off-by: Eduard - Gabriel Munteanu <eduard.munteanu at linux360.ro>
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/eepro100.c b/hw/eepro100.c
index 4e3c52f..7d59e71 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -46,6 +46,7 @@
 #include "net.h"
 #include "eeprom93xx.h"
 #include "sysemu.h"
+#include "dma.h"
 
 /* QEMU sends frames smaller than 60 bytes to ethernet nics.
  * Such frames are rejected by real nics and their emulations.
@@ -315,38 +316,6 @@ static const uint16_t eepro100_mdi_mask[] = {
     0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
 };
 
-/* Read a 16 bit little endian value from physical memory. */
-static uint16_t e100_ldw_le_phys(target_phys_addr_t addr)
-{
-    /* Load 16 bit (little endian) word from emulated hardware. */
-    uint16_t val;
-    cpu_physical_memory_read(addr, &val, sizeof(val));
-    return le16_to_cpu(val);
-}
-
-/* Read a 32 bit little endian value from physical memory. */
-static uint32_t e100_ldl_le_phys(target_phys_addr_t addr)
-{
-    /* Load 32 bit (little endian) word from emulated hardware. */
-    uint32_t val;
-    cpu_physical_memory_read(addr, &val, sizeof(val));
-    return le32_to_cpu(val);
-}
-
-/* Write a 16 bit little endian value to physical memory. */
-static void e100_stw_le_phys(target_phys_addr_t addr, uint16_t val)
-{
-    val = cpu_to_le16(val);
-    cpu_physical_memory_write(addr, &val, sizeof(val));
-}
-
-/* Write a 32 bit little endian value to physical memory. */
-static void e100_stl_le_phys(target_phys_addr_t addr, uint32_t val)
-{
-    val = cpu_to_le32(val);
-    cpu_physical_memory_write(addr, &val, sizeof(val));
-}
-
 #define POLYNOMIAL 0x04c11db6
 
 /* From FreeBSD */
@@ -744,21 +713,26 @@ static void dump_statistics(EEPRO100State * s)
      * values which really matter.
      * Number of data should check configuration!!!
      */
-    cpu_physical_memory_write(s->statsaddr, &s->statistics, s->stats_size);
-    e100_stl_le_phys(s->statsaddr + 0, s->statistics.tx_good_frames);
-    e100_stl_le_phys(s->statsaddr + 36, s->statistics.rx_good_frames);
-    e100_stl_le_phys(s->statsaddr + 48, s->statistics.rx_resource_errors);
-    e100_stl_le_phys(s->statsaddr + 60, s->statistics.rx_short_frame_errors);
+    pci_dma_write(&s->dev, s->statsaddr,
+                  (uint8_t *) &s->statistics, s->stats_size);
+    stl_le_pci_dma(&s->dev, s->statsaddr + 0,
+                   s->statistics.tx_good_frames);
+    stl_le_pci_dma(&s->dev, s->statsaddr + 36,
+                   s->statistics.rx_good_frames);
+    stl_le_pci_dma(&s->dev, s->statsaddr + 48,
+                   s->statistics.rx_resource_errors);
+    stl_le_pci_dma(&s->dev, s->statsaddr + 60,
+                   s->statistics.rx_short_frame_errors);
 #if 0
-    e100_stw_le_phys(s->statsaddr + 76, s->statistics.xmt_tco_frames);
-    e100_stw_le_phys(s->statsaddr + 78, s->statistics.rcv_tco_frames);
+    stw_le_pci_dma(&s->dev, s->statsaddr + 76, s->statistics.xmt_tco_frames);
+    stw_le_pci_dma(&s->dev, s->statsaddr + 78, s->statistics.rcv_tco_frames);
     missing("CU dump statistical counters");
 #endif
 }
 
 static void read_cb(EEPRO100State *s)
 {
-    cpu_physical_memory_read(s->cb_address, &s->tx, sizeof(s->tx));
+    pci_dma_read(&s->dev, s->cb_address, (uint8_t *) &s->tx, sizeof(s->tx));
     s->tx.status = le16_to_cpu(s->tx.status);
     s->tx.command = le16_to_cpu(s->tx.command);
     s->tx.link = le32_to_cpu(s->tx.link);
@@ -788,18 +762,17 @@ static void tx_command(EEPRO100State *s)
     }
     assert(tcb_bytes <= sizeof(buf));
     while (size < tcb_bytes) {
-        uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address);
-        uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4);
+        uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, tbd_address);
+        uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, tbd_address + 4);
 #if 0
-        uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6);
+        uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, tbd_address + 6);
 #endif
         tbd_address += 8;
         TRACE(RXTX, logout
             ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n",
              tx_buffer_address, tx_buffer_size));
         tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
-        cpu_physical_memory_read(tx_buffer_address, &buf[size],
-                                 tx_buffer_size);
+        pci_dma_read(&s->dev, tx_buffer_address, &buf[size], tx_buffer_size);
         size += tx_buffer_size;
     }
     if (tbd_array == 0xffffffff) {
@@ -810,16 +783,19 @@ static void tx_command(EEPRO100State *s)
         if (s->has_extended_tcb_support && !(s->configuration[6] & BIT(4))) {
             /* Extended Flexible TCB. */
             for (; tbd_count < 2; tbd_count++) {
-                uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address);
-                uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4);
-                uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6);
+                uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev,
+                                                            tbd_address);
+                uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev,
+                                                          tbd_address + 4);
+                uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev,
+                                                        tbd_address + 6);
                 tbd_address += 8;
                 TRACE(RXTX, logout
                     ("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n",
                      tx_buffer_address, tx_buffer_size));
                 tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
-                cpu_physical_memory_read(tx_buffer_address, &buf[size],
-                                         tx_buffer_size);
+                pci_dma_read(&s->dev, tx_buffer_address,
+                             &buf[size], tx_buffer_size);
                 size += tx_buffer_size;
                 if (tx_buffer_el & 1) {
                     break;
@@ -828,16 +804,16 @@ static void tx_command(EEPRO100State *s)
         }
         tbd_address = tbd_array;
         for (; tbd_count < s->tx.tbd_count; tbd_count++) {
-            uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address);
-            uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4);
-            uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6);
+            uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, tbd_address);
+            uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, tbd_address + 4);
+            uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, tbd_address + 6);
             tbd_address += 8;
             TRACE(RXTX, logout
                 ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n",
                  tx_buffer_address, tx_buffer_size));
             tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
-            cpu_physical_memory_read(tx_buffer_address, &buf[size],
-                                     tx_buffer_size);
+            pci_dma_read(&s->dev, tx_buffer_address,
+                         &buf[size], tx_buffer_size);
             size += tx_buffer_size;
             if (tx_buffer_el & 1) {
                 break;
@@ -862,7 +838,7 @@ static void set_multicast_list(EEPRO100State *s)
     TRACE(OTHER, logout("multicast list, multicast count = %u\n", multicast_count));
     for (i = 0; i < multicast_count; i += 6) {
         uint8_t multicast_addr[6];
-        cpu_physical_memory_read(s->cb_address + 10 + i, multicast_addr, 6);
+        pci_dma_read(&s->dev, s->cb_address + 10 + i, multicast_addr, 6);
         TRACE(OTHER, logout("multicast entry %s\n", nic_dump(multicast_addr, 6)));
         unsigned mcast_idx = compute_mcast_idx(multicast_addr);
         assert(mcast_idx < 64);
@@ -896,12 +872,12 @@ static void action_command(EEPRO100State *s)
             /* Do nothing. */
             break;
         case CmdIASetup:
-            cpu_physical_memory_read(s->cb_address + 8, &s->conf.macaddr.a[0], 6);
+            pci_dma_read(&s->dev, s->cb_address + 8, &s->conf.macaddr.a[0], 6);
             TRACE(OTHER, logout("macaddr: %s\n", nic_dump(&s->conf.macaddr.a[0], 6)));
             break;
         case CmdConfigure:
-            cpu_physical_memory_read(s->cb_address + 8, &s->configuration[0],
-                                     sizeof(s->configuration));
+            pci_dma_read(&s->dev, s->cb_address + 8,
+                         &s->configuration[0], sizeof(s->configuration));
             TRACE(OTHER, logout("configuration: %s\n",
                                 nic_dump(&s->configuration[0], 16)));
             TRACE(OTHER, logout("configuration: %s\n",
@@ -938,7 +914,8 @@ static void action_command(EEPRO100State *s)
             break;
         }
         /* Write new status. */
-        e100_stw_le_phys(s->cb_address, s->tx.status | ok_status | STATUS_C);
+        stw_le_pci_dma(&s->dev, s->cb_address,
+                       s->tx.status | ok_status | STATUS_C);
         if (bit_i) {
             /* CU completed action. */
             eepro100_cx_interrupt(s);
@@ -1005,7 +982,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
         /* Dump statistical counters. */
         TRACE(OTHER, logout("val=0x%02x (dump stats)\n", val));
         dump_statistics(s);
-        e100_stl_le_phys(s->statsaddr + s->stats_size, 0xa005);
+        stl_le_pci_dma(&s->dev, s->statsaddr + s->stats_size, 0xa005);
         break;
     case CU_CMD_BASE:
         /* Load CU base. */
@@ -1016,7 +993,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
         /* Dump and reset statistical counters. */
         TRACE(OTHER, logout("val=0x%02x (dump stats and reset)\n", val));
         dump_statistics(s);
-        e100_stl_le_phys(s->statsaddr + s->stats_size, 0xa007);
+        stl_le_pci_dma(&s->dev, s->statsaddr + s->stats_size, 0xa007);
         memset(&s->statistics, 0, sizeof(s->statistics));
         break;
     case CU_SRESUME:
@@ -1310,10 +1287,10 @@ static void eepro100_write_port(EEPRO100State *s)
     case PORT_SELFTEST:
         TRACE(OTHER, logout("selftest address=0x%08x\n", address));
         eepro100_selftest_t data;
-        cpu_physical_memory_read(address, &data, sizeof(data));
+        pci_dma_read(&s->dev, address, (uint8_t *) &data, sizeof(data));
         data.st_sign = 0xffffffff;
         data.st_result = 0;
-        cpu_physical_memory_write(address, &data, sizeof(data));
+        pci_dma_write(&s->dev, address, (uint8_t *) &data, sizeof(data));
         break;
     case PORT_SELECTIVE_RESET:
         TRACE(OTHER, logout("selective reset, selftest address=0x%08x\n", address));
@@ -1729,8 +1706,8 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
     }
     /* !!! */
     eepro100_rx_t rx;
-    cpu_physical_memory_read(s->ru_base + s->ru_offset, &rx,
-                             sizeof(eepro100_rx_t));
+    pci_dma_read(&s->dev, s->ru_base + s->ru_offset,
+                 (uint8_t *) &rx, sizeof(eepro100_rx_t));
     uint16_t rfd_command = le16_to_cpu(rx.command);
     uint16_t rfd_size = le16_to_cpu(rx.size);
 
@@ -1746,10 +1723,10 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
 #endif
     TRACE(OTHER, logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n",
           rfd_command, rx.link, rx.rx_buf_addr, rfd_size));
-    e100_stw_le_phys(s->ru_base + s->ru_offset +
-                     offsetof(eepro100_rx_t, status), rfd_status);
-    e100_stw_le_phys(s->ru_base + s->ru_offset +
-                     offsetof(eepro100_rx_t, count), size);
+    stw_le_pci_dma(&s->dev, s->ru_base + s->ru_offset +
+                offsetof(eepro100_rx_t, status), rfd_status);
+    stw_le_pci_dma(&s->dev, s->ru_base + s->ru_offset +
+                offsetof(eepro100_rx_t, count), size);
     /* Early receive interrupt not supported. */
 #if 0
     eepro100_er_interrupt(s);
@@ -1763,8 +1740,8 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
 #if 0
     assert(!(s->configuration[17] & BIT(0)));
 #endif
-    cpu_physical_memory_write(s->ru_base + s->ru_offset +
-                              sizeof(eepro100_rx_t), buf, size);
+    pci_dma_write(&s->dev, s->ru_base + s->ru_offset +
+                  sizeof(eepro100_rx_t), buf, size);
     s->statistics.rx_good_frames++;
     eepro100_fr_interrupt(s);
     s->ru_offset = le32_to_cpu(rx.link);
commit 3ada003aee2004d24f23b9cd6f4eda87d9601ddb
Author: Eduard - Gabriel Munteanu <eduard.munteanu at linux360.ro>
Date:   Mon Oct 31 17:06:48 2011 +1100

    rtl8139: Use PCI DMA stub functions
    
    This updates the rtl8139 device emulation to use the explicit PCI DMA
    functions, instead of directly calling physical memory access functions.
    
    Signed-off-by: Eduard - Gabriel Munteanu <eduard.munteanu at linux360.ro>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 3753950..4c37993 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -53,6 +53,7 @@
 
 #include "hw.h"
 #include "pci.h"
+#include "dma.h"
 #include "qemu-timer.h"
 #include "net.h"
 #include "loader.h"
@@ -427,9 +428,6 @@ typedef struct RTL8139TallyCounters
 /* Clears all tally counters */
 static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters);
 
-/* Writes tally counters to specified physical memory address */
-static void RTL8139TallyCounters_physical_memory_write(target_phys_addr_t tc_addr, RTL8139TallyCounters* counters);
-
 typedef struct RTL8139State {
     PCIDevice dev;
     uint8_t phys[8]; /* mac address */
@@ -512,6 +510,9 @@ typedef struct RTL8139State {
     int rtl8139_mmio_io_addr_dummy;
 } RTL8139State;
 
+/* Writes tally counters to memory via DMA */
+static void RTL8139TallyCounters_dma_write(RTL8139State *s, dma_addr_t tc_addr);
+
 static void rtl8139_set_next_tctr_time(RTL8139State *s, int64_t current_time);
 
 static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command)
@@ -773,15 +774,15 @@ static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size)
 
             if (size > wrapped)
             {
-                cpu_physical_memory_write( s->RxBuf + s->RxBufAddr,
-                                           buf, size-wrapped );
+                pci_dma_write(&s->dev, s->RxBuf + s->RxBufAddr,
+                              buf, size-wrapped);
             }
 
             /* reset buffer pointer */
             s->RxBufAddr = 0;
 
-            cpu_physical_memory_write( s->RxBuf + s->RxBufAddr,
-                                       buf + (size-wrapped), wrapped );
+            pci_dma_write(&s->dev, s->RxBuf + s->RxBufAddr,
+                          buf + (size-wrapped), wrapped);
 
             s->RxBufAddr = wrapped;
 
@@ -790,13 +791,13 @@ static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size)
     }
 
     /* non-wrapping path or overwrapping enabled */
-    cpu_physical_memory_write( s->RxBuf + s->RxBufAddr, buf, size );
+    pci_dma_write(&s->dev, s->RxBuf + s->RxBufAddr, buf, size);
 
     s->RxBufAddr += size;
 }
 
 #define MIN_BUF_SIZE 60
-static inline target_phys_addr_t rtl8139_addr64(uint32_t low, uint32_t high)
+static inline dma_addr_t rtl8139_addr64(uint32_t low, uint32_t high)
 {
 #if TARGET_PHYS_ADDR_BITS > 32
     return low | ((target_phys_addr_t)high << 32);
@@ -979,24 +980,24 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 /* w3 high 32bit of Rx buffer ptr */
 
         int descriptor = s->currCPlusRxDesc;
-        target_phys_addr_t cplus_rx_ring_desc;
+        dma_addr_t cplus_rx_ring_desc;
 
         cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI);
         cplus_rx_ring_desc += 16 * descriptor;
 
         DPRINTF("+++ C+ mode reading RX descriptor %d from host memory at "
-            "%08x %08x = "TARGET_FMT_plx"\n", descriptor, s->RxRingAddrHI,
+            "%08x %08x = "DMA_ADDR_FMT"\n", descriptor, s->RxRingAddrHI,
             s->RxRingAddrLO, cplus_rx_ring_desc);
 
         uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI;
 
-        cpu_physical_memory_read(cplus_rx_ring_desc,    (uint8_t *)&val, 4);
+        pci_dma_read(&s->dev, cplus_rx_ring_desc, (uint8_t *)&val, 4);
         rxdw0 = le32_to_cpu(val);
-        cpu_physical_memory_read(cplus_rx_ring_desc+4,  (uint8_t *)&val, 4);
+        pci_dma_read(&s->dev, cplus_rx_ring_desc+4, (uint8_t *)&val, 4);
         rxdw1 = le32_to_cpu(val);
-        cpu_physical_memory_read(cplus_rx_ring_desc+8,  (uint8_t *)&val, 4);
+        pci_dma_read(&s->dev, cplus_rx_ring_desc+8, (uint8_t *)&val, 4);
         rxbufLO = le32_to_cpu(val);
-        cpu_physical_memory_read(cplus_rx_ring_desc+12, (uint8_t *)&val, 4);
+        pci_dma_read(&s->dev, cplus_rx_ring_desc+12, (uint8_t *)&val, 4);
         rxbufHI = le32_to_cpu(val);
 
         DPRINTF("+++ C+ mode RX descriptor %d %08x %08x %08x %08x\n",
@@ -1060,16 +1061,16 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
             return size_;
         }
 
-        target_phys_addr_t rx_addr = rtl8139_addr64(rxbufLO, rxbufHI);
+        dma_addr_t rx_addr = rtl8139_addr64(rxbufLO, rxbufHI);
 
         /* receive/copy to target memory */
         if (dot1q_buf) {
-            cpu_physical_memory_write(rx_addr, buf, 2 * ETHER_ADDR_LEN);
-            cpu_physical_memory_write(rx_addr + 2 * ETHER_ADDR_LEN,
-                buf + 2 * ETHER_ADDR_LEN + VLAN_HLEN,
-                size - 2 * ETHER_ADDR_LEN);
+            pci_dma_write(&s->dev, rx_addr, buf, 2 * ETHER_ADDR_LEN);
+            pci_dma_write(&s->dev, rx_addr + 2 * ETHER_ADDR_LEN,
+                          buf + 2 * ETHER_ADDR_LEN + VLAN_HLEN,
+                          size - 2 * ETHER_ADDR_LEN);
         } else {
-            cpu_physical_memory_write(rx_addr, buf, size);
+            pci_dma_write(&s->dev, rx_addr, buf, size);
         }
 
         if (s->CpCmd & CPlusRxChkSum)
@@ -1079,7 +1080,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 
         /* write checksum */
         val = cpu_to_le32(crc32(0, buf, size_));
-        cpu_physical_memory_write( rx_addr+size, (uint8_t *)&val, 4);
+        pci_dma_write(&s->dev, rx_addr+size, (uint8_t *)&val, 4);
 
 /* first segment of received packet flag */
 #define CP_RX_STATUS_FS (1<<29)
@@ -1125,9 +1126,9 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 
         /* update ring data */
         val = cpu_to_le32(rxdw0);
-        cpu_physical_memory_write(cplus_rx_ring_desc,    (uint8_t *)&val, 4);
+        pci_dma_write(&s->dev, cplus_rx_ring_desc, (uint8_t *)&val, 4);
         val = cpu_to_le32(rxdw1);
-        cpu_physical_memory_write(cplus_rx_ring_desc+4,  (uint8_t *)&val, 4);
+        pci_dma_write(&s->dev, cplus_rx_ring_desc+4, (uint8_t *)&val, 4);
 
         /* update tally counter */
         ++s->tally_counters.RxOk;
@@ -1307,50 +1308,51 @@ static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters)
     counters->TxUndrn = 0;
 }
 
-static void RTL8139TallyCounters_physical_memory_write(target_phys_addr_t tc_addr, RTL8139TallyCounters* tally_counters)
+static void RTL8139TallyCounters_dma_write(RTL8139State *s, dma_addr_t tc_addr)
 {
+    RTL8139TallyCounters *tally_counters = &s->tally_counters;
     uint16_t val16;
     uint32_t val32;
     uint64_t val64;
 
     val64 = cpu_to_le64(tally_counters->TxOk);
-    cpu_physical_memory_write(tc_addr + 0,    (uint8_t *)&val64, 8);
+    pci_dma_write(&s->dev, tc_addr + 0,     (uint8_t *)&val64, 8);
 
     val64 = cpu_to_le64(tally_counters->RxOk);
-    cpu_physical_memory_write(tc_addr + 8,    (uint8_t *)&val64, 8);
+    pci_dma_write(&s->dev, tc_addr + 8,     (uint8_t *)&val64, 8);
 
     val64 = cpu_to_le64(tally_counters->TxERR);
-    cpu_physical_memory_write(tc_addr + 16,    (uint8_t *)&val64, 8);
+    pci_dma_write(&s->dev, tc_addr + 16,    (uint8_t *)&val64, 8);
 
     val32 = cpu_to_le32(tally_counters->RxERR);
-    cpu_physical_memory_write(tc_addr + 24,    (uint8_t *)&val32, 4);
+    pci_dma_write(&s->dev, tc_addr + 24,    (uint8_t *)&val32, 4);
 
     val16 = cpu_to_le16(tally_counters->MissPkt);
-    cpu_physical_memory_write(tc_addr + 28,    (uint8_t *)&val16, 2);
+    pci_dma_write(&s->dev, tc_addr + 28,    (uint8_t *)&val16, 2);
 
     val16 = cpu_to_le16(tally_counters->FAE);
-    cpu_physical_memory_write(tc_addr + 30,    (uint8_t *)&val16, 2);
+    pci_dma_write(&s->dev, tc_addr + 30,    (uint8_t *)&val16, 2);
 
     val32 = cpu_to_le32(tally_counters->Tx1Col);
-    cpu_physical_memory_write(tc_addr + 32,    (uint8_t *)&val32, 4);
+    pci_dma_write(&s->dev, tc_addr + 32,    (uint8_t *)&val32, 4);
 
     val32 = cpu_to_le32(tally_counters->TxMCol);
-    cpu_physical_memory_write(tc_addr + 36,    (uint8_t *)&val32, 4);
+    pci_dma_write(&s->dev, tc_addr + 36,    (uint8_t *)&val32, 4);
 
     val64 = cpu_to_le64(tally_counters->RxOkPhy);
-    cpu_physical_memory_write(tc_addr + 40,    (uint8_t *)&val64, 8);
+    pci_dma_write(&s->dev, tc_addr + 40,    (uint8_t *)&val64, 8);
 
     val64 = cpu_to_le64(tally_counters->RxOkBrd);
-    cpu_physical_memory_write(tc_addr + 48,    (uint8_t *)&val64, 8);
+    pci_dma_write(&s->dev, tc_addr + 48,    (uint8_t *)&val64, 8);
 
     val32 = cpu_to_le32(tally_counters->RxOkMul);
-    cpu_physical_memory_write(tc_addr + 56,    (uint8_t *)&val32, 4);
+    pci_dma_write(&s->dev, tc_addr + 56,    (uint8_t *)&val32, 4);
 
     val16 = cpu_to_le16(tally_counters->TxAbt);
-    cpu_physical_memory_write(tc_addr + 60,    (uint8_t *)&val16, 2);
+    pci_dma_write(&s->dev, tc_addr + 60,    (uint8_t *)&val16, 2);
 
     val16 = cpu_to_le16(tally_counters->TxUndrn);
-    cpu_physical_memory_write(tc_addr + 62,    (uint8_t *)&val16, 2);
+    pci_dma_write(&s->dev, tc_addr + 62,    (uint8_t *)&val16, 2);
 }
 
 /* Loads values of tally counters from VM state file */
@@ -1842,7 +1844,7 @@ static int rtl8139_transmit_one(RTL8139State *s, int descriptor)
     DPRINTF("+++ transmit reading %d bytes from host memory at 0x%08x\n",
         txsize, s->TxAddr[descriptor]);
 
-    cpu_physical_memory_read(s->TxAddr[descriptor], txbuffer, txsize);
+    pci_dma_read(&s->dev, s->TxAddr[descriptor], txbuffer, txsize);
 
     /* Mark descriptor as transferred */
     s->TxStatus[descriptor] |= TxHostOwns;
@@ -1963,25 +1965,24 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 
     int descriptor = s->currCPlusTxDesc;
 
-    target_phys_addr_t cplus_tx_ring_desc =
-        rtl8139_addr64(s->TxAddr[0], s->TxAddr[1]);
+    dma_addr_t cplus_tx_ring_desc = rtl8139_addr64(s->TxAddr[0], s->TxAddr[1]);
 
     /* Normal priority ring */
     cplus_tx_ring_desc += 16 * descriptor;
 
     DPRINTF("+++ C+ mode reading TX descriptor %d from host memory at "
-        "%08x0x%08x = 0x"TARGET_FMT_plx"\n", descriptor, s->TxAddr[1],
+        "%08x0x%08x = 0x"DMA_ADDR_FMT"\n", descriptor, s->TxAddr[1],
         s->TxAddr[0], cplus_tx_ring_desc);
 
     uint32_t val, txdw0,txdw1,txbufLO,txbufHI;
 
-    cpu_physical_memory_read(cplus_tx_ring_desc,    (uint8_t *)&val, 4);
+    pci_dma_read(&s->dev, cplus_tx_ring_desc,    (uint8_t *)&val, 4);
     txdw0 = le32_to_cpu(val);
-    cpu_physical_memory_read(cplus_tx_ring_desc+4,  (uint8_t *)&val, 4);
+    pci_dma_read(&s->dev, cplus_tx_ring_desc+4,  (uint8_t *)&val, 4);
     txdw1 = le32_to_cpu(val);
-    cpu_physical_memory_read(cplus_tx_ring_desc+8,  (uint8_t *)&val, 4);
+    pci_dma_read(&s->dev, cplus_tx_ring_desc+8,  (uint8_t *)&val, 4);
     txbufLO = le32_to_cpu(val);
-    cpu_physical_memory_read(cplus_tx_ring_desc+12, (uint8_t *)&val, 4);
+    pci_dma_read(&s->dev, cplus_tx_ring_desc+12, (uint8_t *)&val, 4);
     txbufHI = le32_to_cpu(val);
 
     DPRINTF("+++ C+ mode TX descriptor %d %08x %08x %08x %08x\n", descriptor,
@@ -2047,7 +2048,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
     }
 
     int txsize = txdw0 & CP_TX_BUFFER_SIZE_MASK;
-    target_phys_addr_t tx_addr = rtl8139_addr64(txbufLO, txbufHI);
+    dma_addr_t tx_addr = rtl8139_addr64(txbufLO, txbufHI);
 
     /* make sure we have enough space to assemble the packet */
     if (!s->cplus_txbuffer)
@@ -2086,10 +2087,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
     /* append more data to the packet */
 
     DPRINTF("+++ C+ mode transmit reading %d bytes from host memory at "
-        TARGET_FMT_plx" to offset %d\n", txsize, tx_addr,
-        s->cplus_txbuffer_offset);
+            DMA_ADDR_FMT" to offset %d\n", txsize, tx_addr,
+            s->cplus_txbuffer_offset);
 
-    cpu_physical_memory_read(tx_addr, s->cplus_txbuffer + s->cplus_txbuffer_offset, txsize);
+    pci_dma_read(&s->dev, tx_addr,
+                 s->cplus_txbuffer + s->cplus_txbuffer_offset, txsize);
     s->cplus_txbuffer_offset += txsize;
 
     /* seek to next Rx descriptor */
@@ -2116,7 +2118,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 
     /* update ring data */
     val = cpu_to_le32(txdw0);
-    cpu_physical_memory_write(cplus_tx_ring_desc,    (uint8_t *)&val, 4);
+    pci_dma_write(&s->dev, cplus_tx_ring_desc, (uint8_t *)&val, 4);
 
     /* Now decide if descriptor being processed is holding the last segment of packet */
     if (txdw0 & CP_TX_LS)
@@ -2475,7 +2477,7 @@ static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32
             target_phys_addr_t tc_addr = rtl8139_addr64(s->TxStatus[0] & ~0x3f, s->TxStatus[1]);
 
             /* dump tally counters to specified memory location */
-            RTL8139TallyCounters_physical_memory_write( tc_addr, &s->tally_counters);
+            RTL8139TallyCounters_dma_write(s, tc_addr);
 
             /* mark dump completed */
             s->TxStatus[0] &= ~0x8;
commit ec17457588ad944794502cfe1c76a34ff8a11618
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Oct 31 17:06:47 2011 +1100

    Add stub functions for PCI device models to do PCI DMA
    
    This patch adds functions to pci.[ch] to perform PCI DMA operations.
    At present, these are just stubs which perform directly cpu physical
    memory accesses.  Stubs are included which are analogous to
    cpu_physical_memory_{read,write}(), the stX_phys() and ldX_phys()
    functions and cpu_physical_memory_{map,unmap}().
    
    In addition, a wrapper around qemu_sglist_init() is provided, which
    also takes a PCIDevice *.  It's assumed that _init() is the only
    sglist function which will need wrapping, the idea being that once we
    have IOMMU support whatever IOMMU context handle the wrapper derives
    from the PCI device will be stored within the sglist structure for
    later use.
    
    Using these stubs, however, distinguishes PCI device DMA transactions from
    other accesses to physical memory, which will allow PCI IOMMU support to
    be added in one place, rather than updating every PCI driver at that time.
    
    That is, it allows us to update individual PCI drivers to support an IOMMU
    without having yet determined the details of how the IOMMU emulation will
    operate.  This will let us remove the most bitrot-sensitive part of an
    IOMMU patch in advance.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pci.h b/hw/pci.h
index 98f30f7..4b2e785 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -5,6 +5,7 @@
 
 #include "qdev.h"
 #include "memory.h"
+#include "dma.h"
 
 /* PCI includes legacy ISA access.  */
 #include "isa.h"
@@ -483,4 +484,70 @@ static inline uint32_t pci_config_size(const PCIDevice *d)
     return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE;
 }
 
+/* DMA access functions */
+static inline int pci_dma_rw(PCIDevice *dev, dma_addr_t addr,
+                             void *buf, dma_addr_t len, DMADirection dir)
+{
+    cpu_physical_memory_rw(addr, buf, len, dir == DMA_DIRECTION_FROM_DEVICE);
+    return 0;
+}
+
+static inline int pci_dma_read(PCIDevice *dev, dma_addr_t addr,
+                               void *buf, dma_addr_t len)
+{
+    return pci_dma_rw(dev, addr, buf, len, DMA_DIRECTION_TO_DEVICE);
+}
+
+static inline int pci_dma_write(PCIDevice *dev, dma_addr_t addr,
+                                const void *buf, dma_addr_t len)
+{
+    return pci_dma_rw(dev, addr, (void *) buf, len, DMA_DIRECTION_FROM_DEVICE);
+}
+
+#define PCI_DMA_DEFINE_LDST(_l, _s, _bits)                              \
+    static inline uint##_bits##_t ld##_l##_pci_dma(PCIDevice *dev,      \
+                                                   dma_addr_t addr)     \
+    {                                                                   \
+        return ld##_l##_phys(addr);                                     \
+    }                                                                   \
+    static inline void st##_s##_pci_dma(PCIDevice *dev,                 \
+                          dma_addr_t addr, uint##_bits##_t val)         \
+    {                                                                   \
+        st##_s##_phys(addr, val);                                       \
+    }
+
+PCI_DMA_DEFINE_LDST(ub, b, 8);
+PCI_DMA_DEFINE_LDST(uw_le, w_le, 16)
+PCI_DMA_DEFINE_LDST(l_le, l_le, 32);
+PCI_DMA_DEFINE_LDST(q_le, q_le, 64);
+PCI_DMA_DEFINE_LDST(uw_be, w_be, 16)
+PCI_DMA_DEFINE_LDST(l_be, l_be, 32);
+PCI_DMA_DEFINE_LDST(q_be, q_be, 64);
+
+#undef PCI_DMA_DEFINE_LDST
+
+static inline void *pci_dma_map(PCIDevice *dev, dma_addr_t addr,
+                                dma_addr_t *plen, DMADirection dir)
+{
+    target_phys_addr_t len = *plen;
+    void *buf;
+
+    buf = cpu_physical_memory_map(addr, &len, dir == DMA_DIRECTION_FROM_DEVICE);
+    *plen = len;
+    return buf;
+}
+
+static inline void pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len,
+                                 DMADirection dir, dma_addr_t access_len)
+{
+    cpu_physical_memory_unmap(buffer, len, dir == DMA_DIRECTION_FROM_DEVICE,
+                              access_len);
+}
+
+static inline void pci_dma_sglist_init(QEMUSGList *qsg, PCIDevice *dev,
+                                       int alloc_hint)
+{
+    qemu_sglist_init(qsg, alloc_hint);
+}
+
 #endif
commit d32311810fd3da5b68912e71cec6c7e59b1ee3eb
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Oct 31 17:06:46 2011 +1100

    Use dma_addr_t type for scatter/gather code
    
    This patch uses the newly created dma_addr_t type throughout the
    scatter/gather handling code in dma-helpers.c whenever we need to
    represent a dma bus address.  This makes a better distinction as to
    what is a bus address and what is a cpu physical address.  Since we
    don't support IOMMUs yet, they can't be very different for now, but
    that will change in future, and this preliminary helps clarify what's
    going on.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/dma-helpers.c b/dma-helpers.c
index 86d2d0a..bdcd38c 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -18,8 +18,7 @@ void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint)
     qsg->size = 0;
 }
 
-void qemu_sglist_add(QEMUSGList *qsg, target_phys_addr_t base,
-                     target_phys_addr_t len)
+void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len)
 {
     if (qsg->nsg == qsg->nalloc) {
         qsg->nalloc = 2 * qsg->nalloc + 1;
@@ -45,7 +44,7 @@ typedef struct {
     bool to_dev;
     bool in_cancel;
     int sg_cur_index;
-    target_phys_addr_t sg_cur_byte;
+    dma_addr_t sg_cur_byte;
     QEMUIOVector iov;
     QEMUBH *bh;
     DMAIOFunc *io_func;
diff --git a/dma.h b/dma.h
index 56e163a..a13209d 100644
--- a/dma.h
+++ b/dma.h
@@ -28,20 +28,19 @@ typedef enum {
 } DMADirection;
 
 struct ScatterGatherEntry {
-    target_phys_addr_t base;
-    target_phys_addr_t len;
+    dma_addr_t base;
+    dma_addr_t len;
 };
 
 struct QEMUSGList {
     ScatterGatherEntry *sg;
     int nsg;
     int nalloc;
-    target_phys_addr_t size;
+    dma_addr_t size;
 };
 
 void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint);
-void qemu_sglist_add(QEMUSGList *qsg, target_phys_addr_t base,
-                     target_phys_addr_t len);
+void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len);
 void qemu_sglist_destroy(QEMUSGList *qsg);
 #endif
 
commit d9d1055ef1426da47b626883fffdc934c5f5ab91
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Oct 31 17:06:45 2011 +1100

    Define DMA address and direction types
    
    As a preliminary to adding more extensive DMA and IOMMU infrastructure
    support into qemu, this patch defines a dma_addr_t for storing DMA bus
    addresses and a DMADirection enum which describes whether a DMA is
    from an external device to main memory or from main memory to an
    external device.
    
    For now dma_addr_t is just defined to be target_phys_addr_t, but in
    future, we can change this to support machines where we have bus
    addresses which don't necessarily have the same format as CPU physical
    addresses.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/dma.h b/dma.h
index 2bdc236..56e163a 100644
--- a/dma.h
+++ b/dma.h
@@ -18,6 +18,15 @@
 typedef struct ScatterGatherEntry ScatterGatherEntry;
 
 #if defined(TARGET_PHYS_ADDR_BITS)
+typedef target_phys_addr_t dma_addr_t;
+
+#define DMA_ADDR_FMT TARGET_FMT_plx
+
+typedef enum {
+    DMA_DIRECTION_TO_DEVICE = 0,
+    DMA_DIRECTION_FROM_DEVICE = 1,
+} DMADirection;
+
 struct ScatterGatherEntry {
     target_phys_addr_t base;
     target_phys_addr_t len;
commit 7f540ab5248a62c6ca4f6346a3564d0eff0069db
Author: Christophe Fergeau <cfergeau at redhat.com>
Date:   Mon Oct 17 13:37:34 2011 +0200

    ps2: migrate ledstate
    
    Make the ps2 device track its ledstate so that we can migrate it.
    Otherwise it gets lost across migration, and spice-server gets
    confused about the actual keyboard state and sends bogus
    caps/scroll/num key events. This fixes RH bug #729294
    
    We only need to migrate the state when it is different of the default
    one (0).
    
    Signed-off-by: Christophe Fergeau <cfergeau at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ps2.c b/hw/ps2.c
index 24228c1..1d9057b 100644
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -92,6 +92,7 @@ typedef struct {
        not the keyboard controller.  */
     int translate;
     int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
+    int ledstate;
 } PS2KbdState;
 
 typedef struct {
@@ -195,11 +196,17 @@ uint32_t ps2_read_data(void *opaque)
     return val;
 }
 
+static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
+{
+    s->ledstate = ledstate;
+    kbd_put_ledstate(ledstate);
+}
+
 static void ps2_reset_keyboard(PS2KbdState *s)
 {
     s->scan_enabled = 1;
     s->scancode_set = 2;
-    kbd_put_ledstate(0);
+    ps2_set_ledstate(s, 0);
 }
 
 void ps2_write_keyboard(void *opaque, int val)
@@ -274,7 +281,7 @@ void ps2_write_keyboard(void *opaque, int val)
         s->common.write_cmd = -1;
         break;
     case KBD_CMD_SET_LEDS:
-        kbd_put_ledstate(val);
+        ps2_set_ledstate(s, val);
         ps2_queue(&s->common, KBD_REPLY_ACK);
         s->common.write_cmd = -1;
         break;
@@ -557,6 +564,33 @@ static const VMStateDescription vmstate_ps2_common = {
     }
 };
 
+static bool ps2_keyboard_ledstate_needed(void *opaque)
+{
+    PS2KbdState *s = opaque;
+
+    return s->ledstate != 0; /* 0 is default state */
+}
+
+static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
+{
+    PS2KbdState *s = opaque;
+
+    kbd_put_ledstate(s->ledstate);
+    return 0;
+}
+
+static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
+    .name = "ps2kbd/ledstate",
+    .version_id = 3,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 2,
+    .post_load = ps2_kbd_ledstate_post_load,
+    .fields      = (VMStateField []) {
+        VMSTATE_INT32(ledstate, PS2KbdState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static int ps2_kbd_post_load(void* opaque, int version_id)
 {
     PS2KbdState *s = (PS2KbdState*)opaque;
@@ -578,6 +612,14 @@ static const VMStateDescription vmstate_ps2_keyboard = {
         VMSTATE_INT32(translate, PS2KbdState),
         VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
         VMSTATE_END_OF_LIST()
+    },
+    .subsections = (VMStateSubsection []) {
+        {
+            .vmsd = &vmstate_ps2_keyboard_ledstate,
+            .needed = ps2_keyboard_ledstate_needed,
+        }, {
+            /* empty */
+        }
     }
 };
 
commit ae878b172e8fe4a4237874de2d3bb879699d8af5
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Oct 7 21:15:20 2011 +0200

    ui/vnc: Fix use of free() instead of g_free()
    
    Please note that mechlist still uses malloc / strdup / free.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c
index e96095a..23b1bf5 100644
--- a/ui/vnc-auth-sasl.c
+++ b/ui/vnc-auth-sasl.c
@@ -34,7 +34,7 @@ void vnc_sasl_client_cleanup(VncState *vs)
         vs->sasl.runSSF = vs->sasl.waitWriteSSF = vs->sasl.wantSSF = 0;
         vs->sasl.encodedLength = vs->sasl.encodedOffset = 0;
         vs->sasl.encoded = NULL;
-        free(vs->sasl.username);
+        g_free(vs->sasl.username);
         free(vs->sasl.mechlist);
         vs->sasl.username = vs->sasl.mechlist = NULL;
         sasl_dispose(&vs->sasl.conn);
@@ -506,7 +506,7 @@ void start_auth_sasl(VncState *vs)
         goto authabort;
 
     if (!(remoteAddr = vnc_socket_remote_addr("%s;%s", vs->csock))) {
-        free(localAddr);
+        g_free(localAddr);
         goto authabort;
     }
 
@@ -518,8 +518,8 @@ void start_auth_sasl(VncState *vs)
                           NULL, /* Callbacks, not needed */
                           SASL_SUCCESS_DATA,
                           &vs->sasl.conn);
-    free(localAddr);
-    free(remoteAddr);
+    g_free(localAddr);
+    g_free(remoteAddr);
     localAddr = remoteAddr = NULL;
 
     if (err != SASL_OK) {
diff --git a/ui/vnc-enc-hextile.c b/ui/vnc-enc-hextile.c
index d2905c8..c860dbb 100644
--- a/ui/vnc-enc-hextile.c
+++ b/ui/vnc-enc-hextile.c
@@ -80,8 +80,8 @@ int vnc_hextile_send_framebuffer_update(VncState *vs, int x,
                                   last_bg, last_fg, &has_bg, &has_fg);
         }
     }
-    free(last_fg);
-    free(last_bg);
+    g_free(last_fg);
+    g_free(last_bg);
 
     return 1;
 }
diff --git a/ui/vnc-tls.c b/ui/vnc-tls.c
index ffbd172..3aaa939 100644
--- a/ui/vnc-tls.c
+++ b/ui/vnc-tls.c
@@ -413,7 +413,7 @@ void vnc_tls_client_cleanup(struct VncState *vs)
         vs->tls.session = NULL;
     }
     vs->tls.wiremode = VNC_WIREMODE_CLEAR;
-    free(vs->tls.dname);
+    g_free(vs->tls.dname);
 }
 
 
diff --git a/ui/vnc.c b/ui/vnc.c
index 32d4cb7..40018f7 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2911,7 +2911,7 @@ int vnc_display_open(DisplayState *ds, const char *display)
     if ((saslErr = sasl_server_init(NULL, "qemu")) != SASL_OK) {
         fprintf(stderr, "Failed to initialize SASL auth %s",
                 sasl_errstring(saslErr, NULL, NULL));
-        free(vs->display);
+        g_free(vs->display);
         vs->display = NULL;
         return -1;
     }
@@ -2925,7 +2925,7 @@ int vnc_display_open(DisplayState *ds, const char *display)
         else
             vs->lsock = inet_connect(display, SOCK_STREAM);
         if (-1 == vs->lsock) {
-            free(vs->display);
+            g_free(vs->display);
             vs->display = NULL;
             return -1;
         } else {
@@ -2946,10 +2946,10 @@ int vnc_display_open(DisplayState *ds, const char *display)
             vs->lsock = inet_listen(display, dpy, 256, SOCK_STREAM, 5900);
         }
         if (-1 == vs->lsock) {
-            free(dpy);
+            g_free(dpy);
             return -1;
         } else {
-            free(vs->display);
+            g_free(vs->display);
             vs->display = dpy;
         }
     }
commit e589728b6fffaa74f8d535dab5ad65700dc606bb
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Oct 7 15:59:01 2011 +0200

    checkpatch: remove rule on non-indented labels
    
    There are 508 non-indented (non-default) labels, and 511 that are
    indented.  So the rule is debatable at least.  Actually, in the
    common case of labels at the outermost scope, there is really just
    one place where to put the label, so the rule is just wrong IMHO.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 0eba357..7a71324 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -2206,12 +2206,6 @@ sub process {
 			ERROR("space prohibited before that close parenthesis ')'\n" . $herecurr);
 		}
 
-#goto labels aren't indented, allow a single space however
-		if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
-		   !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
-			WARN("labels should not be indented\n" . $herecurr);
-		}
-
 # Return is not a function.
 		if (defined($stat) && $stat =~ /^.\s*return(\s*)(\(.*);/s) {
 			my $spacing = $1;
commit fa39a30fe4b92adb77178f388947da922d41648d
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 25 19:18:58 2011 +0200

    savevm: qemu_fille_buffer() used to return one error for reads of size 0.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/savevm.c b/savevm.c
index f01838f..bee16c0 100644
--- a/savevm.c
+++ b/savevm.c
@@ -476,6 +476,8 @@ static void qemu_fill_buffer(QEMUFile *f)
     if (len > 0) {
         f->buf_size += len;
         f->buf_offset += len;
+    } else if (len == 0) {
+        f->last_error = -EIO;
     } else if (len != -EAGAIN)
         f->last_error = len;
 }
commit db9eae1c49fe2766a7709d7b2c4cdfcd91b9c25b
Author: Xu He Jie <xuhj at linux.vnet.ibm.com>
Date:   Thu Oct 27 10:15:13 2011 +0800

    kvm_init didn't set return value after create vm failed
    
    And kvm_ioctl(s, KVM_CREATE_VM, 0)'s return value can be < -1,
    so change the check of vmfd at label 'err'.
    
    Signed-off-by: Xu He Jie <xuhj at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/kvm-all.c b/kvm-all.c
index c09ddf7..4c466d6 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -740,6 +740,7 @@ int kvm_init(void)
         fprintf(stderr, "Please add the 'switch_amode' kernel parameter to "
                         "your host kernel command line\n");
 #endif
+        ret = s->vmfd;
         goto err;
     }
 
@@ -798,7 +799,7 @@ int kvm_init(void)
 
 err:
     if (s) {
-        if (s->vmfd != -1) {
+        if (s->vmfd >= 0) {
             close(s->vmfd);
         }
         if (s->fd != -1) {
commit 3a26360d1df3c3519a45636ec2189429d3df0ecb
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Nov 1 16:49:17 2011 -0500

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

diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 2a5e637..7162588 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -51,7 +51,7 @@ static PCIDevice *find_dev(sPAPREnvironment *spapr,
             continue;
         }
 
-        QLIST_FOREACH(qdev, &phb->host_state.bus->qbus.children, sibling) {
+        QTAILQ_FOREACH(qdev, &phb->host_state.bus->qbus.children, sibling) {
             PCIDevice *dev = (PCIDevice *)qdev;
             if (dev->devfn == devfn) {
                 return dev;
@@ -397,7 +397,7 @@ int spapr_populate_pci_devices(sPAPRPHBState *phb,
 
     /* Populate PCI devices and allocate IRQs */
     devices = 0;
-    QLIST_FOREACH(qdev, &bus->qbus.children, sibling) {
+    QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) {
         PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev);
         int irq_index = pci_spapr_map_irq(dev, 0);
         uint32_t *irqmap = interrupt_map[devices];
commit 7f7623662781fa152c5aa39fd63a2e8766516a2c
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Tue Nov 1 20:59:32 2011 +0000

    Revert "PPC: Fail configure when libfdt is not available"
    
    This reverts commit f90a9d02401eeeec18a122b61ccccb91244f321c.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/configure b/configure
index 28b76c0..850efc0 100755
--- a/configure
+++ b/configure
@@ -3454,16 +3454,7 @@ case "$target_arch2" in
       fi
     fi
 esac
-if test "$fdt" != "yes" && test "$target_arch2" = "ppc" -o \
-        "$target_arch2" = "ppc64" -o "$target_arch2" = "ppcemb"; then
-  echo
-  echo "Error: libfdt missing"
-  echo "The PowerPC target requires libfdt to work properly."
-  echo "Please make sure to have it and its development packages installed."
-  echo
-  exit 1
-fi
-if test "$target_arch2" = "ppc64"; then
+if test "$target_arch2" = "ppc64" -a "$fdt" = "yes"; then
   echo "CONFIG_PSERIES=y" >> $config_target_mak
 fi
 if test "$target_bigendian" = "yes" ; then
commit e927dab1fda0eee41fa5fe51ae98293f66a86db1
Merge: 2ff6458... 3384f95...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Tue Nov 1 20:57:01 2011 +0000

    Merge branch 'ppc-next' of git://repo.or.cz/qemu/agraf
    
    * 'ppc-next' of git://repo.or.cz/qemu/agraf: (24 commits)
      pseries: Add partial support for PCI
      ppc: Alter CPU state to mask out TCG unimplemented instructions as appropriate
      pseries: Allow writes to KVM accelerated TCE table
      KVM: PPC: Override host vmx/vsx/dfp only when information known
      ppc: Fix up usermode only builds
      pseries: Correct vmx/dfp handling in both KVM and TCG cases
      PPC: Fail configure when libfdt is not available
      ppc: Avoid decrementer related kvm exits
      PPC: Disable non-440 CPUs for ppcemb target
      PPC: Bump qemu-system-ppc to 64-bit physical address space
      pseries: Under kvm use guest cpu = host cpu by default
      ppc: Add cpu defs for POWER7 revisions 2.1 and 2.3
      ppc: First cut implementation of -cpu host
      ppc: Remove broken partial PVR matching
      pseries: Update SLOF firmware image
      pseries: Add device tree properties for VMX/VSX and DFP under kvm
      ppc: Generalize the kvmppc_get_clockfreq() function
      Set an invalid-bits mask for each SPE instructions
      pseries: Update SLOF firmware image
      pseries: Use Book3S-HV TCE acceleration capabilities
      ...

commit 13766eb1e46452affd12f2b944730e136c6a2dda
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Sun Oct 30 23:19:54 2011 +0100

    cocoa: Close sheet after image file selection
    
    If no disk image is specified, the Cocoa frontend displays a modal sheet
    to let the user select an image file to boot from.
    
    This sheet is never closed and it permanently obscures the emulator window.
    
    Close it after obtaining the file name in case the user did select a file.
    Otherwise we exit immediately, so no need to close then.
    
    Signed-off-by: Juan Pineda <juan at logician.com>
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>

diff --git a/ui/cocoa.m b/ui/cocoa.m
index d9e4e3d..0711205 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -811,6 +811,8 @@ QemuCocoaView *cocoaView;
 
         char **argv = (char**)malloc( sizeof(char*)*3 );
 
+        [sheet close];
+
         asprintf(&argv[0], "%s", bin);
         asprintf(&argv[1], "-hda");
         asprintf(&argv[2], "%s", img);
commit db529aabfac17201d3647384abf89fc7f272b493
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Mon Oct 31 19:14:56 2011 +0100

    vl.c: Guard against GThread double-initialization
    
    GThread-ERROR **: GThread system may only be initialized once.
    aborting...
    
    Making the g_thread_init() call in vl.c conditional resolves an abort on
    Mac OS X, where coroutine-gthread.c seems to call it before vl.c.
    
    Reported-by: Juan Pineda <juan at logician.com>
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Cc: Daniel P. Berrange <berrange at redhat.com>

diff --git a/vl.c b/vl.c
index b56e0cb..624da0f 100644
--- a/vl.c
+++ b/vl.c
@@ -2185,7 +2185,9 @@ int main(int argc, char **argv, char **envp)
     error_set_progname(argv[0]);
 
     g_mem_set_vtable(&mem_trace);
-    g_thread_init(NULL);
+    if (!g_thread_supported()) {
+        g_thread_init(NULL);
+    }
 
     runstate_init();
 
commit 351f1bf6fc9f02cd2ef341f853f7bb55d05974ec
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Sun Oct 30 18:08:01 2011 +0100

    MAINTAINERS: Add Cocoa maintainer
    
    Degrade cocoa.m from Maintained to Odd Fixes.
    
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Cc: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/MAINTAINERS b/MAINTAINERS
index bccdd4f..7ee301e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -451,6 +451,11 @@ M: Anthony Liguori <aliguori at us.ibm.com>
 S: Maintained
 F: ui/
 
+Cocoa graphics
+M: Andreas Färber <andreas.faerber at web.de>
+S: Odd Fixes
+F: ui/cocoa.m
+
 Main loop
 M: Anthony Liguori <aliguori at us.ibm.com>
 S: Supported
commit 2ff6458116546ced7ce00cc39423ee30b1477e67
Merge: 0ffcb2c... 39fba3a...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Nov 1 13:09:31 2011 -0500

    Merge remote-tracking branch 'kraxel/usb.29' into staging

commit 0ffcb2ca8d7508f0e60035a17f3a8e055a7a1b89
Merge: 110fc08... 454e202...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Nov 1 13:08:33 2011 -0500

    Merge remote-tracking branch 'stefanha/tracing' into staging

commit 110fc0864d901cf5954a3663389f9598533d1ef5
Merge: 5962353... 54825d2...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Nov 1 13:06:46 2011 -0500

    Merge remote-tracking branch 'spice/spice.v46' into staging

commit 596235300608575ece1828b12a5faf32ebfee3fc
Merge: 90ea59f... 0ce6a43...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Nov 1 13:06:17 2011 -0500

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging

commit 90ea59fe7d121c722e1b44cb9bc0fad1ade73686
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Fri Oct 28 02:10:27 2011 +0400

    opencores_eth: fix RX path: FCS, padding and TL
    
    OpenCores 10/100 Mbps Ethernet MAC specification doesn't clearly state
    whether FCS is counted in the RX frame length or not. Looks like it is.
    Append zero FCS to the received frames.
    
    Get rid of big static buffer for RX frame padding, optimize it for the
    most common MINFL value range.
    
    Set RXD_TL for the long frames only when HUGEN bit is set.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c
index 64b616e..2c1e475 100644
--- a/hw/opencores_eth.c
+++ b/hw/opencores_eth.c
@@ -382,6 +382,7 @@ static ssize_t open_eth_receive(VLANClientState *nc,
     OpenEthState *s = DO_UPCAST(NICState, nc, nc)->opaque;
     size_t maxfl = GET_REGFIELD(s, PACKETLEN, MAXFL);
     size_t minfl = GET_REGFIELD(s, PACKETLEN, MINFL);
+    size_t fcsl = 4;
     bool miss = true;
 
     trace_open_eth_receive((unsigned)size);
@@ -418,6 +419,7 @@ static ssize_t open_eth_receive(VLANClientState *nc,
 #else
     {
 #endif
+        static const uint8_t zero[64] = {0};
         desc *desc = rx_desc(s);
         size_t copy_size = GET_REGBIT(s, MODER, HUGEN) ? 65536 : maxfl;
 
@@ -426,11 +428,13 @@ static ssize_t open_eth_receive(VLANClientState *nc,
 
         if (copy_size > size) {
             copy_size = size;
+        } else {
+            fcsl = 0;
         }
         if (miss) {
             desc->len_flags |= RXD_M;
         }
-        if (size > maxfl) {
+        if (GET_REGBIT(s, MODER, HUGEN) && size > maxfl) {
             desc->len_flags |= RXD_TL;
         }
 #ifdef USE_RECSMALL
@@ -442,13 +446,28 @@ static ssize_t open_eth_receive(VLANClientState *nc,
         cpu_physical_memory_write(desc->buf_ptr, buf, copy_size);
 
         if (GET_REGBIT(s, MODER, PAD) && copy_size < minfl) {
-            static const uint8_t zero[65536] = {0};
+            if (minfl - copy_size > fcsl) {
+                fcsl = 0;
+            } else {
+                fcsl -= minfl - copy_size;
+            }
+            while (copy_size < minfl) {
+                size_t zero_sz = minfl - copy_size < sizeof(zero) ?
+                    minfl - copy_size : sizeof(zero);
 
-            cpu_physical_memory_write(desc->buf_ptr + copy_size,
-                    zero, minfl - copy_size);
-            copy_size = minfl;
+                cpu_physical_memory_write(desc->buf_ptr + copy_size,
+                        zero, zero_sz);
+                copy_size += zero_sz;
+            }
         }
 
+        /* There's no FCS in the frames handed to us by the QEMU, zero fill it.
+         * Don't do it if the frame is cut at the MAXFL or padded with 4 or
+         * more bytes to the MINFL.
+         */
+        cpu_physical_memory_write(desc->buf_ptr + copy_size, zero, fcsl);
+        copy_size += fcsl;
+
         SET_FIELD(desc->len_flags, RXD_LEN, copy_size);
 
         if ((desc->len_flags & RXD_WRAP) || s->rx_desc == 0x7f) {
commit aab2293687ee54a409f3fb53a1ab3595b595e0fb
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Oct 27 09:12:04 2011 +0200

    migration: flush migration data to disk.
    
    This patch increases robustness when migrating to a file with
    two little changes:
    
     (1) Before closing the migration file handle checks if it happens to be
         a regular file and if so it issues a fsync.  This way the data is
         flushed to disk before qemu sends the migration completed event.
     (2) It adds error checking.  In case either fsync or close syscall
         fails pass up the error (and fail migration).
    
    [ v2: return -errno instead of -1 ]
    
    Cc: Juan Quintela <quintela at redhat.com>
    Cc: Jiri Denemark <jdenemar at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration-fd.c b/migration-fd.c
index d0aec89..6211124 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -42,10 +42,31 @@ static int fd_write(MigrationState *s, const void * buf, size_t size)
 
 static int fd_close(MigrationState *s)
 {
+    struct stat st;
+    int ret;
+
     DPRINTF("fd_close\n");
     if (s->fd != -1) {
-        close(s->fd);
+        ret = fstat(s->fd, &st);
+        if (ret == 0 && S_ISREG(st.st_mode)) {
+            /*
+             * If the file handle is a regular file make sure the
+             * data is flushed to disk before signaling success.
+             */
+            ret = fsync(s->fd);
+            if (ret != 0) {
+                ret = -errno;
+                perror("migration-fd: fsync");
+                return ret;
+            }
+        }
+        ret = close(s->fd);
         s->fd = -1;
+        if (ret != 0) {
+            ret = -errno;
+            perror("migration-fd: close");
+            return ret;
+        }
     }
     return 0;
 }
commit 695833bc8bbb9f1dbb0d7736cbe927863e1b40cd
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Sep 1 17:42:19 2011 +0200

    add test-coroutine to checks
    
    There is a "test-coroutine" which isn't in the list.
    Add it so "make check" runs it too.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index d18c8ad..28667fe 100755
--- a/configure
+++ b/configure
@@ -2669,7 +2669,7 @@ if test "$softmmu" = yes ; then
     fi
     if [ "$check_utests" = "yes" ]; then
       checks="check-qint check-qstring check-qdict check-qlist"
-      checks="check-qfloat check-qjson $checks"
+      checks="check-qfloat check-qjson test-coroutine $checks"
     fi
   fi
 fi
commit ea7f78047d8ead786783972bf061d355a68e3382
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Sep 1 17:42:18 2011 +0200

    add "make check" target
    
    Add some Makefile glue so we have a simple "make check"
    to run the unit tests.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index 5696e44..4f6eaa4 100644
--- a/Makefile
+++ b/Makefile
@@ -305,6 +305,12 @@ endif
 test speed: all
 	$(MAKE) -C tests $@
 
+.PHONY: check
+check: $(patsubst %,run-check-%,$(CHECKS))
+
+run-check-%: %
+	./$<
+
 .PHONY: TAGS
 TAGS:
 	find "$(SRC_PATH)" -name '*.[hc]' -print0 | xargs -0 etags
commit fffbeb750e1d137f09b9c417ed1fb79963f6abcd
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Sep 1 17:42:17 2011 +0200

    move checks to separate variable
    
    Create a new CHECKS variable.  Put the checks there instead
    of adding them to the TOOLS variable.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index ba8d738..5696e44 100644
--- a/Makefile
+++ b/Makefile
@@ -75,7 +75,7 @@ defconfig:
 
 -include config-all-devices.mak
 
-build-all: $(DOCS) $(TOOLS) recurse-all
+build-all: $(DOCS) $(TOOLS) $(CHECKS) recurse-all
 
 config-host.h: config-host.h-timestamp
 config-host.h-timestamp: config-host.mak
@@ -219,7 +219,7 @@ clean:
 # avoid old build problems by removing potentially incorrect old files
 	rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
 	rm -f qemu-options.def
-	rm -f *.o *.d *.a *.lo $(TOOLS) qemu-ga TAGS cscope.* *.pod *~ */*~
+	rm -f *.o *.d *.a *.lo $(TOOLS) $(CHECKS) qemu-ga TAGS cscope.* *.pod *~ */*~
 	rm -Rf .libs
 	rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d net/*.o net/*.d fsdev/*.o fsdev/*.d ui/*.o ui/*.d qapi/*.o qapi/*.d qga/*.o qga/*.d
 	rm -f qemu-img-cmds.h
diff --git a/configure b/configure
index 6e4113d..d18c8ad 100755
--- a/configure
+++ b/configure
@@ -2668,8 +2668,8 @@ if test "$softmmu" = yes ; then
       tools="qemu-ga\$(EXESUF) $tools"
     fi
     if [ "$check_utests" = "yes" ]; then
-      tools="check-qint check-qstring check-qdict check-qlist $tools"
-      tools="check-qfloat check-qjson $tools"
+      checks="check-qint check-qstring check-qdict check-qlist"
+      checks="check-qfloat check-qjson $checks"
     fi
   fi
 fi
@@ -3143,6 +3143,7 @@ if test "$trace_default" = "yes"; then
 fi
 
 echo "TOOLS=$tools" >> $config_host_mak
+echo "CHECKS=$checks" >> $config_host_mak
 echo "ROMS=$roms" >> $config_host_mak
 echo "MAKE=$make" >> $config_host_mak
 echo "INSTALL=$install" >> $config_host_mak
commit 25b651bedb917866ef8808f06896fdaed2c189cb
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Sep 1 17:42:16 2011 +0200

    Probe for libcheck by default.
    
    Probe for libcheck and build checks (if found) by default.
    Can be explicitly disabled using --disable-check-utests.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index a6cf6d6..6e4113d 100755
--- a/configure
+++ b/configure
@@ -169,7 +169,7 @@ mixemu="no"
 aix="no"
 blobs="yes"
 pkgversion=""
-check_utests="no"
+check_utests=""
 user_pie="no"
 zero_malloc=""
 trace_backend="nop"
commit 90647853f9829e6a382bc4d6d5b0e56af4da3741
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sat Oct 29 12:58:26 2011 +0100

    ia64-dis.c: Undefine ABS to avoid clash with glib
    
    Undefine ABS to avoid a clash with the macro that glib.h
    helpfully defines for us (and a resulting build failure
    on ia64 hosts).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ia64-dis.c b/ia64-dis.c
index 2886df3..2a103e6 100644
--- a/ia64-dis.c
+++ b/ia64-dis.c
@@ -781,6 +781,9 @@ ext_inc3 (const struct ia64_operand *self, ia64_insn code, ia64_insn *valuep)
   return 0;
 }
 
+/* glib.h defines ABS so we must undefine it to avoid a clash */
+#undef ABS
+
 #define CST	IA64_OPND_CLASS_CST
 #define REG	IA64_OPND_CLASS_REG
 #define IND	IA64_OPND_CLASS_IND
commit 1fdc11c36971e0d4eeb2ce817f7e520b2028c2f2
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Fri Oct 28 14:59:52 2011 -0200

    Fix segfault on migration completion
    
    A simple migration reproduces it:
    
    1. Start the source VM with:
    
       # qemu [...] -S
    
    2. Start the destination VM with:
    
       # qemu <source VM cmd-line> -incoming tcp:0:4444
    
    3. In the source VM:
    
       (qemu) migrate -d tcp:0:4444
    
    4. The source VM will segfault as soon as migration completes (might not
       happen in the first try)
    
    What is happening here is that qemu_file_put_notify() can end up closing
    's->file' (in which case it's also set to NULL). The call stack is rather
    complex, but Eduardo helped tracking it to:
    
    select loop -> migrate_fd_put_notify() -> qemu_file_put_notify() ->
    buffered_put_buffer() -> migrate_fd_put_ready() ->
    migrate_fd_completed() -> migrate_fd_cleanup().
    
    To be honest, it's not completely clear to me in which cases 's->file'
    is not closed (on error maybe)? But I doubt this fix will make anything
    worse.
    
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Acked-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration.c b/migration.c
index 3b4abbd..4b17566 100644
--- a/migration.c
+++ b/migration.c
@@ -216,7 +216,7 @@ static void migrate_fd_put_notify(void *opaque)
 
     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
     qemu_file_put_notify(s->file);
-    if (qemu_file_get_error(s->file)) {
+    if (s->file && qemu_file_get_error(s->file)) {
         migrate_fd_error(s);
     }
 }
commit 4f39d27fe4e8109ba9eb2983b27675f2ca6d3ecb
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Oct 28 15:26:18 2011 +1100

    Add qapi related generated files to .gitignore
    
    .gitignore already lists the qapi-generated subdirectory which includes a
    number of files generated during build.  However, there are some additional
    files generated by the qapi build which go in the top level directory.
    
    This patch adds them to .gitignore, removing the irritating noise from
    diffs and the like.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/.gitignore b/.gitignore
index 6d2acab..406f75f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,10 @@ libhw64
 libuser
 linux-headers/asm
 qapi-generated
+qapi-types.[ch]
+qapi-visit.[ch]
+qmp-commands.h
+qmp-marshal.c
 qemu-doc.html
 qemu-tech.html
 qemu-doc.info
commit 463ce4ae2dc5214f1b3ce5951c7cc3904c903702
Author: Eric Sunshine <sunshine at sunshineco.com>
Date:   Tue Nov 1 05:39:49 2011 -0400

    qemu-barrier: Fix build failure on PowerPC Mac OS X
    
    qemu-barrier.h tests if macro __powerpc__ is defined, however, the
    preprocessor on PowerPC Mac OS X defines only __POWERPC__, not
    __powerpc__.  Resolve by testing instead for qemu-provided _ARCH_PPC.
    
    Signed-off-by: Eric Sunshine <sunshine at sunshineco.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-barrier.h b/qemu-barrier.h
index 735eea6..c11bb2b 100644
--- a/qemu-barrier.h
+++ b/qemu-barrier.h
@@ -14,7 +14,7 @@
  */
 #define smp_wmb()   barrier()
 
-#elif defined(__powerpc__)
+#elif defined(_ARCH_PPC)
 
 /*
  * We use an eieio() for a wmb() on powerpc.  This assumes we don't
commit 9477c87ed9b7795b292cb683cf758fdfec866de3
Author: Pavel Borzenkov <pavel.borzenkov at gmail.com>
Date:   Mon Oct 24 07:31:30 2011 -0400

    fw_cfg: Use g_file_get_contents instead of multiple fread() calls
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Pavel Borzenkov <pavel.borzenkov at gmail.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
index 8df265c..dbcb888 100644
--- a/hw/fw_cfg.c
+++ b/hw/fw_cfg.c
@@ -60,71 +60,55 @@ struct FWCfgState {
 #define JPG_FILE 0
 #define BMP_FILE 1
 
-static FILE *probe_splashfile(char *filename, int *file_sizep, int *file_typep)
+static char *read_splashfile(char *filename, int *file_sizep, int *file_typep)
 {
-    FILE *fp = NULL;
-    int fop_ret;
-    int file_size;
+    GError *err = NULL;
+    gboolean res;
+    gchar *content;
     int file_type = -1;
-    unsigned char buf[2] = {0, 0};
-    unsigned int filehead_value = 0;
+    unsigned int filehead = 0;
     int bmp_bpp;
 
-    fp = fopen(filename, "rb");
-    if (fp == NULL) {
-        error_report("failed to open file '%s'.", filename);
-        return fp;
+    res = g_file_get_contents(filename, &content, (gsize *)file_sizep, &err);
+    if (res == FALSE) {
+        error_report("failed to read splash file '%s'", filename);
+        g_error_free(err);
+        return NULL;
     }
+
     /* check file size */
-    fseek(fp, 0L, SEEK_END);
-    file_size = ftell(fp);
-    if (file_size < 2) {
-        error_report("file size is less than 2 bytes '%s'.", filename);
-        fclose(fp);
-        fp = NULL;
-        return fp;
+    if (*file_sizep < 30) {
+        goto error;
     }
+
     /* check magic ID */
-    fseek(fp, 0L, SEEK_SET);
-    fop_ret = fread(buf, 1, 2, fp);
-    if (fop_ret != 2) {
-        error_report("Could not read header from '%s': %s",
-                     filename, strerror(errno));
-        fclose(fp);
-        fp = NULL;
-        return fp;
-    }
-    filehead_value = (buf[0] + (buf[1] << 8)) & 0xffff;
-    if (filehead_value == 0xd8ff) {
+    filehead = ((content[0] & 0xff) + (content[1] << 8)) & 0xffff;
+    if (filehead == 0xd8ff) {
         file_type = JPG_FILE;
+    } else if (filehead == 0x4d42) {
+        file_type = BMP_FILE;
     } else {
-        if (filehead_value == 0x4d42) {
-            file_type = BMP_FILE;
-        }
-    }
-    if (file_type < 0) {
-        error_report("'%s' not jpg/bmp file,head:0x%x.",
-                         filename, filehead_value);
-        fclose(fp);
-        fp = NULL;
-        return fp;
+        goto error;
     }
+
     /* check BMP bpp */
     if (file_type == BMP_FILE) {
-        fseek(fp, 28, SEEK_SET);
-        fop_ret = fread(buf, 1, 2, fp);
-        bmp_bpp = (buf[0] + (buf[1] << 8)) & 0xffff;
+        bmp_bpp = (content[28] + (content[29] << 8)) & 0xffff;
         if (bmp_bpp != 24) {
-            error_report("only 24bpp bmp file is supported.");
-            fclose(fp);
-            fp = NULL;
-            return fp;
+            goto error;
         }
     }
+
     /* return values */
-    *file_sizep = file_size;
     *file_typep = file_type;
-    return fp;
+
+    return content;
+
+error:
+    error_report("splash file '%s' format not recognized; must be JPEG "
+                 "or 24 bit BMP", filename);
+    g_free(content);
+    return NULL;
 }
 
 static void fw_cfg_bootsplash(FWCfgState *s)
@@ -132,9 +116,7 @@ static void fw_cfg_bootsplash(FWCfgState *s)
     int boot_splash_time = -1;
     const char *boot_splash_filename = NULL;
     char *p;
-    char *filename;
-    FILE *fp;
-    int fop_ret;
+    char *filename, *file_data;
     int file_size;
     int file_type = -1;
     const char *temp;
@@ -174,27 +156,19 @@ static void fw_cfg_bootsplash(FWCfgState *s)
             error_report("failed to find file '%s'.", boot_splash_filename);
             return;
         }
-        /* probing the file */
-        fp = probe_splashfile(filename, &file_size, &file_type);
-        if (fp == NULL) {
+
+        /* loading file data */
+        file_data = read_splashfile(filename, &file_size, &file_type);
+        if (file_data == NULL) {
             g_free(filename);
             return;
         }
-        /* loading file data */
         if (boot_splash_filedata != NULL) {
             g_free(boot_splash_filedata);
         }
-        boot_splash_filedata = g_malloc(file_size);
+        boot_splash_filedata = (uint8_t *)file_data;
         boot_splash_filedata_size = file_size;
-        fseek(fp, 0L, SEEK_SET);
-        fop_ret = fread(boot_splash_filedata, 1, file_size, fp);
-        if (fop_ret != file_size) {
-            error_report("failed to read data from '%s'.",
-                         boot_splash_filename);
-            fclose(fp);
-            return;
-        }
-        fclose(fp);
+
         /* insert data */
         if (file_type == JPG_FILE) {
             fw_cfg_add_file(s, "bootsplash.jpg",
commit bdb7ca67de6ef7170f925fd33bdf77c05e46f76d
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Sep 26 09:40:39 2011 +0200

    Simplify cpu_exec_all to tcg_exec_all
    
    After the removal of the non-threaded mode cpu_exec_all is now only used
    by TCG. Refactor it accordingly, also dropping its unused return value.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/cpus.c b/cpus.c
index f768683..6aff425 100644
--- a/cpus.c
+++ b/cpus.c
@@ -748,6 +748,8 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
     return NULL;
 }
 
+static void tcg_exec_all(void);
+
 static void *qemu_tcg_cpu_thread_fn(void *arg)
 {
     CPUState *env = arg;
@@ -769,7 +771,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
     }
 
     while (1) {
-        cpu_exec_all();
+        tcg_exec_all();
         if (use_icount && qemu_clock_deadline(vm_clock) <= 0) {
             qemu_notify_event();
         }
@@ -1016,7 +1018,7 @@ static int tcg_cpu_exec(CPUState *env)
     return ret;
 }
 
-bool cpu_exec_all(void)
+static void tcg_exec_all(void)
 {
     int r;
 
@@ -1033,12 +1035,7 @@ bool cpu_exec_all(void)
                           (env->singlestep_enabled & SSTEP_NOTIMER) == 0);
 
         if (cpu_can_run(env)) {
-            if (kvm_enabled()) {
-                r = kvm_cpu_exec(env);
-                qemu_kvm_eat_signals(env);
-            } else {
-                r = tcg_cpu_exec(env);
-            }
+            r = tcg_cpu_exec(env);
             if (r == EXCP_DEBUG) {
                 cpu_handle_guest_debug(env);
                 break;
@@ -1048,7 +1045,6 @@ bool cpu_exec_all(void)
         }
     }
     exit_request = 0;
-    return !all_cpu_threads_idle();
 }
 
 void set_numa_modes(void)
diff --git a/cpus.h b/cpus.h
index 3525375..4ea2fe2 100644
--- a/cpus.h
+++ b/cpus.h
@@ -14,7 +14,6 @@ void cpu_synchronize_all_post_init(void);
 /* vl.c */
 extern int smp_cores;
 extern int smp_threads;
-bool cpu_exec_all(void);
 void set_numa_modes(void);
 void set_cpu_log(const char *optarg);
 void set_cpu_log_filename(const char *optarg);
commit b3c4bbe56dc707102d3abd969f51bb2aa9c6c53d
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Oct 28 10:52:42 2011 +0100

    Make cpu_single_env thread-local
    
    Make cpu_single_env thread-local. This fixes a regression
    in handling of multi-threaded programs in linux-user mode
    (bug 823902).
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    [Peter Maydell: rename tls_cpu_single_env to cpu_single_env]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/cpu-all.h b/cpu-all.h
index 42a5fa0..5f47ab8 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -20,6 +20,7 @@
 #define CPU_ALL_H
 
 #include "qemu-common.h"
+#include "qemu-tls.h"
 #include "cpu-common.h"
 
 /* some important defines:
@@ -334,7 +335,8 @@ void cpu_dump_statistics(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
 void QEMU_NORETURN cpu_abort(CPUState *env, const char *fmt, ...)
     GCC_FMT_ATTR(2, 3);
 extern CPUState *first_cpu;
-extern CPUState *cpu_single_env;
+DECLARE_TLS(CPUState *,cpu_single_env);
+#define cpu_single_env get_tls(cpu_single_env)
 
 /* Flags for use in ENV->INTERRUPT_PENDING.
 
diff --git a/exec.c b/exec.c
index 54ecbe7..6b92198 100644
--- a/exec.c
+++ b/exec.c
@@ -120,7 +120,7 @@ static MemoryRegion *system_io;
 CPUState *first_cpu;
 /* current CPU in the current thread. It is only valid inside
    cpu_exec() */
-CPUState *cpu_single_env;
+DEFINE_TLS(CPUState *,cpu_single_env);
 /* 0 = Do not count executed instructions.
    1 = Precise instruction counting.
    2 = Adaptive rate instruction counting.  */
commit 8a5f7b03a0a711ec8e04aeebe339cdb8b876794b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Oct 28 10:52:41 2011 +0100

    darwin-user/main.c: Drop unused cpu_single_env definition
    
    Drop the cpu_single_env definition as it is unused.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/darwin-user/main.c b/darwin-user/main.c
index 1a881a0..c0f14f8 100644
--- a/darwin-user/main.c
+++ b/darwin-user/main.c
@@ -729,8 +729,6 @@ static void usage(void)
 
 /* XXX: currently only used for async signals (see signal.c) */
 CPUState *global_env;
-/* used only if single thread */
-CPUState *cpu_single_env = NULL;
 
 /* used to free thread contexts */
 TaskState *first_task_state;
commit 754fd932bedacfd7de35cf74da6adca89ba28089
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Oct 28 10:52:40 2011 +0100

    qemu-tls.h: Add abstraction layer for TLS variables
    
    Add an abstraction layer for defining and using thread-local
    variables. For the moment this is implemented only for Linux,
    which means they can only be used in restricted circumstances.
    The abstraction layer allows us to add POSIX and Win32 support
    later.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-tls.h b/qemu-tls.h
new file mode 100644
index 0000000..5b70f10
--- /dev/null
+++ b/qemu-tls.h
@@ -0,0 +1,52 @@
+/*
+ * Abstraction layer for defining and using TLS variables
+ *
+ * Copyright (c) 2011 Red Hat, Inc
+ * Copyright (c) 2011 Linaro Limited
+ *
+ * Authors:
+ *  Paolo Bonzini <pbonzini at redhat.com>
+ *  Peter Maydell <peter.maydell at linaro.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 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/>.
+ */
+
+#ifndef QEMU_TLS_H
+#define QEMU_TLS_H
+
+/* Per-thread variables. Note that we only have implementations
+ * which are really thread-local on Linux; the dummy implementations
+ * define plain global variables.
+ *
+ * This means that for the moment use should be restricted to
+ * per-VCPU variables, which are OK because:
+ *  - the only -user mode supporting multiple VCPU threads is linux-user
+ *  - TCG system mode is single-threaded regarding VCPUs
+ *  - KVM system mode is multi-threaded but limited to Linux
+ *
+ * TODO: proper implementations via Win32 .tls sections and
+ * POSIX pthread_getspecific.
+ */
+#ifdef __linux__
+#define DECLARE_TLS(type, x) extern DEFINE_TLS(type, x)
+#define DEFINE_TLS(type, x)  __thread __typeof__(type) tls__##x
+#define get_tls(x)           tls__##x
+#else
+/* Dummy implementations which define plain global variables */
+#define DECLARE_TLS(type, x) extern DEFINE_TLS(type, x)
+#define DEFINE_TLS(type, x)  __typeof__(type) tls__##x
+#define get_tls(x)           tls__##x
+#endif
+
+#endif
commit 3e837b2c05bc63fe2226baf3c29923d5a688593f
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Oct 31 08:54:09 2011 -0600

    Error check find_ram_offset
    
    Spotted via code review, we initialize offset to 0 to avoid a
    compiler warning, but in the unlikely case that offset is
    never set to something else, we should abort instead of return
    a value that will almost certainly cause problems.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/exec.c b/exec.c
index 2f3c6a0..54ecbe7 100644
--- a/exec.c
+++ b/exec.c
@@ -2873,7 +2873,7 @@ static void *file_ram_alloc(RAMBlock *block,
 static ram_addr_t find_ram_offset(ram_addr_t size)
 {
     RAMBlock *block, *next_block;
-    ram_addr_t offset = 0, mingap = RAM_ADDR_MAX;
+    ram_addr_t offset = RAM_ADDR_MAX, mingap = RAM_ADDR_MAX;
 
     if (QLIST_EMPTY(&ram_list.blocks))
         return 0;
@@ -2889,10 +2889,17 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
             }
         }
         if (next - end >= size && next - end < mingap) {
-            offset =  end;
+            offset = end;
             mingap = next - end;
         }
     }
+
+    if (offset == RAM_ADDR_MAX) {
+        fprintf(stderr, "Failed to find gap of requested size: %" PRIu64 "\n",
+                (uint64_t)size);
+        abort();
+    }
+
     return offset;
 }
 
commit 39fba3ada9a9e36a29a40e1acddec0923839c39b
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Oct 28 16:13:50 2011 +0200

    usb-host: fix host close
    
    The whole usb_host_close() function is skipped in case the device is not
    in attached state.  This is wrong though, only then usb_device_detach()
    must be skipped, all other cleanup (especially device reset and closing
    the file handle) still needs to be done.  There are code paths where
    usb_host_close() is called with the device in detached state already.
    
    This fixes usb-host devices not being released and returned to the host
    after removing them with device_del.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/usb-linux.c b/usb-linux.c
index 7d4d1d7..f086d57 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -1349,7 +1349,7 @@ static int usb_host_close(USBHostDevice *dev)
 {
     int i;
 
-    if (dev->fd == -1 || !dev->dev.attached) {
+    if (dev->fd == -1) {
         return -1;
     }
 
@@ -1367,7 +1367,9 @@ static int usb_host_close(USBHostDevice *dev)
     }
     async_complete(dev);
     dev->closing = 0;
-    usb_device_detach(&dev->dev);
+    if (dev->dev.attached) {
+        usb_device_detach(&dev->dev);
+    }
     ioctl(dev->fd, USBDEVFS_RESET);
     close(dev->fd);
     dev->fd = -1;
commit db80358a20e2597a0844998c832b2dce667d0aa0
Author: Roy Tam <roytam at gmail.com>
Date:   Thu Sep 15 11:25:47 2011 +0800

    usb: change VID/PID for usb-hub and usb-msd to prevent conflict
    
    Some USB drivers, for example USBASPI.SYS, will skip different type of
    device which has same VID/PID. The following patch helps preventing
    usb-msd being skipped by the driver.
    
    Signed-off-by: Roy Tam <roytam at gmail.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 7b47079..3eb0f1a 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -127,8 +127,8 @@ static const USBDescDevice desc_device_hub = {
 
 static const USBDesc desc_hub = {
     .id = {
-        .idVendor          = 0,
-        .idProduct         = 0,
+        .idVendor          = 0x0409,
+        .idProduct         = 0x55aa,
         .bcdDevice         = 0x0101,
         .iManufacturer     = STR_MANUFACTURER,
         .iProduct          = STR_PRODUCT,
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 1a0815a..b734177 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -162,8 +162,8 @@ static const USBDescDevice desc_device_high = {
 
 static const USBDesc desc = {
     .id = {
-        .idVendor          = 0,
-        .idProduct         = 0,
+        .idVendor          = 0x46f4, /* CRC16() of "QEMU" */
+        .idProduct         = 0x0001,
         .bcdDevice         = 0,
         .iManufacturer     = STR_MANUFACTURER,
         .iProduct          = STR_PRODUCT,
commit c2a8238a2c1e37a2ae6d628a2b7bd95d1b5f1a89
Author: Stefan Weil <sw at weilnetz.de>
Date:   Mon Oct 31 21:29:46 2011 +0100

    Support running QEMU on Valgrind
    
    Valgrind is a tool which can automatically detect many kinds of bugs.
    
    Running QEMU on Valgrind with x86_64 hosts was not possible because
    Valgrind aborts when memalign is called with an alignment larger than
    1 MiB. QEMU normally uses 2 MiB on Linux x86_64.
    
    Now the alignment is reduced to the page size when QEMU is running on
    Valgrind.
    
    v2:
    Instead of using the macro RUNNING_ON_VALGRIND from valgrind.h,
    the patch now uses a hack from libvirt which tests for the pre-loaded
    vgpreload_*.so shared libraries. This avoids the need for valgrind.h.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/oslib-posix.c b/oslib-posix.c
index dbc8ee8..6f29762 100644
--- a/oslib-posix.c
+++ b/oslib-posix.c
@@ -36,8 +36,11 @@ extern int daemon(int, int);
 #endif
 
 #if defined(__linux__) && defined(__x86_64__)
-   /* Use 2MB alignment so transparent hugepages can be used by KVM */
+   /* Use 2 MiB alignment so transparent hugepages can be used by KVM.
+      Valgrind does not support alignments larger than 1 MiB,
+      therefore we need special code which handles running on Valgrind. */
 #  define QEMU_VMALLOC_ALIGN (512 * 4096)
+#  define CONFIG_VALGRIND
 #else
 #  define QEMU_VMALLOC_ALIGN getpagesize()
 #endif
@@ -47,7 +50,11 @@ extern int daemon(int, int);
 #include "trace.h"
 #include "qemu_socket.h"
 
-
+#if defined(CONFIG_VALGRIND)
+static int running_on_valgrind = -1;
+#else
+#  define running_on_valgrind 0
+#endif
 
 int qemu_daemon(int nochdir, int noclose)
 {
@@ -89,7 +96,16 @@ void *qemu_vmalloc(size_t size)
     void *ptr;
     size_t align = QEMU_VMALLOC_ALIGN;
 
-    if (size < align) {
+#if defined(CONFIG_VALGRIND)
+    if (running_on_valgrind < 0) {
+        /* First call, test whether we are running on Valgrind.
+           This is a substitute for RUNNING_ON_VALGRIND from valgrind.h. */
+        const char *ld = getenv("LD_PRELOAD");
+        running_on_valgrind = (ld != NULL && strstr(ld, "vgpreload"));
+    }
+#endif
+
+    if (size < align || running_on_valgrind) {
         align = getpagesize();
     }
     ptr = qemu_memalign(align, size);
commit ec38d39827df4450fa08fc28f725542afa8c350f
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Tue Nov 1 00:03:07 2011 +0100

    MAINTAINERS: Add PReP maintainer
    
    Officially take on maintainership for PReP and upgrade to Odd Fixes.
    
    Acked-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Cc: Alexander Graf <agraf at suse.de>
    Cc: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/MAINTAINERS b/MAINTAINERS
index 4535eeb..bccdd4f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -303,9 +303,9 @@ M: Alexander Graf <agraf at suse.de>
 S: Maintained
 F: hw/ppc_oldworld.c
 
-Prep
-M: qemu-devel at nongnu.org
-S: Orphan
+PReP
+M: Andreas Färber <andreas.faerber at web.de>
+S: Odd Fixes
 F: hw/ppc_prep.c
 
 SH4 Machines
commit 454e202d52a517c631cb750ba65ff8079c08b301
Author: Mark Wu <wudxw at linux.vnet.ibm.com>
Date:   Mon Oct 31 11:29:04 2011 +0800

    trace: Add wildcard trace event support
    
    A basic wildcard matching is supported in both the monitor command
    "trace-event" and the events list file. That means you can enable/disable
    the events having a common prefix in a batch. For example, virtio-blk trace
    events could be enabled using:
        trace-event virtio_blk_* on
    
    Signed-off-by: Mark Wu <wudxw at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/docs/tracing.txt b/docs/tracing.txt
index 95ca16c..ea29f2c 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -132,12 +132,19 @@ This functionality is also provided through monitor commands:
   means disabled.
 
 * trace-event NAME on|off
-  Enable/disable a given trace event.
+  Enable/disable a given trace event or a group of events having common prefix
+  through wildcard.
 
 The "-trace events=<file>" command line argument can be used to enable the
 events listed in <file> from the very beginning of the program. This file must
 contain one event name per line.
 
+A basic wildcard matching is supported in both the monitor command "trace
+-event" and the events list file. That means you can enable/disable the events
+having a common prefix in a batch. For example, virtio-blk trace events could
+be enabled using:
+  trace-event virtio_blk_* on
+
 == Trace backends ==
 
 The "tracetool" script automates tedious trace event code generation and also
diff --git a/trace/simple.c b/trace/simple.c
index b639dda..6339152 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -324,14 +324,29 @@ void trace_print_events(FILE *stream, fprintf_function stream_printf)
 bool trace_event_set_state(const char *name, bool state)
 {
     unsigned int i;
-
+    unsigned int len;
+    bool wildcard = false;
+    bool matched = false;
+
+    len = strlen(name);
+    if (len > 0 && name[len - 1] == '*') {
+        wildcard = true;
+        len -= 1;
+    }
     for (i = 0; i < NR_TRACE_EVENTS; i++) {
+        if (wildcard) {
+            if (!strncmp(trace_list[i].tp_name, name, len)) {
+                trace_list[i].state = state;
+                matched = true;
+            }
+            continue;
+        }
         if (!strcmp(trace_list[i].tp_name, name)) {
             trace_list[i].state = state;
             return true;
         }
     }
-    return false;
+    return matched;
 }
 
 /* Helper function to create a thread with signals blocked.  Use glib's
diff --git a/trace/stderr.c b/trace/stderr.c
index 7107c4a..0810d6f 100644
--- a/trace/stderr.c
+++ b/trace/stderr.c
@@ -15,14 +15,29 @@ void trace_print_events(FILE *stream, fprintf_function stream_printf)
 bool trace_event_set_state(const char *name, bool state)
 {
     unsigned int i;
+    unsigned int len;
+    bool wildcard = false;
+    bool matched = false;
 
+    len = strlen(name);
+    if (len > 0 && name[len - 1] == '*') {
+        wildcard = true;
+        len -= 1;
+    }
     for (i = 0; i < NR_TRACE_EVENTS; i++) {
+        if (wildcard) {
+            if (!strncmp(trace_list[i].tp_name, name, len)) {
+                trace_list[i].state = state;
+                matched = true;
+            }
+            continue;
+        }
         if (!strcmp(trace_list[i].tp_name, name)) {
             trace_list[i].state = state;
             return true;
         }
     }
-    return false;
+    return matched;
 }
 
 bool trace_backend_init(const char *events, const char *file)
commit 4a33a9ea06f6fbb08d8311a7cfed72975344f9ab
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Oct 14 11:36:43 2011 +0200

    usb-hub: wakeup on attach
    
    When attaching a new device we must send a wakeup request to the root
    hub, otherwise the guest will not notice the new device in case the
    usb hub is suspended.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 09c6516..7b47079 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -163,6 +163,7 @@ static void usb_hub_attach(USBPort *port1)
     } else {
         port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
     }
+    usb_wakeup(&s->dev);
 }
 
 static void usb_hub_detach(USBPort *port1)
commit 54825d2e39b0a809332b5fee837f456d5d9befee
Author: Alon Levy <alevy at redhat.com>
Date:   Tue Oct 25 15:39:50 2011 +0200

    qxl: create slots on post_load in vga state
    
    RHBZ 740547
    
    If we migrate when the device is in vga state the guest
    still believes the slots are created, and will cause operations
    that reference the slots, causing a "panic: virtual address out of range"
    on the first of them. Easy to see by migrating in vga mode with
    a driver loaded, for instance windows cmd window in full screen mode,
    and then exiting vga mode back to native mode will cause said panic.
    
    Fixed by doing the slot recreation in post_load for vga mode as well.
    Note that compat does not require any changes because it creates it's
    only slot by a side effect of QXL_IO_SET_MODE.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index 12f71aa..84ffd45 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1663,12 +1663,25 @@ static int qxl_pre_load(void *opaque)
     return 0;
 }
 
+static void qxl_create_memslots(PCIQXLDevice *d)
+{
+    int i;
+
+    for (i = 0; i < NUM_MEMSLOTS; i++) {
+        if (!d->guest_slots[i].active) {
+            continue;
+        }
+        dprint(d, 1, "%s: restoring guest slot %d\n", __func__, i);
+        qxl_add_memslot(d, i, 0, QXL_SYNC);
+    }
+}
+
 static int qxl_post_load(void *opaque, int version)
 {
     PCIQXLDevice* d = opaque;
     uint8_t *ram_start = d->vga.vram_ptr;
     QXLCommandExt *cmds;
-    int in, out, i, newmode;
+    int in, out, newmode;
 
     dprint(d, 1, "%s: start\n", __FUNCTION__);
 
@@ -1685,19 +1698,16 @@ static int qxl_post_load(void *opaque, int version)
         qxl_mode_to_string(d->mode));
     newmode = d->mode;
     d->mode = QXL_MODE_UNDEFINED;
+
     switch (newmode) {
     case QXL_MODE_UNDEFINED:
         break;
     case QXL_MODE_VGA:
+        qxl_create_memslots(d);
         qxl_enter_vga_mode(d);
         break;
     case QXL_MODE_NATIVE:
-        for (i = 0; i < NUM_MEMSLOTS; i++) {
-            if (!d->guest_slots[i].active) {
-                continue;
-            }
-            qxl_add_memslot(d, i, 0, QXL_SYNC);
-        }
+        qxl_create_memslots(d);
         qxl_create_guest_primary(d, 1, QXL_SYNC);
 
         /* replay surface-create and cursor-set commands */
@@ -1722,6 +1732,8 @@ static int qxl_post_load(void *opaque, int version)
 
         break;
     case QXL_MODE_COMPAT:
+        /* note: no need to call qxl_create_memslots, qxl_set_mode
+         * creates the mem slot. */
         qxl_set_mode(d, d->shadow_rom.mode, 1);
         break;
     }
commit a053f1b1fb63cb57483354db7b154e9a2e585b5a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Oct 21 21:53:54 2011 +0200

    qxl: make sure we continue to run with a shared buffer
    
    The qxl renderer works only with a shared displaysurface.  So better
    make sure we actually have one and restore it when needed.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index a567693..2c51ba9 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -76,7 +76,14 @@ void qxl_render_update(PCIQXLDevice *qxl)
     VGACommonState *vga = &qxl->vga;
     QXLRect dirty[32], update;
     void *ptr;
-    int i;
+    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;
+    }
 
     if (qxl->guest_primary.resized) {
         qxl->guest_primary.resized = 0;
@@ -127,6 +134,10 @@ void qxl_render_update(PCIQXLDevice *qxl)
     memset(dirty, 0, sizeof(dirty));
     qxl_spice_update_area(qxl, 0, &update,
                           dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC);
+    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)) {
commit 0e2487bd6f56445b43307536a465ee2ba810aed9
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Oct 21 15:59:07 2011 +0200

    qxl: stride fixup
    
    spice uses negative stride value to signal the bitmap is upside down.
    The qxl renderer (used for scl, vnc and screenshots) wants a positive
    value because it is easier to work with.  The positive value is then
    stored in the very same variable, which has the drawback that the
    upside-down test works only once.  Fix by using two variables.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index c290739..a567693 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -28,16 +28,16 @@ static void qxl_flip(PCIQXLDevice *qxl, QXLRect *rect)
     int len, i;
 
     src += (qxl->guest_primary.surface.height - rect->top - 1) *
-        qxl->guest_primary.stride;
-    dst += rect->top  * qxl->guest_primary.stride;
+        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;
     len  = (rect->right - rect->left) * qxl->guest_primary.bytes_pp;
 
     for (i = rect->top; i < rect->bottom; i++) {
         memcpy(dst, src, len);
-        dst += qxl->guest_primary.stride;
-        src -= qxl->guest_primary.stride;
+        dst += qxl->guest_primary.abs_stride;
+        src -= qxl->guest_primary.abs_stride;
     }
 }
 
@@ -45,7 +45,8 @@ void qxl_render_resize(PCIQXLDevice *qxl)
 {
     QXLSurfaceCreate *sc = &qxl->guest_primary.surface;
 
-    qxl->guest_primary.stride = sc->stride;
+    qxl->guest_primary.qxl_stride = sc->stride;
+    qxl->guest_primary.abs_stride = abs(sc->stride);
     qxl->guest_primary.resized++;
     switch (sc->format) {
     case SPICE_SURFACE_FMT_16_555:
@@ -87,11 +88,11 @@ void qxl_render_update(PCIQXLDevice *qxl)
         qemu_free_displaysurface(vga->ds);
 
         qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
-        if (qxl->guest_primary.stride < 0) {
+        if (qxl->guest_primary.qxl_stride < 0) {
             /* spice surface is upside down -> need extra buffer to flip */
-            qxl->guest_primary.stride = -qxl->guest_primary.stride;
-            qxl->guest_primary.flipped = g_malloc(qxl->guest_primary.surface.width *
-                                                     qxl->guest_primary.stride);
+            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;
@@ -100,7 +101,7 @@ void qxl_render_update(PCIQXLDevice *qxl)
                __FUNCTION__,
                qxl->guest_primary.surface.width,
                qxl->guest_primary.surface.height,
-               qxl->guest_primary.stride,
+               qxl->guest_primary.qxl_stride,
                qxl->guest_primary.bytes_pp,
                qxl->guest_primary.bits_pp,
                qxl->guest_primary.flipped ? "yes" : "no");
@@ -108,7 +109,7 @@ void qxl_render_update(PCIQXLDevice *qxl)
             qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
                                             qxl->guest_primary.surface.height,
                                             qxl->guest_primary.bits_pp,
-                                            qxl->guest_primary.stride,
+                                            qxl->guest_primary.abs_stride,
                                             ptr);
         dpy_resize(vga->ds);
     }
diff --git a/hw/qxl.h b/hw/qxl.h
index 37b2619..766aa6d 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -48,7 +48,8 @@ typedef struct PCIQXLDevice {
         QXLSurfaceCreate surface;
         uint32_t       commands;
         uint32_t       resized;
-        int32_t        stride;
+        int32_t        qxl_stride;
+        uint32_t       abs_stride;
         uint32_t       bits_pp;
         uint32_t       bytes_pp;
         uint8_t        *data, *flipped;
commit 0ce6a434176e274a7e86bcaa268542c5cc402696
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Oct 28 17:07:02 2011 +0200

    acl: Fix use after free in qemu_acl_reset()
    
    Reproducer:
    
        $ MALLOC_PERTURB_=234 qemu-system-x86_64 -vnc :0,acl,sasl [...]
        QEMU 0.15.50 monitor - type 'help' for more information
        (qemu) acl_add vnc.username fred allow
        acl: added rule at position 1
        (qemu) acl_reset vnc.username
        Segmentation fault (core dumped)
    
    Spotted by Coverity.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/acl.c b/acl.c
index 0654f38..e840b9b 100644
--- a/acl.c
+++ b/acl.c
@@ -95,13 +95,13 @@ int qemu_acl_party_is_allowed(qemu_acl *acl,
 
 void qemu_acl_reset(qemu_acl *acl)
 {
-    qemu_acl_entry *entry;
+    qemu_acl_entry *entry, *next_entry;
 
     /* Put back to deny by default, so there is no window
      * of "open access" while the user re-initializes the
      * access control list */
     acl->defaultDeny = 1;
-    QTAILQ_FOREACH(entry, &acl->entries, next) {
+    QTAILQ_FOREACH_SAFE(entry, &acl->entries, next, next_entry) {
         QTAILQ_REMOVE(&acl->entries, entry, next);
         free(entry->match);
         free(entry);
commit acf8394eaed69f23d39b0ebbb20477aef1afcbb2
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Fri Oct 28 15:58:26 2011 +0100

    qapi: fix typos in documentation JSON examples
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index f345866..c0a9325 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -41,7 +41,7 @@ dictionary.  This corresponds to a struct in C or an Object in JSON.  An
 example of a complex type is:
 
  { 'type': 'MyType',
-   'data' { 'member1': 'str', 'member2': 'int', '*member3': 'str } }
+   'data': { 'member1': 'str', 'member2': 'int', '*member3': 'str' } }
 
 The use of '*' as a prefix to the name means the member is optional.  Optional
 members should always be added to the end of the dictionary to preserve
@@ -63,7 +63,7 @@ An example command is:
 
  { 'command': 'my-command',
    'data': { 'arg1': 'str', '*arg2': 'str' },
-   'returns': 'str' ]
+   'returns': 'str' }
 
 Command names should be all lower case with words separated by a hyphen.
 
commit d0bc5bc3aac64be2c0b91f1446ed748444cc3141
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Oct 28 10:52:25 2011 +0200

    sysbus: Supply missing va_end()
    
    C99 7.15.1: Each invocation of the va_start and va_copy macros shall
    be matched by a corresponding invocation of the va_end macro in the
    same function.
    
    Spotted by Coverity.  Harmless on the (common) systems where va_end()
    does nothing.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/sysbus.c b/hw/sysbus.c
index 4fab5a4..fd2fc6a 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -198,6 +198,7 @@ DeviceState *sysbus_create_varargs(const char *name,
         sysbus_connect_irq(s, n, irq);
         n++;
     }
+    va_end(va);
     return dev;
 }
 
@@ -229,6 +230,7 @@ DeviceState *sysbus_try_create_varargs(const char *name,
         sysbus_connect_irq(s, n, irq);
         n++;
     }
+    va_end(va);
     return dev;
 }
 
commit 93a7320e32a2b7463c4dc3cfb5a0c77c46d8e687
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Fri Oct 14 15:05:10 2011 -0300

    net: tap-linux: Fix unhelpful error message
    
    I'm getting:
    
        could not configure /dev/net/tun (tap%d): Operation not permitted
    
    When the ioctl() fails, ifr.ifr_name will most likely not be overwritten.
    So we better only use it when ifname contains a string.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/net/tap-linux.c b/net/tap-linux.c
index ff8cad0..41d581b 100644
--- a/net/tap-linux.c
+++ b/net/tap-linux.c
@@ -73,7 +73,11 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
         pstrcpy(ifr.ifr_name, IFNAMSIZ, "tap%d");
     ret = ioctl(fd, TUNSETIFF, (void *) &ifr);
     if (ret != 0) {
-        error_report("could not configure %s (%s): %m", PATH_NET_TUN, ifr.ifr_name);
+        if (ifname[0] != '\0') {
+            error_report("could not configure %s (%s): %m", PATH_NET_TUN, ifr.ifr_name);
+        } else {
+            error_report("could not configure %s: %m", PATH_NET_TUN);
+        }
         close(fd);
         return -1;
     }
commit 9195b2c2b1b00799b68f6d68a73e547d1274eb03
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Oct 19 07:07:18 2011 +0200

    tcg: Add tcg interpreter to configure / make
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/Makefile.target b/Makefile.target
index 530c1d1..406b125 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -69,6 +69,7 @@ all: $(PROGS) stap
 # cpu emulator library
 libobj-y = exec.o translate-all.o cpu-exec.o translate.o
 libobj-y += tcg/tcg.o tcg/optimize.o
+libobj-$(CONFIG_TCG_INTERPRETER) += tci.o
 libobj-y += fpu/softfloat.o
 libobj-y += op_helper.o helper.o
 ifeq ($(TARGET_BASE_ARCH), i386)
@@ -85,6 +86,9 @@ libobj-$(TARGET_SPARC) += int32_helper.o
 libobj-$(TARGET_SPARC64) += int64_helper.o
 
 libobj-y += disas.o
+libobj-$(CONFIG_TCI_DIS) += tci-dis.o
+
+tci-dis.o: QEMU_CFLAGS += -I$(SRC_PATH)/tcg -I$(SRC_PATH)/tcg/tci
 
 $(libobj-y): $(GENERATED_HEADERS)
 
diff --git a/configure b/configure
index a6cf6d6..54674df 100755
--- a/configure
+++ b/configure
@@ -138,6 +138,7 @@ debug_tcg="no"
 debug_mon="no"
 debug="no"
 strip_opt="yes"
+tcg_interpreter="no"
 bigendian="no"
 mingw32="no"
 EXESUF=""
@@ -654,6 +655,10 @@ for opt do
   ;;
   --enable-kvm) kvm="yes"
   ;;
+  --disable-tcg-interpreter) tcg_interpreter="no"
+  ;;
+  --enable-tcg-interpreter) tcg_interpreter="yes"
+  ;;
   --disable-spice) spice="no"
   ;;
   --enable-spice) spice="yes"
@@ -1009,6 +1014,7 @@ echo "  --enable-bluez           enable bluez stack connectivity"
 echo "  --disable-slirp          disable SLIRP userspace network connectivity"
 echo "  --disable-kvm            disable KVM acceleration support"
 echo "  --enable-kvm             enable KVM acceleration support"
+echo "  --enable-tcg-interpreter enable TCG with bytecode interpreter (TCI)"
 echo "  --disable-nptl           disable usermode NPTL support"
 echo "  --enable-nptl            enable usermode NPTL support"
 echo "  --enable-system          enable all system emulation targets"
@@ -2755,6 +2761,7 @@ echo "Linux AIO support $linux_aio"
 echo "ATTR/XATTR support $attr"
 echo "Install blobs     $blobs"
 echo "KVM support       $kvm"
+echo "TCG interpreter   $tcg_interpreter"
 echo "fdt support       $fdt"
 echo "preadv support    $preadv"
 echo "fdatasync         $fdatasync"
@@ -2803,6 +2810,15 @@ case "$cpu" in
   armv4b|armv4l)
     ARCH=arm
   ;;
+  *)
+    if test "$tcg_interpreter" = "yes" ; then
+        echo "Unsupported CPU = $cpu, will use TCG with TCI (experimental)"
+        ARCH=tci
+    else
+        echo "Unsupported CPU = $cpu, try --enable-tcg-interpreter"
+        exit 1
+    fi
+  ;;
 esac
 echo "ARCH=$ARCH" >> $config_host_mak
 if test "$debug_tcg" = "yes" ; then
@@ -3036,6 +3052,9 @@ fi
 if test "$signalfd" = "yes" ; then
   echo "CONFIG_SIGNALFD=y" >> $config_host_mak
 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
@@ -3508,7 +3527,9 @@ cflags=""
 includes=""
 ldflags=""
 
-if test "$ARCH" = "sparc64" ; then
+if test "$tcg_interpreter" = "yes"; then
+  includes="-I\$(SRC_PATH)/tcg/tci $includes"
+elif test "$ARCH" = "sparc64" ; then
   includes="-I\$(SRC_PATH)/tcg/sparc $includes"
 elif test "$ARCH" = "s390x" ; then
   includes="-I\$(SRC_PATH)/tcg/s390 $includes"
@@ -3585,6 +3606,10 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
   ;;
   esac
 done
+if test "$tcg_interpreter" = "yes" ; then
+  echo "CONFIG_TCI_DIS=y"  >> $config_target_mak
+  echo "CONFIG_TCI_DIS=y"  >> $libdis_config_mak
+fi
 
 case "$ARCH" in
 alpha)
@@ -3631,7 +3656,12 @@ if test "$gprof" = "yes" ; then
   fi
 fi
 
-linker_script="-Wl,-T../config-host.ld -Wl,-T,\$(SRC_PATH)/\$(ARCH).ld"
+if test "$ARCH" = "tci"; then
+  linker_script=""
+else
+  linker_script="-Wl,-T../config-host.ld -Wl,-T,\$(SRC_PATH)/\$(ARCH).ld"
+fi
+
 if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then
   case "$ARCH" in
   sparc)
commit 5826e51917525dac7704ba8f80d624578fdad3c8
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Oct 5 20:03:53 2011 +0200

    tcg: Add tci disassembler
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/dis-asm.h b/dis-asm.h
index 5b07d7f..4f15fad 100644
--- a/dis-asm.h
+++ b/dis-asm.h
@@ -365,6 +365,7 @@ typedef struct disassemble_info {
    target address.  Return number of bytes processed.  */
 typedef int (*disassembler_ftype) (bfd_vma, disassemble_info *);
 
+int print_insn_tci(bfd_vma, disassemble_info*);
 int print_insn_big_mips         (bfd_vma, disassemble_info*);
 int print_insn_little_mips      (bfd_vma, disassemble_info*);
 int print_insn_i386             (bfd_vma, disassemble_info*);
diff --git a/disas.c b/disas.c
index 611b30b..3b1fd97 100644
--- a/disas.c
+++ b/disas.c
@@ -273,7 +273,9 @@ void disas(FILE *out, void *code, unsigned long size)
 #else
     disasm_info.endian = BFD_ENDIAN_LITTLE;
 #endif
-#if defined(__i386__)
+#if defined(CONFIG_TCG_INTERPRETER)
+    print_insn = print_insn_tci;
+#elif defined(__i386__)
     disasm_info.mach = bfd_mach_i386_i386;
     print_insn = print_insn_i386;
 #elif defined(__x86_64__)
diff --git a/tci-dis.c b/tci-dis.c
new file mode 100644
index 0000000..10c411b
--- /dev/null
+++ b/tci-dis.c
@@ -0,0 +1,59 @@
+/*
+ * Tiny Code Interpreter for QEMU - disassembler
+ *
+ * Copyright (c) 2011 Stefan Weil
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "dis-asm.h"
+#include "tcg/tcg.h"
+
+/* Disassemble TCI bytecode. */
+int print_insn_tci(bfd_vma addr, disassemble_info *info)
+{
+    int length;
+    uint8_t byte;
+    int status;
+    TCGOpcode op;
+
+    status = info->read_memory_func(addr, &byte, 1, info);
+    if (status != 0) {
+        info->memory_error_func(status, addr, info);
+        return -1;
+    }
+    op = byte;
+
+    addr++;
+    status = info->read_memory_func(addr, &byte, 1, info);
+    if (status != 0) {
+        info->memory_error_func(status, addr, info);
+        return -1;
+    }
+    length = byte;
+
+    if (op >= tcg_op_defs_max) {
+        info->fprintf_func(info->stream, "illegal opcode %d", op);
+    } else {
+        const TCGOpDef *def = &tcg_op_defs[op];
+        int nb_oargs = def->nb_oargs;
+        int nb_iargs = def->nb_iargs;
+        int nb_cargs = def->nb_cargs;
+        /* TODO: Improve disassembler output. */
+        info->fprintf_func(info->stream, "%s\to=%d i=%d c=%d",
+                           def->name, nb_oargs, nb_iargs, nb_cargs);
+    }
+
+    return length;
+}
commit 7657f4bf68c829623074a60b64f7569532137488
Author: Stefan Weil <sw at weilnetz.de>
Date:   Tue Sep 27 06:30:58 2011 +0200

    tcg: Add interpreter for bytecode
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/tci.c b/tci.c
new file mode 100644
index 0000000..f17785d
--- /dev/null
+++ b/tci.c
@@ -0,0 +1,1208 @@
+/*
+ * Tiny Code Interpreter for QEMU
+ *
+ * Copyright (c) 2009, 2011 Stefan Weil
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+/* Defining NDEBUG disables assertions (which makes the code faster). */
+#if !defined(CONFIG_TCG_DEBUG) && !defined(NDEBUG)
+# define NDEBUG
+#endif
+
+#include "qemu-common.h"
+#include "dyngen-exec.h"        /* env */
+#include "exec-all.h"           /* MAX_OPC_PARAM_IARGS */
+#include "tcg-op.h"
+
+/* Marker for missing code. */
+#define TODO() \
+    do { \
+        fprintf(stderr, "TODO %s:%u: %s()\n", \
+                __FILE__, __LINE__, __func__); \
+        tcg_abort(); \
+    } while (0)
+
+#if MAX_OPC_PARAM_IARGS != 4
+# error Fix needed, number of supported input arguments changed!
+#endif
+#if TCG_TARGET_REG_BITS == 32
+typedef uint64_t (*helper_function)(tcg_target_ulong, tcg_target_ulong,
+                                    tcg_target_ulong, tcg_target_ulong,
+                                    tcg_target_ulong, tcg_target_ulong,
+                                    tcg_target_ulong, tcg_target_ulong);
+#else
+typedef uint64_t (*helper_function)(tcg_target_ulong, tcg_target_ulong,
+                                    tcg_target_ulong, tcg_target_ulong);
+#endif
+
+/* TCI can optionally use a global register variable for env. */
+#if !defined(AREG0)
+CPUState *env;
+#endif
+
+/* Targets which don't use GETPC also don't need tci_tb_ptr
+   which makes them a little faster. */
+#if defined(GETPC)
+void *tci_tb_ptr;
+#endif
+
+static tcg_target_ulong tci_reg[TCG_TARGET_NB_REGS];
+
+static tcg_target_ulong tci_read_reg(TCGRegister index)
+{
+    assert(index < ARRAY_SIZE(tci_reg));
+    return tci_reg[index];
+}
+
+#if TCG_TARGET_HAS_ext8s_i32 || TCG_TARGET_HAS_ext8s_i64
+static int8_t tci_read_reg8s(TCGRegister index)
+{
+    return (int8_t)tci_read_reg(index);
+}
+#endif
+
+#if TCG_TARGET_HAS_ext16s_i32 || TCG_TARGET_HAS_ext16s_i64
+static int16_t tci_read_reg16s(TCGRegister index)
+{
+    return (int16_t)tci_read_reg(index);
+}
+#endif
+
+#if TCG_TARGET_REG_BITS == 64
+static int32_t tci_read_reg32s(TCGRegister index)
+{
+    return (int32_t)tci_read_reg(index);
+}
+#endif
+
+static uint8_t tci_read_reg8(TCGRegister index)
+{
+    return (uint8_t)tci_read_reg(index);
+}
+
+static uint16_t tci_read_reg16(TCGRegister index)
+{
+    return (uint16_t)tci_read_reg(index);
+}
+
+static uint32_t tci_read_reg32(TCGRegister index)
+{
+    return (uint32_t)tci_read_reg(index);
+}
+
+#if TCG_TARGET_REG_BITS == 64
+static uint64_t tci_read_reg64(TCGRegister index)
+{
+    return tci_read_reg(index);
+}
+#endif
+
+static void tci_write_reg(TCGRegister index, tcg_target_ulong value)
+{
+    assert(index < ARRAY_SIZE(tci_reg));
+    assert(index != TCG_AREG0);
+    tci_reg[index] = value;
+}
+
+static void tci_write_reg8s(TCGRegister index, int8_t value)
+{
+    tci_write_reg(index, value);
+}
+
+static void tci_write_reg16s(TCGRegister index, int16_t value)
+{
+    tci_write_reg(index, value);
+}
+
+#if TCG_TARGET_REG_BITS == 64
+static void tci_write_reg32s(TCGRegister index, int32_t value)
+{
+    tci_write_reg(index, value);
+}
+#endif
+
+static void tci_write_reg8(TCGRegister index, uint8_t value)
+{
+    tci_write_reg(index, value);
+}
+
+static void tci_write_reg16(TCGRegister index, uint16_t value)
+{
+    tci_write_reg(index, value);
+}
+
+static void tci_write_reg32(TCGRegister index, uint32_t value)
+{
+    tci_write_reg(index, value);
+}
+
+#if TCG_TARGET_REG_BITS == 32
+static void tci_write_reg64(uint32_t high_index, uint32_t low_index,
+                            uint64_t value)
+{
+    tci_write_reg(low_index, value);
+    tci_write_reg(high_index, value >> 32);
+}
+#elif TCG_TARGET_REG_BITS == 64
+static void tci_write_reg64(TCGRegister index, uint64_t value)
+{
+    tci_write_reg(index, value);
+}
+#endif
+
+#if TCG_TARGET_REG_BITS == 32
+/* Create a 64 bit value from two 32 bit values. */
+static uint64_t tci_uint64(uint32_t high, uint32_t low)
+{
+    return ((uint64_t)high << 32) + low;
+}
+#endif
+
+/* Read constant (native size) from bytecode. */
+static tcg_target_ulong tci_read_i(uint8_t **tb_ptr)
+{
+    tcg_target_ulong value = *(tcg_target_ulong *)(*tb_ptr);
+    *tb_ptr += sizeof(value);
+    return value;
+}
+
+/* Read constant (32 bit) from bytecode. */
+static uint32_t tci_read_i32(uint8_t **tb_ptr)
+{
+    uint32_t value = *(uint32_t *)(*tb_ptr);
+    *tb_ptr += sizeof(value);
+    return value;
+}
+
+#if TCG_TARGET_REG_BITS == 64
+/* Read constant (64 bit) from bytecode. */
+static uint64_t tci_read_i64(uint8_t **tb_ptr)
+{
+    uint64_t value = *(uint64_t *)(*tb_ptr);
+    *tb_ptr += sizeof(value);
+    return value;
+}
+#endif
+
+/* Read indexed register (native size) from bytecode. */
+static tcg_target_ulong tci_read_r(uint8_t **tb_ptr)
+{
+    tcg_target_ulong value = tci_read_reg(**tb_ptr);
+    *tb_ptr += 1;
+    return value;
+}
+
+/* Read indexed register (8 bit) from bytecode. */
+static uint8_t tci_read_r8(uint8_t **tb_ptr)
+{
+    uint8_t value = tci_read_reg8(**tb_ptr);
+    *tb_ptr += 1;
+    return value;
+}
+
+#if TCG_TARGET_HAS_ext8s_i32 || TCG_TARGET_HAS_ext8s_i64
+/* Read indexed register (8 bit signed) from bytecode. */
+static int8_t tci_read_r8s(uint8_t **tb_ptr)
+{
+    int8_t value = tci_read_reg8s(**tb_ptr);
+    *tb_ptr += 1;
+    return value;
+}
+#endif
+
+/* Read indexed register (16 bit) from bytecode. */
+static uint16_t tci_read_r16(uint8_t **tb_ptr)
+{
+    uint16_t value = tci_read_reg16(**tb_ptr);
+    *tb_ptr += 1;
+    return value;
+}
+
+#if TCG_TARGET_HAS_ext16s_i32 || TCG_TARGET_HAS_ext16s_i64
+/* Read indexed register (16 bit signed) from bytecode. */
+static int16_t tci_read_r16s(uint8_t **tb_ptr)
+{
+    int16_t value = tci_read_reg16s(**tb_ptr);
+    *tb_ptr += 1;
+    return value;
+}
+#endif
+
+/* Read indexed register (32 bit) from bytecode. */
+static uint32_t tci_read_r32(uint8_t **tb_ptr)
+{
+    uint32_t value = tci_read_reg32(**tb_ptr);
+    *tb_ptr += 1;
+    return value;
+}
+
+#if TCG_TARGET_REG_BITS == 32
+/* Read two indexed registers (2 * 32 bit) from bytecode. */
+static uint64_t tci_read_r64(uint8_t **tb_ptr)
+{
+    uint32_t low = tci_read_r32(tb_ptr);
+    return tci_uint64(tci_read_r32(tb_ptr), low);
+}
+#elif TCG_TARGET_REG_BITS == 64
+/* Read indexed register (32 bit signed) from bytecode. */
+static int32_t tci_read_r32s(uint8_t **tb_ptr)
+{
+    int32_t value = tci_read_reg32s(**tb_ptr);
+    *tb_ptr += 1;
+    return value;
+}
+
+/* Read indexed register (64 bit) from bytecode. */
+static uint64_t tci_read_r64(uint8_t **tb_ptr)
+{
+    uint64_t value = tci_read_reg64(**tb_ptr);
+    *tb_ptr += 1;
+    return value;
+}
+#endif
+
+/* Read indexed register(s) with target address from bytecode. */
+static target_ulong tci_read_ulong(uint8_t **tb_ptr)
+{
+    target_ulong taddr = tci_read_r(tb_ptr);
+#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
+    taddr += (uint64_t)tci_read_r(tb_ptr) << 32;
+#endif
+    return taddr;
+}
+
+/* Read indexed register or constant (native size) from bytecode. */
+static tcg_target_ulong tci_read_ri(uint8_t **tb_ptr)
+{
+    tcg_target_ulong value;
+    TCGRegister r = **tb_ptr;
+    *tb_ptr += 1;
+    if (r == TCG_CONST) {
+        value = tci_read_i(tb_ptr);
+    } else {
+        value = tci_read_reg(r);
+    }
+    return value;
+}
+
+/* Read indexed register or constant (32 bit) from bytecode. */
+static uint32_t tci_read_ri32(uint8_t **tb_ptr)
+{
+    uint32_t value;
+    TCGRegister r = **tb_ptr;
+    *tb_ptr += 1;
+    if (r == TCG_CONST) {
+        value = tci_read_i32(tb_ptr);
+    } else {
+        value = tci_read_reg32(r);
+    }
+    return value;
+}
+
+#if TCG_TARGET_REG_BITS == 32
+/* Read two indexed registers or constants (2 * 32 bit) from bytecode. */
+static uint64_t tci_read_ri64(uint8_t **tb_ptr)
+{
+    uint32_t low = tci_read_ri32(tb_ptr);
+    return tci_uint64(tci_read_ri32(tb_ptr), low);
+}
+#elif TCG_TARGET_REG_BITS == 64
+/* Read indexed register or constant (64 bit) from bytecode. */
+static uint64_t tci_read_ri64(uint8_t **tb_ptr)
+{
+    uint64_t value;
+    TCGRegister r = **tb_ptr;
+    *tb_ptr += 1;
+    if (r == TCG_CONST) {
+        value = tci_read_i64(tb_ptr);
+    } else {
+        value = tci_read_reg64(r);
+    }
+    return value;
+}
+#endif
+
+static target_ulong tci_read_label(uint8_t **tb_ptr)
+{
+    target_ulong label = tci_read_i(tb_ptr);
+    assert(label != 0);
+    return label;
+}
+
+static bool tci_compare32(uint32_t u0, uint32_t u1, TCGCond condition)
+{
+    bool result = false;
+    int32_t i0 = u0;
+    int32_t i1 = u1;
+    switch (condition) {
+    case TCG_COND_EQ:
+        result = (u0 == u1);
+        break;
+    case TCG_COND_NE:
+        result = (u0 != u1);
+        break;
+    case TCG_COND_LT:
+        result = (i0 < i1);
+        break;
+    case TCG_COND_GE:
+        result = (i0 >= i1);
+        break;
+    case TCG_COND_LE:
+        result = (i0 <= i1);
+        break;
+    case TCG_COND_GT:
+        result = (i0 > i1);
+        break;
+    case TCG_COND_LTU:
+        result = (u0 < u1);
+        break;
+    case TCG_COND_GEU:
+        result = (u0 >= u1);
+        break;
+    case TCG_COND_LEU:
+        result = (u0 <= u1);
+        break;
+    case TCG_COND_GTU:
+        result = (u0 > u1);
+        break;
+    default:
+        TODO();
+    }
+    return result;
+}
+
+static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition)
+{
+    bool result = false;
+    int64_t i0 = u0;
+    int64_t i1 = u1;
+    switch (condition) {
+    case TCG_COND_EQ:
+        result = (u0 == u1);
+        break;
+    case TCG_COND_NE:
+        result = (u0 != u1);
+        break;
+    case TCG_COND_LT:
+        result = (i0 < i1);
+        break;
+    case TCG_COND_GE:
+        result = (i0 >= i1);
+        break;
+    case TCG_COND_LE:
+        result = (i0 <= i1);
+        break;
+    case TCG_COND_GT:
+        result = (i0 > i1);
+        break;
+    case TCG_COND_LTU:
+        result = (u0 < u1);
+        break;
+    case TCG_COND_GEU:
+        result = (u0 >= u1);
+        break;
+    case TCG_COND_LEU:
+        result = (u0 <= u1);
+        break;
+    case TCG_COND_GTU:
+        result = (u0 > u1);
+        break;
+    default:
+        TODO();
+    }
+    return result;
+}
+
+/* Interpret pseudo code in tb. */
+unsigned long tcg_qemu_tb_exec(CPUState *cpustate, uint8_t *tb_ptr)
+{
+    unsigned long next_tb = 0;
+
+    env = cpustate;
+    tci_reg[TCG_AREG0] = (tcg_target_ulong)env;
+    assert(tb_ptr);
+
+    for (;;) {
+#if defined(GETPC)
+        tci_tb_ptr = tb_ptr;
+#endif
+        TCGOpcode opc = tb_ptr[0];
+#if !defined(NDEBUG)
+        uint8_t op_size = tb_ptr[1];
+        uint8_t *old_code_ptr = tb_ptr;
+#endif
+        tcg_target_ulong t0;
+        tcg_target_ulong t1;
+        tcg_target_ulong t2;
+        tcg_target_ulong label;
+        TCGCond condition;
+        target_ulong taddr;
+#ifndef CONFIG_SOFTMMU
+        tcg_target_ulong host_addr;
+#endif
+        uint8_t tmp8;
+        uint16_t tmp16;
+        uint32_t tmp32;
+        uint64_t tmp64;
+#if TCG_TARGET_REG_BITS == 32
+        uint64_t v64;
+#endif
+
+        /* Skip opcode and size entry. */
+        tb_ptr += 2;
+
+        switch (opc) {
+        case INDEX_op_end:
+        case INDEX_op_nop:
+            break;
+        case INDEX_op_nop1:
+        case INDEX_op_nop2:
+        case INDEX_op_nop3:
+        case INDEX_op_nopn:
+        case INDEX_op_discard:
+            TODO();
+            break;
+        case INDEX_op_set_label:
+            TODO();
+            break;
+        case INDEX_op_call:
+            t0 = tci_read_ri(&tb_ptr);
+#if TCG_TARGET_REG_BITS == 32
+            tmp64 = ((helper_function)t0)(tci_read_reg(TCG_REG_R0),
+                                          tci_read_reg(TCG_REG_R1),
+                                          tci_read_reg(TCG_REG_R2),
+                                          tci_read_reg(TCG_REG_R3),
+                                          tci_read_reg(TCG_REG_R5),
+                                          tci_read_reg(TCG_REG_R6),
+                                          tci_read_reg(TCG_REG_R7),
+                                          tci_read_reg(TCG_REG_R8));
+            tci_write_reg(TCG_REG_R0, tmp64);
+            tci_write_reg(TCG_REG_R1, tmp64 >> 32);
+#else
+            tmp64 = ((helper_function)t0)(tci_read_reg(TCG_REG_R0),
+                                          tci_read_reg(TCG_REG_R1),
+                                          tci_read_reg(TCG_REG_R2),
+                                          tci_read_reg(TCG_REG_R3));
+            tci_write_reg(TCG_REG_R0, tmp64);
+#endif
+            break;
+        case INDEX_op_jmp:
+        case INDEX_op_br:
+            label = tci_read_label(&tb_ptr);
+            assert(tb_ptr == old_code_ptr + op_size);
+            tb_ptr = (uint8_t *)label;
+            continue;
+        case INDEX_op_setcond_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r32(&tb_ptr);
+            t2 = tci_read_ri32(&tb_ptr);
+            condition = *tb_ptr++;
+            tci_write_reg32(t0, tci_compare32(t1, t2, condition));
+            break;
+#if TCG_TARGET_REG_BITS == 32
+        case INDEX_op_setcond2_i32:
+            t0 = *tb_ptr++;
+            tmp64 = tci_read_r64(&tb_ptr);
+            v64 = tci_read_ri64(&tb_ptr);
+            condition = *tb_ptr++;
+            tci_write_reg32(t0, tci_compare64(tmp64, v64, condition));
+            break;
+#elif TCG_TARGET_REG_BITS == 64
+        case INDEX_op_setcond_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r64(&tb_ptr);
+            t2 = tci_read_ri64(&tb_ptr);
+            condition = *tb_ptr++;
+            tci_write_reg64(t0, tci_compare64(t1, t2, condition));
+            break;
+#endif
+        case INDEX_op_mov_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r32(&tb_ptr);
+            tci_write_reg32(t0, t1);
+            break;
+        case INDEX_op_movi_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_i32(&tb_ptr);
+            tci_write_reg32(t0, t1);
+            break;
+
+            /* Load/store operations (32 bit). */
+
+        case INDEX_op_ld8u_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r(&tb_ptr);
+            t2 = tci_read_i32(&tb_ptr);
+            tci_write_reg8(t0, *(uint8_t *)(t1 + t2));
+            break;
+        case INDEX_op_ld8s_i32:
+        case INDEX_op_ld16u_i32:
+            TODO();
+            break;
+        case INDEX_op_ld16s_i32:
+            TODO();
+            break;
+        case INDEX_op_ld_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r(&tb_ptr);
+            t2 = tci_read_i32(&tb_ptr);
+            tci_write_reg32(t0, *(uint32_t *)(t1 + t2));
+            break;
+        case INDEX_op_st8_i32:
+            t0 = tci_read_r8(&tb_ptr);
+            t1 = tci_read_r(&tb_ptr);
+            t2 = tci_read_i32(&tb_ptr);
+            *(uint8_t *)(t1 + t2) = t0;
+            break;
+        case INDEX_op_st16_i32:
+            t0 = tci_read_r16(&tb_ptr);
+            t1 = tci_read_r(&tb_ptr);
+            t2 = tci_read_i32(&tb_ptr);
+            *(uint16_t *)(t1 + t2) = t0;
+            break;
+        case INDEX_op_st_i32:
+            t0 = tci_read_r32(&tb_ptr);
+            t1 = tci_read_r(&tb_ptr);
+            t2 = tci_read_i32(&tb_ptr);
+            *(uint32_t *)(t1 + t2) = t0;
+            break;
+
+            /* Arithmetic operations (32 bit). */
+
+        case INDEX_op_add_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri32(&tb_ptr);
+            t2 = tci_read_ri32(&tb_ptr);
+            tci_write_reg32(t0, t1 + t2);
+            break;
+        case INDEX_op_sub_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri32(&tb_ptr);
+            t2 = tci_read_ri32(&tb_ptr);
+            tci_write_reg32(t0, t1 - t2);
+            break;
+        case INDEX_op_mul_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri32(&tb_ptr);
+            t2 = tci_read_ri32(&tb_ptr);
+            tci_write_reg32(t0, t1 * t2);
+            break;
+#if TCG_TARGET_HAS_div_i32
+        case INDEX_op_div_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri32(&tb_ptr);
+            t2 = tci_read_ri32(&tb_ptr);
+            tci_write_reg32(t0, (int32_t)t1 / (int32_t)t2);
+            break;
+        case INDEX_op_divu_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri32(&tb_ptr);
+            t2 = tci_read_ri32(&tb_ptr);
+            tci_write_reg32(t0, t1 / t2);
+            break;
+        case INDEX_op_rem_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri32(&tb_ptr);
+            t2 = tci_read_ri32(&tb_ptr);
+            tci_write_reg32(t0, (int32_t)t1 % (int32_t)t2);
+            break;
+        case INDEX_op_remu_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri32(&tb_ptr);
+            t2 = tci_read_ri32(&tb_ptr);
+            tci_write_reg32(t0, t1 % t2);
+            break;
+#elif TCG_TARGET_HAS_div2_i32
+        case INDEX_op_div2_i32:
+        case INDEX_op_divu2_i32:
+            TODO();
+            break;
+#endif
+        case INDEX_op_and_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri32(&tb_ptr);
+            t2 = tci_read_ri32(&tb_ptr);
+            tci_write_reg32(t0, t1 & t2);
+            break;
+        case INDEX_op_or_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri32(&tb_ptr);
+            t2 = tci_read_ri32(&tb_ptr);
+            tci_write_reg32(t0, t1 | t2);
+            break;
+        case INDEX_op_xor_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri32(&tb_ptr);
+            t2 = tci_read_ri32(&tb_ptr);
+            tci_write_reg32(t0, t1 ^ t2);
+            break;
+
+            /* Shift/rotate operations (32 bit). */
+
+        case INDEX_op_shl_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri32(&tb_ptr);
+            t2 = tci_read_ri32(&tb_ptr);
+            tci_write_reg32(t0, t1 << t2);
+            break;
+        case INDEX_op_shr_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri32(&tb_ptr);
+            t2 = tci_read_ri32(&tb_ptr);
+            tci_write_reg32(t0, t1 >> t2);
+            break;
+        case INDEX_op_sar_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri32(&tb_ptr);
+            t2 = tci_read_ri32(&tb_ptr);
+            tci_write_reg32(t0, ((int32_t)t1 >> t2));
+            break;
+#if TCG_TARGET_HAS_rot_i32
+        case INDEX_op_rotl_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri32(&tb_ptr);
+            t2 = tci_read_ri32(&tb_ptr);
+            tci_write_reg32(t0, (t1 << t2) | (t1 >> (32 - t2)));
+            break;
+        case INDEX_op_rotr_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri32(&tb_ptr);
+            t2 = tci_read_ri32(&tb_ptr);
+            tci_write_reg32(t0, (t1 >> t2) | (t1 << (32 - t2)));
+            break;
+#endif
+        case INDEX_op_brcond_i32:
+            t0 = tci_read_r32(&tb_ptr);
+            t1 = tci_read_ri32(&tb_ptr);
+            condition = *tb_ptr++;
+            label = tci_read_label(&tb_ptr);
+            if (tci_compare32(t0, t1, condition)) {
+                assert(tb_ptr == old_code_ptr + op_size);
+                tb_ptr = (uint8_t *)label;
+                continue;
+            }
+            break;
+#if TCG_TARGET_REG_BITS == 32
+        case INDEX_op_add2_i32:
+            t0 = *tb_ptr++;
+            t1 = *tb_ptr++;
+            tmp64 = tci_read_r64(&tb_ptr);
+            tmp64 += tci_read_r64(&tb_ptr);
+            tci_write_reg64(t1, t0, tmp64);
+            break;
+        case INDEX_op_sub2_i32:
+            t0 = *tb_ptr++;
+            t1 = *tb_ptr++;
+            tmp64 = tci_read_r64(&tb_ptr);
+            tmp64 -= tci_read_r64(&tb_ptr);
+            tci_write_reg64(t1, t0, tmp64);
+            break;
+        case INDEX_op_brcond2_i32:
+            tmp64 = tci_read_r64(&tb_ptr);
+            v64 = tci_read_ri64(&tb_ptr);
+            condition = *tb_ptr++;
+            label = tci_read_label(&tb_ptr);
+            if (tci_compare64(tmp64, v64, condition)) {
+                assert(tb_ptr == old_code_ptr + op_size);
+                tb_ptr = (uint8_t *)label;
+                continue;
+            }
+            break;
+        case INDEX_op_mulu2_i32:
+            t0 = *tb_ptr++;
+            t1 = *tb_ptr++;
+            t2 = tci_read_r32(&tb_ptr);
+            tmp64 = tci_read_r32(&tb_ptr);
+            tci_write_reg64(t1, t0, t2 * tmp64);
+            break;
+#endif /* TCG_TARGET_REG_BITS == 32 */
+#if TCG_TARGET_HAS_ext8s_i32
+        case INDEX_op_ext8s_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r8s(&tb_ptr);
+            tci_write_reg32(t0, t1);
+            break;
+#endif
+#if TCG_TARGET_HAS_ext16s_i32
+        case INDEX_op_ext16s_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r16s(&tb_ptr);
+            tci_write_reg32(t0, t1);
+            break;
+#endif
+#if TCG_TARGET_HAS_ext8u_i32
+        case INDEX_op_ext8u_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r8(&tb_ptr);
+            tci_write_reg32(t0, t1);
+            break;
+#endif
+#if TCG_TARGET_HAS_ext16u_i32
+        case INDEX_op_ext16u_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r16(&tb_ptr);
+            tci_write_reg32(t0, t1);
+            break;
+#endif
+#if TCG_TARGET_HAS_bswap16_i32
+        case INDEX_op_bswap16_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r16(&tb_ptr);
+            tci_write_reg32(t0, bswap16(t1));
+            break;
+#endif
+#if TCG_TARGET_HAS_bswap32_i32
+        case INDEX_op_bswap32_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r32(&tb_ptr);
+            tci_write_reg32(t0, bswap32(t1));
+            break;
+#endif
+#if TCG_TARGET_HAS_not_i32
+        case INDEX_op_not_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r32(&tb_ptr);
+            tci_write_reg32(t0, ~t1);
+            break;
+#endif
+#if TCG_TARGET_HAS_neg_i32
+        case INDEX_op_neg_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r32(&tb_ptr);
+            tci_write_reg32(t0, -t1);
+            break;
+#endif
+#if TCG_TARGET_REG_BITS == 64
+        case INDEX_op_mov_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r64(&tb_ptr);
+            tci_write_reg64(t0, t1);
+            break;
+        case INDEX_op_movi_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_i64(&tb_ptr);
+            tci_write_reg64(t0, t1);
+            break;
+
+            /* Load/store operations (64 bit). */
+
+        case INDEX_op_ld8u_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r(&tb_ptr);
+            t2 = tci_read_i32(&tb_ptr);
+            tci_write_reg8(t0, *(uint8_t *)(t1 + t2));
+            break;
+        case INDEX_op_ld8s_i64:
+        case INDEX_op_ld16u_i64:
+        case INDEX_op_ld16s_i64:
+            TODO();
+            break;
+        case INDEX_op_ld32u_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r(&tb_ptr);
+            t2 = tci_read_i32(&tb_ptr);
+            tci_write_reg32(t0, *(uint32_t *)(t1 + t2));
+            break;
+        case INDEX_op_ld32s_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r(&tb_ptr);
+            t2 = tci_read_i32(&tb_ptr);
+            tci_write_reg32s(t0, *(int32_t *)(t1 + t2));
+            break;
+        case INDEX_op_ld_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r(&tb_ptr);
+            t2 = tci_read_i32(&tb_ptr);
+            tci_write_reg64(t0, *(uint64_t *)(t1 + t2));
+            break;
+        case INDEX_op_st8_i64:
+            t0 = tci_read_r8(&tb_ptr);
+            t1 = tci_read_r(&tb_ptr);
+            t2 = tci_read_i32(&tb_ptr);
+            *(uint8_t *)(t1 + t2) = t0;
+            break;
+        case INDEX_op_st16_i64:
+            t0 = tci_read_r16(&tb_ptr);
+            t1 = tci_read_r(&tb_ptr);
+            t2 = tci_read_i32(&tb_ptr);
+            *(uint16_t *)(t1 + t2) = t0;
+            break;
+        case INDEX_op_st32_i64:
+            t0 = tci_read_r32(&tb_ptr);
+            t1 = tci_read_r(&tb_ptr);
+            t2 = tci_read_i32(&tb_ptr);
+            *(uint32_t *)(t1 + t2) = t0;
+            break;
+        case INDEX_op_st_i64:
+            t0 = tci_read_r64(&tb_ptr);
+            t1 = tci_read_r(&tb_ptr);
+            t2 = tci_read_i32(&tb_ptr);
+            *(uint64_t *)(t1 + t2) = t0;
+            break;
+
+            /* Arithmetic operations (64 bit). */
+
+        case INDEX_op_add_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri64(&tb_ptr);
+            t2 = tci_read_ri64(&tb_ptr);
+            tci_write_reg64(t0, t1 + t2);
+            break;
+        case INDEX_op_sub_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri64(&tb_ptr);
+            t2 = tci_read_ri64(&tb_ptr);
+            tci_write_reg64(t0, t1 - t2);
+            break;
+        case INDEX_op_mul_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri64(&tb_ptr);
+            t2 = tci_read_ri64(&tb_ptr);
+            tci_write_reg64(t0, t1 * t2);
+            break;
+#if TCG_TARGET_HAS_div_i64
+        case INDEX_op_div_i64:
+        case INDEX_op_divu_i64:
+        case INDEX_op_rem_i64:
+        case INDEX_op_remu_i64:
+            TODO();
+            break;
+#elif TCG_TARGET_HAS_div2_i64
+        case INDEX_op_div2_i64:
+        case INDEX_op_divu2_i64:
+            TODO();
+            break;
+#endif
+        case INDEX_op_and_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri64(&tb_ptr);
+            t2 = tci_read_ri64(&tb_ptr);
+            tci_write_reg64(t0, t1 & t2);
+            break;
+        case INDEX_op_or_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri64(&tb_ptr);
+            t2 = tci_read_ri64(&tb_ptr);
+            tci_write_reg64(t0, t1 | t2);
+            break;
+        case INDEX_op_xor_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri64(&tb_ptr);
+            t2 = tci_read_ri64(&tb_ptr);
+            tci_write_reg64(t0, t1 ^ t2);
+            break;
+
+            /* Shift/rotate operations (64 bit). */
+
+        case INDEX_op_shl_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri64(&tb_ptr);
+            t2 = tci_read_ri64(&tb_ptr);
+            tci_write_reg64(t0, t1 << t2);
+            break;
+        case INDEX_op_shr_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri64(&tb_ptr);
+            t2 = tci_read_ri64(&tb_ptr);
+            tci_write_reg64(t0, t1 >> t2);
+            break;
+        case INDEX_op_sar_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri64(&tb_ptr);
+            t2 = tci_read_ri64(&tb_ptr);
+            tci_write_reg64(t0, ((int64_t)t1 >> t2));
+            break;
+#if TCG_TARGET_HAS_rot_i64
+        case INDEX_op_rotl_i64:
+        case INDEX_op_rotr_i64:
+            TODO();
+            break;
+#endif
+        case INDEX_op_brcond_i64:
+            t0 = tci_read_r64(&tb_ptr);
+            t1 = tci_read_ri64(&tb_ptr);
+            condition = *tb_ptr++;
+            label = tci_read_label(&tb_ptr);
+            if (tci_compare64(t0, t1, condition)) {
+                assert(tb_ptr == old_code_ptr + op_size);
+                tb_ptr = (uint8_t *)label;
+                continue;
+            }
+            break;
+#if TCG_TARGET_HAS_ext8u_i64
+        case INDEX_op_ext8u_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r8(&tb_ptr);
+            tci_write_reg64(t0, t1);
+            break;
+#endif
+#if TCG_TARGET_HAS_ext8s_i64
+        case INDEX_op_ext8s_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r8s(&tb_ptr);
+            tci_write_reg64(t0, t1);
+            break;
+#endif
+#if TCG_TARGET_HAS_ext16s_i64
+        case INDEX_op_ext16s_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r16s(&tb_ptr);
+            tci_write_reg64(t0, t1);
+            break;
+#endif
+#if TCG_TARGET_HAS_ext16u_i64
+        case INDEX_op_ext16u_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r16(&tb_ptr);
+            tci_write_reg64(t0, t1);
+            break;
+#endif
+#if TCG_TARGET_HAS_ext32s_i64
+        case INDEX_op_ext32s_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r32s(&tb_ptr);
+            tci_write_reg64(t0, t1);
+            break;
+#endif
+#if TCG_TARGET_HAS_ext32u_i64
+        case INDEX_op_ext32u_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r32(&tb_ptr);
+            tci_write_reg64(t0, t1);
+            break;
+#endif
+#if TCG_TARGET_HAS_bswap16_i64
+        case INDEX_op_bswap16_i64:
+            TODO();
+            t0 = *tb_ptr++;
+            t1 = tci_read_r16(&tb_ptr);
+            tci_write_reg64(t0, bswap16(t1));
+            break;
+#endif
+#if TCG_TARGET_HAS_bswap32_i64
+        case INDEX_op_bswap32_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r32(&tb_ptr);
+            tci_write_reg64(t0, bswap32(t1));
+            break;
+#endif
+#if TCG_TARGET_HAS_bswap64_i64
+        case INDEX_op_bswap64_i64:
+            TODO();
+            t0 = *tb_ptr++;
+            t1 = tci_read_r64(&tb_ptr);
+            tci_write_reg64(t0, bswap64(t1));
+            break;
+#endif
+#if TCG_TARGET_HAS_not_i64
+        case INDEX_op_not_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r64(&tb_ptr);
+            tci_write_reg64(t0, ~t1);
+            break;
+#endif
+#if TCG_TARGET_HAS_neg_i64
+        case INDEX_op_neg_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r64(&tb_ptr);
+            tci_write_reg64(t0, -t1);
+            break;
+#endif
+#endif /* TCG_TARGET_REG_BITS == 64 */
+
+            /* QEMU specific operations. */
+
+#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
+        case INDEX_op_debug_insn_start:
+            TODO();
+            break;
+#else
+        case INDEX_op_debug_insn_start:
+            TODO();
+            break;
+#endif
+        case INDEX_op_exit_tb:
+            next_tb = *(uint64_t *)tb_ptr;
+            goto exit;
+            break;
+        case INDEX_op_goto_tb:
+            t0 = tci_read_i32(&tb_ptr);
+            assert(tb_ptr == old_code_ptr + op_size);
+            tb_ptr += (int32_t)t0;
+            continue;
+        case INDEX_op_qemu_ld8u:
+            t0 = *tb_ptr++;
+            taddr = tci_read_ulong(&tb_ptr);
+#ifdef CONFIG_SOFTMMU
+            tmp8 = __ldb_mmu(taddr, tci_read_i(&tb_ptr));
+#else
+            host_addr = (tcg_target_ulong)taddr;
+            assert(taddr == host_addr);
+            tmp8 = *(uint8_t *)(host_addr + GUEST_BASE);
+#endif
+            tci_write_reg8(t0, tmp8);
+            break;
+        case INDEX_op_qemu_ld8s:
+            t0 = *tb_ptr++;
+            taddr = tci_read_ulong(&tb_ptr);
+#ifdef CONFIG_SOFTMMU
+            tmp8 = __ldb_mmu(taddr, tci_read_i(&tb_ptr));
+#else
+            host_addr = (tcg_target_ulong)taddr;
+            assert(taddr == host_addr);
+            tmp8 = *(uint8_t *)(host_addr + GUEST_BASE);
+#endif
+            tci_write_reg8s(t0, tmp8);
+            break;
+        case INDEX_op_qemu_ld16u:
+            t0 = *tb_ptr++;
+            taddr = tci_read_ulong(&tb_ptr);
+#ifdef CONFIG_SOFTMMU
+            tmp16 = __ldw_mmu(taddr, tci_read_i(&tb_ptr));
+#else
+            host_addr = (tcg_target_ulong)taddr;
+            assert(taddr == host_addr);
+            tmp16 = tswap16(*(uint16_t *)(host_addr + GUEST_BASE));
+#endif
+            tci_write_reg16(t0, tmp16);
+            break;
+        case INDEX_op_qemu_ld16s:
+            t0 = *tb_ptr++;
+            taddr = tci_read_ulong(&tb_ptr);
+#ifdef CONFIG_SOFTMMU
+            tmp16 = __ldw_mmu(taddr, tci_read_i(&tb_ptr));
+#else
+            host_addr = (tcg_target_ulong)taddr;
+            assert(taddr == host_addr);
+            tmp16 = tswap16(*(uint16_t *)(host_addr + GUEST_BASE));
+#endif
+            tci_write_reg16s(t0, tmp16);
+            break;
+#if TCG_TARGET_REG_BITS == 64
+        case INDEX_op_qemu_ld32u:
+            t0 = *tb_ptr++;
+            taddr = tci_read_ulong(&tb_ptr);
+#ifdef CONFIG_SOFTMMU
+            tmp32 = __ldl_mmu(taddr, tci_read_i(&tb_ptr));
+#else
+            host_addr = (tcg_target_ulong)taddr;
+            assert(taddr == host_addr);
+            tmp32 = tswap32(*(uint32_t *)(host_addr + GUEST_BASE));
+#endif
+            tci_write_reg32(t0, tmp32);
+            break;
+        case INDEX_op_qemu_ld32s:
+            t0 = *tb_ptr++;
+            taddr = tci_read_ulong(&tb_ptr);
+#ifdef CONFIG_SOFTMMU
+            tmp32 = __ldl_mmu(taddr, tci_read_i(&tb_ptr));
+#else
+            host_addr = (tcg_target_ulong)taddr;
+            assert(taddr == host_addr);
+            tmp32 = tswap32(*(uint32_t *)(host_addr + GUEST_BASE));
+#endif
+            tci_write_reg32s(t0, tmp32);
+            break;
+#endif /* TCG_TARGET_REG_BITS == 64 */
+        case INDEX_op_qemu_ld32:
+            t0 = *tb_ptr++;
+            taddr = tci_read_ulong(&tb_ptr);
+#ifdef CONFIG_SOFTMMU
+            tmp32 = __ldl_mmu(taddr, tci_read_i(&tb_ptr));
+#else
+            host_addr = (tcg_target_ulong)taddr;
+            assert(taddr == host_addr);
+            tmp32 = tswap32(*(uint32_t *)(host_addr + GUEST_BASE));
+#endif
+            tci_write_reg32(t0, tmp32);
+            break;
+        case INDEX_op_qemu_ld64:
+            t0 = *tb_ptr++;
+#if TCG_TARGET_REG_BITS == 32
+            t1 = *tb_ptr++;
+#endif
+            taddr = tci_read_ulong(&tb_ptr);
+#ifdef CONFIG_SOFTMMU
+            tmp64 = __ldq_mmu(taddr, tci_read_i(&tb_ptr));
+#else
+            host_addr = (tcg_target_ulong)taddr;
+            assert(taddr == host_addr);
+            tmp64 = tswap64(*(uint64_t *)(host_addr + GUEST_BASE));
+#endif
+            tci_write_reg(t0, tmp64);
+#if TCG_TARGET_REG_BITS == 32
+            tci_write_reg(t1, tmp64 >> 32);
+#endif
+            break;
+        case INDEX_op_qemu_st8:
+            t0 = tci_read_r8(&tb_ptr);
+            taddr = tci_read_ulong(&tb_ptr);
+#ifdef CONFIG_SOFTMMU
+            t2 = tci_read_i(&tb_ptr);
+            __stb_mmu(taddr, t0, t2);
+#else
+            host_addr = (tcg_target_ulong)taddr;
+            assert(taddr == host_addr);
+            *(uint8_t *)(host_addr + GUEST_BASE) = t0;
+#endif
+            break;
+        case INDEX_op_qemu_st16:
+            t0 = tci_read_r16(&tb_ptr);
+            taddr = tci_read_ulong(&tb_ptr);
+#ifdef CONFIG_SOFTMMU
+            t2 = tci_read_i(&tb_ptr);
+            __stw_mmu(taddr, t0, t2);
+#else
+            host_addr = (tcg_target_ulong)taddr;
+            assert(taddr == host_addr);
+            *(uint16_t *)(host_addr + GUEST_BASE) = tswap16(t0);
+#endif
+            break;
+        case INDEX_op_qemu_st32:
+            t0 = tci_read_r32(&tb_ptr);
+            taddr = tci_read_ulong(&tb_ptr);
+#ifdef CONFIG_SOFTMMU
+            t2 = tci_read_i(&tb_ptr);
+            __stl_mmu(taddr, t0, t2);
+#else
+            host_addr = (tcg_target_ulong)taddr;
+            assert(taddr == host_addr);
+            *(uint32_t *)(host_addr + GUEST_BASE) = tswap32(t0);
+#endif
+            break;
+        case INDEX_op_qemu_st64:
+            tmp64 = tci_read_r64(&tb_ptr);
+            taddr = tci_read_ulong(&tb_ptr);
+#ifdef CONFIG_SOFTMMU
+            t2 = tci_read_i(&tb_ptr);
+            __stq_mmu(taddr, tmp64, t2);
+#else
+            host_addr = (tcg_target_ulong)taddr;
+            assert(taddr == host_addr);
+            *(uint64_t *)(host_addr + GUEST_BASE) = tswap64(tmp64);
+#endif
+            break;
+        default:
+            TODO();
+            break;
+        }
+        assert(tb_ptr == old_code_ptr + op_size);
+    }
+exit:
+    return next_tb;
+}
commit 7316329aa54bb4e404dc92b8bf481d0c43c82c76
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Oct 5 20:03:02 2011 +0200

    tcg: Add bytecode generator for tcg interpreter
    
    Unlike other tcg target code generators, this one does not generate
    machine code for some cpu. It generates machine independent bytecode
    which is interpreted later.
    
    This allows running QEMU on any host.
    
    Interpreted bytecode is slower than direct execution of generated
    machine code.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/dyngen-exec.h b/dyngen-exec.h
index fbde29e..3544372 100644
--- a/dyngen-exec.h
+++ b/dyngen-exec.h
@@ -19,7 +19,12 @@
 #if !defined(__DYNGEN_EXEC_H__)
 #define __DYNGEN_EXEC_H__
 
-#if defined(__i386__)
+#if defined(CONFIG_TCG_INTERPRETER)
+/* The TCG interpreter does not need a special register AREG0,
+ * but it is possible to use one by defining AREG0.
+ * On i386, register edi seems to work. */
+/* Run without special register AREG0 or use a value defined elsewhere. */
+#elif defined(__i386__)
 #define AREG0 "ebp"
 #elif defined(__x86_64__)
 #define AREG0 "r14"
@@ -55,6 +60,11 @@
 #error unsupported CPU
 #endif
 
+#if defined(AREG0)
 register CPUState *env asm(AREG0);
+#else
+/* TODO: Try env = cpu_single_env. */
+extern CPUState *env;
+#endif
 
 #endif /* !defined(__DYNGEN_EXEC_H__) */
diff --git a/exec-all.h b/exec-all.h
index 85a37bf..c211242 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -122,6 +122,8 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
 
 #if defined(_ARCH_PPC) || defined(__x86_64__) || defined(__arm__) || defined(__i386__)
 #define USE_DIRECT_JUMP
+#elif defined(CONFIG_TCG_INTERPRETER)
+#define USE_DIRECT_JUMP
 #endif
 
 struct TranslationBlock {
@@ -189,7 +191,14 @@ extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
 
 #if defined(USE_DIRECT_JUMP)
 
-#if defined(_ARCH_PPC)
+#if defined(CONFIG_TCG_INTERPRETER)
+static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
+{
+    /* patch the branch destination */
+    *(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
+    /* no need to flush icache explicitly */
+}
+#elif defined(_ARCH_PPC)
 void ppc_tb_set_jmp_target(unsigned long jmp_addr, unsigned long addr);
 #define tb_set_jmp_target1 ppc_tb_set_jmp_target
 #elif defined(__i386__) || defined(__x86_64__)
@@ -223,6 +232,8 @@ static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr
     __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
 #endif
 }
+#else
+#error tb_set_jmp_target1 is missing
 #endif
 
 static inline void tb_set_jmp_target(TranslationBlock *tb,
@@ -269,7 +280,14 @@ extern int tb_invalidated_flag;
 
 /* The return address may point to the start of the next instruction.
    Subtracting one gets us the call instruction itself.  */
-#if defined(__s390__) && !defined(__s390x__)
+#if defined(CONFIG_TCG_INTERPRETER)
+/* Alpha and SH4 user mode emulations and Softmmu call GETPC().
+   For all others, GETPC remains undefined (which makes TCI a little faster. */
+# if defined(CONFIG_SOFTMMU) || defined(TARGET_ALPHA) || defined(TARGET_SH4)
+extern void *tci_tb_ptr;
+#  define GETPC() tci_tb_ptr
+# endif
+#elif defined(__s390__) && !defined(__s390x__)
 # define GETPC() ((void*)(((unsigned long)__builtin_return_address(0) & 0x7fffffffUL) - 1))
 #elif defined(__arm__)
 /* Thumb return addresses have the low bit set, so we need to subtract two.
diff --git a/tcg/tci/README b/tcg/tci/README
new file mode 100644
index 0000000..6ac1ac9
--- /dev/null
+++ b/tcg/tci/README
@@ -0,0 +1,130 @@
+TCG Interpreter (TCI) - Copyright (c) 2011 Stefan Weil.
+
+This file is released under the BSD license.
+
+1) Introduction
+
+TCG (Tiny Code Generator) is a code generator which translates
+code fragments ("basic blocks") from target code (any of the
+targets supported by QEMU) to a code representation which
+can be run on a host.
+
+QEMU can create native code for some hosts (arm, hppa, i386, ia64, ppc, ppc64,
+s390, sparc, x86_64). For others, unofficial host support was written.
+
+By adding a code generator for a virtual machine and using an
+interpreter for the generated bytecode, it is possible to
+support (almost) any host.
+
+This is what TCI (Tiny Code Interpreter) does.
+
+2) Implementation
+
+Like each TCG host frontend, TCI implements the code generator in
+tcg-target.c, tcg-target.h. Both files are in directory tcg/tci.
+
+The additional file tcg/tci.c adds the interpreter.
+
+The bytecode consists of opcodes (same numeric values as those used by
+TCG), command length and arguments of variable size and number.
+
+3) Usage
+
+For hosts without native TCG, the interpreter TCI must be enabled by
+
+        configure --enable-tcg-interpreter
+
+If configure is called without --enable-tcg-interpreter, it will
+suggest using this option. Setting it automatically would need
+additional code in configure which must be fixed when new native TCG
+implementations are added.
+
+System emulation should work on any 32 or 64 bit host.
+User mode emulation might work. Maybe a new linker script (*.ld)
+is needed. Byte order might be wrong (on big endian hosts)
+and need fixes in configure.
+
+For hosts with native TCG, the interpreter TCI can be enabled by
+
+        configure --enable-tcg-interpreter
+
+The only difference from running QEMU with TCI to running without TCI
+should be speed. Especially during development of TCI, it was very
+useful to compare runs with and without TCI. Create /tmp/qemu.log by
+
+        qemu-system-i386 -d in_asm,op_opt,cpu -singlestep
+
+once with interpreter and once without interpreter and compare the resulting
+qemu.log files. This is also useful to see the effects of additional
+registers or additional opcodes (it is easy to modify the virtual machine).
+It can also be used to verify native TCGs.
+
+Hosts with native TCG can also enable TCI by claiming to be unsupported:
+
+        configure --cpu=unknown --enable-tcg-interpreter
+
+configure then no longer uses the native linker script (*.ld) for
+user mode emulation.
+
+
+4) Status
+
+TCI needs special implementation for 32 and 64 bit host, 32 and 64 bit target,
+host and target with same or different endianness.
+
+            | host (le)                     host (be)
+            | 32             64             32             64
+------------+------------------------------------------------------------
+target (le) | s0, u0         s1, u1         s?, u?         s?, u?
+32 bit      |
+            |
+target (le) | sc, uc         s1, u1         s?, u?         s?, u?
+64 bit      |
+            |
+target (be) | sc, u0         sc, uc         s?, u?         s?, u?
+32 bit      |
+            |
+target (be) | sc, uc         sc, uc         s?, u?         s?, u?
+64 bit      |
+            |
+
+System emulation
+s? = untested
+sc = compiles
+s0 = bios works
+s1 = grub works
+s2 = Linux boots
+
+Linux user mode emulation
+u? = untested
+uc = compiles
+u0 = static hello works
+u1 = linux-user-test works
+
+5) Todo list
+
+* TCI is not widely tested. It was written and tested on a x86_64 host
+  running i386 and x86_64 system emulation and Linux user mode.
+  A cross compiled QEMU for i386 host also works with the same basic tests.
+  A cross compiled QEMU for mipsel host works, too. It is terribly slow
+  because I run it in a mips malta emulation, so it is an interpreted
+  emulation in an emulation.
+  A cross compiled QEMU for arm host works (tested with pc bios).
+  A cross compiled QEMU for ppc host works at least partially:
+  i386-linux-user/qemu-i386 can run a simple hello-world program
+  (tested in a ppc emulation).
+
+* Some TCG opcodes are either missing in the code generator and/or
+  in the interpreter. These opcodes raise a runtime exception, so it is
+  possible to see where code must be added.
+
+* The pseudo code is not optimized and still ugly. For hosts with special
+  alignment requirements, it needs some fixes (maybe aligned bytecode
+  would also improve speed for hosts which support byte alignment).
+
+* A better disassembler for the pseudo code would be nice (a very primitive
+  disassembler is included in tcg-target.c).
+
+* It might be useful to have a runtime option which selects the native TCG
+  or TCI, so QEMU would have to include two TCGs. Today, selecting TCI
+  is a configure option, so you need two compilations of QEMU.
diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c
new file mode 100644
index 0000000..e373e2a
--- /dev/null
+++ b/tcg/tci/tcg-target.c
@@ -0,0 +1,906 @@
+/*
+ * Tiny Code Generator for QEMU
+ *
+ * Copyright (c) 2009, 2011 Stefan Weil
+ *
+ * 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.
+ */
+
+/* TODO list:
+ * - See TODO comments in code.
+ */
+
+/* Marker for missing code. */
+#define TODO() \
+    do { \
+        fprintf(stderr, "TODO %s:%u: %s()\n", \
+                __FILE__, __LINE__, __func__); \
+        tcg_abort(); \
+    } while (0)
+
+/* Single bit n. */
+#define BIT(n) (1 << (n))
+
+/* Bitfield n...m (in 32 bit value). */
+#define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m)
+
+/* Used for function call generation. */
+#define TCG_REG_CALL_STACK              TCG_REG_R4
+#define TCG_TARGET_STACK_ALIGN          16
+#define TCG_TARGET_CALL_STACK_OFFSET    0
+
+/* TODO: documentation. */
+static uint8_t *tb_ret_addr;
+
+/* Macros used in tcg_target_op_defs. */
+#define R       "r"
+#define RI      "ri"
+#if TCG_TARGET_REG_BITS == 32
+# define R64    "r", "r"
+#else
+# define R64    "r"
+#endif
+#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
+# define L      "L", "L"
+# define S      "S", "S"
+#else
+# define L      "L"
+# define S      "S"
+#endif
+
+/* TODO: documentation. */
+static const TCGTargetOpDef tcg_target_op_defs[] = {
+    { INDEX_op_exit_tb, { NULL } },
+    { INDEX_op_goto_tb, { NULL } },
+    { INDEX_op_call, { RI } },
+    { INDEX_op_jmp, { RI } },
+    { INDEX_op_br, { NULL } },
+
+    { INDEX_op_mov_i32, { R, R } },
+    { INDEX_op_movi_i32, { R } },
+
+    { INDEX_op_ld8u_i32, { R, R } },
+    { INDEX_op_ld8s_i32, { R, R } },
+    { INDEX_op_ld16u_i32, { R, R } },
+    { INDEX_op_ld16s_i32, { R, R } },
+    { INDEX_op_ld_i32, { R, R } },
+    { INDEX_op_st8_i32, { R, R } },
+    { INDEX_op_st16_i32, { R, R } },
+    { INDEX_op_st_i32, { R, R } },
+
+    { INDEX_op_add_i32, { R, RI, RI } },
+    { INDEX_op_sub_i32, { R, RI, RI } },
+    { INDEX_op_mul_i32, { R, RI, RI } },
+#if TCG_TARGET_HAS_div_i32
+    { INDEX_op_div_i32, { R, R, R } },
+    { INDEX_op_divu_i32, { R, R, R } },
+    { INDEX_op_rem_i32, { R, R, R } },
+    { INDEX_op_remu_i32, { R, R, R } },
+#elif TCG_TARGET_HAS_div2_i32
+    { INDEX_op_div2_i32, { R, R, "0", "1", R } },
+    { INDEX_op_divu2_i32, { R, R, "0", "1", R } },
+#endif
+    /* TODO: Does R, RI, RI result in faster code than R, R, RI?
+       If both operands are constants, we can optimize. */
+    { INDEX_op_and_i32, { R, RI, RI } },
+#if TCG_TARGET_HAS_andc_i32
+    { INDEX_op_andc_i32, { R, RI, RI } },
+#endif
+#if TCG_TARGET_HAS_eqv_i32
+    { INDEX_op_eqv_i32, { R, RI, RI } },
+#endif
+#if TCG_TARGET_HAS_nand_i32
+    { INDEX_op_nand_i32, { R, RI, RI } },
+#endif
+#if TCG_TARGET_HAS_nor_i32
+    { INDEX_op_nor_i32, { R, RI, RI } },
+#endif
+    { INDEX_op_or_i32, { R, RI, RI } },
+#if TCG_TARGET_HAS_orc_i32
+    { INDEX_op_orc_i32, { R, RI, RI } },
+#endif
+    { INDEX_op_xor_i32, { R, RI, RI } },
+    { INDEX_op_shl_i32, { R, RI, RI } },
+    { INDEX_op_shr_i32, { R, RI, RI } },
+    { INDEX_op_sar_i32, { R, RI, RI } },
+#if TCG_TARGET_HAS_rot_i32
+    { INDEX_op_rotl_i32, { R, RI, RI } },
+    { INDEX_op_rotr_i32, { R, RI, RI } },
+#endif
+
+    { INDEX_op_brcond_i32, { R, RI } },
+
+    { INDEX_op_setcond_i32, { R, R, RI } },
+#if TCG_TARGET_REG_BITS == 64
+    { INDEX_op_setcond_i64, { R, R, RI } },
+#endif /* TCG_TARGET_REG_BITS == 64 */
+
+#if TCG_TARGET_REG_BITS == 32
+    /* TODO: Support R, R, R, R, RI, RI? Will it be faster? */
+    { INDEX_op_add2_i32, { R, R, R, R, R, R } },
+    { INDEX_op_sub2_i32, { R, R, R, R, R, R } },
+    { INDEX_op_brcond2_i32, { R, R, RI, RI } },
+    { INDEX_op_mulu2_i32, { R, R, R, R } },
+    { INDEX_op_setcond2_i32, { R, R, R, RI, RI } },
+#endif
+
+#if TCG_TARGET_HAS_not_i32
+    { INDEX_op_not_i32, { R, R } },
+#endif
+#if TCG_TARGET_HAS_neg_i32
+    { INDEX_op_neg_i32, { R, R } },
+#endif
+
+#if TCG_TARGET_REG_BITS == 64
+    { INDEX_op_mov_i64, { R, R } },
+    { INDEX_op_movi_i64, { R } },
+
+    { INDEX_op_ld8u_i64, { R, R } },
+    { INDEX_op_ld8s_i64, { R, R } },
+    { INDEX_op_ld16u_i64, { R, R } },
+    { INDEX_op_ld16s_i64, { R, R } },
+    { INDEX_op_ld32u_i64, { R, R } },
+    { INDEX_op_ld32s_i64, { R, R } },
+    { INDEX_op_ld_i64, { R, R } },
+
+    { INDEX_op_st8_i64, { R, R } },
+    { INDEX_op_st16_i64, { R, R } },
+    { INDEX_op_st32_i64, { R, R } },
+    { INDEX_op_st_i64, { R, R } },
+
+    { INDEX_op_add_i64, { R, RI, RI } },
+    { INDEX_op_sub_i64, { R, RI, RI } },
+    { INDEX_op_mul_i64, { R, RI, RI } },
+#if TCG_TARGET_HAS_div_i64
+    { INDEX_op_div_i64, { R, R, R } },
+    { INDEX_op_divu_i64, { R, R, R } },
+    { INDEX_op_rem_i64, { R, R, R } },
+    { INDEX_op_remu_i64, { R, R, R } },
+#elif TCG_TARGET_HAS_div2_i64
+    { INDEX_op_div2_i64, { R, R, "0", "1", R } },
+    { INDEX_op_divu2_i64, { R, R, "0", "1", R } },
+#endif
+    { INDEX_op_and_i64, { R, RI, RI } },
+#if TCG_TARGET_HAS_andc_i64
+    { INDEX_op_andc_i64, { R, RI, RI } },
+#endif
+#if TCG_TARGET_HAS_eqv_i64
+    { INDEX_op_eqv_i64, { R, RI, RI } },
+#endif
+#if TCG_TARGET_HAS_nand_i64
+    { INDEX_op_nand_i64, { R, RI, RI } },
+#endif
+#if TCG_TARGET_HAS_nor_i64
+    { INDEX_op_nor_i64, { R, RI, RI } },
+#endif
+    { INDEX_op_or_i64, { R, RI, RI } },
+#if TCG_TARGET_HAS_orc_i64
+    { INDEX_op_orc_i64, { R, RI, RI } },
+#endif
+    { INDEX_op_xor_i64, { R, RI, RI } },
+    { INDEX_op_shl_i64, { R, RI, RI } },
+    { INDEX_op_shr_i64, { R, RI, RI } },
+    { INDEX_op_sar_i64, { R, RI, RI } },
+#if TCG_TARGET_HAS_rot_i64
+    { INDEX_op_rotl_i64, { R, RI, RI } },
+    { INDEX_op_rotr_i64, { R, RI, RI } },
+#endif
+    { INDEX_op_brcond_i64, { R, RI } },
+
+#if TCG_TARGET_HAS_ext8s_i64
+    { INDEX_op_ext8s_i64, { R, R } },
+#endif
+#if TCG_TARGET_HAS_ext16s_i64
+    { INDEX_op_ext16s_i64, { R, R } },
+#endif
+#if TCG_TARGET_HAS_ext32s_i64
+    { INDEX_op_ext32s_i64, { R, R } },
+#endif
+#if TCG_TARGET_HAS_ext8u_i64
+    { INDEX_op_ext8u_i64, { R, R } },
+#endif
+#if TCG_TARGET_HAS_ext16u_i64
+    { INDEX_op_ext16u_i64, { R, R } },
+#endif
+#if TCG_TARGET_HAS_ext32u_i64
+    { INDEX_op_ext32u_i64, { R, R } },
+#endif
+#if TCG_TARGET_HAS_bswap16_i64
+    { INDEX_op_bswap16_i64, { R, R } },
+#endif
+#if TCG_TARGET_HAS_bswap32_i64
+    { INDEX_op_bswap32_i64, { R, R } },
+#endif
+#if TCG_TARGET_HAS_bswap64_i64
+    { INDEX_op_bswap64_i64, { R, R } },
+#endif
+#if TCG_TARGET_HAS_not_i64
+    { INDEX_op_not_i64, { R, R } },
+#endif
+#if TCG_TARGET_HAS_neg_i64
+    { INDEX_op_neg_i64, { R, R } },
+#endif
+#endif /* TCG_TARGET_REG_BITS == 64 */
+
+    { INDEX_op_qemu_ld8u, { R, L } },
+    { INDEX_op_qemu_ld8s, { R, L } },
+    { INDEX_op_qemu_ld16u, { R, L } },
+    { INDEX_op_qemu_ld16s, { R, L } },
+    { INDEX_op_qemu_ld32, { R, L } },
+#if TCG_TARGET_REG_BITS == 64
+    { INDEX_op_qemu_ld32u, { R, L } },
+    { INDEX_op_qemu_ld32s, { R, L } },
+#endif
+    { INDEX_op_qemu_ld64, { R64, L } },
+
+    { INDEX_op_qemu_st8, { R, S } },
+    { INDEX_op_qemu_st16, { R, S } },
+    { INDEX_op_qemu_st32, { R, S } },
+    { INDEX_op_qemu_st64, { R64, S } },
+
+#if TCG_TARGET_HAS_ext8s_i32
+    { INDEX_op_ext8s_i32, { R, R } },
+#endif
+#if TCG_TARGET_HAS_ext16s_i32
+    { INDEX_op_ext16s_i32, { R, R } },
+#endif
+#if TCG_TARGET_HAS_ext8u_i32
+    { INDEX_op_ext8u_i32, { R, R } },
+#endif
+#if TCG_TARGET_HAS_ext16u_i32
+    { INDEX_op_ext16u_i32, { R, R } },
+#endif
+
+#if TCG_TARGET_HAS_bswap16_i32
+    { INDEX_op_bswap16_i32, { R, R } },
+#endif
+#if TCG_TARGET_HAS_bswap32_i32
+    { INDEX_op_bswap32_i32, { R, R } },
+#endif
+
+    { -1 },
+};
+
+static const int tcg_target_reg_alloc_order[] = {
+    TCG_REG_R0,
+    TCG_REG_R1,
+    TCG_REG_R2,
+    TCG_REG_R3,
+#if 0 /* used for TCG_REG_CALL_STACK */
+    TCG_REG_R4,
+#endif
+    TCG_REG_R5,
+    TCG_REG_R6,
+    TCG_REG_R7,
+#if TCG_TARGET_NB_REGS >= 16
+    TCG_REG_R8,
+    TCG_REG_R9,
+    TCG_REG_R10,
+    TCG_REG_R11,
+    TCG_REG_R12,
+    TCG_REG_R13,
+    TCG_REG_R14,
+    TCG_REG_R15,
+#endif
+};
+
+#if MAX_OPC_PARAM_IARGS != 4
+# error Fix needed, number of supported input arguments changed!
+#endif
+
+static const int tcg_target_call_iarg_regs[] = {
+    TCG_REG_R0,
+    TCG_REG_R1,
+    TCG_REG_R2,
+    TCG_REG_R3,
+#if TCG_TARGET_REG_BITS == 32
+    /* 32 bit hosts need 2 * MAX_OPC_PARAM_IARGS registers. */
+#if 0 /* used for TCG_REG_CALL_STACK */
+    TCG_REG_R4,
+#endif
+    TCG_REG_R5,
+    TCG_REG_R6,
+    TCG_REG_R7,
+#if TCG_TARGET_NB_REGS >= 16
+    TCG_REG_R8,
+#else
+# error Too few input registers available
+#endif
+#endif
+};
+
+static const int tcg_target_call_oarg_regs[] = {
+    TCG_REG_R0,
+#if TCG_TARGET_REG_BITS == 32
+    TCG_REG_R1
+#endif
+};
+
+#ifndef NDEBUG
+static const char *const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
+    "r00",
+    "r01",
+    "r02",
+    "r03",
+    "r04",
+    "r05",
+    "r06",
+    "r07",
+#if TCG_TARGET_NB_REGS >= 16
+    "r08",
+    "r09",
+    "r10",
+    "r11",
+    "r12",
+    "r13",
+    "r14",
+    "r15",
+#if TCG_TARGET_NB_REGS >= 32
+    "r16",
+    "r17",
+    "r18",
+    "r19",
+    "r20",
+    "r21",
+    "r22",
+    "r23",
+    "r24",
+    "r25",
+    "r26",
+    "r27",
+    "r28",
+    "r29",
+    "r30",
+    "r31"
+#endif
+#endif
+};
+#endif
+
+static void flush_icache_range(unsigned long start, unsigned long stop)
+{
+}
+
+static void patch_reloc(uint8_t *code_ptr, int type,
+                        tcg_target_long value, tcg_target_long addend)
+{
+    /* tcg_out_reloc always uses the same type, addend. */
+    assert(type == sizeof(tcg_target_long));
+    assert(addend == 0);
+    assert(value != 0);
+    *(tcg_target_long *)code_ptr = value;
+}
+
+/* Parse target specific constraints. */
+static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
+{
+    const char *ct_str = *pct_str;
+    switch (ct_str[0]) {
+    case 'r':
+    case 'L':                   /* qemu_ld constraint */
+    case 'S':                   /* qemu_st constraint */
+        ct->ct |= TCG_CT_REG;
+        tcg_regset_set32(ct->u.regs, 0, BIT(TCG_TARGET_NB_REGS) - 1);
+        break;
+    default:
+        return -1;
+    }
+    ct_str++;
+    *pct_str = ct_str;
+    return 0;
+}
+
+#if defined(CONFIG_DEBUG_TCG_INTERPRETER)
+/* Show current bytecode. Used by tcg interpreter. */
+void tci_disas(uint8_t opc)
+{
+    const TCGOpDef *def = &tcg_op_defs[opc];
+    fprintf(stderr, "TCG %s %u, %u, %u\n",
+            def->name, def->nb_oargs, def->nb_iargs, def->nb_cargs);
+}
+#endif
+
+/* Write value (native size). */
+static void tcg_out_i(TCGContext *s, tcg_target_ulong v)
+{
+    *(tcg_target_ulong *)s->code_ptr = v;
+    s->code_ptr += sizeof(tcg_target_ulong);
+}
+
+/* Write 64 bit value. */
+static void tcg_out64(TCGContext *s, uint64_t v)
+{
+    *(uint64_t *)s->code_ptr = v;
+    s->code_ptr += sizeof(v);
+}
+
+/* Write opcode. */
+static void tcg_out_op_t(TCGContext *s, TCGOpcode op)
+{
+    tcg_out8(s, op);
+    tcg_out8(s, 0);
+}
+
+/* Write register. */
+static void tcg_out_r(TCGContext *s, TCGArg t0)
+{
+    assert(t0 < TCG_TARGET_NB_REGS);
+    tcg_out8(s, t0);
+}
+
+/* Write register or constant (native size). */
+static void tcg_out_ri(TCGContext *s, int const_arg, TCGArg arg)
+{
+    if (const_arg) {
+        assert(const_arg == 1);
+        tcg_out8(s, TCG_CONST);
+        tcg_out_i(s, arg);
+    } else {
+        tcg_out_r(s, arg);
+    }
+}
+
+/* Write register or constant (32 bit). */
+static void tcg_out_ri32(TCGContext *s, int const_arg, TCGArg arg)
+{
+    if (const_arg) {
+        assert(const_arg == 1);
+        tcg_out8(s, TCG_CONST);
+        tcg_out32(s, arg);
+    } else {
+        tcg_out_r(s, arg);
+    }
+}
+
+#if TCG_TARGET_REG_BITS == 64
+/* Write register or constant (64 bit). */
+static void tcg_out_ri64(TCGContext *s, int const_arg, TCGArg arg)
+{
+    if (const_arg) {
+        assert(const_arg == 1);
+        tcg_out8(s, TCG_CONST);
+        tcg_out64(s, arg);
+    } else {
+        tcg_out_r(s, arg);
+    }
+}
+#endif
+
+/* Write label. */
+static void tci_out_label(TCGContext *s, TCGArg arg)
+{
+    TCGLabel *label = &s->labels[arg];
+    if (label->has_value) {
+        tcg_out_i(s, label->u.value);
+        assert(label->u.value);
+    } else {
+        tcg_out_reloc(s, s->code_ptr, sizeof(tcg_target_ulong), arg, 0);
+        tcg_out_i(s, 0);
+    }
+}
+
+static void tcg_out_ld(TCGContext *s, TCGType type, int ret, int arg1,
+                       tcg_target_long arg2)
+{
+    uint8_t *old_code_ptr = s->code_ptr;
+    if (type == TCG_TYPE_I32) {
+        tcg_out_op_t(s, INDEX_op_ld_i32);
+        tcg_out_r(s, ret);
+        tcg_out_r(s, arg1);
+        tcg_out32(s, arg2);
+    } else {
+        assert(type == TCG_TYPE_I64);
+#if TCG_TARGET_REG_BITS == 64
+        tcg_out_op_t(s, INDEX_op_ld_i64);
+        tcg_out_r(s, ret);
+        tcg_out_r(s, arg1);
+        assert(arg2 == (uint32_t)arg2);
+        tcg_out32(s, arg2);
+#else
+        TODO();
+#endif
+    }
+    old_code_ptr[1] = s->code_ptr - old_code_ptr;
+}
+
+static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
+{
+    uint8_t *old_code_ptr = s->code_ptr;
+    assert(ret != arg);
+#if TCG_TARGET_REG_BITS == 32
+    tcg_out_op_t(s, INDEX_op_mov_i32);
+#else
+    tcg_out_op_t(s, INDEX_op_mov_i64);
+#endif
+    tcg_out_r(s, ret);
+    tcg_out_r(s, arg);
+    old_code_ptr[1] = s->code_ptr - old_code_ptr;
+}
+
+static void tcg_out_movi(TCGContext *s, TCGType type,
+                         int t0, tcg_target_long arg)
+{
+    uint8_t *old_code_ptr = s->code_ptr;
+    uint32_t arg32 = arg;
+    if (type == TCG_TYPE_I32 || arg == arg32) {
+        tcg_out_op_t(s, INDEX_op_movi_i32);
+        tcg_out_r(s, t0);
+        tcg_out32(s, arg32);
+    } else {
+        assert(type == TCG_TYPE_I64);
+#if TCG_TARGET_REG_BITS == 64
+        tcg_out_op_t(s, INDEX_op_movi_i64);
+        tcg_out_r(s, t0);
+        tcg_out64(s, arg);
+#else
+        TODO();
+#endif
+    }
+    old_code_ptr[1] = s->code_ptr - old_code_ptr;
+}
+
+static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
+                       const int *const_args)
+{
+    uint8_t *old_code_ptr = s->code_ptr;
+
+    tcg_out_op_t(s, opc);
+
+    switch (opc) {
+    case INDEX_op_exit_tb:
+        tcg_out64(s, args[0]);
+        break;
+    case INDEX_op_goto_tb:
+        if (s->tb_jmp_offset) {
+            /* Direct jump method. */
+            assert(args[0] < ARRAY_SIZE(s->tb_jmp_offset));
+            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
+            tcg_out32(s, 0);
+        } else {
+            /* Indirect jump method. */
+            TODO();
+        }
+        assert(args[0] < ARRAY_SIZE(s->tb_next_offset));
+        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
+        break;
+    case INDEX_op_br:
+        tci_out_label(s, args[0]);
+        break;
+    case INDEX_op_call:
+        tcg_out_ri(s, const_args[0], args[0]);
+        break;
+    case INDEX_op_jmp:
+        TODO();
+        break;
+    case INDEX_op_setcond_i32:
+        tcg_out_r(s, args[0]);
+        tcg_out_r(s, args[1]);
+        tcg_out_ri32(s, const_args[2], args[2]);
+        tcg_out8(s, args[3]);   /* condition */
+        break;
+#if TCG_TARGET_REG_BITS == 32
+    case INDEX_op_setcond2_i32:
+        /* setcond2_i32 cond, t0, t1_low, t1_high, t2_low, t2_high */
+        tcg_out_r(s, args[0]);
+        tcg_out_r(s, args[1]);
+        tcg_out_r(s, args[2]);
+        tcg_out_ri32(s, const_args[3], args[3]);
+        tcg_out_ri32(s, const_args[4], args[4]);
+        tcg_out8(s, args[5]);   /* condition */
+        break;
+#elif TCG_TARGET_REG_BITS == 64
+    case INDEX_op_setcond_i64:
+        tcg_out_r(s, args[0]);
+        tcg_out_r(s, args[1]);
+        tcg_out_ri64(s, const_args[2], args[2]);
+        tcg_out8(s, args[3]);   /* condition */
+        break;
+#endif
+    case INDEX_op_movi_i32:
+        TODO(); /* Handled by tcg_out_movi? */
+        break;
+    case INDEX_op_ld8u_i32:
+    case INDEX_op_ld8s_i32:
+    case INDEX_op_ld16u_i32:
+    case INDEX_op_ld16s_i32:
+    case INDEX_op_ld_i32:
+    case INDEX_op_st8_i32:
+    case INDEX_op_st16_i32:
+    case INDEX_op_st_i32:
+    case INDEX_op_ld8u_i64:
+    case INDEX_op_ld8s_i64:
+    case INDEX_op_ld16u_i64:
+    case INDEX_op_ld16s_i64:
+    case INDEX_op_ld32u_i64:
+    case INDEX_op_ld32s_i64:
+    case INDEX_op_ld_i64:
+    case INDEX_op_st8_i64:
+    case INDEX_op_st16_i64:
+    case INDEX_op_st32_i64:
+    case INDEX_op_st_i64:
+        tcg_out_r(s, args[0]);
+        tcg_out_r(s, args[1]);
+        assert(args[2] == (uint32_t)args[2]);
+        tcg_out32(s, args[2]);
+        break;
+    case INDEX_op_add_i32:
+    case INDEX_op_sub_i32:
+    case INDEX_op_mul_i32:
+    case INDEX_op_and_i32:
+    case INDEX_op_andc_i32:     /* Optional (TCG_TARGET_HAS_andc_i32). */
+    case INDEX_op_eqv_i32:      /* Optional (TCG_TARGET_HAS_eqv_i32). */
+    case INDEX_op_nand_i32:     /* Optional (TCG_TARGET_HAS_nand_i32). */
+    case INDEX_op_nor_i32:      /* Optional (TCG_TARGET_HAS_nor_i32). */
+    case INDEX_op_or_i32:
+    case INDEX_op_orc_i32:      /* Optional (TCG_TARGET_HAS_orc_i32). */
+    case INDEX_op_xor_i32:
+    case INDEX_op_shl_i32:
+    case INDEX_op_shr_i32:
+    case INDEX_op_sar_i32:
+    case INDEX_op_rotl_i32:     /* Optional (TCG_TARGET_HAS_rot_i32). */
+    case INDEX_op_rotr_i32:     /* Optional (TCG_TARGET_HAS_rot_i32). */
+        tcg_out_r(s, args[0]);
+        tcg_out_ri32(s, const_args[1], args[1]);
+        tcg_out_ri32(s, const_args[2], args[2]);
+        break;
+
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_mov_i64:
+    case INDEX_op_movi_i64:
+        TODO();
+        break;
+    case INDEX_op_add_i64:
+    case INDEX_op_sub_i64:
+    case INDEX_op_mul_i64:
+    case INDEX_op_and_i64:
+    case INDEX_op_andc_i64:     /* Optional (TCG_TARGET_HAS_andc_i64). */
+    case INDEX_op_eqv_i64:      /* Optional (TCG_TARGET_HAS_eqv_i64). */
+    case INDEX_op_nand_i64:     /* Optional (TCG_TARGET_HAS_nand_i64). */
+    case INDEX_op_nor_i64:      /* Optional (TCG_TARGET_HAS_nor_i64). */
+    case INDEX_op_or_i64:
+    case INDEX_op_orc_i64:      /* Optional (TCG_TARGET_HAS_orc_i64). */
+    case INDEX_op_xor_i64:
+    case INDEX_op_shl_i64:
+    case INDEX_op_shr_i64:
+    case INDEX_op_sar_i64:
+        /* TODO: Implementation of rotl_i64, rotr_i64 missing in tci.c. */
+    case INDEX_op_rotl_i64:     /* Optional (TCG_TARGET_HAS_rot_i64). */
+    case INDEX_op_rotr_i64:     /* Optional (TCG_TARGET_HAS_rot_i64). */
+        tcg_out_r(s, args[0]);
+        tcg_out_ri64(s, const_args[1], args[1]);
+        tcg_out_ri64(s, const_args[2], args[2]);
+        break;
+    case INDEX_op_div_i64:      /* Optional (TCG_TARGET_HAS_div_i64). */
+    case INDEX_op_divu_i64:     /* Optional (TCG_TARGET_HAS_div_i64). */
+    case INDEX_op_rem_i64:      /* Optional (TCG_TARGET_HAS_div_i64). */
+    case INDEX_op_remu_i64:     /* Optional (TCG_TARGET_HAS_div_i64). */
+        TODO();
+        break;
+    case INDEX_op_div2_i64:     /* Optional (TCG_TARGET_HAS_div2_i64). */
+    case INDEX_op_divu2_i64:    /* Optional (TCG_TARGET_HAS_div2_i64). */
+        TODO();
+        break;
+    case INDEX_op_brcond_i64:
+        tcg_out_r(s, args[0]);
+        tcg_out_ri64(s, const_args[1], args[1]);
+        tcg_out8(s, args[2]);           /* condition */
+        tci_out_label(s, args[3]);
+        break;
+    case INDEX_op_bswap16_i64:  /* Optional (TCG_TARGET_HAS_bswap16_i64). */
+    case INDEX_op_bswap32_i64:  /* Optional (TCG_TARGET_HAS_bswap32_i64). */
+    case INDEX_op_bswap64_i64:  /* Optional (TCG_TARGET_HAS_bswap64_i64). */
+    case INDEX_op_not_i64:      /* Optional (TCG_TARGET_HAS_not_i64). */
+    case INDEX_op_neg_i64:      /* Optional (TCG_TARGET_HAS_neg_i64). */
+    case INDEX_op_ext8s_i64:    /* Optional (TCG_TARGET_HAS_ext8s_i64). */
+    case INDEX_op_ext8u_i64:    /* Optional (TCG_TARGET_HAS_ext8u_i64). */
+    case INDEX_op_ext16s_i64:   /* Optional (TCG_TARGET_HAS_ext16s_i64). */
+    case INDEX_op_ext16u_i64:   /* Optional (TCG_TARGET_HAS_ext16u_i64). */
+    case INDEX_op_ext32s_i64:   /* Optional (TCG_TARGET_HAS_ext32s_i64). */
+    case INDEX_op_ext32u_i64:   /* Optional (TCG_TARGET_HAS_ext32u_i64). */
+#endif /* TCG_TARGET_REG_BITS == 64 */
+    case INDEX_op_neg_i32:      /* Optional (TCG_TARGET_HAS_neg_i32). */
+    case INDEX_op_not_i32:      /* Optional (TCG_TARGET_HAS_not_i32). */
+    case INDEX_op_ext8s_i32:    /* Optional (TCG_TARGET_HAS_ext8s_i32). */
+    case INDEX_op_ext16s_i32:   /* Optional (TCG_TARGET_HAS_ext16s_i32). */
+    case INDEX_op_ext8u_i32:    /* Optional (TCG_TARGET_HAS_ext8u_i32). */
+    case INDEX_op_ext16u_i32:   /* Optional (TCG_TARGET_HAS_ext16u_i32). */
+    case INDEX_op_bswap16_i32:  /* Optional (TCG_TARGET_HAS_bswap16_i32). */
+    case INDEX_op_bswap32_i32:  /* Optional (TCG_TARGET_HAS_bswap32_i32). */
+        tcg_out_r(s, args[0]);
+        tcg_out_r(s, args[1]);
+        break;
+    case INDEX_op_div_i32:      /* Optional (TCG_TARGET_HAS_div_i32). */
+    case INDEX_op_divu_i32:     /* Optional (TCG_TARGET_HAS_div_i32). */
+    case INDEX_op_rem_i32:      /* Optional (TCG_TARGET_HAS_div_i32). */
+    case INDEX_op_remu_i32:     /* Optional (TCG_TARGET_HAS_div_i32). */
+        tcg_out_r(s, args[0]);
+        tcg_out_ri32(s, const_args[1], args[1]);
+        tcg_out_ri32(s, const_args[2], args[2]);
+        break;
+    case INDEX_op_div2_i32:     /* Optional (TCG_TARGET_HAS_div2_i32). */
+    case INDEX_op_divu2_i32:    /* Optional (TCG_TARGET_HAS_div2_i32). */
+        TODO();
+        break;
+#if TCG_TARGET_REG_BITS == 32
+    case INDEX_op_add2_i32:
+    case INDEX_op_sub2_i32:
+        tcg_out_r(s, args[0]);
+        tcg_out_r(s, args[1]);
+        tcg_out_r(s, args[2]);
+        tcg_out_r(s, args[3]);
+        tcg_out_r(s, args[4]);
+        tcg_out_r(s, args[5]);
+        break;
+    case INDEX_op_brcond2_i32:
+        tcg_out_r(s, args[0]);
+        tcg_out_r(s, args[1]);
+        tcg_out_ri32(s, const_args[2], args[2]);
+        tcg_out_ri32(s, const_args[3], args[3]);
+        tcg_out8(s, args[4]);           /* condition */
+        tci_out_label(s, args[5]);
+        break;
+    case INDEX_op_mulu2_i32:
+        tcg_out_r(s, args[0]);
+        tcg_out_r(s, args[1]);
+        tcg_out_r(s, args[2]);
+        tcg_out_r(s, args[3]);
+        break;
+#endif
+    case INDEX_op_brcond_i32:
+        tcg_out_r(s, args[0]);
+        tcg_out_ri32(s, const_args[1], args[1]);
+        tcg_out8(s, args[2]);           /* condition */
+        tci_out_label(s, args[3]);
+        break;
+    case INDEX_op_qemu_ld8u:
+    case INDEX_op_qemu_ld8s:
+    case INDEX_op_qemu_ld16u:
+    case INDEX_op_qemu_ld16s:
+    case INDEX_op_qemu_ld32:
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_qemu_ld32s:
+    case INDEX_op_qemu_ld32u:
+#endif
+        tcg_out_r(s, *args++);
+        tcg_out_r(s, *args++);
+#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
+        tcg_out_r(s, *args++);
+#endif
+#ifdef CONFIG_SOFTMMU
+        tcg_out_i(s, *args);
+#endif
+        break;
+    case INDEX_op_qemu_ld64:
+        tcg_out_r(s, *args++);
+#if TCG_TARGET_REG_BITS == 32
+        tcg_out_r(s, *args++);
+#endif
+        tcg_out_r(s, *args++);
+#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
+        tcg_out_r(s, *args++);
+#endif
+#ifdef CONFIG_SOFTMMU
+        tcg_out_i(s, *args);
+#endif
+        break;
+    case INDEX_op_qemu_st8:
+    case INDEX_op_qemu_st16:
+    case INDEX_op_qemu_st32:
+        tcg_out_r(s, *args++);
+        tcg_out_r(s, *args++);
+#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
+        tcg_out_r(s, *args++);
+#endif
+#ifdef CONFIG_SOFTMMU
+        tcg_out_i(s, *args);
+#endif
+        break;
+    case INDEX_op_qemu_st64:
+        tcg_out_r(s, *args++);
+#if TCG_TARGET_REG_BITS == 32
+        tcg_out_r(s, *args++);
+#endif
+        tcg_out_r(s, *args++);
+#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
+        tcg_out_r(s, *args++);
+#endif
+#ifdef CONFIG_SOFTMMU
+        tcg_out_i(s, *args);
+#endif
+        break;
+    case INDEX_op_end:
+        TODO();
+        break;
+    default:
+        fprintf(stderr, "Missing: %s\n", tcg_op_defs[opc].name);
+        tcg_abort();
+    }
+    old_code_ptr[1] = s->code_ptr - old_code_ptr;
+}
+
+static void tcg_out_st(TCGContext *s, TCGType type, int arg, int arg1,
+                       tcg_target_long arg2)
+{
+    uint8_t *old_code_ptr = s->code_ptr;
+    if (type == TCG_TYPE_I32) {
+        tcg_out_op_t(s, INDEX_op_st_i32);
+        tcg_out_r(s, arg);
+        tcg_out_r(s, arg1);
+        tcg_out32(s, arg2);
+    } else {
+        assert(type == TCG_TYPE_I64);
+#if TCG_TARGET_REG_BITS == 64
+        tcg_out_op_t(s, INDEX_op_st_i64);
+        tcg_out_r(s, arg);
+        tcg_out_r(s, arg1);
+        tcg_out32(s, arg2);
+#else
+        TODO();
+#endif
+    }
+    old_code_ptr[1] = s->code_ptr - old_code_ptr;
+}
+
+/* Test if a constant matches the constraint. */
+static int tcg_target_const_match(tcg_target_long val,
+                                  const TCGArgConstraint *arg_ct)
+{
+    /* No need to return 0 or 1, 0 or != 0 is good enough. */
+    return arg_ct->ct & TCG_CT_CONST;
+}
+
+/* Maximum number of register used for input function arguments. */
+static int tcg_target_get_call_iarg_regs_count(int flags)
+{
+    return ARRAY_SIZE(tcg_target_call_iarg_regs);
+}
+
+static void tcg_target_init(TCGContext *s)
+{
+#if defined(CONFIG_DEBUG_TCG_INTERPRETER)
+    const char *envval = getenv("DEBUG_TCG");
+    if (envval) {
+        loglevel = strtol(envval, NULL, 0);
+    }
+#endif
+
+    /* The current code uses uint8_t for tcg operations. */
+    assert(ARRAY_SIZE(tcg_op_defs) <= UINT8_MAX);
+
+    /* Registers available for 32 bit operations. */
+    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0,
+                     BIT(TCG_TARGET_NB_REGS) - 1);
+    /* Registers available for 64 bit operations. */
+    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0,
+                     BIT(TCG_TARGET_NB_REGS) - 1);
+    /* TODO: Which registers should be set here? */
+    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
+                     BIT(TCG_TARGET_NB_REGS) - 1);
+    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),
+                  CPU_TEMP_BUF_NLONGS * sizeof(long));
+}
+
+/* Generate global QEMU prologue and epilogue code. */
+static void tcg_target_qemu_prologue(TCGContext *s)
+{
+    tb_ret_addr = s->code_ptr;
+}
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
new file mode 100644
index 0000000..81ded86
--- /dev/null
+++ b/tcg/tci/tcg-target.h
@@ -0,0 +1,160 @@
+/*
+ * Tiny Code Generator for QEMU
+ *
+ * Copyright (c) 2009, 2011 Stefan Weil
+ *
+ * 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.
+ */
+
+/*
+ * This code implements a TCG which does not generate machine code for some
+ * real target machine but which generates virtual machine code for an
+ * interpreter. Interpreted pseudo code is slow, but it works on any host.
+ *
+ * Some remarks might help in understanding the code:
+ *
+ * "target" or "TCG target" is the machine which runs the generated code.
+ * This is different to the usual meaning in QEMU where "target" is the
+ * emulated machine. So normally QEMU host is identical to TCG target.
+ * Here the TCG target is a virtual machine, but this virtual machine must
+ * use the same word size like the real machine.
+ * Therefore, we need both 32 and 64 bit virtual machines (interpreter).
+ */
+
+#if !defined(TCG_TARGET_H)
+#define TCG_TARGET_H
+
+#include "config-host.h"
+
+#define TCG_TARGET_INTERPRETER 1
+
+#ifdef CONFIG_DEBUG_TCG
+/* Enable debug output. */
+#define CONFIG_DEBUG_TCG_INTERPRETER
+#endif
+
+#if 0 /* TCI tries to emulate a little endian host. */
+#if defined(HOST_WORDS_BIGENDIAN)
+# define TCG_TARGET_WORDS_BIGENDIAN
+#endif
+#endif
+
+/* Optional instructions. */
+
+#define TCG_TARGET_HAS_bswap16_i32      1
+#define TCG_TARGET_HAS_bswap32_i32      1
+/* Not more than one of the next two defines must be 1. */
+#define TCG_TARGET_HAS_div_i32          1
+#define TCG_TARGET_HAS_div2_i32         0
+#define TCG_TARGET_HAS_ext8s_i32        1
+#define TCG_TARGET_HAS_ext16s_i32       1
+#define TCG_TARGET_HAS_ext8u_i32        1
+#define TCG_TARGET_HAS_ext16u_i32       1
+#define TCG_TARGET_HAS_andc_i32         0
+#define TCG_TARGET_HAS_deposit_i32      0
+#define TCG_TARGET_HAS_eqv_i32          0
+#define TCG_TARGET_HAS_nand_i32         0
+#define TCG_TARGET_HAS_nor_i32          0
+#define TCG_TARGET_HAS_neg_i32          1
+#define TCG_TARGET_HAS_not_i32          1
+#define TCG_TARGET_HAS_orc_i32          0
+#define TCG_TARGET_HAS_rot_i32          1
+
+#if TCG_TARGET_REG_BITS == 64
+#define TCG_TARGET_HAS_bswap16_i64      1
+#define TCG_TARGET_HAS_bswap32_i64      1
+#define TCG_TARGET_HAS_bswap64_i64      1
+#define TCG_TARGET_HAS_deposit_i64      0
+/* Not more than one of the next two defines must be 1. */
+#define TCG_TARGET_HAS_div_i64          0
+#define TCG_TARGET_HAS_div2_i64         0
+#define TCG_TARGET_HAS_ext8s_i64        1
+#define TCG_TARGET_HAS_ext16s_i64       1
+#define TCG_TARGET_HAS_ext32s_i64       1
+#define TCG_TARGET_HAS_ext8u_i64        1
+#define TCG_TARGET_HAS_ext16u_i64       1
+#define TCG_TARGET_HAS_ext32u_i64       1
+#define TCG_TARGET_HAS_andc_i64         0
+#define TCG_TARGET_HAS_eqv_i64          0
+#define TCG_TARGET_HAS_nand_i64         0
+#define TCG_TARGET_HAS_nor_i64          0
+#define TCG_TARGET_HAS_neg_i64          1
+#define TCG_TARGET_HAS_not_i64          1
+#define TCG_TARGET_HAS_orc_i64          0
+#define TCG_TARGET_HAS_rot_i64          1
+#endif /* TCG_TARGET_REG_BITS == 64 */
+
+/* Offset to user memory in user mode. */
+#define TCG_TARGET_HAS_GUEST_BASE
+
+/* Number of registers available.
+   For 32 bit hosts, we need more than 8 registers (call arguments). */
+/* #define TCG_TARGET_NB_REGS 8 */
+#define TCG_TARGET_NB_REGS 16
+/* #define TCG_TARGET_NB_REGS 32 */
+
+/* List of registers which are used by TCG. */
+typedef enum {
+    TCG_REG_R0 = 0,
+    TCG_REG_R1,
+    TCG_REG_R2,
+    TCG_REG_R3,
+    TCG_REG_R4,
+    TCG_REG_R5,
+    TCG_REG_R6,
+    TCG_REG_R7,
+    TCG_AREG0 = TCG_REG_R7,
+#if TCG_TARGET_NB_REGS >= 16
+    TCG_REG_R8,
+    TCG_REG_R9,
+    TCG_REG_R10,
+    TCG_REG_R11,
+    TCG_REG_R12,
+    TCG_REG_R13,
+    TCG_REG_R14,
+    TCG_REG_R15,
+#if TCG_TARGET_NB_REGS >= 32
+    TCG_REG_R16,
+    TCG_REG_R17,
+    TCG_REG_R18,
+    TCG_REG_R19,
+    TCG_REG_R20,
+    TCG_REG_R21,
+    TCG_REG_R22,
+    TCG_REG_R23,
+    TCG_REG_R24,
+    TCG_REG_R25,
+    TCG_REG_R26,
+    TCG_REG_R27,
+    TCG_REG_R28,
+    TCG_REG_R29,
+    TCG_REG_R30,
+    TCG_REG_R31,
+#endif
+#endif
+    /* Special value UINT8_MAX is used by TCI to encode constant values. */
+    TCG_CONST = UINT8_MAX
+} TCGRegister;
+
+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
+
+#endif /* TCG_TARGET_H */
commit 2a24374ab6c27c00dd346f0961a0f05e13672a86
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Sep 29 18:33:21 2011 +0200

    tcg: Make ARRAY_SIZE(tcg_op_defs) globally available
    
    tcg_op_defs was already a global array.
    
    The tci disassembler also needs ARRAY_SIZE(tcg_op_defs),
    so add a new global constant with this value.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 30f3aef..6b27d7b 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -89,6 +89,7 @@ TCGOpDef tcg_op_defs[] = {
 #include "tcg-opc.h"
 #undef DEF
 };
+const size_t tcg_op_defs_max = ARRAY_SIZE(tcg_op_defs);
 
 static TCGRegSet tcg_target_available_regs[2];
 static TCGRegSet tcg_target_call_clobber_regs;
diff --git a/tcg/tcg.h b/tcg/tcg.h
index ca48075..755a8b3 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -525,7 +525,8 @@ typedef struct TCGOpDef {
 } TCGOpDef;
 
 extern TCGOpDef tcg_op_defs[];
-        
+extern const size_t tcg_op_defs_max;
+
 typedef struct TCGTargetOpDef {
     TCGOpcode op;
     const char *args_ct_str[TCG_MAX_OP_ARGS];
commit ce285b17549e806483f6499d7f3d418168116950
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Sep 30 21:23:06 2011 +0200

    tcg: TCG targets may define tcg_qemu_tb_exec
    
    Targets may use a non standard definition of tcg_tb_exec
    by defining this macro in their tcg_target.h.
    
    This is used here by ppc. It will be used by the TCG interpreter, too.
    
    Cc: malc <av1474 at comtv.ru>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index 5c2d612..25a6ea4 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -96,3 +96,7 @@ enum {
 #define TCG_AREG0 TCG_REG_R27
 
 #define TCG_TARGET_HAS_GUEST_BASE
+
+#define tcg_qemu_tb_exec(env, tb_ptr) \
+    ((long REGPARM __attribute__ ((longcall)) \
+      (*)(void *, void *))code_gen_prologue)(env, tb_ptr)
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 015f88a..ca48075 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -584,10 +584,9 @@ TCGv_i32 tcg_const_local_i32(int32_t val);
 TCGv_i64 tcg_const_local_i64(int64_t val);
 
 extern uint8_t code_gen_prologue[];
-#if defined(_ARCH_PPC) && !defined(_ARCH_PPC64)
-#define tcg_qemu_tb_exec(env, tb_ptr)                                    \
-    ((long REGPARM __attribute__ ((longcall)) (*)(void *, void *))code_gen_prologue)(env, tb_ptr)
-#else
-#define tcg_qemu_tb_exec(env, tb_ptr)                                    \
+
+/* 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)
 #endif
commit 3384f95c59e5db381cf3e605c8acec71baf0e6b8
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Sun Oct 30 17:16:46 2011 +0000

    pseries: Add partial support for PCI
    
    This patch adds a PCI bus to the pseries machine.  This instantiates
    the qemu generic PCI bus code, advertises a PCI host bridge in the
    guest's device tree and implements the RTAS methods specified by PAPR
    to access PCI config space.  It also sets up the memory regions we
    need to provide windows into the PCI memory and IO space, and
    advertises those to the guest.
    
    However, because qemu can't yet emulate an IOMMU, which is mandatory on
    pseries, PCI devices which use DMA (i.e. most of them) will not work with
    this code alone.  Still, this is enough to support the virtio_pci device
    (which probably _should_ use emulated PCI DMA, but is specced to use
    direct hypervisor access to guest physical memory instead).
    
    [agraf] remove typedef which could cause compile errors
    
    Signed-off-by: Alexey Kardashevskiy <aik at au1.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/Makefile.target b/Makefile.target
index fe5f6f7..2329df5 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -248,6 +248,7 @@ obj-ppc-y += ppc_newworld.o
 # IBM pSeries (sPAPR)
 obj-ppc-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
 obj-ppc-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
+obj-ppc-$(CONFIG_PSERIES) += spapr_pci.o device-hotplug.o pci-hotplug.o
 # PowerPC 4xx boards
 obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
 obj-ppc-y += ppc440.o ppc440_bamboo.o
diff --git a/hw/spapr.c b/hw/spapr.c
index 933af32..bdaa938 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -39,10 +39,12 @@
 
 #include "hw/spapr.h"
 #include "hw/spapr_vio.h"
+#include "hw/spapr_pci.h"
 #include "hw/xics.h"
 
 #include "kvm.h"
 #include "kvm_ppc.h"
+#include "pci.h"
 
 #include "exec-memory.h"
 
@@ -62,6 +64,11 @@
 #define MAX_CPUS                256
 #define XICS_IRQS		1024
 
+#define SPAPR_PCI_BUID          0x800000020000001ULL
+#define SPAPR_PCI_MEM_WIN_ADDR  (0x10000000000ULL + 0xA0000000)
+#define SPAPR_PCI_MEM_WIN_SIZE  0x20000000
+#define SPAPR_PCI_IO_WIN_ADDR   (0x10000000000ULL + 0x80000000)
+
 #define PHANDLE_XICP            0x00001111
 
 sPAPREnvironment *spapr;
@@ -146,6 +153,14 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
                        &end_prop, sizeof(end_prop))));
     _FDT((fdt_property_string(fdt, "qemu,boot-device", boot_device)));
 
+    /*
+     * Because we don't always invoke any firmware, we can't rely on
+     * that to do BAR allocation.  Long term, we should probably do
+     * that ourselves, but for now, this setting (plus advertising the
+     * current BARs as 0) causes sufficiently recent kernels to to the
+     * BAR assignment themselves */
+    _FDT((fdt_property_cell(fdt, "linux,pci-probe-only", 0)));
+
     _FDT((fdt_end_node(fdt)));
 
     /* memory node(s) */
@@ -308,6 +323,7 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
 {
     int ret;
     void *fdt;
+    sPAPRPHBState *phb;
 
     fdt = g_malloc(FDT_MAX_SIZE);
 
@@ -320,6 +336,15 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
         exit(1);
     }
 
+    QLIST_FOREACH(phb, &spapr->phbs, list) {
+        ret = spapr_populate_pci_devices(phb, PHANDLE_XICP, fdt);
+    }
+
+    if (ret < 0) {
+        fprintf(stderr, "couldn't setup PCI devices in fdt\n");
+        exit(1);
+    }
+
     /* RTAS */
     ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size);
     if (ret < 0) {
@@ -478,6 +503,12 @@ static void ppc_spapr_init(ram_addr_t ram_size,
         }
     }
 
+    /* Set up PCI */
+    spapr_create_phb(spapr, "pci", SPAPR_PCI_BUID,
+                     SPAPR_PCI_MEM_WIN_ADDR,
+                     SPAPR_PCI_MEM_WIN_SIZE,
+                     SPAPR_PCI_IO_WIN_ADDR);
+
     for (i = 0; i < nb_nics; i++) {
         NICInfo *nd = &nd_table[i];
 
@@ -488,10 +519,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
         if (strcmp(nd->model, "ibmveth") == 0) {
             spapr_vlan_create(spapr->vio_bus, 0x1000 + i, nd);
         } else {
-            fprintf(stderr, "pSeries (sPAPR) platform does not support "
-                    "NIC model '%s' (only ibmveth is supported)\n",
-                    nd->model);
-            exit(1);
+            pci_nic_init_nofail(&nd_table[i], nd->model, NULL);
         }
     }
 
diff --git a/hw/spapr.h b/hw/spapr.h
index 6657c33..df88f6a 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -4,10 +4,12 @@
 #include "hw/xics.h"
 
 struct VIOsPAPRBus;
+struct sPAPRPHBState;
 struct icp_state;
 
 typedef struct sPAPREnvironment {
     struct VIOsPAPRBus *vio_bus;
+    QLIST_HEAD(, sPAPRPHBState) phbs;
     struct icp_state *icp;
 
     target_phys_addr_t ram_limit;
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
new file mode 100644
index 0000000..2a5e637
--- /dev/null
+++ b/hw/spapr_pci.c
@@ -0,0 +1,508 @@
+/*
+ * QEMU sPAPR PCI host originated from Uninorth PCI host
+ *
+ * Copyright (c) 2011 Alexey Kardashevskiy, IBM Corporation.
+ * Copyright (C) 2011 David Gibson, IBM Corporation.
+ *
+ * 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 "pci.h"
+#include "pci_host.h"
+#include "hw/spapr.h"
+#include "hw/spapr_pci.h"
+#include "exec-memory.h"
+#include <libfdt.h>
+
+#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)
+{
+    DeviceState *qdev;
+    int devfn = (config_addr >> 8) & 0xFF;
+    sPAPRPHBState *phb;
+
+    QLIST_FOREACH(phb, &spapr->phbs, list) {
+        if (phb->buid != buid) {
+            continue;
+        }
+
+        QLIST_FOREACH(qdev, &phb->host_state.bus->qbus.children, sibling) {
+            PCIDevice *dev = (PCIDevice *)qdev;
+            if (dev->devfn == devfn) {
+                return dev;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+static void rtas_ibm_read_pci_config(sPAPREnvironment *spapr,
+                                     uint32_t token, uint32_t nargs,
+                                     target_ulong args,
+                                     uint32_t nret, target_ulong rets)
+{
+    uint32_t val, size, addr;
+    uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
+    PCIDevice *dev = find_dev(spapr, buid, rtas_ld(args, 0));
+
+    if (!dev) {
+        rtas_st(rets, 0, -1);
+        return;
+    }
+    size = rtas_ld(args, 3);
+    addr = rtas_ld(args, 0) & 0xFF;
+    val = pci_default_read_config(dev, addr, size);
+    rtas_st(rets, 0, 0);
+    rtas_st(rets, 1, val);
+}
+
+static void rtas_read_pci_config(sPAPREnvironment *spapr,
+                                 uint32_t token, uint32_t nargs,
+                                 target_ulong args,
+                                 uint32_t nret, target_ulong rets)
+{
+    uint32_t val, size, addr;
+    PCIDevice *dev = find_dev(spapr, 0, rtas_ld(args, 0));
+
+    if (!dev) {
+        rtas_st(rets, 0, -1);
+        return;
+    }
+    size = rtas_ld(args, 1);
+    addr = rtas_ld(args, 0) & 0xFF;
+    val = pci_default_read_config(dev, addr, size);
+    rtas_st(rets, 0, 0);
+    rtas_st(rets, 1, val);
+}
+
+static void rtas_ibm_write_pci_config(sPAPREnvironment *spapr,
+                                      uint32_t token, uint32_t nargs,
+                                      target_ulong args,
+                                      uint32_t nret, target_ulong rets)
+{
+    uint32_t val, size, addr;
+    uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
+    PCIDevice *dev = find_dev(spapr, buid, rtas_ld(args, 0));
+
+    if (!dev) {
+        rtas_st(rets, 0, -1);
+        return;
+    }
+    val = rtas_ld(args, 4);
+    size = rtas_ld(args, 3);
+    addr = rtas_ld(args, 0) & 0xFF;
+    pci_default_write_config(dev, addr, val, size);
+    rtas_st(rets, 0, 0);
+}
+
+static void rtas_write_pci_config(sPAPREnvironment *spapr,
+                                  uint32_t token, uint32_t nargs,
+                                  target_ulong args,
+                                  uint32_t nret, target_ulong rets)
+{
+    uint32_t val, size, addr;
+    PCIDevice *dev = find_dev(spapr, 0, rtas_ld(args, 0));
+
+    if (!dev) {
+        rtas_st(rets, 0, -1);
+        return;
+    }
+    val = rtas_ld(args, 2);
+    size = rtas_ld(args, 1);
+    addr = rtas_ld(args, 0) & 0xFF;
+    pci_default_write_config(dev, addr, val, size);
+    rtas_st(rets, 0, 0);
+}
+
+static int pci_spapr_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    /*
+     * Here we need to convert pci_dev + irq_num to some unique value
+     * which is less than number of IRQs on the specific bus (now it
+     * is 16).  At the moment irq_num == device_id (number of the
+     * slot?)
+     * FIXME: we should swizzle in fn and irq_num
+     */
+    return (pci_dev->devfn >> 3) % SPAPR_PCI_NUM_LSI;
+}
+
+static void pci_spapr_set_irq(void *opaque, int irq_num, int level)
+{
+    /*
+     * Here we use the number returned by pci_spapr_map_irq to find a
+     * corresponding qemu_irq.
+     */
+    sPAPRPHBState *phb = opaque;
+
+    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_irq(0, &num);
+        if (!qirq) {
+            return -1;
+        }
+
+        phb->lsi_table[i].dt_irq = num;
+        phb->lsi_table[i].qirq = qirq;
+    }
+
+    return 0;
+}
+
+static int spapr_main_pci_host_init(PCIDevice *d)
+{
+    return 0;
+}
+
+static PCIDeviceInfo spapr_main_pci_host_info = {
+    .qdev.name = "spapr-pci-host-bridge",
+    .qdev.size = sizeof(PCIDevice),
+    .init      = spapr_main_pci_host_init,
+};
+
+static void spapr_register_devices(void)
+{
+    sysbus_register_dev("spapr-pci-host-bridge", sizeof(sPAPRPHBState),
+                        spapr_phb_init);
+    pci_qdev_register(&spapr_main_pci_host_info);
+}
+
+device_init(spapr_register_devices)
+
+static uint64_t spapr_io_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
+{
+    switch (size) {
+    case 1:
+        return cpu_inb(addr);
+    case 2:
+        return cpu_inw(addr);
+    case 4:
+        return cpu_inl(addr);
+    }
+    assert(0);
+}
+
+static void spapr_io_write(void *opaque, target_phys_addr_t addr,
+                           uint64_t data, unsigned size)
+{
+    switch (size) {
+    case 1:
+        cpu_outb(addr, data);
+        return;
+    case 2:
+        cpu_outw(addr, data);
+        return;
+    case 4:
+        cpu_outl(addr, data);
+        return;
+    }
+    assert(0);
+}
+
+static MemoryRegionOps spapr_io_ops = {
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .read = spapr_io_read,
+    .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)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    sPAPRPHBState *phb;
+    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->mem_win_addr = mem_win_addr;
+
+    sprintf(namebuf, "%s-mem", busname);
+    memory_region_init(&phb->memspace, namebuf, INT64_MAX);
+
+    sprintf(namebuf, "%s-memwindow", busname);
+    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,
+                                &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,
+     * if any of the IO BAR subregions use the old_portio mechanism,
+     * that won't be processed properly unless accessed from the
+     * 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);
+    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);
+    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,
+                                &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);
+
+    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);
+
+    /* pci_bus_set_mem_base(bus, mem_va_start - SPAPR_PCI_MEM_BAR_START); */
+}
+
+/* Macros to operate with address in OF binding to PCI */
+#define b_x(x, p, l)    (((x) & ((1<<(l))-1)) << (p))
+#define b_n(x)          b_x((x), 31, 1) /* 0 if relocatable */
+#define b_p(x)          b_x((x), 30, 1) /* 1 if prefetchable */
+#define b_t(x)          b_x((x), 29, 1) /* 1 if the address is aliased */
+#define b_ss(x)         b_x((x), 24, 2) /* the space code */
+#define b_bbbbbbbb(x)   b_x((x), 16, 8) /* bus number */
+#define b_ddddd(x)      b_x((x), 11, 5) /* device number */
+#define b_fff(x)        b_x((x), 8, 3)  /* function number */
+#define b_rrrrrrrr(x)   b_x((x), 0, 8)  /* register number */
+
+static uint32_t regtype_to_ss(uint8_t type)
+{
+    if (type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+        return 3;
+    }
+    if (type == PCI_BASE_ADDRESS_SPACE_IO) {
+        return 1;
+    }
+    return 2;
+}
+
+int spapr_populate_pci_devices(sPAPRPHBState *phb,
+                               uint32_t xics_phandle,
+                               void *fdt)
+{
+    PCIBus *bus = phb->host_state.bus;
+    int bus_off, node_off = 0, devid, fn, i, n, devices;
+    DeviceState *qdev;
+    char nodename[256];
+    struct {
+        uint32_t hi;
+        uint64_t addr;
+        uint64_t size;
+    } __attribute__((packed)) reg[PCI_NUM_REGIONS + 1],
+          assigned_addresses[PCI_NUM_REGIONS];
+    uint32_t bus_range[] = { cpu_to_be32(0), cpu_to_be32(0xff) };
+    struct {
+        uint32_t hi;
+        uint64_t child;
+        uint64_t parent;
+        uint64_t size;
+    } __attribute__((packed)) ranges[] = {
+        {
+            cpu_to_be32(b_ss(1)), cpu_to_be64(0),
+            cpu_to_be64(phb->io_win_addr),
+            cpu_to_be64(memory_region_size(&phb->iospace)),
+        },
+        {
+            cpu_to_be32(b_ss(2)), cpu_to_be64(SPAPR_PCI_MEM_WIN_BUS_OFFSET),
+            cpu_to_be64(phb->mem_win_addr),
+            cpu_to_be64(memory_region_size(&phb->memwindow)),
+        },
+    };
+    uint64_t bus_reg[] = { cpu_to_be64(phb->buid), 0 };
+    uint32_t interrupt_map_mask[] = {
+        cpu_to_be32(b_ddddd(-1)|b_fff(-1)), 0x0, 0x0, 0x0};
+    uint32_t interrupt_map[bus->nirq][7];
+
+    /* Start populating the FDT */
+    sprintf(nodename, "pci@%" PRIx64, phb->buid);
+    bus_off = fdt_add_subnode(fdt, 0, nodename);
+    if (bus_off < 0) {
+        return bus_off;
+    }
+
+#define _FDT(exp) \
+    do { \
+        int ret = (exp);                                           \
+        if (ret < 0) {                                             \
+            return ret;                                            \
+        }                                                          \
+    } while (0)
+
+    /* Write PHB properties */
+    _FDT(fdt_setprop_string(fdt, bus_off, "device_type", "pci"));
+    _FDT(fdt_setprop_string(fdt, bus_off, "compatible", "IBM,Logical_PHB"));
+    _FDT(fdt_setprop_cell(fdt, bus_off, "#address-cells", 0x3));
+    _FDT(fdt_setprop_cell(fdt, bus_off, "#size-cells", 0x2));
+    _FDT(fdt_setprop_cell(fdt, bus_off, "#interrupt-cells", 0x1));
+    _FDT(fdt_setprop(fdt, bus_off, "used-by-rtas", NULL, 0));
+    _FDT(fdt_setprop(fdt, bus_off, "bus-range", &bus_range, sizeof(bus_range)));
+    _FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof(ranges)));
+    _FDT(fdt_setprop(fdt, bus_off, "reg", &bus_reg, sizeof(bus_reg)));
+    _FDT(fdt_setprop(fdt, bus_off, "interrupt-map-mask",
+                     &interrupt_map_mask, sizeof(interrupt_map_mask)));
+
+    /* Populate PCI devices and allocate IRQs */
+    devices = 0;
+    QLIST_FOREACH(qdev, &bus->qbus.children, sibling) {
+        PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev);
+        int irq_index = pci_spapr_map_irq(dev, 0);
+        uint32_t *irqmap = interrupt_map[devices];
+        uint8_t *config = dev->config;
+
+        devid = dev->devfn >> 3;
+        fn = dev->devfn & 7;
+
+        sprintf(nodename, "pci@%u,%u", devid, fn);
+
+        /* Allocate interrupt from the map */
+        if (devid > bus->nirq)  {
+            printf("Unexpected behaviour in spapr_populate_pci_devices,"
+                    "wrong devid %u\n", devid);
+            exit(-1);
+        }
+        irqmap[0] = cpu_to_be32(b_ddddd(devid)|b_fff(fn));
+        irqmap[1] = 0;
+        irqmap[2] = 0;
+        irqmap[3] = 0;
+        irqmap[4] = cpu_to_be32(xics_phandle);
+        irqmap[5] = cpu_to_be32(phb->lsi_table[irq_index].dt_irq);
+        irqmap[6] = cpu_to_be32(0x8);
+
+        /* Add node to FDT */
+        node_off = fdt_add_subnode(fdt, bus_off, nodename);
+        if (node_off < 0) {
+            return node_off;
+        }
+
+        _FDT(fdt_setprop_cell(fdt, node_off, "vendor-id",
+                              pci_get_word(&config[PCI_VENDOR_ID])));
+        _FDT(fdt_setprop_cell(fdt, node_off, "device-id",
+                              pci_get_word(&config[PCI_DEVICE_ID])));
+        _FDT(fdt_setprop_cell(fdt, node_off, "revision-id",
+                              pci_get_byte(&config[PCI_REVISION_ID])));
+        _FDT(fdt_setprop_cell(fdt, node_off, "class-code",
+                              pci_get_long(&config[PCI_CLASS_REVISION]) >> 8));
+        _FDT(fdt_setprop_cell(fdt, node_off, "subsystem-id",
+                              pci_get_word(&config[PCI_SUBSYSTEM_ID])));
+        _FDT(fdt_setprop_cell(fdt, node_off, "subsystem-vendor-id",
+                              pci_get_word(&config[PCI_SUBSYSTEM_VENDOR_ID])));
+
+        /* Config space region comes first */
+        reg[0].hi = cpu_to_be32(
+            b_n(0) |
+            b_p(0) |
+            b_t(0) |
+            b_ss(0/*config*/) |
+            b_bbbbbbbb(0) |
+            b_ddddd(devid) |
+            b_fff(fn));
+        reg[0].addr = 0;
+        reg[0].size = 0;
+
+        n = 0;
+        for (i = 0; i < PCI_NUM_REGIONS; ++i) {
+            if (0 == dev->io_regions[i].size) {
+                continue;
+            }
+
+            reg[n+1].hi = cpu_to_be32(
+                b_n(0) |
+                b_p(0) |
+                b_t(0) |
+                b_ss(regtype_to_ss(dev->io_regions[i].type)) |
+                b_bbbbbbbb(0) |
+                b_ddddd(devid) |
+                b_fff(fn) |
+                b_rrrrrrrr(bars[i]));
+            reg[n+1].addr = 0;
+            reg[n+1].size = cpu_to_be64(dev->io_regions[i].size);
+
+            assigned_addresses[n].hi = cpu_to_be32(
+                b_n(1) |
+                b_p(0) |
+                b_t(0) |
+                b_ss(regtype_to_ss(dev->io_regions[i].type)) |
+                b_bbbbbbbb(0) |
+                b_ddddd(devid) |
+                b_fff(fn) |
+                b_rrrrrrrr(bars[i]));
+
+            /*
+             * Writing zeroes to assigned_addresses causes the guest kernel to
+             * reassign BARs
+             */
+            assigned_addresses[n].addr = cpu_to_be64(dev->io_regions[i].addr);
+            assigned_addresses[n].size = reg[n+1].size;
+
+            ++n;
+        }
+        _FDT(fdt_setprop(fdt, node_off, "reg", reg, sizeof(reg[0])*(n+1)));
+        _FDT(fdt_setprop(fdt, node_off, "assigned-addresses",
+                         assigned_addresses,
+                         sizeof(assigned_addresses[0])*(n)));
+        _FDT(fdt_setprop_cell(fdt, node_off, "interrupts",
+                              pci_get_byte(&config[PCI_INTERRUPT_PIN])));
+
+        ++devices;
+    }
+
+    /* Write interrupt map */
+    _FDT(fdt_setprop(fdt, bus_off, "interrupt-map", &interrupt_map,
+                     devices * sizeof(interrupt_map[0])));
+
+    return 0;
+}
diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h
new file mode 100644
index 0000000..213340c
--- /dev/null
+++ b/hw/spapr_pci.h
@@ -0,0 +1,61 @@
+/*
+ * QEMU SPAPR PCI BUS definitions
+ *
+ * Copyright (c) 2011 Alexey Kardashevskiy <aik at au1.ibm.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 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/>.
+ */
+#if !defined(__HW_SPAPR_H__)
+#error Please include spapr.h before this file!
+#endif
+
+#if !defined(__HW_SPAPR_PCI_H__)
+#define __HW_SPAPR_PCI_H__
+
+#include "hw/pci_host.h"
+#include "hw/xics.h"
+
+#define SPAPR_PCI_NUM_LSI   16
+
+typedef struct sPAPRPHBState {
+    SysBusDevice busdev;
+    PCIHostState host_state;
+
+    uint64_t buid;
+
+    MemoryRegion memspace, iospace;
+    target_phys_addr_t mem_win_addr, io_win_addr;
+    MemoryRegion memwindow, iowindow;
+
+    struct {
+        uint32_t dt_irq;
+        qemu_irq qirq;
+    } lsi_table[SPAPR_PCI_NUM_LSI];
+
+    QLIST_ENTRY(sPAPRPHBState) list;
+} sPAPRPHBState;
+
+#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL
+#define SPAPR_PCI_IO_WIN_SIZE        0x10000
+
+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);
+
+int spapr_populate_pci_devices(sPAPRPHBState *phb,
+                               uint32_t xics_phandle,
+                               void *fdt);
+
+#endif /* __HW_SPAPR_PCI_H__ */
commit 02d4eae4b0be19d84996105cf6e0cc33f41e3833
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Sun Oct 30 15:51:24 2011 +0000

    ppc: Alter CPU state to mask out TCG unimplemented instructions as appropriate
    
    The CPU state contains two bitmaps, initialized from the CPU spec
    which describes which instructions are implemented on the CPU.  A
    couple of bits are defined which cover instructions (VSX and DFP)
    which are not currently implemented in TCG.  So far, these are only
    used to handle the case of -cpu host because a KVM guest can use
    the instructions when the host CPU supports them.
    
    However, it's a mild layering violation to simply not include those
    bits in the CPU descriptions for those CPUs that do support them,
    just because we can't handle them in TCG.  This patch corrects the
    situation, so that the instruction bits _are_ shown correctly in the
    cpu spec table, but are masked out from the cpu state in the non-KVM
    case.
    
    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 3ef4eba..e84108c 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1856,6 +1856,30 @@ enum {
     /* popcntw and popcntd instructions                                      */
     PPC_POPCNTWD       = 0x8000000000000000ULL,
 
+#define PPC_TCG_INSNS  (PPC_INSNS_BASE | PPC_POWER | PPC_POWER2 \
+                        | PPC_POWER_RTC | PPC_POWER_BR | PPC_64B \
+                        | PPC_64BX | PPC_64H | PPC_WAIT | PPC_MFTB \
+                        | PPC_602_SPEC | PPC_ISEL | PPC_POPCNTB \
+                        | PPC_STRING | PPC_FLOAT | PPC_FLOAT_EXT \
+                        | PPC_FLOAT_FSQRT | PPC_FLOAT_FRES \
+                        | PPC_FLOAT_FRSQRTE | PPC_FLOAT_FRSQRTES \
+                        | PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX \
+                        | PPC_ALTIVEC | PPC_SPE | PPC_SPE_SINGLE \
+                        | PPC_SPE_DOUBLE | PPC_MEM_TLBIA \
+                        | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC \
+                        | PPC_MEM_SYNC | PPC_MEM_EIEIO \
+                        | PPC_CACHE | PPC_CACHE_ICBI \
+                        | PPC_CACHE_DCBZ | PPC_CACHE_DCBZT \
+                        | PPC_CACHE_DCBA | PPC_CACHE_LOCK \
+                        | PPC_EXTERN | PPC_SEGMENT | PPC_6xx_TLB \
+                        | PPC_74xx_TLB | PPC_40x_TLB | PPC_SEGMENT_64B \
+                        | PPC_SLBI | PPC_WRTEE | PPC_40x_EXCP \
+                        | PPC_405_MAC | PPC_440_SPEC | PPC_BOOKE \
+                        | PPC_MFAPIDI | PPC_TLBIVA | PPC_TLBIVAX \
+                        | PPC_4xx_COMMON | PPC_40x_ICBT | PPC_RFMCI \
+                        | PPC_RFDI | PPC_DCR | PPC_DCRX | PPC_DCRUX \
+                        | PPC_POPCNTWD)
+
     /* extended type values */
 
     /* BookE 2.06 PowerPC specification                                      */
@@ -1864,6 +1888,8 @@ enum {
     PPC2_VSX           = 0x0000000000000002ULL,
     /* Decimal Floating Point (DFP)                                          */
     PPC2_DFP           = 0x0000000000000004ULL,
+
+#define PPC_TCG_INSNS2 (PPC2_BOOKE206)
 };
 
 /*****************************************************************************/
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 4dfd7f3..8a7233f 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -6519,9 +6519,7 @@ static void init_proc_970MP (CPUPPCState *env)
                               PPC_64B | PPC_ALTIVEC |                         \
                               PPC_SEGMENT_64B | PPC_SLBI |                    \
                               PPC_POPCNTB | PPC_POPCNTWD)
-/* FIXME: Should also have PPC2_VSX and PPC2_DFP, but we don't
- * implement those in TCG yet */
-#define POWERPC_INSNS2_POWER7 (PPC_NONE)
+#define POWERPC_INSNS2_POWER7 (PPC2_VSX | PPC2_DFP)
 #define POWERPC_MSRM_POWER7   (0x800000000204FF36ULL)
 #define POWERPC_MMU_POWER7    (POWERPC_MMU_2_06)
 #define POWERPC_EXCP_POWER7   (POWERPC_EXCP_POWER7)
@@ -9848,6 +9846,22 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
     env->bus_model = def->bus_model;
     env->insns_flags = def->insns_flags;
     env->insns_flags2 = def->insns_flags2;
+    if (!kvm_enabled()) {
+        /* TCG doesn't (yet) emulate some groups of instructions that
+         * are implemented on some otherwise supported CPUs (e.g. VSX
+         * and decimal floating point instructions on POWER7).  We
+         * remove unsupported instruction groups from the cpu state's
+         * instruction masks and hope the guest can cope.  For at
+         * least the pseries machine, the unavailability of these
+         * instructions can be advertise to the guest via the device
+         * tree.
+         *
+         * FIXME: we should have a similar masking for CPU features
+         * not accessible under KVM, but so far, there aren't any of
+         * those. */
+        env->insns_flags &= PPC_TCG_INSNS;
+        env->insns_flags2 &= PPC_TCG_INSNS2;
+    }
     env->flags = def->flags;
     env->bfd_mach = def->bfd_mach;
     env->check_pow = def->check_pow;
commit 74b41e5676568e6560474267bbf1a5a32d3e2c41
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Thu Oct 27 15:56:31 2011 +0000

    pseries: Allow writes to KVM accelerated TCE table
    
    Sufficiently recent kernels include a KVM call to accelerate use of
    PAPR TCE tables (IOMMU), which are used by PAPR virtual IO devices.
    This involves qemu mapping the TCE table in from a kernel obtained fd,
    which currently we do with PROT_READ only.  This is a hangover from
    early (never released) versions of this kernel interface which only
    permitted read-only mappings and required us to destroy and recreate
    the table when we needed to clear it from qemu.
    
    Now, the kernel permits read-write mappings, and we rely on this to
    clear the table in spapr_vio_quiesce_one().  However, due to
    insufficient testing, I forgot to update the actual mapping of the
    table in kvmppc_create_spapr_tce() to add PROT_WRITE to the mmap().
    
    This patch corrects the oversight.
    
    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 f3d0861..429349f 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -850,7 +850,7 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd)
     len = (window_size / SPAPR_VIO_TCE_PAGE_SIZE) * sizeof(VIOsPAPR_RTCE);
     /* FIXME: round this up to page size */
 
-    table = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
+    table = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
     if (table == MAP_FAILED) {
         close(fd);
         return NULL;
commit 70bca53ffb811ea59dc090b3ca7825cf0bf346a7
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Oct 24 20:43:22 2011 +0200

    KVM: PPC: Override host vmx/vsx/dfp only when information known
    
    The -cpu host feature tries to find out the host capabilities based
    on device tree information. However, we don't always have that available
    because it's an optional property in dt.
    
    So instead of force unsetting values depending on an unreliable source
    of information, let's just try to be clever about it and not override
    capabilities when we don't know the device tree pieces.
    
    This fixes altivec with -cpu host on YDL PowerStations.
    
    Reported-by: Nishanth Aravamudan <nacc at us.ibm.com>
    Acked-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 a090d79..f3d0861 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -912,9 +912,15 @@ const ppc_def_t *kvmppc_host_cpu_def(void)
 
     /* Now fix up the spec with information we can query from the host */
 
-    alter_insns(&spec->insns_flags, PPC_ALTIVEC, vmx > 0);
-    alter_insns(&spec->insns_flags2, PPC2_VSX, vmx > 1);
-    alter_insns(&spec->insns_flags2, PPC2_DFP, dfp);
+    if (vmx != -1) {
+        /* Only override when we know what the host supports */
+        alter_insns(&spec->insns_flags, PPC_ALTIVEC, vmx > 0);
+        alter_insns(&spec->insns_flags2, PPC2_VSX, vmx > 1);
+    }
+    if (dfp != -1) {
+        /* Only override when we know what the host supports */
+        alter_insns(&spec->insns_flags2, PPC2_DFP, dfp);
+    }
 
     return spec;
 }
commit 98efaf75282a96ffbe2914f79a9f5cb736a03db4
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Sun Oct 23 17:25:04 2011 +0000

    ppc: Fix up usermode only builds
    
    The recent usage of MemoryRegion in kvm_ppc.h breaks builds with
    CONFIG_USER_ONLY=y.  This patch fixes it.
    
    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_ppc.h b/target-ppc/kvm_ppc.h
index b0d6fb6..f9c0198 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -23,9 +23,11 @@ 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_smt_threads(void);
+#ifndef CONFIG_USER_ONLY
 off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem);
 void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd);
 int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size);
+#endif /* !CONFIG_USER_ONLY */
 const ppc_def_t *kvmppc_host_cpu_def(void);
 
 #else
@@ -69,6 +71,7 @@ static inline int kvmppc_smt_threads(void)
     return 1;
 }
 
+#ifndef CONFIG_USER_ONLY
 static inline off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
 {
     return 0;
@@ -85,6 +88,7 @@ static inline int kvmppc_remove_spapr_tce(void *table, int pfd,
 {
     return -1;
 }
+#endif /* !CONFIG_USER_ONLY */
 
 static inline const ppc_def_t *kvmppc_host_cpu_def(void)
 {
commit a7342588c081c7497bc7810431a03fa7b669af40
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Oct 17 18:15:41 2011 +0000

    pseries: Correct vmx/dfp handling in both KVM and TCG cases
    
    Currently, when KVM is enabled, the pseries machine checks if the host
    CPU supports VMX, VSX and/or DFP instructions and advertises
    accordingly in the guest device tree.  It does this regardless of what
    CPU is selected on the command line.  On the other hand, when in TCG
    mode, it never advertises any of these facilities, even basic VMX
    (Altivec) which is supported in TCG.
    
    Now that we have a -cpu host option for ppc, it is fairly
    straightforward to fix both problems.  This patch changes the -cpu
    host code to override the basic cpu spec derived from the PVR with
    information queried from the host avout VMX, VSX and DFP capability.
    The pseries code then uses the instruction availability advertised in
    the cpu state to set the guest device tree correctly for both the KVM
    and TCG cases.
    
    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 08c7399..933af32 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -188,8 +188,6 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
                            0xffffffff, 0xffffffff};
         uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ;
         uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000;
-        uint32_t vmx = kvm_enabled() ? kvmppc_get_vmx() : 0;
-        uint32_t dfp = kvm_enabled() ? kvmppc_get_dfp() : 0;
 
         if ((index % smt) != 0) {
             continue;
@@ -241,15 +239,17 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
          *   0 / no property == no vector extensions
          *   1               == VMX / Altivec available
          *   2               == VSX available */
-        if (vmx) {
+        if (env->insns_flags & PPC_ALTIVEC) {
+            uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
+
             _FDT((fdt_property_cell(fdt, "ibm,vmx", vmx)));
         }
 
         /* Advertise DFP (Decimal Floating Point) if available
          *   0 / no property == no DFP
          *   1               == DFP available */
-        if (dfp) {
-            _FDT((fdt_property_cell(fdt, "ibm,dfp", dfp)));
+        if (env->insns_flags2 & PPC2_DFP) {
+            _FDT((fdt_property_cell(fdt, "ibm,dfp", 1)));
         }
 
         _FDT((fdt_end_node(fdt)));
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index f36f375..3ef4eba 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -858,6 +858,22 @@ enum {
 /* The whole PowerPC CPU context */
 #define NB_MMU_MODES 3
 
+struct ppc_def_t {
+    const char *name;
+    uint32_t pvr;
+    uint32_t svr;
+    uint64_t insns_flags;
+    uint64_t insns_flags2;
+    uint64_t msr_mask;
+    powerpc_mmu_t   mmu_model;
+    powerpc_excp_t  excp_model;
+    powerpc_input_t bus_model;
+    uint32_t flags;
+    int bfd_mach;
+    void (*init_proc)(CPUPPCState *env);
+    int  (*check_pow)(CPUPPCState *env);
+};
+
 struct CPUPPCState {
     /* First are the most commonly used resources
      * during translated code execution
@@ -1844,6 +1860,10 @@ enum {
 
     /* BookE 2.06 PowerPC specification                                      */
     PPC2_BOOKE206      = 0x0000000000000001ULL,
+    /* VSX (extensions to Altivec / VMX)                                     */
+    PPC2_VSX           = 0x0000000000000002ULL,
+    /* Decimal Floating Point (DFP)                                          */
+    PPC2_DFP           = 0x0000000000000004ULL,
 };
 
 /*****************************************************************************/
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 313c7b2..a090d79 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -888,14 +888,35 @@ static inline uint32_t mfpvr(void)
     return pvr;
 }
 
+static void alter_insns(uint64_t *word, uint64_t flags, bool on)
+{
+    if (on) {
+        *word |= flags;
+    } else {
+        *word &= ~flags;
+    }
+}
+
 const ppc_def_t *kvmppc_host_cpu_def(void)
 {
     uint32_t host_pvr = mfpvr();
     const ppc_def_t *base_spec;
+    ppc_def_t *spec;
+    uint32_t vmx = kvmppc_get_vmx();
+    uint32_t dfp = kvmppc_get_dfp();
 
     base_spec = ppc_find_by_pvr(host_pvr);
 
-    return base_spec;
+    spec = g_malloc0(sizeof(*spec));
+    memcpy(spec, base_spec, sizeof(*spec));
+
+    /* Now fix up the spec with information we can query from the host */
+
+    alter_insns(&spec->insns_flags, PPC_ALTIVEC, vmx > 0);
+    alter_insns(&spec->insns_flags2, PPC2_VSX, vmx > 1);
+    alter_insns(&spec->insns_flags2, PPC2_DFP, dfp);
+
+    return spec;
 }
 
 bool kvm_arch_stop_on_emulation_error(CPUState *env)
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index f0ae1d1..4dfd7f3 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -34,22 +34,6 @@
 #define TODO_USER_ONLY 1
 #endif
 
-struct ppc_def_t {
-    const char *name;
-    uint32_t pvr;
-    uint32_t svr;
-    uint64_t insns_flags;
-    uint64_t insns_flags2;
-    uint64_t msr_mask;
-    powerpc_mmu_t   mmu_model;
-    powerpc_excp_t  excp_model;
-    powerpc_input_t bus_model;
-    uint32_t flags;
-    int bfd_mach;
-    void (*init_proc)(CPUPPCState *env);
-    int  (*check_pow)(CPUPPCState *env);
-};
-
 /* For user-mode emulation, we don't emulate any IRQ controller */
 #if defined(CONFIG_USER_ONLY)
 #define PPC_IRQ_INIT_FN(name)                                                 \
@@ -6535,6 +6519,8 @@ static void init_proc_970MP (CPUPPCState *env)
                               PPC_64B | PPC_ALTIVEC |                         \
                               PPC_SEGMENT_64B | PPC_SLBI |                    \
                               PPC_POPCNTB | PPC_POPCNTWD)
+/* FIXME: Should also have PPC2_VSX and PPC2_DFP, but we don't
+ * implement those in TCG yet */
 #define POWERPC_INSNS2_POWER7 (PPC_NONE)
 #define POWERPC_MSRM_POWER7   (0x800000000204FF36ULL)
 #define POWERPC_MMU_POWER7    (POWERPC_MMU_2_06)
commit f90a9d02401eeeec18a122b61ccccb91244f321c
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Oct 18 02:10:36 2011 +0200

    PPC: Fail configure when libfdt is not available
    
    We have several targets in the PPC tree now that basically require libfdt
    to function properly, namely the pseries and the e500 targets. This dependency
    will rather increase than decrease in the future, so I want to make sure
    that people building shiny new 1.0 actually have libfdt installed to get
    rid of a few ifdefs in the code.
    
    Warning: This patch will likely make configure fail for people who don't
    select their own --target-list, but don't have libfdt development packages
    installed. However, we really need this new dependency to move on.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    
    ---
    
    v1 -> v2:
    
      - no paranthesis
      - no fdt check for config_pseries
      - add . in error message

diff --git a/configure b/configure
index f8dd4db..18537e8 100755
--- a/configure
+++ b/configure
@@ -3422,7 +3422,16 @@ case "$target_arch2" in
       fi
     fi
 esac
-if test "$target_arch2" = "ppc64" -a "$fdt" = "yes"; then
+if test "$fdt" != "yes" && test "$target_arch2" = "ppc" -o \
+        "$target_arch2" = "ppc64" -o "$target_arch2" = "ppcemb"; then
+  echo
+  echo "Error: libfdt missing"
+  echo "The PowerPC target requires libfdt to work properly."
+  echo "Please make sure to have it and its development packages installed."
+  echo
+  exit 1
+fi
+if test "$target_arch2" = "ppc64"; then
   echo "CONFIG_PSERIES=y" >> $config_target_mak
 fi
 if test "$target_bigendian" = "yes" ; then
commit 55f7d4b09e0bd1f6e5875fe0a5a58852999e4e92
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Sun Oct 16 19:26:17 2011 +0000

    ppc: Avoid decrementer related kvm exits
    
    In __cpu_ppc_store_decr(), we set up a regular timer used to trigger
    decrementer interrupts.  This is necessary to implement the decrementer
    properly under TCG, but is unnecessary under KVM (true for both Book3S-PR
    and Book3S-HV KVM variants), because the kernel handles generating and
    delivering decrementer exceptions.
    
    Under kvm, in fact, the timer causes expensive and unnecessary exits from
    kvm to qemu.  This patch, therefore, disables setting the timer when kvm
    is in use.
    
    Signed-off-by: Anton Blanchard <anton at au1.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/hw/ppc.c b/hw/ppc.c
index 25b59dd..d29af0b 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -662,6 +662,12 @@ static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
 
     LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__,
                 decr, value);
+
+    if (kvm_enabled()) {
+        /* KVM handles decrementer exceptions, we don't need our own timer */
+        return;
+    }
+
     now = qemu_get_clock_ns(vm_clock);
     next = now + muldiv64(value, get_ticks_per_sec(), tb_env->decr_freq);
     if (is_excp) {
commit f0ad8c340145b246982885addef1aac183790706
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Oct 18 02:00:51 2011 +0200

    PPC: Disable non-440 CPUs for ppcemb target
    
    The sole reason we have the ppcemb target is to support MMUs that have
    less than the usual 4k possible page size. There are very few of these
    chips and I don't want to add additional QA and testing burden to everyone
    to ensure that code still works when TARGET_PAGE_SIZE is not 4k.
    
    So this patch disables all CPUs except for MMU_BOOKE capable ones from
    the ppcemb target.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 7de097d..f0ae1d1 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -10047,11 +10047,27 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
     return 0;
 }
 
+static bool ppc_cpu_usable(const ppc_def_t *def)
+{
+#if defined(TARGET_PPCEMB)
+    /* When using the ppcemb target, we only support 440 style cores */
+    if (def->mmu_model != POWERPC_MMU_BOOKE) {
+        return false;
+    }
+#endif
+
+    return true;
+}
+
 const ppc_def_t *ppc_find_by_pvr(uint32_t pvr)
 {
     int i;
 
     for (i = 0; i < ARRAY_SIZE(ppc_defs); i++) {
+        if (!ppc_cpu_usable(&ppc_defs[i])) {
+            continue;
+        }
+
         /* If we have an exact match, we're done */
         if (pvr == ppc_defs[i].pvr) {
             return &ppc_defs[i];
@@ -10091,6 +10107,10 @@ const ppc_def_t *cpu_ppc_find_by_name (const char *name)
     ret = NULL;
     max = ARRAY_SIZE(ppc_defs);
     for (i = 0; i < max; i++) {
+        if (!ppc_cpu_usable(&ppc_defs[i])) {
+            continue;
+        }
+
         if (strcasecmp(name, ppc_defs[i].name) == 0) {
             ret = &ppc_defs[i];
             break;
@@ -10106,6 +10126,10 @@ void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf)
 
     max = ARRAY_SIZE(ppc_defs);
     for (i = 0; i < max; i++) {
+        if (!ppc_cpu_usable(&ppc_defs[i])) {
+            continue;
+        }
+
         (*cpu_fprintf)(f, "PowerPC %-16s PVR %08x\n",
                        ppc_defs[i].name, ppc_defs[i].pvr);
     }
commit 8b242eba641a6106db2d3b0356687f8e7e08e568
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Oct 18 01:46:08 2011 +0200

    PPC: Bump qemu-system-ppc to 64-bit physical address space
    
    Some 32-bit PPC CPUs can use up to 36 bit of physical address space.
    Treat them accordingly in the qemu-system-ppc binary type.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/configure b/configure
index 4f87e0a..f8dd4db 100755
--- a/configure
+++ b/configure
@@ -3309,7 +3309,7 @@ case "$target_arch2" in
   ;;
   ppc)
     gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
-    target_phys_bits=32
+    target_phys_bits=64
     target_nptl="yes"
     target_libs_softmmu="$fdt_libs"
   ;;
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 8e5c85c..f36f375 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -66,7 +66,7 @@
 #define TARGET_PAGE_BITS 12
 #endif /* defined(TARGET_PPCEMB) */
 
-#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_PHYS_ADDR_SPACE_BITS 36
 #define TARGET_VIRT_ADDR_SPACE_BITS 32
 
 #endif /* defined (TARGET_PPC64) */
commit 6b7a2cf6d93294a4e7c79fe101d31fc19d04fb48
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Wed Oct 12 22:40:34 2011 +0000

    pseries: Under kvm use guest cpu = host cpu by default
    
    Now that we've implemented -cpu host for ppc, this patch updates the
    pseries machine to use the host cpu as the guest cpu by default when
    running under KVM.  This is important because under KVM Book3S-HV the guest
    cpu _cannot_ be of a different type to the host cpu (at the moment
    KVM Book3S-HV will silently virtualize the host cpu instead of whatever was
    requested, but in future it is likely to simply refuse to run the VM if
    a cpu model other than the host's is requested).
    
    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 4d2a55e..08c7399 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -406,7 +406,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
 
     /* init CPUs */
     if (cpu_model == NULL) {
-        cpu_model = "POWER7";
+        cpu_model = kvm_enabled() ? "host" : "POWER7";
     }
     for (i = 0; i < smp_cpus; i++) {
         env = cpu_init(cpu_model);
commit 37e305ce167279307335b069bff7e254b858fa6b
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Wed Oct 12 22:40:33 2011 +0000

    ppc: Add cpu defs for POWER7 revisions 2.1 and 2.3
    
    This patch adds cpu specs to the table for POWER7 revisions 2.1 and 2.3.
    This allows -cpu host to be used on these host cpus.
    
    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/translate_init.c b/target-ppc/translate_init.c
index 62f0a6b..7de097d 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7333,6 +7333,8 @@ enum {
     CPU_POWERPC_POWER6A            = 0x0F000002,
 #define CPU_POWERPC_POWER7           CPU_POWERPC_POWER7_v20
     CPU_POWERPC_POWER7_v20         = 0x003F0200,
+    CPU_POWERPC_POWER7_v21         = 0x003F0201,
+    CPU_POWERPC_POWER7_v23         = 0x003F0203,
     CPU_POWERPC_970                = 0x00390202,
 #define CPU_POWERPC_970FX            CPU_POWERPC_970FX_v31
     CPU_POWERPC_970FX_v10          = 0x00391100,
@@ -9139,6 +9141,8 @@ static const ppc_def_t ppc_defs[] = {
     /* POWER7                                                                */
     POWERPC_DEF("POWER7",        CPU_POWERPC_POWER7,                 POWER7),
     POWERPC_DEF("POWER7_v2.0",   CPU_POWERPC_POWER7_v20,             POWER7),
+    POWERPC_DEF("POWER7_v2.1",   CPU_POWERPC_POWER7_v21,             POWER7),
+    POWERPC_DEF("POWER7_v2.3",   CPU_POWERPC_POWER7_v23,             POWER7),
     /* PowerPC 970                                                           */
     POWERPC_DEF("970",           CPU_POWERPC_970,                    970),
     /* PowerPC 970FX (G5)                                                    */
commit a1e985833cde3208b0f57c4c7e640b60fbc6c54d
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Wed Oct 12 22:40:32 2011 +0000

    ppc: First cut implementation of -cpu host
    
    For convenience with kvm, x86 allows the user to specify -cpu host on the
    qemu command line, which means make the guest cpu the same as the host
    cpu.  This patch implements the same option for ppc targets.
    
    For now, this just read the host PVR (Processor Version Register) and
    selects one of our existing CPU specs based on it.  This means that the
    option will not work if the host cpu is not supported by TCG, even if that
    wouldn't matter for use under kvm.
    
    In future, we can extend this in future to override parts of the cpu spec
    based on information obtained from the host (via /proc/cpuinfo, the host
    device tree, or explicit KVM calls).  That will let us handle cases where
    the real kvm-virtualized CPU doesn't behave exactly like the TCG-emulated
    CPU.  With appropriate annotation of the CPU specs we'll also then be able
    to use host cpus under kvm even when there isn't a matching full TCG model.
    
    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 3f77e30..8e5c85c 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1107,6 +1107,7 @@ void ppc_store_msr (CPUPPCState *env, target_ulong value);
 
 void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf);
 
+const ppc_def_t *ppc_find_by_pvr(uint32_t pvr);
 const ppc_def_t *cpu_ppc_find_by_name (const char *name);
 int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def);
 
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 96139ac..313c7b2 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -879,6 +879,25 @@ int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t window_size)
     return 0;
 }
 
+static inline uint32_t mfpvr(void)
+{
+    uint32_t pvr;
+
+    asm ("mfpvr %0"
+         : "=r"(pvr));
+    return pvr;
+}
+
+const ppc_def_t *kvmppc_host_cpu_def(void)
+{
+    uint32_t host_pvr = mfpvr();
+    const ppc_def_t *base_spec;
+
+    base_spec = ppc_find_by_pvr(host_pvr);
+
+    return base_spec;
+}
+
 bool kvm_arch_stop_on_emulation_error(CPUState *env)
 {
     return true;
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 955729a..b0d6fb6 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -26,6 +26,7 @@ int kvmppc_smt_threads(void);
 off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem);
 void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd);
 int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size);
+const ppc_def_t *kvmppc_host_cpu_def(void);
 
 #else
 
@@ -85,6 +86,11 @@ static inline int kvmppc_remove_spapr_tce(void *table, int pfd,
     return -1;
 }
 
+static inline const ppc_def_t *kvmppc_host_cpu_def(void)
+{
+    return NULL;
+}
+
 #endif
 
 #ifndef CONFIG_KVM
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 73b49cf..62f0a6b 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -24,6 +24,8 @@
 
 #include "dis-asm.h"
 #include "gdbstub.h"
+#include <kvm.h>
+#include "kvm_ppc.h"
 
 //#define PPC_DUMP_CPU
 //#define PPC_DEBUG_SPR
@@ -10041,7 +10043,7 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
     return 0;
 }
 
-static const ppc_def_t *ppc_find_by_pvr (uint32_t pvr)
+const ppc_def_t *ppc_find_by_pvr(uint32_t pvr)
 {
     int i;
 
@@ -10063,6 +10065,10 @@ const ppc_def_t *cpu_ppc_find_by_name (const char *name)
     const char *p;
     int i, max, len;
 
+    if (kvm_enabled() && (strcasecmp(name, "host") == 0)) {
+        return kvmppc_host_cpu_def();
+    }
+
     /* Check if the given name is a PVR */
     len = strlen(name);
     if (len == 10 && name[0] == '0' && name[1] == 'x') {
commit be40edcd87b8493cdf691dbe77049e0d9644dcc1
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Wed Oct 12 22:40:31 2011 +0000

    ppc: Remove broken partial PVR matching
    
    The ppc target contains a ppc_find_by_pvr() function, which looks up a
    CPU spec based on a PVR (that is, based on the value in the target cpu's
    Processor Version Register).  PVR values contain information on both the
    cpu model (upper 16 bits, usually) and on the precise revision (low 16
    bits, usually).
    
    ppc_find_by_pvr, as well as making exact PVR matches, attempts to find
    "close" PVR matches, when we don't have a CPU spec for the exact revision
    specified.  This sounds like a good idea, execpt that the current logic
    is completely nonsensical.
    
    It seems to assume CPU families are subdivided bit by bit in the PVR in a
    way they just aren't.  Specifically, it requires a match on all bits of the
    specified pvr up to the last non-zero bit.  This has the bizarre effect
    that when the low bits are simply a sequential revision number (a common
    though not universal pattern), then odd specified revisions must be matched
    exactly, whereas even specified revisions will also match the next odd
    revision, likewise for powers of 4, 8 and so forth.
    
    To correctly do inexact matching we'd need to re-organize the table of CPU
    specs to include a mask showing what PVR range the spec is compatible with
    (similar to the cputable code in the Linux kernel).
    
    For now, just remove the bogosity by only permitting exact PVR matches.
    That at least makes the matching simple and consistent.  If we need inexact
    matching we can add the necessary per-subfamily masks later.
    
    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/translate_init.c b/target-ppc/translate_init.c
index ca0d852..73b49cf 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -10043,40 +10043,16 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
 
 static const ppc_def_t *ppc_find_by_pvr (uint32_t pvr)
 {
-    const ppc_def_t *ret;
-    uint32_t pvr_rev;
-    int i, best, match, best_match, max;
+    int i;
 
-    ret = NULL;
-    max = ARRAY_SIZE(ppc_defs);
-    best = -1;
-    pvr_rev = pvr & 0xFFFF;
-    /* We want all specified bits to match */
-    best_match = 32 - ctz32(pvr_rev);
-    for (i = 0; i < max; i++) {
-        /* We check that the 16 higher bits are the same to ensure the CPU
-         * model will be the choosen one.
-         */
-        if (((pvr ^ ppc_defs[i].pvr) >> 16) == 0) {
-            /* We want as much as possible of the low-level 16 bits
-             * to be the same but we allow inexact matches.
-             */
-            match = clz32(pvr_rev ^ (ppc_defs[i].pvr & 0xFFFF));
-            /* We check '>=' instead of '>' because the PPC_defs table
-             * is ordered by increasing revision.
-             * Then, we will match the higher revision compatible
-             * with the requested PVR
-             */
-            if (match >= best_match) {
-                best = i;
-                best_match = match;
-            }
+    for (i = 0; i < ARRAY_SIZE(ppc_defs); i++) {
+        /* If we have an exact match, we're done */
+        if (pvr == ppc_defs[i].pvr) {
+            return &ppc_defs[i];
         }
     }
-    if (best != -1)
-        ret = &ppc_defs[best];
 
-    return ret;
+    return NULL;
 }
 
 #include <ctype.h>
commit d20dfdd4d21d7cae2cbc29e91674ea45f4a025d6
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Wed Oct 12 19:10:30 2011 +0000

    pseries: Update SLOF firmware image
    
    This patch is a general update to the SLOF firmware image used on the
    pseries machine.  This doesn't contain updates for specific features but
    contains a number of bugfixes and enhancements in the main SLOF tree from
    Thomas Huth.
    
    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 32a438e..0668559 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-20110930.
+  built from git tag qemu-slof-20111013.
 
 - The PXE roms come from the iPXE project. Built with BANNER_TIME 0.
   Sources available at http://ipxe.org.  Vendor:Device ID -> ROM mapping:
diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin
index b9d4f35..1e84582 100644
Binary files a/pc-bios/slof.bin and b/pc-bios/slof.bin differ
diff --git a/roms/SLOF b/roms/SLOF
index b94bde0..32e3430 160000
--- a/roms/SLOF
+++ b/roms/SLOF
@@ -1 +1 @@
-Subproject commit b94bde008b0d49ec4bfe933e110d0952d032ac28
+Subproject commit 32e3430c018ceb8413cb808477449d1968c42497
commit 6659394fa1fa20aa640efa42c8fa5ee6994b6286
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Oct 10 18:31:01 2011 +0000

    pseries: Add device tree properties for VMX/VSX and DFP under kvm
    
    Sufficiently recent PAPR specifications define properties "ibm,vmx"
    and "ibm,dfp" on the CPU node which advertise whether the VMX vector
    extensions (or the later VSX version) and/or the Decimal Floating
    Point operations from IBM's recent POWER CPUs are available.
    
    Currently we do not put these in the guest device tree and the guest
    kernel will consequently assume they are not available.  This is good,
    because they are not supported under TCG.  VMX is similar enough to
    Altivec that it might be trivial to support, but VSX and DFP would
    both require significant work to support in TCG.
    
    However, when running under kvm on a host which supports these
    instructions, there's no reason not to let the guest use them.  This
    patch, therefore, checks for the relevant support on the host CPU
    and, if present, advertises them to the guest as well.
    
    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 193398b..4d2a55e 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -188,6 +188,8 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
                            0xffffffff, 0xffffffff};
         uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ;
         uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000;
+        uint32_t vmx = kvm_enabled() ? kvmppc_get_vmx() : 0;
+        uint32_t dfp = kvm_enabled() ? kvmppc_get_dfp() : 0;
 
         if ((index % smt) != 0) {
             continue;
@@ -235,6 +237,21 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
                                segs, sizeof(segs))));
         }
 
+        /* Advertise VMX/VSX (vector extensions) if available
+         *   0 / no property == no vector extensions
+         *   1               == VMX / Altivec available
+         *   2               == VSX available */
+        if (vmx) {
+            _FDT((fdt_property_cell(fdt, "ibm,vmx", vmx)));
+        }
+
+        /* Advertise DFP (Decimal Floating Point) if available
+         *   0 / no property == no DFP
+         *   1               == DFP available */
+        if (dfp) {
+            _FDT((fdt_property_cell(fdt, "ibm,dfp", dfp)));
+        }
+
         _FDT((fdt_end_node(fdt)));
     }
 
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index c48cd76..96139ac 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -694,6 +694,16 @@ uint64_t kvmppc_get_clockfreq(void)
     return kvmppc_read_int_cpu_dt("clock-frequency");
 }
 
+uint32_t kvmppc_get_vmx(void)
+{
+    return kvmppc_read_int_cpu_dt("ibm,vmx");
+}
+
+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)
 {
     uint32_t *hc = (uint32_t*)buf;
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 87d1bdd..955729a 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -17,6 +17,8 @@ void kvmppc_init(void);
 
 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);
@@ -37,6 +39,16 @@ static inline uint64_t kvmppc_get_clockfreq(void)
     return 0;
 }
 
+static inline uint32_t kvmppc_get_vmx(void)
+{
+    return 0;
+}
+
+static inline uint32_t kvmppc_get_dfp(void)
+{
+    return 0;
+}
+
 static inline int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len)
 {
     return -1;
commit 9bc884b741d3ab5bc3471a5cbccc38480676bf2b
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Oct 10 18:31:00 2011 +0000

    ppc: Generalize the kvmppc_get_clockfreq() function
    
    Currently the kvmppc_get_clockfreq() function reads the host's clock
    frequency from /proc/device-tree, which is useful to past to the guest
    in KVM setups.  However, there are some other host properties
    advertised in the device tree which can also be relevant to the
    guests.
    
    This patch, therefore, replaces kvmppc_get_clockfreq() which can
    retrieve any named, single integer property from the host device
    tree's CPU node.
    
    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 06cad41..c48cd76 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -650,37 +650,50 @@ static int kvmppc_find_cpu_dt(char *buf, int buf_len)
     return 0;
 }
 
-uint64_t kvmppc_get_clockfreq(void)
+/* Read a CPU node property from the host device tree that's a single
+ * integer (32-bit or 64-bit).  Returns 0 if anything goes wrong
+ * (can't find or open the property, or doesn't understand the
+ * format) */
+static uint64_t kvmppc_read_int_cpu_dt(const char *propname)
 {
-    char buf[512];
-    uint32_t tb[2];
+    char buf[PATH_MAX];
+    union {
+        uint32_t v32;
+        uint64_t v64;
+    } u;
     FILE *f;
     int len;
 
     if (kvmppc_find_cpu_dt(buf, sizeof(buf))) {
-        return 0;
+        return -1;
     }
 
-    strncat(buf, "/clock-frequency", sizeof(buf) - strlen(buf));
+    strncat(buf, "/", sizeof(buf) - strlen(buf));
+    strncat(buf, propname, sizeof(buf) - strlen(buf));
 
     f = fopen(buf, "rb");
     if (!f) {
         return -1;
     }
 
-    len = fread(tb, sizeof(tb[0]), 2, f);
+    len = fread(&u, 1, sizeof(u), f);
     fclose(f);
     switch (len) {
-    case 1:
-        /* freq is only a single cell */
-        return tb[0];
-    case 2:
-        return *(uint64_t*)tb;
+    case 4:
+        /* property is a 32-bit quantity */
+        return be32_to_cpu(u.v32);
+    case 8:
+        return be64_to_cpu(u.v64);
     }
 
     return 0;
 }
 
+uint64_t kvmppc_get_clockfreq(void)
+{
+    return kvmppc_read_int_cpu_dt("clock-frequency");
+}
+
 int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len)
 {
     uint32_t *hc = (uint32_t*)buf;
commit 70560da79d5be611bd7867f9c590847702c61fb5
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Wed Sep 28 05:54:05 2011 +0000

    Set an invalid-bits mask for each SPE instructions
    
    SPE instructions are defined by pairs. Currently, the invalid-bits mask is set
    for the first instruction, but the second one can have a different mask.
    
    example:
    GEN_SPE(efdcmpeq,    efdcfs,      0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE),
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 1e362fc..99e995c 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -205,8 +205,10 @@ typedef struct DisasContext {
 } DisasContext;
 
 struct opc_handler_t {
-    /* invalid bits */
-    uint32_t inval;
+    /* invalid bits for instruction 1 (Rc(opcode) == 0) */
+    uint32_t inval1;
+    /* invalid bits for instruction 2 (Rc(opcode) == 1) */
+    uint32_t inval2;
     /* instruction type */
     uint64_t type;
     /* extended instruction type */
@@ -478,7 +480,23 @@ static inline target_ulong MASK(uint32_t start, uint32_t end)
     .opc3 = op3,                                                              \
     .pad  = { 0, },                                                           \
     .handler = {                                                              \
-        .inval   = invl,                                                      \
+        .inval1  = invl,                                                      \
+        .type = _typ,                                                         \
+        .type2 = _typ2,                                                       \
+        .handler = &gen_##name,                                               \
+        .oname = stringify(name),                                             \
+    },                                                                        \
+    .oname = stringify(name),                                                 \
+}
+#define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2)       \
+{                                                                             \
+    .opc1 = op1,                                                              \
+    .opc2 = op2,                                                              \
+    .opc3 = op3,                                                              \
+    .pad  = { 0, },                                                           \
+    .handler = {                                                              \
+        .inval1  = invl1,                                                     \
+        .inval2  = invl2,                                                     \
         .type = _typ,                                                         \
         .type2 = _typ2,                                                       \
         .handler = &gen_##name,                                               \
@@ -493,7 +511,7 @@ static inline target_ulong MASK(uint32_t start, uint32_t end)
     .opc3 = op3,                                                              \
     .pad  = { 0, },                                                           \
     .handler = {                                                              \
-        .inval   = invl,                                                      \
+        .inval1  = invl,                                                      \
         .type = _typ,                                                         \
         .type2 = _typ2,                                                       \
         .handler = &gen_##name,                                               \
@@ -509,7 +527,22 @@ static inline target_ulong MASK(uint32_t start, uint32_t end)
     .opc3 = op3,                                                              \
     .pad  = { 0, },                                                           \
     .handler = {                                                              \
-        .inval   = invl,                                                      \
+        .inval1  = invl,                                                      \
+        .type = _typ,                                                         \
+        .type2 = _typ2,                                                       \
+        .handler = &gen_##name,                                               \
+    },                                                                        \
+    .oname = stringify(name),                                                 \
+}
+#define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2)       \
+{                                                                             \
+    .opc1 = op1,                                                              \
+    .opc2 = op2,                                                              \
+    .opc3 = op3,                                                              \
+    .pad  = { 0, },                                                           \
+    .handler = {                                                              \
+        .inval1  = invl1,                                                     \
+        .inval2  = invl2,                                                     \
         .type = _typ,                                                         \
         .type2 = _typ2,                                                       \
         .handler = &gen_##name,                                               \
@@ -523,7 +556,7 @@ static inline target_ulong MASK(uint32_t start, uint32_t end)
     .opc3 = op3,                                                              \
     .pad  = { 0, },                                                           \
     .handler = {                                                              \
-        .inval   = invl,                                                      \
+        .inval1  = invl,                                                      \
         .type = _typ,                                                         \
         .type2 = _typ2,                                                       \
         .handler = &gen_##name,                                               \
@@ -550,7 +583,8 @@ static void gen_invalid(DisasContext *ctx)
 }
 
 static opc_handler_t invalid_handler = {
-    .inval   = 0xFFFFFFFF,
+    .inval1  = 0xFFFFFFFF,
+    .inval2  = 0xFFFFFFFF,
     .type    = PPC_NONE,
     .type2   = PPC_NONE,
     .handler = gen_invalid,
@@ -6693,7 +6727,7 @@ static inline void gen_store_gpr64(int reg, TCGv_i64 t)
 #endif
 }
 
-#define GEN_SPE(name0, name1, opc2, opc3, inval, type)                        \
+#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type)         \
 static void glue(gen_, name0##_##name1)(DisasContext *ctx)                    \
 {                                                                             \
     if (Rc(ctx->opcode))                                                      \
@@ -7416,35 +7450,35 @@ static inline void gen_evmwsmiaa(DisasContext *ctx)
     tcg_temp_free_i64(tmp);
 }
 
-GEN_SPE(evaddw,         speundef,      0x00, 0x08, 0x00000000, PPC_SPE); ////
-GEN_SPE(evaddiw,        speundef,      0x01, 0x08, 0x00000000, PPC_SPE);
-GEN_SPE(evsubfw,        speundef,      0x02, 0x08, 0x00000000, PPC_SPE); ////
-GEN_SPE(evsubifw,       speundef,      0x03, 0x08, 0x00000000, PPC_SPE);
-GEN_SPE(evabs,          evneg,         0x04, 0x08, 0x0000F800, PPC_SPE); ////
-GEN_SPE(evextsb,        evextsh,       0x05, 0x08, 0x0000F800, PPC_SPE); ////
-GEN_SPE(evrndw,         evcntlzw,      0x06, 0x08, 0x0000F800, PPC_SPE); ////
-GEN_SPE(evcntlsw,       brinc,         0x07, 0x08, 0x00000000, PPC_SPE); //
-GEN_SPE(evmra,          speundef,      0x02, 0x13, 0x0000F800, PPC_SPE);
-GEN_SPE(speundef,       evand,         0x08, 0x08, 0x00000000, PPC_SPE); ////
-GEN_SPE(evandc,         speundef,      0x09, 0x08, 0x00000000, PPC_SPE); ////
-GEN_SPE(evxor,          evor,          0x0B, 0x08, 0x00000000, PPC_SPE); ////
-GEN_SPE(evnor,          eveqv,         0x0C, 0x08, 0x00000000, PPC_SPE); ////
-GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE);
-GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE);
-GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evorc,         0x0D, 0x08, 0x00000000, PPC_SPE); ////
-GEN_SPE(evnand,         speundef,      0x0F, 0x08, 0x00000000, PPC_SPE); ////
-GEN_SPE(evsrwu,         evsrws,        0x10, 0x08, 0x00000000, PPC_SPE); ////
-GEN_SPE(evsrwiu,        evsrwis,       0x11, 0x08, 0x00000000, PPC_SPE);
-GEN_SPE(evslw,          speundef,      0x12, 0x08, 0x00000000, PPC_SPE); ////
-GEN_SPE(evslwi,         speundef,      0x13, 0x08, 0x00000000, PPC_SPE);
-GEN_SPE(evrlw,          evsplati,      0x14, 0x08, 0x00000000, PPC_SPE); //
-GEN_SPE(evrlwi,         evsplatfi,     0x15, 0x08, 0x00000000, PPC_SPE);
-GEN_SPE(evmergehi,      evmergelo,     0x16, 0x08, 0x00000000, PPC_SPE); ////
-GEN_SPE(evmergehilo,    evmergelohi,   0x17, 0x08, 0x00000000, PPC_SPE); ////
-GEN_SPE(evcmpgtu,       evcmpgts,      0x18, 0x08, 0x00600000, PPC_SPE); ////
-GEN_SPE(evcmpltu,       evcmplts,      0x19, 0x08, 0x00600000, PPC_SPE); ////
-GEN_SPE(evcmpeq,        speundef,      0x1A, 0x08, 0x00600000, PPC_SPE); ////
+GEN_SPE(evaddw,      speundef,    0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
+GEN_SPE(evaddiw,     speundef,    0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
+GEN_SPE(evsubfw,     speundef,    0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
+GEN_SPE(evsubifw,    speundef,    0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
+GEN_SPE(evabs,       evneg,       0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
+GEN_SPE(evextsb,     evextsh,     0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
+GEN_SPE(evrndw,      evcntlzw,    0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
+GEN_SPE(evcntlsw,    brinc,       0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE); //
+GEN_SPE(evmra,       speundef,    0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE);
+GEN_SPE(speundef,    evand,       0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); ////
+GEN_SPE(evandc,      speundef,    0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
+GEN_SPE(evxor,       evor,        0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
+GEN_SPE(evnor,       eveqv,       0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
+GEN_SPE(evmwumi,     evmwsmi,     0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(evmwumia,    evmwsmia,    0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(evmwumiaa,   evmwsmiaa,   0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,    evorc,       0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); ////
+GEN_SPE(evnand,      speundef,    0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
+GEN_SPE(evsrwu,      evsrws,      0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
+GEN_SPE(evsrwiu,     evsrwis,     0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(evslw,       speundef,    0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
+GEN_SPE(evslwi,      speundef,    0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
+GEN_SPE(evrlw,       evsplati,    0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE); //
+GEN_SPE(evrlwi,      evsplatfi,   0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE);
+GEN_SPE(evmergehi,   evmergelo,   0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
+GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
+GEN_SPE(evcmpgtu,    evcmpgts,    0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE); ////
+GEN_SPE(evcmpltu,    evcmplts,    0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE); ////
+GEN_SPE(evcmpeq,     speundef,    0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE); ////
 
 /* SPE load and stores */
 static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
@@ -7803,74 +7837,74 @@ GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
 
 /* Multiply and add - TODO */
 #if 0
-GEN_SPE(speundef,       evmhessf,      0x01, 0x10, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhossf,      0x03, 0x10, 0x00000000, PPC_SPE);
-GEN_SPE(evmheumi,       evmhesmi,      0x04, 0x10, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhesmf,      0x05, 0x10, 0x00000000, PPC_SPE);
-GEN_SPE(evmhoumi,       evmhosmi,      0x06, 0x10, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhosmf,      0x07, 0x10, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhessfa,     0x11, 0x10, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhossfa,     0x13, 0x10, 0x00000000, PPC_SPE);
-GEN_SPE(evmheumia,      evmhesmia,     0x14, 0x10, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhesmfa,     0x15, 0x10, 0x00000000, PPC_SPE);
-GEN_SPE(evmhoumia,      evmhosmia,     0x16, 0x10, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhosmfa,     0x17, 0x10, 0x00000000, PPC_SPE);
-
-GEN_SPE(speundef,       evmwhssf,      0x03, 0x11, 0x00000000, PPC_SPE);
-GEN_SPE(evmwlumi,       speundef,      0x04, 0x11, 0x00000000, PPC_SPE);
-GEN_SPE(evmwhumi,       evmwhsmi,      0x06, 0x11, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmwhsmf,      0x07, 0x11, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmwssf,       0x09, 0x11, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmwsmf,       0x0D, 0x11, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmwhssfa,     0x13, 0x11, 0x00000000, PPC_SPE);
-GEN_SPE(evmwlumia,      speundef,      0x14, 0x11, 0x00000000, PPC_SPE);
-GEN_SPE(evmwhumia,      evmwhsmia,     0x16, 0x11, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmwhsmfa,     0x17, 0x11, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmwssfa,      0x19, 0x11, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmwsmfa,      0x1D, 0x11, 0x00000000, PPC_SPE);
-
-GEN_SPE(evadduiaaw,     evaddsiaaw,    0x00, 0x13, 0x0000F800, PPC_SPE);
-GEN_SPE(evsubfusiaaw,   evsubfssiaaw,  0x01, 0x13, 0x0000F800, PPC_SPE);
-GEN_SPE(evaddumiaaw,    evaddsmiaaw,   0x04, 0x13, 0x0000F800, PPC_SPE);
-GEN_SPE(evsubfumiaaw,   evsubfsmiaaw,  0x05, 0x13, 0x0000F800, PPC_SPE);
-GEN_SPE(evdivws,        evdivwu,       0x06, 0x13, 0x00000000, PPC_SPE);
-
-GEN_SPE(evmheusiaaw,    evmhessiaaw,   0x00, 0x14, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhessfaaw,   0x01, 0x14, 0x00000000, PPC_SPE);
-GEN_SPE(evmhousiaaw,    evmhossiaaw,   0x02, 0x14, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhossfaaw,   0x03, 0x14, 0x00000000, PPC_SPE);
-GEN_SPE(evmheumiaaw,    evmhesmiaaw,   0x04, 0x14, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhesmfaaw,   0x05, 0x14, 0x00000000, PPC_SPE);
-GEN_SPE(evmhoumiaaw,    evmhosmiaaw,   0x06, 0x14, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhosmfaaw,   0x07, 0x14, 0x00000000, PPC_SPE);
-GEN_SPE(evmhegumiaa,    evmhegsmiaa,   0x14, 0x14, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhegsmfaa,   0x15, 0x14, 0x00000000, PPC_SPE);
-GEN_SPE(evmhogumiaa,    evmhogsmiaa,   0x16, 0x14, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhogsmfaa,   0x17, 0x14, 0x00000000, PPC_SPE);
-
-GEN_SPE(evmwlusiaaw,    evmwlssiaaw,   0x00, 0x15, 0x00000000, PPC_SPE);
-GEN_SPE(evmwlumiaaw,    evmwlsmiaaw,   0x04, 0x15, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmwssfaa,     0x09, 0x15, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmwsmfaa,     0x0D, 0x15, 0x00000000, PPC_SPE);
-
-GEN_SPE(evmheusianw,    evmhessianw,   0x00, 0x16, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhessfanw,   0x01, 0x16, 0x00000000, PPC_SPE);
-GEN_SPE(evmhousianw,    evmhossianw,   0x02, 0x16, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhossfanw,   0x03, 0x16, 0x00000000, PPC_SPE);
-GEN_SPE(evmheumianw,    evmhesmianw,   0x04, 0x16, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhesmfanw,   0x05, 0x16, 0x00000000, PPC_SPE);
-GEN_SPE(evmhoumianw,    evmhosmianw,   0x06, 0x16, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhosmfanw,   0x07, 0x16, 0x00000000, PPC_SPE);
-GEN_SPE(evmhegumian,    evmhegsmian,   0x14, 0x16, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhegsmfan,   0x15, 0x16, 0x00000000, PPC_SPE);
-GEN_SPE(evmhigumian,    evmhigsmian,   0x16, 0x16, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmhogsmfan,   0x17, 0x16, 0x00000000, PPC_SPE);
-
-GEN_SPE(evmwlusianw,    evmwlssianw,   0x00, 0x17, 0x00000000, PPC_SPE);
-GEN_SPE(evmwlumianw,    evmwlsmianw,   0x04, 0x17, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmwssfan,     0x09, 0x17, 0x00000000, PPC_SPE);
-GEN_SPE(evmwumian,      evmwsmian,     0x0C, 0x17, 0x00000000, PPC_SPE);
-GEN_SPE(speundef,       evmwsmfan,     0x0D, 0x17, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhessf,      0x01, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);//
+GEN_SPE(speundef,       evmhossf,      0x03, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(evmheumi,       evmhesmi,      0x04, 0x10, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhesmf,      0x05, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(evmhoumi,       evmhosmi,      0x06, 0x10, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhosmf,      0x07, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhessfa,     0x11, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhossfa,     0x13, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(evmheumia,      evmhesmia,     0x14, 0x10, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhesmfa,     0x15, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(evmhoumia,      evmhosmia,     0x16, 0x10, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhosmfa,     0x17, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+
+GEN_SPE(speundef,       evmwhssf,      0x03, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(evmwlumi,       speundef,      0x04, 0x11, 0x00000000, 0xFFFFFFFF, PPC_SPE);
+GEN_SPE(evmwhumi,       evmwhsmi,      0x06, 0x11, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwhsmf,      0x07, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwssf,       0x09, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwsmf,       0x0D, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwhssfa,     0x13, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(evmwlumia,      speundef,      0x14, 0x11, 0x00000000, 0xFFFFFFFF, PPC_SPE);
+GEN_SPE(evmwhumia,      evmwhsmia,     0x16, 0x11, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwhsmfa,     0x17, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwssfa,      0x19, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwsmfa,      0x1D, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+
+GEN_SPE(evadduiaaw,     evaddsiaaw,    0x00, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
+GEN_SPE(evsubfusiaaw,   evsubfssiaaw,  0x01, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
+GEN_SPE(evaddumiaaw,    evaddsmiaaw,   0x04, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
+GEN_SPE(evsubfumiaaw,   evsubfsmiaaw,  0x05, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
+GEN_SPE(evdivws,        evdivwu,       0x06, 0x13, 0x00000000, 0x00000000, PPC_SPE);
+
+GEN_SPE(evmheusiaaw,    evmhessiaaw,   0x00, 0x14, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhessfaaw,   0x01, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(evmhousiaaw,    evmhossiaaw,   0x02, 0x14, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhossfaaw,   0x03, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(evmheumiaaw,    evmhesmiaaw,   0x04, 0x14, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhesmfaaw,   0x05, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(evmhoumiaaw,    evmhosmiaaw,   0x06, 0x14, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhosmfaaw,   0x07, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(evmhegumiaa,    evmhegsmiaa,   0x14, 0x14, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhegsmfaa,   0x15, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(evmhogumiaa,    evmhogsmiaa,   0x16, 0x14, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhogsmfaa,   0x17, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+
+GEN_SPE(evmwlusiaaw,    evmwlssiaaw,   0x00, 0x15, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(evmwlumiaaw,    evmwlsmiaaw,   0x04, 0x15, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwssfaa,     0x09, 0x15, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwsmfaa,     0x0D, 0x15, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+
+GEN_SPE(evmheusianw,    evmhessianw,   0x00, 0x16, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhessfanw,   0x01, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(evmhousianw,    evmhossianw,   0x02, 0x16, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhossfanw,   0x03, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(evmheumianw,    evmhesmianw,   0x04, 0x16, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhesmfanw,   0x05, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(evmhoumianw,    evmhosmianw,   0x06, 0x16, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhosmfanw,   0x07, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(evmhegumian,    evmhegsmian,   0x14, 0x16, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhegsmfan,   0x15, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(evmhigumian,    evmhigsmian,   0x16, 0x16, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhogsmfan,   0x17, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+
+GEN_SPE(evmwlusianw,    evmwlssianw,   0x00, 0x17, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(evmwlumianw,    evmwlsmianw,   0x04, 0x17, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwssfan,     0x09, 0x17, 0xFFFFFFFF, 0x00000000, PPC_SPE);
+GEN_SPE(evmwumian,      evmwsmian,     0x0C, 0x17, 0x00000000, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwsmfan,     0x0D, 0x17, 0xFFFFFFFF, 0x00000000, PPC_SPE);
 #endif
 
 /***                      SPE floating-point extension                     ***/
@@ -8131,20 +8165,20 @@ GEN_SPEFPUOP_COMP_64(evfststlt);
 GEN_SPEFPUOP_COMP_64(evfststeq);
 
 /* Opcodes definitions */
-GEN_SPE(evfsadd,        evfssub,       0x00, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
-GEN_SPE(evfsabs,        evfsnabs,      0x02, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
-GEN_SPE(evfsneg,        speundef,      0x03, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
-GEN_SPE(evfsmul,        evfsdiv,       0x04, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
-GEN_SPE(evfscmpgt,      evfscmplt,     0x06, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
-GEN_SPE(evfscmpeq,      speundef,      0x07, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
-GEN_SPE(evfscfui,       evfscfsi,      0x08, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
-GEN_SPE(evfscfuf,       evfscfsf,      0x09, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
-GEN_SPE(evfsctui,       evfsctsi,      0x0A, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
-GEN_SPE(evfsctuf,       evfsctsf,      0x0B, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
-GEN_SPE(evfsctuiz,      speundef,      0x0C, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
-GEN_SPE(evfsctsiz,      speundef,      0x0D, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
-GEN_SPE(evfststgt,      evfststlt,     0x0E, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
-GEN_SPE(evfststeq,      speundef,      0x0F, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
+GEN_SPE(evfsadd,   evfssub,   0x00, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
+GEN_SPE(evfsabs,   evfsnabs,  0x02, 0x0A, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); //
+GEN_SPE(evfsneg,   speundef,  0x03, 0x0A, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); //
+GEN_SPE(evfsmul,   evfsdiv,   0x04, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
+GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
+GEN_SPE(evfscmpeq, speundef,  0x07, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
+GEN_SPE(evfscfui,  evfscfsi,  0x08, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(evfscfuf,  evfscfsf,  0x09, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(evfsctui,  evfsctsi,  0x0A, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(evfsctuf,  evfsctsf,  0x0B, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(evfsctuiz, speundef,  0x0C, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
+GEN_SPE(evfsctsiz, speundef,  0x0D, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
+GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
+GEN_SPE(evfststeq, speundef,  0x0F, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
 
 /* Single precision floating-point operations */
 /* Arithmetic */
@@ -8199,20 +8233,20 @@ GEN_SPEFPUOP_COMP_32(efststlt);
 GEN_SPEFPUOP_COMP_32(efststeq);
 
 /* Opcodes definitions */
-GEN_SPE(efsadd,         efssub,        0x00, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
-GEN_SPE(efsabs,         efsnabs,       0x02, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
-GEN_SPE(efsneg,         speundef,      0x03, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
-GEN_SPE(efsmul,         efsdiv,        0x04, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
-GEN_SPE(efscmpgt,       efscmplt,      0x06, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
-GEN_SPE(efscmpeq,       efscfd,        0x07, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
-GEN_SPE(efscfui,        efscfsi,       0x08, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
-GEN_SPE(efscfuf,        efscfsf,       0x09, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
-GEN_SPE(efsctui,        efsctsi,       0x0A, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
-GEN_SPE(efsctuf,        efsctsf,       0x0B, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
-GEN_SPE(efsctuiz,       speundef,      0x0C, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
-GEN_SPE(efsctsiz,       speundef,      0x0D, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
-GEN_SPE(efststgt,       efststlt,      0x0E, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
-GEN_SPE(efststeq,       speundef,      0x0F, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
+GEN_SPE(efsadd,   efssub,   0x00, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
+GEN_SPE(efsabs,   efsnabs,  0x02, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); //
+GEN_SPE(efsneg,   speundef, 0x03, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); //
+GEN_SPE(efsmul,   efsdiv,   0x04, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
+GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
+GEN_SPE(efscmpeq, efscfd,   0x07, 0x0B, 0x00600000, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(efscfui,  efscfsi,  0x08, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(efscfuf,  efscfsf,  0x09, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(efsctui,  efsctsi,  0x0A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(efsctuf,  efsctsf,  0x0B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
+GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
+GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
+GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
 
 /* Double precision floating-point operations */
 /* Arithmetic */
@@ -8286,22 +8320,22 @@ GEN_SPEFPUOP_COMP_64(efdtstlt);
 GEN_SPEFPUOP_COMP_64(efdtsteq);
 
 /* Opcodes definitions */
-GEN_SPE(efdadd,         efdsub,        0x10, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
-GEN_SPE(efdcfuid,       efdcfsid,      0x11, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
-GEN_SPE(efdabs,         efdnabs,       0x12, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
-GEN_SPE(efdneg,         speundef,      0x13, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
-GEN_SPE(efdmul,         efddiv,        0x14, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
-GEN_SPE(efdctuidz,      efdctsidz,     0x15, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
-GEN_SPE(efdcmpgt,       efdcmplt,      0x16, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
-GEN_SPE(efdcmpeq,       efdcfs,        0x17, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
-GEN_SPE(efdcfui,        efdcfsi,       0x18, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
-GEN_SPE(efdcfuf,        efdcfsf,       0x19, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
-GEN_SPE(efdctui,        efdctsi,       0x1A, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
-GEN_SPE(efdctuf,        efdctsf,       0x1B, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
-GEN_SPE(efdctuiz,       speundef,      0x1C, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
-GEN_SPE(efdctsiz,       speundef,      0x1D, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
-GEN_SPE(efdtstgt,       efdtstlt,      0x1E, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
-GEN_SPE(efdtsteq,       speundef,      0x1F, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdadd,    efdsub,    0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdcfuid,  efdcfsid,  0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdabs,    efdnabs,   0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE); //
+GEN_SPE(efdneg,    speundef,  0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
+GEN_SPE(efdmul,    efddiv,    0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdcmpgt,  efdcmplt,  0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdcmpeq,  efdcfs,    0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdcfui,   efdcfsi,   0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdcfuf,   efdcfsf,   0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdctui,   efdctsi,   0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdctuf,   efdctsf,   0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdctuiz,  speundef,  0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
+GEN_SPE(efdctsiz,  speundef,  0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
+GEN_SPE(efdtstgt,  efdtstlt,  0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdtsteq,  speundef,  0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
 
 static opcode_t opcodes[] = {
 GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE),
@@ -9070,84 +9104,84 @@ GEN_VAFORM_PAIRED(vsel, vperm, 21),
 GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23),
 
 #undef GEN_SPE
-#define GEN_SPE(name0, name1, opc2, opc3, inval, type)                        \
-GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type)
-GEN_SPE(evaddw,         speundef,      0x00, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evaddiw,        speundef,      0x01, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evsubfw,        speundef,      0x02, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evsubifw,       speundef,      0x03, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evabs,          evneg,         0x04, 0x08, 0x0000F800, PPC_SPE),
-GEN_SPE(evextsb,        evextsh,       0x05, 0x08, 0x0000F800, PPC_SPE),
-GEN_SPE(evrndw,         evcntlzw,      0x06, 0x08, 0x0000F800, PPC_SPE),
-GEN_SPE(evcntlsw,       brinc,         0x07, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evmra,          speundef,      0x02, 0x13, 0x0000F800, PPC_SPE),
-GEN_SPE(speundef,       evand,         0x08, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evandc,         speundef,      0x09, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evxor,          evor,          0x0B, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evnor,          eveqv,         0x0C, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE),
-GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE),
-GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE),
-GEN_SPE(speundef,       evorc,         0x0D, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evnand,         speundef,      0x0F, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evsrwu,         evsrws,        0x10, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evsrwiu,        evsrwis,       0x11, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evslw,          speundef,      0x12, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evslwi,         speundef,      0x13, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evrlw,          evsplati,      0x14, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evrlwi,         evsplatfi,     0x15, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evmergehi,      evmergelo,     0x16, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evmergehilo,    evmergelohi,   0x17, 0x08, 0x00000000, PPC_SPE),
-GEN_SPE(evcmpgtu,       evcmpgts,      0x18, 0x08, 0x00600000, PPC_SPE),
-GEN_SPE(evcmpltu,       evcmplts,      0x19, 0x08, 0x00600000, PPC_SPE),
-GEN_SPE(evcmpeq,        speundef,      0x1A, 0x08, 0x00600000, PPC_SPE),
-
-GEN_SPE(evfsadd,        evfssub,       0x00, 0x0A, 0x00000000, PPC_SPE_SINGLE),
-GEN_SPE(evfsabs,        evfsnabs,      0x02, 0x0A, 0x0000F800, PPC_SPE_SINGLE),
-GEN_SPE(evfsneg,        speundef,      0x03, 0x0A, 0x0000F800, PPC_SPE_SINGLE),
-GEN_SPE(evfsmul,        evfsdiv,       0x04, 0x0A, 0x00000000, PPC_SPE_SINGLE),
-GEN_SPE(evfscmpgt,      evfscmplt,     0x06, 0x0A, 0x00600000, PPC_SPE_SINGLE),
-GEN_SPE(evfscmpeq,      speundef,      0x07, 0x0A, 0x00600000, PPC_SPE_SINGLE),
-GEN_SPE(evfscfui,       evfscfsi,      0x08, 0x0A, 0x00180000, PPC_SPE_SINGLE),
-GEN_SPE(evfscfuf,       evfscfsf,      0x09, 0x0A, 0x00180000, PPC_SPE_SINGLE),
-GEN_SPE(evfsctui,       evfsctsi,      0x0A, 0x0A, 0x00180000, PPC_SPE_SINGLE),
-GEN_SPE(evfsctuf,       evfsctsf,      0x0B, 0x0A, 0x00180000, PPC_SPE_SINGLE),
-GEN_SPE(evfsctuiz,      speundef,      0x0C, 0x0A, 0x00180000, PPC_SPE_SINGLE),
-GEN_SPE(evfsctsiz,      speundef,      0x0D, 0x0A, 0x00180000, PPC_SPE_SINGLE),
-GEN_SPE(evfststgt,      evfststlt,     0x0E, 0x0A, 0x00600000, PPC_SPE_SINGLE),
-GEN_SPE(evfststeq,      speundef,      0x0F, 0x0A, 0x00600000, PPC_SPE_SINGLE),
-
-GEN_SPE(efsadd,         efssub,        0x00, 0x0B, 0x00000000, PPC_SPE_SINGLE),
-GEN_SPE(efsabs,         efsnabs,       0x02, 0x0B, 0x0000F800, PPC_SPE_SINGLE),
-GEN_SPE(efsneg,         speundef,      0x03, 0x0B, 0x0000F800, PPC_SPE_SINGLE),
-GEN_SPE(efsmul,         efsdiv,        0x04, 0x0B, 0x00000000, PPC_SPE_SINGLE),
-GEN_SPE(efscmpgt,       efscmplt,      0x06, 0x0B, 0x00600000, PPC_SPE_SINGLE),
-GEN_SPE(efscmpeq,       efscfd,        0x07, 0x0B, 0x00600000, PPC_SPE_SINGLE),
-GEN_SPE(efscfui,        efscfsi,       0x08, 0x0B, 0x00180000, PPC_SPE_SINGLE),
-GEN_SPE(efscfuf,        efscfsf,       0x09, 0x0B, 0x00180000, PPC_SPE_SINGLE),
-GEN_SPE(efsctui,        efsctsi,       0x0A, 0x0B, 0x00180000, PPC_SPE_SINGLE),
-GEN_SPE(efsctuf,        efsctsf,       0x0B, 0x0B, 0x00180000, PPC_SPE_SINGLE),
-GEN_SPE(efsctuiz,       speundef,      0x0C, 0x0B, 0x00180000, PPC_SPE_SINGLE),
-GEN_SPE(efsctsiz,       speundef,      0x0D, 0x0B, 0x00180000, PPC_SPE_SINGLE),
-GEN_SPE(efststgt,       efststlt,      0x0E, 0x0B, 0x00600000, PPC_SPE_SINGLE),
-GEN_SPE(efststeq,       speundef,      0x0F, 0x0B, 0x00600000, PPC_SPE_SINGLE),
-
-GEN_SPE(efdadd,         efdsub,        0x10, 0x0B, 0x00000000, PPC_SPE_DOUBLE),
-GEN_SPE(efdcfuid,       efdcfsid,      0x11, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
-GEN_SPE(efdabs,         efdnabs,       0x12, 0x0B, 0x0000F800, PPC_SPE_DOUBLE),
-GEN_SPE(efdneg,         speundef,      0x13, 0x0B, 0x0000F800, PPC_SPE_DOUBLE),
-GEN_SPE(efdmul,         efddiv,        0x14, 0x0B, 0x00000000, PPC_SPE_DOUBLE),
-GEN_SPE(efdctuidz,      efdctsidz,     0x15, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
-GEN_SPE(efdcmpgt,       efdcmplt,      0x16, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
-GEN_SPE(efdcmpeq,       efdcfs,        0x17, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
-GEN_SPE(efdcfui,        efdcfsi,       0x18, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
-GEN_SPE(efdcfuf,        efdcfsf,       0x19, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
-GEN_SPE(efdctui,        efdctsi,       0x1A, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
-GEN_SPE(efdctuf,        efdctsf,       0x1B, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
-GEN_SPE(efdctuiz,       speundef,      0x1C, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
-GEN_SPE(efdctsiz,       speundef,      0x1D, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
-GEN_SPE(efdtstgt,       efdtstlt,      0x1E, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
-GEN_SPE(efdtsteq,       speundef,      0x1F, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
+#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
+    GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE)
+GEN_SPE(evaddw,      speundef,    0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
+GEN_SPE(evaddiw,     speundef,    0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
+GEN_SPE(evsubfw,     speundef,    0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
+GEN_SPE(evsubifw,    speundef,    0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
+GEN_SPE(evabs,       evneg,       0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
+GEN_SPE(evextsb,     evextsh,     0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
+GEN_SPE(evrndw,      evcntlzw,    0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
+GEN_SPE(evcntlsw,    brinc,       0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE),
+GEN_SPE(evmra,       speundef,    0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE),
+GEN_SPE(speundef,    evand,       0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE),
+GEN_SPE(evandc,      speundef,    0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
+GEN_SPE(evxor,       evor,        0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE),
+GEN_SPE(evnor,       eveqv,       0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE),
+GEN_SPE(evmwumi,     evmwsmi,     0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE),
+GEN_SPE(evmwumia,    evmwsmia,    0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE),
+GEN_SPE(evmwumiaa,   evmwsmiaa,   0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE),
+GEN_SPE(speundef,    evorc,       0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE),
+GEN_SPE(evnand,      speundef,    0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
+GEN_SPE(evsrwu,      evsrws,      0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE),
+GEN_SPE(evsrwiu,     evsrwis,     0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE),
+GEN_SPE(evslw,       speundef,    0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
+GEN_SPE(evslwi,      speundef,    0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
+GEN_SPE(evrlw,       evsplati,    0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE),
+GEN_SPE(evrlwi,      evsplatfi,   0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE),
+GEN_SPE(evmergehi,   evmergelo,   0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE),
+GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE),
+GEN_SPE(evcmpgtu,    evcmpgts,    0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE),
+GEN_SPE(evcmpltu,    evcmplts,    0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE),
+GEN_SPE(evcmpeq,     speundef,    0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE),
+
+GEN_SPE(evfsadd,     evfssub,     0x00, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
+GEN_SPE(evfsabs,     evfsnabs,    0x02, 0x0A, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE),
+GEN_SPE(evfsneg,     speundef,    0x03, 0x0A, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE),
+GEN_SPE(evfsmul,     evfsdiv,     0x04, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
+GEN_SPE(evfscmpgt,   evfscmplt,   0x06, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
+GEN_SPE(evfscmpeq,   speundef,    0x07, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
+GEN_SPE(evfscfui,    evfscfsi,    0x08, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
+GEN_SPE(evfscfuf,    evfscfsf,    0x09, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
+GEN_SPE(evfsctui,    evfsctsi,    0x0A, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
+GEN_SPE(evfsctuf,    evfsctsf,    0x0B, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
+GEN_SPE(evfsctuiz,   speundef,    0x0C, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
+GEN_SPE(evfsctsiz,   speundef,    0x0D, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
+GEN_SPE(evfststgt,   evfststlt,   0x0E, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
+GEN_SPE(evfststeq,   speundef,    0x0F, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
+
+GEN_SPE(efsadd,      efssub,      0x00, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
+GEN_SPE(efsabs,      efsnabs,     0x02, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE),
+GEN_SPE(efsneg,      speundef,    0x03, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE),
+GEN_SPE(efsmul,      efsdiv,      0x04, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
+GEN_SPE(efscmpgt,    efscmplt,    0x06, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
+GEN_SPE(efscmpeq,    efscfd,      0x07, 0x0B, 0x00600000, 0x00180000, PPC_SPE_SINGLE),
+GEN_SPE(efscfui,     efscfsi,     0x08, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
+GEN_SPE(efscfuf,     efscfsf,     0x09, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
+GEN_SPE(efsctui,     efsctsi,     0x0A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
+GEN_SPE(efsctuf,     efsctsf,     0x0B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
+GEN_SPE(efsctuiz,    speundef,    0x0C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
+GEN_SPE(efsctsiz,    speundef,    0x0D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
+GEN_SPE(efststgt,    efststlt,    0x0E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
+GEN_SPE(efststeq,    speundef,    0x0F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
+
+GEN_SPE(efdadd,      efdsub,      0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE),
+GEN_SPE(efdcfuid,    efdcfsid,    0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
+GEN_SPE(efdabs,      efdnabs,     0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE),
+GEN_SPE(efdneg,      speundef,    0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE),
+GEN_SPE(efdmul,      efddiv,      0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE),
+GEN_SPE(efdctuidz,   efdctsidz,   0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
+GEN_SPE(efdcmpgt,    efdcmplt,    0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE),
+GEN_SPE(efdcmpeq,    efdcfs,      0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE),
+GEN_SPE(efdcfui,     efdcfsi,     0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
+GEN_SPE(efdcfuf,     efdcfsf,     0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
+GEN_SPE(efdctui,     efdctsi,     0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
+GEN_SPE(efdctuf,     efdctsf,     0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
+GEN_SPE(efdctuiz,    speundef,    0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
+GEN_SPE(efdctsiz,    speundef,    0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
+GEN_SPE(efdtstgt,    efdtstlt,    0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE),
+GEN_SPE(efdtsteq,    speundef,    0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
 
 #undef GEN_SPEOP_LDST
 #define GEN_SPEOP_LDST(name, opc2, sh)                                        \
@@ -9484,11 +9518,19 @@ static inline void gen_intermediate_code_internal(CPUState *env,
                          opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
             }
         } else {
-            if (unlikely((ctx.opcode & handler->inval) != 0)) {
+            uint32_t inval;
+
+            if (unlikely(handler->type & (PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE) && Rc(ctx.opcode))) {
+                inval = handler->inval2;
+            } else {
+                inval = handler->inval1;
+            }
+
+            if (unlikely((ctx.opcode & inval) != 0)) {
                 if (qemu_log_enabled()) {
                     qemu_log("invalid bits: %08x for opcode: "
                              "%02x - %02x - %02x (%08x) " TARGET_FMT_lx "\n",
-                             ctx.opcode & handler->inval, opc1(ctx.opcode),
+                             ctx.opcode & inval, opc1(ctx.opcode),
                              opc2(ctx.opcode), opc3(ctx.opcode),
                              ctx.opcode, ctx.nip - 4);
                 }
commit bdcf9d6cd4ff987e58ba4f311ba7b1a33cf3ce5e
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Thu Sep 29 21:39:13 2011 +0000

    pseries: Update SLOF firmware image
    
    This patch updates the SLOF submodule and precompiled image.  The new
    SLOF versions contains two changes of note:
    
     * The previous SLOF has a bug in SCSI condition handling that was
       exposed by recent updates to qemu's SCSI emulation.  This update
       fixes the bug.
    
     * The previous SLOF has a bug in its addressing of SCSI devices,
       which can be exposed under certain conditions.  The new SLOF also
       fixes this.
    
    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 4d1d816..32a438e 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-20110323.
+  built from git tag qemu-slof-20110930.
 
 - The PXE roms come from the iPXE project. Built with BANNER_TIME 0.
   Sources available at http://ipxe.org.  Vendor:Device ID -> ROM mapping:
diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin
index 22c4c7f..b9d4f35 100644
Binary files a/pc-bios/slof.bin and b/pc-bios/slof.bin differ
diff --git a/roms/SLOF b/roms/SLOF
index d1d6b53..b94bde0 160000
--- a/roms/SLOF
+++ b/roms/SLOF
@@ -1 +1 @@
-Subproject commit d1d6b53b713a2b7c2c25685268fa932d28a4b4c0
+Subproject commit b94bde008b0d49ec4bfe933e110d0952d032ac28
commit 0f5cb2989f33059a70e8da335b62af5f27fabbe2
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Thu Sep 29 21:39:12 2011 +0000

    pseries: Use Book3S-HV TCE acceleration capabilities
    
    The pseries machine of qemu implements the TCE mechanism used as a
    virtual IOMMU for the PAPR defined virtual IO devices.  Because the
    PAPR spec only defines a small DMA address space, the guest VIO
    drivers need to update TCE mappings very frequently - the virtual
    network device is particularly bad.  This means many slow exits to
    qemu to emulate the H_PUT_TCE hypercall.
    
    Sufficiently recent kernels allow this to be mitigated by implementing
    H_PUT_TCE in the host kernel.  To make use of this, however, qemu
    needs to initialize the necessary TCE tables, and map them into itself
    so that the VIO device implementations can retrieve the mappings when
    they access guest memory (which is treated as a virtual DMA
    operation).
    
    This patch adds the necessary calls to use the KVM TCE acceleration.
    If the kernel does not support acceleration, or there is some other
    error creating the accelerated TCE table, then it will still fall back
    to full userspace TCE implementation.
    
    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_vio.c b/hw/spapr_vio.c
index 35818e1..1da3032 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -165,7 +165,13 @@ static void rtce_init(VIOsPAPRDevice *dev)
         * sizeof(VIOsPAPR_RTCE);
 
     if (size) {
-        dev->rtce_table = g_malloc0(size);
+        dev->rtce_table = kvmppc_create_spapr_tce(dev->reg,
+                                                  dev->rtce_window_size,
+                                                  &dev->kvmtce_fd);
+
+        if (!dev->rtce_table) {
+            dev->rtce_table = g_malloc0(size);
+        }
     }
 }
 
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index 4fe5f74..a325a5f 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -57,6 +57,7 @@ typedef struct VIOsPAPRDevice {
     target_ulong signal_state;
     uint32_t rtce_window_size;
     VIOsPAPR_RTCE *rtce_table;
+    int kvmtce_fd;
     VIOsPAPR_CRQ crq;
 } VIOsPAPRDevice;
 
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index fd17d23..06cad41 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -28,6 +28,7 @@
 #include "kvm_ppc.h"
 #include "cpu.h"
 #include "device_tree.h"
+#include "hw/sysbus.h"
 #include "hw/spapr.h"
 
 #include "hw/sysbus.h"
@@ -56,6 +57,7 @@ static int cap_segstate;
 static int cap_booke_sregs;
 static int cap_ppc_smt;
 static int cap_ppc_rma;
+static int cap_spapr_tce;
 
 /* XXX We have a race condition where we actually have a level triggered
  *     interrupt, but the infrastructure can't expose that yet, so the guest
@@ -81,6 +83,7 @@ int kvm_arch_init(KVMState *s)
     cap_booke_sregs = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_SREGS);
     cap_ppc_smt = kvm_check_extension(s, KVM_CAP_PPC_SMT);
     cap_ppc_rma = kvm_check_extension(s, KVM_CAP_PPC_RMA);
+    cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE);
 
     if (!cap_interrupt_level) {
         fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@@ -802,6 +805,57 @@ off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
     return size;
 }
 
+void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd)
+{
+    struct kvm_create_spapr_tce args = {
+        .liobn = liobn,
+        .window_size = window_size,
+    };
+    long len;
+    int fd;
+    void *table;
+
+    if (!cap_spapr_tce) {
+        return NULL;
+    }
+
+    fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE, &args);
+    if (fd < 0) {
+        return NULL;
+    }
+
+    len = (window_size / SPAPR_VIO_TCE_PAGE_SIZE) * sizeof(VIOsPAPR_RTCE);
+    /* FIXME: round this up to page size */
+
+    table = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
+    if (table == MAP_FAILED) {
+        close(fd);
+        return NULL;
+    }
+
+    *pfd = fd;
+    return table;
+}
+
+int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t window_size)
+{
+    long len;
+
+    if (fd < 0) {
+        return -1;
+    }
+
+    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));
+        /* Leak the table */
+    }
+
+    return 0;
+}
+
 bool kvm_arch_stop_on_emulation_error(CPUState *env)
 {
     return true;
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 82f32f4..87d1bdd 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -22,6 +22,8 @@ int kvmppc_set_interrupt(CPUState *env, int irq, int level);
 void kvmppc_set_papr(CPUState *env);
 int kvmppc_smt_threads(void);
 off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem);
+void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd);
+int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size);
 
 #else
 
@@ -59,6 +61,18 @@ static inline off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
     return 0;
 }
 
+static inline void *kvmppc_create_spapr_tce(uint32_t liobn,
+                                            uint32_t window_size, int *fd)
+{
+    return NULL;
+}
+
+static inline int kvmppc_remove_spapr_tce(void *table, int pfd,
+                                          uint32_t window_size)
+{
+    return -1;
+}
+
 #endif
 
 #ifndef CONFIG_KVM
commit 354ac20a36a82a5ee09b0a6c8ba8655358a7597f
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Thu Sep 29 21:39:11 2011 +0000

    pseries: Allow KVM Book3S-HV on PPC970 CPUS
    
    At present, using the hypervisor aware Book3S-HV KVM will only work
    with qemu on POWER7 CPUs.  PPC970 CPUs also have hypervisor
    capability, but they lack the VRMA feature which makes assigning guest
    memory easier.
    
    In order to allow KVM Book3S-HV on PPC970, we need to specially
    allocate the first chunk of guest memory (the "Real Mode Area" or
    RMA), so that it is physically contiguous.
    
    Sufficiently recent host kernels allow such contiguous RMAs to be
    allocated, with a kvm capability advertising whether the feature is
    available and/or necessary on this hardware.  This patch enables qemu
    to use this support, thus allowing kvm acceleration of pseries qemu
    machines on PPC970 hardware.
    
    Signed-off-by: Paul Mackerras <paulus at samba.org>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>
    
    ---
    
    agraf: fix to use memory api

diff --git a/hw/spapr.c b/hw/spapr.c
index c2675e1..193398b 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -91,6 +91,7 @@ qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num)
 }
 
 static void *spapr_create_fdt_skel(const char *cpu_model,
+                                   target_phys_addr_t rma_size,
                                    target_phys_addr_t initrd_base,
                                    target_phys_addr_t initrd_size,
                                    const char *boot_device,
@@ -99,7 +100,9 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
 {
     void *fdt;
     CPUState *env;
-    uint64_t mem_reg_property[] = { 0, cpu_to_be64(ram_size) };
+    uint64_t mem_reg_property_rma[] = { 0, cpu_to_be64(rma_size) };
+    uint64_t mem_reg_property_nonrma[] = { cpu_to_be64(rma_size),
+                                           cpu_to_be64(ram_size - rma_size) };
     uint32_t start_prop = cpu_to_be32(initrd_base);
     uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
     uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
@@ -145,15 +148,25 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
 
     _FDT((fdt_end_node(fdt)));
 
-    /* memory node */
+    /* memory node(s) */
     _FDT((fdt_begin_node(fdt, "memory at 0")));
 
     _FDT((fdt_property_string(fdt, "device_type", "memory")));
-    _FDT((fdt_property(fdt, "reg",
-                       mem_reg_property, sizeof(mem_reg_property))));
-
+    _FDT((fdt_property(fdt, "reg", mem_reg_property_rma,
+                       sizeof(mem_reg_property_rma))));
     _FDT((fdt_end_node(fdt)));
 
+    if (ram_size > rma_size) {
+        char mem_name[32];
+
+        sprintf(mem_name, "memory@%" PRIx64, (uint64_t)rma_size);
+        _FDT((fdt_begin_node(fdt, mem_name)));
+        _FDT((fdt_property_string(fdt, "device_type", "memory")));
+        _FDT((fdt_property(fdt, "reg", mem_reg_property_nonrma,
+                           sizeof(mem_reg_property_nonrma))));
+        _FDT((fdt_end_node(fdt)));
+    }
+
     /* cpus */
     _FDT((fdt_begin_node(fdt, "cpus")));
 
@@ -346,6 +359,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     int i;
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
+    target_phys_addr_t rma_alloc_size, rma_size;
     uint32_t initrd_base;
     long kernel_size, initrd_size, fw_size;
     long pteg_shift = 17;
@@ -354,10 +368,23 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     spapr = g_malloc(sizeof(*spapr));
     cpu_ppc_hypercall = emulate_spapr_hypercall;
 
-    /* We place the device tree just below either the top of RAM, or
-     * 2GB, so that it can be processed with 32-bit code if
-     * necessary */
-    spapr->fdt_addr = MIN(ram_size, 0x80000000) - FDT_MAX_SIZE;
+    /* Allocate RMA if necessary */
+    rma_alloc_size = kvmppc_alloc_rma("ppc_spapr.rma", sysmem);
+
+    if (rma_alloc_size == -1) {
+        hw_error("qemu: Unable to create RMA\n");
+        exit(1);
+    }
+    if (rma_alloc_size && (rma_alloc_size < ram_size)) {
+        rma_size = rma_alloc_size;
+    } else {
+        rma_size = ram_size;
+    }
+
+    /* We place the device tree just below either the top of the RMA,
+     * or just below 2GB, whichever is lowere, so that it can be
+     * processed with 32-bit real mode code if necessary */
+    spapr->fdt_addr = MIN(rma_size, 0x80000000) - FDT_MAX_SIZE;
     spapr->rtas_addr = spapr->fdt_addr - RTAS_MAX_SIZE;
 
     /* init CPUs */
@@ -382,8 +409,13 @@ static void ppc_spapr_init(ram_addr_t ram_size,
 
     /* allocate RAM */
     spapr->ram_limit = ram_size;
-    memory_region_init_ram(ram, NULL, "ppc_spapr.ram", spapr->ram_limit);
-    memory_region_add_subregion(sysmem, 0, ram);
+    if (spapr->ram_limit > rma_alloc_size) {
+        ram_addr_t nonrma_base = rma_alloc_size;
+        ram_addr_t nonrma_size = spapr->ram_limit - rma_alloc_size;
+
+        memory_region_init_ram(ram, NULL, "ppc_spapr.ram", nonrma_size);
+        memory_region_add_subregion(sysmem, nonrma_base, ram);
+    }
 
     /* allocate hash page table.  For now we always make this 16mb,
      * later we should probably make it scale to the size of guest
@@ -507,7 +539,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     }
 
     /* Prepare the device tree */
-    spapr->fdt_skel = spapr_create_fdt_skel(cpu_model,
+    spapr->fdt_skel = spapr_create_fdt_skel(cpu_model, rma_size,
                                             initrd_base, initrd_size,
                                             boot_device, kernel_cmdline,
                                             pteg_shift + 7);
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 6c7ca6f..fd17d23 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -55,6 +55,7 @@ static int cap_interrupt_level = false;
 static int cap_segstate;
 static int cap_booke_sregs;
 static int cap_ppc_smt;
+static int cap_ppc_rma;
 
 /* XXX We have a race condition where we actually have a level triggered
  *     interrupt, but the infrastructure can't expose that yet, so the guest
@@ -79,6 +80,7 @@ int kvm_arch_init(KVMState *s)
     cap_segstate = kvm_check_extension(s, KVM_CAP_PPC_SEGSTATE);
     cap_booke_sregs = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_SREGS);
     cap_ppc_smt = kvm_check_extension(s, KVM_CAP_PPC_SMT);
+    cap_ppc_rma = kvm_check_extension(s, KVM_CAP_PPC_RMA);
 
     if (!cap_interrupt_level) {
         fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@@ -758,6 +760,48 @@ int kvmppc_smt_threads(void)
     return cap_ppc_smt ? cap_ppc_smt : 1;
 }
 
+off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
+{
+    void *rma;
+    off_t size;
+    int fd;
+    struct kvm_allocate_rma ret;
+    MemoryRegion *rma_region;
+
+    /* If cap_ppc_rma == 0, contiguous RMA allocation is not supported
+     * if cap_ppc_rma == 1, contiguous RMA allocation is supported, but
+     *                      not necessary on this hardware
+     * if cap_ppc_rma == 2, contiguous RMA allocation is needed on this hardware
+     *
+     * FIXME: We should allow the user to force contiguous RMA
+     * allocation in the cap_ppc_rma==1 case.
+     */
+    if (cap_ppc_rma < 2) {
+        return 0;
+    }
+
+    fd = kvm_vm_ioctl(kvm_state, KVM_ALLOCATE_RMA, &ret);
+    if (fd < 0) {
+        fprintf(stderr, "KVM: Error on KVM_ALLOCATE_RMA: %s\n",
+                strerror(errno));
+        return -1;
+    }
+
+    size = MIN(ret.rma_size, 256ul << 20);
+
+    rma = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+    if (rma == MAP_FAILED) {
+        fprintf(stderr, "KVM: Error mapping RMA: %s\n", strerror(errno));
+        return -1;
+    };
+
+    rma_region = g_new(MemoryRegion, 1);
+    memory_region_init_ram_ptr(rma_region, NULL, name, size, rma);
+    memory_region_add_subregion(sysmem, 0, rma_region);
+
+    return size;
+}
+
 bool kvm_arch_stop_on_emulation_error(CPUState *env)
 {
     return true;
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index c298411..82f32f4 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -9,6 +9,8 @@
 #ifndef __KVM_PPC_H__
 #define __KVM_PPC_H__
 
+#include "memory.h"
+
 void kvmppc_init(void);
 
 #ifdef CONFIG_KVM
@@ -19,6 +21,7 @@ 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_smt_threads(void);
+off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem);
 
 #else
 
@@ -51,6 +54,11 @@ static inline int kvmppc_smt_threads(void)
     return 1;
 }
 
+static inline off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
+{
+    return 0;
+}
+
 #endif
 
 #ifndef CONFIG_KVM
commit e97c363638b32943afc4bd2845f4081496fabfbc
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Thu Sep 29 21:39:10 2011 +0000

    pseries: Support SMT systems for KVM Book3S-HV
    
    Alex Graf has already made qemu support KVM for the pseries machine
    when using the Book3S-PR KVM variant (which runs the guest in
    usermode, emulating supervisor operations).  This code allows gets us
    very close to also working with KVM Book3S-HV (using the hypervisor
    capabilities of recent POWER CPUs).
    
    This patch moves us another step towards Book3S-HV support by
    correctly handling SMT (multithreaded) POWER CPUs.  There are two
    parts to this:
    
     * Querying KVM to check SMT capability, and if present, adjusting the
       cpu numbers that qemu assigns to cause KVM to assign guest threads
       to cores in the right way (this isn't automatic, because the POWER
       HV support has a limitation that different threads on a single core
       cannot be in different guests at the same time).
    
     * Correctly informing the guest OS of the SMT thread to core mappings
       via the device tree.
    
    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 63e5d33..c2675e1 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -29,6 +29,9 @@
 #include "elf.h"
 #include "net.h"
 #include "blockdev.h"
+#include "cpus.h"
+#include "kvm.h"
+#include "kvm_ppc.h"
 
 #include "hw/boards.h"
 #include "hw/ppc.h"
@@ -105,6 +108,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
     uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
     int i;
     char *modelname;
+    int smt = kvmppc_smt_threads();
 
 #define _FDT(exp) \
     do { \
@@ -164,13 +168,18 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         int index = env->cpu_index;
-        uint32_t gserver_prop[] = {cpu_to_be32(index), 0}; /* HACK! */
+        uint32_t servers_prop[smp_threads];
+        uint32_t gservers_prop[smp_threads * 2];
         char *nodename;
         uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
                            0xffffffff, 0xffffffff};
         uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ;
         uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000;
 
+        if ((index % smt) != 0) {
+            continue;
+        }
+
         if (asprintf(&nodename, "%s@%x", modelname, index) < 0) {
             fprintf(stderr, "Allocation failure\n");
             exit(1);
@@ -195,9 +204,18 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
                            pft_size_prop, sizeof(pft_size_prop))));
         _FDT((fdt_property_string(fdt, "status", "okay")));
         _FDT((fdt_property(fdt, "64-bit", NULL, 0)));
-        _FDT((fdt_property_cell(fdt, "ibm,ppc-interrupt-server#s", index)));
+
+        /* Build interrupt servers and gservers properties */
+        for (i = 0; i < smp_threads; i++) {
+            servers_prop[i] = cpu_to_be32(index + i);
+            /* Hack, direct the group queues back to cpu 0 */
+            gservers_prop[i*2] = cpu_to_be32(index + i);
+            gservers_prop[i*2 + 1] = 0;
+        }
+        _FDT((fdt_property(fdt, "ibm,ppc-interrupt-server#s",
+                           servers_prop, sizeof(servers_prop))));
         _FDT((fdt_property(fdt, "ibm,ppc-interrupt-gserver#s",
-                           gserver_prop, sizeof(gserver_prop))));
+                           gservers_prop, sizeof(gservers_prop))));
 
         if (env->mmu_model & POWERPC_MMU_1TSEG) {
             _FDT((fdt_property(fdt, "ibm,processor-segment-sizes",
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 6339be3..137a494 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -26,6 +26,8 @@
 #include "helper_regs.h"
 #include "qemu-common.h"
 #include "kvm.h"
+#include "kvm_ppc.h"
+#include "cpus.h"
 
 //#define DEBUG_MMU
 //#define DEBUG_BATS
@@ -3189,6 +3191,15 @@ CPUPPCState *cpu_ppc_init (const char *cpu_model)
     if (tcg_enabled()) {
         ppc_translate_init();
     }
+    /* Adjust cpu index for SMT */
+#if !defined(CONFIG_USER_ONLY)
+    if (kvm_enabled()) {
+        int smt = kvmppc_smt_threads();
+
+        env->cpu_index = (env->cpu_index / smp_threads)*smt
+            + (env->cpu_index % smp_threads);
+    }
+#endif /* !CONFIG_USER_ONLY */
     env->cpu_model_str = cpu_model;
     cpu_ppc_register_internal(env, def);
 
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 75832d8..6c7ca6f 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -28,6 +28,7 @@
 #include "kvm_ppc.h"
 #include "cpu.h"
 #include "device_tree.h"
+#include "hw/spapr.h"
 
 #include "hw/sysbus.h"
 #include "hw/spapr.h"
@@ -53,6 +54,7 @@ static int cap_interrupt_unset = false;
 static int cap_interrupt_level = false;
 static int cap_segstate;
 static int cap_booke_sregs;
+static int cap_ppc_smt;
 
 /* XXX We have a race condition where we actually have a level triggered
  *     interrupt, but the infrastructure can't expose that yet, so the guest
@@ -76,6 +78,7 @@ int kvm_arch_init(KVMState *s)
     cap_interrupt_level = kvm_check_extension(s, KVM_CAP_PPC_IRQ_LEVEL);
     cap_segstate = kvm_check_extension(s, KVM_CAP_PPC_SEGSTATE);
     cap_booke_sregs = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_SREGS);
+    cap_ppc_smt = kvm_check_extension(s, KVM_CAP_PPC_SMT);
 
     if (!cap_interrupt_level) {
         fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@@ -750,6 +753,11 @@ fail:
     cpu_abort(env, "This KVM version does not support PAPR\n");
 }
 
+int kvmppc_smt_threads(void)
+{
+    return cap_ppc_smt ? cap_ppc_smt : 1;
+}
+
 bool kvm_arch_stop_on_emulation_error(CPUState *env)
 {
     return true;
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index c484e60..c298411 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -18,6 +18,7 @@ uint64_t kvmppc_get_clockfreq(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_smt_threads(void);
 
 #else
 
@@ -45,6 +46,11 @@ static inline void kvmppc_set_papr(CPUState *env)
 {
 }
 
+static inline int kvmppc_smt_threads(void)
+{
+    return 1;
+}
+
 #endif
 
 #ifndef CONFIG_KVM
commit eeae2e7b52255dae0976a027b6e11274990c708d
Author: Liu Yu-B13201 <Yu.Liu at freescale.com>
Date:   Thu Sep 29 17:52:50 2011 +0000

    ppc/e500_pci: Fix an array overflow issue
    
    When access PPCE500_PCI_IW1 the previous index get overflow.
    The patch fix the issue and update all to keep consistent style.
    
    Signed-off-by: Liu Yu <yu.liu at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 0ece422..960a5d0 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -89,6 +89,7 @@ static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
     PPCE500PCIState *pci = opaque;
     unsigned long win;
     uint32_t value = 0;
+    int idx;
 
     win = addr & 0xfe0;
 
@@ -97,18 +98,19 @@ static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
     case PPCE500_PCI_OW2:
     case PPCE500_PCI_OW3:
     case PPCE500_PCI_OW4:
+        idx = (addr >> 5) & 0x7;
         switch (addr & 0xC) {
         case PCI_POTAR:
-            value = pci->pob[(addr >> 5) & 0x7].potar;
+            value = pci->pob[idx].potar;
             break;
         case PCI_POTEAR:
-            value = pci->pob[(addr >> 5) & 0x7].potear;
+            value = pci->pob[idx].potear;
             break;
         case PCI_POWBAR:
-            value = pci->pob[(addr >> 5) & 0x7].powbar;
+            value = pci->pob[idx].powbar;
             break;
         case PCI_POWAR:
-            value = pci->pob[(addr >> 5) & 0x7].powar;
+            value = pci->pob[idx].powar;
             break;
         default:
             break;
@@ -118,18 +120,19 @@ static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
     case PPCE500_PCI_IW3:
     case PPCE500_PCI_IW2:
     case PPCE500_PCI_IW1:
+        idx = ((addr >> 5) & 0x3) - 1;
         switch (addr & 0xC) {
         case PCI_PITAR:
-            value = pci->pib[(addr >> 5) & 0x3].pitar;
+            value = pci->pib[idx].pitar;
             break;
         case PCI_PIWBAR:
-            value = pci->pib[(addr >> 5) & 0x3].piwbar;
+            value = pci->pib[idx].piwbar;
             break;
         case PCI_PIWBEAR:
-            value = pci->pib[(addr >> 5) & 0x3].piwbear;
+            value = pci->pib[idx].piwbear;
             break;
         case PCI_PIWAR:
-            value = pci->pib[(addr >> 5) & 0x3].piwar;
+            value = pci->pib[idx].piwar;
             break;
         default:
             break;
@@ -160,6 +163,7 @@ static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
 {
     PPCE500PCIState *pci = opaque;
     unsigned long win;
+    int idx;
 
     win = addr & 0xfe0;
 
@@ -171,18 +175,19 @@ static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
     case PPCE500_PCI_OW2:
     case PPCE500_PCI_OW3:
     case PPCE500_PCI_OW4:
+        idx = (addr >> 5) & 0x7;
         switch (addr & 0xC) {
         case PCI_POTAR:
-            pci->pob[(addr >> 5) & 0x7].potar = value;
+            pci->pob[idx].potar = value;
             break;
         case PCI_POTEAR:
-            pci->pob[(addr >> 5) & 0x7].potear = value;
+            pci->pob[idx].potear = value;
             break;
         case PCI_POWBAR:
-            pci->pob[(addr >> 5) & 0x7].powbar = value;
+            pci->pob[idx].powbar = value;
             break;
         case PCI_POWAR:
-            pci->pob[(addr >> 5) & 0x7].powar = value;
+            pci->pob[idx].powar = value;
             break;
         default:
             break;
@@ -192,18 +197,19 @@ static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
     case PPCE500_PCI_IW3:
     case PPCE500_PCI_IW2:
     case PPCE500_PCI_IW1:
+        idx = ((addr >> 5) & 0x3) - 1;
         switch (addr & 0xC) {
         case PCI_PITAR:
-            pci->pib[(addr >> 5) & 0x3].pitar = value;
+            pci->pib[idx].pitar = value;
             break;
         case PCI_PIWBAR:
-            pci->pib[(addr >> 5) & 0x3].piwbar = value;
+            pci->pib[idx].piwbar = value;
             break;
         case PCI_PIWBEAR:
-            pci->pib[(addr >> 5) & 0x3].piwbear = value;
+            pci->pib[idx].piwbear = value;
             break;
         case PCI_PIWAR:
-            pci->pib[(addr >> 5) & 0x3].piwar = value;
+            pci->pib[idx].piwar = value;
             break;
         default:
             break;
commit 6875dc8ea4f9e14f33c217c3596af51c60cfd1b5
Author: Liu Yu-B13201 <Yu.Liu at freescale.com>
Date:   Thu Sep 29 17:52:49 2011 +0000

    ppc/e500_pci: Fix code style
    
    Put trailing statements on next line.
    
    Signed-off-by: Liu Yu <yu.liu at freescale.com>
    Reviewed-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 2db365d..0ece422 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -98,11 +98,20 @@ static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
     case PPCE500_PCI_OW3:
     case PPCE500_PCI_OW4:
         switch (addr & 0xC) {
-        case PCI_POTAR: value = pci->pob[(addr >> 5) & 0x7].potar; break;
-        case PCI_POTEAR: value = pci->pob[(addr >> 5) & 0x7].potear; break;
-        case PCI_POWBAR: value = pci->pob[(addr >> 5) & 0x7].powbar; break;
-        case PCI_POWAR: value = pci->pob[(addr >> 5) & 0x7].powar; break;
-        default: break;
+        case PCI_POTAR:
+            value = pci->pob[(addr >> 5) & 0x7].potar;
+            break;
+        case PCI_POTEAR:
+            value = pci->pob[(addr >> 5) & 0x7].potear;
+            break;
+        case PCI_POWBAR:
+            value = pci->pob[(addr >> 5) & 0x7].powbar;
+            break;
+        case PCI_POWAR:
+            value = pci->pob[(addr >> 5) & 0x7].powar;
+            break;
+        default:
+            break;
         }
         break;
 
@@ -110,11 +119,20 @@ static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
     case PPCE500_PCI_IW2:
     case PPCE500_PCI_IW1:
         switch (addr & 0xC) {
-        case PCI_PITAR: value = pci->pib[(addr >> 5) & 0x3].pitar; break;
-        case PCI_PIWBAR: value = pci->pib[(addr >> 5) & 0x3].piwbar; break;
-        case PCI_PIWBEAR: value = pci->pib[(addr >> 5) & 0x3].piwbear; break;
-        case PCI_PIWAR: value = pci->pib[(addr >> 5) & 0x3].piwar; break;
-        default: break;
+        case PCI_PITAR:
+            value = pci->pib[(addr >> 5) & 0x3].pitar;
+            break;
+        case PCI_PIWBAR:
+            value = pci->pib[(addr >> 5) & 0x3].piwbar;
+            break;
+        case PCI_PIWBEAR:
+            value = pci->pib[(addr >> 5) & 0x3].piwbear;
+            break;
+        case PCI_PIWAR:
+            value = pci->pib[(addr >> 5) & 0x3].piwar;
+            break;
+        default:
+            break;
         };
         break;
 
@@ -154,11 +172,20 @@ static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
     case PPCE500_PCI_OW3:
     case PPCE500_PCI_OW4:
         switch (addr & 0xC) {
-        case PCI_POTAR: pci->pob[(addr >> 5) & 0x7].potar = value; break;
-        case PCI_POTEAR: pci->pob[(addr >> 5) & 0x7].potear = value; break;
-        case PCI_POWBAR: pci->pob[(addr >> 5) & 0x7].powbar = value; break;
-        case PCI_POWAR: pci->pob[(addr >> 5) & 0x7].powar = value; break;
-        default: break;
+        case PCI_POTAR:
+            pci->pob[(addr >> 5) & 0x7].potar = value;
+            break;
+        case PCI_POTEAR:
+            pci->pob[(addr >> 5) & 0x7].potear = value;
+            break;
+        case PCI_POWBAR:
+            pci->pob[(addr >> 5) & 0x7].powbar = value;
+            break;
+        case PCI_POWAR:
+            pci->pob[(addr >> 5) & 0x7].powar = value;
+            break;
+        default:
+            break;
         };
         break;
 
@@ -166,11 +193,20 @@ static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
     case PPCE500_PCI_IW2:
     case PPCE500_PCI_IW1:
         switch (addr & 0xC) {
-        case PCI_PITAR: pci->pib[(addr >> 5) & 0x3].pitar = value; break;
-        case PCI_PIWBAR: pci->pib[(addr >> 5) & 0x3].piwbar = value; break;
-        case PCI_PIWBEAR: pci->pib[(addr >> 5) & 0x3].piwbear = value; break;
-        case PCI_PIWAR: pci->pib[(addr >> 5) & 0x3].piwar = value; break;
-        default: break;
+        case PCI_PITAR:
+            pci->pib[(addr >> 5) & 0x3].pitar = value;
+            break;
+        case PCI_PIWBAR:
+            pci->pib[(addr >> 5) & 0x3].piwbar = value;
+            break;
+        case PCI_PIWBEAR:
+            pci->pib[(addr >> 5) & 0x3].piwbear = value;
+            break;
+        case PCI_PIWAR:
+            pci->pib[(addr >> 5) & 0x3].piwar = value;
+            break;
+        default:
+            break;
         };
         break;
 
commit 08dafab4bde2e7a9fdca8a65f9c41bdb947ff38f
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Oct 16 13:19:17 2011 +0200

    memory: use 128-bit integers for sizes and intermediates
    
    Since the memory API supports 64-bit buses, it needs a larger type to represent
    intermediate results.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/memory.c b/memory.c
index dc5e35d..c0c1d12 100644
--- a/memory.c
+++ b/memory.c
@@ -28,43 +28,48 @@ typedef struct AddrRange AddrRange;
  * (large MemoryRegion::alias_offset).
  */
 struct AddrRange {
-    int64_t start;
-    int64_t size;
+    Int128 start;
+    Int128 size;
 };
 
-static AddrRange addrrange_make(int64_t start, int64_t size)
+static AddrRange addrrange_make(Int128 start, Int128 size)
 {
     return (AddrRange) { start, size };
 }
 
 static bool addrrange_equal(AddrRange r1, AddrRange r2)
 {
-    return r1.start == r2.start && r1.size == r2.size;
+    return int128_eq(r1.start, r2.start) && int128_eq(r1.size, r2.size);
 }
 
-static int64_t addrrange_end(AddrRange r)
+static Int128 addrrange_end(AddrRange r)
 {
-    return r.start + r.size;
+    return int128_add(r.start, r.size);
 }
 
-static AddrRange addrrange_shift(AddrRange range, int64_t delta)
+static AddrRange addrrange_shift(AddrRange range, Int128 delta)
 {
-    range.start += delta;
+    int128_addto(&range.start, delta);
     return range;
 }
 
+static bool addrrange_contains(AddrRange range, Int128 addr)
+{
+    return int128_ge(addr, range.start)
+        && int128_lt(addr, addrrange_end(range));
+}
+
 static bool addrrange_intersects(AddrRange r1, AddrRange r2)
 {
-    return (r1.start >= r2.start && (r1.start - r2.start) < r2.size)
-        || (r2.start >= r1.start && (r2.start - r1.start) < r1.size);
+    return addrrange_contains(r1, r2.start)
+        || addrrange_contains(r2, r1.start);
 }
 
 static AddrRange addrrange_intersection(AddrRange r1, AddrRange r2)
 {
-    int64_t start = MAX(r1.start, r2.start);
-    /* off-by-one arithmetic to prevent overflow */
-    int64_t end = MIN(addrrange_end(r1) - 1, addrrange_end(r2) - 1);
-    return addrrange_make(start, end - start + 1);
+    Int128 start = int128_max(r1.start, r2.start);
+    Int128 end = int128_min(addrrange_end(r1), addrrange_end(r2));
+    return addrrange_make(start, int128_sub(end, start));
 }
 
 struct CoalescedMemoryRange {
@@ -82,13 +87,13 @@ struct MemoryRegionIoeventfd {
 static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
                                            MemoryRegionIoeventfd b)
 {
-    if (a.addr.start < b.addr.start) {
+    if (int128_lt(a.addr.start, b.addr.start)) {
         return true;
-    } else if (a.addr.start > b.addr.start) {
+    } else if (int128_gt(a.addr.start, b.addr.start)) {
         return false;
-    } else if (a.addr.size < b.addr.size) {
+    } else if (int128_lt(a.addr.size, b.addr.size)) {
         return true;
-    } else if (a.addr.size > b.addr.size) {
+    } else if (int128_gt(a.addr.size, b.addr.size)) {
         return false;
     } else if (a.match_data < b.match_data) {
         return true;
@@ -201,9 +206,11 @@ static void flatview_destroy(FlatView *view)
 
 static bool can_merge(FlatRange *r1, FlatRange *r2)
 {
-    return addrrange_end(r1->addr) == r2->addr.start
+    return int128_eq(addrrange_end(r1->addr), r2->addr.start)
         && r1->mr == r2->mr
-        && r1->offset_in_region + r1->addr.size == r2->offset_in_region
+        && int128_eq(int128_add(int128_make64(r1->offset_in_region),
+                                r1->addr.size),
+                     int128_make64(r2->offset_in_region))
         && r1->dirty_log_mask == r2->dirty_log_mask
         && r1->readable == r2->readable
         && r1->readonly == r2->readonly;
@@ -219,7 +226,7 @@ static void flatview_simplify(FlatView *view)
         j = i + 1;
         while (j < view->nr
                && can_merge(&view->ranges[j-1], &view->ranges[j])) {
-            view->ranges[i].addr.size += view->ranges[j].addr.size;
+            int128_addto(&view->ranges[i].addr.size, view->ranges[j].addr.size);
             ++j;
         }
         ++i;
@@ -314,8 +321,8 @@ static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
         phys_offset |= IO_MEM_ROM;
     }
 
-    cpu_register_physical_memory_log(fr->addr.start,
-                                     fr->addr.size,
+    cpu_register_physical_memory_log(int128_get64(fr->addr.start),
+                                     int128_get64(fr->addr.size),
                                      phys_offset,
                                      region_offset,
                                      fr->dirty_log_mask);
@@ -324,30 +331,35 @@ static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
 static void as_memory_range_del(AddressSpace *as, FlatRange *fr)
 {
     if (fr->dirty_log_mask) {
-        cpu_physical_sync_dirty_bitmap(fr->addr.start,
-                                       fr->addr.start + fr->addr.size);
+        Int128 end = addrrange_end(fr->addr);
+        cpu_physical_sync_dirty_bitmap(int128_get64(fr->addr.start),
+                                       int128_get64(end));
     }
-    cpu_register_physical_memory(fr->addr.start, fr->addr.size,
+    cpu_register_physical_memory(int128_get64(fr->addr.start),
+                                 int128_get64(fr->addr.size),
                                  IO_MEM_UNASSIGNED);
 }
 
 static void as_memory_log_start(AddressSpace *as, FlatRange *fr)
 {
-    cpu_physical_log_start(fr->addr.start, fr->addr.size);
+    cpu_physical_log_start(int128_get64(fr->addr.start),
+                           int128_get64(fr->addr.size));
 }
 
 static void as_memory_log_stop(AddressSpace *as, FlatRange *fr)
 {
-    cpu_physical_log_stop(fr->addr.start, fr->addr.size);
+    cpu_physical_log_stop(int128_get64(fr->addr.start),
+                          int128_get64(fr->addr.size));
 }
 
 static void as_memory_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
 {
     int r;
 
-    assert(fd->match_data && fd->addr.size == 4);
+    assert(fd->match_data && int128_get64(fd->addr.size) == 4);
 
-    r = kvm_set_ioeventfd_mmio_long(fd->fd, fd->addr.start, fd->data, true);
+    r = kvm_set_ioeventfd_mmio_long(fd->fd, int128_get64(fd->addr.start),
+                                    fd->data, true);
     if (r < 0) {
         abort();
     }
@@ -357,7 +369,8 @@ static void as_memory_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
 {
     int r;
 
-    r = kvm_set_ioeventfd_mmio_long(fd->fd, fd->addr.start, fd->data, false);
+    r = kvm_set_ioeventfd_mmio_long(fd->fd, int128_get64(fd->addr.start),
+                                    fd->data, false);
     if (r < 0) {
         abort();
     }
@@ -453,22 +466,24 @@ static const IORangeOps memory_region_iorange_ops = {
 static void as_io_range_add(AddressSpace *as, FlatRange *fr)
 {
     iorange_init(&fr->mr->iorange, &memory_region_iorange_ops,
-                 fr->addr.start,fr->addr.size);
+                 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(fr->addr.start, fr->addr.size);
+    isa_unassign_ioport(int128_get64(fr->addr.start),
+                        int128_get64(fr->addr.size));
 }
 
 static void as_io_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
 {
     int r;
 
-    assert(fd->match_data && fd->addr.size == 2);
+    assert(fd->match_data && int128_get64(fd->addr.size) == 2);
 
-    r = kvm_set_ioeventfd_pio_word(fd->fd, fd->addr.start, fd->data, true);
+    r = kvm_set_ioeventfd_pio_word(fd->fd, int128_get64(fd->addr.start),
+                                   fd->data, true);
     if (r < 0) {
         abort();
     }
@@ -478,7 +493,8 @@ static void as_io_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
 {
     int r;
 
-    r = kvm_set_ioeventfd_pio_word(fd->fd, fd->addr.start, fd->data, false);
+    r = kvm_set_ioeventfd_pio_word(fd->fd, int128_get64(fd->addr.start),
+                                   fd->data, false);
     if (r < 0) {
         abort();
     }
@@ -500,19 +516,19 @@ static AddressSpace address_space_io = {
  */
 static void render_memory_region(FlatView *view,
                                  MemoryRegion *mr,
-                                 target_phys_addr_t base,
+                                 Int128 base,
                                  AddrRange clip,
                                  bool readonly)
 {
     MemoryRegion *subregion;
     unsigned i;
     target_phys_addr_t offset_in_region;
-    int64_t remain;
-    int64_t now;
+    Int128 remain;
+    Int128 now;
     FlatRange fr;
     AddrRange tmp;
 
-    base += mr->addr;
+    int128_addto(&base, int128_make64(mr->addr));
     readonly |= mr->readonly;
 
     tmp = addrrange_make(base, mr->size);
@@ -524,8 +540,8 @@ static void render_memory_region(FlatView *view,
     clip = addrrange_intersection(tmp, clip);
 
     if (mr->alias) {
-        base -= mr->alias->addr;
-        base -= mr->alias_offset;
+        int128_subfrom(&base, int128_make64(mr->alias->addr));
+        int128_subfrom(&base, int128_make64(mr->alias_offset));
         render_memory_region(view, mr->alias, base, clip, readonly);
         return;
     }
@@ -539,17 +555,18 @@ static void render_memory_region(FlatView *view,
         return;
     }
 
-    offset_in_region = clip.start - base;
+    offset_in_region = int128_get64(int128_sub(clip.start, base));
     base = clip.start;
     remain = clip.size;
 
     /* Render the region itself into any gaps left by the current view. */
-    for (i = 0; i < view->nr && remain; ++i) {
-        if (base >= addrrange_end(view->ranges[i].addr)) {
+    for (i = 0; i < view->nr && int128_nz(remain); ++i) {
+        if (int128_ge(base, addrrange_end(view->ranges[i].addr))) {
             continue;
         }
-        if (base < view->ranges[i].addr.start) {
-            now = MIN(remain, view->ranges[i].addr.start - base);
+        if (int128_lt(base, view->ranges[i].addr.start)) {
+            now = int128_min(remain,
+                             int128_sub(view->ranges[i].addr.start, base));
             fr.mr = mr;
             fr.offset_in_region = offset_in_region;
             fr.addr = addrrange_make(base, now);
@@ -558,18 +575,18 @@ static void render_memory_region(FlatView *view,
             fr.readonly = readonly;
             flatview_insert(view, i, &fr);
             ++i;
-            base += now;
-            offset_in_region += now;
-            remain -= now;
+            int128_addto(&base, now);
+            offset_in_region += int128_get64(now);
+            int128_subfrom(&remain, now);
         }
-        if (base == view->ranges[i].addr.start) {
-            now = MIN(remain, view->ranges[i].addr.size);
-            base += now;
-            offset_in_region += now;
-            remain -= now;
+        if (int128_eq(base, view->ranges[i].addr.start)) {
+            now = int128_min(remain, view->ranges[i].addr.size);
+            int128_addto(&base, now);
+            offset_in_region += int128_get64(now);
+            int128_subfrom(&remain, now);
         }
     }
-    if (remain) {
+    if (int128_nz(remain)) {
         fr.mr = mr;
         fr.offset_in_region = offset_in_region;
         fr.addr = addrrange_make(base, remain);
@@ -587,7 +604,8 @@ static FlatView generate_memory_topology(MemoryRegion *mr)
 
     flatview_init(&view);
 
-    render_memory_region(&view, mr, 0, addrrange_make(0, INT64_MAX), false);
+    render_memory_region(&view, mr, int128_zero(),
+                         addrrange_make(int128_zero(), int128_2_64()), false);
     flatview_simplify(&view);
 
     return view;
@@ -637,7 +655,8 @@ static void address_space_update_ioeventfds(AddressSpace *as)
     FOR_EACH_FLAT_RANGE(fr, &as->current_map) {
         for (i = 0; i < fr->mr->ioeventfd_nb; ++i) {
             tmp = addrrange_shift(fr->mr->ioeventfds[i].addr,
-                                  fr->addr.start - fr->offset_in_region);
+                                  int128_sub(fr->addr.start,
+                                             int128_make64(fr->offset_in_region)));
             if (addrrange_intersects(fr->addr, tmp)) {
                 ++ioeventfd_nb;
                 ioeventfds = g_realloc(ioeventfds,
@@ -682,8 +701,8 @@ static void address_space_update_topology_pass(AddressSpace *as,
 
         if (frold
             && (!frnew
-                || frold->addr.start < frnew->addr.start
-                || (frold->addr.start == frnew->addr.start
+                || int128_lt(frold->addr.start, frnew->addr.start)
+                || (int128_eq(frold->addr.start, frnew->addr.start)
                     && !flatrange_equal(frold, frnew)))) {
             /* In old, but (not in new, or in new but attributes changed). */
 
@@ -788,7 +807,10 @@ void memory_region_init(MemoryRegion *mr,
 {
     mr->ops = NULL;
     mr->parent = NULL;
-    mr->size = size;
+    mr->size = int128_make64(size);
+    if (size == UINT64_MAX) {
+        mr->size = int128_2_64();
+    }
     mr->addr = 0;
     mr->offset = 0;
     mr->terminates = false;
@@ -1014,7 +1036,10 @@ void memory_region_destroy(MemoryRegion *mr)
 
 uint64_t memory_region_size(MemoryRegion *mr)
 {
-    return mr->size;
+    if (int128_eq(mr->size, int128_2_64())) {
+        return UINT64_MAX;
+    }
+    return int128_get64(mr->size);
 }
 
 void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset)
@@ -1049,8 +1074,8 @@ void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
 
     FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) {
         if (fr->mr == mr) {
-            cpu_physical_sync_dirty_bitmap(fr->addr.start,
-                                           fr->addr.start + fr->addr.size);
+            cpu_physical_sync_dirty_bitmap(int128_get64(fr->addr.start),
+                                           int128_get64(addrrange_end(fr->addr)));
         }
     }
 }
@@ -1099,15 +1124,18 @@ static void memory_region_update_coalesced_range(MemoryRegion *mr)
 
     FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) {
         if (fr->mr == mr) {
-            qemu_unregister_coalesced_mmio(fr->addr.start, fr->addr.size);
+            qemu_unregister_coalesced_mmio(int128_get64(fr->addr.start),
+                                           int128_get64(fr->addr.size));
             QTAILQ_FOREACH(cmr, &mr->coalesced, link) {
                 tmp = addrrange_shift(cmr->addr,
-                                      fr->addr.start - fr->offset_in_region);
+                                      int128_sub(fr->addr.start,
+                                                 int128_make64(fr->offset_in_region)));
                 if (!addrrange_intersects(tmp, fr->addr)) {
                     continue;
                 }
                 tmp = addrrange_intersection(tmp, fr->addr);
-                qemu_register_coalesced_mmio(tmp.start, tmp.size);
+                qemu_register_coalesced_mmio(int128_get64(tmp.start),
+                                             int128_get64(tmp.size));
             }
         }
     }
@@ -1116,7 +1144,7 @@ static void memory_region_update_coalesced_range(MemoryRegion *mr)
 void memory_region_set_coalescing(MemoryRegion *mr)
 {
     memory_region_clear_coalescing(mr);
-    memory_region_add_coalescing(mr, 0, mr->size);
+    memory_region_add_coalescing(mr, 0, int128_get64(mr->size));
 }
 
 void memory_region_add_coalescing(MemoryRegion *mr,
@@ -1125,7 +1153,7 @@ void memory_region_add_coalescing(MemoryRegion *mr,
 {
     CoalescedMemoryRange *cmr = g_malloc(sizeof(*cmr));
 
-    cmr->addr = addrrange_make(offset, size);
+    cmr->addr = addrrange_make(int128_make64(offset), int128_make64(size));
     QTAILQ_INSERT_TAIL(&mr->coalesced, cmr, link);
     memory_region_update_coalesced_range(mr);
 }
@@ -1150,8 +1178,8 @@ void memory_region_add_eventfd(MemoryRegion *mr,
                                int fd)
 {
     MemoryRegionIoeventfd mrfd = {
-        .addr.start = addr,
-        .addr.size = size,
+        .addr.start = int128_make64(addr),
+        .addr.size = int128_make64(size),
         .match_data = match_data,
         .data = data,
         .fd = fd,
@@ -1180,8 +1208,8 @@ void memory_region_del_eventfd(MemoryRegion *mr,
                                int fd)
 {
     MemoryRegionIoeventfd mrfd = {
-        .addr.start = addr,
-        .addr.size = size,
+        .addr.start = int128_make64(addr),
+        .addr.size = int128_make64(size),
         .match_data = match_data,
         .data = data,
         .fd = fd,
@@ -1215,18 +1243,20 @@ static void memory_region_add_subregion_common(MemoryRegion *mr,
         if (subregion->may_overlap || other->may_overlap) {
             continue;
         }
-        if (offset >= other->addr + other->size
-            || offset + subregion->size <= other->addr) {
+        if (int128_gt(int128_make64(offset),
+                      int128_add(int128_make64(other->addr), other->size))
+            || int128_le(int128_add(int128_make64(offset), subregion->size),
+                         int128_make64(other->addr))) {
             continue;
         }
 #if 0
         printf("warning: subregion collision %llx/%llx (%s) "
                "vs %llx/%llx (%s)\n",
                (unsigned long long)offset,
-               (unsigned long long)subregion->size,
+               (unsigned long long)int128_get64(subregion->size),
                subregion->name,
                (unsigned long long)other->addr,
-               (unsigned long long)other->size,
+               (unsigned long long)int128_get64(other->size),
                other->name);
 #endif
     }
@@ -1330,16 +1360,19 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
         mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d): alias %s @%s "
                    TARGET_FMT_plx "-" TARGET_FMT_plx "\n",
                    base + mr->addr,
-                   base + mr->addr + (target_phys_addr_t)mr->size - 1,
+                   base + mr->addr
+                   + (target_phys_addr_t)int128_get64(mr->size) - 1,
                    mr->priority,
                    mr->name,
                    mr->alias->name,
                    mr->alias_offset,
-                   mr->alias_offset + (target_phys_addr_t)mr->size - 1);
+                   mr->alias_offset
+                   + (target_phys_addr_t)int128_get64(mr->size) - 1);
     } else {
         mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d): %s\n",
                    base + mr->addr,
-                   base + mr->addr + (target_phys_addr_t)mr->size - 1,
+                   base + mr->addr
+                   + (target_phys_addr_t)int128_get64(mr->size) - 1,
                    mr->priority,
                    mr->name);
     }
diff --git a/memory.h b/memory.h
index d5b47da..7fb36d1 100644
--- a/memory.h
+++ b/memory.h
@@ -24,6 +24,7 @@
 #include "qemu-queue.h"
 #include "iorange.h"
 #include "ioport.h"
+#include "int128.h"
 
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegion MemoryRegion;
@@ -105,7 +106,7 @@ struct MemoryRegion {
     const MemoryRegionOps *ops;
     void *opaque;
     MemoryRegion *parent;
-    uint64_t size;
+    Int128 size;
     target_phys_addr_t addr;
     target_phys_addr_t offset;
     bool backend_registered;
commit b7cd3db6f4d79f11abf0572fdc5e41d0811ea2e2
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Oct 16 13:13:05 2011 +0200

    Add support for 128-bit arithmetic
    
    The memory API supports 64-bit buses (e.g. PCI).  A size on such a bus cannot
    be represented with a 64-bit data type, if both 0 and the entire address
    space size are to be represented.  Futhermore, any address arithemetic may
    overflow and return unexpected results.
    
    Introduce a 128-bit signed integer type for use in such cases.  Addition,
    subtraction, and comparison are the only operations supported.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/int128.h b/int128.h
new file mode 100644
index 0000000..b3864b6
--- /dev/null
+++ b/int128.h
@@ -0,0 +1,116 @@
+#ifndef INT128_H
+#define INT128_H
+
+typedef struct Int128 Int128;
+
+struct Int128 {
+    uint64_t lo;
+    int64_t hi;
+};
+
+static inline Int128 int128_make64(uint64_t a)
+{
+    return (Int128) { a, 0 };
+}
+
+static inline uint64_t int128_get64(Int128 a)
+{
+    assert(!a.hi);
+    return a.lo;
+}
+
+static inline Int128 int128_zero(void)
+{
+    return int128_make64(0);
+}
+
+static inline Int128 int128_one(void)
+{
+    return int128_make64(1);
+}
+
+static inline Int128 int128_2_64(void)
+{
+    return (Int128) { 0, 1 };
+}
+
+static inline Int128 int128_add(Int128 a, Int128 b)
+{
+    Int128 r = { a.lo + b.lo, a.hi + b.hi };
+    r.hi += (r.lo < a.lo) || (r.lo < b.lo);
+    return r;
+}
+
+static inline Int128 int128_neg(Int128 a)
+{
+    a.lo = ~a.lo;
+    a.hi = ~a.hi;
+    return int128_add(a, int128_one());
+}
+
+static inline Int128 int128_sub(Int128 a, Int128 b)
+{
+    return int128_add(a, int128_neg(b));
+}
+
+static inline bool int128_nonneg(Int128 a)
+{
+    return a.hi >= 0;
+}
+
+static inline bool int128_eq(Int128 a, Int128 b)
+{
+    return a.lo == b.lo && a.hi == b.hi;
+}
+
+static inline bool int128_ne(Int128 a, Int128 b)
+{
+    return !int128_eq(a, b);
+}
+
+static inline bool int128_ge(Int128 a, Int128 b)
+{
+    return int128_nonneg(int128_sub(a, b));
+}
+
+static inline bool int128_lt(Int128 a, Int128 b)
+{
+    return !int128_ge(a, b);
+}
+
+static inline bool int128_le(Int128 a, Int128 b)
+{
+    return int128_ge(b, a);
+}
+
+static inline bool int128_gt(Int128 a, Int128 b)
+{
+    return !int128_le(a, b);
+}
+
+static inline bool int128_nz(Int128 a)
+{
+    return a.lo || a.hi;
+}
+
+static inline Int128 int128_min(Int128 a, Int128 b)
+{
+    return int128_le(a, b) ? a : b;
+}
+
+static inline Int128 int128_max(Int128 a, Int128 b)
+{
+    return int128_ge(a, b) ? a : b;
+}
+
+static inline void int128_addto(Int128 *a, Int128 b)
+{
+    *a = int128_add(*a, b);
+}
+
+static inline void int128_subfrom(Int128 *a, Int128 b)
+{
+    *a = int128_sub(*a, b);
+}
+
+#endif


More information about the Spice-commits mailing list