[Spice-commits] 233 commits - .gitignore CODING_STYLE Makefile Makefile.hw Makefile.objs Makefile.target VERSION block.c block.h block/qcow2-cache.c block/qcow2-refcount.c block/qcow2.h block/raw-posix.c block/raw-win32.c block/sheepdog.c block/vmdk.c block_int.h blockdev.c bsd-user/main.c bswap.h compatfd.c compatfd.h compiler.h configure console.c console.h cpu-all.h cpu-common.h cpus.c darwin-user/main.c docs/memory.txt docs/qapi-code-gen.txt dyngen-exec.h error.h exec-all.h exec-memory.h exec.c fpu/softfloat-specialize.h fpu/softfloat.h gdbstub.c hmp-commands.hx hw/a9mpcore.c hw/acpi.c hw/acpi_piix4.c hw/an5206.c hw/apb_pci.c hw/arm-misc.h hw/arm11mpcore.c hw/arm_boot.c hw/arm_gic.c hw/arm_pic.c hw/arm_sysctl.c hw/arm_timer.c hw/armv7m_nvic.c hw/axis_dev88.c hw/baum.c hw/baum.h hw/bitbang_i2c.c hw/bonito.c hw/ccid-card-emulated.c hw/ccid.h hw/dp8393x.c hw/ds1225y.c hw/ds1338.c hw/dummy_m68k.c hw/esp.c hw/etraxfs_eth.c hw/flash.h hw/fw_cfg.c hw/grackle_pci.c hw/gt64xxx.c hw/hw.h hw/i2c.c hw/i2c.h hw/ide hw/ide.h hw/integratorcp.c hw/lan9118.c hw/lm832x.c hw/lsi53c895a.c hw/marvell_88w8618_audio.c hw/mc146818rtc.c hw/mcf5206.c hw/mcf5208.c hw/mcf_fec.c hw/mcf_intc.c hw/mcf_uart.c hw/mips.h hw/mips_jazz.c hw/mipsnet.c hw/mpcore.c hw/msmouse.c hw/msmouse.h hw/multiboot.c hw/musicpal.c hw/nand.c hw/nseries.c hw/omap.h hw/omap1.c hw/omap2.c hw/omap_clk.c hw/omap_gpio.c hw/omap_l4.c hw/onenand.c hw/palm.c hw/pc.c hw/pc.h hw/pc_piix.c hw/pci.c hw/pci.h hw/pci_host.h hw/pci_internals.h hw/piix_pci.c hw/pl011.c hw/pl022.c hw/pl050.c hw/pl061.c hw/pl080.c hw/pl110.c hw/pl110_template.h hw/pl181.c hw/pl190.c hw/ppc4xx_pci.c hw/ppc_mac.h hw/ppc_newworld.c hw/ppc_oldworld.c hw/ppc_prep.c hw/ppce500_pci.c hw/prep_pci.c hw/prep_pci.h hw/ptimer.c hw/pxa.h hw/pxa2xx.c hw/pxa2xx_dma.c hw/pxa2xx_pic.c hw/pxa2xx_timer.c hw/qdev.c hw/qxl.c hw/realview.c hw/realview_gic.c hw/scsi-bus.c hw/scsi-disk.c hw/scsi-generic.c hw/scsi.h hw/sd.c hw/sh_intc.c hw/sh_pci.c hw/sh_time r.c hw/smbus.c hw/smc91c111.c hw/spapr_hcall.c hw/spapr_vscsi.c hw/spitz.c hw/ssd0303.c hw/ssd0323.c hw/ssi-sd.c hw/ssi.c hw/stellaris.c hw/stellaris_enet.c hw/stellaris_input.c hw/sysbus.c hw/sysbus.h hw/tc6393xb.c hw/unin_pci.c hw/usb-bt.c hw/usb-ccid.c hw/usb-ehci.c hw/usb-hid.c hw/usb-msd.c hw/usb-net.c hw/usb-ohci.c hw/usb-serial.c hw/usb-uhci.c hw/usb-wacom.c hw/versatile_pci.c hw/versatilepb.c hw/vga_int.h hw/virtio-console.c hw/virtio-net.c hw/virtio-serial-bus.c hw/xen.h hw/xen_devconfig.c hw/xen_platform.c hw/z2.c input.c ioport.c ioport.h iov.c iov.h libcacard/Makefile libcacard/libcacard.pc.in libcacard/vcard_emul_nss.c linux-user/main.c linux-user/syscall.c memory.c memory.h migration.c module.h monitor.c nbd.c net.c net.h net/slirp.c net/socket.c notify.c notify.h oslib-posix.c pc-bios/README pc-bios/openbios-sparc32 pc-bios/openbios-sparc64 poison.h qapi-schema-guest.json qapi-schema-test.json qapi/qapi-dealloc-visitor.c qapi/qapi-dealloc-visitor.h qapi/qapi-t ypes-core.h qapi/qapi-visit-core.c qapi/qapi-visit-core.h qapi/qmp-core.h qapi/qmp-dispatch.c qapi/qmp-input-visitor.c qapi/qmp-input-visitor.h qapi/qmp-output-visitor.c qapi/qmp-output-visitor.h qapi/qmp-registry.c qemu-char.c qemu-char.h qemu-common.h qemu-config.c qemu-ga.c qemu-img-cmds.hx qemu-img.c qemu-img.texi qemu-io.c qemu-options.hx qemu-timer.c qemu-timer.h qerror.c qerror.h qga/guest-agent-command-state.c qga/guest-agent-commands.c qga/guest-agent-core.h qlist.h qmp-commands.hx savevm.c scripts/checkpatch.pl scripts/ordereddict.py scripts/qapi-commands.py scripts/qapi-types.py scripts/qapi-visit.py scripts/qapi.py simpletrace.c slirp/ip_icmp.c slirp/ip_icmp.h slirp/ip_input.c slirp/ip_output.c slirp/mbuf.h slirp/misc.c slirp/slirp.c slirp/slirp.h slirp/socket.c slirp/tcp_input.c slirp/tcp_subr.c slirp/udp.c softmmu-semi.h spice-qemu-char.c sysemu.h target-alpha/cpu.h target-alpha/exec.h target-alpha/op_helper.c target-arm/cpu.h target-arm/exec.h target-arm/helpe r.c target-arm/helper.h target-arm/iwmmxt_helper.c target-arm/machine.c target-arm/neon_helper.c target-arm/op_addsub.h target-arm/op_helper.c target-arm/translate.c target-cris/exec.h target-cris/op_helper.c target-i386/cpu.h target-i386/exec.h target-i386/helper.c target-i386/op_helper.c target-lm32/exec.h target-lm32/op_helper.c target-m68k/exec.h target-m68k/op_helper.c target-microblaze/cpu.h target-microblaze/exec.h target-microblaze/op_helper.c target-microblaze/translate.c target-mips/cpu.h target-mips/exec.h target-mips/op_helper.c target-ppc/exec.h target-ppc/op_helper.c target-s390x/exec.h target-s390x/op_helper.c target-sh4/exec.h target-sh4/op_helper.c target-sparc/cpu.h target-sparc/exec.h target-sparc/helper.c target-sparc/helper.h target-sparc/op_helper.c target-sparc/translate.c target-unicore32/exec.h target-unicore32/op_helper.c tcg/mips tcg/optimize.c tcg/tcg.c tcg/tcg.h test-qmp-commands.c test-visitor.c trace-events ui/qemu-spice.h ui/sdl.c ui/spice-cor e.c ui/spice-input.c ui/vnc-auth-sasl.c ui/vnc-auth-vencrypt.c ui/vnc-tls.c ui/vnc.c ui/vnc.h usb-linux.c usb-redir.c user-exec.c vl.c xen-all.c xen-mapcache.c xen-mapcache.h

Gerd Hoffmann kraxel at kemper.freedesktop.org
Wed Aug 3 03:06:57 PDT 2011


 .gitignore                      |    2 
 CODING_STYLE                    |    4 
 Makefile                        |   49 
 Makefile.hw                     |    2 
 Makefile.objs                   |   11 
 Makefile.target                 |    9 
 VERSION                         |    2 
 block.c                         |   19 
 block.h                         |    1 
 block/qcow2-cache.c             |   12 
 block/qcow2-refcount.c          |   38 
 block/qcow2.h                   |    2 
 block/raw-posix.c               |   21 
 block/raw-win32.c               |   29 
 block/sheepdog.c                |   73 +
 block/vmdk.c                    | 1297 +++++++++++++------
 block_int.h                     |    2 
 blockdev.c                      |    4 
 bsd-user/main.c                 |    8 
 bswap.h                         |  474 +++++++
 compatfd.c                      |   11 
 compatfd.h                      |    1 
 compiler.h                      |   34 
 configure                       |  119 +
 console.c                       |    8 
 console.h                       |    3 
 cpu-all.h                       |  446 ------
 cpu-common.h                    |   31 
 cpus.c                          |   24 
 darwin-user/main.c              |    8 
 docs/memory.txt                 |  172 ++
 docs/qapi-code-gen.txt          |  316 ++++
 dyngen-exec.h                   |    2 
 error.h                         |    1 
 exec-all.h                      |    2 
 exec-memory.h                   |   39 
 exec.c                          |   44 
 fpu/softfloat-specialize.h      |   72 +
 fpu/softfloat.h                 |   60 
 gdbstub.c                       |    2 
 hmp-commands.hx                 |    2 
 hw/a9mpcore.c                   |    2 
 hw/acpi.c                       |  298 ++--
 hw/acpi_piix4.c                 |   22 
 hw/an5206.c                     |    2 
 hw/apb_pci.c                    |    2 
 hw/arm-misc.h                   |    2 
 hw/arm11mpcore.c                |    2 
 hw/arm_boot.c                   |    2 
 hw/arm_gic.c                    |    2 
 hw/arm_pic.c                    |    2 
 hw/arm_sysctl.c                 |    2 
 hw/arm_timer.c                  |    2 
 hw/armv7m_nvic.c                |    2 
 hw/axis_dev88.c                 |    8 
 hw/baum.c                       |    7 
 hw/baum.h                       |    2 
 hw/bitbang_i2c.c                |    2 
 hw/bonito.c                     |    4 
 hw/ccid-card-emulated.c         |    2 
 hw/ccid.h                       |    3 
 hw/dp8393x.c                    |    2 
 hw/ds1225y.c                    |  152 +-
 hw/ds1338.c                     |    2 
 hw/dummy_m68k.c                 |    2 
 hw/esp.c                        |    2 
 hw/etraxfs_eth.c                |    2 
 hw/flash.h                      |   17 
 hw/fw_cfg.c                     |  142 ++
 hw/grackle_pci.c                |    5 
 hw/gt64xxx.c                    |    4 
 hw/hw.h                         |    1 
 hw/i2c.c                        |    2 
 hw/i2c.h                        |    2 
 hw/ide.h                        |    1 
 hw/ide/ich.c                    |    6 
 hw/ide/piix.c                   |   44 
 hw/ide/qdev.c                   |    5 
 hw/integratorcp.c               |    2 
 hw/lan9118.c                    |    2 
 hw/lm832x.c                     |    4 
 hw/lsi53c895a.c                 |   24 
 hw/marvell_88w8618_audio.c      |    2 
 hw/mc146818rtc.c                |   20 
 hw/mcf5206.c                    |    2 
 hw/mcf5208.c                    |    2 
 hw/mcf_fec.c                    |    4 
 hw/mcf_intc.c                   |    2 
 hw/mcf_uart.c                   |    2 
 hw/mips.h                       |    4 
 hw/mips_jazz.c                  |   10 
 hw/mipsnet.c                    |    2 
 hw/mpcore.c                     |    2 
 hw/msmouse.c                    |    5 
 hw/msmouse.h                    |    2 
 hw/multiboot.c                  |   32 
 hw/musicpal.c                   |    2 
 hw/nand.c                       |  351 +++--
 hw/nseries.c                    |   59 
 hw/omap.h                       |   22 
 hw/omap1.c                      |   10 
 hw/omap2.c                      |   34 
 hw/omap_clk.c                   |    6 
 hw/omap_gpio.c                  |  258 ++-
 hw/omap_l4.c                    |    6 
 hw/onenand.c                    |  172 +-
 hw/palm.c                       |   26 
 hw/pc.c                         |   62 
 hw/pc.h                         |    9 
 hw/pc_piix.c                    |   26 
 hw/pci.c                        |   63 
 hw/pci.h                        |   15 
 hw/pci_host.h                   |    1 
 hw/pci_internals.h              |    1 
 hw/piix_pci.c                   |   13 
 hw/pl011.c                      |    2 
 hw/pl022.c                      |    2 
 hw/pl050.c                      |    2 
 hw/pl061.c                      |    2 
 hw/pl080.c                      |    2 
 hw/pl110.c                      |    2 
 hw/pl110_template.h             |    2 
 hw/pl181.c                      |    2 
 hw/pl190.c                      |    2 
 hw/ppc4xx_pci.c                 |    5 
 hw/ppc_mac.h                    |    9 
 hw/ppc_newworld.c               |    5 
 hw/ppc_oldworld.c               |    3 
 hw/ppc_prep.c                   |    3 
 hw/ppce500_pci.c                |    6 
 hw/prep_pci.c                   |    5 
 hw/prep_pci.h                   |    3 
 hw/ptimer.c                     |    2 
 hw/pxa.h                        |    2 
 hw/pxa2xx.c                     |    2 
 hw/pxa2xx_dma.c                 |    2 
 hw/pxa2xx_pic.c                 |    2 
 hw/pxa2xx_timer.c               |    2 
 hw/qdev.c                       |    5 
 hw/qxl.c                        |    4 
 hw/realview.c                   |    2 
 hw/realview_gic.c               |    2 
 hw/scsi-bus.c                   |    9 
 hw/scsi-disk.c                  |   23 
 hw/scsi-generic.c               |    7 
 hw/scsi.h                       |   10 
 hw/sd.c                         |   23 
 hw/sh_intc.c                    |    2 
 hw/sh_pci.c                     |    4 
 hw/sh_timer.c                   |    2 
 hw/smbus.c                      |    2 
 hw/smc91c111.c                  |    2 
 hw/spapr_hcall.c                |    2 
 hw/spapr_vscsi.c                |   28 
 hw/spitz.c                      |    6 
 hw/ssd0303.c                    |    2 
 hw/ssd0323.c                    |    2 
 hw/ssi-sd.c                     |    2 
 hw/ssi.c                        |    2 
 hw/stellaris.c                  |    4 
 hw/stellaris_enet.c             |    2 
 hw/stellaris_input.c            |    2 
 hw/sysbus.c                     |   27 
 hw/sysbus.h                     |    3 
 hw/tc6393xb.c                   |    7 
 hw/unin_pci.c                   |   10 
 hw/usb-bt.c                     |    6 
 hw/usb-ccid.c                   |   11 
 hw/usb-ehci.c                   |    7 
 hw/usb-hid.c                    |   14 
 hw/usb-msd.c                    |   23 
 hw/usb-net.c                    |    6 
 hw/usb-ohci.c                   |   42 
 hw/usb-serial.c                 |    9 
 hw/usb-uhci.c                   |    6 
 hw/usb-wacom.c                  |    6 
 hw/versatile_pci.c              |    4 
 hw/versatilepb.c                |    2 
 hw/vga_int.h                    |   10 
 hw/virtio-console.c             |    4 
 hw/virtio-net.c                 |    2 
 hw/virtio-serial-bus.c          |   20 
 hw/xen.h                        |    2 
 hw/xen_devconfig.c              |    4 
 hw/xen_platform.c               |   43 
 hw/z2.c                         |  358 +++++
 input.c                         |    2 
 ioport.c                        |   23 
 ioport.h                        |    2 
 iov.c                           |   49 
 iov.h                           |   10 
 libcacard/Makefile              |   27 
 libcacard/libcacard.pc.in       |   13 
 libcacard/vcard_emul_nss.c      |  257 ++-
 linux-user/main.c               |   11 
 linux-user/syscall.c            |    2 
 memory.c                        | 1141 +++++++++++++++++
 memory.h                        |  469 +++++++
 migration.c                     |   12 
 module.h                        |    2 
 monitor.c                       |   34 
 nbd.c                           |    2 
 net.c                           |   65 
 net.h                           |    8 
 net/slirp.c                     |   23 
 net/socket.c                    |    4 
 notify.c                        |    4 
 notify.h                        |    4 
 oslib-posix.c                   |    5 
 pc-bios/README                  |    7 
 pc-bios/openbios-sparc32        |binary
 pc-bios/openbios-sparc64        |binary
 poison.h                        |    9 
 qapi-schema-guest.json          |  217 +++
 qapi-schema-test.json           |   22 
 qapi/qapi-dealloc-visitor.c     |  147 ++
 qapi/qapi-dealloc-visitor.h     |   26 
 qapi/qapi-types-core.h          |   20 
 qapi/qapi-visit-core.c          |  118 +
 qapi/qapi-visit-core.h          |   76 +
 qapi/qmp-core.h                 |   41 
 qapi/qmp-dispatch.c             |  124 +
 qapi/qmp-input-visitor.c        |  301 ++++
 qapi/qmp-input-visitor.h        |   27 
 qapi/qmp-output-visitor.c       |  239 +++
 qapi/qmp-output-visitor.h       |   28 
 qapi/qmp-registry.c             |   40 
 qemu-char.c                     |  204 +--
 qemu-char.h                     |    2 
 qemu-common.h                   |   31 
 qemu-config.c                   |   38 
 qemu-ga.c                       |  637 +++++++++
 qemu-img-cmds.hx                |    4 
 qemu-img.c                      |   31 
 qemu-img.texi                   |    6 
 qemu-io.c                       | 2653 ++++++++++++++++++++--------------------
 qemu-options.hx                 |   70 -
 qemu-timer.c                    |   77 -
 qemu-timer.h                    |    5 
 qerror.c                        |   17 
 qerror.h                        |   12 
 qga/guest-agent-command-state.c |   73 +
 qga/guest-agent-commands.c      |  561 ++++++++
 qga/guest-agent-core.h          |   31 
 qlist.h                         |   11 
 qmp-commands.hx                 |   63 
 savevm.c                        |    3 
 scripts/checkpatch.pl           |    1 
 scripts/ordereddict.py          |  127 +
 scripts/qapi-commands.py        |  385 +++++
 scripts/qapi-types.py           |  270 ++++
 scripts/qapi-visit.py           |  246 +++
 scripts/qapi.py                 |  203 +++
 simpletrace.c                   |    2 
 slirp/ip_icmp.c                 |   95 +
 slirp/ip_icmp.h                 |    3 
 slirp/ip_input.c                |   34 
 slirp/ip_output.c               |    4 
 slirp/mbuf.h                    |    3 
 slirp/misc.c                    |   16 
 slirp/slirp.c                   |   39 
 slirp/slirp.h                   |    5 
 slirp/socket.c                  |    6 
 slirp/tcp_input.c               |   10 
 slirp/tcp_subr.c                |    2 
 slirp/udp.c                     |   23 
 softmmu-semi.h                  |    2 
 spice-qemu-char.c               |    9 
 sysemu.h                        |    3 
 target-alpha/cpu.h              |    5 
 target-alpha/exec.h             |   39 
 target-alpha/op_helper.c        |   13 
 target-arm/cpu.h                |    8 
 target-arm/exec.h               |   30 
 target-arm/helper.c             |  193 ++
 target-arm/helper.h             |  293 ++--
 target-arm/iwmmxt_helper.c      |   80 -
 target-arm/machine.c            |   12 
 target-arm/neon_helper.c        |  203 +--
 target-arm/op_addsub.h          |    2 
 target-arm/op_helper.c          |    9 
 target-arm/translate.c          |  457 ++++--
 target-cris/exec.h              |   28 
 target-cris/op_helper.c         |    4 
 target-i386/cpu.h               |    3 
 target-i386/exec.h              |  142 --
 target-i386/helper.c            |    2 
 target-i386/op_helper.c         |  165 ++
 target-lm32/exec.h              |   38 
 target-lm32/op_helper.c         |    3 
 target-m68k/exec.h              |   28 
 target-m68k/op_helper.c         |    5 
 target-microblaze/cpu.h         |    4 
 target-microblaze/exec.h        |   27 
 target-microblaze/op_helper.c   |   19 
 target-microblaze/translate.c   |    1 
 target-mips/cpu.h               |    6 
 target-mips/exec.h              |   60 
 target-mips/op_helper.c         |   62 
 target-ppc/exec.h               |   34 
 target-ppc/op_helper.c          |    7 
 target-s390x/exec.h             |   37 
 target-s390x/op_helper.c        |    4 
 target-sh4/exec.h               |   33 
 target-sh4/op_helper.c          |    4 
 target-sparc/cpu.h              |   39 
 target-sparc/exec.h             |   15 
 target-sparc/helper.c           |  153 +-
 target-sparc/helper.h           |    4 
 target-sparc/op_helper.c        |   95 -
 target-sparc/translate.c        |  163 ++
 target-unicore32/exec.h         |   43 
 target-unicore32/op_helper.c    |    3 
 tcg/mips/tcg-target.c           |    2 
 tcg/optimize.c                  |  675 ++++++++++
 tcg/tcg.c                       |    6 
 tcg/tcg.h                       |    3 
 test-qmp-commands.c             |  113 +
 test-visitor.c                  |  306 ++++
 trace-events                    |   10 
 ui/qemu-spice.h                 |    2 
 ui/sdl.c                        |    2 
 ui/spice-core.c                 |   13 
 ui/spice-input.c                |    4 
 ui/vnc-auth-sasl.c              |   15 
 ui/vnc-auth-vencrypt.c          |   18 
 ui/vnc-tls.c                    |    2 
 ui/vnc.c                        |   52 
 ui/vnc.h                        |    2 
 usb-linux.c                     |    2 
 usb-redir.c                     | 1218 ++++++++++++++++++
 user-exec.c                     |   49 
 vl.c                            |   88 -
 xen-all.c                       |   56 
 xen-mapcache.c                  |    3 
 xen-mapcache.h                  |   32 
 336 files changed, 16263 insertions(+), 4933 deletions(-)

New commits:
commit 927d721777e73339f73719f36eaf400ab641366c
Author: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
Date:   Sun Jul 31 06:40:13 2011 +0200

    microblaze: Add missing call to qemu_init_vcpu.
    
    Fixes emulation with io-thread.
    
    Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 31e8306..41beb0a 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1850,6 +1850,7 @@ CPUState *cpu_mb_init (const char *cpu_model)
 
     cpu_exec_init(env);
     cpu_reset(env);
+    qemu_init_vcpu(env);
     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
 
     if (tcg_initialized)
commit 2ec00650f66ea624e06d76fadd0918317de1119f
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Jul 30 18:53:27 2011 +0000

    TCG: fix breakage by previous patch
    
    Fix incorrect logic and typos in previous commit
    1bfd07bdfe56cea43dbe258dcb161e46b0ee29b7.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/optimize.c b/tcg/optimize.c
index 6a0a4dd..a3bfa5e 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -318,7 +318,8 @@ static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y)
 #if defined(TCG_TARGET_HAS_not_i32) || defined(TCG_TARGET_HAS_not_i64)
 #ifdef TCG_TARGET_HAS_not_i32
     case INDEX_op_not_i32:
-#else
+#endif
+#ifdef TCG_TARGET_HAS_not_i64
     case INDEX_op_not_i64:
 #endif
         return ~x;
@@ -327,7 +328,8 @@ static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y)
 #if defined(TCG_TARGET_HAS_ext8s_i32) || defined(TCG_TARGET_HAS_ext8s_i64)
 #ifdef TCG_TARGET_HAS_ext8s_i32
     case INDEX_op_ext8s_i32:
-#else
+#endif
+#ifdef TCG_TARGET_HAS_ext8s_i64
     case INDEX_op_ext8s_i64:
 #endif
         return (int8_t)x;
@@ -336,7 +338,8 @@ static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y)
 #if defined(TCG_TARGET_HAS_ext16s_i32) || defined(TCG_TARGET_HAS_ext16s_i64)
 #ifdef TCG_TARGET_HAS_ext16s_i32
     case INDEX_op_ext16s_i32:
-#else
+#endif
+#ifdef TCG_TARGET_HAS_ext16s_i64
     case INDEX_op_ext16s_i64:
 #endif
         return (int16_t)x;
@@ -345,7 +348,8 @@ static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y)
 #if defined(TCG_TARGET_HAS_ext8u_i32) || defined(TCG_TARGET_HAS_ext8u_i64)
 #ifdef TCG_TARGET_HAS_ext8u_i32
     case INDEX_op_ext8u_i32:
-#else
+#endif
+#ifdef TCG_TARGET_HAS_ext8u_i64
     case INDEX_op_ext8u_i64:
 #endif
         return (uint8_t)x;
@@ -354,19 +358,20 @@ static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y)
 #if defined(TCG_TARGET_HAS_ext16u_i32) || defined(TCG_TARGET_HAS_ext16u_i64)
 #ifdef TCG_TARGET_HAS_ext16u_i32
     case INDEX_op_ext16u_i32:
-#else
+#endif
+#ifdef TCG_TARGET_HAS_ext16u_i64
     case INDEX_op_ext16u_i64:
 #endif
         return (uint16_t)x;
 #endif
 
 #if TCG_TARGET_REG_BITS == 64
-#ifdef TCG_TARGET_HAS_ext32s_i32
+#ifdef TCG_TARGET_HAS_ext32s_i64
     case INDEX_op_ext32s_i64:
         return (int32_t)x;
 #endif
 
-#ifdef TCG_TARGET_HAS_ext32u_i32
+#ifdef TCG_TARGET_HAS_ext32u_i64
     case INDEX_op_ext32u_i64:
         return (uint32_t)x;
 #endif
commit 1bfd07bdfe56cea43dbe258dcb161e46b0ee29b7
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Jul 30 12:21:33 2011 +0000

    TCG: fix breakage on some RISC hosts
    
    Fix breakage by a640f03178c22355a158fa9378e4f8bfa4f517a6
    and 55c0975c5b358e948b9ae7bd7b07eff92508e756.
    
    Some TCG targets don't implement all TCG ops, so make
    optimizing those conditional.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/optimize.c b/tcg/optimize.c
index a324e98..6a0a4dd 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -105,13 +105,25 @@ static int op_bits(int op)
     case INDEX_op_shl_i32:
     case INDEX_op_shr_i32:
     case INDEX_op_sar_i32:
+#ifdef TCG_TARGET_HAS_rot_i32
     case INDEX_op_rotl_i32:
     case INDEX_op_rotr_i32:
+#endif
+#ifdef TCG_TARGET_HAS_not_i32
     case INDEX_op_not_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext8s_i32
     case INDEX_op_ext8s_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext16s_i32
     case INDEX_op_ext16s_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext8u_i32
     case INDEX_op_ext8u_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext16u_i32
     case INDEX_op_ext16u_i32:
+#endif
         return 32;
 #if TCG_TARGET_REG_BITS == 64
     case INDEX_op_mov_i64:
@@ -124,15 +136,31 @@ static int op_bits(int op)
     case INDEX_op_shl_i64:
     case INDEX_op_shr_i64:
     case INDEX_op_sar_i64:
+#ifdef TCG_TARGET_HAS_rot_i64
     case INDEX_op_rotl_i64:
     case INDEX_op_rotr_i64:
+#endif
+#ifdef TCG_TARGET_HAS_not_i64
     case INDEX_op_not_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext8s_i64
     case INDEX_op_ext8s_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext16s_i64
     case INDEX_op_ext16s_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext32s_i64
     case INDEX_op_ext32s_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext8u_i64
     case INDEX_op_ext8u_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext16u_i64
     case INDEX_op_ext16u_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext32u_i64
     case INDEX_op_ext32u_i64:
+#endif
         return 64;
 #endif
     default:
@@ -251,6 +279,7 @@ static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y)
         return (int64_t)x >> (int64_t)y;
 #endif
 
+#ifdef TCG_TARGET_HAS_rot_i32
     case INDEX_op_rotr_i32:
 #if TCG_TARGET_REG_BITS == 64
         x &= 0xffffffff;
@@ -258,13 +287,17 @@ static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y)
 #endif
         x = (x << (32 - y)) | (x >> y);
         return x;
+#endif
 
+#ifdef TCG_TARGET_HAS_rot_i64
 #if TCG_TARGET_REG_BITS == 64
     case INDEX_op_rotr_i64:
         x = (x << (64 - y)) | (x >> y);
         return x;
 #endif
+#endif
 
+#ifdef TCG_TARGET_HAS_rot_i32
     case INDEX_op_rotl_i32:
 #if TCG_TARGET_REG_BITS == 64
         x &= 0xffffffff;
@@ -272,35 +305,72 @@ static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y)
 #endif
         x = (x << y) | (x >> (32 - y));
         return x;
+#endif
 
+#ifdef TCG_TARGET_HAS_rot_i64
 #if TCG_TARGET_REG_BITS == 64
     case INDEX_op_rotl_i64:
         x = (x << y) | (x >> (64 - y));
         return x;
 #endif
+#endif
 
-    CASE_OP_32_64(not):
+#if defined(TCG_TARGET_HAS_not_i32) || defined(TCG_TARGET_HAS_not_i64)
+#ifdef TCG_TARGET_HAS_not_i32
+    case INDEX_op_not_i32:
+#else
+    case INDEX_op_not_i64:
+#endif
         return ~x;
+#endif
 
-    CASE_OP_32_64(ext8s):
+#if defined(TCG_TARGET_HAS_ext8s_i32) || defined(TCG_TARGET_HAS_ext8s_i64)
+#ifdef TCG_TARGET_HAS_ext8s_i32
+    case INDEX_op_ext8s_i32:
+#else
+    case INDEX_op_ext8s_i64:
+#endif
         return (int8_t)x;
+#endif
 
-    CASE_OP_32_64(ext16s):
+#if defined(TCG_TARGET_HAS_ext16s_i32) || defined(TCG_TARGET_HAS_ext16s_i64)
+#ifdef TCG_TARGET_HAS_ext16s_i32
+    case INDEX_op_ext16s_i32:
+#else
+    case INDEX_op_ext16s_i64:
+#endif
         return (int16_t)x;
+#endif
 
-    CASE_OP_32_64(ext8u):
+#if defined(TCG_TARGET_HAS_ext8u_i32) || defined(TCG_TARGET_HAS_ext8u_i64)
+#ifdef TCG_TARGET_HAS_ext8u_i32
+    case INDEX_op_ext8u_i32:
+#else
+    case INDEX_op_ext8u_i64:
+#endif
         return (uint8_t)x;
+#endif
 
-    CASE_OP_32_64(ext16u):
+#if defined(TCG_TARGET_HAS_ext16u_i32) || defined(TCG_TARGET_HAS_ext16u_i64)
+#ifdef TCG_TARGET_HAS_ext16u_i32
+    case INDEX_op_ext16u_i32:
+#else
+    case INDEX_op_ext16u_i64:
+#endif
         return (uint16_t)x;
+#endif
 
 #if TCG_TARGET_REG_BITS == 64
+#ifdef TCG_TARGET_HAS_ext32s_i32
     case INDEX_op_ext32s_i64:
         return (int32_t)x;
+#endif
 
+#ifdef TCG_TARGET_HAS_ext32u_i32
     case INDEX_op_ext32u_i64:
         return (uint32_t)x;
 #endif
+#endif
 
     default:
         fprintf(stderr,
@@ -378,8 +448,14 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
         CASE_OP_32_64(shl):
         CASE_OP_32_64(shr):
         CASE_OP_32_64(sar):
-        CASE_OP_32_64(rotl):
-        CASE_OP_32_64(rotr):
+#ifdef TCG_TARGET_HAS_rot_i32
+        case INDEX_op_rotl_i32:
+        case INDEX_op_rotr_i32:
+#endif
+#ifdef TCG_TARGET_HAS_rot_i64
+        case INDEX_op_rotl_i64:
+        case INDEX_op_rotr_i64:
+#endif
             if (temps[args[1]].state == TCG_TEMP_CONST) {
                 /* Proceed with possible constant folding. */
                 break;
@@ -460,10 +536,30 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
             args += 2;
             break;
         CASE_OP_32_64(not):
-        CASE_OP_32_64(ext8s):
-        CASE_OP_32_64(ext16s):
-        CASE_OP_32_64(ext8u):
-        CASE_OP_32_64(ext16u):
+#ifdef TCG_TARGET_HAS_ext8s_i32
+        case INDEX_op_ext8s_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext8s_i64
+        case INDEX_op_ext8s_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext16s_i32
+        case INDEX_op_ext16s_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext16s_i64
+        case INDEX_op_ext16s_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext8u_i32
+        case INDEX_op_ext8u_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext8u_i64
+        case INDEX_op_ext8u_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext16u_i32
+        case INDEX_op_ext16u_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext16u_i64
+        case INDEX_op_ext16u_i64:
+#endif
 #if TCG_TARGET_REG_BITS == 64
         case INDEX_op_ext32s_i64:
         case INDEX_op_ext32u_i64:
@@ -492,8 +588,14 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
         CASE_OP_32_64(shl):
         CASE_OP_32_64(shr):
         CASE_OP_32_64(sar):
-        CASE_OP_32_64(rotl):
-        CASE_OP_32_64(rotr):
+#ifdef TCG_TARGET_HAS_rot_i32
+        case INDEX_op_rotl_i32:
+        case INDEX_op_rotr_i32:
+#endif
+#ifdef TCG_TARGET_HAS_rot_i64
+        case INDEX_op_rotl_i64:
+        case INDEX_op_rotr_i64:
+#endif
             if (temps[args[1]].state == TCG_TEMP_CONST
                 && temps[args[2]].state == TCG_TEMP_CONST) {
                 gen_opc_buf[op_index] = op_to_movi(op);
commit a640f03178c22355a158fa9378e4f8bfa4f517a6
Author: Kirill Batuzov <batuzovk at ispras.ru>
Date:   Thu Jul 7 16:37:17 2011 +0400

    Do constant folding for unary operations.
    
    Perform constant folding for NOT and EXT{8,16,32}{S,U} operations.
    
    Signed-off-by: Kirill Batuzov <batuzovk at ispras.ru>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/optimize.c b/tcg/optimize.c
index a1bb287..a324e98 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -107,6 +107,11 @@ static int op_bits(int op)
     case INDEX_op_sar_i32:
     case INDEX_op_rotl_i32:
     case INDEX_op_rotr_i32:
+    case INDEX_op_not_i32:
+    case INDEX_op_ext8s_i32:
+    case INDEX_op_ext16s_i32:
+    case INDEX_op_ext8u_i32:
+    case INDEX_op_ext16u_i32:
         return 32;
 #if TCG_TARGET_REG_BITS == 64
     case INDEX_op_mov_i64:
@@ -121,6 +126,13 @@ static int op_bits(int op)
     case INDEX_op_sar_i64:
     case INDEX_op_rotl_i64:
     case INDEX_op_rotr_i64:
+    case INDEX_op_not_i64:
+    case INDEX_op_ext8s_i64:
+    case INDEX_op_ext16s_i64:
+    case INDEX_op_ext32s_i64:
+    case INDEX_op_ext8u_i64:
+    case INDEX_op_ext16u_i64:
+    case INDEX_op_ext32u_i64:
         return 64;
 #endif
     default:
@@ -267,6 +279,29 @@ static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y)
         return x;
 #endif
 
+    CASE_OP_32_64(not):
+        return ~x;
+
+    CASE_OP_32_64(ext8s):
+        return (int8_t)x;
+
+    CASE_OP_32_64(ext16s):
+        return (int16_t)x;
+
+    CASE_OP_32_64(ext8u):
+        return (uint8_t)x;
+
+    CASE_OP_32_64(ext16u):
+        return (uint16_t)x;
+
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_ext32s_i64:
+        return (int32_t)x;
+
+    case INDEX_op_ext32u_i64:
+        return (uint32_t)x;
+#endif
+
     default:
         fprintf(stderr,
                 "Unrecognized operation %d in do_constant_folding.\n", op);
@@ -424,6 +459,30 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
             gen_args += 2;
             args += 2;
             break;
+        CASE_OP_32_64(not):
+        CASE_OP_32_64(ext8s):
+        CASE_OP_32_64(ext16s):
+        CASE_OP_32_64(ext8u):
+        CASE_OP_32_64(ext16u):
+#if TCG_TARGET_REG_BITS == 64
+        case INDEX_op_ext32s_i64:
+        case INDEX_op_ext32u_i64:
+#endif
+            if (temps[args[1]].state == TCG_TEMP_CONST) {
+                gen_opc_buf[op_index] = op_to_movi(op);
+                tmp = do_constant_folding(op, temps[args[1]].val, 0);
+                tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
+                gen_args += 2;
+                args += 2;
+                break;
+            } else {
+                reset_temp(args[0], nb_temps, nb_globals);
+                gen_args[0] = args[0];
+                gen_args[1] = args[1];
+                gen_args += 2;
+                args += 2;
+                break;
+            }
         CASE_OP_32_64(add):
         CASE_OP_32_64(sub):
         CASE_OP_32_64(mul):
commit 55c0975c5b358e948b9ae7bd7b07eff92508e756
Author: Kirill Batuzov <batuzovk at ispras.ru>
Date:   Thu Jul 7 16:37:16 2011 +0400

    Do constant folding for shift operations.
    
    Perform constant forlding for SHR, SHL, SAR, ROTR, ROTL operations.
    
    Signed-off-by: Kirill Batuzov <batuzovk at ispras.ru>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/optimize.c b/tcg/optimize.c
index c469952..a1bb287 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -102,6 +102,11 @@ static int op_bits(int op)
     case INDEX_op_and_i32:
     case INDEX_op_or_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:
+    case INDEX_op_rotr_i32:
         return 32;
 #if TCG_TARGET_REG_BITS == 64
     case INDEX_op_mov_i64:
@@ -111,6 +116,11 @@ static int op_bits(int op)
     case INDEX_op_and_i64:
     case INDEX_op_or_i64:
     case INDEX_op_xor_i64:
+    case INDEX_op_shl_i64:
+    case INDEX_op_shr_i64:
+    case INDEX_op_sar_i64:
+    case INDEX_op_rotl_i64:
+    case INDEX_op_rotr_i64:
         return 64;
 #endif
     default:
@@ -205,6 +215,58 @@ static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y)
     CASE_OP_32_64(xor):
         return x ^ y;
 
+    case INDEX_op_shl_i32:
+        return (uint32_t)x << (uint32_t)y;
+
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_shl_i64:
+        return (uint64_t)x << (uint64_t)y;
+#endif
+
+    case INDEX_op_shr_i32:
+        return (uint32_t)x >> (uint32_t)y;
+
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_shr_i64:
+        return (uint64_t)x >> (uint64_t)y;
+#endif
+
+    case INDEX_op_sar_i32:
+        return (int32_t)x >> (int32_t)y;
+
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_sar_i64:
+        return (int64_t)x >> (int64_t)y;
+#endif
+
+    case INDEX_op_rotr_i32:
+#if TCG_TARGET_REG_BITS == 64
+        x &= 0xffffffff;
+        y &= 0xffffffff;
+#endif
+        x = (x << (32 - y)) | (x >> y);
+        return x;
+
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_rotr_i64:
+        x = (x << (64 - y)) | (x >> y);
+        return x;
+#endif
+
+    case INDEX_op_rotl_i32:
+#if TCG_TARGET_REG_BITS == 64
+        x &= 0xffffffff;
+        y &= 0xffffffff;
+#endif
+        x = (x << y) | (x >> (32 - y));
+        return x;
+
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_rotl_i64:
+        x = (x << y) | (x >> (64 - y));
+        return x;
+#endif
+
     default:
         fprintf(stderr,
                 "Unrecognized operation %d in do_constant_folding.\n", op);
@@ -278,6 +340,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
         switch (op) {
         CASE_OP_32_64(add):
         CASE_OP_32_64(sub):
+        CASE_OP_32_64(shl):
+        CASE_OP_32_64(shr):
+        CASE_OP_32_64(sar):
+        CASE_OP_32_64(rotl):
+        CASE_OP_32_64(rotr):
             if (temps[args[1]].state == TCG_TEMP_CONST) {
                 /* Proceed with possible constant folding. */
                 break;
@@ -363,6 +430,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
         CASE_OP_32_64(or):
         CASE_OP_32_64(and):
         CASE_OP_32_64(xor):
+        CASE_OP_32_64(shl):
+        CASE_OP_32_64(shr):
+        CASE_OP_32_64(sar):
+        CASE_OP_32_64(rotl):
+        CASE_OP_32_64(rotr):
             if (temps[args[1]].state == TCG_TEMP_CONST
                 && temps[args[2]].state == TCG_TEMP_CONST) {
                 gen_opc_buf[op_index] = op_to_movi(op);
commit 9a81090b12a3141ff1f1b4dc331042efbdfd2ad8
Author: Kirill Batuzov <batuzovk at ispras.ru>
Date:   Thu Jul 7 16:37:15 2011 +0400

    Do constant folding for boolean operations.
    
    Perform constant folding for AND, OR, XOR operations.
    
    Signed-off-by: Kirill Batuzov <batuzovk at ispras.ru>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/optimize.c b/tcg/optimize.c
index 42a1bda..c469952 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -99,12 +99,18 @@ static int op_bits(int op)
     case INDEX_op_add_i32:
     case INDEX_op_sub_i32:
     case INDEX_op_mul_i32:
+    case INDEX_op_and_i32:
+    case INDEX_op_or_i32:
+    case INDEX_op_xor_i32:
         return 32;
 #if TCG_TARGET_REG_BITS == 64
     case INDEX_op_mov_i64:
     case INDEX_op_add_i64:
     case INDEX_op_sub_i64:
     case INDEX_op_mul_i64:
+    case INDEX_op_and_i64:
+    case INDEX_op_or_i64:
+    case INDEX_op_xor_i64:
         return 64;
 #endif
     default:
@@ -190,6 +196,15 @@ static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y)
     CASE_OP_32_64(mul):
         return x * y;
 
+    CASE_OP_32_64(and):
+        return x & y;
+
+    CASE_OP_32_64(or):
+        return x | y;
+
+    CASE_OP_32_64(xor):
+        return x ^ y;
+
     default:
         fprintf(stderr,
                 "Unrecognized operation %d in do_constant_folding.\n", op);
@@ -246,6 +261,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
         switch (op) {
         CASE_OP_32_64(add):
         CASE_OP_32_64(mul):
+        CASE_OP_32_64(and):
+        CASE_OP_32_64(or):
+        CASE_OP_32_64(xor):
             if (temps[args[1]].state == TCG_TEMP_CONST) {
                 tmp = args[1];
                 args[1] = args[2];
@@ -291,6 +309,22 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                 continue;
             }
             break;
+        CASE_OP_32_64(or):
+        CASE_OP_32_64(and):
+            if (args[1] == args[2]) {
+                if (args[1] == args[0]) {
+                    args += 3;
+                    gen_opc_buf[op_index] = INDEX_op_nop;
+                } else {
+                    gen_opc_buf[op_index] = op_to_mov(op);
+                    tcg_opt_gen_mov(gen_args, args[0], args[1], nb_temps,
+                                    nb_globals);
+                    gen_args += 2;
+                    args += 3;
+                }
+                continue;
+            }
+            break;
         }
 
         /* Propagate constants through copy operations and do constant
@@ -326,6 +360,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
         CASE_OP_32_64(add):
         CASE_OP_32_64(sub):
         CASE_OP_32_64(mul):
+        CASE_OP_32_64(or):
+        CASE_OP_32_64(and):
+        CASE_OP_32_64(xor):
             if (temps[args[1]].state == TCG_TEMP_CONST
                 && temps[args[2]].state == TCG_TEMP_CONST) {
                 gen_opc_buf[op_index] = op_to_movi(op);
commit 53108fb57413cf6f3d81a71a70257d49a73569c7
Author: Kirill Batuzov <batuzovk at ispras.ru>
Date:   Thu Jul 7 16:37:14 2011 +0400

    Do constant folding for basic arithmetic operations.
    
    Perform actual constant folding for ADD, SUB and MUL operations.
    
    Signed-off-by: Kirill Batuzov <batuzovk at ispras.ru>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/optimize.c b/tcg/optimize.c
index f8afe71..42a1bda 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -96,9 +96,15 @@ static int op_bits(int op)
 {
     switch (op) {
     case INDEX_op_mov_i32:
+    case INDEX_op_add_i32:
+    case INDEX_op_sub_i32:
+    case INDEX_op_mul_i32:
         return 32;
 #if TCG_TARGET_REG_BITS == 64
     case INDEX_op_mov_i64:
+    case INDEX_op_add_i64:
+    case INDEX_op_sub_i64:
+    case INDEX_op_mul_i64:
         return 64;
 #endif
     default:
@@ -156,6 +162,52 @@ static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val,
         gen_args[1] = val;
 }
 
+static int op_to_mov(int op)
+{
+    switch (op_bits(op)) {
+    case 32:
+        return INDEX_op_mov_i32;
+#if TCG_TARGET_REG_BITS == 64
+    case 64:
+        return INDEX_op_mov_i64;
+#endif
+    default:
+        fprintf(stderr, "op_to_mov: unexpected return value of "
+                "function op_bits.\n");
+        tcg_abort();
+    }
+}
+
+static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y)
+{
+    switch (op) {
+    CASE_OP_32_64(add):
+        return x + y;
+
+    CASE_OP_32_64(sub):
+        return x - y;
+
+    CASE_OP_32_64(mul):
+        return x * y;
+
+    default:
+        fprintf(stderr,
+                "Unrecognized operation %d in do_constant_folding.\n", op);
+        tcg_abort();
+    }
+}
+
+static TCGArg do_constant_folding(int op, TCGArg x, TCGArg y)
+{
+    TCGArg res = do_constant_folding_2(op, x, y);
+#if TCG_TARGET_REG_BITS == 64
+    if (op_bits(op) == 32) {
+        res &= 0xffffffff;
+    }
+#endif
+    return res;
+}
+
 /* Propagate constants and copies, fold constant expressions. */
 static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                                     TCGArg *args, TCGOpDef *tcg_op_defs)
@@ -163,6 +215,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
     int i, nb_ops, op_index, op, nb_temps, nb_globals, nb_call_args;
     const TCGOpDef *def;
     TCGArg *gen_args;
+    TCGArg tmp;
     /* Array VALS has an element for each temp.
        If this temp holds a constant then its value is kept in VALS' element.
        If this temp is a copy of other ones then this equivalence class'
@@ -189,6 +242,57 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
             }
         }
 
+        /* For commutative operations make constant second argument */
+        switch (op) {
+        CASE_OP_32_64(add):
+        CASE_OP_32_64(mul):
+            if (temps[args[1]].state == TCG_TEMP_CONST) {
+                tmp = args[1];
+                args[1] = args[2];
+                args[2] = tmp;
+            }
+            break;
+        default:
+            break;
+        }
+
+        /* Simplify expression if possible. */
+        switch (op) {
+        CASE_OP_32_64(add):
+        CASE_OP_32_64(sub):
+            if (temps[args[1]].state == TCG_TEMP_CONST) {
+                /* Proceed with possible constant folding. */
+                break;
+            }
+            if (temps[args[2]].state == TCG_TEMP_CONST
+                && temps[args[2]].val == 0) {
+                if ((temps[args[0]].state == TCG_TEMP_COPY
+                    && temps[args[0]].val == args[1])
+                    || args[0] == args[1]) {
+                    args += 3;
+                    gen_opc_buf[op_index] = INDEX_op_nop;
+                } else {
+                    gen_opc_buf[op_index] = op_to_mov(op);
+                    tcg_opt_gen_mov(gen_args, args[0], args[1],
+                                    nb_temps, nb_globals);
+                    gen_args += 2;
+                    args += 3;
+                }
+                continue;
+            }
+            break;
+        CASE_OP_32_64(mul):
+            if ((temps[args[2]].state == TCG_TEMP_CONST
+                && temps[args[2]].val == 0)) {
+                gen_opc_buf[op_index] = op_to_movi(op);
+                tcg_opt_gen_movi(gen_args, args[0], 0, nb_temps, nb_globals);
+                args += 3;
+                gen_args += 2;
+                continue;
+            }
+            break;
+        }
+
         /* Propagate constants through copy operations and do constant
            folding.  Constants will be substituted to arguments by register
            allocator where needed and possible.  Also detect copies. */
@@ -219,6 +323,27 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
             gen_args += 2;
             args += 2;
             break;
+        CASE_OP_32_64(add):
+        CASE_OP_32_64(sub):
+        CASE_OP_32_64(mul):
+            if (temps[args[1]].state == TCG_TEMP_CONST
+                && temps[args[2]].state == TCG_TEMP_CONST) {
+                gen_opc_buf[op_index] = op_to_movi(op);
+                tmp = do_constant_folding(op, temps[args[1]].val,
+                                          temps[args[2]].val);
+                tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
+                gen_args += 2;
+                args += 3;
+                break;
+            } else {
+                reset_temp(args[0], nb_temps, nb_globals);
+                gen_args[0] = args[0];
+                gen_args[1] = args[1];
+                gen_args[2] = args[2];
+                gen_args += 3;
+                args += 3;
+                break;
+            }
         case INDEX_op_call:
             nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
             if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
commit 22613af4a6d9602001e6d0e7b6d98aa40aa018dc
Author: Kirill Batuzov <batuzovk at ispras.ru>
Date:   Thu Jul 7 16:37:13 2011 +0400

    Add copy and constant propagation.
    
    Make tcg_constant_folding do copy and constant propagation. It is a
    preparational work before actual constant folding.
    
    Signed-off-by: Kirill Batuzov <batuzovk at ispras.ru>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/optimize.c b/tcg/optimize.c
index c7c7da9..f8afe71 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -40,24 +40,196 @@
         glue(glue(case INDEX_op_, x), _i32)
 #endif
 
+typedef enum {
+    TCG_TEMP_UNDEF = 0,
+    TCG_TEMP_CONST,
+    TCG_TEMP_COPY,
+    TCG_TEMP_HAS_COPY,
+    TCG_TEMP_ANY
+} tcg_temp_state;
+
+struct tcg_temp_info {
+    tcg_temp_state state;
+    uint16_t prev_copy;
+    uint16_t next_copy;
+    tcg_target_ulong val;
+};
+
+static struct tcg_temp_info temps[TCG_MAX_TEMPS];
+
+/* Reset TEMP's state to TCG_TEMP_ANY.  If TEMP was a representative of some
+   class of equivalent temp's, a new representative should be chosen in this
+   class. */
+static void reset_temp(TCGArg temp, int nb_temps, int nb_globals)
+{
+    int i;
+    TCGArg new_base = (TCGArg)-1;
+    if (temps[temp].state == TCG_TEMP_HAS_COPY) {
+        for (i = temps[temp].next_copy; i != temp; i = temps[i].next_copy) {
+            if (i >= nb_globals) {
+                temps[i].state = TCG_TEMP_HAS_COPY;
+                new_base = i;
+                break;
+            }
+        }
+        for (i = temps[temp].next_copy; i != temp; i = temps[i].next_copy) {
+            if (new_base == (TCGArg)-1) {
+                temps[i].state = TCG_TEMP_ANY;
+            } else {
+                temps[i].val = new_base;
+            }
+        }
+        temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
+        temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
+    } else if (temps[temp].state == TCG_TEMP_COPY) {
+        temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
+        temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
+        new_base = temps[temp].val;
+    }
+    temps[temp].state = TCG_TEMP_ANY;
+    if (new_base != (TCGArg)-1 && temps[new_base].next_copy == new_base) {
+        temps[new_base].state = TCG_TEMP_ANY;
+    }
+}
+
+static int op_bits(int op)
+{
+    switch (op) {
+    case INDEX_op_mov_i32:
+        return 32;
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_mov_i64:
+        return 64;
+#endif
+    default:
+        fprintf(stderr, "Unrecognized operation %d in op_bits.\n", op);
+        tcg_abort();
+    }
+}
+
+static int op_to_movi(int op)
+{
+    switch (op_bits(op)) {
+    case 32:
+        return INDEX_op_movi_i32;
+#if TCG_TARGET_REG_BITS == 64
+    case 64:
+        return INDEX_op_movi_i64;
+#endif
+    default:
+        fprintf(stderr, "op_to_movi: unexpected return value of "
+                "function op_bits.\n");
+        tcg_abort();
+    }
+}
+
+static void tcg_opt_gen_mov(TCGArg *gen_args, TCGArg dst, TCGArg src,
+                            int nb_temps, int nb_globals)
+{
+        reset_temp(dst, nb_temps, nb_globals);
+        assert(temps[src].state != TCG_TEMP_COPY);
+        if (src >= nb_globals) {
+            assert(temps[src].state != TCG_TEMP_CONST);
+            if (temps[src].state != TCG_TEMP_HAS_COPY) {
+                temps[src].state = TCG_TEMP_HAS_COPY;
+                temps[src].next_copy = src;
+                temps[src].prev_copy = src;
+            }
+            temps[dst].state = TCG_TEMP_COPY;
+            temps[dst].val = src;
+            temps[dst].next_copy = temps[src].next_copy;
+            temps[dst].prev_copy = src;
+            temps[temps[dst].next_copy].prev_copy = dst;
+            temps[src].next_copy = dst;
+        }
+        gen_args[0] = dst;
+        gen_args[1] = src;
+}
+
+static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val,
+                             int nb_temps, int nb_globals)
+{
+        reset_temp(dst, nb_temps, nb_globals);
+        temps[dst].state = TCG_TEMP_CONST;
+        temps[dst].val = val;
+        gen_args[0] = dst;
+        gen_args[1] = val;
+}
+
+/* Propagate constants and copies, fold constant expressions. */
 static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                                     TCGArg *args, TCGOpDef *tcg_op_defs)
 {
-    int i, nb_ops, op_index, op, nb_temps, nb_globals;
+    int i, nb_ops, op_index, op, nb_temps, nb_globals, nb_call_args;
     const TCGOpDef *def;
     TCGArg *gen_args;
+    /* Array VALS has an element for each temp.
+       If this temp holds a constant then its value is kept in VALS' element.
+       If this temp is a copy of other ones then this equivalence class'
+       representative is kept in VALS' element.
+       If this temp is neither copy nor constant then corresponding VALS'
+       element is unused. */
 
     nb_temps = s->nb_temps;
     nb_globals = s->nb_globals;
+    memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
 
     nb_ops = tcg_opc_ptr - gen_opc_buf;
     gen_args = args;
     for (op_index = 0; op_index < nb_ops; op_index++) {
         op = gen_opc_buf[op_index];
         def = &tcg_op_defs[op];
+        /* Do copy propagation */
+        if (!(def->flags & (TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS))) {
+            assert(op != INDEX_op_call);
+            for (i = def->nb_oargs; i < def->nb_oargs + def->nb_iargs; i++) {
+                if (temps[args[i]].state == TCG_TEMP_COPY) {
+                    args[i] = temps[args[i]].val;
+                }
+            }
+        }
+
+        /* Propagate constants through copy operations and do constant
+           folding.  Constants will be substituted to arguments by register
+           allocator where needed and possible.  Also detect copies. */
         switch (op) {
+        CASE_OP_32_64(mov):
+            if ((temps[args[1]].state == TCG_TEMP_COPY
+                && temps[args[1]].val == args[0])
+                || args[0] == args[1]) {
+                args += 2;
+                gen_opc_buf[op_index] = INDEX_op_nop;
+                break;
+            }
+            if (temps[args[1]].state != TCG_TEMP_CONST) {
+                tcg_opt_gen_mov(gen_args, args[0], args[1],
+                                nb_temps, nb_globals);
+                gen_args += 2;
+                args += 2;
+                break;
+            }
+            /* Source argument is constant.  Rewrite the operation and
+               let movi case handle it. */
+            op = op_to_movi(op);
+            gen_opc_buf[op_index] = op;
+            args[1] = temps[args[1]].val;
+            /* fallthrough */
+        CASE_OP_32_64(movi):
+            tcg_opt_gen_movi(gen_args, args[0], args[1], nb_temps, nb_globals);
+            gen_args += 2;
+            args += 2;
+            break;
         case INDEX_op_call:
-            i = (args[0] >> 16) + (args[0] & 0xffff) + 3;
+            nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
+            if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
+                for (i = 0; i < nb_globals; i++) {
+                    reset_temp(i, nb_temps, nb_globals);
+                }
+            }
+            for (i = 0; i < (args[0] >> 16); i++) {
+                reset_temp(args[i + 1], nb_temps, nb_globals);
+            }
+            i = nb_call_args + 3;
             while (i) {
                 *gen_args = *args;
                 args++;
@@ -69,6 +241,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
         case INDEX_op_jmp:
         case INDEX_op_br:
         CASE_OP_32_64(brcond):
+            memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
             for (i = 0; i < def->nb_args; i++) {
                 *gen_args = *args;
                 args++;
@@ -76,6 +249,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
             }
             break;
         default:
+            /* Default case: we do know nothing about operation so no
+               propagation is done.  We only trash output args.  */
+            for (i = 0; i < def->nb_oargs; i++) {
+                reset_temp(args[i], nb_temps, nb_globals);
+            }
             for (i = 0; i < def->nb_args; i++) {
                 gen_args[i] = args[i];
             }
commit 8f2e8c07a65c340b525b08e08925b568844d4f3d
Author: Kirill Batuzov <batuzovk at ispras.ru>
Date:   Thu Jul 7 16:37:12 2011 +0400

    Add TCG optimizations stub
    
    Added file tcg/optimize.c to hold TCG optimizations. Function tcg_optimize
    is called from tcg_gen_code_common. It calls other functions performing
    specific optimizations. Stub for constant folding was added.
    
    Signed-off-by: Kirill Batuzov <batuzovk at ispras.ru>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index d4ea042..4aacc67 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -72,7 +72,7 @@ all: $(PROGS) stap
 #########################################################
 # cpu emulator library
 libobj-y = exec.o translate-all.o cpu-exec.o translate.o
-libobj-y += tcg/tcg.o
+libobj-y += tcg/tcg.o tcg/optimize.o
 libobj-y += fpu/softfloat.o
 libobj-y += op_helper.o helper.o
 ifeq ($(TARGET_BASE_ARCH), i386)
diff --git a/tcg/optimize.c b/tcg/optimize.c
new file mode 100644
index 0000000..c7c7da9
--- /dev/null
+++ b/tcg/optimize.c
@@ -0,0 +1,97 @@
+/*
+ * Optimizations for Tiny Code Generator for QEMU
+ *
+ * Copyright (c) 2010 Samsung Electronics.
+ * Contributed by Kirill Batuzov <batuzovk at ispras.ru>
+ *
+ * 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 "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "qemu-common.h"
+#include "tcg-op.h"
+
+#if TCG_TARGET_REG_BITS == 64
+#define CASE_OP_32_64(x)                        \
+        glue(glue(case INDEX_op_, x), _i32):    \
+        glue(glue(case INDEX_op_, x), _i64)
+#else
+#define CASE_OP_32_64(x)                        \
+        glue(glue(case INDEX_op_, x), _i32)
+#endif
+
+static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
+                                    TCGArg *args, TCGOpDef *tcg_op_defs)
+{
+    int i, nb_ops, op_index, op, nb_temps, nb_globals;
+    const TCGOpDef *def;
+    TCGArg *gen_args;
+
+    nb_temps = s->nb_temps;
+    nb_globals = s->nb_globals;
+
+    nb_ops = tcg_opc_ptr - gen_opc_buf;
+    gen_args = args;
+    for (op_index = 0; op_index < nb_ops; op_index++) {
+        op = gen_opc_buf[op_index];
+        def = &tcg_op_defs[op];
+        switch (op) {
+        case INDEX_op_call:
+            i = (args[0] >> 16) + (args[0] & 0xffff) + 3;
+            while (i) {
+                *gen_args = *args;
+                args++;
+                gen_args++;
+                i--;
+            }
+            break;
+        case INDEX_op_set_label:
+        case INDEX_op_jmp:
+        case INDEX_op_br:
+        CASE_OP_32_64(brcond):
+            for (i = 0; i < def->nb_args; i++) {
+                *gen_args = *args;
+                args++;
+                gen_args++;
+            }
+            break;
+        default:
+            for (i = 0; i < def->nb_args; i++) {
+                gen_args[i] = args[i];
+            }
+            args += def->nb_args;
+            gen_args += def->nb_args;
+            break;
+        }
+    }
+
+    return gen_args;
+}
+
+TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr,
+        TCGArg *args, TCGOpDef *tcg_op_defs)
+{
+    TCGArg *res;
+    res = tcg_constant_folding(s, tcg_opc_ptr, args, tcg_op_defs);
+    return res;
+}
diff --git a/tcg/tcg.c b/tcg/tcg.c
index c05413b..92f1989 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -24,6 +24,7 @@
 
 /* define it to use liveness analysis (better code) */
 #define USE_LIVENESS_ANALYSIS
+#define USE_TCG_OPTIMIZATIONS
 
 #include "config.h"
 
@@ -2035,6 +2036,11 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
     }
 #endif
 
+#ifdef USE_TCG_OPTIMIZATIONS
+    gen_opparam_ptr =
+        tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
+#endif
+
 #ifdef CONFIG_PROFILER
     s->la_time -= profile_getclock();
 #endif
diff --git a/tcg/tcg.h b/tcg/tcg.h
index a2dd8b8..e76f9af 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -502,6 +502,9 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
 void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
                         int c, int right, int arith);
 
+TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr, TCGArg *args,
+                     TCGOpDef *tcg_op_def);
+
 /* only used for debugging purposes */
 void tcg_register_helper(void *func, const char *name);
 const char *tcg_helper_get_name(TCGContext *s, void *func);
commit 3e4571724fb92c77de81d8b54957de8232be6706
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Wed Jul 13 12:44:15 2011 +0000

    exec.h cleanup
    
    Move softmmu_exec.h include directives from target-*/exec.h to
    target-*/op_helper.c. Move also various other stuff only used in
    op_helper.c there.
    
    Define global env in dyngen-exec.h.
    
    For i386, move wrappers for segment and FPU helpers from user-exec.c
    to op_helper.c. Implement raise_exception_err_env() to handle dynamic
    CPUState. Move the function declarations to cpu.h since they can be
    used outside of op_helper.c context.
    
    LM32, s390x, UniCore32: remove unused cpu_halted(), regs_to_env() and
    env_to_regs().
    
    ARM: make raise_exception() static.
    
    Convert
    #include "exec.h"
    to
    #include "cpu.h"
    #include "dyngen-exec.h"
    and remove now unused target-*/exec.h.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/dyngen-exec.h b/dyngen-exec.h
index db00fba..cc1e4fb 100644
--- a/dyngen-exec.h
+++ b/dyngen-exec.h
@@ -64,6 +64,8 @@ typedef void * host_reg_t;
 #error unsupported CPU
 #endif
 
+register CPUState *env asm(AREG0);
+
 #define xglue(x, y) x ## y
 #define glue(x, y) xglue(x, y)
 #define stringify(s)	tostring(s)
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index 5cd8d8f..f7ead04 100644
--- a/hw/spapr_hcall.c
+++ b/hw/spapr_hcall.c
@@ -1,9 +1,9 @@
 #include "sysemu.h"
 #include "cpu.h"
+#include "dyngen-exec.h"
 #include "qemu-char.h"
 #include "sysemu.h"
 #include "qemu-char.h"
-#include "exec.h"
 #include "helper_regs.h"
 #include "hw/spapr.h"
 
diff --git a/target-alpha/exec.h b/target-alpha/exec.h
deleted file mode 100644
index afb01d3..0000000
--- a/target-alpha/exec.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  Alpha emulation cpu run-time definitions for qemu.
- *
- *  Copyright (c) 2007 Jocelyn Mayer
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#if !defined (__ALPHA_EXEC_H__)
-#define __ALPHA_EXEC_H__
-
-#include "config.h"
-
-#include "dyngen-exec.h"
-
-#define TARGET_LONG_BITS 64
-
-register struct CPUAlphaState *env asm(AREG0);
-
-#define FP_STATUS (env->fp_status)
-
-#include "cpu.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
-
-#endif /* !defined (__ALPHA_EXEC_H__) */
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 8f39154..c2bb679 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -17,12 +17,15 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "host-utils.h"
 #include "softfloat.h"
 #include "helper.h"
 #include "qemu-timer.h"
 
+#define FP_STATUS (env->fp_status)
+
 /*****************************************************************************/
 /* Exceptions processing helpers */
 
@@ -1311,6 +1314,8 @@ void QEMU_NORETURN cpu_unassigned_access(CPUState *env1,
     dynamic_excp(EXCP_MCHK, 0);
 }
 
+#include "softmmu_exec.h"
+
 #define MMUSUFFIX _mmu
 #define ALIGNED_ONLY
 
diff --git a/target-arm/exec.h b/target-arm/exec.h
deleted file mode 100644
index 6793288..0000000
--- a/target-arm/exec.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- *  ARM execution defines
- *
- *  Copyright (c) 2003 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "config.h"
-#include "dyngen-exec.h"
-
-register struct CPUARMState *env asm(AREG0);
-
-#include "cpu.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif
-
-void raise_exception(int);
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 4635884..57e4977 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -16,17 +16,20 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "helper.h"
 
 #define SIGNBIT (uint32_t)0x80000000
 #define SIGNBIT64 ((uint64_t)1 << 63)
 
-void raise_exception(int tt)
+#if !defined(CONFIG_USER_ONLY)
+static void raise_exception(int tt)
 {
     env->exception_index = tt;
     cpu_loop_exit(env);
 }
+#endif
 
 uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def,
                           uint32_t rn, uint32_t maxindex)
@@ -52,6 +55,8 @@ uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def,
 
 #if !defined(CONFIG_USER_ONLY)
 
+#include "softmmu_exec.h"
+
 #define MMUSUFFIX _mmu
 
 #define SHIFT 0
diff --git a/target-cris/exec.h b/target-cris/exec.h
deleted file mode 100644
index 3294abe..0000000
--- a/target-cris/exec.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  CRIS execution defines
- *
- *  Copyright (c) 2007 AXIS Communications AB
- *  Written by Edgar E. Iglesias
- *
- * 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "dyngen-exec.h"
-
-register struct CPUCRISState *env asm(AREG0);
-
-#include "cpu.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif
diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c
index b3ddd33..246f08f 100644
--- a/target-cris/op_helper.c
+++ b/target-cris/op_helper.c
@@ -18,7 +18,8 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "mmu.h"
 #include "helper.h"
 #include "host-utils.h"
@@ -35,6 +36,7 @@
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
 
 #define MMUSUFFIX _mmu
 
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 9819b5f..dd6c5fa 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -1050,6 +1050,9 @@ void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
 /* op_helper.c */
 void do_interrupt(CPUState *env);
 void do_interrupt_x86_hardirq(CPUState *env, int intno, int is_hw);
+void QEMU_NORETURN raise_exception_env(int exception_index, CPUState *nenv);
+void QEMU_NORETURN raise_exception_err_env(CPUState *nenv, int exception_index,
+                                           int error_code);
 
 void do_smm_enter(CPUState *env1);
 
diff --git a/target-i386/exec.h b/target-i386/exec.h
deleted file mode 100644
index dd9bce4..0000000
--- a/target-i386/exec.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- *  i386 execution defines
- *
- *  Copyright (c) 2003 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "config.h"
-#include "dyngen-exec.h"
-
-/* XXX: factorize this mess */
-#ifdef TARGET_X86_64
-#define TARGET_LONG_BITS 64
-#else
-#define TARGET_LONG_BITS 32
-#endif
-
-#include "cpu-defs.h"
-
-register struct CPUX86State *env asm(AREG0);
-
-#include "qemu-common.h"
-#include "qemu-log.h"
-
-#include "cpu.h"
-
-/* op_helper.c */
-void QEMU_NORETURN raise_exception_err(int exception_index, int error_code);
-void QEMU_NORETURN raise_exception(int exception_index);
-void QEMU_NORETURN raise_exception_env(int exception_index, CPUState *nenv);
-
-/* n must be a constant to be efficient */
-static inline target_long lshift(target_long x, int n)
-{
-    if (n >= 0)
-        return x << n;
-    else
-        return x >> (-n);
-}
-
-#include "helper.h"
-
-#if !defined(CONFIG_USER_ONLY)
-
-#include "softmmu_exec.h"
-
-#endif /* !defined(CONFIG_USER_ONLY) */
-
-#define RC_MASK         0xc00
-#define RC_NEAR		0x000
-#define RC_DOWN		0x400
-#define RC_UP		0x800
-#define RC_CHOP		0xc00
-
-#define MAXTAN 9223372036854775808.0
-
-/* the following deal with x86 long double-precision numbers */
-#define MAXEXPD 0x7fff
-#define EXPBIAS 16383
-#define EXPD(fp)	(fp.l.upper & 0x7fff)
-#define SIGND(fp)	((fp.l.upper) & 0x8000)
-#define MANTD(fp)       (fp.l.lower)
-#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
-
-static inline void fpush(void)
-{
-    env->fpstt = (env->fpstt - 1) & 7;
-    env->fptags[env->fpstt] = 0; /* validate stack entry */
-}
-
-static inline void fpop(void)
-{
-    env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
-    env->fpstt = (env->fpstt + 1) & 7;
-}
-
-static inline floatx80 helper_fldt(target_ulong ptr)
-{
-    CPU_LDoubleU temp;
-
-    temp.l.lower = ldq(ptr);
-    temp.l.upper = lduw(ptr + 8);
-    return temp.d;
-}
-
-static inline void helper_fstt(floatx80 f, target_ulong ptr)
-{
-    CPU_LDoubleU temp;
-
-    temp.d = f;
-    stq(ptr, temp.l.lower);
-    stw(ptr + 8, temp.l.upper);
-}
-
-#define FPUS_IE (1 << 0)
-#define FPUS_DE (1 << 1)
-#define FPUS_ZE (1 << 2)
-#define FPUS_OE (1 << 3)
-#define FPUS_UE (1 << 4)
-#define FPUS_PE (1 << 5)
-#define FPUS_SF (1 << 6)
-#define FPUS_SE (1 << 7)
-#define FPUS_B  (1 << 15)
-
-#define FPUC_EM 0x3f
-
-static inline uint32_t compute_eflags(void)
-{
-    return env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
-}
-
-/* NOTE: CC_OP must be modified manually to CC_OP_EFLAGS */
-static inline void load_eflags(int eflags, int update_mask)
-{
-    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
-    DF = 1 - (2 * ((eflags >> 10) & 1));
-    env->eflags = (env->eflags & ~update_mask) |
-        (eflags & update_mask) | 0x2;
-}
-
-/* load efer and update the corresponding hflags. XXX: do consistency
-   checks with cpuid bits ? */
-static inline void cpu_load_efer(CPUState *env, uint64_t val)
-{
-    env->efer = val;
-    env->hflags &= ~(HF_LMA_MASK | HF_SVME_MASK);
-    if (env->efer & MSR_EFER_LMA)
-        env->hflags |= HF_LMA_MASK;
-    if (env->efer & MSR_EFER_SVME)
-        env->hflags |= HF_SVME_MASK;
-}
diff --git a/target-i386/helper.c b/target-i386/helper.c
index e9be104..182009a 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1027,8 +1027,6 @@ int check_hw_breakpoints(CPUState *env, int force_dr6_update)
 
 static CPUDebugExcpHandler *prev_debug_excp_handler;
 
-void raise_exception_env(int exception_index, CPUState *env);
-
 static void breakpoint_handler(CPUState *env)
 {
     CPUBreakpoint *bp;
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index 315e18b..1380934 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -18,12 +18,20 @@
  */
 
 #include <math.h>
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "host-utils.h"
 #include "ioport.h"
+#include "qemu-common.h"
+#include "qemu-log.h"
+#include "cpu-defs.h"
+#include "helper.h"
 
-//#define DEBUG_PCALL
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#endif /* !defined(CONFIG_USER_ONLY) */
 
+//#define DEBUG_PCALL
 
 #ifdef DEBUG_PCALL
 #  define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__)
@@ -34,6 +42,101 @@
 #  define LOG_PCALL_STATE(env) do { } while (0)
 #endif
 
+/* n must be a constant to be efficient */
+static inline target_long lshift(target_long x, int n)
+{
+    if (n >= 0) {
+        return x << n;
+    } else {
+        return x >> (-n);
+    }
+}
+
+#define RC_MASK         0xc00
+#define RC_NEAR         0x000
+#define RC_DOWN         0x400
+#define RC_UP           0x800
+#define RC_CHOP         0xc00
+
+#define MAXTAN 9223372036854775808.0
+
+/* the following deal with x86 long double-precision numbers */
+#define MAXEXPD 0x7fff
+#define EXPBIAS 16383
+#define EXPD(fp)        (fp.l.upper & 0x7fff)
+#define SIGND(fp)       ((fp.l.upper) & 0x8000)
+#define MANTD(fp)       (fp.l.lower)
+#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
+
+static inline void fpush(void)
+{
+    env->fpstt = (env->fpstt - 1) & 7;
+    env->fptags[env->fpstt] = 0; /* validate stack entry */
+}
+
+static inline void fpop(void)
+{
+    env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
+    env->fpstt = (env->fpstt + 1) & 7;
+}
+
+static inline floatx80 helper_fldt(target_ulong ptr)
+{
+    CPU_LDoubleU temp;
+
+    temp.l.lower = ldq(ptr);
+    temp.l.upper = lduw(ptr + 8);
+    return temp.d;
+}
+
+static inline void helper_fstt(floatx80 f, target_ulong ptr)
+{
+    CPU_LDoubleU temp;
+
+    temp.d = f;
+    stq(ptr, temp.l.lower);
+    stw(ptr + 8, temp.l.upper);
+}
+
+#define FPUS_IE (1 << 0)
+#define FPUS_DE (1 << 1)
+#define FPUS_ZE (1 << 2)
+#define FPUS_OE (1 << 3)
+#define FPUS_UE (1 << 4)
+#define FPUS_PE (1 << 5)
+#define FPUS_SF (1 << 6)
+#define FPUS_SE (1 << 7)
+#define FPUS_B  (1 << 15)
+
+#define FPUC_EM 0x3f
+
+static inline uint32_t compute_eflags(void)
+{
+    return env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
+}
+
+/* NOTE: CC_OP must be modified manually to CC_OP_EFLAGS */
+static inline void load_eflags(int eflags, int update_mask)
+{
+    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
+    DF = 1 - (2 * ((eflags >> 10) & 1));
+    env->eflags = (env->eflags & ~update_mask) |
+        (eflags & update_mask) | 0x2;
+}
+
+/* load efer and update the corresponding hflags. XXX: do consistency
+   checks with cpuid bits ? */
+static inline void cpu_load_efer(CPUState *env, uint64_t val)
+{
+    env->efer = val;
+    env->hflags &= ~(HF_LMA_MASK | HF_SVME_MASK);
+    if (env->efer & MSR_EFER_LMA) {
+        env->hflags |= HF_LMA_MASK;
+    }
+    if (env->efer & MSR_EFER_SVME) {
+        env->hflags |= HF_SVME_MASK;
+    }
+}
 
 #if 0
 #define raise_exception_err(a, b)\
@@ -43,6 +146,9 @@ do {\
 } while (0)
 #endif
 
+static void QEMU_NORETURN raise_exception_err(int exception_index,
+                                              int error_code);
+
 static const uint8_t parity_table[256] = {
     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
@@ -1381,12 +1487,20 @@ static void QEMU_NORETURN raise_interrupt(int intno, int is_int, int error_code,
 
 /* shortcuts to generate exceptions */
 
-void raise_exception_err(int exception_index, int error_code)
+static void QEMU_NORETURN raise_exception_err(int exception_index,
+                                              int error_code)
+{
+    raise_interrupt(exception_index, 0, error_code, 0);
+}
+
+void raise_exception_err_env(CPUState *nenv, int exception_index,
+                             int error_code)
 {
+    env = nenv;
     raise_interrupt(exception_index, 0, error_code, 0);
 }
 
-void raise_exception(int exception_index)
+static void QEMU_NORETURN raise_exception(int exception_index)
 {
     raise_interrupt(exception_index, 0, 0, 0);
 }
@@ -4426,6 +4540,49 @@ void helper_frstor(target_ulong ptr, int data32)
     }
 }
 
+
+#if defined(CONFIG_USER_ONLY)
+void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
+{
+    CPUX86State *saved_env;
+
+    saved_env = env;
+    env = s;
+    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
+        selector &= 0xffff;
+        cpu_x86_load_seg_cache(env, seg_reg, selector,
+                               (selector << 4), 0xffff, 0);
+    } else {
+        helper_load_seg(seg_reg, selector);
+    }
+    env = saved_env;
+}
+
+void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
+{
+    CPUX86State *saved_env;
+
+    saved_env = env;
+    env = s;
+
+    helper_fsave(ptr, data32);
+
+    env = saved_env;
+}
+
+void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
+{
+    CPUX86State *saved_env;
+
+    saved_env = env;
+    env = s;
+
+    helper_frstor(ptr, data32);
+
+    env = saved_env;
+}
+#endif
+
 void helper_fxsave(target_ulong ptr, int data64)
 {
     int fpus, fptag, i, nb_xmm_regs;
diff --git a/target-lm32/exec.h b/target-lm32/exec.h
deleted file mode 100644
index 2a227b2..0000000
--- a/target-lm32/exec.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *  LatticeMico32 execution defines.
- *
- *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "dyngen-exec.h"
-
-register struct CPULM32State *env asm(AREG0);
-
-#include "cpu.h"
-
-static inline int cpu_halted(CPUState *env)
-{
-    if (!env->halted) {
-        return 0;
-    }
-
-    /* IRQ execeptions wakes us up.  */
-    if (cpu_has_work(env)) {
-        env->halted = 0;
-        return 0;
-    }
-    return EXCP_HALTED;
-}
diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c
index a34cecd..32b9a03 100644
--- a/target-lm32/op_helper.c
+++ b/target-lm32/op_helper.c
@@ -1,5 +1,6 @@
 #include <assert.h>
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "helper.h"
 #include "host-utils.h"
 
diff --git a/target-m68k/exec.h b/target-m68k/exec.h
deleted file mode 100644
index 93e7912..0000000
--- a/target-m68k/exec.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  m68k execution defines
- *
- *  Copyright (c) 2005-2006 CodeSourcery
- *  Written by Paul Brook
- *
- * 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "dyngen-exec.h"
-
-register struct CPUM68KState *env asm(AREG0);
-
-#include "cpu.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 237fc4c..764b6a0 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -16,7 +16,8 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "helpers.h"
 
 #if defined(CONFIG_USER_ONLY)
@@ -34,6 +35,8 @@ void do_interrupt_m68k_hardirq(CPUState *env1)
 
 extern int semihosting_enabled;
 
+#include "softmmu_exec.h"
+
 #define MMUSUFFIX _mmu
 
 #define SHIFT 0
diff --git a/target-microblaze/exec.h b/target-microblaze/exec.h
deleted file mode 100644
index 71b4d39..0000000
--- a/target-microblaze/exec.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  Microblaze execution defines
- *
- *  Copyright (c) 2009 Edgar E. Iglesias
- *
- * 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "dyngen-exec.h"
-
-register struct CPUMBState *env asm(AREG0);
-
-#include "cpu.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index 664ffe5..189c59c 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -18,13 +18,16 @@
  */
 
 #include <assert.h>
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "helper.h"
 #include "host-utils.h"
 
 #define D(x)
 
 #if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+
 #define MMUSUFFIX _mmu
 #define SHIFT 0
 #include "softmmu_template.h"
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 33be296..030f499 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -1,6 +1,8 @@
 #if !defined (__MIPS_CPU_H__)
 #define __MIPS_CPU_H__
 
+//#define DEBUG_OP
+
 #define TARGET_HAS_ICE 1
 
 #define ELF_MACHINE	EM_MIPS
diff --git a/target-mips/exec.h b/target-mips/exec.h
deleted file mode 100644
index e787e9a..0000000
--- a/target-mips/exec.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#if !defined(__QEMU_MIPS_EXEC_H__)
-#define __QEMU_MIPS_EXEC_H__
-
-//#define DEBUG_OP
-
-#include "config.h"
-#include "mips-defs.h"
-#include "dyngen-exec.h"
-#include "cpu-defs.h"
-
-register struct CPUMIPSState *env asm(AREG0);
-
-#include "cpu.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
-
-static inline void compute_hflags(CPUState *env)
-{
-    env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
-                     MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
-                     MIPS_HFLAG_UX);
-    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
-        !(env->CP0_Status & (1 << CP0St_ERL)) &&
-        !(env->hflags & MIPS_HFLAG_DM)) {
-        env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
-    }
-#if defined(TARGET_MIPS64)
-    if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
-        (env->CP0_Status & (1 << CP0St_PX)) ||
-        (env->CP0_Status & (1 << CP0St_UX)))
-        env->hflags |= MIPS_HFLAG_64;
-    if (env->CP0_Status & (1 << CP0St_UX))
-        env->hflags |= MIPS_HFLAG_UX;
-#endif
-    if ((env->CP0_Status & (1 << CP0St_CU0)) ||
-        !(env->hflags & MIPS_HFLAG_KSU))
-        env->hflags |= MIPS_HFLAG_CP0;
-    if (env->CP0_Status & (1 << CP0St_CU1))
-        env->hflags |= MIPS_HFLAG_FPU;
-    if (env->CP0_Status & (1 << CP0St_FR))
-        env->hflags |= MIPS_HFLAG_F64;
-    if (env->insn_flags & ISA_MIPS32R2) {
-        if (env->active_fpu.fcr0 & (1 << FCR0_F64))
-            env->hflags |= MIPS_HFLAG_COP1X;
-    } else if (env->insn_flags & ISA_MIPS32) {
-        if (env->hflags & MIPS_HFLAG_64)
-            env->hflags |= MIPS_HFLAG_COP1X;
-    } else if (env->insn_flags & ISA_MIPS4) {
-        /* All supported MIPS IV CPUs use the XX (CU3) to enable
-           and disable the MIPS IV extensions to the MIPS III ISA.
-           Some other MIPS IV CPUs ignore the bit, so the check here
-           would be too restrictive for them.  */
-        if (env->CP0_Status & (1 << CP0St_CU3))
-            env->hflags |= MIPS_HFLAG_COP1X;
-    }
-}
-
-#endif /* !defined(__QEMU_MIPS_EXEC_H__) */
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 01315ef..185ae40 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -17,16 +17,70 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 #include <stdlib.h>
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 
 #include "host-utils.h"
 
 #include "helper.h"
 
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#endif /* !defined(CONFIG_USER_ONLY) */
+
 #ifndef CONFIG_USER_ONLY
 static inline void cpu_mips_tlb_flush (CPUState *env, int flush_global);
 #endif
 
+static inline void compute_hflags(CPUState *env)
+{
+    env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
+                     MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
+                     MIPS_HFLAG_UX);
+    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
+        !(env->CP0_Status & (1 << CP0St_ERL)) &&
+        !(env->hflags & MIPS_HFLAG_DM)) {
+        env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
+    }
+#if defined(TARGET_MIPS64)
+    if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
+        (env->CP0_Status & (1 << CP0St_PX)) ||
+        (env->CP0_Status & (1 << CP0St_UX))) {
+        env->hflags |= MIPS_HFLAG_64;
+    }
+    if (env->CP0_Status & (1 << CP0St_UX)) {
+        env->hflags |= MIPS_HFLAG_UX;
+    }
+#endif
+    if ((env->CP0_Status & (1 << CP0St_CU0)) ||
+        !(env->hflags & MIPS_HFLAG_KSU)) {
+        env->hflags |= MIPS_HFLAG_CP0;
+    }
+    if (env->CP0_Status & (1 << CP0St_CU1)) {
+        env->hflags |= MIPS_HFLAG_FPU;
+    }
+    if (env->CP0_Status & (1 << CP0St_FR)) {
+        env->hflags |= MIPS_HFLAG_F64;
+    }
+    if (env->insn_flags & ISA_MIPS32R2) {
+        if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
+            env->hflags |= MIPS_HFLAG_COP1X;
+        }
+    } else if (env->insn_flags & ISA_MIPS32) {
+        if (env->hflags & MIPS_HFLAG_64) {
+            env->hflags |= MIPS_HFLAG_COP1X;
+        }
+    } else if (env->insn_flags & ISA_MIPS4) {
+        /* All supported MIPS IV CPUs use the XX (CU3) to enable
+           and disable the MIPS IV extensions to the MIPS III ISA.
+           Some other MIPS IV CPUs ignore the bit, so the check here
+           would be too restrictive for them.  */
+        if (env->CP0_Status & (1 << CP0St_CU3)) {
+            env->hflags |= MIPS_HFLAG_COP1X;
+        }
+    }
+}
+
 /*****************************************************************************/
 /* Exceptions processing helpers */
 
diff --git a/target-ppc/exec.h b/target-ppc/exec.h
deleted file mode 100644
index f4453e4..0000000
--- a/target-ppc/exec.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *  PowerPC emulation definitions for qemu.
- *
- *  Copyright (c) 2003-2007 Jocelyn Mayer
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#if !defined (__PPC_H__)
-#define __PPC_H__
-
-#include "config.h"
-
-#include "dyngen-exec.h"
-
-#include "cpu.h"
-
-register struct CPUPPCState *env asm(AREG0);
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
-
-#endif /* !defined (__PPC_H__) */
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index dde7595..6e100d9 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -17,12 +17,17 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 #include <string.h>
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "host-utils.h"
 #include "helper.h"
 
 #include "helper_regs.h"
 
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#endif /* !defined(CONFIG_USER_ONLY) */
+
 //#define DEBUG_OP
 //#define DEBUG_EXCEPTIONS
 //#define DEBUG_SOFTWARE_TLB
diff --git a/target-s390x/exec.h b/target-s390x/exec.h
deleted file mode 100644
index fb73f31..0000000
--- a/target-s390x/exec.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  S/390 execution defines
- *
- *  Copyright (c) 2009 Ulrich Hecht
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "dyngen-exec.h"
-
-register struct CPUS390XState *env asm(AREG0);
-
-#include "config.h"
-#include "cpu.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
-
-static inline void regs_to_env(void)
-{
-}
-
-static inline void env_to_regs(void)
-{
-}
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index cd33f99..25a1e81 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -18,7 +18,8 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "host-utils.h"
 #include "helpers.h"
 #include <string.h>
@@ -31,6 +32,7 @@
 /*****************************************************************************/
 /* Softmmu support */
 #if !defined (CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
 
 #define MMUSUFFIX _mmu
 
diff --git a/target-sh4/exec.h b/target-sh4/exec.h
deleted file mode 100644
index 4a6ae58..0000000
--- a/target-sh4/exec.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *  SH4 emulation
- *
- *  Copyright (c) 2005 Samuel Tardieu
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef _EXEC_SH4_H
-#define _EXEC_SH4_H
-
-#include "config.h"
-#include "dyngen-exec.h"
-
-register struct CPUSH4State *env asm(AREG0);
-
-#include "cpu.h"
-
-#ifndef CONFIG_USER_ONLY
-#include "softmmu_exec.h"
-#endif
-
-#endif				/* _EXEC_SH4_H */
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index a932225..568bf0d 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -18,7 +18,8 @@
  */
 #include <assert.h>
 #include <stdlib.h>
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "helper.h"
 
 static void cpu_restore_state_from_retaddr(void *retaddr)
@@ -38,6 +39,7 @@ static void cpu_restore_state_from_retaddr(void *retaddr)
 }
 
 #ifndef CONFIG_USER_ONLY
+#include "softmmu_exec.h"
 
 #define MMUSUFFIX _mmu
 
diff --git a/target-sparc/exec.h b/target-sparc/exec.h
deleted file mode 100644
index 2395b00..0000000
--- a/target-sparc/exec.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef EXEC_SPARC_H
-#define EXEC_SPARC_H 1
-#include "config.h"
-#include "dyngen-exec.h"
-
-register struct CPUSPARCState *env asm(AREG0);
-
-#include "cpu.h"
-#include "exec-all.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
-
-#endif
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 8962e38..c1c4d4b 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -1,8 +1,13 @@
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "host-utils.h"
 #include "helper.h"
 #include "sysemu.h"
 
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#endif
+
 //#define DEBUG_MMU
 //#define DEBUG_MXCC
 //#define DEBUG_UNALIGNED
diff --git a/target-unicore32/exec.h b/target-unicore32/exec.h
deleted file mode 100644
index 7912105..0000000
--- a/target-unicore32/exec.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *  UniCore32 execution defines
- *
- * Copyright (C) 2010-2011 GUAN Xue-tao
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef __UC32_EXEC_H__
-#define __UC32_EXEC_H__
-
-#include "config.h"
-#include "dyngen-exec.h"
-
-register struct CPUState_UniCore32 *env asm(AREG0);
-
-#include "cpu.h"
-
-static inline void env_to_regs(void)
-{
-}
-
-static inline void regs_to_env(void)
-{
-}
-
-static inline int cpu_halted(CPUState *env)
-{
-    if (!env->halted) {
-        return 0;
-    }
-    /* An interrupt wakes the CPU even if the I and R ASR bits are
-       set.  We use EXITTB to silently wake CPU without causing an
-       actual interrupt.  */
-    if (cpu_has_work(env)) {
-        env->halted = 0;
-        return 0;
-    }
-    return EXCP_HALTED;
-}
-
-#endif /* __UC32_EXEC_H__ */
diff --git a/target-unicore32/op_helper.c b/target-unicore32/op_helper.c
index 541e6f0..6cf5255 100644
--- a/target-unicore32/op_helper.c
+++ b/target-unicore32/op_helper.c
@@ -7,7 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "helper.h"
 
 #define SIGNBIT (uint32_t)0x80000000
diff --git a/user-exec.c b/user-exec.c
index 02c2f8b..14c0f25 100644
--- a/user-exec.c
+++ b/user-exec.c
@@ -17,7 +17,8 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "config.h"
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "disas.h"
 #include "tcg.h"
 
@@ -40,7 +41,7 @@
 static void exception_action(CPUState *env1)
 {
 #if defined(TARGET_I386)
-    raise_exception_err(env1->exception_index, env1->error_code);
+    raise_exception_err_env(env1, env1->exception_index, env1->error_code);
 #else
     cpu_loop_exit(env1);
 #endif
@@ -628,47 +629,3 @@ int cpu_signal_handler(int host_signum, void *pinfo,
 #error host CPU specific signal handler needed
 
 #endif
-
-#if defined(TARGET_I386)
-
-void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
-{
-    CPUX86State *saved_env;
-
-    saved_env = env;
-    env = s;
-    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
-        selector &= 0xffff;
-        cpu_x86_load_seg_cache(env, seg_reg, selector,
-                               (selector << 4), 0xffff, 0);
-    } else {
-        helper_load_seg(seg_reg, selector);
-    }
-    env = saved_env;
-}
-
-void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
-{
-    CPUX86State *saved_env;
-
-    saved_env = env;
-    env = s;
-
-    helper_fsave(ptr, data32);
-
-    env = saved_env;
-}
-
-void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
-{
-    CPUX86State *saved_env;
-
-    saved_env = env;
-    env = s;
-
-    helper_frstor(ptr, data32);
-
-    env = saved_env;
-}
-
-#endif /* TARGET_I386 */
commit 104bf02eb50e080ac9d0de5905f80f9a09730154
Author: Michael Tokarev <mjt at tls.msk.ru>
Date:   Thu May 12 18:44:17 2011 +0400

    revamp acpitable parsing and allow to specify complete (headerful) table
    
    This patch almost rewrites acpi_table_add() function
    (but still leaves it using old get_param_value() interface).
    The result is that it's now possible to specify whole table
    (together with a header) in an external file, instead of just
    data portion, with a new file= parameter, but at the same time
    it's still possible to specify header fields as before.
    
    Now with the checkpatch.pl formatting fixes, thanks to
    Stefan Hajnoczi for suggestions, with changes from
    Isaku Yamahata, and with my further refinements.
    
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>
    Cc: Isaku Yamahata <yamahata at valinux.co.jp>
    Cc: John Baboval <john.baboval at virtualcomputer.com>
    Cc: Blue Swirl <blauwirbel at gmail.com>
    [yamahata at valinux.co.jp: fix compile error, comment fallthrough]
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/acpi.c b/hw/acpi.c
index ad40fb4..79ec66c 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -20,19 +20,30 @@
 #include "pc.h"
 #include "acpi.h"
 
-struct acpi_table_header
-{
-    char signature [4];    /* ACPI signature (4 ASCII characters) */
+struct acpi_table_header {
+    uint16_t _length;         /* our length, not actual part of the hdr */
+                              /* XXX why we have 2 length fields here? */
+    char sig[4];              /* ACPI signature (4 ASCII characters) */
     uint32_t length;          /* Length of table, in bytes, including header */
     uint8_t revision;         /* ACPI Specification minor version # */
     uint8_t checksum;         /* To make sum of entire table == 0 */
-    char oem_id [6];       /* OEM identification */
-    char oem_table_id [8]; /* OEM table identification */
+    char oem_id[6];           /* OEM identification */
+    char oem_table_id[8];     /* OEM table identification */
     uint32_t oem_revision;    /* OEM revision number */
-    char asl_compiler_id [4]; /* ASL compiler vendor ID */
+    char asl_compiler_id[4];  /* ASL compiler vendor ID */
     uint32_t asl_compiler_revision; /* ASL compiler revision number */
 } __attribute__((packed));
 
+#define ACPI_TABLE_HDR_SIZE sizeof(struct acpi_table_header)
+#define ACPI_TABLE_PFX_SIZE sizeof(uint16_t)  /* size of the extra prefix */
+
+static const char dfl_hdr[ACPI_TABLE_HDR_SIZE] =
+    "\0\0"                   /* fake _length (2) */
+    "QEMU\0\0\0\0\1\0"       /* sig (4), len(4), revno (1), csum (1) */
+    "QEMUQEQEMUQEMU\1\0\0\0" /* OEM id (6), table (8), revno (4) */
+    "QEMU\1\0\0\0"           /* ASL compiler ID (4), version (4) */
+    ;
+
 char *acpi_tables;
 size_t acpi_tables_len;
 
@@ -40,163 +51,198 @@ static int acpi_checksum(const uint8_t *data, int len)
 {
     int sum, i;
     sum = 0;
-    for(i = 0; i < len; i++)
+    for (i = 0; i < len; i++) {
         sum += data[i];
+    }
     return (-sum) & 0xff;
 }
 
+/* like strncpy() but zero-fills the tail of destination */
+static void strzcpy(char *dst, const char *src, size_t size)
+{
+    size_t len = strlen(src);
+    if (len >= size) {
+        len = size;
+    } else {
+      memset(dst + len, 0, size - len);
+    }
+    memcpy(dst, src, len);
+}
+
+/* XXX fixme: this function uses obsolete argument parsing interface */
 int acpi_table_add(const char *t)
 {
-    static const char *dfl_id = "QEMUQEMU";
     char buf[1024], *p, *f;
-    struct acpi_table_header acpi_hdr;
     unsigned long val;
-    uint32_t length;
-    struct acpi_table_header *acpi_hdr_p;
-    size_t off;
+    size_t len, start, allen;
+    bool has_header;
+    int changed;
+    int r;
+    struct acpi_table_header hdr;
+
+    r = 0;
+    r |= get_param_value(buf, sizeof(buf), "data", t) ? 1 : 0;
+    r |= get_param_value(buf, sizeof(buf), "file", t) ? 2 : 0;
+    switch (r) {
+    case 0:
+        buf[0] = '\0';
+        /* fallthrough for default behavior */
+    case 1:
+        has_header = false;
+        break;
+    case 2:
+        has_header = true;
+        break;
+    default:
+        fprintf(stderr, "acpitable: both data and file are specified\n");
+        return -1;
+    }
 
-    memset(&acpi_hdr, 0, sizeof(acpi_hdr));
-  
-    if (get_param_value(buf, sizeof(buf), "sig", t)) {
-        strncpy(acpi_hdr.signature, buf, 4);
+    if (!acpi_tables) {
+        allen = sizeof(uint16_t);
+        acpi_tables = qemu_mallocz(allen);
     } else {
-        strncpy(acpi_hdr.signature, dfl_id, 4);
+        allen = acpi_tables_len;
     }
+
+    start = allen;
+    acpi_tables = qemu_realloc(acpi_tables, start + ACPI_TABLE_HDR_SIZE);
+    allen += has_header ? ACPI_TABLE_PFX_SIZE : ACPI_TABLE_HDR_SIZE;
+
+    /* now read in the data files, reallocating buffer as needed */
+
+    for (f = strtok(buf, ":"); f; f = strtok(NULL, ":")) {
+        int fd = open(f, O_RDONLY);
+
+        if (fd < 0) {
+            fprintf(stderr, "can't open file %s: %s\n", f, strerror(errno));
+            return -1;
+        }
+
+        for (;;) {
+            char data[8192];
+            r = read(fd, data, sizeof(data));
+            if (r == 0) {
+                break;
+            } else if (r > 0) {
+                acpi_tables = qemu_realloc(acpi_tables, allen + r);
+                memcpy(acpi_tables + allen, data, r);
+                allen += r;
+            } else if (errno != EINTR) {
+                fprintf(stderr, "can't read file %s: %s\n",
+                        f, strerror(errno));
+                close(fd);
+                return -1;
+            }
+        }
+
+        close(fd);
+    }
+
+    /* now fill in the header fields */
+
+    f = acpi_tables + start;   /* start of the table */
+    changed = 0;
+
+    /* copy the header to temp place to align the fields */
+    memcpy(&hdr, has_header ? f : dfl_hdr, ACPI_TABLE_HDR_SIZE);
+
+    /* length of the table minus our prefix */
+    len = allen - start - ACPI_TABLE_PFX_SIZE;
+
+    hdr._length = cpu_to_le16(len);
+
+    if (get_param_value(buf, sizeof(buf), "sig", t)) {
+        strzcpy(hdr.sig, buf, sizeof(hdr.sig));
+        ++changed;
+    }
+
+    /* length of the table including header, in bytes */
+    if (has_header) {
+        /* check if actual length is correct */
+        val = le32_to_cpu(hdr.length);
+        if (val != len) {
+            fprintf(stderr,
+                "warning: acpitable has wrong length,"
+                " header says %lu, actual size %zu bytes\n",
+                val, len);
+            ++changed;
+        }
+    }
+    /* we may avoid putting length here if has_header is true */
+    hdr.length = cpu_to_le32(len);
+
     if (get_param_value(buf, sizeof(buf), "rev", t)) {
-        val = strtoul(buf, &p, 10);
-        if (val > 255 || *p != '\0')
-            goto out;
-    } else {
-        val = 1;
+        val = strtoul(buf, &p, 0);
+        if (val > 255 || *p) {
+            fprintf(stderr, "acpitable: \"rev=%s\" is invalid\n", buf);
+            return -1;
+        }
+        hdr.revision = (uint8_t)val;
+        ++changed;
     }
-    acpi_hdr.revision = (int8_t)val;
 
     if (get_param_value(buf, sizeof(buf), "oem_id", t)) {
-        strncpy(acpi_hdr.oem_id, buf, 6);
-    } else {
-        strncpy(acpi_hdr.oem_id, dfl_id, 6);
+        strzcpy(hdr.oem_id, buf, sizeof(hdr.oem_id));
+        ++changed;
     }
 
     if (get_param_value(buf, sizeof(buf), "oem_table_id", t)) {
-        strncpy(acpi_hdr.oem_table_id, buf, 8);
-    } else {
-        strncpy(acpi_hdr.oem_table_id, dfl_id, 8);
+        strzcpy(hdr.oem_table_id, buf, sizeof(hdr.oem_table_id));
+        ++changed;
     }
 
     if (get_param_value(buf, sizeof(buf), "oem_rev", t)) {
-        val = strtol(buf, &p, 10);
-        if(*p != '\0')
-            goto out;
-    } else {
-        val = 1;
+        val = strtol(buf, &p, 0);
+        if (*p) {
+            fprintf(stderr, "acpitable: \"oem_rev=%s\" is invalid\n", buf);
+            return -1;
+        }
+        hdr.oem_revision = cpu_to_le32(val);
+        ++changed;
     }
-    acpi_hdr.oem_revision = cpu_to_le32(val);
 
     if (get_param_value(buf, sizeof(buf), "asl_compiler_id", t)) {
-        strncpy(acpi_hdr.asl_compiler_id, buf, 4);
-    } else {
-        strncpy(acpi_hdr.asl_compiler_id, dfl_id, 4);
+        strzcpy(hdr.asl_compiler_id, buf, sizeof(hdr.asl_compiler_id));
+        ++changed;
     }
 
     if (get_param_value(buf, sizeof(buf), "asl_compiler_rev", t)) {
-        val = strtol(buf, &p, 10);
-        if(*p != '\0')
-            goto out;
-    } else {
-        val = 1;
-    }
-    acpi_hdr.asl_compiler_revision = cpu_to_le32(val);
-    
-    if (!get_param_value(buf, sizeof(buf), "data", t)) {
-         buf[0] = '\0';
-    }
-
-    length = sizeof(acpi_hdr);
-
-    f = buf;
-    while (buf[0]) {
-        struct stat s;
-        char *n = strchr(f, ':');
-        if (n)
-            *n = '\0';
-        if(stat(f, &s) < 0) {
-            fprintf(stderr, "Can't stat file '%s': %s\n", f, strerror(errno));
-            goto out;
+        val = strtol(buf, &p, 0);
+        if (*p) {
+            fprintf(stderr, "acpitable: \"%s=%s\" is invalid\n",
+                    "asl_compiler_rev", buf);
+            return -1;
         }
-        length += s.st_size;
-        if (!n)
-            break;
-        *n = ':';
-        f = n + 1;
+        hdr.asl_compiler_revision = cpu_to_le32(val);
+        ++changed;
     }
 
-    if (!acpi_tables) {
-        acpi_tables_len = sizeof(uint16_t);
-        acpi_tables = qemu_mallocz(acpi_tables_len);
+    if (!has_header && !changed) {
+        fprintf(stderr, "warning: acpitable: no table headers are specified\n");
     }
-    acpi_tables = qemu_realloc(acpi_tables,
-                               acpi_tables_len + sizeof(uint16_t) + length);
-    p = acpi_tables + acpi_tables_len;
-    acpi_tables_len += sizeof(uint16_t) + length;
-
-    *(uint16_t*)p = cpu_to_le32(length);
-    p += sizeof(uint16_t);
-    memcpy(p, &acpi_hdr, sizeof(acpi_hdr));
-    off = sizeof(acpi_hdr);
-
-    f = buf;
-    while (buf[0]) {
-        struct stat s;
-        int fd;
-        char *n = strchr(f, ':');
-        if (n)
-            *n = '\0';
-        fd = open(f, O_RDONLY);
-
-        if(fd < 0)
-            goto out;
-        if(fstat(fd, &s) < 0) {
-            close(fd);
-            goto out;
-        }
 
-        /* off < length is necessary because file size can be changed
-           under our foot */
-        while(s.st_size && off < length) {
-            int r;
-            r = read(fd, p + off, s.st_size);
-            if (r > 0) {
-                off += r;
-                s.st_size -= r;
-            } else if ((r < 0 && errno != EINTR) || r == 0) {
-                close(fd);
-                goto out;
-            }
-        }
 
-        close(fd);
-        if (!n)
-            break;
-        f = n + 1;
-    }
-    if (off < length) {
-        /* don't pass random value in process to guest */
-        memset(p + off, 0, length - off);
+    /* now calculate checksum of the table, complete with the header */
+    /* we may as well leave checksum intact if has_header is true */
+    /* alternatively there may be a way to set cksum to a given value */
+    hdr.checksum = 0;    /* for checksum calculation */
+
+    /* put header back */
+    memcpy(f, &hdr, sizeof(hdr));
+
+    if (changed || !has_header || 1) {
+        ((struct acpi_table_header *)f)->checksum =
+            acpi_checksum((uint8_t *)f + ACPI_TABLE_PFX_SIZE, len);
     }
 
-    acpi_hdr_p = (struct acpi_table_header*)p;
-    acpi_hdr_p->length = cpu_to_le32(length);
-    acpi_hdr_p->checksum = acpi_checksum((uint8_t*)p, length);
     /* increase number of tables */
-    (*(uint16_t*)acpi_tables) =
-	    cpu_to_le32(le32_to_cpu(*(uint16_t*)acpi_tables) + 1);
+    (*(uint16_t *)acpi_tables) =
+        cpu_to_le32(le32_to_cpu(*(uint16_t *)acpi_tables) + 1);
+
+    acpi_tables_len = allen;
     return 0;
-out:
-    if (acpi_tables) {
-        qemu_free(acpi_tables);
-        acpi_tables = NULL;
-    }
-    return -1;
+
 }
 
 /* ACPI PM1a EVT */
diff --git a/qemu-options.hx b/qemu-options.hx
index c77f868..d86815d 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1074,12 +1074,17 @@ Enable virtio balloon device (default), optionally with PCI address
 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=file1[:file2]...]\n"
+    "-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)
 STEXI
 @item -acpitable [sig=@var{str}][,rev=@var{n}][,oem_id=@var{str}][,oem_table_id=@var{str}][,oem_rev=@var{n}] [,asl_compiler_id=@var{str}][,asl_compiler_rev=@var{n}][,data=@var{file1}[:@var{file2}]...]
 @findex -acpitable
 Add ACPI table with specified header fields and context from specified files.
+For file=, take whole ACPI table from the specified files, including all
+ACPI headers (possible overridden by other options).
+For data=, only data
+portion of the table is used, all header information is specified in the
+command line.
 ETEXI
 
 DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
commit 638737ad0342ba48f3dfbd2ae03a48cc53501b26
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Sat Jul 23 11:20:07 2011 +0900

    SPARC64: implement %fprs dirty bits
    
    Implement %fprs.DU/DL bits.
    The FPU sets %fprs.DL and %fprs.DU when values are assigned to %f0-31
    and %f32-63 respectively.
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index f68b3bc..958fbc5 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1558,6 +1558,13 @@ static int gen_trap_ifnofpu(DisasContext *dc, TCGv r_cond)
     return 0;
 }
 
+static inline void gen_update_fprs_dirty(int rd)
+{
+#if defined(TARGET_SPARC64)
+    tcg_gen_ori_i32(cpu_fprs, cpu_fprs, (rd < 32) ? 1 : 2);
+#endif
+}
+
 static inline void gen_op_clear_ieee_excp_and_FTT(void)
 {
     tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_CEXC_NMASK);
@@ -2351,12 +2358,15 @@ static void disas_sparc_insn(DisasContext * dc)
                 switch (xop) {
                 case 0x1: /* fmovs */
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x5: /* fnegs */
                     gen_helper_fnegs(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x9: /* fabss */
                     gen_helper_fabss(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x29: /* fsqrts */
                     CHECK_FPU_FEATURE(dc, FSQRT);
@@ -2364,6 +2374,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsqrts(cpu_tmp32, cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x2a: /* fsqrtd */
                     CHECK_FPU_FEATURE(dc, FSQRT);
@@ -2372,6 +2383,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsqrtd();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x2b: /* fsqrtq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2380,12 +2392,14 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsqrtq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x41: /* fadds */
                     gen_clear_float_exceptions();
                     gen_helper_fadds(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x42: /* faddd */
                     gen_op_load_fpr_DT0(DFPREG(rs1));
@@ -2394,6 +2408,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_faddd();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x43: /* faddq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2403,12 +2418,14 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_faddq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x45: /* fsubs */
                     gen_clear_float_exceptions();
                     gen_helper_fsubs(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x46: /* fsubd */
                     gen_op_load_fpr_DT0(DFPREG(rs1));
@@ -2417,6 +2434,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsubd();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x47: /* fsubq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2426,6 +2444,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsubq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x49: /* fmuls */
                     CHECK_FPU_FEATURE(dc, FMUL);
@@ -2433,6 +2452,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fmuls(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x4a: /* fmuld */
                     CHECK_FPU_FEATURE(dc, FMUL);
@@ -2442,6 +2462,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fmuld();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x4b: /* fmulq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2452,12 +2473,14 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fmulq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x4d: /* fdivs */
                     gen_clear_float_exceptions();
                     gen_helper_fdivs(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x4e: /* fdivd */
                     gen_op_load_fpr_DT0(DFPREG(rs1));
@@ -2466,6 +2489,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdivd();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x4f: /* fdivq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2475,6 +2499,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdivq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x69: /* fsmuld */
                     CHECK_FPU_FEATURE(dc, FSMULD);
@@ -2482,6 +2507,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsmuld(cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x6e: /* fdmulq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2491,12 +2517,14 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdmulq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xc4: /* fitos */
                     gen_clear_float_exceptions();
                     gen_helper_fitos(cpu_tmp32, cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0xc6: /* fdtos */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
@@ -2504,6 +2532,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdtos(cpu_tmp32);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0xc7: /* fqtos */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2512,14 +2541,17 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fqtos(cpu_tmp32);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0xc8: /* fitod */
                     gen_helper_fitod(cpu_fpr[rs2]);
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0xc9: /* fstod */
                     gen_helper_fstod(cpu_fpr[rs2]);
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0xcb: /* fqtod */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2528,28 +2560,33 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fqtod();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0xcc: /* fitoq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_helper_fitoq(cpu_fpr[rs2]);
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xcd: /* fstoq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_helper_fstoq(cpu_fpr[rs2]);
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xce: /* fdtoq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fdtoq();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xd1: /* fstoi */
                     gen_clear_float_exceptions();
                     gen_helper_fstoi(cpu_tmp32, cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0xd2: /* fdtoi */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
@@ -2557,6 +2594,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdtoi(cpu_tmp32);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0xd3: /* fqtoi */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2565,12 +2603,14 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fqtoi(cpu_tmp32);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
 #ifdef TARGET_SPARC64
                 case 0x2: /* V9 fmovd */
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs2)]);
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x3: /* V9 fmovq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2581,34 +2621,40 @@ static void disas_sparc_insn(DisasContext * dc)
                                     cpu_fpr[QFPREG(rs2) + 2]);
                     tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3],
                                     cpu_fpr[QFPREG(rs2) + 3]);
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x6: /* V9 fnegd */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fnegd();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x7: /* V9 fnegq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_QT1(QFPREG(rs2));
                     gen_helper_fnegq();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xa: /* V9 fabsd */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fabsd();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0xb: /* V9 fabsq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_QT1(QFPREG(rs2));
                     gen_helper_fabsq();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x81: /* V9 fstox */
                     gen_clear_float_exceptions();
                     gen_helper_fstox(cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x82: /* V9 fdtox */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
@@ -2616,6 +2662,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdtox();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x83: /* V9 fqtox */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2624,6 +2671,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fqtox();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x84: /* V9 fxtos */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
@@ -2631,6 +2679,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fxtos(cpu_tmp32);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x88: /* V9 fxtod */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
@@ -2638,6 +2687,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fxtod();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x8c: /* V9 fxtoq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2646,6 +2696,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fxtoq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
 #endif
                 default:
@@ -2672,6 +2723,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
                                        0, l1);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     gen_set_label(l1);
                     break;
                 } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
@@ -2684,6 +2736,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                        0, l1);
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs2)]);
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1], cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     gen_set_label(l1);
                     break;
                 } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
@@ -2699,6 +2752,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 1], cpu_fpr[QFPREG(rs2) + 1]);
                     tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 2], cpu_fpr[QFPREG(rs2) + 2]);
                     tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3], cpu_fpr[QFPREG(rs2) + 3]);
+                    gen_update_fprs_dirty(QFPREG(rd));
                     gen_set_label(l1);
                     break;
                 }
@@ -2717,6 +2771,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                            0, l1);                      \
                         tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);     \
+                        gen_update_fprs_dirty(rd);                      \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -2735,6 +2790,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                         cpu_fpr[DFPREG(rs2)]);          \
                         tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1],        \
                                         cpu_fpr[DFPREG(rs2) + 1]);      \
+                        gen_update_fprs_dirty(DFPREG(rd));              \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -2757,6 +2813,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                         cpu_fpr[QFPREG(rs2) + 2]);      \
                         tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3],        \
                                         cpu_fpr[QFPREG(rs2) + 3]);      \
+                        gen_update_fprs_dirty(QFPREG(rd));              \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -2815,6 +2872,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                            0, l1);                      \
                         tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);     \
+                        gen_update_fprs_dirty(rd);                      \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -2833,6 +2891,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                         cpu_fpr[DFPREG(rs2)]);          \
                         tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1],        \
                                         cpu_fpr[DFPREG(rs2) + 1]);      \
+                        gen_update_fprs_dirty(DFPREG(rd));              \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -2855,6 +2914,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                         cpu_fpr[QFPREG(rs2) + 2]);      \
                         tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3],        \
                                         cpu_fpr[QFPREG(rs2) + 3]);      \
+                        gen_update_fprs_dirty(QFPREG(rd));              \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -3848,6 +3908,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmul8x16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x033: /* VIS I fmul8x16au */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3855,6 +3916,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmul8x16au();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x035: /* VIS I fmul8x16al */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3862,6 +3924,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmul8x16al();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x036: /* VIS I fmul8sux16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3869,6 +3932,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmul8sux16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x037: /* VIS I fmul8ulx16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3876,6 +3940,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmul8ulx16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x038: /* VIS I fmuld8sux16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3883,6 +3948,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmuld8sux16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x039: /* VIS I fmuld8ulx16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3890,6 +3956,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmuld8ulx16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x03a: /* VIS I fpack32 */
                 case 0x03b: /* VIS I fpack16 */
@@ -3903,6 +3970,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_faligndata();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x04b: /* VIS I fpmerge */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3910,6 +3978,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fpmerge();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x04c: /* VIS II bshuffle */
                     // XXX
@@ -3920,6 +3989,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fexpand();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x050: /* VIS I fpadd16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3927,11 +3997,13 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fpadd16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x051: /* VIS I fpadd16s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_helper_fpadd16s(cpu_fpr[rd],
                                         cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x052: /* VIS I fpadd32 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3939,11 +4011,13 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fpadd32();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x053: /* VIS I fpadd32s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_helper_fpadd32s(cpu_fpr[rd],
                                         cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x054: /* VIS I fpsub16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3951,11 +4025,13 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fpsub16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x055: /* VIS I fpsub16s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_helper_fpsub16s(cpu_fpr[rd],
                                         cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x056: /* VIS I fpsub32 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3963,20 +4039,24 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fpsub32();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x057: /* VIS I fpsub32s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_helper_fpsub32s(cpu_fpr[rd],
                                         cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x060: /* VIS I fzero */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_movi_i32(cpu_fpr[DFPREG(rd)], 0);
                     tcg_gen_movi_i32(cpu_fpr[DFPREG(rd) + 1], 0);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x061: /* VIS I fzeros */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_movi_i32(cpu_fpr[rd], 0);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x062: /* VIS I fnor */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3985,10 +4065,12 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_nor_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x063: /* VIS I fnors */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_nor_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x064: /* VIS I fandnot2 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3997,20 +4079,24 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_andc_i32(cpu_fpr[DFPREG(rd) + 1],
                                      cpu_fpr[DFPREG(rs1) + 1],
                                      cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x065: /* VIS I fandnot2s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_andc_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x066: /* VIS I fnot2 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_not_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs2)]);
                     tcg_gen_not_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x067: /* VIS I fnot2s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_not_i32(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x068: /* VIS I fandnot1 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4019,20 +4105,24 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_andc_i32(cpu_fpr[DFPREG(rd) + 1],
                                      cpu_fpr[DFPREG(rs2) + 1],
                                      cpu_fpr[DFPREG(rs1) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x069: /* VIS I fandnot1s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_andc_i32(cpu_fpr[rd], cpu_fpr[rs2], cpu_fpr[rs1]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x06a: /* VIS I fnot1 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_not_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)]);
                     tcg_gen_not_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x06b: /* VIS I fnot1s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_not_i32(cpu_fpr[rd], cpu_fpr[rs1]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x06c: /* VIS I fxor */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4041,10 +4131,12 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_xor_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x06d: /* VIS I fxors */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_xor_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x06e: /* VIS I fnand */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4053,10 +4145,12 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_nand_i32(cpu_fpr[DFPREG(rd) + 1],
                                      cpu_fpr[DFPREG(rs1) + 1],
                                      cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x06f: /* VIS I fnands */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_nand_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x070: /* VIS I fand */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4065,10 +4159,12 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_and_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x071: /* VIS I fands */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_and_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x072: /* VIS I fxnor */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4078,21 +4174,25 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_xori_i32(cpu_tmp32, cpu_fpr[DFPREG(rs2) + 1], -1);
                     tcg_gen_xor_i32(cpu_fpr[DFPREG(rd) + 1], cpu_tmp32,
                                     cpu_fpr[DFPREG(rs1) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x073: /* VIS I fxnors */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_xori_i32(cpu_tmp32, cpu_fpr[rs2], -1);
                     tcg_gen_xor_i32(cpu_fpr[rd], cpu_tmp32, cpu_fpr[rs1]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x074: /* VIS I fsrc1 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)]);
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x075: /* VIS I fsrc1s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs1]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x076: /* VIS I fornot2 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4101,19 +4201,23 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_orc_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x077: /* VIS I fornot2s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_orc_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x078: /* VIS I fsrc2 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs2));
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x079: /* VIS I fsrc2s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x07a: /* VIS I fornot1 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4122,10 +4226,12 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_orc_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x07b: /* VIS I fornot1s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_orc_i32(cpu_fpr[rd], cpu_fpr[rs2], cpu_fpr[rs1]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x07c: /* VIS I for */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4134,19 +4240,23 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_or_i32(cpu_fpr[DFPREG(rd) + 1],
                                    cpu_fpr[DFPREG(rs1) + 1],
                                    cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x07d: /* VIS I fors */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_or_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x07e: /* VIS I fone */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_movi_i32(cpu_fpr[DFPREG(rd)], -1);
                     tcg_gen_movi_i32(cpu_fpr[DFPREG(rd) + 1], -1);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x07f: /* VIS I fones */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_movi_i32(cpu_fpr[rd], -1);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x080: /* VIS I shutdown */
                 case 0x081: /* VIS II siam */
@@ -4492,6 +4602,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     }
                     save_state(dc, cpu_cond);
                     gen_ldf_asi(cpu_addr, insn, 4, rd);
+                    gen_update_fprs_dirty(rd);
                     goto skip_move;
                 case 0x33: /* V9 lddfa */
                     if (gen_trap_ifnofpu(dc, cpu_cond)) {
@@ -4499,6 +4610,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     }
                     save_state(dc, cpu_cond);
                     gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     goto skip_move;
                 case 0x3d: /* V9 prefetcha, no effect */
                     goto skip_move;
@@ -4509,6 +4621,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     }
                     save_state(dc, cpu_cond);
                     gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     goto skip_move;
 #endif
                 default:
@@ -4527,6 +4640,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_address_mask(dc, cpu_addr);
                     tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
                     tcg_gen_trunc_tl_i32(cpu_fpr[rd], cpu_tmp0);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x21:      /* ldfsr, V9 ldxfsr */
 #ifdef TARGET_SPARC64
@@ -4556,6 +4670,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         gen_helper_ldqf(cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
                         gen_op_store_QT0_fpr(QFPREG(rd));
+                        gen_update_fprs_dirty(QFPREG(rd));
                     }
                     break;
                 case 0x23:      /* lddf, load double fpreg */
@@ -4567,6 +4682,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         gen_helper_lddf(cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
                         gen_op_store_DT0_fpr(DFPREG(rd));
+                        gen_update_fprs_dirty(DFPREG(rd));
                     }
                     break;
                 default:
commit ccb57e0ea74892a29969f9a28c67df3fdcb5259d
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Sat Jul 23 11:20:06 2011 +0900

    SPARC64: fix fnor* and fnand*
    
    Fix the problem that result values are not assigned to the destination
    registers.
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 15967c5..f68b3bc 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -3980,14 +3980,15 @@ static void disas_sparc_insn(DisasContext * dc)
                     break;
                 case 0x062: /* VIS I fnor */
                     CHECK_FPU_FEATURE(dc, VIS1);
-                    tcg_gen_nor_i32(cpu_tmp32, cpu_fpr[DFPREG(rs1)],
+                    tcg_gen_nor_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)],
                                     cpu_fpr[DFPREG(rs2)]);
-                    tcg_gen_nor_i32(cpu_tmp32, cpu_fpr[DFPREG(rs1) + 1],
+                    tcg_gen_nor_i32(cpu_fpr[DFPREG(rd) + 1],
+                                    cpu_fpr[DFPREG(rs1) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
                     break;
                 case 0x063: /* VIS I fnors */
                     CHECK_FPU_FEATURE(dc, VIS1);
-                    tcg_gen_nor_i32(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
+                    tcg_gen_nor_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
                     break;
                 case 0x064: /* VIS I fandnot2 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4047,14 +4048,15 @@ static void disas_sparc_insn(DisasContext * dc)
                     break;
                 case 0x06e: /* VIS I fnand */
                     CHECK_FPU_FEATURE(dc, VIS1);
-                    tcg_gen_nand_i32(cpu_tmp32, cpu_fpr[DFPREG(rs1)],
+                    tcg_gen_nand_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)],
                                      cpu_fpr[DFPREG(rs2)]);
-                    tcg_gen_nand_i32(cpu_tmp32, cpu_fpr[DFPREG(rs1) + 1],
+                    tcg_gen_nand_i32(cpu_fpr[DFPREG(rd) + 1],
+                                     cpu_fpr[DFPREG(rs1) + 1],
                                      cpu_fpr[DFPREG(rs2) + 1]);
                     break;
                 case 0x06f: /* VIS I fnands */
                     CHECK_FPU_FEATURE(dc, VIS1);
-                    tcg_gen_nand_i32(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
+                    tcg_gen_nand_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
                     break;
                 case 0x070: /* VIS I fand */
                     CHECK_FPU_FEATURE(dc, VIS1);
commit 5e37141bbb9796ef139aee902a882ca97d59b84d
Author: Vincent Palatin <vpalatin at chromium.org>
Date:   Mon Jul 25 16:19:05 2011 -0700

    sd: do not add one sector to the disk size
    
    This leads to random off-by-one error.
    When the size of the SD is exactly 1GB, the emulation was returning a
    wrong SDHC CSD descriptor.
    
    Signed-off-by: Vincent Palatin <vpalatin at chromium.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/sd.c b/hw/sd.c
index 219a0dd..c2c80ab 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -393,9 +393,7 @@ static void sd_reset(SDState *sd, BlockDriverState *bdrv)
     } else {
         sect = 0;
     }
-    sect <<= 9;
-
-    size = sect + 1;
+    size = sect << 9;
 
     sect = (size >> (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)) + 1;
 
commit 4b5dfd8246321d2cdca0508f6837a681f7873f43
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Jul 18 11:44:09 2011 +0100

    user: Restore debug usage message for '-d ?' in user mode emulation
    
    The code which prints the debug usage message on '-d ?' for *-user
    has to come before the check for "not enough arguments", so that
    "qemu-foo -d ?" prints the list of possible debug log items rather than
    the generic usage message. (This was inadvertently broken in commit
    c235d73.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/bsd-user/main.c b/bsd-user/main.c
index 6018a41..a63b877 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -856,9 +856,6 @@ int main(int argc, char **argv)
             usage();
         }
     }
-    if (optind >= argc)
-        usage();
-    filename = argv[optind];
 
     /* init debug */
     cpu_set_log_filename(log_file);
@@ -877,6 +874,11 @@ int main(int argc, char **argv)
         cpu_set_log(mask);
     }
 
+    if (optind >= argc) {
+        usage();
+    }
+    filename = argv[optind];
+
     /* Zero out regs */
     memset(regs, 0, sizeof(struct target_pt_regs));
 
diff --git a/darwin-user/main.c b/darwin-user/main.c
index 35196a1..72307ad 100644
--- a/darwin-user/main.c
+++ b/darwin-user/main.c
@@ -809,9 +809,6 @@ int main(int argc, char **argv)
             usage();
         }
     }
-    if (optind >= argc)
-        usage();
-    filename = argv[optind];
 
     /* init debug */
     cpu_set_log_filename(log_file);
@@ -830,6 +827,11 @@ int main(int argc, char **argv)
         cpu_set_log(mask);
     }
 
+    if (optind >= argc) {
+        usage();
+    }
+    filename = argv[optind];
+
     /* Zero out regs */
     memset(regs, 0, sizeof(struct target_pt_regs));
 
diff --git a/linux-user/main.c b/linux-user/main.c
index 2135b9c..6a8f4bd 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3048,11 +3048,6 @@ int main(int argc, char **argv, char **envp)
             usage();
         }
     }
-    if (optind >= argc)
-        usage();
-    filename = argv[optind];
-    exec_path = argv[optind];
-
     /* init debug */
     cpu_set_log_filename(log_file);
     if (log_mask) {
@@ -3070,6 +3065,12 @@ int main(int argc, char **argv, char **envp)
         cpu_set_log(mask);
     }
 
+    if (optind >= argc) {
+        usage();
+    }
+    filename = argv[optind];
+    exec_path = argv[optind];
+
     /* Zero out regs */
     memset(regs, 0, sizeof(struct target_pt_regs));
 
commit 8534b8ba337e55031592144ea524f7bcaf144113
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sat Jul 30 07:18:41 2011 +0200

    usb-hid: Fix 0/0 position for Windows in tablet mode
    
    For unknown reasons, Windows drivers (tested with XP and Win7) ignore
    usb-tablet events that move the pointer to 0/0. So always report 0/0 as
    1/0.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index b812da2..9008320 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -459,6 +459,11 @@ static void usb_pointer_event_combine(USBPointerEvent *e, int xyrel,
     } else {
         e->xdx = x1;
         e->ydy = y1;
+        /* Windows drivers do not like the 0/0 position and ignore such
+         * events. */
+        if (!(x1 | y1)) {
+            x1 = 1;
+        }
     }
     e->dz += z1;
 }
commit 3bf11207c0676cfd29a3c76c6709fdf9a983c0c8
Author: Vasily Khoruzhick <anarsoul at gmail.com>
Date:   Wed Jul 6 16:52:49 2011 +0300

    Add support for Zipit Z2 machine
    
    Zipit Z2 is small PXA270 based handheld.
    
    Signed-off-by: Vasily Khoruzhick <anarsoul at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/Makefile.target b/Makefile.target
index 8884a56..d4ea042 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -352,6 +352,7 @@ obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
 obj-arm-y += omap_sx1.o palm.o tsc210x.o
 obj-arm-y += nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 obj-arm-y += mst_fpga.o mainstone.o
+obj-arm-y += z2.o
 obj-arm-y += musicpal.o bitbang_i2c.o marvell_88w8618_audio.o
 obj-arm-y += framebuffer.o
 obj-arm-y += syborg.o syborg_fb.o syborg_interrupt.o syborg_keyboard.o
diff --git a/hw/z2.c b/hw/z2.c
new file mode 100644
index 0000000..f93a1bf
--- /dev/null
+++ b/hw/z2.c
@@ -0,0 +1,358 @@
+/*
+ * PXA270-based Zipit Z2 device
+ *
+ * Copyright (c) 2011 by Vasily Khoruzhick <anarsoul at gmail.com>
+ *
+ * Code is based on mainstone platform.
+ *
+ * This code is licensed under the GNU GPL v2.
+ */
+
+#include "hw.h"
+#include "pxa.h"
+#include "arm-misc.h"
+#include "devices.h"
+#include "i2c.h"
+#include "ssi.h"
+#include "boards.h"
+#include "sysemu.h"
+#include "flash.h"
+#include "blockdev.h"
+#include "console.h"
+#include "audio/audio.h"
+
+#ifdef DEBUG_Z2
+#define DPRINTF(fmt, ...) \
+        printf(fmt, ## __VA_ARGS__)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+static struct keymap map[0x100] = {
+    [0 ... 0xff] = { -1, -1 },
+    [0x3b] = {0, 0}, /* Option = F1 */
+    [0xc8] = {0, 1}, /* Up */
+    [0xd0] = {0, 2}, /* Down */
+    [0xcb] = {0, 3}, /* Left */
+    [0xcd] = {0, 4}, /* Right */
+    [0xcf] = {0, 5}, /* End */
+    [0x0d] = {0, 6}, /* KPPLUS */
+    [0xc7] = {1, 0}, /* Home */
+    [0x10] = {1, 1}, /* Q */
+    [0x17] = {1, 2}, /* I */
+    [0x22] = {1, 3}, /* G */
+    [0x2d] = {1, 4}, /* X */
+    [0x1c] = {1, 5}, /* Enter */
+    [0x0c] = {1, 6}, /* KPMINUS */
+    [0xc9] = {2, 0}, /* PageUp */
+    [0x11] = {2, 1}, /* W */
+    [0x18] = {2, 2}, /* O */
+    [0x23] = {2, 3}, /* H */
+    [0x2e] = {2, 4}, /* C */
+    [0x38] = {2, 5}, /* LeftAlt */
+    [0xd1] = {3, 0}, /* PageDown */
+    [0x12] = {3, 1}, /* E */
+    [0x19] = {3, 2}, /* P */
+    [0x24] = {3, 3}, /* J */
+    [0x2f] = {3, 4}, /* V */
+    [0x2a] = {3, 5}, /* LeftShift */
+    [0x01] = {4, 0}, /* Esc */
+    [0x13] = {4, 1}, /* R */
+    [0x1e] = {4, 2}, /* A */
+    [0x25] = {4, 3}, /* K */
+    [0x30] = {4, 4}, /* B */
+    [0x1d] = {4, 5}, /* LeftCtrl */
+    [0x0f] = {5, 0}, /* Tab */
+    [0x14] = {5, 1}, /* T */
+    [0x1f] = {5, 2}, /* S */
+    [0x26] = {5, 3}, /* L */
+    [0x31] = {5, 4}, /* N */
+    [0x39] = {5, 5}, /* Space */
+    [0x3c] = {6, 0}, /* Stop = F2 */
+    [0x15] = {6, 1}, /* Y */
+    [0x20] = {6, 2}, /* D */
+    [0x0e] = {6, 3}, /* Backspace */
+    [0x32] = {6, 4}, /* M */
+    [0x33] = {6, 5}, /* Comma */
+    [0x3d] = {7, 0}, /* Play = F3 */
+    [0x16] = {7, 1}, /* U */
+    [0x21] = {7, 2}, /* F */
+    [0x2c] = {7, 3}, /* Z */
+    [0x27] = {7, 4}, /* Semicolon */
+    [0x34] = {7, 5}, /* Dot */
+};
+
+#define Z2_RAM_SIZE     0x02000000
+#define Z2_FLASH_BASE   0x00000000
+#define Z2_FLASH_SIZE   0x00800000
+
+static struct arm_boot_info z2_binfo = {
+    .loader_start   = PXA2XX_SDRAM_BASE,
+    .ram_size       = Z2_RAM_SIZE,
+};
+
+#define Z2_GPIO_SD_DETECT   96
+#define Z2_GPIO_AC_IN       0
+#define Z2_GPIO_KEY_ON      1
+#define Z2_GPIO_LCD_CS      88
+
+typedef struct {
+    SSISlave ssidev;
+    int32_t selected;
+    int32_t enabled;
+    uint8_t buf[3];
+    uint32_t cur_reg;
+    int pos;
+} ZipitLCD;
+
+static uint32_t zipit_lcd_transfer(SSISlave *dev, uint32_t value)
+{
+    ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev);
+    uint16_t val;
+    if (z->selected) {
+        z->buf[z->pos] = value & 0xff;
+        z->pos++;
+    }
+    if (z->pos == 3) {
+        switch (z->buf[0]) {
+        case 0x74:
+            DPRINTF("%s: reg: 0x%.2x\n", __func__, z->buf[2]);
+            z->cur_reg = z->buf[2];
+            break;
+        case 0x76:
+            val = z->buf[1] << 8 | z->buf[2];
+            DPRINTF("%s: value: 0x%.4x\n", __func__, val);
+            if (z->cur_reg == 0x22 && val == 0x0000) {
+                z->enabled = 1;
+                printf("%s: LCD enabled\n", __func__);
+            } else if (z->cur_reg == 0x10 && val == 0x0000) {
+                z->enabled = 0;
+                printf("%s: LCD disabled\n", __func__);
+            }
+            break;
+        default:
+            DPRINTF("%s: unknown command!\n", __func__);
+            break;
+        }
+        z->pos = 0;
+    }
+    return 0;
+}
+
+static void z2_lcd_cs(void *opaque, int line, int level)
+{
+    ZipitLCD *z2_lcd = opaque;
+    z2_lcd->selected = !level;
+}
+
+static int zipit_lcd_init(SSISlave *dev)
+{
+    ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev);
+    z->selected = 0;
+    z->enabled = 0;
+    z->pos = 0;
+
+    return 0;
+}
+
+static VMStateDescription vmstate_zipit_lcd_state = {
+    .name = "zipit-lcd",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_INT32(selected, ZipitLCD),
+        VMSTATE_INT32(enabled, ZipitLCD),
+        VMSTATE_BUFFER(buf, ZipitLCD),
+        VMSTATE_UINT32(cur_reg, ZipitLCD),
+        VMSTATE_INT32(pos, ZipitLCD),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static SSISlaveInfo zipit_lcd_info = {
+    .qdev.name = "zipit-lcd",
+    .qdev.size = sizeof(ZipitLCD),
+    .qdev.vmsd = &vmstate_zipit_lcd_state,
+    .init = zipit_lcd_init,
+    .transfer = zipit_lcd_transfer
+};
+
+typedef struct {
+    i2c_slave i2c;
+    int len;
+    uint8_t buf[3];
+} AER915State;
+
+static int aer915_send(i2c_slave *i2c, uint8_t data)
+{
+    AER915State *s = FROM_I2C_SLAVE(AER915State, i2c);
+    s->buf[s->len] = data;
+    if (s->len++ > 2) {
+        DPRINTF("%s: message too long (%i bytes)\n",
+            __func__, s->len);
+        return 1;
+    }
+
+    if (s->len == 2) {
+        DPRINTF("%s: reg %d value 0x%02x\n", __func__,
+                s->buf[0], s->buf[1]);
+    }
+
+    return 0;
+}
+
+static void aer915_event(i2c_slave *i2c, enum i2c_event event)
+{
+    AER915State *s = FROM_I2C_SLAVE(AER915State, i2c);
+    switch (event) {
+    case I2C_START_SEND:
+        s->len = 0;
+        break;
+    case I2C_START_RECV:
+        if (s->len != 1) {
+            DPRINTF("%s: short message!?\n", __func__);
+        }
+        break;
+    case I2C_FINISH:
+        break;
+    default:
+        break;
+    }
+}
+
+static int aer915_recv(i2c_slave *slave)
+{
+    int retval = 0x00;
+    AER915State *s = FROM_I2C_SLAVE(AER915State, slave);
+
+    switch (s->buf[0]) {
+    /* Return hardcoded battery voltage,
+     * 0xf0 means ~4.1V
+     */
+    case 0x02:
+        retval = 0xf0;
+        break;
+    /* Return 0x00 for other regs,
+     * we don't know what they are for,
+     * anyway they return 0x00 on real hardware.
+     */
+    default:
+        break;
+    }
+
+    return retval;
+}
+
+static int aer915_init(i2c_slave *i2c)
+{
+    /* Nothing to do.  */
+    return 0;
+}
+
+static VMStateDescription vmstate_aer915_state = {
+    .name = "aer915",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_INT32(len, AER915State),
+        VMSTATE_BUFFER(buf, AER915State),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static I2CSlaveInfo aer915_info = {
+    .qdev.name = "aer915",
+    .qdev.size = sizeof(AER915State),
+    .qdev.vmsd = &vmstate_aer915_state,
+    .init = aer915_init,
+    .event = aer915_event,
+    .recv = aer915_recv,
+    .send = aer915_send
+};
+
+static void z2_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)
+{
+    uint32_t sector_len = 0x10000;
+    PXA2xxState *cpu;
+    DriveInfo *dinfo;
+    int be;
+    void *z2_lcd;
+    i2c_bus *bus;
+    DeviceState *wm;
+
+    if (!cpu_model) {
+        cpu_model = "pxa270-c5";
+    }
+
+    /* Setup CPU & memory */
+    cpu = pxa270_init(z2_binfo.ram_size, cpu_model);
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    be = 1;
+#else
+    be = 0;
+#endif
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (!dinfo) {
+        fprintf(stderr, "Flash image must be given with the "
+                "'pflash' parameter\n");
+        exit(1);
+    }
+
+    if (!pflash_cfi01_register(Z2_FLASH_BASE,
+                               qemu_ram_alloc(NULL, "z2.flash0", Z2_FLASH_SIZE),
+                               dinfo->bdrv, sector_len,
+                               Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0,
+                               be)) {
+        fprintf(stderr, "qemu: Error registering flash memory.\n");
+        exit(1);
+    }
+
+    /* setup keypad */
+    pxa27x_register_keypad(cpu->kp, map, 0x100);
+
+    /* MMC/SD host */
+    pxa2xx_mmci_handlers(cpu->mmc,
+        NULL,
+        qdev_get_gpio_in(cpu->gpio, Z2_GPIO_SD_DETECT));
+
+    ssi_register_slave(&zipit_lcd_info);
+    i2c_register_slave(&aer915_info);
+    z2_lcd = ssi_create_slave(cpu->ssp[1], "zipit-lcd");
+    bus = pxa2xx_i2c_bus(cpu->i2c[0]);
+    i2c_create_slave(bus, "aer915", 0x55);
+    wm = i2c_create_slave(bus, "wm8750", 0x1b);
+    cpu->i2s->opaque = wm;
+    cpu->i2s->codec_out = wm8750_dac_dat;
+    cpu->i2s->codec_in = wm8750_adc_dat;
+    wm8750_data_req_set(wm, cpu->i2s->data_req, cpu->i2s);
+
+    qdev_connect_gpio_out(cpu->gpio, Z2_GPIO_LCD_CS,
+        qemu_allocate_irqs(z2_lcd_cs, z2_lcd, 1)[0]);
+
+    if (kernel_filename) {
+        z2_binfo.kernel_filename = kernel_filename;
+        z2_binfo.kernel_cmdline = kernel_cmdline;
+        z2_binfo.initrd_filename = initrd_filename;
+        z2_binfo.board_id = 0x6dd;
+        arm_load_kernel(cpu->env, &z2_binfo);
+    }
+}
+
+static QEMUMachine z2_machine = {
+    .name = "z2",
+    .desc = "Zipit Z2 (PXA27x)",
+    .init = z2_init,
+};
+
+static void z2_machine_init(void)
+{
+    qemu_register_machine(&z2_machine);
+}
+
+machine_init(z2_machine_init);
commit 63efb1d9c4140108ab57e706fa7a90a21e07cfcc
Author: Andrzej Zaborowski <andrew.zaborowski at intel.com>
Date:   Sat Jul 30 06:53:39 2011 +0200

    onenand: Add missing brace.
    
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/onenand.c b/hw/onenand.c
index e8d1d4b..b0cbebc 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -720,6 +720,7 @@ void *onenand_init(BlockDriverState *bdrv,
     if (!s->bdrv) {
         s->image = memset(qemu_malloc(size + (size >> 5)),
                         0xff, size + (size >> 5));
+    }
     s->otp = memset(qemu_malloc((64 + 2) << PAGE_SHIFT),
                     0xff, (64 + 2) << PAGE_SHIFT);
     s->ram = qemu_ram_alloc(NULL, "onenand.ram", 0xc000 << s->shift);
commit f1588dd26c25bd7590e18a0cce59a5fa82323ce5
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Fri Jul 29 16:35:28 2011 +0100

    hw/onenand: program actions can only clear bits
    
    The program actions onenand_prog_main() and onenand_prog_spare()
    can only set bits.
    
    This implies a rewrite of onenand_erase() to not use the program
    functions, since erase does need to set bits.
    
    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>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/onenand.c b/hw/onenand.c
index d87079e..e8d1d4b 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -179,14 +179,39 @@ static inline int onenand_load_main(OneNANDState *s, int sec, int secn,
 static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
                 void *src)
 {
-    if (s->bdrv_cur)
-        return bdrv_write(s->bdrv_cur, sec, src, secn) < 0;
-    else if (sec + secn > s->secs_cur)
-        return 1;
-
-    memcpy(s->current + (sec << 9), src, secn << 9);
+    int result = 0;
+
+    if (secn > 0) {
+        uint32_t size = (uint32_t) secn * 512;
+        const uint8_t *sp = (const uint8_t *) src;
+        uint8_t *dp = 0;
+        if (s->bdrv_cur) {
+            dp = qemu_malloc(size);
+            if (!dp || bdrv_read(s->bdrv_cur, sec, dp, secn) < 0) {
+                result = 1;
+            }
+        } else {
+            if (sec + secn > s->secs_cur) {
+                result = 1;
+            } else {
+                dp = (uint8_t *) s->current + (sec << 9);
+            }
+        }
+        if (!result) {
+            uint32_t i;
+            for (i = 0; i < size; i++) {
+                dp[i] &= sp[i];
+            }
+            if (s->bdrv_cur) {
+                result = bdrv_write(s->bdrv_cur, sec, dp, secn) < 0;
+            }
+        }
+        if (dp && s->bdrv_cur) {
+            qemu_free(dp);
+        }
+    }
 
-    return 0;
+    return result;
 }
 
 static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
@@ -209,35 +234,87 @@ static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
 static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
                 void *src)
 {
-    uint8_t buf[512];
-
-    if (s->bdrv_cur) {
-        if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0)
-            return 1;
-        memcpy(buf + ((sec & 31) << 4), src, secn << 4);
-        return bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0;
-    } else if (sec + secn > s->secs_cur)
-        return 1;
-
-    memcpy(s->current + (s->secs_cur << 9) + (sec << 4), src, secn << 4);
- 
-    return 0;
+    int result = 0;
+    if (secn > 0) {
+        const uint8_t *sp = (const uint8_t *) src;
+        uint8_t *dp = 0, *dpp = 0;
+        if (s->bdrv_cur) {
+            dp = qemu_malloc(512);
+            if (!dp || bdrv_read(s->bdrv_cur,
+                                s->secs_cur + (sec >> 5),
+                                dp, 1) < 0) {
+                result = 1;
+            } else {
+                dpp = dp + ((sec & 31) << 4);
+            }
+        } else {
+            if (sec + secn > s->secs_cur) {
+                result = 1;
+            } else {
+                dpp = s->current + (s->secs_cur << 9) + (sec << 4);
+            }
+        }
+        if (!result) {
+            uint32_t i;
+            for (i = 0; i < (secn << 4); i++) {
+                dpp[i] &= sp[i];
+            }
+            if (s->bdrv_cur) {
+                result = bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5),
+                                dp, 1) < 0;
+            }
+        }
+        if (dp) {
+            qemu_free(dp);
+        }
+    }
+    return result;
 }
 
 static inline int onenand_erase(OneNANDState *s, int sec, int num)
 {
-    /* TODO: optimise */
-    uint8_t buf[512];
-
-    memset(buf, 0xff, sizeof(buf));
-    for (; num > 0; num --, sec ++) {
-        if (onenand_prog_main(s, sec, 1, buf))
-            return 1;
-        if (onenand_prog_spare(s, sec, 1, buf))
-            return 1;
+    uint8_t *blankbuf, *tmpbuf;
+    blankbuf = qemu_malloc(512);
+    if (!blankbuf) {
+        return 1;
+    }
+    tmpbuf = qemu_malloc(512);
+    if (!tmpbuf) {
+        qemu_free(blankbuf);
+        return 1;
+    }
+    memset(blankbuf, 0xff, 512);
+    for (; num > 0; num--, sec++) {
+        if (s->bdrv_cur) {
+            int erasesec = s->secs_cur + (sec >> 5);
+            if (bdrv_write(s->bdrv_cur, sec, blankbuf, 1)) {
+                goto fail;
+            }
+            if (bdrv_read(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
+                goto fail;
+            }
+            memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4);
+            if (bdrv_write(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
+                goto fail;
+            }
+        } else {
+            if (sec + 1 > s->secs_cur) {
+                goto fail;
+            }
+            memcpy(s->current + (sec << 9), blankbuf, 512);
+            memcpy(s->current + (s->secs_cur << 9) + (sec << 4),
+                   blankbuf, 1 << 4);
+        }
     }
 
+    qemu_free(tmpbuf);
+    qemu_free(blankbuf);
     return 0;
+
+fail:
+    qemu_free(tmpbuf);
+    qemu_free(blankbuf);
+    return 1;
 }
 
 static void onenand_command(OneNANDState *s, int cmd)
commit 5923ba424b4754a60ea5f6dc7777684e018648e6
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Fri Jul 29 16:35:26 2011 +0100

    onenand: Handle various ID fields separately
    
    Handle the manufacturer, device and version IDs separately rather than
    smooshing them all together into a single uint32_t. Note that the ID
    registers are actually 16 bit, even though typically the top bits are 0
    and the Read Identification Data command only returns the bottom 8 bits.
    
    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>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/flash.h b/hw/flash.h
index d61647f..140ae39 100644
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -38,7 +38,8 @@ uint32_t nand_getbuswidth(DeviceState *dev);
 /* onenand.c */
 void onenand_base_update(void *opaque, target_phys_addr_t new);
 void onenand_base_unmap(void *opaque);
-void *onenand_init(BlockDriverState *bdrv, uint32_t id,
+void *onenand_init(BlockDriverState *bdrv,
+                uint16_t man_id, uint16_t dev_id, uint16_t ver_id,
                 int regshift, qemu_irq irq);
 void *onenand_raw_otp(void *opaque);
 
diff --git a/hw/nseries.c b/hw/nseries.c
index be50a5c..6a5575e 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -167,8 +167,9 @@ static void n8x0_nand_setup(struct n800_s *s)
     DriveInfo *dinfo;
 
     dinfo = drive_get(IF_MTD, 0, 0);
-    /* Either ec40xx or ec48xx are OK for the ID */
-    s->nand = onenand_init(dinfo ? dinfo->bdrv : 0, 0xec4800, 1,
+    /* Either 0x40 or 0x48 are OK for the device ID */
+    s->nand = onenand_init(dinfo ? dinfo->bdrv : 0,
+                    NAND_MFR_SAMSUNG, 0x48, 0, 1,
                     qdev_get_gpio_in(s->cpu->gpio, N8X0_ONENAND_GPIO));
     omap_gpmc_attach(s->cpu->gpmc, N8X0_ONENAND_CS, 0, onenand_base_update,
                     onenand_base_unmap, s->nand);
diff --git a/hw/onenand.c b/hw/onenand.c
index 942b69a..d87079e 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -31,7 +31,11 @@
 #define BLOCK_SHIFT	(PAGE_SHIFT + 6)
 
 typedef struct {
-    uint32_t id;
+    struct {
+        uint16_t man;
+        uint16_t dev;
+        uint16_t ver;
+    } id;
     int shift;
     target_phys_addr_t base;
     qemu_irq intr;
@@ -453,12 +457,12 @@ static uint32_t onenand_read(void *opaque, target_phys_addr_t addr)
         return lduw_le_p(s->boot[0] + addr);
 
     case 0xf000:	/* Manufacturer ID */
-        return (s->id >> 16) & 0xff;
+        return s->id.man;
     case 0xf001:	/* Device ID */
-        return (s->id >>  8) & 0xff;
-    /* TODO: get the following values from a real chip!  */
+        return s->id.dev;
     case 0xf002:	/* Version ID */
-        return (s->id >>  0) & 0xff;
+        return s->id.ver;
+    /* TODO: get the following values from a real chip!  */
     case 0xf003:	/* Data Buffer size */
         return 1 << PAGE_SHIFT;
     case 0xf004:	/* Boot Buffer size */
@@ -541,8 +545,8 @@ static void onenand_write(void *opaque, target_phys_addr_t addr,
 
         case 0x0090:	/* Read Identification Data */
             memset(s->boot[0], 0, 3 << s->shift);
-            s->boot[0][0 << s->shift] = (s->id >> 16) & 0xff;
-            s->boot[0][1 << s->shift] = (s->id >>  8) & 0xff;
+            s->boot[0][0 << s->shift] = s->id.man & 0xff;
+            s->boot[0][1 << s->shift] = s->id.dev & 0xff;
             s->boot[0][2 << s->shift] = s->wpstatus & 0xff;
             break;
 
@@ -615,21 +619,24 @@ static CPUWriteMemoryFunc * const onenand_writefn[] = {
     onenand_write,
 };
 
-void *onenand_init(BlockDriverState *bdrv, uint32_t id,
+void *onenand_init(BlockDriverState *bdrv,
+                uint16_t man_id, uint16_t dev_id, uint16_t ver_id,
                 int regshift, qemu_irq irq)
 {
     OneNANDState *s = (OneNANDState *) qemu_mallocz(sizeof(*s));
-    uint32_t size = 1 << (24 + ((id >> 12) & 7));
+    uint32_t size = 1 << (24 + ((dev_id >> 4) & 7));
     void *ram;
 
     s->shift = regshift;
     s->intr = irq;
     s->rdy = NULL;
-    s->id = id;
+    s->id.man = man_id;
+    s->id.dev = dev_id;
+    s->id.ver = ver_id;
     s->blocks = size >> BLOCK_SHIFT;
     s->secs = size >> 9;
     s->blockwp = qemu_malloc(s->blocks);
-    s->density_mask = (id & (1 << 11)) ? (1 << (6 + ((id >> 12) & 7))) : 0;
+    s->density_mask = (dev_id & 0x08) ? (1 << (6 + ((dev_id >> 4) & 7))) : 0;
     s->iomemtype = cpu_register_io_memory(onenand_readfn,
                     onenand_writefn, s, DEVICE_NATIVE_ENDIAN);
     s->bdrv = bdrv;
commit af5a75f41c2fd172ceaa1cabd4bec99de8dde83a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jul 29 16:35:25 2011 +0100

    onenand: Pass BlockDriverState to init function
    
    Pass the BlockDriverState to the onenand init function so it doesn't
    need to look up the drive itself.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/flash.h b/hw/flash.h
index 43260ce..d61647f 100644
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -38,7 +38,8 @@ uint32_t nand_getbuswidth(DeviceState *dev);
 /* onenand.c */
 void onenand_base_update(void *opaque, target_phys_addr_t new);
 void onenand_base_unmap(void *opaque);
-void *onenand_init(uint32_t id, int regshift, qemu_irq irq);
+void *onenand_init(BlockDriverState *bdrv, uint32_t id,
+                int regshift, qemu_irq irq);
 void *onenand_raw_otp(void *opaque);
 
 /* ecc.c */
diff --git a/hw/nseries.c b/hw/nseries.c
index d12ed46..be50a5c 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -31,6 +31,7 @@
 #include "hw.h"
 #include "bt.h"
 #include "loader.h"
+#include "blockdev.h"
 
 /* Nokia N8x0 support */
 struct n800_s {
@@ -163,13 +164,14 @@ static const uint8_t n8x0_cal_bt_id[] = {
 static void n8x0_nand_setup(struct n800_s *s)
 {
     char *otp_region;
+    DriveInfo *dinfo;
 
+    dinfo = drive_get(IF_MTD, 0, 0);
     /* Either ec40xx or ec48xx are OK for the ID */
+    s->nand = onenand_init(dinfo ? dinfo->bdrv : 0, 0xec4800, 1,
+                    qdev_get_gpio_in(s->cpu->gpio, N8X0_ONENAND_GPIO));
     omap_gpmc_attach(s->cpu->gpmc, N8X0_ONENAND_CS, 0, onenand_base_update,
-                    onenand_base_unmap,
-                    (s->nand = onenand_init(0xec4800, 1,
-                                            qdev_get_gpio_in(s->cpu->gpio,
-                                                    N8X0_ONENAND_GPIO))));
+                    onenand_base_unmap, s->nand);
     otp_region = onenand_raw_otp(s->nand);
 
     memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac));
diff --git a/hw/onenand.c b/hw/onenand.c
index 71c1ab4..942b69a 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -615,10 +615,10 @@ static CPUWriteMemoryFunc * const onenand_writefn[] = {
     onenand_write,
 };
 
-void *onenand_init(uint32_t id, int regshift, qemu_irq irq)
+void *onenand_init(BlockDriverState *bdrv, uint32_t id,
+                int regshift, qemu_irq irq)
 {
     OneNANDState *s = (OneNANDState *) qemu_mallocz(sizeof(*s));
-    DriveInfo *dinfo = drive_get(IF_MTD, 0, 0);
     uint32_t size = 1 << (24 + ((id >> 12) & 7));
     void *ram;
 
@@ -632,11 +632,10 @@ void *onenand_init(uint32_t id, int regshift, qemu_irq irq)
     s->density_mask = (id & (1 << 11)) ? (1 << (6 + ((id >> 12) & 7))) : 0;
     s->iomemtype = cpu_register_io_memory(onenand_readfn,
                     onenand_writefn, s, DEVICE_NATIVE_ENDIAN);
-    if (!dinfo)
+    s->bdrv = bdrv;
+    if (!s->bdrv) {
         s->image = memset(qemu_malloc(size + (size >> 5)),
                         0xff, size + (size >> 5));
-    else
-        s->bdrv = dinfo->bdrv;
     s->otp = memset(qemu_malloc((64 + 2) << PAGE_SHIFT),
                     0xff, (64 + 2) << PAGE_SHIFT);
     s->ram = qemu_ram_alloc(NULL, "onenand.ram", 0xc000 << s->shift);
commit d4220389ffcc1e6302e759d3b15f8605201d6369
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Fri Jul 29 16:35:24 2011 +0100

    hw/nand: qdevify
    
    Qdevify the NAND device.
    
    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>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index de1f5a5..e0a8c14 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -37,7 +37,7 @@
 
 struct nand_state_t
 {
-    NANDFlashState *nand;
+    DeviceState *nand;
     unsigned int rdy:1;
     unsigned int ale:1;
     unsigned int cle:1;
diff --git a/hw/flash.h b/hw/flash.h
index 132ad29..43260ce 100644
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -18,15 +18,13 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
                                 int be);
 
 /* nand.c */
-typedef struct NANDFlashState NANDFlashState;
-NANDFlashState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id);
-void nand_done(NANDFlashState *s);
-void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
+DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id);
+void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale,
                   uint8_t ce, uint8_t wp, uint8_t gnd);
-void nand_getpins(NANDFlashState *s, int *rb);
-void nand_setio(NANDFlashState *s, uint32_t value);
-uint32_t nand_getio(NANDFlashState *s);
-uint32_t nand_getbuswidth(NANDFlashState *s);
+void nand_getpins(DeviceState *dev, int *rb);
+void nand_setio(DeviceState *dev, uint32_t value);
+uint32_t nand_getio(DeviceState *dev);
+uint32_t nand_getbuswidth(DeviceState *dev);
 
 #define NAND_MFR_TOSHIBA	0x98
 #define NAND_MFR_SAMSUNG	0xec
diff --git a/hw/nand.c b/hw/nand.c
index 35804c7..28d9f0b 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -18,6 +18,7 @@
 # include "hw.h"
 # include "flash.h"
 # include "blockdev.h"
+# include "sysbus.h"
 
 # define NAND_CMD_READ0		0x00
 # define NAND_CMD_READ1		0x01
@@ -47,7 +48,9 @@
 # define MAX_PAGE		0x800
 # define MAX_OOB		0x40
 
+typedef struct NANDFlashState NANDFlashState;
 struct NANDFlashState {
+    SysBusDevice busdev;
     uint8_t manf_id, chip_id;
     uint8_t buswidth; /* in BYTES */
     int size, pages;
@@ -215,8 +218,9 @@ static const struct {
     [0xc5] = { 2048,	16,	0, 0, LP_OPTIONS16 },
 };
 
-static void nand_reset(NANDFlashState *s)
+static void nand_reset(DeviceState *dev)
 {
+    NANDFlashState *s = FROM_SYSBUS(NANDFlashState, sysbus_from_qdev(dev));
     s->cmd = NAND_CMD_READ0;
     s->addr = 0;
     s->addrlen = 0;
@@ -270,7 +274,7 @@ static void nand_command(NANDFlashState *s)
         break;
 
     case NAND_CMD_RESET:
-        nand_reset(s);
+        nand_reset(&s->busdev.qdev);
         break;
 
     case NAND_CMD_PAGEPROGRAM1:
@@ -354,15 +358,85 @@ static const VMStateDescription vmstate_nand = {
     }
 };
 
+static int nand_device_init(SysBusDevice *dev)
+{
+    int pagesize;
+    NANDFlashState *s = FROM_SYSBUS(NANDFlashState, dev);
+
+    s->buswidth = nand_flash_ids[s->chip_id].width >> 3;
+    s->size = nand_flash_ids[s->chip_id].size << 20;
+    if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
+        s->page_shift = 11;
+        s->erase_shift = 6;
+    } else {
+        s->page_shift = nand_flash_ids[s->chip_id].page_shift;
+        s->erase_shift = nand_flash_ids[s->chip_id].erase_shift;
+    }
+
+    switch (1 << s->page_shift) {
+    case 256:
+        nand_init_256(s);
+        break;
+    case 512:
+        nand_init_512(s);
+        break;
+    case 2048:
+        nand_init_2048(s);
+        break;
+    default:
+        hw_error("%s: Unsupported NAND block size.\n", __func__);
+    }
+
+    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) {
+        pagesize += 1 << s->page_shift;
+    }
+    if (pagesize) {
+        s->storage = (uint8_t *) memset(qemu_malloc(s->pages * pagesize),
+                        0xff, s->pages * pagesize);
+    }
+    /* Give s->ioaddr a sane value in case we save state before it is used. */
+    s->ioaddr = s->io;
+
+    return 0;
+}
+
+static SysBusDeviceInfo nand_info = {
+    .init = nand_device_init,
+    .qdev.name = "nand",
+    .qdev.size = sizeof(NANDFlashState),
+    .qdev.reset = nand_reset,
+    .qdev.vmsd = &vmstate_nand,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT8("manufacturer_id", NANDFlashState, manf_id, 0),
+        DEFINE_PROP_UINT8("chip_id", NANDFlashState, chip_id, 0),
+        DEFINE_PROP_DRIVE("drive", NANDFlashState, bdrv),
+        DEFINE_PROP_END_OF_LIST()
+    }
+};
+
+static void nand_create_device(void)
+{
+    sysbus_register_withprop(&nand_info);
+}
+
 /*
  * Chip inputs are CLE, ALE, CE, WP, GND and eight I/O pins.  Chip
  * outputs are R/B and eight I/O pins.
  *
  * CE, WP and R/B are active low.
  */
-void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
+void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale,
                   uint8_t ce, uint8_t wp, uint8_t gnd)
 {
+    NANDFlashState *s = (NANDFlashState *) dev;
     s->cle = cle;
     s->ale = ale;
     s->ce = ce;
@@ -374,15 +448,15 @@ void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
         s->status &= ~NAND_IOSTATUS_UNPROTCT;
 }
 
-void nand_getpins(NANDFlashState *s, int *rb)
+void nand_getpins(DeviceState *dev, int *rb)
 {
     *rb = 1;
 }
 
-void nand_setio(NANDFlashState *s, uint32_t value)
+void nand_setio(DeviceState *dev, uint32_t value)
 {
     int i;
-
+    NANDFlashState *s = (NANDFlashState *) dev;
     if (!s->ce && s->cle) {
         if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
             if (s->cmd == NAND_CMD_READ0 && value == NAND_CMD_LPREAD2)
@@ -482,10 +556,11 @@ void nand_setio(NANDFlashState *s, uint32_t value)
     }
 }
 
-uint32_t nand_getio(NANDFlashState *s)
+uint32_t nand_getio(DeviceState *dev)
 {
     int offset;
     uint32_t x = 0;
+    NANDFlashState *s = (NANDFlashState *) dev;
 
     /* Allow sequential reading */
     if (!s->iolen && s->cmd == NAND_CMD_READ0) {
@@ -516,82 +591,31 @@ uint32_t nand_getio(NANDFlashState *s)
     return x;
 }
 
-uint32_t nand_getbuswidth(NANDFlashState *s)
+uint32_t nand_getbuswidth(DeviceState *dev)
 {
+    NANDFlashState *s = (NANDFlashState *) dev;
     return s->buswidth << 3;
 }
 
-NANDFlashState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id)
+DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id)
 {
-    int pagesize;
-    NANDFlashState *s;
+    DeviceState *dev;
 
     if (nand_flash_ids[chip_id].size == 0) {
         hw_error("%s: Unsupported NAND chip ID.\n", __FUNCTION__);
     }
-
-    s = (NANDFlashState *) qemu_mallocz(sizeof(NANDFlashState));
-    s->bdrv = bdrv;
-    s->manf_id = manf_id;
-    s->chip_id = chip_id;
-    s->buswidth = nand_flash_ids[s->chip_id].width >> 3;
-    s->size = nand_flash_ids[s->chip_id].size << 20;
-    if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
-        s->page_shift = 11;
-        s->erase_shift = 6;
-    } else {
-        s->page_shift = nand_flash_ids[s->chip_id].page_shift;
-        s->erase_shift = nand_flash_ids[s->chip_id].erase_shift;
-    }
-
-    switch (1 << s->page_shift) {
-    case 256:
-        nand_init_256(s);
-        break;
-    case 512:
-        nand_init_512(s);
-        break;
-    case 2048:
-        nand_init_2048(s);
-        break;
-    default:
-        hw_error("%s: Unsupported NAND block size.\n", __FUNCTION__);
-    }
-
-    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;
+    dev = qdev_create(NULL, "nand");
+    qdev_prop_set_uint8(dev, "manufacturer_id", manf_id);
+    qdev_prop_set_uint8(dev, "chip_id", chip_id);
+    if (bdrv) {
+        qdev_prop_set_drive_nofail(dev, "drive", bdrv);
     }
 
-    if (!s->bdrv)
-        pagesize += 1 << s->page_shift;
-    if (pagesize)
-        s->storage = (uint8_t *) memset(qemu_malloc(s->pages * pagesize),
-                        0xff, s->pages * pagesize);
-    /* Give s->ioaddr a sane value in case we save state before it
-       is used.  */
-    s->ioaddr = s->io;
-
-    vmstate_register(NULL, -1, &vmstate_nand, s);
-
-    return s;
+    qdev_init_nofail(dev);
+    return dev;
 }
 
-void nand_done(NANDFlashState *s)
-{
-    if (s->bdrv) {
-        bdrv_close(s->bdrv);
-        bdrv_delete(s->bdrv);
-    }
-
-    if (!s->bdrv || s->mem_oob)
-        qemu_free(s->storage);
-
-    qemu_free(s);
-}
+device_init(nand_create_device)
 
 #else
 
diff --git a/hw/spitz.c b/hw/spitz.c
index 78e9c34..c05b5f7 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -48,7 +48,7 @@
 
 typedef struct {
     SysBusDevice busdev;
-    NANDFlashState *nand;
+    DeviceState *nand;
     uint8_t ctl;
     uint8_t manf_id;
     uint8_t chip_id;
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index 4de0819..a1c48bf 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -118,7 +118,7 @@ struct TC6393xbState {
     } nand;
     int nand_enable;
     uint32_t nand_phys;
-    NANDFlashState *flash;
+    DeviceState *flash;
     ECCState ecc;
 
     DisplayState *ds;
commit 89f640bc0405ed1e9c5c5a6cb6c19c8012d11e3f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jul 29 16:35:23 2011 +0100

    hw/nand: Writing to NAND can only clear bits
    
    Writing to a NAND device cannot set bits, it can only clear them;
    implement this rather than simply copying the data.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/nand.c b/hw/nand.c
index 1eefe28..35804c7 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -75,6 +75,15 @@ struct NANDFlashState {
     uint32_t ioaddr_vmstate;
 };
 
+static void mem_and(uint8_t *dest, const uint8_t *src, size_t n)
+{
+    /* Like memcpy() but we logical-AND the data into the destination */
+    int i;
+    for (i = 0; i < n; i++) {
+        dest[i] &= src[i];
+    }
+}
+
 # define NAND_NO_AUTOINCR	0x00000001
 # define NAND_BUSWIDTH_16	0x00000002
 # define NAND_NO_PADDING	0x00000004
@@ -595,7 +604,7 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
         return;
 
     if (!s->bdrv) {
-        memcpy(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) +
+        mem_and(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) +
                         s->offset, s->io, s->iolen);
     } else if (s->mem_oob) {
         sector = SECTOR(s->addr);
@@ -606,10 +615,10 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
             return;
         }
 
-        memcpy(iobuf + (soff | off), s->io, MIN(s->iolen, PAGE_SIZE - off));
+        mem_and(iobuf + (soff | off), s->io, MIN(s->iolen, PAGE_SIZE - off));
         if (off + s->iolen > PAGE_SIZE) {
             page = PAGE(s->addr);
-            memcpy(s->storage + (page << OOB_SHIFT), s->io + PAGE_SIZE - off,
+            mem_and(s->storage + (page << OOB_SHIFT), s->io + PAGE_SIZE - off,
                             MIN(OOB_SIZE, off + s->iolen - PAGE_SIZE));
         }
 
@@ -624,7 +633,7 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
             return;
         }
 
-        memcpy(iobuf + soff, s->io, s->iolen);
+        mem_and(iobuf + soff, s->io, s->iolen);
 
         if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1)
             printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
commit d72245fbcf3391bfb61ec447dc1888919b3d148b
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Fri Jul 29 16:35:22 2011 +0100

    hw/nand: Support multiple reads following READ STATUS
    
    After receiving READ STATUS command all subsequent IO reads should return
    the status register value until another command is issued.
    
    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>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/nand.c b/hw/nand.c
index 4d1dff1..1eefe28 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -496,9 +496,14 @@ uint32_t nand_getio(NANDFlashState *s)
     for (offset = s->buswidth; offset--;) {
         x |= s->ioaddr[offset] << (offset << 3);
     }
-    s->addr   += s->buswidth;
-    s->ioaddr += s->buswidth;
-    s->iolen  -= s->buswidth;
+    /* after receiving READ STATUS command all subsequent reads will
+     * return the status register value until another command is issued
+     */
+    if (s->cmd != NAND_CMD_READSTATUS) {
+        s->addr   += s->buswidth;
+        s->ioaddr += s->buswidth;
+        s->iolen  -= s->buswidth;
+    }
     return x;
 }
 
commit 48197dfa6a26fa1807f19f510a2e840bb3885680
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Fri Jul 29 16:35:21 2011 +0100

    hw/nand: Support devices wider than 8 bits
    
    Support NAND devices which are wider than 8 bits.
    
    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>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/flash.h b/hw/flash.h
index a992bb8..132ad29 100644
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -24,8 +24,9 @@ void nand_done(NANDFlashState *s);
 void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
                   uint8_t ce, uint8_t wp, uint8_t gnd);
 void nand_getpins(NANDFlashState *s, int *rb);
-void nand_setio(NANDFlashState *s, uint8_t value);
-uint8_t nand_getio(NANDFlashState *s);
+void nand_setio(NANDFlashState *s, uint32_t value);
+uint32_t nand_getio(NANDFlashState *s);
+uint32_t nand_getbuswidth(NANDFlashState *s);
 
 #define NAND_MFR_TOSHIBA	0x98
 #define NAND_MFR_SAMSUNG	0xec
diff --git a/hw/nand.c b/hw/nand.c
index f5f204a..4d1dff1 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -49,6 +49,7 @@
 
 struct NANDFlashState {
     uint8_t manf_id, chip_id;
+    uint8_t buswidth; /* in BYTES */
     int size, pages;
     int page_shift, oob_shift, erase_shift, addr_shift;
     uint8_t *storage;
@@ -215,6 +216,14 @@ static void nand_reset(NANDFlashState *s)
     s->status &= NAND_IOSTATUS_UNPROTCT;
 }
 
+static inline void nand_pushio_byte(NANDFlashState *s, uint8_t value)
+{
+    s->ioaddr[s->iolen++] = value;
+    for (value = s->buswidth; --value;) {
+        s->ioaddr[s->iolen++] = 0;
+    }
+}
+
 static void nand_command(NANDFlashState *s)
 {
     unsigned int offset;
@@ -224,15 +233,19 @@ static void nand_command(NANDFlashState *s)
         break;
 
     case NAND_CMD_READID:
-        s->io[0] = s->manf_id;
-        s->io[1] = s->chip_id;
-        s->io[2] = 'Q';		/* Don't-care byte (often 0xa5) */
-        if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP)
-            s->io[3] = 0x15;	/* Page Size, Block Size, Spare Size.. */
-        else
-            s->io[3] = 0xc0;	/* Multi-plane */
         s->ioaddr = s->io;
-        s->iolen = 4;
+        s->iolen = 0;
+        nand_pushio_byte(s, s->manf_id);
+        nand_pushio_byte(s, s->chip_id);
+        nand_pushio_byte(s, 'Q'); /* Don't-care byte (often 0xa5) */
+        if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
+            /* Page Size, Block Size, Spare Size; bit 6 indicates
+             * 8 vs 16 bit width NAND.
+             */
+            nand_pushio_byte(s, (s->buswidth == 2) ? 0x55 : 0x15);
+        } else {
+            nand_pushio_byte(s, 0xc0); /* Multi-plane */
+        }
         break;
 
     case NAND_CMD_RANDOMREAD2:
@@ -277,9 +290,9 @@ static void nand_command(NANDFlashState *s)
         break;
 
     case NAND_CMD_READSTATUS:
-        s->io[0] = s->status;
         s->ioaddr = s->io;
-        s->iolen = 1;
+        s->iolen = 0;
+        nand_pushio_byte(s, s->status);
         break;
 
     default:
@@ -357,8 +370,10 @@ void nand_getpins(NANDFlashState *s, int *rb)
     *rb = 1;
 }
 
-void nand_setio(NANDFlashState *s, uint8_t value)
+void nand_setio(NANDFlashState *s, uint32_t value)
 {
+    int i;
+
     if (!s->ce && s->cle) {
         if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
             if (s->cmd == NAND_CMD_READ0 && value == NAND_CMD_LPREAD2)
@@ -404,36 +419,64 @@ void nand_setio(NANDFlashState *s, uint8_t value)
         s->addr = (s->addr & mask) | v;
         s->addrlen ++;
 
-        if (s->addrlen == 1 && s->cmd == NAND_CMD_READID)
-            nand_command(s);
-
-        if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
-                s->addrlen == 3 && (
-                    s->cmd == NAND_CMD_READ0 ||
-                    s->cmd == NAND_CMD_PAGEPROGRAM1))
-            nand_command(s);
-        if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
-               s->addrlen == 4 && (
-                    s->cmd == NAND_CMD_READ0 ||
-                    s->cmd == NAND_CMD_PAGEPROGRAM1))
-            nand_command(s);
+        switch (s->addrlen) {
+        case 1:
+            if (s->cmd == NAND_CMD_READID) {
+                nand_command(s);
+            }
+            break;
+        case 2: /* fix cache address as a byte address */
+            s->addr <<= (s->buswidth - 1);
+            break;
+        case 3:
+            if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
+                    (s->cmd == NAND_CMD_READ0 ||
+                     s->cmd == NAND_CMD_PAGEPROGRAM1)) {
+                nand_command(s);
+            }
+            break;
+        case 4:
+            if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
+                    nand_flash_ids[s->chip_id].size < 256 && /* 1Gb or less */
+                    (s->cmd == NAND_CMD_READ0 ||
+                     s->cmd == NAND_CMD_PAGEPROGRAM1)) {
+                nand_command(s);
+            }
+            break;
+        case 5:
+            if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
+                    nand_flash_ids[s->chip_id].size >= 256 && /* 2Gb or more */
+                    (s->cmd == NAND_CMD_READ0 ||
+                     s->cmd == NAND_CMD_PAGEPROGRAM1)) {
+                nand_command(s);
+            }
+            break;
+        default:
+            break;
+        }
     }
 
     if (!s->cle && !s->ale && s->cmd == NAND_CMD_PAGEPROGRAM1) {
-        if (s->iolen < (1 << s->page_shift) + (1 << s->oob_shift))
-            s->io[s->iolen ++] = value;
+        if (s->iolen < (1 << s->page_shift) + (1 << s->oob_shift)) {
+            for (i = s->buswidth; i--; value >>= 8) {
+                s->io[s->iolen ++] = (uint8_t) (value & 0xff);
+            }
+        }
     } else if (!s->cle && !s->ale && s->cmd == NAND_CMD_COPYBACKPRG1) {
         if ((s->addr & ((1 << s->addr_shift) - 1)) <
                 (1 << s->page_shift) + (1 << s->oob_shift)) {
-            s->io[s->iolen + (s->addr & ((1 << s->addr_shift) - 1))] = value;
-            s->addr ++;
+            for (i = s->buswidth; i--; s->addr++, value >>= 8) {
+                s->io[s->iolen + (s->addr & ((1 << s->addr_shift) - 1))] =
+                    (uint8_t) (value & 0xff);
+            }
         }
     }
 }
 
-uint8_t nand_getio(NANDFlashState *s)
+uint32_t nand_getio(NANDFlashState *s)
 {
     int offset;
+    uint32_t x = 0;
 
     /* Allow sequential reading */
     if (!s->iolen && s->cmd == NAND_CMD_READ0) {
@@ -450,9 +493,18 @@ uint8_t nand_getio(NANDFlashState *s)
     if (s->ce || s->iolen <= 0)
         return 0;
 
-    s->iolen --;
-    s->addr++;
-    return *(s->ioaddr ++);
+    for (offset = s->buswidth; offset--;) {
+        x |= s->ioaddr[offset] << (offset << 3);
+    }
+    s->addr   += s->buswidth;
+    s->ioaddr += s->buswidth;
+    s->iolen  -= s->buswidth;
+    return x;
+}
+
+uint32_t nand_getbuswidth(NANDFlashState *s)
+{
+    return s->buswidth << 3;
 }
 
 NANDFlashState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id)
@@ -468,6 +520,7 @@ NANDFlashState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id)
     s->bdrv = bdrv;
     s->manf_id = manf_id;
     s->chip_id = chip_id;
+    s->buswidth = nand_flash_ids[s->chip_id].width >> 3;
     s->size = nand_flash_ids[s->chip_id].size << 20;
     if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
         s->page_shift = 11;
commit ac2466cdc625d0cf9e7a885b7901084ac59d507f
Author: Andrzej Zaborowski <andrew.zaborowski at intel.com>
Date:   Sat Jul 30 06:01:37 2011 +0200

    nand: Bump vmstate version after changing structure.
    
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/nand.c b/hw/nand.c
index 764356a..f5f204a 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -308,9 +308,9 @@ static int nand_post_load(void *opaque, int version_id)
 
 static const VMStateDescription vmstate_nand = {
     .name = "nand",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
     .pre_save = nand_pre_save,
     .post_load = nand_post_load,
     .fields      = (VMStateField[]) {
commit d5f2fd586f1cc4651f8b03336b34c28dceab43bb
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Fri Jul 29 16:35:20 2011 +0100

    hw/nand: Support large NAND devices
    
    Add support for NAND devices of over 1Gb.
    
    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>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/nand.c b/hw/nand.c
index d6204d9..764356a 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -6,6 +6,10 @@
  * Copyright (c) 2006 Openedhand Ltd.
  * Written by Andrzej Zaborowski <balrog at zabor.org>
  *
+ * Support for additional features based on "MT29F2G16ABCWP 2Gx16"
+ * datasheet from Micron Technology and "NAND02G-B2C" datasheet
+ * from ST Microelectronics.
+ *
  * This code is licensed under the GNU GPL v2.
  */
 
@@ -57,14 +61,15 @@ struct NANDFlashState {
     uint8_t *ioaddr;
     int iolen;
 
-    uint32_t cmd, addr;
+    uint32_t cmd;
+    uint64_t addr;
     int addrlen;
     int status;
     int offset;
 
     void (*blk_write)(NANDFlashState *s);
     void (*blk_erase)(NANDFlashState *s);
-    void (*blk_load)(NANDFlashState *s, uint32_t addr, int offset);
+    void (*blk_load)(NANDFlashState *s, uint64_t addr, int offset);
 
     uint32_t ioaddr_vmstate;
 };
@@ -318,7 +323,7 @@ static const VMStateDescription vmstate_nand = {
         VMSTATE_UINT32(ioaddr_vmstate, NANDFlashState),
         VMSTATE_INT32(iolen, NANDFlashState),
         VMSTATE_UINT32(cmd, NANDFlashState),
-        VMSTATE_UINT32(addr, NANDFlashState),
+        VMSTATE_UINT64(addr, NANDFlashState),
         VMSTATE_INT32(addrlen, NANDFlashState),
         VMSTATE_INT32(status, NANDFlashState),
         VMSTATE_INT32(offset, NANDFlashState),
@@ -432,7 +437,7 @@ uint8_t nand_getio(NANDFlashState *s)
 
     /* Allow sequential reading */
     if (!s->iolen && s->cmd == NAND_CMD_READ0) {
-        offset = (s->addr & ((1 << s->addr_shift) - 1)) + s->offset;
+        offset = (int) (s->addr & ((1 << s->addr_shift) - 1)) + s->offset;
         s->offset = 0;
 
         s->blk_load(s, s->addr, offset);
@@ -526,7 +531,7 @@ void nand_done(NANDFlashState *s)
 /* Program a single page */
 static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
 {
-    uint32_t off, page, sector, soff;
+    uint64_t off, page, sector, soff;
     uint8_t iobuf[(PAGE_SECTORS + 2) * 0x200];
     if (PAGE(s->addr) >= s->pages)
         return;
@@ -539,7 +544,7 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
         off = (s->addr & PAGE_MASK) + s->offset;
         soff = SECTOR_OFFSET(s->addr);
         if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1) {
-            printf("%s: read error in sector %i\n", __FUNCTION__, sector);
+            printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
             return;
         }
 
@@ -551,20 +556,20 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
         }
 
         if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1)
-            printf("%s: write error in sector %i\n", __FUNCTION__, sector);
+            printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
     } else {
         off = PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset;
         sector = off >> 9;
         soff = off & 0x1ff;
         if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1) {
-            printf("%s: read error in sector %i\n", __FUNCTION__, sector);
+            printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
             return;
         }
 
         memcpy(iobuf + soff, s->io, s->iolen);
 
         if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1)
-            printf("%s: write error in sector %i\n", __FUNCTION__, sector);
+            printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
     }
     s->offset = 0;
 }
@@ -572,7 +577,7 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
 /* Erase a single block */
 static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s)
 {
-    uint32_t i, page, addr;
+    uint64_t i, page, addr;
     uint8_t iobuf[0x200] = { [0 ... 0x1ff] = 0xff, };
     addr = s->addr & ~((1 << (ADDR_SHIFT + s->erase_shift)) - 1);
 
@@ -589,34 +594,35 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s)
         page = SECTOR(addr + (ADDR_SHIFT + s->erase_shift));
         for (; i < page; i ++)
             if (bdrv_write(s->bdrv, i, iobuf, 1) == -1)
-                printf("%s: write error in sector %i\n", __FUNCTION__, i);
+                printf("%s: write error in sector %" PRIu64 "\n", __func__, i);
     } else {
         addr = PAGE_START(addr);
         page = addr >> 9;
         if (bdrv_read(s->bdrv, page, iobuf, 1) == -1)
-            printf("%s: read error in sector %i\n", __FUNCTION__, page);
+            printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
         memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1);
         if (bdrv_write(s->bdrv, page, iobuf, 1) == -1)
-            printf("%s: write error in sector %i\n", __FUNCTION__, page);
+            printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
 
         memset(iobuf, 0xff, 0x200);
         i = (addr & ~0x1ff) + 0x200;
         for (addr += ((PAGE_SIZE + OOB_SIZE) << s->erase_shift) - 0x200;
                         i < addr; i += 0x200)
             if (bdrv_write(s->bdrv, i >> 9, iobuf, 1) == -1)
-                printf("%s: write error in sector %i\n", __FUNCTION__, i >> 9);
+                printf("%s: write error in sector %" PRIu64 "\n",
+                       __func__, i >> 9);
 
         page = i >> 9;
         if (bdrv_read(s->bdrv, page, iobuf, 1) == -1)
-            printf("%s: read error in sector %i\n", __FUNCTION__, page);
+            printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
         memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1);
         if (bdrv_write(s->bdrv, page, iobuf, 1) == -1)
-            printf("%s: write error in sector %i\n", __FUNCTION__, page);
+            printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
     }
 }
 
 static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
-                uint32_t addr, int offset)
+                uint64_t addr, int offset)
 {
     if (PAGE(addr) >= s->pages)
         return;
@@ -624,8 +630,8 @@ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
     if (s->bdrv) {
         if (s->mem_oob) {
             if (bdrv_read(s->bdrv, SECTOR(addr), s->io, PAGE_SECTORS) == -1)
-                printf("%s: read error in sector %i\n",
-                                __FUNCTION__, SECTOR(addr));
+                printf("%s: read error in sector %" PRIu64 "\n",
+                                __func__, SECTOR(addr));
             memcpy(s->io + SECTOR_OFFSET(s->addr) + PAGE_SIZE,
                             s->storage + (PAGE(s->addr) << OOB_SHIFT),
                             OOB_SIZE);
@@ -633,8 +639,8 @@ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
         } else {
             if (bdrv_read(s->bdrv, PAGE_START(addr) >> 9,
                                     s->io, (PAGE_SECTORS + 2)) == -1)
-                printf("%s: read error in sector %i\n",
-                                __FUNCTION__, PAGE_START(addr) >> 9);
+                printf("%s: read error in sector %" PRIu64 "\n",
+                                __func__, PAGE_START(addr) >> 9);
             s->ioaddr = s->io + (PAGE_START(addr) & 0x1ff) + offset;
         }
     } else {
commit 522f253ca8c731aafc8e53087a18f6015c4e776e
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jul 29 16:35:19 2011 +0100

    hw/nand: Pass block device state to init function
    
    Pass the BlockDeviceState to the nand_init() function rather
    than having it look it up via drive_get() itself.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 0e2135a..de1f5a5 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -30,6 +30,7 @@
 #include "loader.h"
 #include "elf.h"
 #include "cris-boot.h"
+#include "blockdev.h"
 
 #define D(x)
 #define DNAND(x)
@@ -251,6 +252,7 @@ void axisdev88_init (ram_addr_t ram_size,
     CPUState *env;
     DeviceState *dev;
     SysBusDevice *s;
+    DriveInfo *nand;
     qemu_irq irq[30], nmi[2], *cpu_irq;
     void *etraxfs_dmac;
     struct etraxfs_dma_client *eth[2] = {NULL, NULL};
@@ -278,7 +280,9 @@ void axisdev88_init (ram_addr_t ram_size,
 
 
       /* Attach a NAND flash to CS1.  */
-    nand_state.nand = nand_init(NAND_MFR_STMICRO, 0x39);
+    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);
diff --git a/hw/flash.h b/hw/flash.h
index c22e1a9..a992bb8 100644
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -19,7 +19,7 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
 
 /* nand.c */
 typedef struct NANDFlashState NANDFlashState;
-NANDFlashState *nand_init(int manf_id, int chip_id);
+NANDFlashState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id);
 void nand_done(NANDFlashState *s);
 void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
                   uint8_t ce, uint8_t wp, uint8_t gnd);
diff --git a/hw/nand.c b/hw/nand.c
index 37e51d7..d6204d9 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -14,7 +14,6 @@
 # include "hw.h"
 # include "flash.h"
 # include "blockdev.h"
-/* FIXME: Pass block device as an argument.  */
 
 # define NAND_CMD_READ0		0x00
 # define NAND_CMD_READ1		0x01
@@ -451,20 +450,17 @@ uint8_t nand_getio(NANDFlashState *s)
     return *(s->ioaddr ++);
 }
 
-NANDFlashState *nand_init(int manf_id, int chip_id)
+NANDFlashState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id)
 {
     int pagesize;
     NANDFlashState *s;
-    DriveInfo *dinfo;
 
     if (nand_flash_ids[chip_id].size == 0) {
         hw_error("%s: Unsupported NAND chip ID.\n", __FUNCTION__);
     }
 
     s = (NANDFlashState *) qemu_mallocz(sizeof(NANDFlashState));
-    dinfo = drive_get(IF_MTD, 0, 0);
-    if (dinfo)
-        s->bdrv = dinfo->bdrv;
+    s->bdrv = bdrv;
     s->manf_id = manf_id;
     s->chip_id = chip_id;
     s->size = nand_flash_ids[s->chip_id].size << 20;
diff --git a/hw/spitz.c b/hw/spitz.c
index 006f7a9..78e9c34 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -169,11 +169,13 @@ static void sl_flash_register(PXA2xxState *cpu, int size)
 static int sl_nand_init(SysBusDevice *dev) {
     int iomemtype;
     SLNANDState *s;
+    DriveInfo *nand;
 
     s = FROM_SYSBUS(SLNANDState, dev);
 
     s->ctl = 0;
-    s->nand = nand_init(s->manf_id, s->chip_id);
+    nand = drive_get(IF_MTD, 0, 0);
+    s->nand = nand_init(nand ? nand->bdrv : NULL, s->manf_id, s->chip_id);
 
     iomemtype = cpu_register_io_memory(sl_readfn,
                     sl_writefn, s, DEVICE_NATIVE_ENDIAN);
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index ed49e94..4de0819 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -12,6 +12,7 @@
 #include "flash.h"
 #include "console.h"
 #include "pixel_ops.h"
+#include "blockdev.h"
 
 #define IRQ_TC6393_NAND		0
 #define IRQ_TC6393_MMC		1
@@ -566,6 +567,7 @@ TC6393xbState *tc6393xb_init(uint32_t base, qemu_irq irq)
 {
     int iomemtype;
     TC6393xbState *s;
+    DriveInfo *nand;
     CPUReadMemoryFunc * const tc6393xb_readfn[] = {
         tc6393xb_readb,
         tc6393xb_readw,
@@ -586,7 +588,8 @@ TC6393xbState *tc6393xb_init(uint32_t base, qemu_irq irq)
 
     s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS);
 
-    s->flash = nand_init(NAND_MFR_TOSHIBA, 0x76);
+    nand = drive_get(IF_MTD, 0, 0);
+    s->flash = nand_init(nand ? nand->bdrv : NULL, NAND_MFR_TOSHIBA, 0x76);
 
     iomemtype = cpu_register_io_memory(tc6393xb_readfn,
                     tc6393xb_writefn, s, DEVICE_NATIVE_ENDIAN);
commit c4f05c8cf715fa613e1985421080e62a7b169284
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jul 29 16:35:18 2011 +0100

    lm832x: Take DeviceState pointer in lm832x_key_event()
    
    Since lm832x has been qdev'ified, its users will generally
    have a DeviceState pointer rather than an i2c_slave pointer,
    so adjust lm832x_key_event's prototype to suit.
    
    This allows the n810 (its only user) to actually pass a correct
    pointer to it rather than NULL. The effect is that we no longer
    segfault when a key is pressed.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/i2c.h b/hw/i2c.h
index 5514402..9381d01 100644
--- a/hw/i2c.h
+++ b/hw/i2c.h
@@ -72,6 +72,6 @@ void wm8750_set_bclk_in(void *opaque, int new_hz);
 void tmp105_set(i2c_slave *i2c, int temp);
 
 /* lm832x.c */
-void lm832x_key_event(i2c_slave *i2c, int key, int state);
+void lm832x_key_event(DeviceState *dev, int key, int state);
 
 #endif
diff --git a/hw/lm832x.c b/hw/lm832x.c
index 590a4cc..992ce49 100644
--- a/hw/lm832x.c
+++ b/hw/lm832x.c
@@ -474,9 +474,9 @@ static int lm8323_init(i2c_slave *i2c)
     return 0;
 }
 
-void lm832x_key_event(struct i2c_slave *i2c, int key, int state)
+void lm832x_key_event(DeviceState *dev, int key, int state)
 {
-    LM823KbdState *s = (LM823KbdState *) i2c;
+    LM823KbdState *s = FROM_I2C_SLAVE(LM823KbdState, I2C_SLAVE_FROM_QDEV(dev));
 
     if ((s->status & INT_ERROR) && (s->error & ERR_FIFOOVR))
         return;
diff --git a/hw/nseries.c b/hw/nseries.c
index d9a5428..d12ed46 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -45,7 +45,7 @@ struct n800_s {
     i2c_bus *i2c;
 
     int keymap[0x80];
-    i2c_slave *kbd;
+    DeviceState *kbd;
 
     TUSBState *usb;
     void *retu;
@@ -362,7 +362,6 @@ static int n810_keys[0x80] = {
 static void n810_kbd_setup(struct n800_s *s)
 {
     qemu_irq kbd_irq = qdev_get_gpio_in(s->cpu->gpio, N810_KEYBOARD_GPIO);
-    DeviceState *dev;
     int i;
 
     for (i = 0; i < 0x80; i ++)
@@ -375,8 +374,8 @@ static void n810_kbd_setup(struct n800_s *s)
 
     /* Attach the LM8322 keyboard to the I2C bus,
      * should happen in n8x0_i2c_setup and s->kbd be initialised here.  */
-    dev = i2c_create_slave(s->i2c, "lm8323", N810_LM8323_ADDR);
-    qdev_connect_gpio_out(dev, 0, kbd_irq);
+    s->kbd = i2c_create_slave(s->i2c, "lm8323", N810_LM8323_ADDR);
+    qdev_connect_gpio_out(s->kbd, 0, kbd_irq);
 }
 
 /* LCD MIPI DBI-C controller (URAL) */
commit 77831c204fda6303408aee1853c36768d853b413
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Fri Jul 29 16:35:17 2011 +0100

    hw/omap_gpio.c: Convert to qdev
    
    Convert the OMAP GPIO module to qdev.
    
    Signed-off-by: Juha Riihimäki <juha.riihimaki at nokia.com>
    [Riku Voipio: Fixes and restructuring patchset]
    Signed-off-by: Riku Voipio <riku.voipio at iki.fi>
    [Peter Maydell: More fixes and cleanups for upstream submission]
    Signed-off-by:  Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/nseries.c b/hw/nseries.c
index 2f84f53..d9a5428 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -134,9 +134,9 @@ static void n800_mmc_cs_cb(void *opaque, int line, int level)
 static void n8x0_gpio_setup(struct n800_s *s)
 {
     qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->cpu->mmc, 1);
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_MMC_CS_GPIO, mmc_cs[0]);
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_MMC_CS_GPIO, mmc_cs[0]);
 
-    qemu_irq_lower(omap2_gpio_in_get(s->cpu->gpif, N800_BAT_COVER_GPIO)[0]);
+    qemu_irq_lower(qdev_get_gpio_in(s->cpu->gpio, N800_BAT_COVER_GPIO));
 }
 
 #define MAEMO_CAL_HEADER(...)				\
@@ -168,8 +168,8 @@ static void n8x0_nand_setup(struct n800_s *s)
     omap_gpmc_attach(s->cpu->gpmc, N8X0_ONENAND_CS, 0, onenand_base_update,
                     onenand_base_unmap,
                     (s->nand = onenand_init(0xec4800, 1,
-                                            omap2_gpio_in_get(s->cpu->gpif,
-                                                    N8X0_ONENAND_GPIO)[0])));
+                                            qdev_get_gpio_in(s->cpu->gpio,
+                                                    N8X0_ONENAND_GPIO))));
     otp_region = onenand_raw_otp(s->nand);
 
     memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac));
@@ -180,7 +180,7 @@ static void n8x0_nand_setup(struct n800_s *s)
 static void n8x0_i2c_setup(struct n800_s *s)
 {
     DeviceState *dev;
-    qemu_irq tmp_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TMP105_GPIO)[0];
+    qemu_irq tmp_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TMP105_GPIO);
 
     /* Attach the CPU on one end of our I2C bus.  */
     s->i2c = omap_i2c_bus(s->cpu->i2c[0]);
@@ -249,8 +249,8 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
     /* XXX: are the three pins inverted inside the chip between the
      * tsc and the cpu (N4111)?  */
     qemu_irq penirq = NULL;	/* NC */
-    qemu_irq kbirq = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_KP_IRQ_GPIO)[0];
-    qemu_irq dav = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_TS_GPIO)[0];
+    qemu_irq kbirq = qdev_get_gpio_in(s->cpu->gpio, N800_TSC_KP_IRQ_GPIO);
+    qemu_irq dav = qdev_get_gpio_in(s->cpu->gpio, N800_TSC_TS_GPIO);
 
     s->ts.chip = tsc2301_init(penirq, kbirq, dav);
     s->ts.opaque = s->ts.chip->opaque;
@@ -269,7 +269,7 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
 
 static void n810_tsc_setup(struct n800_s *s)
 {
-    qemu_irq pintdav = omap2_gpio_in_get(s->cpu->gpif, N810_TSC_TS_GPIO)[0];
+    qemu_irq pintdav = qdev_get_gpio_in(s->cpu->gpio, N810_TSC_TS_GPIO);
 
     s->ts.opaque = tsc2005_init(pintdav);
     s->ts.txrx = tsc2005_txrx;
@@ -361,7 +361,7 @@ static int n810_keys[0x80] = {
 
 static void n810_kbd_setup(struct n800_s *s)
 {
-    qemu_irq kbd_irq = omap2_gpio_in_get(s->cpu->gpif, N810_KEYBOARD_GPIO)[0];
+    qemu_irq kbd_irq = qdev_get_gpio_in(s->cpu->gpio, N810_KEYBOARD_GPIO);
     DeviceState *dev;
     int i;
 
@@ -726,15 +726,15 @@ static void n8x0_dss_setup(struct n800_s *s)
 
 static void n8x0_cbus_setup(struct n800_s *s)
 {
-    qemu_irq dat_out = omap2_gpio_in_get(s->cpu->gpif, N8X0_CBUS_DAT_GPIO)[0];
-    qemu_irq retu_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_RETU_GPIO)[0];
-    qemu_irq tahvo_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TAHVO_GPIO)[0];
+    qemu_irq dat_out = qdev_get_gpio_in(s->cpu->gpio, N8X0_CBUS_DAT_GPIO);
+    qemu_irq retu_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_RETU_GPIO);
+    qemu_irq tahvo_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TAHVO_GPIO);
 
     CBus *cbus = cbus_init(dat_out);
 
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_CLK_GPIO, cbus->clk);
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_DAT_GPIO, cbus->dat);
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_SEL_GPIO, cbus->sel);
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_CLK_GPIO, cbus->clk);
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_DAT_GPIO, cbus->dat);
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_SEL_GPIO, cbus->sel);
 
     cbus_attach(cbus, s->retu = retu_init(retu_irq, 1));
     cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1));
@@ -743,12 +743,11 @@ static void n8x0_cbus_setup(struct n800_s *s)
 static void n8x0_uart_setup(struct n800_s *s)
 {
     CharDriverState *radio = uart_hci_init(
-                    omap2_gpio_in_get(s->cpu->gpif,
-                            N8X0_BT_HOST_WKUP_GPIO)[0]);
+                    qdev_get_gpio_in(s->cpu->gpio, N8X0_BT_HOST_WKUP_GPIO));
 
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_BT_RESET_GPIO,
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_BT_RESET_GPIO,
                     csrhci_pins_get(radio)[csrhci_pin_reset]);
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_BT_WKUP_GPIO,
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_BT_WKUP_GPIO,
                     csrhci_pins_get(radio)[csrhci_pin_wakeup]);
 
     omap_uart_attach(s->cpu->uart[BT_UART], radio);
@@ -763,7 +762,7 @@ static void n8x0_usb_power_cb(void *opaque, int line, int level)
 
 static void n8x0_usb_setup(struct n800_s *s)
 {
-    qemu_irq tusb_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TUSB_INT_GPIO)[0];
+    qemu_irq tusb_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TUSB_INT_GPIO);
     qemu_irq tusb_pwr = qemu_allocate_irqs(n8x0_usb_power_cb, s, 1)[0];
     TUSBState *tusb = tusb6010_init(tusb_irq);
 
@@ -774,7 +773,7 @@ static void n8x0_usb_setup(struct n800_s *s)
                     tusb6010_sync_io(tusb), NULL, NULL, tusb);
 
     s->usb = tusb;
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_TUSB_ENABLE_GPIO, tusb_pwr);
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_TUSB_ENABLE_GPIO, tusb_pwr);
 }
 
 /* Setup done before the main bootloader starts by some early setup code
@@ -1020,7 +1019,7 @@ static void n8x0_boot_init(void *opaque)
 
     /* If the machine has a slided keyboard, open it */
     if (s->kbd)
-        qemu_irq_raise(omap2_gpio_in_get(s->cpu->gpif, N810_SLIDE_GPIO)[0]);
+        qemu_irq_raise(qdev_get_gpio_in(s->cpu->gpio, N810_SLIDE_GPIO));
 }
 
 #define OMAP_TAG_NOKIA_BT	0x4e01
diff --git a/hw/omap.h b/hw/omap.h
index 00a0ea9..a064353 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -683,22 +683,6 @@ 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);
 
-/* omap1 gpio module interface */
-struct omap_gpio_s;
-struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
-                qemu_irq irq, omap_clk clk);
-void omap_gpio_reset(struct omap_gpio_s *s);
-qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s);
-void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler);
-
-/* omap2 gpio interface */
-struct omap_gpif_s;
-struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
-                qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules);
-void omap_gpif_reset(struct omap_gpif_s *s);
-qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start);
-void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler);
-
 struct uWireSlave {
     uint16_t (*receive)(void *opaque);
     void (*send)(void *opaque, uint16_t data);
@@ -852,7 +836,7 @@ struct omap_mpu_state_s {
     /* MPUI-TIPB peripherals */
     struct omap_uart_s *uart[3];
 
-    struct omap_gpio_s *gpio;
+    DeviceState *gpio;
 
     struct omap_mcbsp_s *mcbsp1;
     struct omap_mcbsp_s *mcbsp3;
@@ -950,8 +934,6 @@ struct omap_mpu_state_s {
     struct omap_gpmc_s *gpmc;
     struct omap_sysctl_s *sysc;
 
-    struct omap_gpif_s *gpif;
-
     struct omap_mcspi_s *mcspi[2];
 
     struct omap_dss_s *dss;
diff --git a/hw/omap1.c b/hw/omap1.c
index 364c26f..400de47 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -27,6 +27,7 @@
 #include "pc.h"
 #include "blockdev.h"
 #include "range.h"
+#include "sysbus.h"
 
 /* Should signal the TCMI/GPMC */
 uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr)
@@ -3585,7 +3586,6 @@ static void omap1_mpu_reset(void *opaque)
     omap_uart_reset(mpu->uart[2]);
     omap_mmc_reset(mpu->mmc);
     omap_mpuio_reset(mpu->mpuio);
-    omap_gpio_reset(mpu->gpio);
     omap_uwire_reset(mpu->microwire);
     omap_pwl_reset(mpu);
     omap_pwt_reset(mpu);
@@ -3845,8 +3845,12 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
                     s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO],
                     s->wakeup, omap_findclk(s, "clk32-kHz"));
 
-    s->gpio = omap_gpio_init(0xfffce000, s->irq[0][OMAP_INT_GPIO_BANK1],
-                    omap_findclk(s, "arm_gpio_ck"));
+    s->gpio = qdev_create(NULL, "omap-gpio");
+    qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
+    qdev_init_nofail(s->gpio);
+    sysbus_connect_irq(sysbus_from_qdev(s->gpio), 0,
+                    s->irq[0][OMAP_INT_GPIO_BANK1]);
+    sysbus_mmio_map(sysbus_from_qdev(s->gpio), 0, 0xfffce000);
 
     s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX],
                     s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
diff --git a/hw/omap2.c b/hw/omap2.c
index 0f13272..c9b3540 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -27,6 +27,7 @@
 #include "qemu-char.h"
 #include "flash.h"
 #include "soc_dma.h"
+#include "sysbus.h"
 #include "audio/audio.h"
 
 /* Enhanced Audio Controller (CODEC only) */
@@ -2203,7 +2204,6 @@ static void omap2_mpu_reset(void *opaque)
     omap_uart_reset(mpu->uart[1]);
     omap_uart_reset(mpu->uart[2]);
     omap_mmc_reset(mpu->mmc);
-    omap_gpif_reset(mpu->gpif);
     omap_mcspi_reset(mpu->mcspi[0]);
     omap_mcspi_reset(mpu->mcspi[1]);
     omap_i2c_reset(mpu->i2c[0]);
@@ -2232,9 +2232,10 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
     ram_addr_t sram_base, q2_base;
     qemu_irq *cpu_irq;
     qemu_irq dma_irqs[4];
-    omap_clk gpio_clks[4];
     DriveInfo *dinfo;
     int i;
+    SysBusDevice *busdev;
+    struct omap_target_agent_s *ta;
 
     /* Core */
     s->mpu_model = omap2420;
@@ -2377,13 +2378,28 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
                     omap_findclk(s, "i2c2.fclk"),
                     omap_findclk(s, "i2c2.iclk"));
 
-    gpio_clks[0] = omap_findclk(s, "gpio1_dbclk");
-    gpio_clks[1] = omap_findclk(s, "gpio2_dbclk");
-    gpio_clks[2] = omap_findclk(s, "gpio3_dbclk");
-    gpio_clks[3] = omap_findclk(s, "gpio4_dbclk");
-    s->gpif = omap2_gpio_init(omap_l4ta(s->l4, 3),
-                    &s->irq[0][OMAP_INT_24XX_GPIO_BANK1],
-                    gpio_clks, omap_findclk(s, "gpio_iclk"), 4);
+    s->gpio = qdev_create(NULL, "omap2-gpio");
+    qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
+    qdev_prop_set_ptr(s->gpio, "iclk", omap_findclk(s, "gpio_iclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk0", omap_findclk(s, "gpio1_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk1", omap_findclk(s, "gpio2_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk2", omap_findclk(s, "gpio3_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk3", omap_findclk(s, "gpio4_dbclk"));
+    if (s->mpu_model == omap2430) {
+        qdev_prop_set_ptr(s->gpio, "fclk4", omap_findclk(s, "gpio5_dbclk"));
+    }
+    qdev_init_nofail(s->gpio);
+    busdev = sysbus_from_qdev(s->gpio);
+    sysbus_connect_irq(busdev, 0, s->irq[0][OMAP_INT_24XX_GPIO_BANK1]);
+    sysbus_connect_irq(busdev, 3, s->irq[0][OMAP_INT_24XX_GPIO_BANK2]);
+    sysbus_connect_irq(busdev, 6, s->irq[0][OMAP_INT_24XX_GPIO_BANK3]);
+    sysbus_connect_irq(busdev, 9, s->irq[0][OMAP_INT_24XX_GPIO_BANK4]);
+    ta = omap_l4ta(s->l4, 3);
+    sysbus_mmio_map(busdev, 0, omap_l4_region_base(ta, 1));
+    sysbus_mmio_map(busdev, 1, omap_l4_region_base(ta, 0));
+    sysbus_mmio_map(busdev, 2, omap_l4_region_base(ta, 2));
+    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->gpmc = omap_gpmc_init(0x6800a000, s->irq[0][OMAP_INT_24XX_GPMC_IRQ]);
diff --git a/hw/omap_gpio.c b/hw/omap_gpio.c
index 478f7d9..c23964c 100644
--- a/hw/omap_gpio.c
+++ b/hw/omap_gpio.c
@@ -20,10 +20,10 @@
 
 #include "hw.h"
 #include "omap.h"
-/* General-Purpose I/O */
+#include "sysbus.h"
+
 struct omap_gpio_s {
     qemu_irq irq;
-    qemu_irq *in;
     qemu_irq handler[16];
 
     uint16_t inputs;
@@ -35,9 +35,17 @@ struct omap_gpio_s {
     uint16_t pins;
 };
 
+struct omap_gpif_s {
+    SysBusDevice busdev;
+    int mpu_model;
+    void *clk;
+    struct omap_gpio_s omap1;
+};
+
+/* General-Purpose I/O of OMAP1 */
 static void omap_gpio_set(void *opaque, int line, int level)
 {
-    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
+    struct omap_gpio_s *s = &((struct omap_gpif_s *) opaque)->omap1;
     uint16_t prev = s->inputs;
 
     if (level)
@@ -160,7 +168,7 @@ static CPUWriteMemoryFunc * const omap_gpio_writefn[] = {
     omap_badwidth_write16,
 };
 
-void omap_gpio_reset(struct omap_gpio_s *s)
+static void omap_gpio_reset(struct omap_gpio_s *s)
 {
     s->inputs = 0;
     s->outputs = ~0;
@@ -171,43 +179,12 @@ void omap_gpio_reset(struct omap_gpio_s *s)
     s->pins = ~0;
 }
 
-struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
-                qemu_irq irq, omap_clk clk)
-{
-    int iomemtype;
-    struct omap_gpio_s *s = (struct omap_gpio_s *)
-            qemu_mallocz(sizeof(struct omap_gpio_s));
-
-    s->irq = irq;
-    s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
-    omap_gpio_reset(s);
-
-    iomemtype = cpu_register_io_memory(omap_gpio_readfn,
-                    omap_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x1000, iomemtype);
-
-    return s;
-}
-
-qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
-{
-    return s->in;
-}
-
-void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
-{
-    if (line >= 16 || line < 0)
-        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
-    s->handler[line] = handler;
-}
-
-/* General-Purpose Interface of OMAP2 */
 struct omap2_gpio_s {
     qemu_irq irq[2];
     qemu_irq wkup;
-    qemu_irq *in;
-    qemu_irq handler[32];
+    qemu_irq *handler;
 
+    uint8_t revision;
     uint8_t config[2];
     uint32_t inputs;
     uint32_t outputs;
@@ -221,8 +198,21 @@ struct omap2_gpio_s {
     uint8_t delay;
 };
 
+struct omap2_gpif_s {
+    SysBusDevice busdev;
+    int mpu_model;
+    void *iclk;
+    void *fclk[6];
+    int modulecount;
+    struct omap2_gpio_s *modules;
+    qemu_irq *handler;
+    int autoidle;
+    int gpo;
+};
+
+/* General-Purpose Interface of OMAP2/3 */
 static inline void omap2_gpio_module_int_update(struct omap2_gpio_s *s,
-                int line)
+                                                int line)
 {
     qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
 }
@@ -269,10 +259,12 @@ static inline void omap2_gpio_module_int(struct omap2_gpio_s *s, int line)
     omap2_gpio_module_wake(s, line);
 }
 
-static void omap2_gpio_module_set(void *opaque, int line, int level)
+static void omap2_gpio_set(void *opaque, int line, int level)
 {
-    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
+    struct omap2_gpif_s *p = opaque;
+    struct omap2_gpio_s *s = &p->modules[line >> 5];
 
+    line &= 31;
     if (level) {
         if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))
             omap2_gpio_module_int(s, line);
@@ -308,7 +300,7 @@ static uint32_t omap2_gpio_module_read(void *opaque, target_phys_addr_t addr)
 
     switch (addr) {
     case 0x00:	/* GPIO_REVISION */
-        return 0x18;
+        return s->revision;
 
     case 0x10:	/* GPIO_SYSCONFIG */
         return s->config[0];
@@ -583,45 +575,28 @@ static CPUWriteMemoryFunc * const omap2_gpio_module_writefn[] = {
     omap2_gpio_module_write,
 };
 
-static void omap2_gpio_module_init(struct omap2_gpio_s *s,
-                struct omap_target_agent_s *ta, int region,
-                qemu_irq mpu, qemu_irq dsp, qemu_irq wkup,
-                omap_clk fclk, omap_clk iclk)
+static void omap_gpif_reset(DeviceState *dev)
 {
-    int iomemtype;
-
-    s->irq[0] = mpu;
-    s->irq[1] = dsp;
-    s->wkup = wkup;
-    s->in = qemu_allocate_irqs(omap2_gpio_module_set, s, 32);
-
-    iomemtype = l4_register_io_memory(omap2_gpio_module_readfn,
-                    omap2_gpio_module_writefn, s);
-    omap_l4_attach(ta, region, iomemtype);
+    struct omap_gpif_s *s = FROM_SYSBUS(struct omap_gpif_s,
+                    sysbus_from_qdev(dev));
+    omap_gpio_reset(&s->omap1);
 }
 
-struct omap_gpif_s {
-    struct omap2_gpio_s module[5];
-    int modules;
-
-    int autoidle;
-    int gpo;
-};
-
-void omap_gpif_reset(struct omap_gpif_s *s)
+static void omap2_gpif_reset(DeviceState *dev)
 {
     int i;
-
-    for (i = 0; i < s->modules; i ++)
-        omap2_gpio_module_reset(s->module + i);
-
+    struct omap2_gpif_s *s = FROM_SYSBUS(struct omap2_gpif_s,
+                    sysbus_from_qdev(dev));
+    for (i = 0; i < s->modulecount; i++) {
+        omap2_gpio_module_reset(&s->modules[i]);
+    }
     s->autoidle = 0;
     s->gpo = 0;
 }
 
-static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr)
+static uint32_t omap2_gpif_top_read(void *opaque, target_phys_addr_t addr)
 {
-    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
+    struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
 
     switch (addr) {
     case 0x00:	/* IPGENERICOCPSPL_REVISION */
@@ -647,10 +622,10 @@ static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
-static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
+static void omap2_gpif_top_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
-    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
+    struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
 
     switch (addr) {
     case 0x00:	/* IPGENERICOCPSPL_REVISION */
@@ -662,7 +637,7 @@ static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
 
     case 0x10:	/* IPGENERICOCPSPL_SYSCONFIG */
         if (value & (1 << 1))					/* SOFTRESET */
-            omap_gpif_reset(s);
+            omap2_gpif_reset(&s->busdev.qdev);
         s->autoidle = value & 1;
         break;
 
@@ -676,50 +651,119 @@ static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_gpif_top_readfn[] = {
-    omap_gpif_top_read,
-    omap_gpif_top_read,
-    omap_gpif_top_read,
+static CPUReadMemoryFunc * const omap2_gpif_top_readfn[] = {
+    omap2_gpif_top_read,
+    omap2_gpif_top_read,
+    omap2_gpif_top_read,
 };
 
-static CPUWriteMemoryFunc * const omap_gpif_top_writefn[] = {
-    omap_gpif_top_write,
-    omap_gpif_top_write,
-    omap_gpif_top_write,
+static CPUWriteMemoryFunc * const omap2_gpif_top_writefn[] = {
+    omap2_gpif_top_write,
+    omap2_gpif_top_write,
+    omap2_gpif_top_write,
 };
 
-struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
-                qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules)
+static int omap_gpio_init(SysBusDevice *dev)
 {
-    int iomemtype, i;
-    struct omap_gpif_s *s = (struct omap_gpif_s *)
-            qemu_mallocz(sizeof(struct omap_gpif_s));
-    int region[4] = { 0, 2, 4, 5 };
+    struct omap_gpif_s *s = FROM_SYSBUS(struct omap_gpif_s, dev);
+    if (!s->clk) {
+        hw_error("omap-gpio: clk not connected\n");
+    }
+    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));
+    return 0;
+}
 
-    s->modules = modules;
-    for (i = 0; i < modules; i ++)
-        omap2_gpio_module_init(s->module + i, ta, region[i],
-                              irq[i], NULL, NULL, fclk[i], iclk);
+static int omap2_gpio_init(SysBusDevice *dev)
+{
+    int i;
+    struct omap2_gpif_s *s = FROM_SYSBUS(struct omap2_gpif_s, dev);
+    if (!s->iclk) {
+        hw_error("omap2-gpio: iclk not connected\n");
+    }
+    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));
+    } else {
+        s->modulecount = 6;
+    }
+    s->modules = qemu_mallocz(s->modulecount * sizeof(struct omap2_gpio_s));
+    s->handler = qemu_mallocz(s->modulecount * 32 * sizeof(qemu_irq));
+    qdev_init_gpio_in(&dev->qdev, omap2_gpio_set, s->modulecount * 32);
+    qdev_init_gpio_out(&dev->qdev, s->handler, s->modulecount * 32);
+    for (i = 0; i < s->modulecount; i++) {
+        struct omap2_gpio_s *m = &s->modules[i];
+        if (!s->fclk[i]) {
+            hw_error("omap2-gpio: fclk%d not connected\n", i);
+        }
+        m->revision = (s->mpu_model < omap3430) ? 0x18 : 0x25;
+        m->handler = &s->handler[i * 32];
+        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));
+    }
+    return 0;
+}
 
-    omap_gpif_reset(s);
+/* Using qdev pointer properties for the clocks is not ideal.
+ * qdev should support a generic means of defining a 'port' with
+ * an arbitrary interface for connecting two devices. Then we
+ * could reframe the omap clock API in terms of clock ports,
+ * and get some type safety. For now the best qdev provides is
+ * passing an arbitrary pointer.
+ * (It's not possible to pass in the string which is the clock
+ * name, because this device does not have the necessary information
+ * (ie the struct omap_mpu_state_s*) to do the clockname to pointer
+ * translation.)
+ */
 
-    iomemtype = l4_register_io_memory(omap_gpif_top_readfn,
-                    omap_gpif_top_writefn, s);
-    omap_l4_attach(ta, 1, iomemtype);
+static SysBusDeviceInfo omap_gpio_info = {
+    .init = omap_gpio_init,
+    .qdev.name = "omap-gpio",
+    .qdev.size = sizeof(struct omap_gpif_s),
+    .qdev.reset = omap_gpif_reset,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_INT32("mpu_model", struct omap_gpif_s, mpu_model, 0),
+        DEFINE_PROP_PTR("clk", struct omap_gpif_s, clk),
+        DEFINE_PROP_END_OF_LIST()
+    }
+};
 
-    return s;
-}
+static SysBusDeviceInfo omap2_gpio_info = {
+    .init = omap2_gpio_init,
+    .qdev.name = "omap2-gpio",
+    .qdev.size = sizeof(struct omap2_gpif_s),
+    .qdev.reset = omap2_gpif_reset,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_INT32("mpu_model", struct omap2_gpif_s, mpu_model, 0),
+        DEFINE_PROP_PTR("iclk", struct omap2_gpif_s, iclk),
+        DEFINE_PROP_PTR("fclk0", struct omap2_gpif_s, fclk[0]),
+        DEFINE_PROP_PTR("fclk1", struct omap2_gpif_s, fclk[1]),
+        DEFINE_PROP_PTR("fclk2", struct omap2_gpif_s, fclk[2]),
+        DEFINE_PROP_PTR("fclk3", struct omap2_gpif_s, fclk[3]),
+        DEFINE_PROP_PTR("fclk4", struct omap2_gpif_s, fclk[4]),
+        DEFINE_PROP_PTR("fclk5", struct omap2_gpif_s, fclk[5]),
+        DEFINE_PROP_END_OF_LIST()
+    }
+};
 
-qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start)
+static void omap_gpio_register_device(void)
 {
-    if (start >= s->modules * 32 || start < 0)
-        hw_error("%s: No GPIO line %i\n", __FUNCTION__, start);
-    return s->module[start >> 5].in + (start & 31);
+    sysbus_register_withprop(&omap_gpio_info);
+    sysbus_register_withprop(&omap2_gpio_info);
 }
 
-void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler)
-{
-    if (line >= s->modules * 32 || line < 0)
-        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
-    s->module[line >> 5].handler[line & 31] = handler;
-}
+device_init(omap_gpio_register_device)
diff --git a/hw/palm.c b/hw/palm.c
index f22d777..4c67e75 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -94,7 +94,7 @@ static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
 {
     uWireSlave *tsc;
 
-    tsc = tsc2102_init(omap_gpio_in_get(cpu->gpio)[PALMTE_PINTDAV_GPIO]);
+    tsc = tsc2102_init(qdev_get_gpio_in(cpu->gpio, PALMTE_PINTDAV_GPIO));
 
     omap_uwire_attach(cpu->microwire, tsc, 0);
     omap_mcbsp_i2s_attach(cpu->mcbsp1, tsc210x_codec(tsc));
@@ -163,24 +163,24 @@ static void palmte_gpio_setup(struct omap_mpu_state_s *cpu)
     qemu_irq *misc_gpio;
 
     omap_mmc_handlers(cpu->mmc,
-                    omap_gpio_in_get(cpu->gpio)[PALMTE_MMC_WP_GPIO],
+                    qdev_get_gpio_in(cpu->gpio, PALMTE_MMC_WP_GPIO),
                     qemu_irq_invert(omap_mpuio_in_get(cpu->mpuio)
                             [PALMTE_MMC_SWITCH_GPIO]));
 
     misc_gpio = qemu_allocate_irqs(palmte_onoff_gpios, cpu, 7);
-    omap_gpio_out_set(cpu->gpio, PALMTE_MMC_POWER_GPIO,	misc_gpio[0]);
-    omap_gpio_out_set(cpu->gpio, PALMTE_SPEAKER_GPIO,	misc_gpio[1]);
-    omap_gpio_out_set(cpu->gpio, 11,			misc_gpio[2]);
-    omap_gpio_out_set(cpu->gpio, 12,			misc_gpio[3]);
-    omap_gpio_out_set(cpu->gpio, 13,			misc_gpio[4]);
-    omap_mpuio_out_set(cpu->mpuio, 1,			misc_gpio[5]);
-    omap_mpuio_out_set(cpu->mpuio, 3,			misc_gpio[6]);
+    qdev_connect_gpio_out(cpu->gpio, PALMTE_MMC_POWER_GPIO,	misc_gpio[0]);
+    qdev_connect_gpio_out(cpu->gpio, PALMTE_SPEAKER_GPIO,	misc_gpio[1]);
+    qdev_connect_gpio_out(cpu->gpio, 11,			misc_gpio[2]);
+    qdev_connect_gpio_out(cpu->gpio, 12,			misc_gpio[3]);
+    qdev_connect_gpio_out(cpu->gpio, 13,			misc_gpio[4]);
+    omap_mpuio_out_set(cpu->mpuio, 1,				misc_gpio[5]);
+    omap_mpuio_out_set(cpu->mpuio, 3,				misc_gpio[6]);
 
     /* Reset some inputs to initial state.  */
-    qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[PALMTE_USBDETECT_GPIO]);
-    qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[PALMTE_USB_OR_DC_GPIO]);
-    qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[4]);
-    qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[PALMTE_HEADPHONES_GPIO]);
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USBDETECT_GPIO));
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USB_OR_DC_GPIO));
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, 4));
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_HEADPHONES_GPIO));
     qemu_irq_lower(omap_mpuio_in_get(cpu->mpuio)[PALMTE_DC_GPIO]);
     qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[6]);
     qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[7]);
commit 0a34f96690bcb56bd6bc55566c2773e77c67650c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jul 29 16:35:16 2011 +0100

    hw/omap_clk: Add the clock for the OMAP2430-specific fifth GPIO module
    
    The OMAP2430 has a fifth GPIO module which earlier OMAP2 models lack; add
    the clock definition for it.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/omap_clk.c b/hw/omap_clk.c
index 6bcabef..577b326 100644
--- a/hw/omap_clk.c
+++ b/hw/omap_clk.c
@@ -836,7 +836,7 @@ static struct clk i2c2_iclk = {
     .parent	= &core_l4_iclk,
 };
 
-static struct clk gpio_dbclk[4] = {
+static struct clk gpio_dbclk[5] = {
     {
         .name	= "gpio1_dbclk",
         .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
@@ -853,6 +853,10 @@ static struct clk gpio_dbclk[4] = {
         .name	= "gpio4_dbclk",
         .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
         .parent	= &wu_32k_clk,
+    }, {
+        .name   = "gpio5_dbclk",
+        .flags  = CLOCK_IN_OMAP243X,
+        .parent = &wu_32k_clk,
     },
 };
 
commit f9049203d33847562de155a7c5bc75fe7a3e77f6
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Fri Jul 29 16:35:14 2011 +0100

    hw/omap_l4.c: Add helper function omap_l4_region_base
    
    Add helper function omap_l4_region_base() to return the base address
    of a particular region of an L4 target agent.
    
    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>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/omap.h b/hw/omap.h
index c227a82..00a0ea9 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -93,6 +93,8 @@ 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_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);
 
diff --git a/hw/omap_l4.c b/hw/omap_l4.c
index 4af0ca8..59c84b1 100644
--- a/hw/omap_l4.c
+++ b/hw/omap_l4.c
@@ -146,6 +146,12 @@ struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num)
     return bus;
 }
 
+target_phys_addr_t omap_l4_region_base(struct omap_target_agent_s *ta,
+                                       int region)
+{
+    return ta->bus->base + ta->start[region].offset;
+}
+
 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;
commit 64de0e46c06eeb2edb21a936aa4e4b60ca2e5a25
Merge: 23487df... ec67464...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jul 29 09:46:16 2011 -0500

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

commit 23487df884048ed801095e9525baf1bb94e8b4b0
Merge: 3046c98... 0f94d6d...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jul 29 09:43:36 2011 -0500

    Merge remote-tracking branch 'alon/pull-libcacard.afe' into staging

commit 3046c984049070ab5843da1753ce3a22e25b52cd
Merge: e374560... 679f4f8...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jul 29 09:42:12 2011 -0500

    Merge remote-tracking branch 'agraf/xen-next' into staging

commit e374560232776d4141866abc9f520c132b394926
Merge: c62f6d1... 98e51ec...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jul 29 09:39:37 2011 -0500

    Merge remote-tracking branch 'kraxel/migration.2' into staging

commit c62f6d1d76aea587556c85b6b7b5c44167006264
Author: TeLeMan <geleman at gmail.com>
Date:   Mon Jul 25 16:29:14 2011 +0800

    monitor: fix build breakage with --disable-vnc
    
    The breakage was introduced by the commit 13661089810d3e59931f3e80d7cb541b99af7071
    
    Signed-off-by: TeLeMan <geleman at gmail.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/monitor.c b/monitor.c
index 718935b..1b8ba2c 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1200,10 +1200,12 @@ static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_d
         }
 	qerror_report(QERR_ADD_CLIENT_FAILED);
 	return -1;
+#ifdef CONFIG_VNC
     } else if (strcmp(protocol, "vnc") == 0) {
 	int fd = monitor_get_fd(mon, fdname);
 	vnc_display_add_client(NULL, fd, skipauth);
 	return 0;
+#endif
     } else if ((s = qemu_chr_find(protocol)) != NULL) {
 	int fd = monitor_get_fd(mon, fdname);
 	if (qemu_chr_add_client(s, fd) < 0) {
commit 2645c6dcaf6ea2a51a3b6dfa407dd203004e4d11
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Jul 25 18:11:20 2011 +0200

    Allow to leave type on default in -machine
    
    This allows to specify -machine options without setting an explicit
    machine type. We will pick the default machine in this case. Requesting
    the list of available machines is still possible via '-machine ?' e.g.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index a3d8d77..73316cf 100644
--- a/vl.c
+++ b/vl.c
@@ -2724,7 +2724,10 @@ int main(int argc, char **argv, char **envp)
                     fprintf(stderr, "parse error: %s\n", optarg);
                     exit(1);
                 }
-                machine = machine_parse(qemu_opt_get(opts, "type"));
+                optarg = qemu_opt_get(opts, "type");
+                if (optarg) {
+                    machine = machine_parse(optarg);
+                }
                 break;
             case QEMU_OPTION_usb:
                 usb_enabled = 1;
commit 5f070c5fb768cc587b1a75379b7b17c3f841fd40
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Jul 25 18:55:53 2011 +0300

    CODING_STYLE: explicitly allow braceless 'else if'
    
    It's already allowed by the example; there are about 1800 instances in the
    tree; and disallowing it would lead to
    
        if (a) {
            ...
        } else {
            if (b) {
                ...
            } else {
                if (c) {
                    ...
                } else {
                    if (d) {
                        ...
                    } else {
                        ...
                    }
                }
            }
        }
    
    instead of
    
        if (a) {
            ...
        } else if (b) {
            ...
        } else if (c) {
            ...
        } else if (d) {
            ...
        } else {
            ...
        }
    
    which is more readable.
    
    Acked-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/CODING_STYLE b/CODING_STYLE
index 5ecfa22..6e61c49 100644
--- a/CODING_STYLE
+++ b/CODING_STYLE
@@ -68,6 +68,10 @@ keyword.  Example:
         printf("a was something else entirely.\n");
     }
 
+Note that 'else if' is considered a single statement; otherwise a long if/
+else if/else if/.../else sequence would need an indent for every else
+statement.
+
 An exception is the opening brace for a function; for reasons of tradition
 and clarity it comes on a line by itself:
 
commit ecf169b7fa920b87e380981c5206148d057d85fb
Author: Stefan Berger <stefanb at linux.vnet.ibm.com>
Date:   Tue Jul 26 10:33:11 2011 -0400

    Fix a compilation error in xen-mapcache.c
    
    This patch fixes a compilation error in xen-mapcache.c .
    
    /home/stefanb/qemu/qemu-git/xen-mapcache.c: In function ‘xen_ram_addr_from_mapcache’:
    /home/stefanb/qemu/qemu-git/xen-mapcache.c:240:42: error: variable ‘pentry’ set but not used [-Werror=unused-but-set-variable]
    cc1: all warnings being treated as errors
    
    Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/xen-mapcache.c b/xen-mapcache.c
index 007136a..15d1241 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -237,7 +237,7 @@ uint8_t *xen_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size,
 
 ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
 {
-    MapCacheEntry *entry = NULL, *pentry = NULL;
+    MapCacheEntry *entry = NULL;
     MapCacheRev *reventry;
     target_phys_addr_t paddr_index;
     target_phys_addr_t size;
@@ -263,7 +263,6 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
 
     entry = &mapcache->entry[paddr_index % mapcache->nr_buckets];
     while (entry && (entry->paddr_index != paddr_index || entry->size != size)) {
-        pentry = entry;
         entry = entry->next;
     }
     if (!entry) {
commit 6b8273a1b97876950d91c228a420a851e10e12bb
Author: Göran Weinholt <goran at weinholt.se>
Date:   Sun Jul 24 17:55:58 2011 +0200

    multiboot: Fix bss segment support
    
    Multiboot images can specify a bss segment. The boot loader must clear
    the memory of the bss and ensure that no modules or structures are
    allocated inside it. Several fields are provided in the Multiboot
    header that were previously not used properly. The header is now used
    to determine how much data should be read from the image and how much
    memory should be reserved to the bss segment.
    
    Signed-off-by: Göran Weinholt <goran at weinholt.se>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/multiboot.c b/hw/multiboot.c
index 2426e84..a1d3f41 100644
--- a/hw/multiboot.c
+++ b/hw/multiboot.c
@@ -198,11 +198,14 @@ int load_multiboot(void *fw_cfg,
     } else {
         /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_ADDR. */
         uint32_t mh_header_addr = ldl_p(header+i+12);
+        uint32_t mh_load_end_addr = ldl_p(header+i+20);
+        uint32_t mh_bss_end_addr = ldl_p(header+i+24);
         mh_load_addr = ldl_p(header+i+16);
         uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr);
+        uint32_t mb_load_size = mh_load_end_addr - mh_load_addr;
 
         mh_entry_addr = ldl_p(header+i+28);
-        mb_kernel_size = kernel_file_size - mb_kernel_text_offset;
+        mb_kernel_size = mh_bss_end_addr - mh_load_addr;
 
         /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_VBE.
         uint32_t mh_mode_type = ldl_p(header+i+32);
@@ -212,17 +215,18 @@ int load_multiboot(void *fw_cfg,
 
         mb_debug("multiboot: mh_header_addr = %#x\n", mh_header_addr);
         mb_debug("multiboot: mh_load_addr = %#x\n", mh_load_addr);
-        mb_debug("multiboot: mh_load_end_addr = %#x\n", ldl_p(header+i+20));
-        mb_debug("multiboot: mh_bss_end_addr = %#x\n", ldl_p(header+i+24));
+        mb_debug("multiboot: mh_load_end_addr = %#x\n", mh_load_end_addr);
+        mb_debug("multiboot: mh_bss_end_addr = %#x\n", mh_bss_end_addr);
         mb_debug("qemu: loading multiboot kernel (%#x bytes) at %#x\n",
-                 mb_kernel_size, mh_load_addr);
+                 mb_load_size, mh_load_addr);
 
         mbs.mb_buf = qemu_malloc(mb_kernel_size);
         fseek(f, mb_kernel_text_offset, SEEK_SET);
-        if (fread(mbs.mb_buf, 1, mb_kernel_size, f) != mb_kernel_size) {
+        if (fread(mbs.mb_buf, 1, mb_load_size, f) != mb_load_size) {
             fprintf(stderr, "fread() failed\n");
             exit(1);
         }
+        memset(mbs.mb_buf + mb_load_size, 0, mb_kernel_size - mb_load_size);
         fclose(f);
     }
 
commit 1ece9905747fb42ab6b2797c8ddde56496f14796
Author: Alon Levy <alevy at redhat.com>
Date:   Tue Jul 26 12:30:40 2011 +0300

    configure: add --disable-zlib-test
    
    This is required for building libcacard which doesn't itself require
    zlib without bringing in this requirement to the build environment.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index 0e07132..e80a1e9 100755
--- a/configure
+++ b/configure
@@ -179,6 +179,7 @@ smartcard=""
 smartcard_nss=""
 usb_redir=""
 opengl=""
+zlib="yes"
 
 # parse CC options first
 for opt do
@@ -751,6 +752,8 @@ for opt do
   ;;
   --enable-usb-redir) usb_redir="yes"
   ;;
+  --disable-zlib-test) zlib="no"
+  ;;
   *) echo "ERROR: unknown option $opt"; show_help="yes"
   ;;
   esac
@@ -1190,18 +1193,20 @@ fi
 ##########################################
 # zlib check
 
-cat > $TMPC << EOF
+if test "$zlib" != "no" ; then
+    cat > $TMPC << EOF
 #include <zlib.h>
 int main(void) { zlibVersion(); return 0; }
 EOF
-if compile_prog "" "-lz" ; then
-    :
-else
-    echo
-    echo "Error: zlib check failed"
-    echo "Make sure to have the zlib libs and headers installed."
-    echo
-    exit 1
+    if compile_prog "" "-lz" ; then
+        :
+    else
+        echo
+        echo "Error: zlib check failed"
+        echo "Make sure to have the zlib libs and headers installed."
+        echo
+        exit 1
+    fi
 fi
 
 ##########################################
commit c7f4111a06208b46c6d05934d2a1e5cfbebc0180
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Mon Jul 25 17:13:36 2011 +0200

    Add missing trace call to oslib-posix.c:qemu_vmalloc()
    
    Acked-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/oslib-posix.c b/oslib-posix.c
index 3a18e86..196099c 100644
--- a/oslib-posix.c
+++ b/oslib-posix.c
@@ -79,7 +79,10 @@ void *qemu_memalign(size_t alignment, size_t size)
 /* alloc shared memory pages */
 void *qemu_vmalloc(size_t size)
 {
-    return qemu_memalign(getpagesize(), size);
+    void *ptr;
+    ptr = qemu_memalign(getpagesize(), size);
+    trace_qemu_vmalloc(size, ptr);
+    return ptr;
 }
 
 void qemu_vfree(void *ptr)
commit 33fa8234c3d642317583c992b7fdc67ce7fdd1b5
Author: Dr. David Alan Gilbert <david.gilbert at linaro.org>
Date:   Mon Jul 25 13:21:30 2011 +0100

    Fix last sector write on sd card
    
        When writing the last sector of an SD card using WRITE_MULTIPLE_BLOCK
    QEmu throws an error saying that we've run off the end, and leaves
    itself in the wrong state.
    
        Tested on ARM Vexpress model.
    
    Signed-off-by: Dr. David Alan Gilbert <david.gilbert at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/sd.c b/hw/sd.c
index cedfb20..219a0dd 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -1450,14 +1450,8 @@ void sd_write_data(SDState *sd, uint8_t value)
         break;
 
     case 25:	/* CMD25:  WRITE_MULTIPLE_BLOCK */
-        sd->data[sd->data_offset ++] = value;
-        if (sd->data_offset >= sd->blk_len) {
-            /* TODO: Check CRC before committing */
-            sd->state = sd_programming_state;
-            BLK_WRITE_BLOCK(sd->data_start, sd->data_offset);
-            sd->blk_written ++;
-            sd->data_start += sd->blk_len;
-            sd->data_offset = 0;
+        if (sd->data_offset == 0) {
+            /* Start of the block - lets check the address is valid */
             if (sd->data_start + sd->blk_len > sd->size) {
                 sd->card_status |= ADDRESS_ERROR;
                 break;
@@ -1466,6 +1460,15 @@ void sd_write_data(SDState *sd, uint8_t value)
                 sd->card_status |= WP_VIOLATION;
                 break;
             }
+        }
+        sd->data[sd->data_offset++] = value;
+        if (sd->data_offset >= sd->blk_len) {
+            /* TODO: Check CRC before committing */
+            sd->state = sd_programming_state;
+            BLK_WRITE_BLOCK(sd->data_start, sd->data_offset);
+            sd->blk_written++;
+            sd->data_start += sd->blk_len;
+            sd->data_offset = 0;
             sd->csd[14] |= 0x40;
 
             /* Bzzzzzzztt .... Operation complete.  */
commit cbbab9226da9572346837466a8770c117e7e65a2
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Jul 28 12:10:30 2011 +0200

    move unaligned memory access functions to bswap.h
    
    This is just code movement, and moving the fpu/ include path from
    target-dependent to target-independent Make variables.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile.hw b/Makefile.hw
index b9181ab..659e441 100644
--- a/Makefile.hw
+++ b/Makefile.hw
@@ -9,7 +9,7 @@ include $(SRC_PATH)/rules.mak
 
 $(call set-vpath, $(SRC_PATH):$(SRC_PATH)/hw)
 
-QEMU_CFLAGS+=-I.. -I$(SRC_PATH)/fpu
+QEMU_CFLAGS+=-I..
 
 include $(SRC_PATH)/Makefile.objs
 
diff --git a/bswap.h b/bswap.h
index 82a7951..f41bebe 100644
--- a/bswap.h
+++ b/bswap.h
@@ -11,6 +11,8 @@
 #include <machine/bswap.h>
 #else
 
+#include "softfloat.h"
+
 #ifdef CONFIG_BYTESWAP_H
 #include <byteswap.h>
 #else
@@ -237,4 +239,476 @@ static inline uint32_t qemu_bswap_len(uint32_t value, int len)
     return bswap32(value) >> (32 - 8 * len);
 }
 
+typedef union {
+    float32 f;
+    uint32_t l;
+} CPU_FloatU;
+
+typedef union {
+    float64 d;
+#if defined(HOST_WORDS_BIGENDIAN)
+    struct {
+        uint32_t upper;
+        uint32_t lower;
+    } l;
+#else
+    struct {
+        uint32_t lower;
+        uint32_t upper;
+    } l;
+#endif
+    uint64_t ll;
+} CPU_DoubleU;
+
+typedef union {
+     floatx80 d;
+     struct {
+         uint64_t lower;
+         uint16_t upper;
+     } l;
+} CPU_LDoubleU;
+
+typedef union {
+    float128 q;
+#if defined(HOST_WORDS_BIGENDIAN)
+    struct {
+        uint32_t upmost;
+        uint32_t upper;
+        uint32_t lower;
+        uint32_t lowest;
+    } l;
+    struct {
+        uint64_t upper;
+        uint64_t lower;
+    } ll;
+#else
+    struct {
+        uint32_t lowest;
+        uint32_t lower;
+        uint32_t upper;
+        uint32_t upmost;
+    } l;
+    struct {
+        uint64_t lower;
+        uint64_t upper;
+    } ll;
+#endif
+} CPU_QuadU;
+
+/* unaligned/endian-independent pointer access */
+
+/*
+ * the generic syntax is:
+ *
+ * load: ld{type}{sign}{size}{endian}_p(ptr)
+ *
+ * store: st{type}{size}{endian}_p(ptr, val)
+ *
+ * Note there are small differences with the softmmu access API!
+ *
+ * type is:
+ * (empty): integer access
+ *   f    : float access
+ *
+ * sign is:
+ * (empty): for floats or 32 bit size
+ *   u    : unsigned
+ *   s    : signed
+ *
+ * size is:
+ *   b: 8 bits
+ *   w: 16 bits
+ *   l: 32 bits
+ *   q: 64 bits
+ *
+ * endian is:
+ * (empty): 8 bit access
+ *   be   : big endian
+ *   le   : little endian
+ */
+static inline int ldub_p(const void *ptr)
+{
+    return *(uint8_t *)ptr;
+}
+
+static inline int ldsb_p(const void *ptr)
+{
+    return *(int8_t *)ptr;
+}
+
+static inline void stb_p(void *ptr, int v)
+{
+    *(uint8_t *)ptr = v;
+}
+
+/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
+   kernel handles unaligned load/stores may give better results, but
+   it is a system wide setting : bad */
+#if defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
+
+/* conservative code for little endian unaligned accesses */
+static inline int lduw_le_p(const void *ptr)
+{
+#ifdef _ARCH_PPC
+    int val;
+    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
+    return val;
+#else
+    const uint8_t *p = ptr;
+    return p[0] | (p[1] << 8);
+#endif
+}
+
+static inline int ldsw_le_p(const void *ptr)
+{
+#ifdef _ARCH_PPC
+    int val;
+    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
+    return (int16_t)val;
+#else
+    const uint8_t *p = ptr;
+    return (int16_t)(p[0] | (p[1] << 8));
+#endif
+}
+
+static inline int ldl_le_p(const void *ptr)
+{
+#ifdef _ARCH_PPC
+    int val;
+    __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
+    return val;
+#else
+    const uint8_t *p = ptr;
+    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+#endif
+}
+
+static inline uint64_t ldq_le_p(const void *ptr)
+{
+    const uint8_t *p = ptr;
+    uint32_t v1, v2;
+    v1 = ldl_le_p(p);
+    v2 = ldl_le_p(p + 4);
+    return v1 | ((uint64_t)v2 << 32);
+}
+
+static inline void stw_le_p(void *ptr, int v)
+{
+#ifdef _ARCH_PPC
+    __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
+#else
+    uint8_t *p = ptr;
+    p[0] = v;
+    p[1] = v >> 8;
+#endif
+}
+
+static inline void stl_le_p(void *ptr, int v)
+{
+#ifdef _ARCH_PPC
+    __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
+#else
+    uint8_t *p = ptr;
+    p[0] = v;
+    p[1] = v >> 8;
+    p[2] = v >> 16;
+    p[3] = v >> 24;
+#endif
+}
+
+static inline void stq_le_p(void *ptr, uint64_t v)
+{
+    uint8_t *p = ptr;
+    stl_le_p(p, (uint32_t)v);
+    stl_le_p(p + 4, v >> 32);
+}
+
+/* float access */
+
+static inline float32 ldfl_le_p(const void *ptr)
+{
+    union {
+        float32 f;
+        uint32_t i;
+    } u;
+    u.i = ldl_le_p(ptr);
+    return u.f;
+}
+
+static inline void stfl_le_p(void *ptr, float32 v)
+{
+    union {
+        float32 f;
+        uint32_t i;
+    } u;
+    u.f = v;
+    stl_le_p(ptr, u.i);
+}
+
+static inline float64 ldfq_le_p(const void *ptr)
+{
+    CPU_DoubleU u;
+    u.l.lower = ldl_le_p(ptr);
+    u.l.upper = ldl_le_p(ptr + 4);
+    return u.d;
+}
+
+static inline void stfq_le_p(void *ptr, float64 v)
+{
+    CPU_DoubleU u;
+    u.d = v;
+    stl_le_p(ptr, u.l.lower);
+    stl_le_p(ptr + 4, u.l.upper);
+}
+
+#else
+
+static inline int lduw_le_p(const void *ptr)
+{
+    return *(uint16_t *)ptr;
+}
+
+static inline int ldsw_le_p(const void *ptr)
+{
+    return *(int16_t *)ptr;
+}
+
+static inline int ldl_le_p(const void *ptr)
+{
+    return *(uint32_t *)ptr;
+}
+
+static inline uint64_t ldq_le_p(const void *ptr)
+{
+    return *(uint64_t *)ptr;
+}
+
+static inline void stw_le_p(void *ptr, int v)
+{
+    *(uint16_t *)ptr = v;
+}
+
+static inline void stl_le_p(void *ptr, int v)
+{
+    *(uint32_t *)ptr = v;
+}
+
+static inline void stq_le_p(void *ptr, uint64_t v)
+{
+    *(uint64_t *)ptr = v;
+}
+
+/* float access */
+
+static inline float32 ldfl_le_p(const void *ptr)
+{
+    return *(float32 *)ptr;
+}
+
+static inline float64 ldfq_le_p(const void *ptr)
+{
+    return *(float64 *)ptr;
+}
+
+static inline void stfl_le_p(void *ptr, float32 v)
+{
+    *(float32 *)ptr = v;
+}
+
+static inline void stfq_le_p(void *ptr, float64 v)
+{
+    *(float64 *)ptr = v;
+}
+#endif
+
+#if !defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
+
+static inline int lduw_be_p(const void *ptr)
+{
+#if defined(__i386__)
+    int val;
+    asm volatile ("movzwl %1, %0\n"
+                  "xchgb %b0, %h0\n"
+                  : "=q" (val)
+                  : "m" (*(uint16_t *)ptr));
+    return val;
+#else
+    const uint8_t *b = ptr;
+    return ((b[0] << 8) | b[1]);
+#endif
+}
+
+static inline int ldsw_be_p(const void *ptr)
+{
+#if defined(__i386__)
+    int val;
+    asm volatile ("movzwl %1, %0\n"
+                  "xchgb %b0, %h0\n"
+                  : "=q" (val)
+                  : "m" (*(uint16_t *)ptr));
+    return (int16_t)val;
+#else
+    const uint8_t *b = ptr;
+    return (int16_t)((b[0] << 8) | b[1]);
+#endif
+}
+
+static inline int ldl_be_p(const void *ptr)
+{
+#if defined(__i386__) || defined(__x86_64__)
+    int val;
+    asm volatile ("movl %1, %0\n"
+                  "bswap %0\n"
+                  : "=r" (val)
+                  : "m" (*(uint32_t *)ptr));
+    return val;
+#else
+    const uint8_t *b = ptr;
+    return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
+#endif
+}
+
+static inline uint64_t ldq_be_p(const void *ptr)
+{
+    uint32_t a,b;
+    a = ldl_be_p(ptr);
+    b = ldl_be_p((uint8_t *)ptr + 4);
+    return (((uint64_t)a<<32)|b);
+}
+
+static inline void stw_be_p(void *ptr, int v)
+{
+#if defined(__i386__)
+    asm volatile ("xchgb %b0, %h0\n"
+                  "movw %w0, %1\n"
+                  : "=q" (v)
+                  : "m" (*(uint16_t *)ptr), "0" (v));
+#else
+    uint8_t *d = (uint8_t *) ptr;
+    d[0] = v >> 8;
+    d[1] = v;
+#endif
+}
+
+static inline void stl_be_p(void *ptr, int v)
+{
+#if defined(__i386__) || defined(__x86_64__)
+    asm volatile ("bswap %0\n"
+                  "movl %0, %1\n"
+                  : "=r" (v)
+                  : "m" (*(uint32_t *)ptr), "0" (v));
+#else
+    uint8_t *d = (uint8_t *) ptr;
+    d[0] = v >> 24;
+    d[1] = v >> 16;
+    d[2] = v >> 8;
+    d[3] = v;
+#endif
+}
+
+static inline void stq_be_p(void *ptr, uint64_t v)
+{
+    stl_be_p(ptr, v >> 32);
+    stl_be_p((uint8_t *)ptr + 4, v);
+}
+
+/* float access */
+
+static inline float32 ldfl_be_p(const void *ptr)
+{
+    union {
+        float32 f;
+        uint32_t i;
+    } u;
+    u.i = ldl_be_p(ptr);
+    return u.f;
+}
+
+static inline void stfl_be_p(void *ptr, float32 v)
+{
+    union {
+        float32 f;
+        uint32_t i;
+    } u;
+    u.f = v;
+    stl_be_p(ptr, u.i);
+}
+
+static inline float64 ldfq_be_p(const void *ptr)
+{
+    CPU_DoubleU u;
+    u.l.upper = ldl_be_p(ptr);
+    u.l.lower = ldl_be_p((uint8_t *)ptr + 4);
+    return u.d;
+}
+
+static inline void stfq_be_p(void *ptr, float64 v)
+{
+    CPU_DoubleU u;
+    u.d = v;
+    stl_be_p(ptr, u.l.upper);
+    stl_be_p((uint8_t *)ptr + 4, u.l.lower);
+}
+
+#else
+
+static inline int lduw_be_p(const void *ptr)
+{
+    return *(uint16_t *)ptr;
+}
+
+static inline int ldsw_be_p(const void *ptr)
+{
+    return *(int16_t *)ptr;
+}
+
+static inline int ldl_be_p(const void *ptr)
+{
+    return *(uint32_t *)ptr;
+}
+
+static inline uint64_t ldq_be_p(const void *ptr)
+{
+    return *(uint64_t *)ptr;
+}
+
+static inline void stw_be_p(void *ptr, int v)
+{
+    *(uint16_t *)ptr = v;
+}
+
+static inline void stl_be_p(void *ptr, int v)
+{
+    *(uint32_t *)ptr = v;
+}
+
+static inline void stq_be_p(void *ptr, uint64_t v)
+{
+    *(uint64_t *)ptr = v;
+}
+
+/* float access */
+
+static inline float32 ldfl_be_p(const void *ptr)
+{
+    return *(float32 *)ptr;
+}
+
+static inline float64 ldfq_be_p(const void *ptr)
+{
+    return *(float64 *)ptr;
+}
+
+static inline void stfl_be_p(void *ptr, float32 v)
+{
+    *(float32 *)ptr = v;
+}
+
+static inline void stfq_be_p(void *ptr, float64 v)
+{
+    *(float64 *)ptr = v;
+}
+
+#endif
+
 #endif /* BSWAP_H */
diff --git a/configure b/configure
index 38e3724..0e07132 100755
--- a/configure
+++ b/configure
@@ -233,7 +233,7 @@ QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS"
 QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS"
 QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS"
 QEMU_CFLAGS="-D_FORTIFY_SOURCE=2 $QEMU_CFLAGS"
-QEMU_INCLUDES="-I. -I\$(SRC_PATH)"
+QEMU_INCLUDES="-I. -I\$(SRC_PATH) -I\$(SRC_PATH)/fpu"
 LDFLAGS="-g $LDFLAGS"
 
 # make source path absolute
@@ -3374,7 +3374,6 @@ else
   includes="-I\$(SRC_PATH)/tcg/\$(ARCH) $includes"
 fi
 includes="-I\$(SRC_PATH)/tcg $includes"
-includes="-I\$(SRC_PATH)/fpu $includes"
 
 if test "$target_user_only" = "yes" ; then
     libdis_config_mak=libdis-user/config.mak
diff --git a/cpu-all.h b/cpu-all.h
index e839100..fa0205c 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -35,8 +35,6 @@
  * TARGET_WORDS_BIGENDIAN : same for target cpu
  */
 
-#include "softfloat.h"
-
 #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
 #define BSWAP_NEEDED
 #endif
@@ -114,64 +112,6 @@ static inline void tswap64s(uint64_t *s)
 #define bswaptls(s) bswap64s(s)
 #endif
 
-typedef union {
-    float32 f;
-    uint32_t l;
-} CPU_FloatU;
-
-/* NOTE: arm FPA is horrible as double 32 bit words are stored in big
-   endian ! */
-typedef union {
-    float64 d;
-#if defined(HOST_WORDS_BIGENDIAN)
-    struct {
-        uint32_t upper;
-        uint32_t lower;
-    } l;
-#else
-    struct {
-        uint32_t lower;
-        uint32_t upper;
-    } l;
-#endif
-    uint64_t ll;
-} CPU_DoubleU;
-
-typedef union {
-     floatx80 d;
-     struct {
-         uint64_t lower;
-         uint16_t upper;
-     } l;
-} CPU_LDoubleU;
-
-typedef union {
-    float128 q;
-#if defined(HOST_WORDS_BIGENDIAN)
-    struct {
-        uint32_t upmost;
-        uint32_t upper;
-        uint32_t lower;
-        uint32_t lowest;
-    } l;
-    struct {
-        uint64_t upper;
-        uint64_t lower;
-    } ll;
-#else
-    struct {
-        uint32_t lowest;
-        uint32_t lower;
-        uint32_t upper;
-        uint32_t upmost;
-    } l;
-    struct {
-        uint64_t lower;
-        uint64_t upper;
-    } ll;
-#endif
-} CPU_QuadU;
-
 /* CPU memory access without any memory or io remapping */
 
 /*
@@ -207,392 +147,8 @@ typedef union {
  *   user   : user mode access using soft MMU
  *   kernel : kernel mode access using soft MMU
  */
-static inline int ldub_p(const void *ptr)
-{
-    return *(uint8_t *)ptr;
-}
-
-static inline int ldsb_p(const void *ptr)
-{
-    return *(int8_t *)ptr;
-}
-
-static inline void stb_p(void *ptr, int v)
-{
-    *(uint8_t *)ptr = v;
-}
-
-/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
-   kernel handles unaligned load/stores may give better results, but
-   it is a system wide setting : bad */
-#if defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
-
-/* conservative code for little endian unaligned accesses */
-static inline int lduw_le_p(const void *ptr)
-{
-#ifdef _ARCH_PPC
-    int val;
-    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
-    return val;
-#else
-    const uint8_t *p = ptr;
-    return p[0] | (p[1] << 8);
-#endif
-}
-
-static inline int ldsw_le_p(const void *ptr)
-{
-#ifdef _ARCH_PPC
-    int val;
-    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
-    return (int16_t)val;
-#else
-    const uint8_t *p = ptr;
-    return (int16_t)(p[0] | (p[1] << 8));
-#endif
-}
-
-static inline int ldl_le_p(const void *ptr)
-{
-#ifdef _ARCH_PPC
-    int val;
-    __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
-    return val;
-#else
-    const uint8_t *p = ptr;
-    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
-#endif
-}
-
-static inline uint64_t ldq_le_p(const void *ptr)
-{
-    const uint8_t *p = ptr;
-    uint32_t v1, v2;
-    v1 = ldl_le_p(p);
-    v2 = ldl_le_p(p + 4);
-    return v1 | ((uint64_t)v2 << 32);
-}
-
-static inline void stw_le_p(void *ptr, int v)
-{
-#ifdef _ARCH_PPC
-    __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
-#else
-    uint8_t *p = ptr;
-    p[0] = v;
-    p[1] = v >> 8;
-#endif
-}
-
-static inline void stl_le_p(void *ptr, int v)
-{
-#ifdef _ARCH_PPC
-    __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
-#else
-    uint8_t *p = ptr;
-    p[0] = v;
-    p[1] = v >> 8;
-    p[2] = v >> 16;
-    p[3] = v >> 24;
-#endif
-}
-
-static inline void stq_le_p(void *ptr, uint64_t v)
-{
-    uint8_t *p = ptr;
-    stl_le_p(p, (uint32_t)v);
-    stl_le_p(p + 4, v >> 32);
-}
-
-/* float access */
-
-static inline float32 ldfl_le_p(const void *ptr)
-{
-    union {
-        float32 f;
-        uint32_t i;
-    } u;
-    u.i = ldl_le_p(ptr);
-    return u.f;
-}
-
-static inline void stfl_le_p(void *ptr, float32 v)
-{
-    union {
-        float32 f;
-        uint32_t i;
-    } u;
-    u.f = v;
-    stl_le_p(ptr, u.i);
-}
-
-static inline float64 ldfq_le_p(const void *ptr)
-{
-    CPU_DoubleU u;
-    u.l.lower = ldl_le_p(ptr);
-    u.l.upper = ldl_le_p(ptr + 4);
-    return u.d;
-}
-
-static inline void stfq_le_p(void *ptr, float64 v)
-{
-    CPU_DoubleU u;
-    u.d = v;
-    stl_le_p(ptr, u.l.lower);
-    stl_le_p(ptr + 4, u.l.upper);
-}
-
-#else
-
-static inline int lduw_le_p(const void *ptr)
-{
-    return *(uint16_t *)ptr;
-}
-
-static inline int ldsw_le_p(const void *ptr)
-{
-    return *(int16_t *)ptr;
-}
-
-static inline int ldl_le_p(const void *ptr)
-{
-    return *(uint32_t *)ptr;
-}
-
-static inline uint64_t ldq_le_p(const void *ptr)
-{
-    return *(uint64_t *)ptr;
-}
-
-static inline void stw_le_p(void *ptr, int v)
-{
-    *(uint16_t *)ptr = v;
-}
-
-static inline void stl_le_p(void *ptr, int v)
-{
-    *(uint32_t *)ptr = v;
-}
-
-static inline void stq_le_p(void *ptr, uint64_t v)
-{
-    *(uint64_t *)ptr = v;
-}
-
-/* float access */
-
-static inline float32 ldfl_le_p(const void *ptr)
-{
-    return *(float32 *)ptr;
-}
-
-static inline float64 ldfq_le_p(const void *ptr)
-{
-    return *(float64 *)ptr;
-}
-
-static inline void stfl_le_p(void *ptr, float32 v)
-{
-    *(float32 *)ptr = v;
-}
-
-static inline void stfq_le_p(void *ptr, float64 v)
-{
-    *(float64 *)ptr = v;
-}
-#endif
-
-#if !defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
-
-static inline int lduw_be_p(const void *ptr)
-{
-#if defined(__i386__)
-    int val;
-    asm volatile ("movzwl %1, %0\n"
-                  "xchgb %b0, %h0\n"
-                  : "=q" (val)
-                  : "m" (*(uint16_t *)ptr));
-    return val;
-#else
-    const uint8_t *b = ptr;
-    return ((b[0] << 8) | b[1]);
-#endif
-}
-
-static inline int ldsw_be_p(const void *ptr)
-{
-#if defined(__i386__)
-    int val;
-    asm volatile ("movzwl %1, %0\n"
-                  "xchgb %b0, %h0\n"
-                  : "=q" (val)
-                  : "m" (*(uint16_t *)ptr));
-    return (int16_t)val;
-#else
-    const uint8_t *b = ptr;
-    return (int16_t)((b[0] << 8) | b[1]);
-#endif
-}
-
-static inline int ldl_be_p(const void *ptr)
-{
-#if defined(__i386__) || defined(__x86_64__)
-    int val;
-    asm volatile ("movl %1, %0\n"
-                  "bswap %0\n"
-                  : "=r" (val)
-                  : "m" (*(uint32_t *)ptr));
-    return val;
-#else
-    const uint8_t *b = ptr;
-    return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
-#endif
-}
-
-static inline uint64_t ldq_be_p(const void *ptr)
-{
-    uint32_t a,b;
-    a = ldl_be_p(ptr);
-    b = ldl_be_p((uint8_t *)ptr + 4);
-    return (((uint64_t)a<<32)|b);
-}
-
-static inline void stw_be_p(void *ptr, int v)
-{
-#if defined(__i386__)
-    asm volatile ("xchgb %b0, %h0\n"
-                  "movw %w0, %1\n"
-                  : "=q" (v)
-                  : "m" (*(uint16_t *)ptr), "0" (v));
-#else
-    uint8_t *d = (uint8_t *) ptr;
-    d[0] = v >> 8;
-    d[1] = v;
-#endif
-}
-
-static inline void stl_be_p(void *ptr, int v)
-{
-#if defined(__i386__) || defined(__x86_64__)
-    asm volatile ("bswap %0\n"
-                  "movl %0, %1\n"
-                  : "=r" (v)
-                  : "m" (*(uint32_t *)ptr), "0" (v));
-#else
-    uint8_t *d = (uint8_t *) ptr;
-    d[0] = v >> 24;
-    d[1] = v >> 16;
-    d[2] = v >> 8;
-    d[3] = v;
-#endif
-}
-
-static inline void stq_be_p(void *ptr, uint64_t v)
-{
-    stl_be_p(ptr, v >> 32);
-    stl_be_p((uint8_t *)ptr + 4, v);
-}
-
-/* float access */
-
-static inline float32 ldfl_be_p(const void *ptr)
-{
-    union {
-        float32 f;
-        uint32_t i;
-    } u;
-    u.i = ldl_be_p(ptr);
-    return u.f;
-}
-
-static inline void stfl_be_p(void *ptr, float32 v)
-{
-    union {
-        float32 f;
-        uint32_t i;
-    } u;
-    u.f = v;
-    stl_be_p(ptr, u.i);
-}
-
-static inline float64 ldfq_be_p(const void *ptr)
-{
-    CPU_DoubleU u;
-    u.l.upper = ldl_be_p(ptr);
-    u.l.lower = ldl_be_p((uint8_t *)ptr + 4);
-    return u.d;
-}
-
-static inline void stfq_be_p(void *ptr, float64 v)
-{
-    CPU_DoubleU u;
-    u.d = v;
-    stl_be_p(ptr, u.l.upper);
-    stl_be_p((uint8_t *)ptr + 4, u.l.lower);
-}
-
-#else
-
-static inline int lduw_be_p(const void *ptr)
-{
-    return *(uint16_t *)ptr;
-}
-
-static inline int ldsw_be_p(const void *ptr)
-{
-    return *(int16_t *)ptr;
-}
-
-static inline int ldl_be_p(const void *ptr)
-{
-    return *(uint32_t *)ptr;
-}
-
-static inline uint64_t ldq_be_p(const void *ptr)
-{
-    return *(uint64_t *)ptr;
-}
-
-static inline void stw_be_p(void *ptr, int v)
-{
-    *(uint16_t *)ptr = v;
-}
-
-static inline void stl_be_p(void *ptr, int v)
-{
-    *(uint32_t *)ptr = v;
-}
-
-static inline void stq_be_p(void *ptr, uint64_t v)
-{
-    *(uint64_t *)ptr = v;
-}
-
-/* float access */
-
-static inline float32 ldfl_be_p(const void *ptr)
-{
-    return *(float32 *)ptr;
-}
-
-static inline float64 ldfq_be_p(const void *ptr)
-{
-    return *(float64 *)ptr;
-}
-
-static inline void stfl_be_p(void *ptr, float32 v)
-{
-    *(float32 *)ptr = v;
-}
-
-static inline void stfq_be_p(void *ptr, float64 v)
-{
-    *(float64 *)ptr = v;
-}
-
-#endif
 
-/* target CPU memory access functions */
+/* target-endianness CPU memory access functions */
 #if defined(TARGET_WORDS_BIGENDIAN)
 #define lduw_p(p) lduw_be_p(p)
 #define ldsw_p(p) ldsw_be_p(p)
commit 789ec7ce20f34b175b3983707e077e8d67385126
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Jul 28 12:10:29 2011 +0200

    softfloat: change default nan definitions to variables
    
    Most definitions in softfloat.h are really target-independent, but the
    file is not because it includes definitions of the default NaN values.
    Change those to variables to allow including softfloat.h from files that
    are not compiled per-target.  By making them const, the compiler is
    allowed to optimize them into softfloat functions that use them.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index c7d35a1..c165205 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -35,6 +35,78 @@ these four paragraphs for those parts of this code that are retained.
 
 =============================================================================*/
 
+#if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
+#define SNAN_BIT_IS_ONE		1
+#else
+#define SNAN_BIT_IS_ONE		0
+#endif
+
+/*----------------------------------------------------------------------------
+| The pattern for a default generated half-precision NaN.
+*----------------------------------------------------------------------------*/
+#if defined(TARGET_ARM)
+const float16 float16_default_nan = const_float16(0x7E00);
+#elif SNAN_BIT_IS_ONE
+const float16 float16_default_nan = const_float16(0x7DFF);
+#else
+const float16 float16_default_nan = const_float16(0xFE00);
+#endif
+
+/*----------------------------------------------------------------------------
+| The pattern for a default generated single-precision NaN.
+*----------------------------------------------------------------------------*/
+#if defined(TARGET_SPARC)
+const float32 float32_default_nan = const_float32(0x7FFFFFFF);
+#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
+const float32 float32_default_nan = const_float32(0x7FC00000);
+#elif SNAN_BIT_IS_ONE
+const float32 float32_default_nan = const_float32(0x7FBFFFFF);
+#else
+const float32 float32_default_nan = const_float32(0xFFC00000);
+#endif
+
+/*----------------------------------------------------------------------------
+| The pattern for a default generated double-precision NaN.
+*----------------------------------------------------------------------------*/
+#if defined(TARGET_SPARC)
+const float64 float64_default_nan = const_float64(LIT64( 0x7FFFFFFFFFFFFFFF ));
+#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
+const float64 float64_default_nan = const_float64(LIT64( 0x7FF8000000000000 ));
+#elif SNAN_BIT_IS_ONE
+const float64 float64_default_nan = const_float64(LIT64( 0x7FF7FFFFFFFFFFFF ));
+#else
+const float64 float64_default_nan = const_float64(LIT64( 0xFFF8000000000000 ));
+#endif
+
+/*----------------------------------------------------------------------------
+| The pattern for a default generated extended double-precision NaN.
+*----------------------------------------------------------------------------*/
+#if SNAN_BIT_IS_ONE
+#define floatx80_default_nan_high 0x7FFF
+#define floatx80_default_nan_low  LIT64( 0xBFFFFFFFFFFFFFFF )
+#else
+#define floatx80_default_nan_high 0xFFFF
+#define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
+#endif
+
+const floatx80 floatx80_default_nan = make_floatx80(floatx80_default_nan_high,
+                                                    floatx80_default_nan_low);
+
+/*----------------------------------------------------------------------------
+| The pattern for a default generated quadruple-precision NaN.  The `high' and
+| `low' values hold the most- and least-significant bits, respectively.
+*----------------------------------------------------------------------------*/
+#if SNAN_BIT_IS_ONE
+#define float128_default_nan_high LIT64( 0x7FFF7FFFFFFFFFFF )
+#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
+#else
+#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
+#define float128_default_nan_low  LIT64( 0x0000000000000000 )
+#endif
+
+const float128 float128_default_nan = make_float128(float128_default_nan_high,
+                                                    float128_default_nan_low);
+
 /*----------------------------------------------------------------------------
 | Raises the exceptions specified by `flags'.  Floating-point traps can be
 | defined here if desired.  It is currently not possible for such a trap
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index bde2500..3bb7d8f 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -43,7 +43,7 @@ these four paragraphs for those parts of this code that are retained.
 #endif
 
 #include <inttypes.h>
-#include "config.h"
+#include "config-host.h"
 
 /*----------------------------------------------------------------------------
 | Each of the following `typedef's defines the most convenient type that holds
@@ -68,12 +68,6 @@ typedef int64_t int64;
 #define LIT64( a ) a##LL
 #define INLINE static inline
 
-#if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-#define SNAN_BIT_IS_ONE		1
-#else
-#define SNAN_BIT_IS_ONE		0
-#endif
-
 #define STATUS_PARAM , float_status *status
 #define STATUS(field) status->field
 #define STATUS_VAR , status
@@ -142,6 +136,7 @@ typedef struct {
     uint64_t low, high;
 #endif
 } float128;
+#define make_float128(high_, low_) ((float128) { .high = high_, .low = low_ })
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE floating-point underflow tininess-detection mode.
@@ -248,13 +243,7 @@ float16 float16_maybe_silence_nan( float16 );
 /*----------------------------------------------------------------------------
 | The pattern for a default generated half-precision NaN.
 *----------------------------------------------------------------------------*/
-#if defined(TARGET_ARM)
-#define float16_default_nan make_float16(0x7E00)
-#elif SNAN_BIT_IS_ONE
-#define float16_default_nan make_float16(0x7DFF)
-#else
-#define float16_default_nan make_float16(0xFE00)
-#endif
+extern const float16 float16_default_nan;
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE single-precision conversion routines.
@@ -357,15 +346,7 @@ INLINE float32 float32_set_sign(float32 a, int sign)
 /*----------------------------------------------------------------------------
 | The pattern for a default generated single-precision NaN.
 *----------------------------------------------------------------------------*/
-#if defined(TARGET_SPARC)
-#define float32_default_nan make_float32(0x7FFFFFFF)
-#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
-#define float32_default_nan make_float32(0x7FC00000)
-#elif SNAN_BIT_IS_ONE
-#define float32_default_nan make_float32(0x7FBFFFFF)
-#else
-#define float32_default_nan make_float32(0xFFC00000)
-#endif
+extern const float32 float32_default_nan;
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE double-precision conversion routines.
@@ -470,15 +451,7 @@ INLINE float64 float64_set_sign(float64 a, int sign)
 /*----------------------------------------------------------------------------
 | The pattern for a default generated double-precision NaN.
 *----------------------------------------------------------------------------*/
-#if defined(TARGET_SPARC)
-#define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF ))
-#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
-#define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 ))
-#elif SNAN_BIT_IS_ONE
-#define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
-#else
-#define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
-#endif
+extern const float64 float64_default_nan;
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE extended double-precision conversion routines.
@@ -561,17 +534,9 @@ INLINE int floatx80_is_any_nan(floatx80 a)
 #define floatx80_infinity make_floatx80(0x7fff, 0x8000000000000000LL)
 
 /*----------------------------------------------------------------------------
-| The pattern for a default generated extended double-precision NaN.  The
-| `high' and `low' values hold the most- and least-significant bits,
-| respectively.
+| The pattern for a default generated extended double-precision NaN.
 *----------------------------------------------------------------------------*/
-#if SNAN_BIT_IS_ONE
-#define floatx80_default_nan_high 0x7FFF
-#define floatx80_default_nan_low  LIT64( 0xBFFFFFFFFFFFFFFF )
-#else
-#define floatx80_default_nan_high 0xFFFF
-#define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
-#endif
+extern const floatx80 floatx80_default_nan;
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE quadruple-precision conversion routines.
@@ -648,15 +613,8 @@ INLINE int float128_is_any_nan(float128 a)
 }
 
 /*----------------------------------------------------------------------------
-| The pattern for a default generated quadruple-precision NaN.  The `high' and
-| `low' values hold the most- and least-significant bits, respectively.
+| The pattern for a default generated quadruple-precision NaN.
 *----------------------------------------------------------------------------*/
-#if SNAN_BIT_IS_ONE
-#define float128_default_nan_high LIT64( 0x7FFF7FFFFFFFFFFF )
-#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
-#else
-#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
-#define float128_default_nan_low  LIT64( 0x0000000000000000 )
-#endif
+extern const float128 float128_default_nan;
 
 #endif /* !SOFTFLOAT_H */
commit 332ae28dad2d4f155e1ad82bf89a605c2b2710ba
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Jul 28 12:10:28 2011 +0200

    move WORDS_ALIGNED to qemu-common.h
    
    This is not a CPU interface, and a configure test would not be too
    precise.  So just add it to qemu-common.h.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/cpu-common.h b/cpu-common.h
index 44b04b3..16c9f4f 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -3,10 +3,6 @@
 
 /* CPU interfaces that are target indpendent.  */
 
-#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__) || defined(__ia64__)
-#define WORDS_ALIGNED
-#endif
-
 #ifdef TARGET_PHYS_ADDR_BITS
 #include "targphys.h"
 #endif
diff --git a/qemu-common.h b/qemu-common.h
index 391fadd..1e3c665 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -5,6 +5,10 @@
 #include "compiler.h"
 #include "config-host.h"
 
+#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__) || defined(__ia64__)
+#define WORDS_ALIGNED
+#endif
+
 #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
 
 typedef struct QEMUTimer QEMUTimer;
commit 3d3b8303c6f83b9b245bc774af530a6403cc4ce6
Author: wayne <xiawenc at linux.vnet.ibm.com>
Date:   Wed Jul 27 18:04:55 2011 +0800

    showing a splash picture when start
    
        Added options to let qemu transfer two configuration files to bios:
    "bootsplash.bmp" and "etc/boot-menu-wait", which could be specified by command
        -boot splash=P,splash-time=T
    P is jpg/bmp file name or an absolute path, T have a max value of 0xffff, unit
    is ms. With these two options, if user invoke qemu with menu=on option, then
    a splash picture would be showed in a given time. For example:
        qemu -boot menu=on,splash=/root/boot.bmp,splash-time=5000
    would make boot.bmp shown as a brand with 5 seconds in the booting up process.
    This feature need the new seabios's support, which could be got from git.
    
    Signed-off-by: Wayne Xia <xiawenc at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
index 34e7526..a29db90 100644
--- a/hw/fw_cfg.c
+++ b/hw/fw_cfg.c
@@ -26,6 +26,7 @@
 #include "isa.h"
 #include "fw_cfg.h"
 #include "sysbus.h"
+#include "qemu-error.h"
 
 /* debug firmware config */
 //#define DEBUG_FW_CFG
@@ -56,6 +57,143 @@ struct FWCfgState {
     Notifier machine_ready;
 };
 
+#define JPG_FILE 0
+#define BMP_FILE 1
+
+static FILE *probe_splashfile(char *filename, int *file_sizep, int *file_typep)
+{
+    FILE *fp = NULL;
+    int fop_ret;
+    int file_size;
+    int file_type = -1;
+    unsigned char buf[2] = {0, 0};
+    unsigned int filehead_value = 0;
+    int bmp_bpp;
+
+    fp = fopen(filename, "rb");
+    if (fp == NULL) {
+        error_report("failed to open file '%s'.", filename);
+        return fp;
+    }
+    /* 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;
+    }
+    /* check magic ID */
+    fseek(fp, 0L, SEEK_SET);
+    fop_ret = fread(buf, 1, 2, fp);
+    filehead_value = (buf[0] + (buf[1] << 8)) & 0xffff;
+    if (filehead_value == 0xd8ff) {
+        file_type = JPG_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;
+    }
+    /* 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;
+        if (bmp_bpp != 24) {
+            error_report("only 24bpp bmp file is supported.");
+            fclose(fp);
+            fp = NULL;
+            return fp;
+        }
+    }
+    /* return values */
+    *file_sizep = file_size;
+    *file_typep = file_type;
+    return fp;
+}
+
+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;
+    int file_size;
+    int file_type = -1;
+    const char *temp;
+
+    /* get user configuration */
+    QemuOptsList *plist = qemu_find_opts("boot-opts");
+    QemuOpts *opts = QTAILQ_FIRST(&plist->head);
+    if (opts != NULL) {
+        temp = qemu_opt_get(opts, "splash");
+        if (temp != NULL) {
+            boot_splash_filename = temp;
+        }
+        temp = qemu_opt_get(opts, "splash-time");
+        if (temp != NULL) {
+            p = (char *)temp;
+            boot_splash_time = strtol(p, (char **)&p, 10);
+        }
+    }
+
+    /* insert splash time if user configurated */
+    if (boot_splash_time >= 0) {
+        /* validate the input */
+        if (boot_splash_time > 0xffff) {
+            error_report("splash time is big than 65535, force it to 65535.");
+            boot_splash_time = 0xffff;
+        }
+        /* use little endian format */
+        qemu_extra_params_fw[0] = (uint8_t)(boot_splash_time & 0xff);
+        qemu_extra_params_fw[1] = (uint8_t)((boot_splash_time >> 8) & 0xff);
+        fw_cfg_add_file(s, "etc/boot-menu-wait", qemu_extra_params_fw, 2);
+    }
+
+    /* insert splash file if user configurated */
+    if (boot_splash_filename != NULL) {
+        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, boot_splash_filename);
+        if (filename == NULL) {
+            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) {
+            qemu_free(filename);
+            return;
+        }
+        /* loading file data */
+        if (boot_splash_filedata != NULL) {
+            qemu_free(boot_splash_filedata);
+        }
+        boot_splash_filedata = qemu_malloc(file_size);
+        boot_splash_filedata_size = file_size;
+        fseek(fp, 0L, SEEK_SET);
+        fop_ret = fread(boot_splash_filedata, 1, file_size, fp);
+        fclose(fp);
+        /* insert data */
+        if (file_type == JPG_FILE) {
+            fw_cfg_add_file(s, "bootsplash.jpg",
+                    boot_splash_filedata, boot_splash_filedata_size);
+        } else {
+            fw_cfg_add_file(s, "bootsplash.bmp",
+                    boot_splash_filedata, boot_splash_filedata_size);
+        }
+        qemu_free(filename);
+    }
+}
+
 static void fw_cfg_write(FWCfgState *s, uint8_t value)
 {
     int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL);
@@ -352,7 +490,7 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
     fw_cfg_add_i16(s, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
     fw_cfg_add_i16(s, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
     fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu);
-
+    fw_cfg_bootsplash(s);
 
     s->machine_ready.notify = fw_cfg_machine_ready;
     qemu_add_machine_init_done_notifier(&s->machine_ready);
diff --git a/qemu-config.c b/qemu-config.c
index b2ec40b..1eb6b9a 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -480,6 +480,32 @@ static QemuOptsList qemu_machine_opts = {
     },
 };
 
+QemuOptsList qemu_boot_opts = {
+    .name = "boot-opts",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_boot_opts.head),
+    .desc = {
+        /* the three names below are not used now */
+        {
+            .name = "order",
+            .type = QEMU_OPT_STRING,
+        }, {
+            .name = "once",
+            .type = QEMU_OPT_STRING,
+        }, {
+            .name = "menu",
+            .type = QEMU_OPT_STRING,
+        /* following are really used */
+        }, {
+            .name = "splash",
+            .type = QEMU_OPT_STRING,
+        }, {
+            .name = "splash-time",
+            .type = QEMU_OPT_STRING,
+        },
+        { /*End of list */ }
+    },
+};
+
 static QemuOptsList *vm_config_groups[32] = {
     &qemu_drive_opts,
     &qemu_chardev_opts,
@@ -495,6 +521,7 @@ static QemuOptsList *vm_config_groups[32] = {
 #endif
     &qemu_option_rom_opts,
     &qemu_machine_opts,
+    &qemu_boot_opts,
     NULL,
 };
 
diff --git a/qemu-options.hx b/qemu-options.hx
index 1d57f64..c77f868 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -303,10 +303,13 @@ ETEXI
 
 DEF("boot", HAS_ARG, QEMU_OPTION_boot,
     "-boot [order=drives][,once=drives][,menu=on|off]\n"
-    "                'drives': floppy (a), hard disk (c), CD-ROM (d), network (n)\n",
+    "      [,splash=sp_name][,splash-time=sp_time]\n"
+    "                'drives': floppy (a), hard disk (c), CD-ROM (d), network (n)\n"
+    "                'sp_name': the file's name that would be passed to bios as logo picture, if menu=on\n"
+    "                'sp_time': the period that splash picture last if menu=on, unit is ms\n",
     QEMU_ARCH_ALL)
 STEXI
- at item -boot [order=@var{drives}][,once=@var{drives}][,menu=on|off]
+ at item -boot [order=@var{drives}][,once=@var{drives}][,menu=on|off][,splash=@var{sp_name}][,splash-time=@var{sp_time}]
 @findex -boot
 Specify boot order @var{drives} as a string of drive letters. Valid
 drive letters depend on the target achitecture. The x86 PC uses: a, b
@@ -318,11 +321,20 @@ particular boot order only on the first startup, specify it via
 Interactive boot menus/prompts can be enabled via @option{menu=on} as far
 as firmware/BIOS supports them. The default is non-interactive boot.
 
+A splash picture could be passed to bios, enabling user to show it as logo,
+when option splash=@var{sp_name} is given and menu=on, If firmware/BIOS
+supports them. Currently Seabios for X86 system support it.
+limitation: The splash file could be a jpeg file or a BMP file in 24 BPP
+format(true color). The resolution should be supported by the SVGA mode, so
+the recommended is 320x240, 640x480, 800x640.
+
 @example
 # try to boot from network first, then from hard disk
 qemu -boot order=nc
 # boot from CD-ROM first, switch back to default order after reboot
 qemu -boot once=d
+# boot with a splash picture for 5 seconds.
+qemu -boot menu=on,splash=/root/boot.bmp,splash-time=5000
 @end example
 
 Note: The legacy format '-boot @var{drives}' is still supported but its
diff --git a/sysemu.h b/sysemu.h
index d3013f5..bd830e5 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -123,6 +123,9 @@ extern int no_shutdown;
 extern int semihosting_enabled;
 extern int old_param;
 extern int boot_menu;
+extern uint8_t *boot_splash_filedata;
+extern int boot_splash_filedata_size;
+extern uint8_t qemu_extra_params_fw[2];
 extern QEMUClock *rtc_clock;
 
 #define MAX_NODES 64
diff --git a/vl.c b/vl.c
index 4b6688b..a3d8d77 100644
--- a/vl.c
+++ b/vl.c
@@ -228,6 +228,9 @@ int ctrl_grab = 0;
 unsigned int nb_prom_envs = 0;
 const char *prom_envs[MAX_PROM_ENVS];
 int boot_menu;
+uint8_t *boot_splash_filedata;
+int boot_splash_filedata_size;
+uint8_t qemu_extra_params_fw[2];
 
 typedef struct FWBootEntry FWBootEntry;
 
@@ -293,6 +296,14 @@ static struct {
     { .driver = "qxl-vga",              .flag = &default_vga       },
 };
 
+static void res_free(void)
+{
+    if (boot_splash_filedata != NULL) {
+        qemu_free(boot_splash_filedata);
+        boot_splash_filedata = NULL;
+    }
+}
+
 static int default_driver_check(QemuOpts *opts, void *opaque)
 {
     const char *driver = qemu_opt_get(opts, "driver");
@@ -2330,7 +2341,8 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_boot:
                 {
                     static const char * const params[] = {
-                        "order", "once", "menu", NULL
+                        "order", "once", "menu",
+                        "splash", "splash-time", NULL
                     };
                     char buf[sizeof(boot_devices)];
                     char *standard_boot_devices;
@@ -2373,6 +2385,8 @@ int main(int argc, char **argv, char **envp)
                                 exit(1);
                             }
                         }
+                        qemu_opts_parse(qemu_find_opts("boot-opts"),
+                                        optarg, 0);
                     }
                 }
                 break;
@@ -3335,6 +3349,7 @@ int main(int argc, char **argv, char **envp)
     main_loop();
     quit_timers();
     net_cleanup();
+    res_free();
 
     return 0;
 }
commit 6da48311bbd884da4d0a4ae03b0fc7a78981a5f4
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:22 2011 +0300

    usb-ohci: convert to MemoryRegion
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 8491d59..337b250 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -62,7 +62,7 @@ typedef struct OHCIPort {
 typedef struct {
     USBBus bus;
     qemu_irq irq;
-    int mem;
+    MemoryRegion mem;
     int num_ports;
     const char *name;
 
@@ -1440,13 +1440,13 @@ static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
     return;
 }
 
-static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr)
+static uint64_t ohci_mem_read(void *opaque,
+                              target_phys_addr_t addr,
+                              unsigned size)
 {
-    OHCIState *ohci = ptr;
+    OHCIState *ohci = opaque;
     uint32_t retval;
 
-    addr &= 0xff;
-
     /* Only aligned reads are allowed on OHCI */
     if (addr & 3) {
         fprintf(stderr, "usb-ohci: Mis-aligned read\n");
@@ -1563,11 +1563,12 @@ static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr)
     return retval;
 }
 
-static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val)
+static void ohci_mem_write(void *opaque,
+                           target_phys_addr_t addr,
+                           uint64_t val,
+                           unsigned size)
 {
-    OHCIState *ohci = ptr;
-
-    addr &= 0xff;
+    OHCIState *ohci = opaque;
 
     /* Only aligned reads are allowed on OHCI */
     if (addr & 3) {
@@ -1697,18 +1698,10 @@ static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
     }
 }
 
-/* Only dword reads are defined on OHCI register space */
-static CPUReadMemoryFunc * const ohci_readfn[3]={
-    ohci_mem_read,
-    ohci_mem_read,
-    ohci_mem_read
-};
-
-/* Only dword writes are defined on OHCI register space */
-static CPUWriteMemoryFunc * const ohci_writefn[3]={
-    ohci_mem_write,
-    ohci_mem_write,
-    ohci_mem_write
+static const MemoryRegionOps ohci_mem_ops = {
+    .read = ohci_mem_read,
+    .write = ohci_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static USBPortOps ohci_port_ops = {
@@ -1764,8 +1757,7 @@ static int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
         }
     }
 
-    ohci->mem = cpu_register_io_memory(ohci_readfn, ohci_writefn, ohci,
-                                       DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&ohci->mem, &ohci_mem_ops, ohci, "ohci", 256);
     ohci->localmem_base = localmem_base;
 
     ohci->name = dev->info->name;
@@ -1799,7 +1791,7 @@ static int usb_ohci_initfn_pci(struct PCIDevice *dev)
     ohci->state.irq = ohci->pci_dev.irq[0];
 
     /* TODO: avoid cast below by using dev */
-    pci_register_bar_simple(&ohci->pci_dev, 0, 256, 0, ohci->state.mem);
+    pci_register_bar_region(&ohci->pci_dev, 0, 0, &ohci->state.mem);
     return 0;
 }
 
@@ -1822,7 +1814,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(dev, 0x1000, s->ohci.mem);
+    sysbus_init_mmio_region(dev, &s->ohci.mem);
 
     return 0;
 }
commit ec3bb837a21a7d32d3dcb010e955991f5784c1e8
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:21 2011 +0300

    sysbus: add MemoryRegion based memory management API
    
    Allow registering sysbus device memory using a MemoryRegion.  Once all users
    are converted, sysbus_init_mmio() and sysbus_init_mmio_cb() will be removed.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/sysbus.c b/hw/sysbus.c
index 2e22be7..ea442ac 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -19,6 +19,7 @@
 
 #include "sysbus.h"
 #include "monitor.h"
+#include "exec-memory.h"
 
 static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
 static char *sysbus_get_fw_dev_path(DeviceState *dev);
@@ -49,11 +50,20 @@ 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.  */
-        cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size,
-                                     IO_MEM_UNASSIGNED);
+        if (dev->mmio[n].memory) {
+            memory_region_del_subregion(get_system_memory(),
+                                        dev->mmio[n].memory);
+        } else {
+            cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size,
+                                         IO_MEM_UNASSIGNED);
+        }
     }
     dev->mmio[n].addr = addr;
-    if (dev->mmio[n].cb) {
+    if (dev->mmio[n].memory) {
+        memory_region_add_subregion(get_system_memory(),
+                                    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,
@@ -107,6 +117,17 @@ void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
     dev->mmio[n].cb = cb;
 }
 
+void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory)
+{
+    int n;
+
+    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;
+}
+
 void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size)
 {
     pio_addr_t i;
diff --git a/hw/sysbus.h b/hw/sysbus.h
index 4e8cb16..5f62e2d 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -4,6 +4,7 @@
 /* Devices attached directly to the main system bus.  */
 
 #include "qdev.h"
+#include "memory.h"
 
 #define QDEV_MAX_MMIO 32
 #define QDEV_MAX_PIO 32
@@ -23,6 +24,7 @@ struct SysBusDevice {
         target_phys_addr_t size;
         mmio_mapfunc cb;
         ram_addr_t iofunc;
+        MemoryRegion *memory;
     } mmio[QDEV_MAX_MMIO];
     int num_pio;
     pio_addr_t pio[QDEV_MAX_PIO];
@@ -46,6 +48,7 @@ void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size,
                       ram_addr_t iofunc);
 void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
                             mmio_mapfunc cb);
+void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory);
 void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p);
 void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target);
 void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size);
commit 79ff8cb0df5f3f7ec818690f7ad5bdc03859525d
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:20 2011 +0300

    pci: add MemoryRegion based BAR management API
    
    Allow registering a BAR using a MemoryRegion.  Once all users are converted,
    pci_register_bar() and pci_register_bar_simple() will be removed.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pci.c b/hw/pci.c
index cf16f3b..36db58b 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -844,10 +844,15 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
         if (r->type == PCI_BASE_ADDRESS_SPACE_IO) {
             isa_unassign_ioport(r->addr, r->filtered_size);
         } else {
-            cpu_register_physical_memory(pci_to_cpu_addr(pci_dev->bus,
-                                                         r->addr),
-                                         r->filtered_size,
-                                         IO_MEM_UNASSIGNED);
+            if (r->memory) {
+                memory_region_del_subregion(pci_dev->bus->address_space,
+                                            r->memory);
+            } else {
+                cpu_register_physical_memory(pci_to_cpu_addr(pci_dev->bus,
+                                                             r->addr),
+                                             r->filtered_size,
+                                             IO_MEM_UNASSIGNED);
+            }
         }
     }
 }
@@ -893,6 +898,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     r->type = type;
     r->map_func = map_func;
     r->ram_addr = IO_MEM_UNASSIGNED;
+    r->memory = NULL;
 
     wmask = ~(size - 1);
     addr = pci_bar(pci_dev, region_num);
@@ -918,6 +924,16 @@ static void pci_simple_bar_mapfunc(PCIDevice *pci_dev, int region_num,
                                  pci_dev->io_regions[region_num].ram_addr);
 }
 
+static void pci_simple_bar_mapfunc_region(PCIDevice *pci_dev, int region_num,
+                                          pcibus_t addr, pcibus_t size,
+                                          int type)
+{
+    memory_region_add_subregion_overlap(pci_dev->bus->address_space,
+                                        addr,
+                                        pci_dev->io_regions[region_num].memory,
+                                        1);
+}
+
 void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
                              pcibus_t size,  uint8_t attr, ram_addr_t ram_addr)
 {
@@ -927,6 +943,15 @@ void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
     pci_dev->io_regions[region_num].ram_addr = ram_addr;
 }
 
+void pci_register_bar_region(PCIDevice *pci_dev, int region_num,
+                             uint8_t attr, MemoryRegion *memory)
+{
+    pci_register_bar(pci_dev, region_num, memory_region_size(memory),
+                     PCI_BASE_ADDRESS_SPACE_MEMORY | attr,
+                     pci_simple_bar_mapfunc_region);
+    pci_dev->io_regions[region_num].memory = memory;
+}
+
 static void pci_bridge_filter(PCIDevice *d, pcibus_t *addr, pcibus_t *size,
                               uint8_t type)
 {
@@ -1065,10 +1090,16 @@ static void pci_update_mappings(PCIDevice *d)
                     isa_unassign_ioport(r->addr, r->filtered_size);
                 }
             } else {
-                cpu_register_physical_memory(pci_to_cpu_addr(d->bus, r->addr),
-                                             r->filtered_size,
-                                             IO_MEM_UNASSIGNED);
-                qemu_unregister_coalesced_mmio(r->addr, r->filtered_size);
+                if (r->memory) {
+                    memory_region_del_subregion(d->bus->address_space,
+                                                r->memory);
+                } else {
+                    cpu_register_physical_memory(pci_to_cpu_addr(d->bus,
+                                                                 r->addr),
+                                                 r->filtered_size,
+                                                 IO_MEM_UNASSIGNED);
+                    qemu_unregister_coalesced_mmio(r->addr, r->filtered_size);
+                }
             }
         }
         r->addr = new_addr;
diff --git a/hw/pci.h b/hw/pci.h
index cfeb042..c51156d 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -94,6 +94,7 @@ typedef struct PCIIORegion {
     uint8_t type;
     PCIMapIORegionFunc *map_func;
     ram_addr_t ram_addr;
+    MemoryRegion *memory;
 } PCIIORegion;
 
 #define PCI_ROM_SLOT 6
@@ -204,6 +205,8 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
                             PCIMapIORegionFunc *map_func);
 void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
                              pcibus_t size, uint8_t attr, ram_addr_t ram_addr);
+void pci_register_bar_region(PCIDevice *pci_dev, int region_num,
+                             uint8_t attr, MemoryRegion *memory);
 
 int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
                        uint8_t offset, uint8_t size);
commit 1e39101c649a008462db1ac1d027c62870454d1f
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:19 2011 +0300

    pci: pass address space to pci bus when created
    
    This is now done sloppily, via get_system_memory().  Eventually callers
    will be converted to stop using that.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 974c87a..8b9939c 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -34,6 +34,7 @@
 #include "rwhandler.h"
 #include "apb_pci.h"
 #include "sysemu.h"
+#include "exec-memory.h"
 
 /* debug APB */
 //#define DEBUG_APB
@@ -346,6 +347,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
 
     d->bus = pci_register_bus(&d->busdev.qdev, "pci",
                                          pci_apb_set_irq, pci_pbm_map_irq, d,
+                                         get_system_memory(),
                                          0, 32);
     pci_bus_set_mem_base(d->bus, mem_base);
 
diff --git a/hw/bonito.c b/hw/bonito.c
index e8c57a3..5f62dda 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -42,6 +42,7 @@
 #include "mips.h"
 #include "pci_host.h"
 #include "sysemu.h"
+#include "exec-memory.h"
 
 //#define DEBUG_BONITO
 
@@ -773,7 +774,8 @@ PCIBus *bonito_init(qemu_irq *pic)
     dev = qdev_create(NULL, "Bonito-pcihost");
     pcihost = FROM_SYSBUS(BonitoState, sysbus_from_qdev(dev));
     b = pci_register_bus(&pcihost->busdev.qdev, "pci", pci_bonito_set_irq,
-                         pci_bonito_map_irq, pic, 0x28, 32);
+                         pci_bonito_map_irq, pic, get_system_memory(),
+                         0x28, 32);
     pcihost->bus = b;
     qdev_init_nofail(dev);
 
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index cee07e0..da67cf9 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -61,7 +61,8 @@ static void pci_grackle_reset(void *opaque)
 {
 }
 
-PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
+PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
+                         MemoryRegion *address_space)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -74,7 +75,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                          pci_grackle_set_irq,
                                          pci_grackle_map_irq,
-                                         pic, 0, 4);
+                                         pic, address_space, 0, 4);
 
     pci_create_simple(d->host_state.bus, 0, "grackle");
 
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 8e1f6a0..65e63dd 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -27,6 +27,7 @@
 #include "pci.h"
 #include "pci_host.h"
 #include "pc.h"
+#include "exec-memory.h"
 
 //#define DEBUG
 
@@ -1092,7 +1093,8 @@ PCIBus *gt64120_register(qemu_irq *pic)
     d = FROM_SYSBUS(GT64120State, s);
     d->pci.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                   gt64120_pci_set_irq, gt64120_pci_map_irq,
-                                  pic, PCI_DEVFN(18, 0), 4);
+                                  pic, get_system_memory(),
+                                  PCI_DEVFN(18, 0), 4);
     d->ISD_handle = cpu_register_io_memory(gt64120_read, gt64120_write, d,
                                            DEVICE_NATIVE_ENDIAN);
 
diff --git a/hw/pc.h b/hw/pc.h
index 40684f4..a2de0fe 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -178,7 +178,9 @@ int pcspk_audio_init(qemu_irq *pic);
 struct PCII440FXState;
 typedef struct PCII440FXState PCII440FXState;
 
-PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, qemu_irq *pic, ram_addr_t ram_size);
+PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn,
+                    qemu_irq *pic, MemoryRegion *address_space,
+                    ram_addr_t ram_size);
 void i440fx_init_memory_mappings(PCII440FXState *d);
 
 /* piix4.c */
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index f2d0476..2b9c2b1 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -128,7 +128,8 @@ static void pc_init1(MemoryRegion *system_memory,
     isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
 
     if (pci_enabled) {
-        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
+        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq,
+                              system_memory, ram_size);
     } else {
         pci_bus = NULL;
         i440fx_state = NULL;
diff --git a/hw/pci.c b/hw/pci.c
index b904a4e..cf16f3b 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -263,11 +263,14 @@ int pci_find_domain(const PCIBus *bus)
 }
 
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
-                         const char *name, uint8_t devfn_min)
+                         const char *name,
+                         MemoryRegion *address_space,
+                         uint8_t devfn_min)
 {
     qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name);
     assert(PCI_FUNC(devfn_min) == 0);
     bus->devfn_min = devfn_min;
+    bus->address_space = address_space;
 
     /* host bridge */
     QLIST_INIT(&bus->child);
@@ -276,13 +279,14 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
     vmstate_register(NULL, -1, &vmstate_pcibus, bus);
 }
 
-PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min)
+PCIBus *pci_bus_new(DeviceState *parent, const char *name,
+                    MemoryRegion *address_space, uint8_t devfn_min)
 {
     PCIBus *bus;
 
     bus = qemu_mallocz(sizeof(*bus));
     bus->qbus.qdev_allocated = 1;
-    pci_bus_new_inplace(bus, parent, name, devfn_min);
+    pci_bus_new_inplace(bus, parent, name, address_space, devfn_min);
     return bus;
 }
 
@@ -310,11 +314,13 @@ void pci_bus_set_mem_base(PCIBus *bus, target_phys_addr_t base)
 
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                         void *irq_opaque, uint8_t devfn_min, int nirq)
+                         void *irq_opaque,
+                         MemoryRegion *address_space,
+                         uint8_t devfn_min, int nirq)
 {
     PCIBus *bus;
 
-    bus = pci_bus_new(parent, name, devfn_min);
+    bus = pci_bus_new(parent, name, address_space, devfn_min);
     pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq);
     return bus;
 }
diff --git a/hw/pci.h b/hw/pci.h
index c220745..cfeb042 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -5,6 +5,7 @@
 #include "qobject.h"
 
 #include "qdev.h"
+#include "memory.h"
 
 /* PCI includes legacy ISA access.  */
 #include "isa.h"
@@ -233,15 +234,20 @@ typedef enum {
 typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
                               PCIHotplugState state);
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
-                         const char *name, uint8_t devfn_min);
-PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min);
+                         const char *name,
+                         MemoryRegion *address_space,
+                         uint8_t devfn_min);
+PCIBus *pci_bus_new(DeviceState *parent, const char *name,
+                    MemoryRegion *address_space, uint8_t devfn_min);
 void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                   void *irq_opaque, int nirq);
 int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
 void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                         void *irq_opaque, uint8_t devfn_min, int nirq);
+                         void *irq_opaque,
+                         MemoryRegion *address_space,
+                         uint8_t devfn_min, int nirq);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
diff --git a/hw/pci_host.h b/hw/pci_host.h
index 0a58595..05dcb66 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -35,6 +35,7 @@ struct PCIHostState {
     SysBusDevice busdev;
     ReadWriteHandler conf_handler;
     ReadWriteHandler data_handler;
+    MemoryRegion *address_space;
     uint32_t config_reg;
     PCIBus *bus;
 };
diff --git a/hw/pci_internals.h b/hw/pci_internals.h
index fbe1866..c3a463a 100644
--- a/hw/pci_internals.h
+++ b/hw/pci_internals.h
@@ -25,6 +25,7 @@ struct PCIBus {
     PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX];
     PCIDevice *parent_dev;
     target_phys_addr_t mem_base;
+    MemoryRegion *address_space;
 
     QLIST_HEAD(, PCIBus) child; /* this will be replaced by qdev later */
     QLIST_ENTRY(PCIBus) sibling;/* this will be replaced by qdev later */
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index d08b31a..80d6665 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -241,7 +241,9 @@ static int i440fx_initfn(PCIDevice *dev)
 static PCIBus *i440fx_common_init(const char *device_name,
                                   PCII440FXState **pi440fx_state,
                                   int *piix3_devfn,
-                                  qemu_irq *pic, ram_addr_t ram_size)
+                                  qemu_irq *pic,
+                                  MemoryRegion *address_space,
+                                  ram_addr_t ram_size)
 {
     DeviceState *dev;
     PCIBus *b;
@@ -251,7 +253,8 @@ static PCIBus *i440fx_common_init(const char *device_name,
 
     dev = qdev_create(NULL, "i440FX-pcihost");
     s = FROM_SYSBUS(I440FXState, sysbus_from_qdev(dev));
-    b = pci_bus_new(&s->busdev.qdev, NULL, 0);
+    s->address_space = address_space;
+    b = pci_bus_new(&s->busdev.qdev, NULL, s->address_space, 0);
     s->bus = b;
     qdev_init_nofail(dev);
 
@@ -288,11 +291,13 @@ static PCIBus *i440fx_common_init(const char *device_name,
 }
 
 PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
-                    qemu_irq *pic, ram_addr_t ram_size)
+                    qemu_irq *pic, MemoryRegion *address_space,
+                    ram_addr_t ram_size)
 {
     PCIBus *b;
 
-    b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, pic, ram_size);
+    b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, pic,
+                           address_space, ram_size);
     return b;
 }
 
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index 299473c..15c24f6 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -24,6 +24,7 @@
 #include "ppc4xx.h"
 #include "pci.h"
 #include "pci_host.h"
+#include "exec-memory.h"
 
 #undef DEBUG
 #ifdef DEBUG
@@ -345,7 +346,9 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
     controller->pci_state.bus = pci_register_bus(NULL, "pci",
                                                  ppc4xx_pci_set_irq,
                                                  ppc4xx_pci_map_irq,
-                                                 pci_irqs, 0, 4);
+                                                 pci_irqs,
+                                                 get_system_memory(),
+                                                 0, 4);
 
     controller->pci_dev = pci_register_device(controller->pci_state.bus,
                                               "host bridge", sizeof(PCIDevice),
diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h
index 68dade7..6fad20a 100644
--- a/hw/ppc_mac.h
+++ b/hw/ppc_mac.h
@@ -25,6 +25,8 @@
 #if !defined(__PPC_MAC_H__)
 #define __PPC_MAC_H__
 
+#include "memory.h"
+
 /* SMP is not enabled, for now */
 #define MAX_CPUS 1
 
@@ -52,11 +54,12 @@ qemu_irq *heathrow_pic_init(int *pmem_index,
                             int nb_cpus, qemu_irq **irqs);
 
 /* Grackle PCI */
-PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic);
+PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
+                         MemoryRegion *address_space);
 
 /* UniNorth PCI */
-PCIBus *pci_pmac_init(qemu_irq *pic);
-PCIBus *pci_pmac_u3_init(qemu_irq *pic);
+PCIBus *pci_pmac_init(qemu_irq *pic, MemoryRegion *address_space);
+PCIBus *pci_pmac_u3_init(qemu_irq *pic, MemoryRegion *address_space);
 
 /* Mac NVRAM */
 typedef struct MacIONVRAMState MacIONVRAMState;
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 5bce709..2c0fae8 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -67,6 +67,7 @@
 #include "kvm_ppc.h"
 #include "hw/usb.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 #define MAX_IDE_BUS 2
 #define CFG_ADDR 0xf0000510
@@ -317,10 +318,10 @@ static void ppc_core99_init (ram_addr_t ram_size,
     pic = openpic_init(NULL, &pic_mem_index, smp_cpus, openpic_irqs, NULL);
     if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) {
         /* 970 gets a U3 bus */
-        pci_bus = pci_pmac_u3_init(pic);
+        pci_bus = pci_pmac_u3_init(pic, get_system_memory());
         machine_arch = ARCH_MAC99_U3;
     } else {
-        pci_bus = pci_pmac_init(pic);
+        pci_bus = pci_pmac_init(pic, get_system_memory());
         machine_arch = ARCH_MAC99;
     }
     /* init basic PC hardware */
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 20cd8e1..585afd6 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -43,6 +43,7 @@
 #include "kvm.h"
 #include "kvm_ppc.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 #define MAX_IDE_BUS 2
 #define CFG_ADDR 0xf0000510
@@ -233,7 +234,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
         hw_error("Only 6xx bus is supported on heathrow machine\n");
     }
     pic = heathrow_pic_init(&pic_mem_index, 1, heathrow_irqs);
-    pci_bus = pci_grackle_init(0xfec00000, pic);
+    pci_bus = pci_grackle_init(0xfec00000, pic, get_system_memory());
     pci_vga_init(pci_bus);
 
     escc_mem_index = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0],
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 0e9cfc2..91ebe07 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -38,6 +38,7 @@
 #include "loader.h"
 #include "mc146818rtc.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 //#define HARD_DEBUG_PPC_IO
 //#define DEBUG_PPC_IO
@@ -648,7 +649,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
         hw_error("Only 6xx bus is supported on PREP machine\n");
     }
     i8259 = i8259_init(first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
-    pci_bus = pci_prep_init(i8259);
+    pci_bus = pci_prep_init(i8259, get_system_memory());
     /* Hmm, prep has no pci-isa bridge ??? */
     isa_bus_new(NULL);
     isa_bus_irqs(i8259);
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index fc11af4..1344539 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -274,12 +274,15 @@ static void e500_pci_map(SysBusDevice *dev, target_phys_addr_t base)
                                  s->reg);
 }
 
+#include "exec-memory.h"
+
 static int e500_pcihost_initfn(SysBusDevice *dev)
 {
     PCIHostState *h;
     PPCE500PCIState *s;
     PCIBus *b;
     int i;
+    MemoryRegion *address_space = get_system_memory();
 
     h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
     s = DO_UPCAST(PPCE500PCIState, pci_state, h);
@@ -289,7 +292,8 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
     }
 
     b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, mpc85xx_pci_set_irq,
-                         mpc85xx_pci_map_irq, s->irq, PCI_DEVFN(0x11, 0), 4);
+                         mpc85xx_pci_map_irq, s->irq, address_space,
+                         PCI_DEVFN(0x11, 0), 4);
     s->pci_state.bus = b;
 
     pci_create_simple(b, 0, "e500-host-bridge");
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index f88b825..da02f0e 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -110,7 +110,7 @@ static void prep_set_irq(void *opaque, int irq_num, int level)
     qemu_set_irq(pic[(irq_num & 1) ? 11 : 9] , level);
 }
 
-PCIBus *pci_prep_init(qemu_irq *pic)
+PCIBus *pci_prep_init(qemu_irq *pic, MemoryRegion *address_space)
 {
     PREPPCIState *s;
     PCIDevice *d;
@@ -118,7 +118,8 @@ PCIBus *pci_prep_init(qemu_irq *pic)
 
     s = qemu_mallocz(sizeof(PREPPCIState));
     s->bus = pci_register_bus(NULL, "pci",
-                              prep_set_irq, prep_map_irq, pic, 0, 4);
+                              prep_set_irq, prep_map_irq, pic,
+                              address_space, 0, 4);
 
     pci_host_conf_register_ioport(0xcf8, s);
 
diff --git a/hw/prep_pci.h b/hw/prep_pci.h
index cd68512..a27368b 100644
--- a/hw/prep_pci.h
+++ b/hw/prep_pci.h
@@ -2,7 +2,8 @@
 #define QEMU_PREP_PCI_H
 
 #include "qemu-common.h"
+#include "memory.h"
 
-PCIBus *pci_prep_init(qemu_irq *pic);
+PCIBus *pci_prep_init(qemu_irq *pic, MemoryRegion *address_space);
 
 #endif
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index a076cf2..0ef93a0 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -26,6 +26,7 @@
 #include "pci.h"
 #include "pci_host.h"
 #include "bswap.h"
+#include "exec-memory.h"
 
 typedef struct SHPCIState {
     SysBusDevice busdev;
@@ -127,7 +128,8 @@ static int sh_pci_init_device(SysBusDevice *dev)
     }
     s->bus = pci_register_bus(&s->busdev.qdev, "pci",
                               sh_pci_set_irq, sh_pci_map_irq,
-                              s->irq, PCI_DEVFN(0, 0), 4);
+                              s->irq, get_system_memory(),
+                              PCI_DEVFN(0, 0), 4);
     s->memconfig = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w,
                                           s, DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio_cb(dev, 0x224, sh_pci_map);
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index d364daa..b499523 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -201,7 +201,7 @@ static int pci_unin_internal_init_device(SysBusDevice *dev)
     return 0;
 }
 
-PCIBus *pci_pmac_init(qemu_irq *pic)
+PCIBus *pci_pmac_init(qemu_irq *pic, MemoryRegion *address_space)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -215,7 +215,8 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
     d = FROM_SYSBUS(UNINState, s);
     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                          pci_unin_set_irq, pci_unin_map_irq,
-                                         pic, PCI_DEVFN(11, 0), 4);
+                                         pic, address_space,
+                                         PCI_DEVFN(11, 0), 4);
 
 #if 0
     pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north");
@@ -252,7 +253,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
     return d->host_state.bus;
 }
 
-PCIBus *pci_pmac_u3_init(qemu_irq *pic)
+PCIBus *pci_pmac_u3_init(qemu_irq *pic, MemoryRegion *address_space)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -267,7 +268,8 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic)
 
     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                          pci_unin_set_irq, pci_unin_map_irq,
-                                         pic, PCI_DEVFN(11, 0), 4);
+                                         pic, address_space,
+                                         PCI_DEVFN(11, 0), 4);
 
     sysbus_mmio_map(s, 0, 0xf0800000);
     sysbus_mmio_map(s, 1, 0xf0c00000);
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index 290a900..cffe387 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -10,6 +10,7 @@
 #include "sysbus.h"
 #include "pci.h"
 #include "pci_host.h"
+#include "exec-memory.h"
 
 typedef struct {
     SysBusDevice busdev;
@@ -111,6 +112,7 @@ static int pci_vpb_init(SysBusDevice *dev)
     }
     bus = pci_register_bus(&dev->qdev, "pci",
                            pci_vpb_set_irq, pci_vpb_map_irq, s->irq,
+                           get_system_memory(),
                            PCI_DEVFN(11, 0), 4);
 
     /* ??? Register memory space.  */
commit 6bd105151ac5529605a478de3b6c3aceed5995e9
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:18 2011 +0300

    pc: move global memory map out of pc_init1() and into its callers
    
    Signed-off-by: Avi Kivity <avi 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 d83854c..f2d0476 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -68,7 +68,8 @@ static void ioapic_init(IsaIrqState *isa_irq_state)
 }
 
 /* PC hardware initialisation */
-static void pc_init1(ram_addr_t ram_size,
+static void pc_init1(MemoryRegion *system_memory,
+                     ram_addr_t ram_size,
                      const char *boot_device,
                      const char *kernel_filename,
                      const char *kernel_cmdline,
@@ -91,9 +92,6 @@ static void pc_init1(ram_addr_t ram_size,
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     BusState *idebus[MAX_IDE_BUS];
     ISADevice *rtc_state;
-    MemoryRegion *system_memory;
-
-    system_memory = get_system_memory();
 
     pc_cpus_init(cpu_model);
 
@@ -214,7 +212,8 @@ static void pc_init_pci(ram_addr_t ram_size,
                         const char *initrd_filename,
                         const char *cpu_model)
 {
-    pc_init1(ram_size, boot_device,
+    pc_init1(get_system_memory(),
+             ram_size, boot_device,
              kernel_filename, kernel_cmdline,
              initrd_filename, cpu_model, 1, 1);
 }
@@ -226,7 +225,8 @@ static void pc_init_pci_no_kvmclock(ram_addr_t ram_size,
                                     const char *initrd_filename,
                                     const char *cpu_model)
 {
-    pc_init1(ram_size, boot_device,
+    pc_init1(get_system_memory(),
+             ram_size, boot_device,
              kernel_filename, kernel_cmdline,
              initrd_filename, cpu_model, 1, 0);
 }
@@ -240,7 +240,8 @@ static void pc_init_isa(ram_addr_t ram_size,
 {
     if (cpu_model == NULL)
         cpu_model = "486";
-    pc_init1(ram_size, boot_device,
+    pc_init1(get_system_memory(),
+             ram_size, boot_device,
              kernel_filename, kernel_cmdline,
              initrd_filename, cpu_model, 0, 1);
 }
commit 00cb2a99f5e7f73c4fff54ae16c7b6acf463ab5c
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:17 2011 +0300

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

diff --git a/hw/pc.c b/hw/pc.c
index 369566a..1c9d89a 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -41,6 +41,7 @@
 #include "sysemu.h"
 #include "blockdev.h"
 #include "ui/qemu-spice.h"
+#include "memory.h"
 
 /* output Bochs bios info messages */
 //#define DEBUG_BIOS
@@ -966,22 +967,30 @@ void pc_memory_init(MemoryRegion *system_memory,
 {
     char *filename;
     int ret, linux_boot, i;
-    ram_addr_t ram_addr, bios_offset, option_rom_offset;
+    MemoryRegion *ram, *bios, *isa_bios, *option_rom_mr;
+    MemoryRegion *ram_below_4g, *ram_above_4g;
     int bios_size, isa_bios_size;
     void *fw_cfg;
 
     linux_boot = (kernel_filename != NULL);
 
-    /* allocate RAM */
-    ram_addr = qemu_ram_alloc(NULL, "pc.ram",
-                              below_4g_mem_size + above_4g_mem_size);
-    cpu_register_physical_memory(0, 0xa0000, ram_addr);
-    cpu_register_physical_memory(0x100000,
-                 below_4g_mem_size - 0x100000,
-                 ram_addr + 0x100000);
+    /* Allocate RAM.  We allocate it as a single memory region and use
+     * aliases to address portions of it, mostly for backwards compatiblity
+     * with older qemus that used qemu_ram_alloc().
+     */
+    ram = qemu_malloc(sizeof(*ram));
+    memory_region_init_ram(ram, NULL, "pc.ram",
+                           below_4g_mem_size + above_4g_mem_size);
+    ram_below_4g = qemu_malloc(sizeof(*ram_below_4g));
+    memory_region_init_alias(ram_below_4g, "ram-below-4g", ram,
+                             0, below_4g_mem_size);
+    memory_region_add_subregion(system_memory, 0, ram_below_4g);
     if (above_4g_mem_size > 0) {
-        cpu_register_physical_memory(0x100000000ULL, above_4g_mem_size,
-                                     ram_addr + below_4g_mem_size);
+        ram_above_4g = qemu_malloc(sizeof(*ram_above_4g));
+        memory_region_init_alias(ram_above_4g, "ram-above-4g", ram,
+                                 below_4g_mem_size, above_4g_mem_size);
+        memory_region_add_subregion(system_memory, 0x100000000ULL,
+                                    ram_above_4g);
     }
 
     /* BIOS load */
@@ -997,7 +1006,9 @@ void pc_memory_init(MemoryRegion *system_memory,
         (bios_size % 65536) != 0) {
         goto bios_error;
     }
-    bios_offset = qemu_ram_alloc(NULL, "pc.bios", bios_size);
+    bios = qemu_malloc(sizeof(*bios));
+    memory_region_init_ram(bios, NULL, "pc.bios", bios_size);
+    memory_region_set_readonly(bios, true);
     ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
     if (ret != 0) {
     bios_error:
@@ -1011,16 +1022,26 @@ void pc_memory_init(MemoryRegion *system_memory,
     isa_bios_size = bios_size;
     if (isa_bios_size > (128 * 1024))
         isa_bios_size = 128 * 1024;
-    cpu_register_physical_memory(0x100000 - isa_bios_size,
-                                 isa_bios_size,
-                                 (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
-
-    option_rom_offset = qemu_ram_alloc(NULL, "pc.rom", PC_ROM_SIZE);
-    cpu_register_physical_memory(PC_ROM_MIN_VGA, PC_ROM_SIZE, option_rom_offset);
+    isa_bios = qemu_malloc(sizeof(*isa_bios));
+    memory_region_init_alias(isa_bios, "isa-bios", bios,
+                             bios_size - isa_bios_size, isa_bios_size);
+    memory_region_add_subregion_overlap(system_memory,
+                                        0x100000 - isa_bios_size,
+                                        isa_bios,
+                                        1);
+    memory_region_set_readonly(isa_bios, true);
+
+    option_rom_mr = qemu_malloc(sizeof(*option_rom_mr));
+    memory_region_init_ram(option_rom_mr, NULL, "pc.rom", PC_ROM_SIZE);
+    memory_region_add_subregion_overlap(system_memory,
+                                        PC_ROM_MIN_VGA,
+                                        option_rom_mr,
+                                        1);
 
     /* map all the bios at the top of memory */
-    cpu_register_physical_memory((uint32_t)(-bios_size),
-                                 bios_size, bios_offset | IO_MEM_ROM);
+    memory_region_add_subregion(system_memory,
+                                (uint32_t)(-bios_size),
+                                bios);
 
     fw_cfg = bochs_bios_init();
     rom_set_fw(fw_cfg);
diff --git a/hw/pc.h b/hw/pc.h
index fa57583..40684f4 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -2,6 +2,7 @@
 #define HW_PC_H
 
 #include "qemu-common.h"
+#include "memory.h"
 #include "ioport.h"
 #include "isa.h"
 #include "fdc.h"
commit 4aa63af14969a50f9c3d2324127daff0f0199c61
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:16 2011 +0300

    pc: grab system_memory
    
    While eventually this should come from the machine initialization function,
    take a short cut to avoid converting all machines now.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pc.c b/hw/pc.c
index a3e8539..369566a 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -957,7 +957,8 @@ void pc_cpus_init(const char *cpu_model)
     }
 }
 
-void pc_memory_init(const char *kernel_filename,
+void pc_memory_init(MemoryRegion *system_memory,
+                    const char *kernel_filename,
                     const char *kernel_cmdline,
                     const char *initrd_filename,
                     ram_addr_t below_4g_mem_size,
diff --git a/hw/pc.h b/hw/pc.h
index 6d5730b..fa57583 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -6,6 +6,7 @@
 #include "isa.h"
 #include "fdc.h"
 #include "net.h"
+#include "memory.h"
 
 /* PC-style peripherals (also used by other machines).  */
 
@@ -129,7 +130,8 @@ void pc_cmos_set_s3_resume(void *opaque, int irq, int level);
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
 
 void pc_cpus_init(const char *cpu_model);
-void pc_memory_init(const char *kernel_filename,
+void pc_memory_init(MemoryRegion *system_memory,
+                    const char *kernel_filename,
                     const char *kernel_cmdline,
                     const char *initrd_filename,
                     ram_addr_t below_4g_mem_size,
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index c5c16b4..d83854c 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -39,6 +39,8 @@
 #include "blockdev.h"
 #include "smbus.h"
 #include "xen.h"
+#include "memory.h"
+#include "exec-memory.h"
 #ifdef CONFIG_XEN
 #  include <xen/hvm/hvm_info_table.h>
 #endif
@@ -89,6 +91,9 @@ static void pc_init1(ram_addr_t ram_size,
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     BusState *idebus[MAX_IDE_BUS];
     ISADevice *rtc_state;
+    MemoryRegion *system_memory;
+
+    system_memory = get_system_memory();
 
     pc_cpus_init(cpu_model);
 
@@ -106,7 +111,8 @@ static void pc_init1(ram_addr_t ram_size,
 
     /* allocate ram and load rom/bios */
     if (!xen_enabled()) {
-        pc_memory_init(kernel_filename, kernel_cmdline, initrd_filename,
+        pc_memory_init(system_memory,
+                       kernel_filename, kernel_cmdline, initrd_filename,
                        below_4g_mem_size, above_4g_mem_size);
     }
 
commit bf3fb0e12aeb9fea08383c145f874ed7acc29e31
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:15 2011 +0300

    ioport: register ranges by byte aligned addresses always
    
    The I/O port space is byte addressable, even for word and long accesses.
    
    An example is the VMware svga card, which has long ports on offsets 0,
    1, and 2.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ioport.c b/ioport.c
index 0d2611d..a32483b 100644
--- a/ioport.c
+++ b/ioport.c
@@ -146,7 +146,7 @@ int register_ioport_read(pio_addr_t start, int length, int size,
         hw_error("register_ioport_read: invalid size");
         return -1;
     }
-    for(i = start; i < start + length; i += size) {
+    for(i = start; i < start + length; ++i) {
         ioport_read_table[bsize][i] = func;
         if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
             hw_error("register_ioport_read: invalid opaque for address 0x%x",
@@ -166,7 +166,7 @@ int register_ioport_write(pio_addr_t start, int length, int size,
         hw_error("register_ioport_write: invalid size");
         return -1;
     }
-    for(i = start; i < start + length; i += size) {
+    for(i = start; i < start + length; ++i) {
         ioport_write_table[bsize][i] = func;
         if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
             hw_error("register_ioport_write: invalid opaque for address 0x%x",
commit 62152b8a014609ac94da2de440aedb3246c1204a
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:14 2011 +0300

    exec.c: initialize memory map
    
    Allocate the root memory region and initialize it.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/exec.c b/exec.c
index 2160ded..d51502f 100644
--- a/exec.c
+++ b/exec.c
@@ -33,6 +33,8 @@
 #include "kvm.h"
 #include "hw/xen.h"
 #include "qemu-timer.h"
+#include "memory.h"
+#include "exec-memory.h"
 #if defined(CONFIG_USER_ONLY)
 #include <qemu.h>
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
@@ -109,6 +111,9 @@ int phys_ram_fd;
 static int in_migration;
 
 RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list) };
+
+static MemoryRegion *system_memory;
+
 #endif
 
 CPUState *first_cpu;
@@ -197,6 +202,7 @@ typedef struct PhysPageDesc {
 static void *l1_phys_map[P_L1_SIZE];
 
 static void io_mem_init(void);
+static void memory_map_init(void);
 
 /* io memory support */
 CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
@@ -571,6 +577,7 @@ void cpu_exec_init_all(unsigned long tb_size)
     code_gen_ptr = code_gen_buffer;
     page_init();
 #if !defined(CONFIG_USER_ONLY)
+    memory_map_init();
     io_mem_init();
 #endif
 #if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE)
@@ -3807,6 +3814,18 @@ static void io_mem_init(void)
                                           DEVICE_NATIVE_ENDIAN);
 }
 
+static void memory_map_init(void)
+{
+    system_memory = qemu_malloc(sizeof(*system_memory));
+    memory_region_init(system_memory, "system", UINT64_MAX);
+    set_system_memory_map(system_memory);
+}
+
+MemoryRegion *get_system_memory(void)
+{
+    return system_memory;
+}
+
 #endif /* !defined(CONFIG_USER_ONLY) */
 
 /* physical memory access (slow version, mainly for debug) */
commit 4ef4db860362ce9852c20b343e9813897ecdefce
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:13 2011 +0300

    memory: transaction API
    
    Allow changes to the memory hierarchy to be accumulated and
    made visible all at once.  This reduces computational effort,
    especially when an accelerator (e.g. kvm) is involved.
    
    Useful when a single register update causes multiple changes
    to an address space.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/memory.c b/memory.c
index 7a5670e..5c6e63d 100644
--- a/memory.c
+++ b/memory.c
@@ -18,6 +18,8 @@
 #include "kvm.h"
 #include <assert.h>
 
+unsigned memory_region_transaction_depth = 0;
+
 typedef struct AddrRange AddrRange;
 
 struct AddrRange {
@@ -626,6 +628,10 @@ static void address_space_update_topology(AddressSpace *as)
 
 static void memory_region_update_topology(void)
 {
+    if (memory_region_transaction_depth) {
+        return;
+    }
+
     if (address_space_memory.root) {
         address_space_update_topology(&address_space_memory);
     }
@@ -634,6 +640,18 @@ static void memory_region_update_topology(void)
     }
 }
 
+void memory_region_transaction_begin(void)
+{
+    ++memory_region_transaction_depth;
+}
+
+void memory_region_transaction_commit(void)
+{
+    assert(memory_region_transaction_depth);
+    --memory_region_transaction_depth;
+    memory_region_update_topology();
+}
+
 void memory_region_init(MemoryRegion *mr,
                         const char *name,
                         uint64_t size)
diff --git a/memory.h b/memory.h
index c280a39..4e518b2 100644
--- a/memory.h
+++ b/memory.h
@@ -456,6 +456,14 @@ 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.
+ */
+void memory_region_transaction_begin(void);
+/* Commit a transaction and make changes visible to the guest.
+ */
+void memory_region_transaction_commit(void);
+
 #endif
 
 #endif
commit b8af1afbfbc157e058f27ab5382527350b814ee7
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:12 2011 +0300

    memory: separate building the final memory map into two steps
    
    Instead of adding and deleting regions in one pass, do a delete
    pass followed by an add pass.  This fixes the following case:
    
    from:
      0x0000-0x0fff ram  (a1)
      0x1000-0x1fff mmio (a2)
      0x2000-0x2fff ram  (a3)
    
    to:
      0x0000-0x2fff ram  (b1)
    
    The single pass algorithm removed a1, added b2, then removed a2 and a3,
    which caused the wrong memory map to be built.  The two pass algorithm
    removes a1, a2, and a3, then adds b1.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/memory.c b/memory.c
index 686bbf2..7a5670e 100644
--- a/memory.c
+++ b/memory.c
@@ -549,10 +549,11 @@ static void address_space_update_ioeventfds(AddressSpace *as)
     as->ioeventfd_nb = ioeventfd_nb;
 }
 
-static void address_space_update_topology(AddressSpace *as)
+static void address_space_update_topology_pass(AddressSpace *as,
+                                               FlatView old_view,
+                                               FlatView new_view,
+                                               bool adding)
 {
-    FlatView old_view = as->current_map;
-    FlatView new_view = generate_memory_topology(as->root);
     unsigned iold, inew;
     FlatRange *frold, *frnew;
 
@@ -579,15 +580,20 @@ static void address_space_update_topology(AddressSpace *as)
                     && !flatrange_equal(frold, frnew)))) {
             /* In old, but (not in new, or in new but attributes changed). */
 
-            as->ops->range_del(as, frold);
+            if (!adding) {
+                as->ops->range_del(as, frold);
+            }
+
             ++iold;
         } else if (frold && frnew && flatrange_equal(frold, frnew)) {
             /* In both (logging may have changed) */
 
-            if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
-                as->ops->log_stop(as, frnew);
-            } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
-                as->ops->log_start(as, frnew);
+            if (adding) {
+                if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
+                    as->ops->log_stop(as, frnew);
+                } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
+                    as->ops->log_start(as, frnew);
+                }
             }
 
             ++iold;
@@ -595,10 +601,24 @@ static void address_space_update_topology(AddressSpace *as)
         } else {
             /* In new */
 
-            as->ops->range_add(as, frnew);
+            if (adding) {
+                as->ops->range_add(as, frnew);
+            }
+
             ++inew;
         }
     }
+}
+
+
+static void address_space_update_topology(AddressSpace *as)
+{
+    FlatView old_view = as->current_map;
+    FlatView new_view = generate_memory_topology(as->root);
+
+    address_space_update_topology_pass(as, old_view, new_view, false);
+    address_space_update_topology_pass(as, old_view, new_view, true);
+
     as->current_map = new_view;
     flatview_destroy(&old_view);
     address_space_update_ioeventfds(as);
commit 3e9d69e737025e987be3ce804f667ffeb07e4c53
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:11 2011 +0300

    memory: add ioeventfd support
    
    As with the rest of the memory API, the caller associates an eventfd
    with an address, and the memory API takes care of registering or
    unregistering when the address is made visible or invisible to the
    guest.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/memory.c b/memory.c
index 7dd7cac..686bbf2 100644
--- a/memory.c
+++ b/memory.c
@@ -15,6 +15,7 @@
 #include "exec-memory.h"
 #include "ioport.h"
 #include "bitops.h"
+#include "kvm.h"
 #include <assert.h>
 
 typedef struct AddrRange AddrRange;
@@ -64,6 +65,50 @@ struct CoalescedMemoryRange {
     QTAILQ_ENTRY(CoalescedMemoryRange) link;
 };
 
+struct MemoryRegionIoeventfd {
+    AddrRange addr;
+    bool match_data;
+    uint64_t data;
+    int fd;
+};
+
+static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
+                                           MemoryRegionIoeventfd b)
+{
+    if (a.addr.start < b.addr.start) {
+        return true;
+    } else if (a.addr.start > b.addr.start) {
+        return false;
+    } else if (a.addr.size < b.addr.size) {
+        return true;
+    } else if (a.addr.size > b.addr.size) {
+        return false;
+    } else if (a.match_data < b.match_data) {
+        return true;
+    } else  if (a.match_data > b.match_data) {
+        return false;
+    } else if (a.match_data) {
+        if (a.data < b.data) {
+            return true;
+        } else if (a.data > b.data) {
+            return false;
+        }
+    }
+    if (a.fd < b.fd) {
+        return true;
+    } else if (a.fd > b.fd) {
+        return false;
+    }
+    return false;
+}
+
+static bool memory_region_ioeventfd_equal(MemoryRegionIoeventfd a,
+                                          MemoryRegionIoeventfd b)
+{
+    return !memory_region_ioeventfd_before(a, b)
+        && !memory_region_ioeventfd_before(b, a);
+}
+
 typedef struct FlatRange FlatRange;
 typedef struct FlatView FlatView;
 
@@ -92,6 +137,8 @@ struct AddressSpace {
     const AddressSpaceOps *ops;
     MemoryRegion *root;
     FlatView current_map;
+    int ioeventfd_nb;
+    MemoryRegionIoeventfd *ioeventfds;
 };
 
 struct AddressSpaceOps {
@@ -99,6 +146,8 @@ struct AddressSpaceOps {
     void (*range_del)(AddressSpace *as, FlatRange *fr);
     void (*log_start)(AddressSpace *as, FlatRange *fr);
     void (*log_stop)(AddressSpace *as, FlatRange *fr);
+    void (*ioeventfd_add)(AddressSpace *as, MemoryRegionIoeventfd *fd);
+    void (*ioeventfd_del)(AddressSpace *as, MemoryRegionIoeventfd *fd);
 };
 
 #define FOR_EACH_FLAT_RANGE(var, view)          \
@@ -208,11 +257,35 @@ static void as_memory_log_stop(AddressSpace *as, FlatRange *fr)
     cpu_physical_log_stop(fr->addr.start, fr->addr.size);
 }
 
+static void as_memory_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+    int r;
+
+    assert(fd->match_data && fd->addr.size == 4);
+
+    r = kvm_set_ioeventfd_mmio_long(fd->fd, fd->addr.start, fd->data, true);
+    if (r < 0) {
+        abort();
+    }
+}
+
+static void as_memory_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+    int r;
+
+    r = kvm_set_ioeventfd_mmio_long(fd->fd, fd->addr.start, fd->data, false);
+    if (r < 0) {
+        abort();
+    }
+}
+
 static const AddressSpaceOps address_space_ops_memory = {
     .range_add = as_memory_range_add,
     .range_del = as_memory_range_del,
     .log_start = as_memory_log_start,
     .log_stop = as_memory_log_stop,
+    .ioeventfd_add = as_memory_ioeventfd_add,
+    .ioeventfd_del = as_memory_ioeventfd_del,
 };
 
 static AddressSpace address_space_memory = {
@@ -288,9 +361,33 @@ static void as_io_range_del(AddressSpace *as, FlatRange *fr)
     isa_unassign_ioport(fr->addr.start, fr->addr.size);
 }
 
+static void as_io_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+    int r;
+
+    assert(fd->match_data && fd->addr.size == 2);
+
+    r = kvm_set_ioeventfd_pio_word(fd->fd, fd->addr.start, fd->data, true);
+    if (r < 0) {
+        abort();
+    }
+}
+
+static void as_io_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+    int r;
+
+    r = kvm_set_ioeventfd_pio_word(fd->fd, fd->addr.start, fd->data, false);
+    if (r < 0) {
+        abort();
+    }
+}
+
 static const AddressSpaceOps address_space_ops_io = {
     .range_add = as_io_range_add,
     .range_del = as_io_range_del,
+    .ioeventfd_add = as_io_ioeventfd_add,
+    .ioeventfd_del = as_io_ioeventfd_del,
 };
 
 static AddressSpace address_space_io = {
@@ -389,6 +486,69 @@ static FlatView generate_memory_topology(MemoryRegion *mr)
     return view;
 }
 
+static void address_space_add_del_ioeventfds(AddressSpace *as,
+                                             MemoryRegionIoeventfd *fds_new,
+                                             unsigned fds_new_nb,
+                                             MemoryRegionIoeventfd *fds_old,
+                                             unsigned fds_old_nb)
+{
+    unsigned iold, inew;
+
+    /* Generate a symmetric difference of the old and new fd sets, adding
+     * and deleting as necessary.
+     */
+
+    iold = inew = 0;
+    while (iold < fds_old_nb || inew < fds_new_nb) {
+        if (iold < fds_old_nb
+            && (inew == fds_new_nb
+                || memory_region_ioeventfd_before(fds_old[iold],
+                                                  fds_new[inew]))) {
+            as->ops->ioeventfd_del(as, &fds_old[iold]);
+            ++iold;
+        } else if (inew < fds_new_nb
+                   && (iold == fds_old_nb
+                       || memory_region_ioeventfd_before(fds_new[inew],
+                                                         fds_old[iold]))) {
+            as->ops->ioeventfd_add(as, &fds_new[inew]);
+            ++inew;
+        } else {
+            ++iold;
+            ++inew;
+        }
+    }
+}
+
+static void address_space_update_ioeventfds(AddressSpace *as)
+{
+    FlatRange *fr;
+    unsigned ioeventfd_nb = 0;
+    MemoryRegionIoeventfd *ioeventfds = NULL;
+    AddrRange tmp;
+    unsigned i;
+
+    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);
+            if (addrrange_intersects(fr->addr, tmp)) {
+                ++ioeventfd_nb;
+                ioeventfds = qemu_realloc(ioeventfds,
+                                          ioeventfd_nb * sizeof(*ioeventfds));
+                ioeventfds[ioeventfd_nb-1] = fr->mr->ioeventfds[i];
+                ioeventfds[ioeventfd_nb-1].addr = tmp;
+            }
+        }
+    }
+
+    address_space_add_del_ioeventfds(as, ioeventfds, ioeventfd_nb,
+                                     as->ioeventfds, as->ioeventfd_nb);
+
+    qemu_free(as->ioeventfds);
+    as->ioeventfds = ioeventfds;
+    as->ioeventfd_nb = ioeventfd_nb;
+}
+
 static void address_space_update_topology(AddressSpace *as)
 {
     FlatView old_view = as->current_map;
@@ -441,6 +601,7 @@ static void address_space_update_topology(AddressSpace *as)
     }
     as->current_map = new_view;
     flatview_destroy(&old_view);
+    address_space_update_ioeventfds(as);
 }
 
 static void memory_region_update_topology(void)
@@ -471,6 +632,8 @@ void memory_region_init(MemoryRegion *mr,
     QTAILQ_INIT(&mr->coalesced);
     mr->name = qemu_strdup(name);
     mr->dirty_log_mask = 0;
+    mr->ioeventfd_nb = 0;
+    mr->ioeventfds = NULL;
 }
 
 static bool memory_region_access_valid(MemoryRegion *mr,
@@ -682,6 +845,7 @@ void memory_region_destroy(MemoryRegion *mr)
     assert(QTAILQ_EMPTY(&mr->subregions));
     memory_region_clear_coalescing(mr);
     qemu_free((char *)mr->name);
+    qemu_free(mr->ioeventfds);
 }
 
 uint64_t memory_region_size(MemoryRegion *mr)
@@ -803,6 +967,66 @@ void memory_region_clear_coalescing(MemoryRegion *mr)
     memory_region_update_coalesced_range(mr);
 }
 
+void memory_region_add_eventfd(MemoryRegion *mr,
+                               target_phys_addr_t addr,
+                               unsigned size,
+                               bool match_data,
+                               uint64_t data,
+                               int fd)
+{
+    MemoryRegionIoeventfd mrfd = {
+        .addr.start = addr,
+        .addr.size = size,
+        .match_data = match_data,
+        .data = data,
+        .fd = fd,
+    };
+    unsigned i;
+
+    for (i = 0; i < mr->ioeventfd_nb; ++i) {
+        if (memory_region_ioeventfd_before(mrfd, mr->ioeventfds[i])) {
+            break;
+        }
+    }
+    ++mr->ioeventfd_nb;
+    mr->ioeventfds = qemu_realloc(mr->ioeventfds,
+                                  sizeof(*mr->ioeventfds) * mr->ioeventfd_nb);
+    memmove(&mr->ioeventfds[i+1], &mr->ioeventfds[i],
+            sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb-1 - i));
+    mr->ioeventfds[i] = mrfd;
+    memory_region_update_topology();
+}
+
+void memory_region_del_eventfd(MemoryRegion *mr,
+                               target_phys_addr_t addr,
+                               unsigned size,
+                               bool match_data,
+                               uint64_t data,
+                               int fd)
+{
+    MemoryRegionIoeventfd mrfd = {
+        .addr.start = addr,
+        .addr.size = size,
+        .match_data = match_data,
+        .data = data,
+        .fd = fd,
+    };
+    unsigned i;
+
+    for (i = 0; i < mr->ioeventfd_nb; ++i) {
+        if (memory_region_ioeventfd_equal(mrfd, mr->ioeventfds[i])) {
+            break;
+        }
+    }
+    assert(i != mr->ioeventfd_nb);
+    memmove(&mr->ioeventfds[i], &mr->ioeventfds[i+1],
+            sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb - (i+1)));
+    --mr->ioeventfd_nb;
+    mr->ioeventfds = qemu_realloc(mr->ioeventfds,
+                                  sizeof(*mr->ioeventfds)*mr->ioeventfd_nb + 1);
+    memory_region_update_topology();
+}
+
 static void memory_region_add_subregion_common(MemoryRegion *mr,
                                                target_phys_addr_t offset,
                                                MemoryRegion *subregion)
diff --git a/memory.h b/memory.h
index 003c999..c280a39 100644
--- a/memory.h
+++ b/memory.h
@@ -98,6 +98,7 @@ struct MemoryRegionOps {
 };
 
 typedef struct CoalescedMemoryRange CoalescedMemoryRange;
+typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
 
 struct MemoryRegion {
     /* All fields are private - violators will be prosecuted */
@@ -120,6 +121,8 @@ struct MemoryRegion {
     QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced;
     const char *name;
     uint8_t dirty_log_mask;
+    unsigned ioeventfd_nb;
+    MemoryRegionIoeventfd *ioeventfds;
 };
 
 struct MemoryRegionPortio {
@@ -364,6 +367,48 @@ void memory_region_add_coalescing(MemoryRegion *mr,
 void memory_region_clear_coalescing(MemoryRegion *mr);
 
 /**
+ * memory_region_add_eventfd: Request an eventfd to be triggered when a word
+ *                            is written to a location.
+ *
+ * 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
+ * action if the callback _is_ called).
+ *
+ * @mr: the memory region being updated.
+ * @addr: the address within @mr that is to be monitored
+ * @size: the size of the access to trigger the eventfd
+ * @match_data: whether to match against @data, instead of just @addr
+ * @data: the data to match against the guest write
+ * @fd: the eventfd to be triggered when @addr, @size, and @data all match.
+ **/
+void memory_region_add_eventfd(MemoryRegion *mr,
+                               target_phys_addr_t addr,
+                               unsigned size,
+                               bool match_data,
+                               uint64_t data,
+                               int fd);
+
+/**
+ * memory_region_del_eventfd: Cancel and eventfd.
+ *
+ * Cancels an eventfd trigger request by a previous memory_region_add_eventfd()
+ * call.
+ *
+ * @mr: the memory region being updated.
+ * @addr: the address within @mr that is to be monitored
+ * @size: the size of the access to trigger the eventfd
+ * @match_data: whether to match against @data, instead of just @addr
+ * @data: the data to match against the guest write
+ * @fd: the eventfd to be triggered when @addr, @size, and @data all match.
+ */
+void memory_region_del_eventfd(MemoryRegion *mr,
+                               target_phys_addr_t addr,
+                               unsigned size,
+                               bool match_data,
+                               uint64_t data,
+                               int fd);
+/**
  * memory_region_add_subregion: Add a sub-region to a container.
  *
  * Adds a sub-region at @offset.  The sub-region may not overlap with other
commit 74901c3bd06a02b54f23172cb870127b49390bd0
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:10 2011 +0300

    memory: add backward compatibility for old mmio registration
    
    This eases the transition to the new API.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/memory.c b/memory.c
index 5f2c9ef..7dd7cac 100644
--- a/memory.c
+++ b/memory.c
@@ -14,6 +14,7 @@
 #include "memory.h"
 #include "exec-memory.h"
 #include "ioport.h"
+#include "bitops.h"
 #include <assert.h>
 
 typedef struct AddrRange AddrRange;
@@ -506,6 +507,10 @@ static uint32_t memory_region_read_thunk_n(void *_mr,
         return -1U; /* FIXME: better signalling */
     }
 
+    if (!mr->ops->read) {
+        return mr->ops->old_mmio.read[bitops_ffsl(size)](mr->opaque, addr);
+    }
+
     /* FIXME: support unaligned access */
 
     access_size_min = mr->ops->impl.min_access_size;
@@ -542,6 +547,11 @@ static void memory_region_write_thunk_n(void *_mr,
         return; /* FIXME: better signalling */
     }
 
+    if (!mr->ops->write) {
+        mr->ops->old_mmio.write[bitops_ffsl(size)](mr->opaque, addr, data);
+        return;
+    }
+
     /* FIXME: support unaligned access */
 
     access_size_min = mr->ops->impl.min_access_size;
diff --git a/memory.h b/memory.h
index 40ab95a..003c999 100644
--- a/memory.h
+++ b/memory.h
@@ -28,6 +28,7 @@
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegion MemoryRegion;
 typedef struct MemoryRegionPortio MemoryRegionPortio;
+typedef struct MemoryRegionMmio MemoryRegionMmio;
 
 /* Must match *_DIRTY_FLAGS in cpu-all.h.  To be replaced with dynamic
  * registration.
@@ -36,6 +37,11 @@ typedef struct MemoryRegionPortio MemoryRegionPortio;
 #define DIRTY_MEMORY_CODE      1
 #define DIRTY_MEMORY_MIGRATION 3
 
+struct MemoryRegionMmio {
+    CPUReadMemoryFunc *read[3];
+    CPUWriteMemoryFunc *write[3];
+};
+
 /*
  * Memory region callbacks
  */
@@ -85,6 +91,10 @@ struct MemoryRegionOps {
      * backwards compatibility with old portio registration
      */
     const MemoryRegionPortio *old_portio;
+    /* If .read and .write are not present, old_mmio may be used for
+     * backwards compatibility with old mmio registration
+     */
+    const MemoryRegionMmio old_mmio;
 };
 
 typedef struct CoalescedMemoryRange CoalescedMemoryRange;
commit 627a0e90dc6b53504d6b9539b8e29210d82ecf9d
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:09 2011 +0300

    memory: add backward compatibility for old portio registration
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/memory.c b/memory.c
index df0ed0e..5f2c9ef 100644
--- a/memory.c
+++ b/memory.c
@@ -218,6 +218,21 @@ static AddressSpace address_space_memory = {
     .ops = &address_space_ops_memory,
 };
 
+static const MemoryRegionPortio *find_portio(MemoryRegion *mr, uint64_t offset,
+                                             unsigned width, bool write)
+{
+    const MemoryRegionPortio *mrp;
+
+    for (mrp = mr->ops->old_portio; mrp->size; ++mrp) {
+        if (offset >= mrp->offset && offset < mrp->offset + mrp->len
+            && width == mrp->size
+            && (write ? (bool)mrp->write : (bool)mrp->read)) {
+            return mrp;
+        }
+    }
+    return NULL;
+}
+
 static void memory_region_iorange_read(IORange *iorange,
                                        uint64_t offset,
                                        unsigned width,
@@ -225,6 +240,15 @@ static void memory_region_iorange_read(IORange *iorange,
 {
     MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
 
+    if (mr->ops->old_portio) {
+        const MemoryRegionPortio *mrp = find_portio(mr, offset, width, false);
+
+        *data = ((uint64_t)1 << (width * 8)) - 1;
+        if (mrp) {
+            *data = mrp->read(mr->opaque, offset - mrp->offset);
+        }
+        return;
+    }
     *data = mr->ops->read(mr->opaque, offset, width);
 }
 
@@ -235,6 +259,14 @@ static void memory_region_iorange_write(IORange *iorange,
 {
     MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
 
+    if (mr->ops->old_portio) {
+        const MemoryRegionPortio *mrp = find_portio(mr, offset, width, true);
+
+        if (mrp) {
+            mrp->write(mr->opaque, offset - mrp->offset, data);
+        }
+        return;
+    }
     mr->ops->write(mr->opaque, offset, data, width);
 }
 
diff --git a/memory.h b/memory.h
index 88ba428..40ab95a 100644
--- a/memory.h
+++ b/memory.h
@@ -23,9 +23,11 @@
 #include "targphys.h"
 #include "qemu-queue.h"
 #include "iorange.h"
+#include "ioport.h"
 
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegion MemoryRegion;
+typedef struct MemoryRegionPortio MemoryRegionPortio;
 
 /* Must match *_DIRTY_FLAGS in cpu-all.h.  To be replaced with dynamic
  * registration.
@@ -78,6 +80,11 @@ struct MemoryRegionOps {
          */
          bool unaligned;
     } impl;
+
+    /* If .read and .write are not present, old_portio may be used for
+     * backwards compatibility with old portio registration
+     */
+    const MemoryRegionPortio *old_portio;
 };
 
 typedef struct CoalescedMemoryRange CoalescedMemoryRange;
@@ -105,6 +112,16 @@ struct MemoryRegion {
     uint8_t dirty_log_mask;
 };
 
+struct MemoryRegionPortio {
+    uint32_t offset;
+    uint32_t len;
+    unsigned size;
+    IOPortReadFunc *read;
+    IOPortWriteFunc *write;
+};
+
+#define PORTIO_END { }
+
 /**
  * memory_region_init: Initialize a memory region
  *
commit 658b2224017b5c5fdc60969fa2f0798781b0cb3f
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:08 2011 +0300

    memory: I/O address space support
    
    Allow registering I/O ports via the same mechanism as mmio ranges.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/exec-memory.h b/exec-memory.h
index aea1b45..c439aba 100644
--- a/exec-memory.h
+++ b/exec-memory.h
@@ -31,6 +31,9 @@ MemoryRegion *get_system_memory(void);
 /* Set the root memory region.  This region is the system memory map. */
 void set_system_memory_map(MemoryRegion *mr);
 
+/* Set the I/O memory region.  This region is the I/O memory map. */
+void set_system_io_map(MemoryRegion *mr);
+
 #endif
 
 #endif
diff --git a/memory.c b/memory.c
index e839c9e..df0ed0e 100644
--- a/memory.c
+++ b/memory.c
@@ -13,6 +13,7 @@
 
 #include "memory.h"
 #include "exec-memory.h"
+#include "ioport.h"
 #include <assert.h>
 
 typedef struct AddrRange AddrRange;
@@ -217,6 +218,52 @@ static AddressSpace address_space_memory = {
     .ops = &address_space_ops_memory,
 };
 
+static void memory_region_iorange_read(IORange *iorange,
+                                       uint64_t offset,
+                                       unsigned width,
+                                       uint64_t *data)
+{
+    MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
+
+    *data = mr->ops->read(mr->opaque, offset, width);
+}
+
+static void memory_region_iorange_write(IORange *iorange,
+                                        uint64_t offset,
+                                        unsigned width,
+                                        uint64_t data)
+{
+    MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
+
+    mr->ops->write(mr->opaque, offset, data, width);
+}
+
+static const IORangeOps memory_region_iorange_ops = {
+    .read = memory_region_iorange_read,
+    .write = memory_region_iorange_write,
+};
+
+static void as_io_range_add(AddressSpace *as, FlatRange *fr)
+{
+    iorange_init(&fr->mr->iorange, &memory_region_iorange_ops,
+                 fr->addr.start,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);
+}
+
+static const AddressSpaceOps address_space_ops_io = {
+    .range_add = as_io_range_add,
+    .range_del = as_io_range_del,
+};
+
+static AddressSpace address_space_io = {
+    .ops = &address_space_ops_io,
+};
+
 /* Render a memory region into the global view.  Ranges in @view obscure
  * ranges in @mr.
  */
@@ -365,7 +412,12 @@ static void address_space_update_topology(AddressSpace *as)
 
 static void memory_region_update_topology(void)
 {
-    address_space_update_topology(&address_space_memory);
+    if (address_space_memory.root) {
+        address_space_update_topology(&address_space_memory);
+    }
+    if (address_space_io.root) {
+        address_space_update_topology(&address_space_io);
+    }
 }
 
 void memory_region_init(MemoryRegion *mr,
@@ -777,3 +829,9 @@ void set_system_memory_map(MemoryRegion *mr)
     address_space_memory.root = mr;
     memory_region_update_topology();
 }
+
+void set_system_io_map(MemoryRegion *mr)
+{
+    address_space_io.root = mr;
+    memory_region_update_topology();
+}
diff --git a/memory.h b/memory.h
index c481038..88ba428 100644
--- a/memory.h
+++ b/memory.h
@@ -22,6 +22,7 @@
 #include "cpu-common.h"
 #include "targphys.h"
 #include "qemu-queue.h"
+#include "iorange.h"
 
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegion MemoryRegion;
@@ -91,6 +92,7 @@ struct MemoryRegion {
     target_phys_addr_t offset;
     bool backend_registered;
     ram_addr_t ram_addr;
+    IORange iorange;
     bool terminates;
     MemoryRegion *alias;
     target_phys_addr_t alias_offset;
commit 16ef61c9e56657d39760e5ad6b9f5361f00b2083
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:07 2011 +0300

    memory: late initialization of ram_addr
    
    For non-RAM memory regions, we cannot tell whether this is an I/O region
    or an MMIO region.  Since the qemu backing registration is different for
    the two, we have to defer initialization until we know which address
    space we are in.
    
    These shenanigans will be removed once the backing registration is unified
    with the memory API.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/memory.c b/memory.c
index 9e1a838..e839c9e 100644
--- a/memory.c
+++ b/memory.c
@@ -165,10 +165,14 @@ static void flatview_simplify(FlatView *view)
     }
 }
 
+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
@@ -519,6 +523,19 @@ 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->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
+                                          memory_region_write_thunk,
+                                          mr,
+                                          mr->ops->endianness);
+    mr->backend_registered = true;
+}
+
 void memory_region_init_io(MemoryRegion *mr,
                            const MemoryRegionOps *ops,
                            void *opaque,
@@ -529,10 +546,7 @@ void memory_region_init_io(MemoryRegion *mr,
     mr->ops = ops;
     mr->opaque = opaque;
     mr->terminates = true;
-    mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
-                                          memory_region_write_thunk,
-                                          mr,
-                                          mr->ops->endianness);
+    mr->backend_registered = false;
 }
 
 void memory_region_init_ram(MemoryRegion *mr,
@@ -543,6 +557,7 @@ void memory_region_init_ram(MemoryRegion *mr,
     memory_region_init(mr, name, size);
     mr->terminates = true;
     mr->ram_addr = qemu_ram_alloc(dev, name, size);
+    mr->backend_registered = true;
 }
 
 void memory_region_init_ram_ptr(MemoryRegion *mr,
@@ -554,6 +569,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr,
     memory_region_init(mr, name, size);
     mr->terminates = true;
     mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr);
+    mr->backend_registered = true;
 }
 
 void memory_region_init_alias(MemoryRegion *mr,
diff --git a/memory.h b/memory.h
index 47d6b9d..c481038 100644
--- a/memory.h
+++ b/memory.h
@@ -89,6 +89,7 @@ struct MemoryRegion {
     uint64_t size;
     target_phys_addr_t addr;
     target_phys_addr_t offset;
+    bool backend_registered;
     ram_addr_t ram_addr;
     bool terminates;
     MemoryRegion *alias;
commit 14a3c10ac890e1982e55bffa37aaca764b4b525b
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:06 2011 +0300

    memory: rename MemoryRegion::has_ram_addr to ::terminates
    
    I/O regions will not have ram_addrs, so this is a better name.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/memory.c b/memory.c
index bae7765..9e1a838 100644
--- a/memory.c
+++ b/memory.c
@@ -251,7 +251,7 @@ static void render_memory_region(FlatView *view,
         render_memory_region(view, subregion, base, clip);
     }
 
-    if (!mr->has_ram_addr) {
+    if (!mr->terminates) {
         return;
     }
 
@@ -373,7 +373,7 @@ void memory_region_init(MemoryRegion *mr,
     mr->size = size;
     mr->addr = 0;
     mr->offset = 0;
-    mr->has_ram_addr = false;
+    mr->terminates = false;
     mr->priority = 0;
     mr->may_overlap = false;
     mr->alias = NULL;
@@ -528,7 +528,7 @@ void memory_region_init_io(MemoryRegion *mr,
     memory_region_init(mr, name, size);
     mr->ops = ops;
     mr->opaque = opaque;
-    mr->has_ram_addr = true;
+    mr->terminates = true;
     mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
                                           memory_region_write_thunk,
                                           mr,
@@ -541,7 +541,7 @@ void memory_region_init_ram(MemoryRegion *mr,
                             uint64_t size)
 {
     memory_region_init(mr, name, size);
-    mr->has_ram_addr = true;
+    mr->terminates = true;
     mr->ram_addr = qemu_ram_alloc(dev, name, size);
 }
 
@@ -552,7 +552,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr,
                                 void *ptr)
 {
     memory_region_init(mr, name, size);
-    mr->has_ram_addr = true;
+    mr->terminates = true;
     mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr);
 }
 
@@ -595,13 +595,13 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
 bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
                              unsigned client)
 {
-    assert(mr->has_ram_addr);
+    assert(mr->terminates);
     return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1 << client);
 }
 
 void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr)
 {
-    assert(mr->has_ram_addr);
+    assert(mr->terminates);
     return cpu_physical_memory_set_dirty(mr->ram_addr + addr);
 }
 
@@ -625,7 +625,7 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
 void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
                                target_phys_addr_t size, unsigned client)
 {
-    assert(mr->has_ram_addr);
+    assert(mr->terminates);
     cpu_physical_memory_reset_dirty(mr->ram_addr + addr,
                                     mr->ram_addr + addr + size,
                                     1 << client);
@@ -637,7 +637,7 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr)
         return memory_region_get_ram_ptr(mr->alias) + mr->alias_offset;
     }
 
-    assert(mr->has_ram_addr);
+    assert(mr->terminates);
 
     return qemu_get_ram_ptr(mr->ram_addr);
 }
diff --git a/memory.h b/memory.h
index d441bd8..47d6b9d 100644
--- a/memory.h
+++ b/memory.h
@@ -90,7 +90,7 @@ struct MemoryRegion {
     target_phys_addr_t addr;
     target_phys_addr_t offset;
     ram_addr_t ram_addr;
-    bool has_ram_addr;
+    bool terminates;
     MemoryRegion *alias;
     target_phys_addr_t alias_offset;
     unsigned priority;
commit cc31e6e7b3a96d99493049ec9f4fe8eaefacbaa8
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:05 2011 +0300

    memory: abstract address space operations
    
    Prepare for multiple address space support by abstracting away the details
    of registering a memory range with qemu's flat representation into an
    AddressSpace object.
    
    Note operations which are memory specific are not abstracted, since they will
    never be called on I/O address spaces anyway.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/memory.c b/memory.c
index fcb612e..bae7765 100644
--- a/memory.c
+++ b/memory.c
@@ -82,12 +82,26 @@ struct FlatView {
     unsigned nr_allocated;
 };
 
+typedef struct AddressSpace AddressSpace;
+typedef struct AddressSpaceOps AddressSpaceOps;
+
+/* A system address space - I/O, memory, etc. */
+struct AddressSpace {
+    const AddressSpaceOps *ops;
+    MemoryRegion *root;
+    FlatView current_map;
+};
+
+struct AddressSpaceOps {
+    void (*range_add)(AddressSpace *as, FlatRange *fr);
+    void (*range_del)(AddressSpace *as, FlatRange *fr);
+    void (*log_start)(AddressSpace *as, FlatRange *fr);
+    void (*log_stop)(AddressSpace *as, FlatRange *fr);
+};
+
 #define FOR_EACH_FLAT_RANGE(var, view)          \
     for (var = (view)->ranges; var < (view)->ranges + (view)->nr; ++var)
 
-static FlatView current_memory_map;
-static MemoryRegion *root_memory_region;
-
 static bool flatrange_equal(FlatRange *a, FlatRange *b)
 {
     return a->mr == b->mr
@@ -151,6 +165,54 @@ static void flatview_simplify(FlatView *view)
     }
 }
 
+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 ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
+        phys_offset += region_offset;
+        region_offset = 0;
+    }
+
+    cpu_register_physical_memory_log(fr->addr.start,
+                                     fr->addr.size,
+                                     phys_offset,
+                                     region_offset,
+                                     fr->dirty_log_mask);
+}
+
+static void as_memory_range_del(AddressSpace *as, FlatRange *fr)
+{
+    cpu_register_physical_memory(fr->addr.start, 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);
+}
+
+static void as_memory_log_stop(AddressSpace *as, FlatRange *fr)
+{
+    cpu_physical_log_stop(fr->addr.start, fr->addr.size);
+}
+
+static const AddressSpaceOps address_space_ops_memory = {
+    .range_add = as_memory_range_add,
+    .range_del = as_memory_range_del,
+    .log_start = as_memory_log_start,
+    .log_stop = as_memory_log_stop,
+};
+
+static AddressSpace address_space_memory = {
+    .ops = &address_space_ops_memory,
+};
+
 /* Render a memory region into the global view.  Ranges in @view obscure
  * ranges in @mr.
  */
@@ -243,13 +305,12 @@ static FlatView generate_memory_topology(MemoryRegion *mr)
     return view;
 }
 
-static void memory_region_update_topology(void)
+static void address_space_update_topology(AddressSpace *as)
 {
-    FlatView old_view = current_memory_map;
-    FlatView new_view = generate_memory_topology(root_memory_region);
+    FlatView old_view = as->current_map;
+    FlatView new_view = generate_memory_topology(as->root);
     unsigned iold, inew;
     FlatRange *frold, *frnew;
-    ram_addr_t phys_offset, region_offset;
 
     /* Generate a symmetric difference of the old and new memory maps.
      * Kill ranges in the old map, and instantiate ranges in the new map.
@@ -274,16 +335,15 @@ static void memory_region_update_topology(void)
                     && !flatrange_equal(frold, frnew)))) {
             /* In old, but (not in new, or in new but attributes changed). */
 
-            cpu_register_physical_memory(frold->addr.start, frold->addr.size,
-                                         IO_MEM_UNASSIGNED);
+            as->ops->range_del(as, frold);
             ++iold;
         } else if (frold && frnew && flatrange_equal(frold, frnew)) {
             /* In both (logging may have changed) */
 
             if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
-                cpu_physical_log_stop(frnew->addr.start, frnew->addr.size);
+                as->ops->log_stop(as, frnew);
             } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
-                cpu_physical_log_start(frnew->addr.start, frnew->addr.size);
+                as->ops->log_start(as, frnew);
             }
 
             ++iold;
@@ -291,28 +351,19 @@ static void memory_region_update_topology(void)
         } else {
             /* In new */
 
-            phys_offset = frnew->mr->ram_addr;
-            region_offset = frnew->offset_in_region;
-            /* 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) {
-                phys_offset += region_offset;
-                region_offset = 0;
-            }
-
-            cpu_register_physical_memory_log(frnew->addr.start,
-                                             frnew->addr.size,
-                                             phys_offset,
-                                             region_offset,
-                                             frnew->dirty_log_mask);
+            as->ops->range_add(as, frnew);
             ++inew;
         }
     }
-    current_memory_map = new_view;
+    as->current_map = new_view;
     flatview_destroy(&old_view);
 }
 
+static void memory_region_update_topology(void)
+{
+    address_space_update_topology(&address_space_memory);
+}
+
 void memory_region_init(MemoryRegion *mr,
                         const char *name,
                         uint64_t size)
@@ -558,7 +609,7 @@ void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
 {
     FlatRange *fr;
 
-    FOR_EACH_FLAT_RANGE(fr, &current_memory_map) {
+    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);
@@ -597,7 +648,7 @@ static void memory_region_update_coalesced_range(MemoryRegion *mr)
     CoalescedMemoryRange *cmr;
     AddrRange tmp;
 
-    FOR_EACH_FLAT_RANGE(fr, &current_memory_map) {
+    FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) {
         if (fr->mr == mr) {
             qemu_unregister_coalesced_mmio(fr->addr.start, fr->addr.size);
             QTAILQ_FOREACH(cmr, &mr->coalesced, link) {
@@ -707,6 +758,6 @@ void memory_region_del_subregion(MemoryRegion *mr,
 
 void set_system_memory_map(MemoryRegion *mr)
 {
-    root_memory_region = mr;
+    address_space_memory.root = mr;
     memory_region_update_topology();
 }
commit 1c0ffa58afab4d8496795d29b70d5e9e67e9341e
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:04 2011 +0300

    Internal interfaces for memory API
    
    get_system_memory() provides the root of the memory hierarchy.
    
    This interface is intended to be private between memory.c and exec.c.
    If this file is included elsewhere, it should be regarded as a bug (or
    TODO item).  However, it will be temporarily needed for the conversion
    to hierarchical memory routing.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/exec-memory.h b/exec-memory.h
new file mode 100644
index 0000000..aea1b45
--- /dev/null
+++ b/exec-memory.h
@@ -0,0 +1,36 @@
+/*
+ * Internal memory managment interfaces
+ *
+ * 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.
+ *
+ */
+
+#ifndef EXEC_MEMORY_H
+#define EXEC_MEMORY_H
+
+/*
+ * Internal interfaces between memory.c/exec.c/vl.c.  Do not #include unless
+ * you're one of them.
+ */
+
+#include "memory.h"
+
+#ifndef CONFIG_USER_ONLY
+
+/* Get the root memory region.  This interface should only be used temporarily
+ * until a proper bus interface is available.
+ */
+MemoryRegion *get_system_memory(void);
+
+/* Set the root memory region.  This region is the system memory map. */
+void set_system_memory_map(MemoryRegion *mr);
+
+#endif
+
+#endif
diff --git a/memory.c b/memory.c
index 121f9e1..fcb612e 100644
--- a/memory.c
+++ b/memory.c
@@ -12,6 +12,7 @@
  */
 
 #include "memory.h"
+#include "exec-memory.h"
 #include <assert.h>
 
 typedef struct AddrRange AddrRange;
@@ -703,3 +704,9 @@ void memory_region_del_subregion(MemoryRegion *mr,
     QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
     memory_region_update_topology();
 }
+
+void set_system_memory_map(MemoryRegion *mr)
+{
+    root_memory_region = mr;
+    memory_region_update_topology();
+}
commit 3d8e6bf97781a8415fd08ba1770269e1332c200c
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:03 2011 +0300

    memory: merge adjacent segments of a single memory region
    
    Simple implementations of memory routers, for example the Cirrus VGA memory banks
    or the 440FX PAM registers can generate adjacent memory regions which are contiguous.
    Detect these and merge them; this saves kvm memory slots and shortens lookup times.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/memory.c b/memory.c
index d858b47..121f9e1 100644
--- a/memory.c
+++ b/memory.c
@@ -122,6 +122,34 @@ static void flatview_destroy(FlatView *view)
     qemu_free(view->ranges);
 }
 
+static bool can_merge(FlatRange *r1, FlatRange *r2)
+{
+    return addrrange_end(r1->addr) == r2->addr.start
+        && r1->mr == r2->mr
+        && r1->offset_in_region + r1->addr.size == r2->offset_in_region
+        && r1->dirty_log_mask == r2->dirty_log_mask;
+}
+
+/* Attempt to simplify a view by merging ajacent ranges */
+static void flatview_simplify(FlatView *view)
+{
+    unsigned i, j;
+
+    i = 0;
+    while (i < view->nr) {
+        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;
+            ++j;
+        }
+        ++i;
+        memmove(&view->ranges[i], &view->ranges[j],
+                (view->nr - j) * sizeof(view->ranges[j]));
+        view->nr -= j - i;
+    }
+}
+
 /* Render a memory region into the global view.  Ranges in @view obscure
  * ranges in @mr.
  */
@@ -209,6 +237,7 @@ static FlatView generate_memory_topology(MemoryRegion *mr)
     flatview_init(&view);
 
     render_memory_region(&view, mr, 0, addrrange_make(0, UINT64_MAX));
+    flatview_simplify(&view);
 
     return view;
 }
commit 5a583347697413f964d886b074860cb888c0e306
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:02 2011 +0300

    memory: implement dirty tracking
    
    Currently dirty tracking is implemented by passing through
    all calls to the underlying cpu_physical_memory_*() calls.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/memory.c b/memory.c
index a9cf317..d858b47 100644
--- a/memory.c
+++ b/memory.c
@@ -69,6 +69,7 @@ struct FlatRange {
     MemoryRegion *mr;
     target_phys_addr_t offset_in_region;
     AddrRange addr;
+    uint8_t dirty_log_mask;
 };
 
 /* Flattened global view of current active memory hierarchy.  Kept in sorted
@@ -177,6 +178,7 @@ static void render_memory_region(FlatView *view,
             fr.mr = mr;
             fr.offset_in_region = offset_in_region;
             fr.addr = addrrange_make(base, now);
+            fr.dirty_log_mask = mr->dirty_log_mask;
             flatview_insert(view, i, &fr);
             ++i;
             base += now;
@@ -194,6 +196,7 @@ static void render_memory_region(FlatView *view,
         fr.mr = mr;
         fr.offset_in_region = offset_in_region;
         fr.addr = addrrange_make(base, remain);
+        fr.dirty_log_mask = mr->dirty_log_mask;
         flatview_insert(view, i, &fr);
     }
 }
@@ -247,9 +250,14 @@ static void memory_region_update_topology(void)
         } else if (frold && frnew && flatrange_equal(frold, frnew)) {
             /* In both (logging may have changed) */
 
+            if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
+                cpu_physical_log_stop(frnew->addr.start, frnew->addr.size);
+            } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
+                cpu_physical_log_start(frnew->addr.start, frnew->addr.size);
+            }
+
             ++iold;
             ++inew;
-            /* FIXME: dirty logging */
         } else {
             /* In new */
 
@@ -267,7 +275,7 @@ static void memory_region_update_topology(void)
                                              frnew->addr.size,
                                              phys_offset,
                                              region_offset,
-                                             0);
+                                             frnew->dirty_log_mask);
             ++inew;
         }
     }
@@ -292,6 +300,7 @@ void memory_region_init(MemoryRegion *mr,
     memset(&mr->subregions_link, 0, sizeof mr->subregions_link);
     QTAILQ_INIT(&mr->coalesced);
     mr->name = qemu_strdup(name);
+    mr->dirty_log_mask = 0;
 }
 
 static bool memory_region_access_valid(MemoryRegion *mr,
@@ -496,24 +505,35 @@ void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset)
 
 void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
 {
-    /* FIXME */
+    uint8_t mask = 1 << client;
+
+    mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask);
+    memory_region_update_topology();
 }
 
 bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
                              unsigned client)
 {
-    /* FIXME */
-    return true;
+    assert(mr->has_ram_addr);
+    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1 << client);
 }
 
 void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr)
 {
-    /* FIXME */
+    assert(mr->has_ram_addr);
+    return cpu_physical_memory_set_dirty(mr->ram_addr + addr);
 }
 
 void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
 {
-    /* FIXME */
+    FlatRange *fr;
+
+    FOR_EACH_FLAT_RANGE(fr, &current_memory_map) {
+        if (fr->mr == mr) {
+            cpu_physical_sync_dirty_bitmap(fr->addr.start,
+                                           fr->addr.start + fr->addr.size);
+        }
+    }
 }
 
 void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
@@ -524,7 +544,10 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
 void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
                                target_phys_addr_t size, unsigned client)
 {
-    /* FIXME */
+    assert(mr->has_ram_addr);
+    cpu_physical_memory_reset_dirty(mr->ram_addr + addr,
+                                    mr->ram_addr + addr + size,
+                                    1 << client);
 }
 
 void *memory_region_get_ram_ptr(MemoryRegion *mr)
diff --git a/memory.h b/memory.h
index a4c94bd..d441bd8 100644
--- a/memory.h
+++ b/memory.h
@@ -99,6 +99,7 @@ struct MemoryRegion {
     QTAILQ_ENTRY(MemoryRegion) subregions_link;
     QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced;
     const char *name;
+    uint8_t dirty_log_mask;
 };
 
 /**
commit 093bc2cd885e4e3420509a80a1b9e81848e4b8fe
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:01 2011 +0300

    Hierarchical memory region API
    
    The memory API separates the attributes of a memory region (its size, how
    reads or writes are handled, dirty logging, and coalescing) from where it
    is mapped and whether it is enabled.  This allows a device to configure
    a memory region once, then hand it off to its parent bus to map it according
    to the bus configuration.
    
    Hierarchical registration also allows a device to compose a region out of
    a number of sub-regions with different properties; for example some may be
    RAM while others may be MMIO.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile.target b/Makefile.target
index cde509b..8884a56 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -198,6 +198,7 @@ obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
 obj-y += rwhandler.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
+obj-y += memory.o
 LIBS+=-lz
 
 QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
diff --git a/memory.c b/memory.c
new file mode 100644
index 0000000..a9cf317
--- /dev/null
+++ b/memory.c
@@ -0,0 +1,653 @@
+/*
+ * Physical memory management
+ *
+ * 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.
+ *
+ */
+
+#include "memory.h"
+#include <assert.h>
+
+typedef struct AddrRange AddrRange;
+
+struct AddrRange {
+    uint64_t start;
+    uint64_t size;
+};
+
+static AddrRange addrrange_make(uint64_t start, uint64_t size)
+{
+    return (AddrRange) { start, size };
+}
+
+static bool addrrange_equal(AddrRange r1, AddrRange r2)
+{
+    return r1.start == r2.start && r1.size == r2.size;
+}
+
+static uint64_t addrrange_end(AddrRange r)
+{
+    return r.start + r.size;
+}
+
+static AddrRange addrrange_shift(AddrRange range, int64_t delta)
+{
+    range.start += delta;
+    return 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);
+}
+
+static AddrRange addrrange_intersection(AddrRange r1, AddrRange r2)
+{
+    uint64_t start = MAX(r1.start, r2.start);
+    /* off-by-one arithmetic to prevent overflow */
+    uint64_t end = MIN(addrrange_end(r1) - 1, addrrange_end(r2) - 1);
+    return addrrange_make(start, end - start + 1);
+}
+
+struct CoalescedMemoryRange {
+    AddrRange addr;
+    QTAILQ_ENTRY(CoalescedMemoryRange) link;
+};
+
+typedef struct FlatRange FlatRange;
+typedef struct FlatView FlatView;
+
+/* Range of memory in the global map.  Addresses are absolute. */
+struct FlatRange {
+    MemoryRegion *mr;
+    target_phys_addr_t offset_in_region;
+    AddrRange addr;
+};
+
+/* Flattened global view of current active memory hierarchy.  Kept in sorted
+ * order.
+ */
+struct FlatView {
+    FlatRange *ranges;
+    unsigned nr;
+    unsigned nr_allocated;
+};
+
+#define FOR_EACH_FLAT_RANGE(var, view)          \
+    for (var = (view)->ranges; var < (view)->ranges + (view)->nr; ++var)
+
+static FlatView current_memory_map;
+static MemoryRegion *root_memory_region;
+
+static bool flatrange_equal(FlatRange *a, FlatRange *b)
+{
+    return a->mr == b->mr
+        && addrrange_equal(a->addr, b->addr)
+        && a->offset_in_region == b->offset_in_region;
+}
+
+static void flatview_init(FlatView *view)
+{
+    view->ranges = NULL;
+    view->nr = 0;
+    view->nr_allocated = 0;
+}
+
+/* Insert a range into a given position.  Caller is responsible for maintaining
+ * sorting order.
+ */
+static void flatview_insert(FlatView *view, unsigned pos, FlatRange *range)
+{
+    if (view->nr == view->nr_allocated) {
+        view->nr_allocated = MAX(2 * view->nr, 10);
+        view->ranges = qemu_realloc(view->ranges,
+                                    view->nr_allocated * sizeof(*view->ranges));
+    }
+    memmove(view->ranges + pos + 1, view->ranges + pos,
+            (view->nr - pos) * sizeof(FlatRange));
+    view->ranges[pos] = *range;
+    ++view->nr;
+}
+
+static void flatview_destroy(FlatView *view)
+{
+    qemu_free(view->ranges);
+}
+
+/* Render a memory region into the global view.  Ranges in @view obscure
+ * ranges in @mr.
+ */
+static void render_memory_region(FlatView *view,
+                                 MemoryRegion *mr,
+                                 target_phys_addr_t base,
+                                 AddrRange clip)
+{
+    MemoryRegion *subregion;
+    unsigned i;
+    target_phys_addr_t offset_in_region;
+    uint64_t remain;
+    uint64_t now;
+    FlatRange fr;
+    AddrRange tmp;
+
+    base += mr->addr;
+
+    tmp = addrrange_make(base, mr->size);
+
+    if (!addrrange_intersects(tmp, clip)) {
+        return;
+    }
+
+    clip = addrrange_intersection(tmp, clip);
+
+    if (mr->alias) {
+        base -= mr->alias->addr;
+        base -= mr->alias_offset;
+        render_memory_region(view, mr->alias, base, clip);
+        return;
+    }
+
+    /* Render subregions in priority order. */
+    QTAILQ_FOREACH(subregion, &mr->subregions, subregions_link) {
+        render_memory_region(view, subregion, base, clip);
+    }
+
+    if (!mr->has_ram_addr) {
+        return;
+    }
+
+    offset_in_region = 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)) {
+            continue;
+        }
+        if (base < view->ranges[i].addr.start) {
+            now = MIN(remain, view->ranges[i].addr.start - base);
+            fr.mr = mr;
+            fr.offset_in_region = offset_in_region;
+            fr.addr = addrrange_make(base, now);
+            flatview_insert(view, i, &fr);
+            ++i;
+            base += now;
+            offset_in_region += now;
+            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 (remain) {
+        fr.mr = mr;
+        fr.offset_in_region = offset_in_region;
+        fr.addr = addrrange_make(base, remain);
+        flatview_insert(view, i, &fr);
+    }
+}
+
+/* Render a memory topology into a list of disjoint absolute ranges. */
+static FlatView generate_memory_topology(MemoryRegion *mr)
+{
+    FlatView view;
+
+    flatview_init(&view);
+
+    render_memory_region(&view, mr, 0, addrrange_make(0, UINT64_MAX));
+
+    return view;
+}
+
+static void memory_region_update_topology(void)
+{
+    FlatView old_view = current_memory_map;
+    FlatView new_view = generate_memory_topology(root_memory_region);
+    unsigned iold, inew;
+    FlatRange *frold, *frnew;
+    ram_addr_t phys_offset, region_offset;
+
+    /* Generate a symmetric difference of the old and new memory maps.
+     * Kill ranges in the old map, and instantiate ranges in the new map.
+     */
+    iold = inew = 0;
+    while (iold < old_view.nr || inew < new_view.nr) {
+        if (iold < old_view.nr) {
+            frold = &old_view.ranges[iold];
+        } else {
+            frold = NULL;
+        }
+        if (inew < new_view.nr) {
+            frnew = &new_view.ranges[inew];
+        } else {
+            frnew = NULL;
+        }
+
+        if (frold
+            && (!frnew
+                || frold->addr.start < frnew->addr.start
+                || (frold->addr.start == frnew->addr.start
+                    && !flatrange_equal(frold, frnew)))) {
+            /* In old, but (not in new, or in new but attributes changed). */
+
+            cpu_register_physical_memory(frold->addr.start, frold->addr.size,
+                                         IO_MEM_UNASSIGNED);
+            ++iold;
+        } else if (frold && frnew && flatrange_equal(frold, frnew)) {
+            /* In both (logging may have changed) */
+
+            ++iold;
+            ++inew;
+            /* FIXME: dirty logging */
+        } else {
+            /* In new */
+
+            phys_offset = frnew->mr->ram_addr;
+            region_offset = frnew->offset_in_region;
+            /* 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) {
+                phys_offset += region_offset;
+                region_offset = 0;
+            }
+
+            cpu_register_physical_memory_log(frnew->addr.start,
+                                             frnew->addr.size,
+                                             phys_offset,
+                                             region_offset,
+                                             0);
+            ++inew;
+        }
+    }
+    current_memory_map = new_view;
+    flatview_destroy(&old_view);
+}
+
+void memory_region_init(MemoryRegion *mr,
+                        const char *name,
+                        uint64_t size)
+{
+    mr->ops = NULL;
+    mr->parent = NULL;
+    mr->size = size;
+    mr->addr = 0;
+    mr->offset = 0;
+    mr->has_ram_addr = false;
+    mr->priority = 0;
+    mr->may_overlap = false;
+    mr->alias = NULL;
+    QTAILQ_INIT(&mr->subregions);
+    memset(&mr->subregions_link, 0, sizeof mr->subregions_link);
+    QTAILQ_INIT(&mr->coalesced);
+    mr->name = qemu_strdup(name);
+}
+
+static bool memory_region_access_valid(MemoryRegion *mr,
+                                       target_phys_addr_t addr,
+                                       unsigned size)
+{
+    if (!mr->ops->valid.unaligned && (addr & (size - 1))) {
+        return false;
+    }
+
+    /* Treat zero as compatibility all valid */
+    if (!mr->ops->valid.max_access_size) {
+        return true;
+    }
+
+    if (size > mr->ops->valid.max_access_size
+        || size < mr->ops->valid.min_access_size) {
+        return false;
+    }
+    return true;
+}
+
+static uint32_t memory_region_read_thunk_n(void *_mr,
+                                           target_phys_addr_t addr,
+                                           unsigned size)
+{
+    MemoryRegion *mr = _mr;
+    unsigned access_size, access_size_min, access_size_max;
+    uint64_t access_mask;
+    uint32_t data = 0, tmp;
+    unsigned i;
+
+    if (!memory_region_access_valid(mr, addr, size)) {
+        return -1U; /* FIXME: better signalling */
+    }
+
+    /* FIXME: support unaligned access */
+
+    access_size_min = mr->ops->impl.min_access_size;
+    if (!access_size_min) {
+        access_size_min = 1;
+    }
+    access_size_max = mr->ops->impl.max_access_size;
+    if (!access_size_max) {
+        access_size_max = 4;
+    }
+    access_size = MAX(MIN(size, access_size_max), access_size_min);
+    access_mask = -1ULL >> (64 - access_size * 8);
+    addr += mr->offset;
+    for (i = 0; i < size; i += access_size) {
+        /* FIXME: big-endian support */
+        tmp = mr->ops->read(mr->opaque, addr + i, access_size);
+        data |= (tmp & access_mask) << (i * 8);
+    }
+
+    return data;
+}
+
+static void memory_region_write_thunk_n(void *_mr,
+                                        target_phys_addr_t addr,
+                                        unsigned size,
+                                        uint64_t data)
+{
+    MemoryRegion *mr = _mr;
+    unsigned access_size, access_size_min, access_size_max;
+    uint64_t access_mask;
+    unsigned i;
+
+    if (!memory_region_access_valid(mr, addr, size)) {
+        return; /* FIXME: better signalling */
+    }
+
+    /* FIXME: support unaligned access */
+
+    access_size_min = mr->ops->impl.min_access_size;
+    if (!access_size_min) {
+        access_size_min = 1;
+    }
+    access_size_max = mr->ops->impl.max_access_size;
+    if (!access_size_max) {
+        access_size_max = 4;
+    }
+    access_size = MAX(MIN(size, access_size_max), access_size_min);
+    access_mask = -1ULL >> (64 - access_size * 8);
+    addr += mr->offset;
+    for (i = 0; i < size; i += access_size) {
+        /* FIXME: big-endian support */
+        mr->ops->write(mr->opaque, addr + i, (data >> (i * 8)) & access_mask,
+                       access_size);
+    }
+}
+
+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)
+{
+    return memory_region_read_thunk_n(mr, addr, 2);
+}
+
+static uint32_t memory_region_read_thunk_l(void *mr, target_phys_addr_t addr)
+{
+    return memory_region_read_thunk_n(mr, addr, 4);
+}
+
+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)
+{
+    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)
+{
+    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,
+                           const char *name,
+                           uint64_t size)
+{
+    memory_region_init(mr, name, size);
+    mr->ops = ops;
+    mr->opaque = opaque;
+    mr->has_ram_addr = true;
+    mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
+                                          memory_region_write_thunk,
+                                          mr,
+                                          mr->ops->endianness);
+}
+
+void memory_region_init_ram(MemoryRegion *mr,
+                            DeviceState *dev,
+                            const char *name,
+                            uint64_t size)
+{
+    memory_region_init(mr, name, size);
+    mr->has_ram_addr = true;
+    mr->ram_addr = qemu_ram_alloc(dev, name, size);
+}
+
+void memory_region_init_ram_ptr(MemoryRegion *mr,
+                                DeviceState *dev,
+                                const char *name,
+                                uint64_t size,
+                                void *ptr)
+{
+    memory_region_init(mr, name, size);
+    mr->has_ram_addr = true;
+    mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr);
+}
+
+void memory_region_init_alias(MemoryRegion *mr,
+                              const char *name,
+                              MemoryRegion *orig,
+                              target_phys_addr_t offset,
+                              uint64_t size)
+{
+    memory_region_init(mr, name, size);
+    mr->alias = orig;
+    mr->alias_offset = offset;
+}
+
+void memory_region_destroy(MemoryRegion *mr)
+{
+    assert(QTAILQ_EMPTY(&mr->subregions));
+    memory_region_clear_coalescing(mr);
+    qemu_free((char *)mr->name);
+}
+
+uint64_t memory_region_size(MemoryRegion *mr)
+{
+    return mr->size;
+}
+
+void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset)
+{
+    mr->offset = offset;
+}
+
+void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
+{
+    /* FIXME */
+}
+
+bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                             unsigned client)
+{
+    /* FIXME */
+    return true;
+}
+
+void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr)
+{
+    /* FIXME */
+}
+
+void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
+{
+    /* FIXME */
+}
+
+void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
+{
+    /* FIXME */
+}
+
+void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                               target_phys_addr_t size, unsigned client)
+{
+    /* FIXME */
+}
+
+void *memory_region_get_ram_ptr(MemoryRegion *mr)
+{
+    if (mr->alias) {
+        return memory_region_get_ram_ptr(mr->alias) + mr->alias_offset;
+    }
+
+    assert(mr->has_ram_addr);
+
+    return qemu_get_ram_ptr(mr->ram_addr);
+}
+
+static void memory_region_update_coalesced_range(MemoryRegion *mr)
+{
+    FlatRange *fr;
+    CoalescedMemoryRange *cmr;
+    AddrRange tmp;
+
+    FOR_EACH_FLAT_RANGE(fr, &current_memory_map) {
+        if (fr->mr == mr) {
+            qemu_unregister_coalesced_mmio(fr->addr.start, fr->addr.size);
+            QTAILQ_FOREACH(cmr, &mr->coalesced, link) {
+                tmp = addrrange_shift(cmr->addr,
+                                      fr->addr.start - 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);
+            }
+        }
+    }
+}
+
+void memory_region_set_coalescing(MemoryRegion *mr)
+{
+    memory_region_clear_coalescing(mr);
+    memory_region_add_coalescing(mr, 0, mr->size);
+}
+
+void memory_region_add_coalescing(MemoryRegion *mr,
+                                  target_phys_addr_t offset,
+                                  uint64_t size)
+{
+    CoalescedMemoryRange *cmr = qemu_malloc(sizeof(*cmr));
+
+    cmr->addr = addrrange_make(offset, size);
+    QTAILQ_INSERT_TAIL(&mr->coalesced, cmr, link);
+    memory_region_update_coalesced_range(mr);
+}
+
+void memory_region_clear_coalescing(MemoryRegion *mr)
+{
+    CoalescedMemoryRange *cmr;
+
+    while (!QTAILQ_EMPTY(&mr->coalesced)) {
+        cmr = QTAILQ_FIRST(&mr->coalesced);
+        QTAILQ_REMOVE(&mr->coalesced, cmr, link);
+        qemu_free(cmr);
+    }
+    memory_region_update_coalesced_range(mr);
+}
+
+static void memory_region_add_subregion_common(MemoryRegion *mr,
+                                               target_phys_addr_t offset,
+                                               MemoryRegion *subregion)
+{
+    MemoryRegion *other;
+
+    assert(!subregion->parent);
+    subregion->parent = mr;
+    subregion->addr = offset;
+    QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
+        if (subregion->may_overlap || other->may_overlap) {
+            continue;
+        }
+        if (offset >= other->offset + other->size
+            || offset + subregion->size <= other->offset) {
+            continue;
+        }
+        printf("warning: subregion collision %llx/%llx vs %llx/%llx\n",
+               (unsigned long long)offset,
+               (unsigned long long)subregion->size,
+               (unsigned long long)other->offset,
+               (unsigned long long)other->size);
+    }
+    QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
+        if (subregion->priority >= other->priority) {
+            QTAILQ_INSERT_BEFORE(other, subregion, subregions_link);
+            goto done;
+        }
+    }
+    QTAILQ_INSERT_TAIL(&mr->subregions, subregion, subregions_link);
+done:
+    memory_region_update_topology();
+}
+
+
+void memory_region_add_subregion(MemoryRegion *mr,
+                                 target_phys_addr_t offset,
+                                 MemoryRegion *subregion)
+{
+    subregion->may_overlap = false;
+    subregion->priority = 0;
+    memory_region_add_subregion_common(mr, offset, subregion);
+}
+
+void memory_region_add_subregion_overlap(MemoryRegion *mr,
+                                         target_phys_addr_t offset,
+                                         MemoryRegion *subregion,
+                                         unsigned priority)
+{
+    subregion->may_overlap = true;
+    subregion->priority = priority;
+    memory_region_add_subregion_common(mr, offset, subregion);
+}
+
+void memory_region_del_subregion(MemoryRegion *mr,
+                                 MemoryRegion *subregion)
+{
+    assert(subregion->parent == mr);
+    subregion->parent = NULL;
+    QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
+    memory_region_update_topology();
+}
diff --git a/memory.h b/memory.h
new file mode 100644
index 0000000..a4c94bd
--- /dev/null
+++ b/memory.h
@@ -0,0 +1,385 @@
+/*
+ * Physical memory management API
+ *
+ * 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.
+ *
+ */
+
+#ifndef MEMORY_H
+#define MEMORY_H
+
+#ifndef CONFIG_USER_ONLY
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "qemu-common.h"
+#include "cpu-common.h"
+#include "targphys.h"
+#include "qemu-queue.h"
+
+typedef struct MemoryRegionOps MemoryRegionOps;
+typedef struct MemoryRegion MemoryRegion;
+
+/* Must match *_DIRTY_FLAGS in cpu-all.h.  To be replaced with dynamic
+ * registration.
+ */
+#define DIRTY_MEMORY_VGA       0
+#define DIRTY_MEMORY_CODE      1
+#define DIRTY_MEMORY_MIGRATION 3
+
+/*
+ * Memory region callbacks
+ */
+struct MemoryRegionOps {
+    /* Read from the memory region. @addr is relative to @mr; @size is
+     * in bytes. */
+    uint64_t (*read)(void *opaque,
+                     target_phys_addr_t addr,
+                     unsigned size);
+    /* Write to the memory region. @addr is relative to @mr; @size is
+     * in bytes. */
+    void (*write)(void *opaque,
+                  target_phys_addr_t addr,
+                  uint64_t data,
+                  unsigned size);
+
+    enum device_endian endianness;
+    /* Guest-visible constraints: */
+    struct {
+        /* If nonzero, specify bounds on access sizes beyond which a machine
+         * check is thrown.
+         */
+        unsigned min_access_size;
+        unsigned max_access_size;
+        /* If true, unaligned accesses are supported.  Otherwise unaligned
+         * accesses throw machine checks.
+         */
+         bool unaligned;
+    } valid;
+    /* Internal implementation constraints: */
+    struct {
+        /* If nonzero, specifies the minimum size implemented.  Smaller sizes
+         * will be rounded upwards and a partial result will be returned.
+         */
+        unsigned min_access_size;
+        /* If nonzero, specifies the maximum size implemented.  Larger sizes
+         * will be done as a series of accesses with smaller sizes.
+         */
+        unsigned max_access_size;
+        /* If true, unaligned accesses are supported.  Otherwise all accesses
+         * are converted to (possibly multiple) naturally aligned accesses.
+         */
+         bool unaligned;
+    } impl;
+};
+
+typedef struct CoalescedMemoryRange CoalescedMemoryRange;
+
+struct MemoryRegion {
+    /* All fields are private - violators will be prosecuted */
+    const MemoryRegionOps *ops;
+    void *opaque;
+    MemoryRegion *parent;
+    uint64_t size;
+    target_phys_addr_t addr;
+    target_phys_addr_t offset;
+    ram_addr_t ram_addr;
+    bool has_ram_addr;
+    MemoryRegion *alias;
+    target_phys_addr_t alias_offset;
+    unsigned priority;
+    bool may_overlap;
+    QTAILQ_HEAD(subregions, MemoryRegion) subregions;
+    QTAILQ_ENTRY(MemoryRegion) subregions_link;
+    QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced;
+    const char *name;
+};
+
+/**
+ * memory_region_init: Initialize a memory region
+ *
+ * The region typically acts as a container for other memory regions.  Us
+ * memory_region_add_subregion() to add subregions.
+ *
+ * @mr: the #MemoryRegion to be initialized
+ * @name: used for debugging; not visible to the user or ABI
+ * @size: size of the region; any subregions beyond this size will be clipped
+ */
+void memory_region_init(MemoryRegion *mr,
+                        const char *name,
+                        uint64_t size);
+/**
+ * memory_region_init_io: Initialize an I/O memory region.
+ *
+ * Accesses into the region will be cause the callbacks in @ops to be called.
+ * if @size is nonzero, subregions will be clipped to @size.
+ *
+ * @mr: the #MemoryRegion to be initialized.
+ * @ops: a structure containing read and write callbacks to be used when
+ *       I/O is performed on the region.
+ * @opaque: passed to to the read and write callbacks of the @ops structure.
+ * @name: used for debugging; not visible to the user or ABI
+ * @size: size of the region.
+ */
+void memory_region_init_io(MemoryRegion *mr,
+                           const MemoryRegionOps *ops,
+                           void *opaque,
+                           const char *name,
+                           uint64_t size);
+
+/**
+ * memory_region_init_ram:  Initialize RAM memory region.  Accesses into the
+ *                          region will be 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.
+ * @size: size of the region.
+ */
+void memory_region_init_ram(MemoryRegion *mr,
+                            DeviceState *dev, /* FIXME: layering violation */
+                            const char *name,
+                            uint64_t size);
+
+/**
+ * memory_region_init_ram:  Initialize RAM memory region from a user-provided.
+ *                          pointer.  Accesses into the region will be 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.
+ * @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);
+
+/**
+ * memory_region_init_alias: Initialize a memory region that aliases all or a
+ *                           part of another memory region.
+ *
+ * @mr: the #MemoryRegion to be initialized.
+ * @name: used for debugging; not visible to the user or ABI
+ * @orig: the region to be referenced; @mr will be equivalent to
+ *        @orig between @offset and @offset + @size - 1.
+ * @offset: start of the section in @orig to be referenced.
+ * @size: size of the region.
+ */
+void memory_region_init_alias(MemoryRegion *mr,
+                              const char *name,
+                              MemoryRegion *orig,
+                              target_phys_addr_t offset,
+                              uint64_t size);
+/**
+ * memory_region_destroy: Destroy a memory region and relaim all resources.
+ *
+ * @mr: the region to be destroyed.  May not currently be a subregion
+ *      (see memory_region_add_subregion()) or referenced in an alias
+ *      (see memory_region_init_alias()).
+ */
+void memory_region_destroy(MemoryRegion *mr);
+
+/**
+ * memory_region_size: get a memory region's size.
+ *
+ * @mr: the memory region being queried.
+ */
+uint64_t memory_region_size(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
+ * memory_region_init_ram() or memory_region_init_ram_ptr()).  Use with
+ * care.
+ *
+ * @mr: the memory region being queried.
+ */
+void *memory_region_get_ram_ptr(MemoryRegion *mr);
+
+/**
+ * memory_region_set_offset: Sets an offset to be added to MemoryRegionOps
+ *                           callbacks.
+ *
+ * This function is deprecated and should not be used in new code.
+ */
+void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset);
+
+/**
+ * memory_region_set_log: Turn dirty logging on or off for a region.
+ *
+ * Turns dirty logging on or off for a specified client (display, migration).
+ * Only meaningful for RAM regions.
+ *
+ * @mr: the memory region being updated.
+ * @log: whether dirty logging is to be enabled or disabled.
+ * @client: the user of the logging information; %DIRTY_MEMORY_MIGRATION or
+ *          %DIRTY_MEMORY_VGA.
+ */
+void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client);
+
+/**
+ * memory_region_get_dirty: Check whether a page is dirty for a specified
+ *                          client.
+ *
+ * Checks whether a page has been written to since the last
+ * call to memory_region_reset_dirty() with the same @client.  Dirty logging
+ * must be enabled.
+ *
+ * @mr: the memory region being queried.
+ * @addr: the address (relative to the start of the region) being queried.
+ * @client: the user of the logging information; %DIRTY_MEMORY_MIGRATION or
+ *          %DIRTY_MEMORY_VGA.
+ */
+bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                             unsigned client);
+
+/**
+ * memory_region_set_dirty: Mark a page as dirty in a memory region.
+ *
+ * Marks a page as dirty, after it has been dirtied outside guest code.
+ *
+ * @mr: the memory region being queried.
+ * @addr: the address (relative to the start of the region) being dirtied.
+ */
+void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr);
+
+/**
+ * memory_region_sync_dirty_bitmap: Synchronize a region's dirty bitmap with
+ *                                  any external TLBs (e.g. kvm)
+ *
+ * Flushes dirty information from accelerators such as kvm and vhost-net
+ * and makes it available to users of the memory API.
+ *
+ * @mr: the region being flushed.
+ */
+void memory_region_sync_dirty_bitmap(MemoryRegion *mr);
+
+/**
+ * memory_region_reset_dirty: Mark a range of pages as clean, for a specified
+ *                            client.
+ *
+ * Marks a range of pages as no longer dirty.
+ *
+ * @mr: the region being updated.
+ * @addr: the start of the subrange being cleaned.
+ * @size: the size of the subrange being cleaned.
+ * @client: the user of the logging information; %DIRTY_MEMORY_MIGRATION or
+ *          %DIRTY_MEMORY_VGA.
+ */
+void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                               target_phys_addr_t size, unsigned client);
+
+/**
+ * memory_region_set_readonly: Turn a memory region read-only (or read-write)
+ *
+ * Allows a memory region to be marked as read-only (turning it into a ROM).
+ * only useful on RAM regions.
+ *
+ * @mr: the region being updated.
+ * @readonly: whether rhe region is to be ROM or RAM.
+ */
+void memory_region_set_readonly(MemoryRegion *mr, bool readonly);
+
+/**
+ * memory_region_set_coalescing: Enable memory coalescing for the region.
+ *
+ * Enabled writes to a region to be queued for later processing. MMIO ->write
+ * callbacks may be delayed until a non-coalesced MMIO is issued.
+ * Only useful for IO regions.  Roughly similar to write-combining hardware.
+ *
+ * @mr: the memory region to be write coalesced
+ */
+void memory_region_set_coalescing(MemoryRegion *mr);
+
+/**
+ * memory_region_add_coalescing: Enable memory coalescing for a sub-range of
+ *                               a region.
+ *
+ * Like memory_region_set_coalescing(), but works on a sub-range of a region.
+ * Multiple calls can be issued coalesced disjoint ranges.
+ *
+ * @mr: the memory region to be updated.
+ * @offset: the start of the range within the region to be coalesced.
+ * @size: the size of the subrange to be coalesced.
+ */
+void memory_region_add_coalescing(MemoryRegion *mr,
+                                  target_phys_addr_t offset,
+                                  uint64_t size);
+
+/**
+ * memory_region_clear_coalescing: Disable MMIO coalescing for the region.
+ *
+ * Disables any coalescing caused by memory_region_set_coalescing() or
+ * memory_region_add_coalescing().  Roughly equivalent to uncacheble memory
+ * hardware.
+ *
+ * @mr: the memory region to be updated.
+ */
+void memory_region_clear_coalescing(MemoryRegion *mr);
+
+/**
+ * memory_region_add_subregion: Add a sub-region to a container.
+ *
+ * Adds a sub-region at @offset.  The sub-region 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
+ * want a region to be a subregion in multiple locations.
+ *
+ * @mr: the region to contain the new subregion; must be a container
+ *      initialized with memory_region_init().
+ * @offset: the offset relative to @mr where @subregion is added.
+ * @subregion: the subregion to be added.
+ */
+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.
+ *
+ * Adds a sub-region at @offset.  The sub-region 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
+ * memory_region_del_subregion()); use memory_region_init_alias() if you
+ * want a region to be a subregion in multiple locations.
+ *
+ * @mr: the region to contain the new subregion; must be a container
+ *      initialized with memory_region_init().
+ * @offset: the offset relative to @mr where @subregion is added.
+ * @subregion: the subregion to be added.
+ * @priority: used for resolving overlaps; highest priority wins.
+ */
+void memory_region_add_subregion_overlap(MemoryRegion *mr,
+                                         target_phys_addr_t offset,
+                                         MemoryRegion *subregion,
+                                         unsigned priority);
+/**
+ * memory_region_del_subregion: Remove a subregion.
+ *
+ * Removes a subregion from its container.
+ *
+ * @mr: the container to be updated.
+ * @subregion: the region being removed; must be a current subregion of @mr.
+ */
+void memory_region_del_subregion(MemoryRegion *mr,
+                                 MemoryRegion *subregion);
+
+#endif
+
+#endif
commit 9d3a4736cb86f0ad7904b223eccb165de8d4327b
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Jul 26 14:26:00 2011 +0300

    Add memory API documentation
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/docs/memory.txt b/docs/memory.txt
new file mode 100644
index 0000000..4460c06
--- /dev/null
+++ b/docs/memory.txt
@@ -0,0 +1,172 @@
+The memory API
+==============
+
+The memory API models the memory and I/O buses and controllers of a QEMU
+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
+
+The memory model provides support for
+
+ - tracking RAM changes by the guest
+ - setting up coalesced memory for kvm
+ - setting up ioeventfd regions for kvm
+
+Memory is modelled as an tree (really acyclic graph) of MemoryRegion objects.
+The root of the tree is memory as seen from the CPU's viewpoint (the system
+bus).  Nodes in the tree represent other buses, memory controllers, and
+memory regions that have been rerouted.  Leaves are RAM and MMIO regions.
+
+Types of regions
+----------------
+
+There are four types of memory regions (all represented by a single C type
+MemoryRegion):
+
+- RAM: a RAM region is simply a range of host memory that can be made available
+  to the guest.
+
+- MMIO: a range of guest memory that is implemented by host callbacks;
+  each read or write causes a callback to be called on the host.
+
+- container: a container simply includes other memory regions, each at
+  a different offset.  Containers are useful for grouping several regions
+  into one unit.  For example, a PCI BAR may be composed of a RAM region
+  and an MMIO region.
+
+  A container's subregions are usually non-overlapping.  In some cases it is
+  useful to have overlapping regions; for example a memory controller that
+  can overlay a subregion of RAM with MMIO or ROM, or a PCI controller
+  that does not prevent card from claiming overlapping BARs.
+
+- alias: a subsection of another region.  Aliases allow a region to be
+  split apart into discontiguous regions.  Examples of uses are memory banks
+  used when the guest address space is smaller than the amount of RAM
+  addressed, or a memory controller that splits main memory to expose a "PCI
+  hole".  Aliases may point to any type of region, including other aliases,
+  but an alias may not point back to itself, directly or indirectly.
+
+
+Region names
+------------
+
+Regions are assigned names by the constructor.  For most regions these are
+only used for debugging purposes, but RAM regions also use the name to identify
+live migration sections.  This means that RAM region names need to have ABI
+stability.
+
+Region lifecycle
+----------------
+
+A region is created by one of the constructor functions (memory_region_init*())
+and destroyed by the destructor (memory_region_destroy()).  In between,
+a region can be added to an address space by using memory_region_add_subregion()
+and removed using memory_region_del_subregion().  Region attributes may be
+changed at any point; they take effect once the region becomes exposed to the
+guest.
+
+Overlapping regions and priority
+--------------------------------
+Usually, regions may not overlap each other; a memory address decodes into
+exactly one target.  In some cases it is useful to allow regions to overlap,
+and sometimes to control which of an overlapping regions is visible to the
+guest.  This is done with memory_region_add_subregion_overlap(), which
+allows the region to overlap any other region in the same container, and
+specifies a priority that allows the core to decide which of two regions at
+the same address are visible (highest wins).
+
+Visibility
+----------
+The memory core uses the following rules to select a memory region when the
+guest accesses an address:
+
+- all direct subregions of the root region are matched against the address, in
+  descending priority order
+  - if the address lies outside the region offset/size, the subregion is
+    discarded
+  - if the subregion is a leaf (RAM or MMIO), the seach terminates
+  - if the subregion is a container, the same algorithm is used within the
+    subregion (after the address is adjusted by the subregion offset)
+  - if the subregion is an alias, the search is continues at the alias target
+    (after the address is adjusted by the subregion offset and alias offset)
+
+Example memory map
+------------------
+
+system_memory: container at 0-2^48-1
+ |
+ +---- lomem: alias at 0-0xdfffffff ---> #ram (0-0xdfffffff)
+ |
+ +---- himem: alias at 0x100000000-0x11fffffff ---> #ram (0xe0000000-0xffffffff)
+ |
+ +---- vga-window: alias at 0xa0000-0xbfffff ---> #pci (0xa0000-0xbffff)
+ |      (prio 1)
+ |
+ +---- pci-hole: alias at 0xe0000000-0xffffffff ---> #pci (0xe0000000-0xffffffff)
+
+pci (0-2^32-1)
+ |
+ +--- vga-area: container at 0xa0000-0xbffff
+ |      |
+ |      +--- alias at 0x00000-0x7fff  ---> #vram (0x010000-0x017fff)
+ |      |
+ |      +--- alias at 0x08000-0xffff  ---> #vram (0x020000-0x027fff)
+ |
+ +---- vram: ram at 0xe1000000-0xe1ffffff
+ |
+ +---- vga-mmio: mmio at 0xe2000000-0xe200ffff
+
+ram: ram at 0x00000000-0xffffffff
+
+The 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
+4GB of memory.
+
+The memory controller diverts addresses in the range 640K-768K to the PCI
+address space.  This is modeled using the "vga-window" alias, mapped at a
+higher priority so it obscures the RAM at the same addresses.  The vga window
+can be removed by programming the memory controller; this is modelled by
+removing the alias and exposing the RAM underneath.
+
+The pci address space is not a direct child of the system address space, since
+we only want parts of it to be visible (we accomplish this using aliases).
+It has two subregions: vga-area models the legacy vga window and is occupied
+by two 32K memory banks pointing at two sections of the framebuffer.
+In addition the vram is mapped as a BAR at address e1000000, and an additional
+BAR containing MMIO registers is mapped after it.
+
+Note that if the guest maps a BAR outside the PCI hole, it would not be
+visible as the pci-hole alias clips it to a 0.5GB range.
+
+Attributes
+----------
+
+Various region attributes (read-only, dirty logging, coalesced mmio, ioeventfd)
+can be changed during the region lifecycle.  They take effect once the region
+is made visible (which can be immediately, later, or never).
+
+MMIO Operations
+---------------
+
+MMIO regions are provided with ->read() and ->write() callbacks; in addition
+various constraints can be supplied to control how these callbacks are called:
+
+ - .valid.min_access_size, .valid.max_access_size define the access sizes
+   (in bytes) which the device accepts; accesses outside this range will
+   have device and bus specific behaviour (ignored, or machine check)
+ - .valid.aligned specifies that the device only accepts naturally aligned
+   accesses.  Unaligned accesses invoke device and bus specific behaviour.
+ - .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, is .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
+   cpu_register_io_memory() and register_ioport().  They should not be used
+   in new code.
commit 5ab28c8340f683121c081a181adfd9f72ab85cba
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Jul 24 19:38:36 2011 +0200

    qdev: Reset hot-plugged devices
    
    Device models rely on the core invoking their reset handlers after init.
    We do this in the cold-plug case, but so far we miss this step after
    hot-plug.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index a0fcd06..b4ea8e1 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -289,6 +289,9 @@ int qdev_init(DeviceState *dev)
                                        dev->alias_required_for_version);
     }
     dev->state = DEV_STATE_INITIALIZED;
+    if (dev->hotplugged && dev->info->reset) {
+        dev->info->reset(dev);
+    }
     return 0;
 }
 
commit ec67464c4f137f58c040d1d351f540268e883b85
Author: Juan Quintela <quintela at redhat.com>
Date:   Mon Jul 11 18:15:11 2011 +0200

    xen_mapcache: remove unused variable
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/xen-mapcache.c b/xen-mapcache.c
index 007136a..15d1241 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -237,7 +237,7 @@ uint8_t *xen_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size,
 
 ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
 {
-    MapCacheEntry *entry = NULL, *pentry = NULL;
+    MapCacheEntry *entry = NULL;
     MapCacheRev *reventry;
     target_phys_addr_t paddr_index;
     target_phys_addr_t size;
@@ -263,7 +263,6 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
 
     entry = &mapcache->entry[paddr_index % mapcache->nr_buckets];
     while (entry && (entry->paddr_index != paddr_index || entry->size != size)) {
-        pentry = entry;
         entry = entry->next;
     }
     if (!entry) {
commit 016c77ad62a8ad607dd4349d8cb8ad1365bab831
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 26 11:39:24 2011 -0500

    Makefile: add missing deps on $(GENERATED_HEADERS)
    
    This fixes a build issue with make -j6+ due to qapi-generated files
    being built before $(GENERATED_HEADERS) have been created.
    
    Tested-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/Makefile b/Makefile
index eb1c788..4855251 100644
--- a/Makefile
+++ b/Makefile
@@ -192,8 +192,10 @@ test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types
 test-qmp-commands: test-qmp-commands.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
 
 QGALIB=qga/guest-agent-command-state.o qga/guest-agent-commands.o
+QGALIB_GEN=$(addprefix $(qapi-dir)/, qga-qapi-types.c qga-qapi-types.h qga-qapi-visit.c qga-qmp-marshal.c)
 
-qemu-ga.o: $(addprefix $(qapi-dir)/, qga-qapi-types.c qga-qapi-types.h qga-qapi-visit.c qga-qmp-marshal.c) $(qapi-obj-y)
+$(QGALIB_GEN): $(GENERATED_HEADERS)
+$(QGALIB) qemu-ga.o: $(QGALIB_GEN) $(qapi-obj-y)
 qemu-ga$(EXESUF): qemu-ga.o $(QGALIB) qemu-tool.o qemu-error.o error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) $(qapi-obj-y) qemu-timer-common.o qemu-sockets.o module.o qapi/qmp-dispatch.o qapi/qmp-registry.o $(qapi-dir)/qga-qapi-visit.o $(qapi-dir)/qga-qapi-types.o $(qapi-dir)/qga-qmp-marshal.o
 
 QEMULIBS=libhw32 libhw64 libuser libdis libdis-user
commit c20cdf8b91b45a4f60a5ceeaab31b830b02adb7a
Author: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
Date:   Wed Jul 27 14:32:56 2011 +0800

    qmp: fix efect -> effect typo in qmp-commands.hx
    
    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/qmp-commands.hx b/qmp-commands.hx
index 54e313c..03f67da 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -42,7 +42,7 @@ and we're going to establish a deprecation policy for badly defined commands.
 
 If you're planning to adopt QMP, please observe the following:
 
-    1. The deprecation policy will take efect and be documented soon, please
+    1. The deprecation policy will take effect and be documented soon, please
        check the documentation of each used command as soon as a new release of
        QEMU is available
 
commit cf2846b5fa5cf85685e8a238323194b2ff9b5faf
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Thu Jul 21 21:46:45 2011 +0200

    slirp: Fix unusual "comments" in unused code
    
    cppcheck detected two rather strange comments which were not
    correctly written as C comments.
    
    They did not cause any harm because they were framed by
    #ifdef notdef ... #endif, so they were never compiled.
    
    Fix them nevertheless (we could also remove the unused code).
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/slirp/ip_input.c b/slirp/ip_input.c
index 5e67631..c7b3eb4 100644
--- a/slirp/ip_input.c
+++ b/slirp/ip_input.c
@@ -511,7 +511,7 @@ typedef uint32_t n_time;
 				 */
 				break;
 			}
-			off--;			/ * 0 origin *  /
+                        off--; /* 0 origin */
 			if (off > optlen - sizeof(struct in_addr)) {
 				/*
 				 * End of source route.  Should be for us.
@@ -554,7 +554,7 @@ typedef uint32_t n_time;
 			/*
 			 * If no space remains, ignore.
 			 */
-			off--;			 * 0 origin *
+                        off--; /* 0 origin */
 			if (off > optlen - sizeof(struct in_addr))
 				break;
 			bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,
commit 45b75ae4ee19a74c826a94e073762b5c7080a90c
Author: Alexandre Raymond <cerbere at gmail.com>
Date:   Wed Jul 20 23:12:15 2011 -0400

    Makefile: Minor cscope fixups
    
    Create cscope symbols for assembly files in addition to .c/.h files.
    Create cscope database with full path instead of relative path so cscope
    can be used with CSCOPE_DB in any directory.
    
    Signed-off-by: Alexandre Raymond <cerbere at gmail.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/Makefile b/Makefile
index daa3aa0..eb1c788 100644
--- a/Makefile
+++ b/Makefile
@@ -291,7 +291,7 @@ TAGS:
 
 cscope:
 	rm -f ./cscope.*
-	find . -name "*.[ch]" -print | sed 's,^\./,,' > ./cscope.files
+	find "$(SRC_PATH)" -name "*.[chsS]" -print | sed 's,^\./,,' > ./cscope.files
 	cscope -b
 
 # documentation
commit 023367e6cd41199521613674b44e9c703c8be1a1
Author: Wolfgang Mauerer <wolfgang.mauerer at siemens.com>
Date:   Mon Jul 11 14:57:43 2011 +0200

    vhost build fix for i386
    
    vhost.c uses __sync_fetch_and_and(), which is only
    available for -march=i486 and above (see
    https://bugzilla.redhat.com/show_bug.cgi?id=624279).
    
    Signed-off-by: Wolfgang Mauerer <wolfgang.mauerer at siemens.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/configure b/configure
index 38e3724..9bfe917 100755
--- a/configure
+++ b/configure
@@ -2510,6 +2510,29 @@ if test "$trace_backend" = "dtrace"; then
 fi
 
 ##########################################
+# __sync_fetch_and_and requires at least -march=i486. Many toolchains
+# use i686 as default anyway, but for those that don't, an explicit
+# specification is necessary
+if test $vhost_net = "yes" && test $cpu = "i386"; then
+  cat > $TMPC << EOF
+int sfaa(unsigned *ptr)
+{
+  return __sync_fetch_and_and(ptr, 0);
+}
+
+int main(int argc, char **argv)
+{
+  int val = 42;
+  sfaa(&val);
+  return val;
+}
+EOF
+  if ! compile_prog "" "" ; then
+    CFLAGS+="-march=i486"
+  fi
+fi
+
+##########################################
 # End of CC checks
 # After here, no more $cc or $ld runs
 
commit 0f94d6da357954857f95d5be69817d8551a5526f
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Jun 27 11:58:20 2011 +0200

    libcacard: add pc file, install it + includes
    
    Additionally:
     + add --includedir configure parameters
     + make install-libcacard install vscclient as well

diff --git a/configure b/configure
index e57efb1..1cc3767 100755
--- a/configure
+++ b/configure
@@ -146,6 +146,7 @@ datadir="\${prefix}/share/qemu"
 docdir="\${prefix}/share/doc/qemu"
 bindir="\${prefix}/bin"
 libdir="\${prefix}/lib"
+includedir="\${prefix}/include"
 sysconfdir="\${prefix}/etc"
 confsuffix="/qemu"
 slirp="yes"
@@ -539,6 +540,8 @@ for opt do
   ;;
   --libdir=*) libdir="$optarg"
   ;;
+  --includedir=*) includedir="$optarg"
+  ;;
   --datadir=*) datadir="$optarg"
   ;;
   --docdir=*) docdir="$optarg"
@@ -2542,6 +2545,7 @@ echo "Install prefix    $prefix"
 echo "BIOS directory    `eval echo $datadir`"
 echo "binary directory  `eval echo $bindir`"
 echo "library directory `eval echo $libdir`"
+echo "include directory `eval echo $includedir`"
 echo "config directory  `eval echo $sysconfdir`"
 if test "$mingw32" = "no" ; then
 echo "Manual directory  `eval echo $mandir`"
@@ -2635,6 +2639,7 @@ echo all: >> $config_host_mak
 echo "prefix=$prefix" >> $config_host_mak
 echo "bindir=$bindir" >> $config_host_mak
 echo "libdir=$libdir" >> $config_host_mak
+echo "includedir=$includedir" >> $config_host_mak
 echo "mandir=$mandir" >> $config_host_mak
 echo "datadir=$datadir" >> $config_host_mak
 echo "sysconfdir=$sysconfdir" >> $config_host_mak
diff --git a/libcacard/Makefile b/libcacard/Makefile
index 9802c37..bc34bf2 100644
--- a/libcacard/Makefile
+++ b/libcacard/Makefile
@@ -2,7 +2,10 @@
 -include $(SRC_PATH)/Makefile.objs
 -include $(SRC_PATH)/rules.mak
 
-$(call set-vpath, $(SRC_PATH):$(SRC_PATH)/libcacard)
+libcacard_srcpath=$(SRC_PATH)/libcacard
+libcacard_includedir=$(includedir)/cacard
+
+$(call set-vpath, $(SRC_PATH):$(libcacard_srcpath))
 
 # objects linked against normal qemu binaries, not compiled with libtool
 QEMU_OBJS=$(addprefix ../,$(oslib-obj-y) qemu-malloc.o qemu-timer-common.o $(trace-obj-y))
@@ -18,7 +21,7 @@ vscclient: $(libcacard-y) $(QEMU_OBJS) vscclient.o
 	$(call quiet-command,$(CC) $(libcacard_libs) -lrt -o $@ $^,"  LINK  $@")
 
 clean:
-	rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~ vscclient *.lo .libs/* *.la
+	rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~ vscclient *.lo .libs/* *.la *.pc
 	rm -Rf .libs
 
 all: vscclient
@@ -36,7 +39,25 @@ else
 libcacard.la: $(libcacard.lib-y) $(QEMU_OBJS_LIB)
 	$(call quiet-command,libtool --mode=link --quiet --tag=CC $(CC) $(libcacard_libs) -lrt -rpath $(libdir) -o $@ $^,"  lt LINK $@")
 
-install-libcacard: libcacard.la
+libcacard.pc: $(libcacard_srcpath)/libcacard.pc.in
+	sed -e 's|@LIBDIR@|$(libdir)|' \
+		-e 's|@INCLUDEDIR@|$(libcacard_includedir)|' \
+	    -e 's|@VERSION@|$(shell cat $(SRC_PATH)/VERSION)|' \
+		-e 's|@PREFIX@|$(prefix)|' \
+		< $(libcacard_srcpath)/libcacard.pc.in > libcacard.pc
+
+.PHONY: install-libcacard
+
+install-libcacard: libcacard.pc libcacard.la vscclient
 	$(INSTALL_DIR) "$(DESTDIR)$(libdir)"
+	$(INSTALL_DIR) "$(DESTDIR)$(libdir)/pkgconfig"
+	$(INSTALL_DIR) "$(DESTDIR)$(libcacard_includedir)"
+	$(INSTALL_DIR) "$(DESTDIR)$(bindir)"
+	libtool --mode=install $(INSTALL_PROG) vscclient "$(DESTDIR)$(bindir)"
 	libtool --mode=install $(INSTALL_PROG) libcacard.la "$(DESTDIR)$(libdir)"
+	libtool --mode=install $(INSTALL_PROG) libcacard.pc "$(DESTDIR)$(libdir)/pkgconfig"
+	for inc in *.h; do \
+		libtool --mode=install $(INSTALL_PROG) $(libcacard_srcpath)/$$inc "$(DESTDIR)$(libcacard_includedir)"; \
+	done
+
 endif
diff --git a/libcacard/libcacard.pc.in b/libcacard/libcacard.pc.in
new file mode 100644
index 0000000..b6859b0
--- /dev/null
+++ b/libcacard/libcacard.pc.in
@@ -0,0 +1,13 @@
+prefix=@PREFIX@
+exec_prefix=${prefix}
+libdir=@LIBDIR@
+includedir=@INCLUDEDIR@
+
+Name: cacard
+Description: CA Card library
+Version: @VERSION@
+
+Requires:  nss
+Libs: -L${libdir} -lcacard
+Libs.private:
+Cflags: -I${includedir}
commit 679f4f8b178e7c66fbc2f39c905374ee8663d5d8
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Mon Jul 18 06:07:02 2011 +0000

    xen: implement unplug protocol in xen_platform
    
    The unplug protocol is necessary to support PV drivers in the guest: the
    drivers expect to be able to "unplug" emulated disks and nics before
    initializing the Xen PV interfaces.
    It is responsibility of the guest to make sure that the unplug is done
    before the emulated devices or the PV interface start to be used.
    
    We use pci_for_each_device to walk the PCI bus, identify the devices and
    disks that we want to disable and dynamically unplug them.
    
    Changes in v2:
    
    - use PCI_CLASS constants;
    
    - replace pci_unplug_device with qdev_unplug;
    
    - do not import hw/ide/internal.h in xen_platform.c;
    
    Changes in v3:
    
    - introduce piix3-ide-xen, that support hot-unplug;
    
    - move the unplug code to hw/ide/piix.c;
    
    - just call qdev_unplug from xen_platform.c to unplug the IDE disks;
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Acked-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ide.h b/hw/ide.h
index 34d9394..a490cbb 100644
--- a/hw/ide.h
+++ b/hw/ide.h
@@ -13,6 +13,7 @@ ISADevice *isa_ide_init(int iobase, int iobase2, int isairq,
 /* ide-pci.c */
 void pci_cmd646_ide_init(PCIBus *bus, DriveInfo **hd_table,
                          int secondary_ide_enabled);
+PCIDevice *pci_piix3_xen_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn);
 PCIDevice *pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn);
 PCIDevice *pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn);
 void vt82c686b_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn);
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 84f72b0..f527dbd 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -149,6 +149,42 @@ static int pci_piix_ide_initfn(PCIDevice *dev)
     return 0;
 }
 
+static int pci_piix3_xen_ide_unplug(DeviceState *dev)
+{
+    PCIDevice *pci_dev;
+    PCIIDEState *pci_ide;
+    DriveInfo *di;
+    int i = 0;
+
+    pci_dev = DO_UPCAST(PCIDevice, qdev, dev);
+    pci_ide = DO_UPCAST(PCIIDEState, dev, pci_dev);
+
+    for (; i < 3; i++) {
+        di = drive_get_by_index(IF_IDE, i);
+        if (di != NULL && di->bdrv != NULL && !di->bdrv->removable) {
+            DeviceState *ds = bdrv_get_attached(di->bdrv);
+            if (ds) {
+                bdrv_detach(di->bdrv, ds);
+            }
+            bdrv_close(di->bdrv);
+            pci_ide->bus[di->bus].ifs[di->unit].bs = NULL;
+            drive_put_ref(di);
+        }
+    }
+    qdev_reset_all(&(pci_ide->dev.qdev));
+    return 0;
+}
+
+PCIDevice *pci_piix3_xen_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
+{
+    PCIDevice *dev;
+
+    dev = pci_create_simple(bus, devfn, "piix3-ide-xen");
+    dev->qdev.info->unplug = pci_piix3_xen_ide_unplug;
+    pci_ide_create_devs(dev, hd_table);
+    return dev;
+}
+
 /* hd_table must contain 4 block drivers */
 /* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
 PCIDevice *pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
@@ -182,6 +218,14 @@ static PCIDeviceInfo piix_ide_info[] = {
         .device_id    = PCI_DEVICE_ID_INTEL_82371SB_1,
         .class_id     = PCI_CLASS_STORAGE_IDE,
     },{
+        .qdev.name    = "piix3-ide-xen",
+        .qdev.size    = sizeof(PCIIDEState),
+        .qdev.no_user = 1,
+        .init         = pci_piix_ide_initfn,
+        .vendor_id    = PCI_VENDOR_ID_INTEL,
+        .device_id    = PCI_DEVICE_ID_INTEL_82371SB_1,
+        .class_id     = PCI_CLASS_STORAGE_IDE,
+    },{
         .qdev.name    = "piix4-ide",
         .qdev.size    = sizeof(PCIIDEState),
         .qdev.no_user = 1,
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index c5c16b4..40b73ea 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -155,7 +155,11 @@ static void pc_init1(ram_addr_t ram_size,
     ide_drive_get(hd, MAX_IDE_BUS);
     if (pci_enabled) {
         PCIDevice *dev;
-        dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
+        if (xen_enabled()) {
+            dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
+        } else {
+            dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
+        }
         idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
         idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
     } else {
diff --git a/hw/xen_platform.c b/hw/xen_platform.c
index f43e175..fb6be6a 100644
--- a/hw/xen_platform.c
+++ b/hw/xen_platform.c
@@ -76,6 +76,35 @@ static void log_writeb(PCIXenPlatformState *s, char val)
 }
 
 /* Xen Platform, Fixed IOPort */
+#define UNPLUG_ALL_IDE_DISKS 1
+#define UNPLUG_ALL_NICS 2
+#define UNPLUG_AUX_IDE_DISKS 4
+
+static void unplug_nic(PCIBus *b, PCIDevice *d)
+{
+    if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
+            PCI_CLASS_NETWORK_ETHERNET) {
+        qdev_unplug(&(d->qdev));
+    }
+}
+
+static void pci_unplug_nics(PCIBus *bus)
+{
+    pci_for_each_device(bus, 0, unplug_nic);
+}
+
+static void unplug_disks(PCIBus *b, PCIDevice *d)
+{
+    if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
+            PCI_CLASS_STORAGE_IDE) {
+        qdev_unplug(&(d->qdev));
+    }
+}
+
+static void pci_unplug_disks(PCIBus *bus)
+{
+    pci_for_each_device(bus, 0, unplug_disks);
+}
 
 static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
 {
@@ -83,10 +112,22 @@ static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t v
 
     switch (addr - XEN_PLATFORM_IOPORT) {
     case 0:
-        /* TODO: */
         /* Unplug devices.  Value is a bitmask of which devices to
            unplug, with bit 0 the IDE devices, bit 1 the network
            devices, and bit 2 the non-primary-master IDE devices. */
+        if (val & UNPLUG_ALL_IDE_DISKS) {
+            DPRINTF("unplug disks\n");
+            qemu_aio_flush();
+            bdrv_flush_all();
+            pci_unplug_disks(s->pci_dev.bus);
+        }
+        if (val & UNPLUG_ALL_NICS) {
+            DPRINTF("unplug nics\n");
+            pci_unplug_nics(s->pci_dev.bus);
+        }
+        if (val & UNPLUG_AUX_IDE_DISKS) {
+            DPRINTF("unplug auxiliary disks not supported\n");
+        }
         break;
     case 2:
         switch (val) {
commit 834e76ea1cc3f6fb261fe6a40f7571600bcb25b1
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Wed Jul 20 08:17:44 2011 +0000

    vl.c: Check the asked ram_size later.
    
    As a Xen guest can have more than 2GB of RAM on a 32bit host, we move
    the conditions after than we now if we run one Xen or not.
    
    [agraf] separate xen branch from ram_size check
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/vl.c b/vl.c
index 4b6688b..d8c7c01 100644
--- a/vl.c
+++ b/vl.c
@@ -2440,11 +2440,6 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
 
-                /* On 32-bit hosts, QEMU is limited by virtual address space */
-                if (value > (2047 << 20) && HOST_LONG_BITS == 32) {
-                    fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n");
-                    exit(1);
-                }
                 if (value != (uint64_t)(ram_addr_t)value) {
                     fprintf(stderr, "qemu: ram size too large\n");
                     exit(1);
@@ -3099,8 +3094,17 @@ int main(int argc, char **argv, char **envp)
         exit(1);
 
     /* init the memory */
-    if (ram_size == 0)
+    if (ram_size == 0) {
         ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
+    }
+
+    if (!xen_enabled()) {
+        /* On 32-bit hosts, QEMU is limited by virtual address space */
+        if (ram_size > (2047 << 20) && HOST_LONG_BITS == 32) {
+            fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n");
+            exit(1);
+        }
+    }
 
     /* init the dynamic translator */
     cpu_exec_init_all(tb_size * 1024 * 1024);
commit 8a369e20e701c9d220834e0daa027e65acd35214
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Wed Jul 20 08:17:43 2011 +0000

    xen: Fix the memory registration to reflect of what is done by Xen.
    
    A Xen guest memory is allocated by libxc. But this memory is not
    allocated continuously, instead, it leaves the VGA IO memory space not
    allocated, same for the MMIO space (at HVM_BELOW_4G_MMIO_START of size
    HVM_BELOW_4G_MMIO_LENGTH).
    
    So to reflect that, we do not register the physical memory for this two
    holes. But we still keep only one RAMBlock for the all RAM as it is more
    easier than have two separate blocks (1 above 4G). Also this prevent QEMU
    from use the MMIO space for a ROM.
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/xen-all.c b/xen-all.c
index 53296bf..9eaeac1 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -19,6 +19,7 @@
 
 #include <xen/hvm/ioreq.h>
 #include <xen/hvm/params.h>
+#include <xen/hvm/e820.h>
 
 //#define DEBUG_XEN
 
@@ -144,6 +145,12 @@ static void xen_ram_init(ram_addr_t ram_size)
     new_block->host = NULL;
     new_block->offset = 0;
     new_block->length = 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;
+    }
 
     QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
 
@@ -152,20 +159,26 @@ static void xen_ram_init(ram_addr_t ram_size)
     memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
            0xff, new_block->length >> TARGET_PAGE_BITS);
 
-    if (ram_size >= 0xe0000000 ) {
-        above_4g_mem_size = ram_size - 0xe0000000;
-        below_4g_mem_size = 0xe0000000;
+    if (ram_size >= HVM_BELOW_4G_RAM_END) {
+        above_4g_mem_size = ram_size - HVM_BELOW_4G_RAM_END;
+        below_4g_mem_size = HVM_BELOW_4G_RAM_END;
     } else {
         below_4g_mem_size = ram_size;
     }
 
-    cpu_register_physical_memory(0, below_4g_mem_size, new_block->offset);
-#if TARGET_PHYS_ADDR_BITS > 32
+    cpu_register_physical_memory(0, 0xa0000, 0);
+    /* 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);
     if (above_4g_mem_size > 0) {
         cpu_register_physical_memory(0x100000000ULL, above_4g_mem_size,
-                                     new_block->offset + below_4g_mem_size);
+                                     0x100000000ULL);
     }
-#endif
 }
 
 void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size)
commit f15fbc4bd1a24bd1477a846e63e62c6d435912f8
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Wed Jul 20 08:17:42 2011 +0000

    cpu-common: Have a ram_addr_t of uint64 with Xen.
    
    In Xen case, memory can be bigger than the host memory. that mean a
    32bits host (and QEMU) should be able to handle a RAM address of 64bits.
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/cpu-common.h b/cpu-common.h
index 44b04b3..0700101 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -27,7 +27,15 @@ enum device_endian {
 };
 
 /* address in the RAM (different from a physical address) */
+#if defined(CONFIG_XEN_BACKEND) && TARGET_PHYS_ADDR_BITS == 64
+typedef uint64_t ram_addr_t;
+#  define RAM_ADDR_MAX UINT64_MAX
+#  define RAM_ADDR_FMT "%" PRIx64
+#else
 typedef unsigned long ram_addr_t;
+#  define RAM_ADDR_MAX ULONG_MAX
+#  define RAM_ADDR_FMT "%lx"
+#endif
 
 /* memory API */
 
diff --git a/exec.c b/exec.c
index 0393d39..bfc9a43 100644
--- a/exec.c
+++ b/exec.c
@@ -2863,13 +2863,13 @@ 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 = ULONG_MAX;
+    ram_addr_t offset = 0, mingap = RAM_ADDR_MAX;
 
     if (QLIST_EMPTY(&ram_list.blocks))
         return 0;
 
     QLIST_FOREACH(block, &ram_list.blocks, next) {
-        ram_addr_t end, next = ULONG_MAX;
+        ram_addr_t end, next = RAM_ADDR_MAX;
 
         end = block->offset + block->length;
 
@@ -3081,7 +3081,8 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
 #endif
                 }
                 if (area != vaddr) {
-                    fprintf(stderr, "Could not remap addr: %lx@%lx\n",
+                    fprintf(stderr, "Could not remap addr: "
+                            RAM_ADDR_FMT "@" RAM_ADDR_FMT "\n",
                             length, addr);
                     exit(1);
                 }
@@ -4052,7 +4053,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
     target_phys_addr_t page;
     unsigned long pd;
     PhysPageDesc *p;
-    ram_addr_t raddr = ULONG_MAX;
+    ram_addr_t raddr = RAM_ADDR_MAX;
     ram_addr_t rlen;
     void *ret;
 
diff --git a/xen-all.c b/xen-all.c
index 83c5476..53296bf 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -184,7 +184,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size)
     }
 
     if (xc_domain_populate_physmap_exact(xen_xc, xen_domid, nr_pfn, 0, 0, pfn_list)) {
-        hw_error("xen: failed to populate ram at %lx", ram_addr);
+        hw_error("xen: failed to populate ram at " RAM_ADDR_FMT, ram_addr);
     }
 
     qemu_free(pfn_list);
commit 59d21e537b6c3a964d4e346e9cf2a1e17267a27c
Author: Alexander Graf <agraf at suse.de>
Date:   Sun Jul 17 07:30:29 2011 +0200

    xen: make xen_enabled even more clever
    
    When using xen_enabled() we're currently only checking if xen is enabled
    at all during the build. But what if you want to build multiple targets
    out of which only one can potentially run xen code?
    
    That means that for generic code we'll still have to fall back to the
    variable and potentially slow the code down, but it's not as important as
    that is mostly xen device emulation which is not touched for non-xen targets.
    
    The target specific code however can with this patch see that it's unable to
    ever execute xen code. We can thus always return 0 on xen_enabled(), giving
    gcc enough hints to evict the mapcache code from the target memory management
    code.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Acked-by: Anthony PERARD <anthony.perard at citrix.com>

diff --git a/configure b/configure
index cd399dc..bc3495c 100755
--- a/configure
+++ b/configure
@@ -3290,7 +3290,12 @@ case "$target_arch2" in
     if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then
       target_phys_bits=64
       echo "CONFIG_XEN=y" >> $config_target_mak
+    else
+      echo "CONFIG_NO_XEN=y" >> $config_target_mak
     fi
+    ;;
+  *)
+    echo "CONFIG_NO_XEN=y" >> $config_target_mak
 esac
 case "$target_arch2" in
   i386|x86_64|ppcemb|ppc|ppc64|s390x)
diff --git a/hw/xen.h b/hw/xen.h
index 43b95d6..2162111 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -24,7 +24,7 @@ extern int xen_allowed;
 
 static inline int xen_enabled(void)
 {
-#ifdef CONFIG_XEN_BACKEND
+#if defined(CONFIG_XEN_BACKEND) && !defined(CONFIG_NO_XEN)
     return xen_allowed;
 #else
     return 0;
commit f03a4ac12222ce1fb7886dc6cb38a027b73ccff2
Author: Alexander Graf <agraf at suse.de>
Date:   Sun Jul 17 07:22:06 2011 +0200

    xen: remove CONFIG_XEN_MAPCACHE
    
    We were still exporting CONFIG_XEN_MAPCACHE, even though it's completely
    unused by now. Remove it.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/configure b/configure
index 38e3724..cd399dc 100755
--- a/configure
+++ b/configure
@@ -3290,9 +3290,6 @@ case "$target_arch2" in
     if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then
       target_phys_bits=64
       echo "CONFIG_XEN=y" >> $config_target_mak
-      if test "$cpu" = "i386" -o "$cpu" = "x86_64"; then
-          echo "CONFIG_XEN_MAPCACHE=y" >> $config_target_mak
-      fi
     fi
 esac
 case "$target_arch2" in
commit 8ca5692df4a635b2c9211d6dc3dea15bd2b674c8
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Fri Jul 15 04:32:53 2011 +0000

    exec.c: Use ram_addr_t in cpu_physical_memory_rw(...).
    
    As the variable pd and addr1 inside the function cpu_physical_memory_rw
    are mean to handle a RAM address, they should be of the ram_addr_t type
    instead of unsigned long.
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/exec.c b/exec.c
index 2160ded..0393d39 100644
--- a/exec.c
+++ b/exec.c
@@ -3858,7 +3858,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
     uint8_t *ptr;
     uint32_t val;
     target_phys_addr_t page;
-    unsigned long pd;
+    ram_addr_t pd;
     PhysPageDesc *p;
 
     while (len > 0) {
@@ -3898,7 +3898,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                     l = 1;
                 }
             } else {
-                unsigned long addr1;
+                ram_addr_t addr1;
                 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
                 /* RAM case */
                 ptr = qemu_get_ram_ptr(addr1);
commit 30ab61252b71446977e298f146be124eb4a5b333
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Fri Jul 15 04:32:52 2011 +0000

    xen: Fix xen_enabled().
    
    Use the "host" CONFIG_ define instead of the "target" one.
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/xen.h b/hw/xen.h
index e432705..43b95d6 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -24,7 +24,7 @@ extern int xen_allowed;
 
 static inline int xen_enabled(void)
 {
-#ifdef CONFIG_XEN
+#ifdef CONFIG_XEN_BACKEND
     return xen_allowed;
 #else
     return 0;
commit fb4bb2b587549612a0da92de68fcc096ffd8a7d7
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Fri Jul 15 00:33:42 2011 +0000

    xen: introduce xen_change_state_handler
    
    Remove the call to xenstore_record_dm_state from xen_main_loop_prepare
    that is HVM specific.
    Add a new vm_change_state_handler shared between xen_pv and xen_hvm
    machines to record the VM state to xenstore.
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/xen-all.c b/xen-all.c
index 167bed6..83c5476 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -797,12 +797,17 @@ void xenstore_store_pv_console_info(int i, CharDriverState *chr)
     }
 }
 
-static void xenstore_record_dm_state(XenIOState *s, const char *state)
+static void xenstore_record_dm_state(struct xs_handle *xs, const char *state)
 {
     char path[50];
 
+    if (xs == NULL) {
+        fprintf(stderr, "xenstore connection not initialized\n");
+        exit(1);
+    }
+
     snprintf(path, sizeof (path), "/local/domain/0/device-model/%u/state", xen_domid);
-    if (!xs_write(s->xenstore, XBT_NULL, path, state, strlen(state))) {
+    if (!xs_write(xs, XBT_NULL, path, state, strlen(state))) {
         fprintf(stderr, "error recording dm state\n");
         exit(1);
     }
@@ -823,15 +828,20 @@ static void xen_main_loop_prepare(XenIOState *state)
     if (evtchn_fd != -1) {
         qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, state);
     }
-
-    /* record state running */
-    xenstore_record_dm_state(state, "running");
 }
 
 
 /* Initialise Xen */
 
-static void xen_vm_change_state_handler(void *opaque, int running, int reason)
+static void xen_change_state_handler(void *opaque, int running, int reason)
+{
+    if (running) {
+        /* record state running */
+        xenstore_record_dm_state(xenstore, "running");
+    }
+}
+
+static void xen_hvm_change_state_handler(void *opaque, int running, int reason)
 {
     XenIOState *state = opaque;
     if (running) {
@@ -854,6 +864,7 @@ int xen_init(void)
         xen_be_printf(NULL, 0, "can't open xen interface\n");
         return -1;
     }
+    qemu_add_vm_change_state_handler(xen_change_state_handler, NULL);
 
     return 0;
 }
@@ -915,7 +926,7 @@ int xen_hvm_init(void)
     xen_map_cache_init();
     xen_ram_init(ram_size);
 
-    qemu_add_vm_change_state_handler(xen_vm_change_state_handler, state);
+    qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
 
     state->client = xen_cpu_phys_memory_client;
     QLIST_INIT(&state->physmap);
commit c886edfb851c0c590d4e77f058f2ec8ed95ad1b5
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Fri Jul 22 21:08:09 2011 +0000

    Let users select their pythons
    
    Add configure check for python, exit if not found. Add switches
    for specifying the path to python, use the path in Makefile.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile b/Makefile
index f3a03ad..daa3aa0 100644
--- a/Makefile
+++ b/Makefile
@@ -168,22 +168,22 @@ test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-di
 
 $(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
-	$(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 -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
-	$(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 -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
-	    $(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 -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
-	$(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 -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
-	$(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 -o "$(qapi-dir)" -p "qga-" < $<, "  GEN   $@")
 $(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 -o "$(qapi-dir)" -p "qga-" < $<, "  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 qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
diff --git a/configure b/configure
index 600da9b..38e3724 100755
--- a/configure
+++ b/configure
@@ -475,6 +475,7 @@ fi
 
 : ${make=${MAKE-make}}
 : ${install=${INSTALL-install}}
+: ${python=${PYTHON-python}}
 
 if test "$mingw32" = "yes" ; then
   EXESUF=".exe"
@@ -516,6 +517,8 @@ for opt do
   ;;
   --install=*) install="$optarg"
   ;;
+  --python=*) python="$optarg"
+  ;;
   --extra-cflags=*)
   ;;
   --extra-ldflags=*)
@@ -924,6 +927,7 @@ echo "  --extra-cflags=CFLAGS    append extra C compiler flags QEMU_CFLAGS"
 echo "  --extra-ldflags=LDFLAGS  append extra linker flags LDFLAGS"
 echo "  --make=MAKE              use specified make [$make]"
 echo "  --install=INSTALL        use specified install [$install]"
+echo "  --python=PYTHON          use specified python [$python]"
 echo "  --static                 enable static build [$static]"
 echo "  --mandir=PATH            install man pages in PATH"
 echo "  --datadir=PATH           install firmware in PATH"
@@ -1084,6 +1088,13 @@ if test "$solaris" = "yes" ; then
   fi
 fi
 
+if has $python; then
+  :
+else
+  echo "Python not found. Use --python=/path/to/python"
+  exit 1
+fi
+
 if test -z "$target_list" ; then
     target_list="$default_target_list"
 else
@@ -2591,6 +2602,7 @@ echo "QEMU_CFLAGS       $QEMU_CFLAGS"
 echo "LDFLAGS           $LDFLAGS"
 echo "make              $make"
 echo "install           $install"
+echo "python            $python"
 echo "host CPU          $cpu"
 echo "host big endian   $bigendian"
 echo "target list       $target_list"
@@ -3003,6 +3015,7 @@ echo "INSTALL=$install" >> $config_host_mak
 echo "INSTALL_DIR=$install -d -m0755 -p" >> $config_host_mak
 echo "INSTALL_DATA=$install -m0644 -p" >> $config_host_mak
 echo "INSTALL_PROG=$install -m0755 -p" >> $config_host_mak
+echo "PYTHON=$python" >> $config_host_mak
 echo "CC=$cc" >> $config_host_mak
 echo "CC_I386=$cc_i386" >> $config_host_mak
 echo "HOST_CC=$host_cc" >> $config_host_mak
commit 0caf448b8062b6e186f7bf12dbb27c3ab4ca6136
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Jul 23 21:21:14 2011 +0000

    simpletrace: suppress a warning from unused variable
    
    Avoid this warning:
      CC    simpletrace.o
    /src/qemu/simpletrace.c: In function 'writeout_thread':
    /src/qemu/simpletrace.c:122:12: error: variable 'unused' set but not used [-Werror=unused-but-set-variable]
    by adding GCC attribute unused to the variable.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/simpletrace.c b/simpletrace.c
index f1dbb5e..de355e9 100644
--- a/simpletrace.c
+++ b/simpletrace.c
@@ -119,7 +119,7 @@ static void *writeout_thread(void *opaque)
     TraceRecord record;
     unsigned int writeout_idx = 0;
     unsigned int num_available, idx;
-    size_t unused;
+    size_t unused __attribute__ ((unused));
 
     for (;;) {
         wait_for_trace_records_available();
commit 00aa0040e8b8ec45a75be4e8926a84b82cc75838
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Jul 23 20:04:29 2011 +0000

    Wrap recv to avoid warnings
    
    Avoid warnings like these by wrapping recv():
      CC    slirp/ip_icmp.o
    /src/qemu/slirp/ip_icmp.c: In function 'icmp_receive':
    /src/qemu/slirp/ip_icmp.c:418:5: error: passing argument 2 of 'recv' from incompatible pointer type [-Werror]
    /usr/local/lib/gcc/i686-mingw32msvc/4.6.0/../../../../i686-mingw32msvc/include/winsock2.h:547:32: note: expected 'char *' but argument is of type 'struct icmp *'
    
    Remove also casts used to avoid warnings.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index 77a4de5..e150ac0 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -496,7 +496,7 @@ static ssize_t recvmsg(int s, struct msghdr *msg, int flags)
     }
     buf = qemu_malloc(size);
 
-    ret = recv(s, buf, size, flags);
+    ret = qemu_recv(s, buf, size, flags);
     if (ret < 0) {
         goto out;
     }
diff --git a/gdbstub.c b/gdbstub.c
index c085a5a..27b0cfa 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -319,7 +319,7 @@ static int get_char(GDBState *s)
     int ret;
 
     for(;;) {
-        ret = recv(s->fd, &ch, 1, 0);
+        ret = qemu_recv(s->fd, &ch, 1, 0);
         if (ret < 0) {
             if (errno == ECONNRESET)
                 s->fd = -1;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 1dd7aad..73f9baa 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2004,7 +2004,7 @@ static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
         ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
     } else {
         addr = NULL; /* To keep compiler quiet.  */
-        ret = get_errno(recv(fd, host_msg, len, flags));
+        ret = get_errno(qemu_recv(fd, host_msg, len, flags));
     }
     if (!is_error(ret)) {
         if (target_addr) {
diff --git a/nbd.c b/nbd.c
index 0dcd86b..e7a585d 100644
--- a/nbd.c
+++ b/nbd.c
@@ -78,7 +78,7 @@ size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read)
         ssize_t len;
 
         if (do_read) {
-            len = recv(fd, buffer + offset, size - offset, 0);
+            len = qemu_recv(fd, buffer + offset, size - offset, 0);
         } else {
             len = send(fd, buffer + offset, size - offset, 0);
         }
diff --git a/net/socket.c b/net/socket.c
index bc1bf58..11fe5f3 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -76,7 +76,7 @@ static void net_socket_send(void *opaque)
     uint8_t buf1[4096];
     const uint8_t *buf;
 
-    size = recv(s->fd, (void *)buf1, sizeof(buf1), 0);
+    size = qemu_recv(s->fd, buf1, sizeof(buf1), 0);
     if (size < 0) {
         err = socket_error();
         if (err != EWOULDBLOCK)
@@ -138,7 +138,7 @@ static void net_socket_send_dgram(void *opaque)
     NetSocketState *s = opaque;
     int size;
 
-    size = recv(s->fd, (void *)s->buf, sizeof(s->buf), 0);
+    size = qemu_recv(s->fd, s->buf, sizeof(s->buf), 0);
     if (size < 0)
         return;
     if (size == 0) {
diff --git a/qemu-char.c b/qemu-char.c
index 2982bfd..8e8cf31 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1860,7 +1860,7 @@ static void udp_chr_read(void *opaque)
 
     if (s->max_size == 0)
         return;
-    s->bufcnt = recv(s->fd, (void *)s->buf, sizeof(s->buf), 0);
+    s->bufcnt = qemu_recv(s->fd, s->buf, sizeof(s->buf), 0);
     s->bufptr = s->bufcnt;
     if (s->bufcnt <= 0)
         return;
@@ -2078,7 +2078,7 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
 static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
 {
     TCPCharDriver *s = chr->opaque;
-    return recv(s->fd, buf, len, 0);
+    return qemu_recv(s->fd, buf, len, 0);
 }
 #endif
 
diff --git a/qemu-common.h b/qemu-common.h
index ba55719..391fadd 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -200,6 +200,12 @@ int qemu_eventfd(int pipefd[2]);
 int qemu_pipe(int pipefd[2]);
 #endif
 
+#ifdef _WIN32
+#define qemu_recv(sockfd, buf, len, flags) recv(sockfd, (void *)buf, len, flags)
+#else
+#define qemu_recv(sockfd, buf, len, flags) recv(sockfd, buf, len, flags)
+#endif
+
 /* Error handling.  */
 
 void QEMU_NORETURN hw_error(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
diff --git a/savevm.c b/savevm.c
index 8139bc7..79db4cb 100644
--- a/savevm.c
+++ b/savevm.c
@@ -194,7 +194,7 @@ static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
     ssize_t len;
 
     do {
-        len = recv(s->fd, (void *)buf, size, 0);
+        len = qemu_recv(s->fd, buf, size, 0);
     } while (len == -1 && socket_error() == EINTR);
 
     if (len == -1)
diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c
index 14a5312..4b43994 100644
--- a/slirp/ip_icmp.c
+++ b/slirp/ip_icmp.c
@@ -415,7 +415,7 @@ void icmp_receive(struct socket *so)
     icp = mtod(m, struct icmp *);
 
     id = icp->icmp_id;
-    len = recv(so->s, icp, m->m_len, 0);
+    len = qemu_recv(so->s, icp, m->m_len, 0);
     icp->icmp_id = id;
 
     m->m_data -= hlen;
diff --git a/slirp/slirp.c b/slirp/slirp.c
index faaa2f3..df787ea 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -522,7 +522,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
 	 	 	 */
 #ifdef PROBE_CONN
 			if (so->so_state & SS_ISFCONNECTING) {
-			  ret = recv(so->s, (char *)&ret, 0,0);
+                          ret = qemu_recv(so->s, &ret, 0,0);
 
 			  if (ret < 0) {
 			    /* XXX */
diff --git a/slirp/socket.c b/slirp/socket.c
index 9b8ae13..77b0c98 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -166,7 +166,7 @@ soread(struct socket *so)
 	nn = readv(so->s, (struct iovec *)iov, n);
 	DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
 #else
-	nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
+	nn = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
 #endif
 	if (nn <= 0) {
 		if (nn < 0 && (errno == EINTR || errno == EAGAIN))
@@ -191,7 +191,7 @@ soread(struct socket *so)
 	 */
 	if (n == 2 && nn == iov[0].iov_len) {
             int ret;
-            ret = recv(so->s, iov[1].iov_base, iov[1].iov_len,0);
+            ret = qemu_recv(so->s, iov[1].iov_base, iov[1].iov_len,0);
             if (ret > 0)
                 nn += ret;
         }
diff --git a/ui/vnc-tls.c b/ui/vnc-tls.c
index dec626c..31f1467 100644
--- a/ui/vnc-tls.c
+++ b/ui/vnc-tls.c
@@ -89,7 +89,7 @@ static ssize_t vnc_tls_pull(gnutls_transport_ptr_t transport,
     int ret;
 
  retry:
-    ret = recv(vs->csock, data, len, 0);
+    ret = qemu_recv(vs->csock, data, len, 0);
     if (ret < 0) {
         if (errno == EINTR)
             goto retry;
diff --git a/ui/vnc.c b/ui/vnc.c
index 4425180..f1e27d9 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1199,7 +1199,7 @@ long vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen)
         }
     } else
 #endif /* CONFIG_VNC_TLS */
-        ret = recv(vs->csock, (void *)data, datalen, 0);
+        ret = qemu_recv(vs->csock, data, datalen, 0);
     VNC_DEBUG("Read wire %p %zd -> %ld\n", data, datalen, ret);
     return vnc_client_io_error(vs, ret, socket_error());
 }
commit aad04cd024f0c59f0b96f032cde2e24eb3abba6d
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Jul 23 19:26:08 2011 +0000

    Fix chrdev return value conversion
    
    6e1db57b2ac9025c2443c665a0d9e78748637b26 didn't
    convert brlapi or win32 chrdevs, breaking build for those.
    
    Fix by converting the chrdevs.
    
    Acked-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/baum.h b/hw/baum.h
index 8af710f..3f28cc3 100644
--- a/hw/baum.h
+++ b/hw/baum.h
@@ -23,4 +23,4 @@
  */
 
 /* char device */
-CharDriverState *chr_baum_init(QemuOpts *opts);
+int chr_baum_init(QemuOpts *opts, CharDriverState **_chr);
diff --git a/qemu-char.c b/qemu-char.c
index dcf7065..2982bfd 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1782,7 +1782,7 @@ static int qemu_chr_open_win_pipe(QemuOpts *opts, CharDriverState **_chr)
     return 0;
 }
 
-static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
+static int qemu_chr_open_win_file(HANDLE fd_out, CharDriverState **pchr)
 {
     CharDriverState *chr;
     WinCharState *s;
@@ -1793,10 +1793,11 @@ static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
     chr->opaque = s;
     chr->chr_write = win_chr_write;
     qemu_chr_generic_open(chr);
-    return chr;
+    *pchr = chr;
+    return 0;
 }
 
-static int qemu_chr_open_win_con(QemuOpts *opts, CharDriverState **_chr)
+static int qemu_chr_open_win_con(QemuOpts *opts, CharDriverState **chr)
 {
     return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE), chr);
 }
commit 1fc7bd4a86a2bfeafcec29445871eb97469a2699
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Sat Jul 23 17:57:47 2011 -0500

    qemu-ga: remove dependency on gio and gthread
    
    As far as I can tell, there isn't a dependency on gthread.  Also, the only use
    of gio was to enable GSocket to accept a unix domain socket.
    
    Since GSocket isn't available on OpenSuSE 11.1, let's just remove that
    dependency.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index 6911c3b..600da9b 100755
--- a/configure
+++ b/configure
@@ -1811,9 +1811,9 @@ fi
 
 ##########################################
 # glib support probe
-if $pkg_config --modversion gthread-2.0 gio-2.0 > /dev/null 2>&1 ; then
-    glib_cflags=`$pkg_config --cflags gthread-2.0 gio-2.0 2>/dev/null`
-    glib_libs=`$pkg_config --libs gthread-2.0 gio-2.0 2>/dev/null`
+if $pkg_config --modversion glib-2.0 > /dev/null 2>&1 ; then
+    glib_cflags=`$pkg_config --cflags glib-2.0 2>/dev/null`
+    glib_libs=`$pkg_config --libs glib-2.0 2>/dev/null`
     libs_softmmu="$glib_libs $libs_softmmu"
     libs_tools="$glib_libs $libs_tools"
 else
diff --git a/qemu-ga.c b/qemu-ga.c
index 6e2f61f..869ee37 100644
--- a/qemu-ga.c
+++ b/qemu-ga.c
@@ -14,7 +14,6 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <glib.h>
-#include <gio/gio.h>
 #include <getopt.h>
 #include <termios.h>
 #include <syslog.h>
@@ -37,9 +36,7 @@
 struct GAState {
     JSONMessageParser parser;
     GMainLoop *main_loop;
-    GSocket *conn_sock;
     GIOChannel *conn_channel;
-    GSocket *listen_sock;
     GIOChannel *listen_channel;
     const char *path;
     const char *method;
@@ -412,18 +409,20 @@ static gboolean listen_channel_accept(GIOChannel *channel,
                                       GIOCondition condition, gpointer data)
 {
     GAState *s = data;
-    GError *err = NULL;
     g_assert(channel != NULL);
-    int ret;
+    int ret, conn_fd;
     bool accepted = false;
+    struct sockaddr_un addr;
+    socklen_t addrlen = sizeof(addr);
 
-    s->conn_sock = g_socket_accept(s->listen_sock, NULL, &err);
-    if (err != NULL) {
-        g_warning("error converting fd to gsocket: %s", err->message);
-        g_error_free(err);
+    conn_fd = qemu_accept(g_io_channel_unix_get_fd(s->listen_channel),
+                             (struct sockaddr *)&addr, &addrlen);
+    if (conn_fd == -1) {
+        g_warning("error converting fd to gsocket: %s", strerror(errno));
         goto out;
     }
-    ret = conn_channel_add(s, g_socket_get_fd(s->conn_sock));
+    fcntl(conn_fd, F_SETFL, O_NONBLOCK);
+    ret = conn_channel_add(s, conn_fd);
     if (ret) {
         g_warning("error setting up connection");
         goto out;
@@ -440,19 +439,8 @@ out:
  */
 static int listen_channel_add(GAState *s, int listen_fd, bool new)
 {
-    GError *err = NULL;
-
     if (new) {
         s->listen_channel = g_io_channel_unix_new(listen_fd);
-        if (s->listen_sock) {
-            g_object_unref(s->listen_sock);
-        }
-        s->listen_sock = g_socket_new_from_fd(listen_fd, &err);
-        if (err != NULL) {
-            g_warning("error converting fd to gsocket: %s", err->message);
-            g_error_free(err);
-            return -1;
-        }
     }
     g_io_add_watch(s->listen_channel, G_IO_IN,
                    listen_channel_accept, s);
@@ -466,8 +454,6 @@ static void conn_channel_close(GAState *s)
 {
     if (strcmp(s->method, "unix-listen") == 0) {
         g_io_channel_shutdown(s->conn_channel, true, NULL);
-        g_object_unref(s->conn_sock);
-        s->conn_sock = NULL;
         listen_channel_add(s, 0, false);
     } else if (strcmp(s->method, "virtio-serial") == 0) {
         /* we spin on EOF for virtio-serial, so back off a bit. also,
@@ -624,9 +610,6 @@ int main(int argc, char **argv)
         become_daemon(pidfile);
     }
 
-    g_type_init();
-    g_thread_init(NULL);
-
     s = qemu_mallocz(sizeof(GAState));
     s->conn_channel = NULL;
     s->path = path;
commit 4eb36d40da8062400a2e7e27f1038e1252df9ede
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Sat Jul 23 16:14:37 2011 -0500

    guest-agent: only enable FSFREEZE when it's supported by the kernel
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qga/guest-agent-commands.c b/qga/guest-agent-commands.c
index 624972e..30c4068 100644
--- a/qga/guest-agent-commands.c
+++ b/qga/guest-agent-commands.c
@@ -10,15 +10,17 @@
  * See the COPYING file in the top-level directory.
  */
 
-#if defined(__linux__)
-#define CONFIG_FSFREEZE
-#endif
-
 #include <glib.h>
-#if defined(CONFIG_FSFREEZE)
+
+#if defined(__linux__)
 #include <mntent.h>
 #include <linux/fs.h>
+
+#if defined(__linux__) && defined(FIFREEZE)
+#define CONFIG_FSFREEZE
 #endif
+#endif
+
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include "qga/guest-agent-core.h"
commit 1167bfd63d983eaa4816ee0edb185f98ff070d6d
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Sat Jul 23 11:57:53 2011 -0500

    Open 1.0 development branch.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/VERSION b/VERSION
index fc6f294..e653127 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.14.90
+0.15.50
commit b8095f24f24e50a7d4be33d8a79474aff3324295
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Sat Jul 23 11:56:07 2011 -0500

    Bump version to reflect v0.15.0-rc0
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/VERSION b/VERSION
index d07c6d0..fc6f294 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.14.50
+0.14.90
commit 8e31bf388e56e5babd9600b110a94381d1be07b1
Author: Matthew Fernandez <matthew.fernandez at gmail.com>
Date:   Sun Jun 26 12:21:35 2011 +1000

    Correct spelling of licensed
    
    Correct typos of "licenced" to "licensed".
    
    Reviewed-by: Stefan Weil <weil at mail.berlios.de>
    Reviewed-by: Andreas F=E4rber <andreas.faerber at web.de>
    Signed-off-by: Matthew Fernandez <matthew.fernandez at gmail.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index b5e5328..6f108f4 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2009 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 /* 64 external IRQ lines.  */
diff --git a/hw/an5206.c b/hw/an5206.c
index 42a0163..04ca420 100644
--- a/hw/an5206.c
+++ b/hw/an5206.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2007 CodeSourcery.
  *
- * This code is licenced under the GPL
+ * This code is licensed under the GPL
  */
 
 #include "hw.h"
diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index 9aeeaea..f8a7472 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -4,7 +4,7 @@
  * Copyright (c) 2006 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the LGPL.
+ * This code is licensed under the LGPL.
  *
  */
 
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index 3bbd885..b47707f 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006-2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 /* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index e021576..215d5de 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006-2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "hw.h"
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 0e934ec..fb07314 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006-2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 /* This file contains implementation code for the RealView EB interrupt
diff --git a/hw/arm_pic.c b/hw/arm_pic.c
index f44568c..985148a 100644
--- a/hw/arm_pic.c
+++ b/hw/arm_pic.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the LGPL
+ * This code is licensed under the LGPL
  */
 
 #include "hw.h"
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index 9225b58..fd0c8bc 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006-2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "hw.h"
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index dac9e70..fd9448f 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2005-2006 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "sysbus.h"
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index d06eec9..1df8d4d 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006-2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  *
  * The ARMv7M System controller is fairly tightly tied in with the
  * NVIC.  Much of that is also implemented here.
diff --git a/hw/bitbang_i2c.c b/hw/bitbang_i2c.c
index 2937b5c..53e9c5c 100644
--- a/hw/bitbang_i2c.c
+++ b/hw/bitbang_i2c.c
@@ -4,7 +4,7 @@
  *
  * Copyright (c) 2008 Jan Kiszka
  *
- * This code is licenced under the GNU GPL v2.
+ * This code is licensed under the GNU GPL v2.
  */
 #include "hw.h"
 #include "bitbang_i2c.h"
diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c
index 0b07184..4762e85 100644
--- a/hw/ccid-card-emulated.c
+++ b/hw/ccid-card-emulated.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2011 Red Hat.
  * Written by Alon Levy.
  *
- * This code is licenced under the GNU LGPL, version 2 or later.
+ * This code is licensed under the GNU LGPL, version 2 or later.
  */
 
 /*
diff --git a/hw/ccid.h b/hw/ccid.h
index d3e0371..9e3abe1 100644
--- a/hw/ccid.h
+++ b/hw/ccid.h
@@ -4,7 +4,7 @@
  * Copyright (c) 2011 Red Hat.
  * Written by Alon Levy.
  *
- * This code is licenced under the GNU LGPL, version 2 or later.
+ * This code is licensed under the GNU LGPL, version 2 or later.
  */
 
 #ifndef CCID_H
diff --git a/hw/ds1338.c b/hw/ds1338.c
index 6f5ae5e..3522af5 100644
--- a/hw/ds1338.c
+++ b/hw/ds1338.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2009 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GNU GPL v2.
+ * This code is licensed under the GNU GPL v2.
  */
 
 #include "i2c.h"
diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c
index cec1cc8..eed9e38 100644
--- a/hw/dummy_m68k.c
+++ b/hw/dummy_m68k.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2007 CodeSourcery.
  *
- * This code is licenced under the GPL
+ * This code is licensed under the GPL
  */
 
 #include "hw.h"
diff --git a/hw/i2c.c b/hw/i2c.c
index f80d12d..49b9ecb 100644
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the LGPL.
+ * This code is licensed under the LGPL.
  */
 
 #include "i2c.h"
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index a6c27be..2814108 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2005-2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL
+ * This code is licensed under the GPL
  */
 
 #include "sysbus.h"
diff --git a/hw/lan9118.c b/hw/lan9118.c
index 3f3c05d..73a8661 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2009 CodeSourcery, LLC.
  * Written by Paul Brook
  *
- * This code is licenced under the GNU GPL v2
+ * This code is licensed under the GNU GPL v2
  */
 
 #include "sysbus.h"
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 69eec1d..e9904c4 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the LGPL.
+ * This code is licensed under the LGPL.
  */
 
 /* ??? Need to check if the {read,write}[wl] routines work properly on
diff --git a/hw/marvell_88w8618_audio.c b/hw/marvell_88w8618_audio.c
index 3eff925..f8c5242 100644
--- a/hw/marvell_88w8618_audio.c
+++ b/hw/marvell_88w8618_audio.c
@@ -4,7 +4,7 @@
  *
  * Copyright (c) 2008 Jan Kiszka
  *
- * This code is licenced under the GNU GPL v2.
+ * This code is licensed under the GNU GPL v2.
  */
 #include "sysbus.h"
 #include "hw.h"
diff --git a/hw/mcf5206.c b/hw/mcf5206.c
index 2a618d4..fce282d 100644
--- a/hw/mcf5206.c
+++ b/hw/mcf5206.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2007 CodeSourcery.
  *
- * This code is licenced under the GPL
+ * This code is licensed under the GPL
  */
 #include "hw.h"
 #include "mcf.h"
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index 17a692d..78fbc5f 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2007 CodeSourcery.
  *
- * This code is licenced under the GPL
+ * This code is licensed under the GPL
  */
 #include "hw.h"
 #include "mcf.h"
diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c
index 5477e0e..748eb59 100644
--- a/hw/mcf_fec.c
+++ b/hw/mcf_fec.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2007 CodeSourcery.
  *
- * This code is licenced under the GPL
+ * This code is licensed under the GPL
  */
 #include "hw.h"
 #include "net.h"
diff --git a/hw/mcf_intc.c b/hw/mcf_intc.c
index ac04295..6cb0a09 100644
--- a/hw/mcf_intc.c
+++ b/hw/mcf_intc.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2007 CodeSourcery.
  *
- * This code is licenced under the GPL
+ * This code is licensed under the GPL
  */
 #include "hw.h"
 #include "mcf.h"
diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
index db57096..905e116 100644
--- a/hw/mcf_uart.c
+++ b/hw/mcf_uart.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2007 CodeSourcery.
  *
- * This code is licenced under the GPL
+ * This code is licensed under the GPL
  */
 #include "hw.h"
 #include "mcf.h"
diff --git a/hw/mpcore.c b/hw/mpcore.c
index 379065a..d778507 100644
--- a/hw/mpcore.c
+++ b/hw/mpcore.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006-2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "sysbus.h"
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 52b2931..63dd391 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2008 Jan Kiszka
  *
- * This code is licenced under the GNU GPL v2.
+ * This code is licensed under the GNU GPL v2.
  */
 
 #include "sysbus.h"
diff --git a/hw/pl011.c b/hw/pl011.c
index 3b94b14..997ce84 100644
--- a/hw/pl011.c
+++ b/hw/pl011.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "sysbus.h"
diff --git a/hw/pl022.c b/hw/pl022.c
index 00e494a..9a1cb71 100644
--- a/hw/pl022.c
+++ b/hw/pl022.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "sysbus.h"
diff --git a/hw/pl050.c b/hw/pl050.c
index b155cc0..f7fa2e2 100644
--- a/hw/pl050.c
+++ b/hw/pl050.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006-2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "sysbus.h"
diff --git a/hw/pl061.c b/hw/pl061.c
index 372dfc2..79e5c53 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -5,7 +5,7 @@
  * Copyright (c) 2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "sysbus.h"
diff --git a/hw/pl080.c b/hw/pl080.c
index dd8139b..5ba3b08 100644
--- a/hw/pl080.c
+++ b/hw/pl080.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "sysbus.h"
diff --git a/hw/pl110.c b/hw/pl110.c
index 06d2dfa..62aba17 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2005-2009 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GNU LGPL
+ * This code is licensed under the GNU LGPL
  */
 
 #include "sysbus.h"
diff --git a/hw/pl110_template.h b/hw/pl110_template.h
index b3c9077..d303336 100644
--- a/hw/pl110_template.h
+++ b/hw/pl110_template.h
@@ -4,7 +4,7 @@
  * Copyright (c) 2005 CodeSourcery, LLC.
  * Written by Paul Brook
  *
- * This code is licenced under the GNU LGPL
+ * This code is licensed under the GNU LGPL
  *
  * Framebuffer format conversion routines.
  */
diff --git a/hw/pl181.c b/hw/pl181.c
index 6bc79f5..0943c09 100644
--- a/hw/pl181.c
+++ b/hw/pl181.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "blockdev.h"
diff --git a/hw/pl190.c b/hw/pl190.c
index 75f2ba1..8dc7e42 100644
--- a/hw/pl190.c
+++ b/hw/pl190.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "sysbus.h"
diff --git a/hw/ptimer.c b/hw/ptimer.c
index 47964a6..6f13ce9 100644
--- a/hw/ptimer.c
+++ b/hw/ptimer.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2007 CodeSourcery.
  *
- * This code is licenced under the GNU LGPL.
+ * This code is licensed under the GNU LGPL.
  */
 #include "hw.h"
 #include "qemu-timer.h"
diff --git a/hw/pxa.h b/hw/pxa.h
index d982f00..859fc67 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -4,7 +4,7 @@
  * Copyright (c) 2006 Openedhand Ltd.
  * Written by Andrzej Zaborowski <balrog at zabor.org>
  *
- * This code is licenced under the GNU GPL v2.
+ * This code is licensed under the GNU GPL v2.
  */
 #ifndef PXA_H
 # define PXA_H			"pxa.h"
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index ac5d95d..cf93110 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006 Openedhand Ltd.
  * Written by Andrzej Zaborowski <balrog at zabor.org>
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "sysbus.h"
diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c
index a67498b..599581e 100644
--- a/hw/pxa2xx_dma.c
+++ b/hw/pxa2xx_dma.c
@@ -5,7 +5,7 @@
  * Copyright (c) 2006 Thorsten Zitterell
  * Written by Andrzej Zaborowski <balrog at zabor.org>
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "hw.h"
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index e9a5361..bdd82e6 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -5,7 +5,7 @@
  * Copyright (c) 2006 Thorsten Zitterell
  * Written by Andrzej Zaborowski <balrog at zabor.org>
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "hw.h"
diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index f777a21..4235e42 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006 Openedhand Ltd.
  * Copyright (c) 2006 Thorsten Zitterell
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "hw.h"
diff --git a/hw/realview.c b/hw/realview.c
index 82f3d82..94ab900 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006-2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "sysbus.h"
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index db908b6..43a2a0d 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006-2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "sysbus.h"
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 05d14ab..f42a5d1 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -12,7 +12,7 @@
  *  2009-Oct-13 Artyom Tarasenko : implemented the block descriptor in the
  *                                 MODE SENSE response.
  *
- * This code is licenced under the LGPL.
+ * This code is licensed under the LGPL.
  *
  * Note that this file only handles the SCSI architecture model and device
  * commands.  Emulation of interface/link layer protocols is handled by
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 90345a7..63361b3 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -7,7 +7,7 @@
  *
  * Written by Laurent Vivier <Laurent.Vivier at bull.net>
  *
- * This code is licenced under the LGPL.
+ * This code is licensed under the LGPL.
  *
  */
 
diff --git a/hw/sh_intc.c b/hw/sh_intc.c
index 0734da9..c43b99f 100644
--- a/hw/sh_intc.c
+++ b/hw/sh_intc.c
@@ -5,7 +5,7 @@
  * Based on sh_timer.c and arm_timer.c by Paul Brook
  * Copyright (c) 2005-2006 CodeSourcery.
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "sh_intc.h"
diff --git a/hw/sh_timer.c b/hw/sh_timer.c
index 5eec6b7..5df7fb6 100644
--- a/hw/sh_timer.c
+++ b/hw/sh_timer.c
@@ -5,7 +5,7 @@
  * Based on arm_timer.c by Paul Brook
  * Copyright (c) 2005-2006 CodeSourcery.
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "hw.h"
diff --git a/hw/smbus.c b/hw/smbus.c
index e464539..ff027c8 100644
--- a/hw/smbus.c
+++ b/hw/smbus.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the LGPL.
+ * This code is licensed under the LGPL.
  */
 
 /* TODO: Implement PEC.  */
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index 701baaf..3a8a85c 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2005 CodeSourcery, LLC.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL
+ * This code is licensed under the GPL
  */
 
 #include "sysbus.h"
diff --git a/hw/ssd0303.c b/hw/ssd0303.c
index b39e259..401fdf5 100644
--- a/hw/ssd0303.c
+++ b/hw/ssd0303.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006-2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 /* The controller can support a variety of different displays, but we only
diff --git a/hw/ssd0323.c b/hw/ssd0323.c
index 8643961..1eb3823 100644
--- a/hw/ssd0323.c
+++ b/hw/ssd0323.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006-2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 /* The controller can support a variety of different displays, but we only
diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c
index fb4b649..18dabd6 100644
--- a/hw/ssi-sd.c
+++ b/hw/ssi-sd.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2007-2009 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GNU GPL v2.
+ * This code is licensed under the GNU GPL v2.
  */
 
 #include "blockdev.h"
diff --git a/hw/ssi.c b/hw/ssi.c
index cfe7c07..3f4c5f9 100644
--- a/hw/ssi.c
+++ b/hw/ssi.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2009 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GNU GPL v2.
+ * This code is licensed under the GNU GPL v2.
  */
 
 #include "ssi.h"
diff --git a/hw/stellaris.c b/hw/stellaris.c
index b8a7ceb..a280930 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "sysbus.h"
diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c
index 6a0583a..1291931 100644
--- a/hw/stellaris_enet.c
+++ b/hw/stellaris_enet.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 #include "sysbus.h"
 #include "net.h"
diff --git a/hw/stellaris_input.c b/hw/stellaris_input.c
index 06c5f9d..95604ec 100644
--- a/hw/stellaris_input.c
+++ b/hw/stellaris_input.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 #include "hw.h"
 #include "devices.h"
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index bfea096..6391dad 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the LGPL.
+ * This code is licensed under the LGPL.
  */
 
 #include "qemu-common.h"
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index 59cb0fb..c69c437 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -5,7 +5,7 @@
  * Copyright (c) 2008 Samuel Thibault <samuel.thibault at ens-lyon.org>
  * Written by Paul Brook, reused for FTDI by Samuel Thibault
  *
- * This code is licenced under the LGPL.
+ * This code is licensed under the LGPL.
  */
 
 #include "qemu-common.h"
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index 8e75ffc..290a900 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006-2009 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the LGPL.
+ * This code is licensed under the LGPL.
  */
 
 #include "sysbus.h"
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 46b6a3f..147fe29 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2005-2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #include "sysbus.h"
diff --git a/softmmu-semi.h b/softmmu-semi.h
index 79278cc..86a9f8a 100644
--- a/softmmu-semi.h
+++ b/softmmu-semi.h
@@ -4,7 +4,7 @@
  *
  * Copyright (c) 2007 CodeSourcery.
  *
- * This code is licenced under the GPL
+ * This code is licensed under the GPL
  */
 
 static inline uint32_t softmmu_tget32(CPUState *env, uint32_t addr)
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 2830627..b51e35a 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2007, 2008 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GNU GPL v2.
+ * This code is licensed under the GNU GPL v2.
  */
 #include <stdlib.h>
 #include <stdio.h>
diff --git a/target-arm/op_addsub.h b/target-arm/op_addsub.h
index c02c92a..ca4a189 100644
--- a/target-arm/op_addsub.h
+++ b/target-arm/op_addsub.h
@@ -4,7 +4,7 @@
  * Copyright (c) 2007 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
 #ifdef ARITH_GE
commit d25f89c9e91d6c46b85969922411a211a6347a7d
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jun 17 11:25:49 2011 +0200

    Register Linux dyntick timer as per-thread signal
    
    Derived from kvm-tool patch
    http://thread.gmane.org/gmane.comp.emulators.kvm.devel/74309
    
    Ingo Molnar pointed out that sending the timer signal to the whole
    process, just blocking it everywhere, is suboptimal with an increasing
    number of threads. QEMU is also using this pattern so far.
    
    Linux provides a (non-portable) way to restrict the signal to a single
    thread: We can use SIGEV_THREAD_ID unless we are forced to emulate
    signalfd via an additional thread. That case could theoretically be
    optimized as well, but it doesn't look worth bothering.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/compatfd.c b/compatfd.c
index 41586ce..31654c6 100644
--- a/compatfd.c
+++ b/compatfd.c
@@ -115,3 +115,14 @@ int qemu_signalfd(const sigset_t *mask)
 
     return qemu_signalfd_compat(mask);
 }
+
+bool qemu_signalfd_available(void)
+{
+#ifdef CONFIG_SIGNALFD
+    errno = 0;
+    syscall(SYS_signalfd, -1, NULL, _NSIG / 8);
+    return errno != ENOSYS;
+#else
+    return false;
+#endif
+}
diff --git a/compatfd.h b/compatfd.h
index fc37915..6b04877 100644
--- a/compatfd.h
+++ b/compatfd.h
@@ -39,5 +39,6 @@ struct qemu_signalfd_siginfo {
 };
 
 int qemu_signalfd(const sigset_t *mask);
+bool qemu_signalfd_available(void);
 
 #endif
diff --git a/qemu-timer.c b/qemu-timer.c
index f95374c..30e8f12 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -831,6 +831,8 @@ static int64_t qemu_next_alarm_deadline(void)
 
 #if defined(__linux__)
 
+#include "compatfd.h"
+
 static int dynticks_start_timer(struct qemu_alarm_timer *t)
 {
     struct sigevent ev;
@@ -850,6 +852,12 @@ static int dynticks_start_timer(struct qemu_alarm_timer *t)
     memset(&ev, 0, sizeof(ev));
     ev.sigev_value.sival_int = 0;
     ev.sigev_notify = SIGEV_SIGNAL;
+#ifdef SIGEV_THREAD_ID
+    if (qemu_signalfd_available()) {
+        ev.sigev_notify = SIGEV_THREAD_ID;
+        ev._sigev_un._tid = qemu_get_thread_id();
+    }
+#endif /* SIGEV_THREAD_ID */
     ev.sigev_signo = SIGALRM;
 
     if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) {
commit 17604dac28b2410c021a4a52dcfa58e8803dfb24
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Jun 20 14:06:28 2011 +0200

    mc146818rtc: Handle host clock resets
    
    Make use of the new clock reset notifier to update the RTC whenever
    rtc_clock is the host clock and that happens to jump backward. This
    avoids that the RTC stalls for the period the host clock was set back.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 1c9a706..feb3b25 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -99,6 +99,7 @@ typedef struct RTCState {
     QEMUTimer *coalesced_timer;
     QEMUTimer *second_timer;
     QEMUTimer *second_timer2;
+    Notifier clock_reset_notifier;
 } RTCState;
 
 static void rtc_set_time(RTCState *s);
@@ -572,6 +573,22 @@ static const VMStateDescription vmstate_rtc = {
     }
 };
 
+static void rtc_notify_clock_reset(Notifier *notifier, void *data)
+{
+    RTCState *s = container_of(notifier, RTCState, clock_reset_notifier);
+    int64_t now = *(int64_t *)data;
+
+    rtc_set_date_from_host(&s->dev);
+    s->next_second_time = now + (get_ticks_per_sec() * 99) / 100;
+    qemu_mod_timer(s->second_timer2, s->next_second_time);
+    rtc_timer_update(s, now);
+#ifdef TARGET_I386
+    if (rtc_td_hack) {
+        rtc_coalesced_timer_update(s);
+    }
+#endif
+}
+
 static void rtc_reset(void *opaque)
 {
     RTCState *s = opaque;
@@ -608,6 +625,9 @@ static int rtc_initfn(ISADevice *dev)
     s->second_timer = qemu_new_timer_ns(rtc_clock, rtc_update_second, s);
     s->second_timer2 = qemu_new_timer_ns(rtc_clock, rtc_update_second2, s);
 
+    s->clock_reset_notifier.notify = rtc_notify_clock_reset;
+    qemu_register_clock_reset_notifier(rtc_clock, &s->clock_reset_notifier);
+
     s->next_second_time =
         qemu_get_clock_ns(rtc_clock) + (get_ticks_per_sec() * 99) / 100;
     qemu_mod_timer(s->second_timer2, s->next_second_time);
commit 691a0c9c9b71360271220c12f20a7238bc302503
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Jun 20 14:06:27 2011 +0200

    qemu-timer: Introduce clock reset notifier
    
    QEMU_CLOCK_HOST is based on the system time which may jump backward in
    case the admin or NTP adjusts it. RTC emulations and other device models
    can suffer in this case as timers will stall for the period the clock
    was tuned back.
    
    This adds a detection mechanism that checks on every host clock readout
    if the new time is before the last result. If that is the case a
    notifier list is informed. Device models interested in this event can
    register a notifier with the clock.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index 67c2974..f95374c 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -150,6 +150,9 @@ struct QEMUClock {
     int enabled;
 
     QEMUTimer *warp_timer;
+
+    NotifierList reset_notifiers;
+    int64_t last;
 };
 
 struct QEMUTimer {
@@ -376,9 +379,15 @@ static QEMUTimer *active_timers[QEMU_NUM_CLOCKS];
 static QEMUClock *qemu_new_clock(int type)
 {
     QEMUClock *clock;
+
     clock = qemu_mallocz(sizeof(QEMUClock));
     clock->type = type;
     clock->enabled = 1;
+    notifier_list_init(&clock->reset_notifiers);
+    /* required to detect & report backward jumps */
+    if (type == QEMU_CLOCK_HOST) {
+        clock->last = get_clock_realtime();
+    }
     return clock;
 }
 
@@ -593,6 +602,8 @@ static void qemu_run_timers(QEMUClock *clock)
 
 int64_t qemu_get_clock_ns(QEMUClock *clock)
 {
+    int64_t now, last;
+
     switch(clock->type) {
     case QEMU_CLOCK_REALTIME:
         return get_clock();
@@ -604,10 +615,26 @@ int64_t qemu_get_clock_ns(QEMUClock *clock)
             return cpu_get_clock();
         }
     case QEMU_CLOCK_HOST:
-        return get_clock_realtime();
+        now = get_clock_realtime();
+        last = clock->last;
+        clock->last = now;
+        if (now < last) {
+            notifier_list_notify(&clock->reset_notifiers, &now);
+        }
+        return now;
     }
 }
 
+void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
+{
+    notifier_list_add(&clock->reset_notifiers, notifier);
+}
+
+void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
+{
+    notifier_list_remove(&clock->reset_notifiers, notifier);
+}
+
 void init_clocks(void)
 {
     rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
diff --git a/qemu-timer.h b/qemu-timer.h
index 06cbe20..0a43469 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -2,6 +2,7 @@
 #define QEMU_TIMER_H
 
 #include "qemu-common.h"
+#include "notify.h"
 #include <time.h>
 #include <sys/time.h>
 
@@ -40,6 +41,10 @@ int64_t qemu_get_clock_ns(QEMUClock *clock);
 void qemu_clock_enable(QEMUClock *clock, int enabled);
 void qemu_clock_warp(QEMUClock *clock);
 
+void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier);
+void qemu_unregister_clock_reset_notifier(QEMUClock *clock,
+                                          Notifier *notifier);
+
 QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
                           QEMUTimerCB *cb, void *opaque);
 void qemu_free_timer(QEMUTimer *ts);
commit 9e8dd45164af05a5dab00324dd10b037f5bd1e2a
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Jun 20 14:06:26 2011 +0200

    notifier: Pass data argument to callback
    
    This allows to pass additional information to the notifier callback
    which is useful if sender and receiver do not share any other distinct
    data structure.
    
    Will be used first for the clock reset notifier.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 03bd768..29f0f76 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -313,7 +313,7 @@ static void piix4_powerdown(void *opaque, int irq, int power_failing)
     acpi_pm1_evt_power_down(pm1a, tmr);
 }
 
-static void piix4_pm_machine_ready(struct Notifier* n)
+static void piix4_pm_machine_ready(Notifier *n, void *opaque)
 {
     PIIX4PMState *s = container_of(n, PIIX4PMState, machine_ready);
     uint8_t *pci_conf;
diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
index 85c8c3c..34e7526 100644
--- a/hw/fw_cfg.c
+++ b/hw/fw_cfg.c
@@ -316,7 +316,7 @@ int fw_cfg_add_file(FWCfgState *s,  const char *filename, uint8_t *data,
     return 1;
 }
 
-static void fw_cfg_machine_ready(struct Notifier* n)
+static void fw_cfg_machine_ready(struct Notifier *n, void *data)
 {
     uint32_t len;
     FWCfgState *s = container_of(n, FWCfgState, machine_ready);
diff --git a/input.c b/input.c
index f0a02e7..310bad5 100644
--- a/input.c
+++ b/input.c
@@ -59,7 +59,7 @@ static void check_mode_change(void)
 
     if (is_absolute != current_is_absolute ||
         has_absolute != current_has_absolute) {
-        notifier_list_notify(&mouse_mode_notifiers);
+        notifier_list_notify(&mouse_mode_notifiers, NULL);
     }
 
     current_is_absolute = is_absolute;
diff --git a/migration.c b/migration.c
index af3a1f2..2a15b98 100644
--- a/migration.c
+++ b/migration.c
@@ -124,7 +124,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
     }
 
     current_migration = s;
-    notifier_list_notify(&migration_state_notifiers);
+    notifier_list_notify(&migration_state_notifiers, NULL);
     return 0;
 }
 
@@ -276,7 +276,7 @@ void migrate_fd_error(FdMigrationState *s)
 {
     DPRINTF("setting error state\n");
     s->state = MIG_STATE_ERROR;
-    notifier_list_notify(&migration_state_notifiers);
+    notifier_list_notify(&migration_state_notifiers, NULL);
     migrate_fd_cleanup(s);
 }
 
@@ -334,7 +334,7 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
             monitor_resume(s->mon);
         }
         s->state = MIG_STATE_ERROR;
-        notifier_list_notify(&migration_state_notifiers);
+        notifier_list_notify(&migration_state_notifiers, NULL);
     }
 
     return ret;
@@ -395,7 +395,7 @@ void migrate_fd_put_ready(void *opaque)
             state = MIG_STATE_ERROR;
         }
         s->state = state;
-        notifier_list_notify(&migration_state_notifiers);
+        notifier_list_notify(&migration_state_notifiers, NULL);
     }
 }
 
@@ -415,7 +415,7 @@ void migrate_fd_cancel(MigrationState *mig_state)
     DPRINTF("cancelling migration\n");
 
     s->state = MIG_STATE_CANCELLED;
-    notifier_list_notify(&migration_state_notifiers);
+    notifier_list_notify(&migration_state_notifiers, NULL);
     qemu_savevm_state_cancel(s->mon, s->file);
 
     migrate_fd_cleanup(s);
@@ -429,7 +429,7 @@ void migrate_fd_release(MigrationState *mig_state)
    
     if (s->state == MIG_STATE_ACTIVE) {
         s->state = MIG_STATE_CANCELLED;
-        notifier_list_notify(&migration_state_notifiers);
+        notifier_list_notify(&migration_state_notifiers, NULL);
         migrate_fd_cleanup(s);
     }
     qemu_free(s);
diff --git a/notify.c b/notify.c
index bcd3fc5..a6bac1f 100644
--- a/notify.c
+++ b/notify.c
@@ -29,11 +29,11 @@ void notifier_list_remove(NotifierList *list, Notifier *notifier)
     QTAILQ_REMOVE(&list->notifiers, notifier, node);
 }
 
-void notifier_list_notify(NotifierList *list)
+void notifier_list_notify(NotifierList *list, void *data)
 {
     Notifier *notifier, *next;
 
     QTAILQ_FOREACH_SAFE(notifier, &list->notifiers, node, next) {
-        notifier->notify(notifier);
+        notifier->notify(notifier, data);
     }
 }
diff --git a/notify.h b/notify.h
index b40522f..54fc57c 100644
--- a/notify.h
+++ b/notify.h
@@ -20,7 +20,7 @@ typedef struct Notifier Notifier;
 
 struct Notifier
 {
-    void (*notify)(Notifier *notifier);
+    void (*notify)(Notifier *notifier, void *data);
     QTAILQ_ENTRY(Notifier) node;
 };
 
@@ -38,6 +38,6 @@ void notifier_list_add(NotifierList *list, Notifier *notifier);
 
 void notifier_list_remove(NotifierList *list, Notifier *notifier);
 
-void notifier_list_notify(NotifierList *list);
+void notifier_list_notify(NotifierList *list, void *data);
 
 #endif
diff --git a/ui/sdl.c b/ui/sdl.c
index f2bd4a0..6dbc5cb 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -481,7 +481,7 @@ static void sdl_grab_end(void)
     sdl_update_caption();
 }
 
-static void sdl_mouse_mode_change(Notifier *notify)
+static void sdl_mouse_mode_change(Notifier *notify, void *data)
 {
     if (kbd_mouse_is_absolute()) {
         if (!absolute_enabled) {
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 1100417..3d77c01 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -416,7 +416,7 @@ void do_info_spice(Monitor *mon, QObject **ret_data)
     *ret_data = QOBJECT(server);
 }
 
-static void migration_state_notifier(Notifier *notifier)
+static void migration_state_notifier(Notifier *notifier, void *data)
 {
     int state = get_migration_state();
 
diff --git a/ui/spice-input.c b/ui/spice-input.c
index 37c8578..75abf5f 100644
--- a/ui/spice-input.c
+++ b/ui/spice-input.c
@@ -178,7 +178,7 @@ static const SpiceTabletInterface tablet_interface = {
     .buttons            = tablet_buttons,
 };
 
-static void mouse_mode_notifier(Notifier *notifier)
+static void mouse_mode_notifier(Notifier *notifier, void *data)
 {
     QemuSpicePointer *pointer = container_of(notifier, QemuSpicePointer, mouse_mode);
     bool is_absolute  = kbd_mouse_is_absolute();
@@ -213,5 +213,5 @@ void qemu_spice_input_init(void)
     pointer->absolute = false;
     pointer->mouse_mode.notify = mouse_mode_notifier;
     qemu_add_mouse_mode_change_notifier(&pointer->mouse_mode);
-    mouse_mode_notifier(&pointer->mouse_mode);
+    mouse_mode_notifier(&pointer->mouse_mode, NULL);
 }
diff --git a/ui/vnc.c b/ui/vnc.c
index 8602adc..4425180 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1346,7 +1346,7 @@ static void client_cut_text(VncState *vs, size_t len, uint8_t *text)
 {
 }
 
-static void check_pointer_type_change(Notifier *notifier)
+static void check_pointer_type_change(Notifier *notifier, void *data)
 {
     VncState *vs = container_of(notifier, VncState, mouse_mode_notifier);
     int absolute = kbd_mouse_is_absolute();
@@ -1769,7 +1769,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
         }
     }
     vnc_desktop_resize(vs);
-    check_pointer_type_change(&vs->mouse_mode_notifier);
+    check_pointer_type_change(&vs->mouse_mode_notifier, NULL);
 }
 
 static void set_pixel_conversion(VncState *vs)
diff --git a/usb-linux.c b/usb-linux.c
index 1a2deb3..53cc5fc 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -1260,7 +1260,7 @@ static int usb_host_close(USBHostDevice *dev)
     return 0;
 }
 
-static void usb_host_exit_notifier(struct Notifier* n)
+static void usb_host_exit_notifier(struct Notifier *n, void *data)
 {
     USBHostDevice *s = container_of(n, USBHostDevice, exit);
 
diff --git a/vl.c b/vl.c
index 99d9201..4b6688b 100644
--- a/vl.c
+++ b/vl.c
@@ -2009,7 +2009,7 @@ void qemu_remove_exit_notifier(Notifier *notify)
 
 static void qemu_run_exit_notifiers(void)
 {
-    notifier_list_notify(&exit_notifiers);
+    notifier_list_notify(&exit_notifiers, NULL);
 }
 
 void qemu_add_machine_init_done_notifier(Notifier *notify)
@@ -2019,7 +2019,7 @@ void qemu_add_machine_init_done_notifier(Notifier *notify)
 
 static void qemu_run_machine_init_done_notifiers(void)
 {
-    notifier_list_notify(&machine_init_done_notifiers);
+    notifier_list_notify(&machine_init_done_notifiers, NULL);
 }
 
 static const QEMUOption *lookup_opt(int argc, char **argv,
diff --git a/xen-all.c b/xen-all.c
index 8105c83..167bed6 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -839,7 +839,7 @@ static void xen_vm_change_state_handler(void *opaque, int running, int reason)
     }
 }
 
-static void xen_exit_notifier(Notifier *n)
+static void xen_exit_notifier(Notifier *n, void *data)
 {
     XenIOState *state = container_of(n, XenIOState, exit);
 
commit e0e8384dd471376c3f815c3070f161480a28cc90
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu May 19 13:37:17 2011 +0200

    ide: Turn properties any IDE device must have into bus properties
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index d9b8f24..6bd8d20 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -31,6 +31,10 @@ static struct BusInfo ide_bus_info = {
     .name  = "IDE",
     .size  = sizeof(IDEBus),
     .get_fw_dev_path = idebus_get_fw_dev_path,
+    .props = (Property[]) {
+        DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1),
+        DEFINE_PROP_END_OF_LIST(),
+    },
 };
 
 void ide_bus_new(IDEBus *idebus, DeviceState *dev, int bus_id)
@@ -174,7 +178,6 @@ static int ide_drive_initfn(IDEDevice *dev)
 }
 
 #define DEFINE_IDE_DEV_PROPERTIES()                     \
-    DEFINE_PROP_UINT32("unit", IDEDrive, dev.unit, -1), \
     DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf),        \
     DEFINE_PROP_STRING("ver",  IDEDrive, dev.version),  \
     DEFINE_PROP_STRING("serial",  IDEDrive, dev.serial)
commit d6cca4b048c5b63547d5c09fb47a10f0057b88bf
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu May 19 13:37:16 2011 +0200

    virtio-serial: Turn props any virtio-serial-bus device must have into bus props
    
    Signed-off-by: Markus Armbruster <armbru 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 7ebfa26..fe5e188 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -139,9 +139,7 @@ static VirtIOSerialPortInfo virtconsole_info = {
     .init          = virtconsole_initfn,
     .exit          = virtconsole_exitfn,
     .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("nr", VirtConsole, port.id, VIRTIO_CONSOLE_BAD_ID),
         DEFINE_PROP_CHR("chardev", VirtConsole, chr),
-        DEFINE_PROP_STRING("name", VirtConsole, port.name),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
@@ -158,9 +156,7 @@ static VirtIOSerialPortInfo virtserialport_info = {
     .init          = virtconsole_initfn,
     .exit          = virtconsole_exitfn,
     .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("nr", VirtConsole, port.id, VIRTIO_CONSOLE_BAD_ID),
         DEFINE_PROP_CHR("chardev", VirtConsole, chr),
-        DEFINE_PROP_STRING("name", VirtConsole, port.name),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index e7e12f0..c5eb931 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -668,6 +668,11 @@ static struct BusInfo virtser_bus_info = {
     .name      = "virtio-serial-bus",
     .size      = sizeof(VirtIOSerialBus),
     .print_dev = virtser_bus_dev_print,
+    .props      = (Property[]) {
+        DEFINE_PROP_UINT32("nr", VirtIOSerialPort, id, VIRTIO_CONSOLE_BAD_ID),
+        DEFINE_PROP_STRING("name", VirtIOSerialPort, name),
+        DEFINE_PROP_END_OF_LIST()
+    }
 };
 
 static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
commit 021a1318604e0898cee3800d5b13033e68191f4e
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu May 19 13:37:15 2011 +0200

    virtio-serial: Clean up virtser_bus_dev_print() output
    
    Old version looks like this in info qtree (last four lines):
    
              dev: virtconsole, id ""
                dev-prop: is_console = 1
                dev-prop: nr = 0
                dev-prop: chardev = <null>
                dev-prop: name = <null>
                 dev-prop-int: id: 0
                 dev-prop-int: guest_connected: 1
                 dev-prop-int: host_connected: 0
                 dev-prop-int: throttled: 0
    
    Indentation is off, and "dev-prop-int" suggests these are properties
    you can configure with -device, which isn't the case.  The other
    buses' print_dev() callbacks don't do that.  For instance, PCI's
    output looks like this:
    
            class Ethernet controller, addr 00:03.0, pci id 1af4:1000 (sub 1af4:0001)
            bar 0: i/o at 0xffffffffffffffff [0x1e]
            bar 1: mem at 0xffffffffffffffff [0xffe]
            bar 6: mem at 0xffffffffffffffff [0xfffe]
    
    Change virtser_bus_dev_print() to that style.  Result:
    
              dev: virtconsole, id ""
                dev-prop: is_console = 1
                dev-prop: nr = 0
                dev-prop: chardev = <null>
                dev-prop: name = <null>
                port 0, guest on, host off, throttle off
    
    Signed-off-by: Markus Armbruster <armbru 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 bdc760c..e7e12f0 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -674,14 +674,11 @@ static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
 {
     VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev);
 
-    monitor_printf(mon, "%*s dev-prop-int: id: %u\n",
-                   indent, "", port->id);
-    monitor_printf(mon, "%*s dev-prop-int: guest_connected: %d\n",
-                   indent, "", port->guest_connected);
-    monitor_printf(mon, "%*s dev-prop-int: host_connected: %d\n",
-                   indent, "", port->host_connected);
-    monitor_printf(mon, "%*s dev-prop-int: throttled: %d\n",
-                   indent, "", port->throttled);
+    monitor_printf(mon, "%*sport %d, guest %s, host %s, throttle %s\n",
+                   indent, "", port->id,
+                   port->guest_connected ? "on" : "off",
+                   port->host_connected ? "on" : "off",
+                   port->throttled ? "on" : "off");
 }
 
 /* This function is only used if a port id is not provided by the user */
commit 1cc2428ccec8759130c45033c8a44867e919485f
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu May 19 13:37:14 2011 +0200

    usb-ccid: Drop unused CCIDCardInfo callback print()
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ccid.h b/hw/ccid.h
index dbfc13c..d3e0371 100644
--- a/hw/ccid.h
+++ b/hw/ccid.h
@@ -29,7 +29,6 @@ struct CCIDCardState {
  */
 struct CCIDCardInfo {
     DeviceInfo qdev;
-    void (*print)(Monitor *mon, CCIDCardState *card, int indent);
     const uint8_t *(*get_atr)(CCIDCardState *card, uint32_t *len);
     void (*apdu_from_guest)(CCIDCardState *card,
                             const uint8_t *apdu,
diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c
index d392299..4dda2c4 100644
--- a/hw/usb-ccid.c
+++ b/hw/usb-ccid.c
@@ -1104,20 +1104,9 @@ static Answer *ccid_peek_next_answer(USBCCIDState *s)
         : &s->pending_answers[s->pending_answers_start % PENDING_ANSWERS_NUM];
 }
 
-static void ccid_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
-{
-    CCIDCardState *card = DO_UPCAST(CCIDCardState, qdev, qdev);
-    CCIDCardInfo *info = DO_UPCAST(CCIDCardInfo, qdev, qdev->info);
-
-    if (info->print) {
-        info->print(mon, card, indent);
-    }
-}
-
 static struct BusInfo ccid_bus_info = {
     .name = "ccid-bus",
     .size = sizeof(CCIDBus),
-    .print_dev = ccid_bus_dev_print,
     .props = (Property[]) {
         DEFINE_PROP_UINT32("slot", struct CCIDCardState, slot, 0),
         DEFINE_PROP_END_OF_LIST(),
commit 3836620c091626c26caa77af66a90c047a8e8384
Author: Daniel P. Berrange <berrange at redhat.com>
Date:   Thu Jun 23 13:31:43 2011 +0100

    Remove unused USES_X509_AUTH macro from VNC sasl code
    
    The USES_X509_AUTH macro is defined in several VNC files,
    but not used in all of them. Remove the unused definition.
    
    * ui/vnc-auth-sasl.c: Remove USES_X509_AUTH macro
    
    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 8aac5ec..15af49b 100644
--- a/ui/vnc-auth-sasl.c
+++ b/ui/vnc-auth-sasl.c
@@ -491,13 +491,6 @@ static int protocol_client_auth_sasl_mechname_len(VncState *vs, uint8_t *data, s
     return 0;
 }
 
-#define USES_X509_AUTH(vs)                              \
-    ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE ||   \
-     (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC ||    \
-     (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN ||  \
-     (vs)->subauth == VNC_AUTH_VENCRYPT_X509SASL)
-
-
 void start_auth_sasl(VncState *vs)
 {
     const char *mechlist = NULL;
commit 13661089810d3e59931f3e80d7cb541b99af7071
Author: Daniel P. Berrange <berrange at redhat.com>
Date:   Thu Jun 23 13:31:42 2011 +0100

    Introduce a 'client_add' monitor command accepting an open FD
    
    Allow client connections for VNC and socket based character
    devices to be passed in over the monitor using SCM_RIGHTS.
    
    One intended usage scenario is to start QEMU with VNC on a
    UNIX domain socket. An unprivileged user which cannot access
    the UNIX domain socket, can then connect to QEMU's VNC server
    by passing an open FD to libvirt, which passes it onto QEMU.
    
     { "execute": "get_fd", "arguments": { "fdname": "myclient" } }
     { "return": {} }
     { "execute": "add_client", "arguments": { "protocol": "vnc",
                                               "fdname": "myclient",
                                               "skipauth": true } }
     { "return": {} }
    
    In this case 'protocol' can be 'vnc' or 'spice', or the name
    of a character device (eg from -chardev id=XXXX)
    
    The 'skipauth' parameter can be used to skip any configured
    VNC authentication scheme, which is useful if the mgmt layer
    talking to the monitor has already authenticated the client
    in another way.
    
    * console.h: Define 'vnc_display_add_client' method
    * monitor.c: Implement 'client_add' command
    * qemu-char.c, qemu-char.h: Add 'qemu_char_add_client' method
    * qerror.c, qerror.h: Add QERR_ADD_CLIENT_FAILED
    * qmp-commands.hx: Declare 'client_add' command
    * ui/vnc.c: Implement 'vnc_display_add_client' method
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/console.h b/console.h
index c09537b..67d1373 100644
--- a/console.h
+++ b/console.h
@@ -372,6 +372,7 @@ void cocoa_display_init(DisplayState *ds, int full_screen);
 void vnc_display_init(DisplayState *ds);
 void vnc_display_close(DisplayState *ds);
 int vnc_display_open(DisplayState *ds, const char *display);
+void vnc_display_add_client(DisplayState *ds, int csock, int skipauth);
 int vnc_display_disable_login(DisplayState *ds);
 char *vnc_display_local_addr(DisplayState *ds);
 #ifdef CONFIG_VNC
diff --git a/monitor.c b/monitor.c
index 67ceb46..718935b 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1185,6 +1185,38 @@ static int expire_password(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return -1;
 }
 
+static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+    const char *protocol  = qdict_get_str(qdict, "protocol");
+    const char *fdname = qdict_get_str(qdict, "fdname");
+    int skipauth = qdict_get_try_bool(qdict, "skipauth", 0);
+    CharDriverState *s;
+
+    if (strcmp(protocol, "spice") == 0) {
+        if (!using_spice) {
+            /* correct one? spice isn't a device ,,, */
+            qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
+            return -1;
+        }
+	qerror_report(QERR_ADD_CLIENT_FAILED);
+	return -1;
+    } else if (strcmp(protocol, "vnc") == 0) {
+	int fd = monitor_get_fd(mon, fdname);
+	vnc_display_add_client(NULL, fd, skipauth);
+	return 0;
+    } else if ((s = qemu_chr_find(protocol)) != NULL) {
+	int fd = monitor_get_fd(mon, fdname);
+	if (qemu_chr_add_client(s, fd) < 0) {
+	    qerror_report(QERR_ADD_CLIENT_FAILED);
+	    return -1;
+	}
+	return 0;
+    }
+
+    qerror_report(QERR_INVALID_PARAMETER, "protocol");
+    return -1;
+}
+
 static int client_migrate_info(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     const char *protocol = qdict_get_str(qdict, "protocol");
diff --git a/qemu-char.c b/qemu-char.c
index 926987b..dcf7065 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -168,6 +168,11 @@ int qemu_chr_get_msgfd(CharDriverState *s)
     return s->get_msgfd ? s->get_msgfd(s) : -1;
 }
 
+int qemu_chr_add_client(CharDriverState *s, int fd)
+{
+    return s->chr_add_client ? s->chr_add_client(s, fd) : -1;
+}
+
 void qemu_chr_accept_input(CharDriverState *s)
 {
     if (s->chr_accept_input)
@@ -2146,6 +2151,22 @@ static void socket_set_nodelay(int fd)
     setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
 }
 
+static int tcp_chr_add_client(CharDriverState *chr, int fd)
+{
+    TCPCharDriver *s = chr->opaque;
+    if (s->fd != -1)
+	return -1;
+
+    socket_set_nonblock(fd);
+    if (s->do_nodelay)
+        socket_set_nodelay(fd);
+    s->fd = fd;
+    qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
+    tcp_chr_connect(chr);
+
+    return 0;
+}
+
 static void tcp_chr_accept(void *opaque)
 {
     CharDriverState *chr = opaque;
@@ -2178,12 +2199,8 @@ static void tcp_chr_accept(void *opaque)
             break;
         }
     }
-    socket_set_nonblock(fd);
-    if (s->do_nodelay)
-        socket_set_nodelay(fd);
-    s->fd = fd;
-    qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
-    tcp_chr_connect(chr);
+    if (tcp_chr_add_client(chr, fd) < 0)
+	close(fd);
 }
 
 static void tcp_chr_close(CharDriverState *chr)
@@ -2256,6 +2273,7 @@ static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
     chr->chr_write = tcp_chr_write;
     chr->chr_close = tcp_chr_close;
     chr->get_msgfd = tcp_get_msgfd;
+    chr->chr_add_client = tcp_chr_add_client;
 
     if (is_listen) {
         s->listen_fd = fd;
diff --git a/qemu-char.h b/qemu-char.h
index 892c6da..f361c6d 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -57,6 +57,7 @@ struct CharDriverState {
     void (*chr_update_read_handler)(struct CharDriverState *s);
     int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg);
     int (*get_msgfd)(struct CharDriverState *s);
+    int (*chr_add_client)(struct CharDriverState *chr, int fd);
     IOEventHandler *chr_event;
     IOCanReadHandler *chr_can_read;
     IOReadHandler *chr_read;
@@ -99,6 +100,7 @@ int qemu_chr_can_read(CharDriverState *s);
 void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len);
 int qemu_chr_get_msgfd(CharDriverState *s);
 void qemu_chr_accept_input(CharDriverState *s);
+int qemu_chr_add_client(CharDriverState *s, int fd);
 void qemu_chr_info_print(Monitor *mon, const QObject *ret_data);
 void qemu_chr_info(Monitor *mon, QObject **ret_data);
 CharDriverState *qemu_chr_find(const char *name);
diff --git a/qerror.c b/qerror.c
index 229d0d6..69c1bc9 100644
--- a/qerror.c
+++ b/qerror.c
@@ -198,6 +198,10 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Could not set password",
     },
     {
+        .error_fmt = QERR_ADD_CLIENT_FAILED,
+        .desc      = "Could not add client",
+    },
+    {
         .error_fmt = QERR_TOO_MANY_FILES,
         .desc      = "Too many open files",
     },
diff --git a/qerror.h b/qerror.h
index 7ec0fc1..8058456 100644
--- a/qerror.h
+++ b/qerror.h
@@ -166,6 +166,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_SET_PASSWD_FAILED \
     "{ 'class': 'SetPasswdFailed', 'data': {} }"
 
+#define QERR_ADD_CLIENT_FAILED \
+    "{ 'class': 'AddClientFailed', 'data': {} }"
+
 #define QERR_TOO_MANY_FILES \
     "{ 'class': 'TooManyFiles', 'data': {} }"
 
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 5d44edf..54e313c 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -919,6 +919,33 @@ Example:
 EQMP
 
     {
+        .name       = "add_client",
+        .args_type  = "protocol:s,fdname:s,skipauth:b?",
+        .params     = "protocol fdname skipauth",
+        .help       = "add a graphics client",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = add_graphics_client,
+    },
+
+SQMP
+add_client
+----------
+
+Add a graphics client
+
+Arguments:
+
+- "protocol": protocol name (json-string)
+- "fdname": file descriptor name (json-string)
+
+Example:
+
+-> { "execute": "add_client", "arguments": { "protocol": "vnc",
+                                             "fdname": "myclient" } }
+<- { "return": {} }
+
+EQMP
+    {
         .name       = "qmp_capabilities",
         .args_type  = "",
         .params     = "",
diff --git a/ui/vnc.c b/ui/vnc.c
index 39b5b51..8602adc 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2924,3 +2924,10 @@ int vnc_display_open(DisplayState *ds, const char *display)
     }
     return qemu_set_fd_handler2(vs->lsock, NULL, vnc_listen_read, NULL, vs);
 }
+
+void vnc_display_add_client(DisplayState *ds, int csock, int skipauth)
+{
+    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+
+    return vnc_connect(vs, csock, skipauth);
+}
commit 7e7e2ebc942da8285931ceabf12823e165dced8b
Author: Daniel P. Berrange <berrange at redhat.com>
Date:   Thu Jun 23 13:31:41 2011 +0100

    Store VNC auth scheme per-client as well as per-server
    
    A future patch will introduce a situation where different
    clients may have different authentication schemes set.
    When a new client arrives, copy the 'auth' and 'subauth'
    fields from VncDisplay into the client's VncState, and
    use the latter in all authentication functions.
    
    * ui/vnc.h: Add 'auth' and 'subauth' to VncState
    * ui/vnc-auth-sasl.c, ui/vnc-auth-vencrypt.c,
      ui/vnc.c: Make auth functions pull auth scheme
      from VncState instead of VncDisplay
    
    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 17a621a..8aac5ec 100644
--- a/ui/vnc-auth-sasl.c
+++ b/ui/vnc-auth-sasl.c
@@ -538,8 +538,8 @@ void start_auth_sasl(VncState *vs)
 
 #ifdef CONFIG_VNC_TLS
     /* Inform SASL that we've got an external SSF layer from TLS/x509 */
-    if (vs->vd->auth == VNC_AUTH_VENCRYPT &&
-        vs->vd->subauth == VNC_AUTH_VENCRYPT_X509SASL) {
+    if (vs->auth == VNC_AUTH_VENCRYPT &&
+        vs->subauth == VNC_AUTH_VENCRYPT_X509SASL) {
         gnutls_cipher_algorithm_t cipher;
         sasl_ssf_t ssf;
 
@@ -570,8 +570,8 @@ void start_auth_sasl(VncState *vs)
 #ifdef CONFIG_VNC_TLS
         /* Disable SSF, if using TLS+x509+SASL only. TLS without x509
            is not sufficiently strong */
-        || (vs->vd->auth == VNC_AUTH_VENCRYPT &&
-            vs->vd->subauth == VNC_AUTH_VENCRYPT_X509SASL)
+        || (vs->auth == VNC_AUTH_VENCRYPT &&
+            vs->subauth == VNC_AUTH_VENCRYPT_X509SASL)
 #endif /* CONFIG_VNC_TLS */
         ) {
         /* If we've got TLS or UNIX domain sock, we don't care about SSF */
diff --git a/ui/vnc-auth-vencrypt.c b/ui/vnc-auth-vencrypt.c
index 07c1691..674ba97 100644
--- a/ui/vnc-auth-vencrypt.c
+++ b/ui/vnc-auth-vencrypt.c
@@ -29,7 +29,7 @@
 
 static void start_auth_vencrypt_subauth(VncState *vs)
 {
-    switch (vs->vd->subauth) {
+    switch (vs->subauth) {
     case VNC_AUTH_VENCRYPT_TLSNONE:
     case VNC_AUTH_VENCRYPT_X509NONE:
        VNC_DEBUG("Accept TLS auth none\n");
@@ -51,7 +51,7 @@ static void start_auth_vencrypt_subauth(VncState *vs)
 #endif /* CONFIG_VNC_SASL */
 
     default: /* Should not be possible, but just in case */
-       VNC_DEBUG("Reject subauth %d server bug\n", vs->vd->auth);
+       VNC_DEBUG("Reject subauth %d server bug\n", vs->auth);
        vnc_write_u8(vs, 1);
        if (vs->minor >= 8) {
            static const char err[] = "Unsupported authentication type";
@@ -110,17 +110,17 @@ static void vnc_tls_handshake_io(void *opaque) {
 
 
 #define NEED_X509_AUTH(vs)                              \
-    ((vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509NONE ||   \
-     (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509VNC ||    \
-     (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509PLAIN ||  \
-     (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509SASL)
+    ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE ||   \
+     (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC ||    \
+     (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN ||  \
+     (vs)->subauth == VNC_AUTH_VENCRYPT_X509SASL)
 
 
 static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len)
 {
     int auth = read_u32(data, 0);
 
-    if (auth != vs->vd->subauth) {
+    if (auth != vs->subauth) {
         VNC_DEBUG("Rejecting auth %d\n", auth);
         vnc_write_u8(vs, 0); /* Reject auth */
         vnc_flush(vs);
@@ -153,10 +153,10 @@ static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len
         vnc_flush(vs);
         vnc_client_error(vs);
     } else {
-        VNC_DEBUG("Sending allowed auth %d\n", vs->vd->subauth);
+        VNC_DEBUG("Sending allowed auth %d\n", vs->subauth);
         vnc_write_u8(vs, 0); /* Accept version */
         vnc_write_u8(vs, 1); /* Number of sub-auths */
-        vnc_write_u32(vs, vs->vd->subauth); /* The supported auth */
+        vnc_write_u32(vs, vs->subauth); /* The supported auth */
         vnc_flush(vs);
         vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
     }
diff --git a/ui/vnc.c b/ui/vnc.c
index 14f2930..39b5b51 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2124,7 +2124,7 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
 {
     /* We only advertise 1 auth scheme at a time, so client
      * must pick the one we sent. Verify this */
-    if (data[0] != vs->vd->auth) { /* Reject auth */
+    if (data[0] != vs->auth) { /* Reject auth */
        VNC_DEBUG("Reject auth %d because it didn't match advertized\n", (int)data[0]);
        vnc_write_u32(vs, 1);
        if (vs->minor >= 8) {
@@ -2135,7 +2135,7 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
        vnc_client_error(vs);
     } else { /* Accept requested auth */
        VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
-       switch (vs->vd->auth) {
+       switch (vs->auth) {
        case VNC_AUTH_NONE:
            VNC_DEBUG("Accept auth none\n");
            if (vs->minor >= 8) {
@@ -2165,7 +2165,7 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
 #endif /* CONFIG_VNC_SASL */
 
        default: /* Should not be possible, but just in case */
-           VNC_DEBUG("Reject auth %d server code bug\n", vs->vd->auth);
+           VNC_DEBUG("Reject auth %d server code bug\n", vs->auth);
            vnc_write_u8(vs, 1);
            if (vs->minor >= 8) {
                static const char err[] = "Authentication failed";
@@ -2210,26 +2210,26 @@ static int protocol_version(VncState *vs, uint8_t *version, size_t len)
         vs->minor = 3;
 
     if (vs->minor == 3) {
-        if (vs->vd->auth == VNC_AUTH_NONE) {
+        if (vs->auth == VNC_AUTH_NONE) {
             VNC_DEBUG("Tell client auth none\n");
-            vnc_write_u32(vs, vs->vd->auth);
+            vnc_write_u32(vs, vs->auth);
             vnc_flush(vs);
             start_client_init(vs);
-       } else if (vs->vd->auth == VNC_AUTH_VNC) {
+       } else if (vs->auth == VNC_AUTH_VNC) {
             VNC_DEBUG("Tell client VNC auth\n");
-            vnc_write_u32(vs, vs->vd->auth);
+            vnc_write_u32(vs, vs->auth);
             vnc_flush(vs);
             start_auth_vnc(vs);
        } else {
-            VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->vd->auth);
+            VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->auth);
             vnc_write_u32(vs, VNC_AUTH_INVALID);
             vnc_flush(vs);
             vnc_client_error(vs);
        }
     } else {
-        VNC_DEBUG("Telling client we support auth %d\n", vs->vd->auth);
+        VNC_DEBUG("Telling client we support auth %d\n", vs->auth);
         vnc_write_u8(vs, 1); /* num auth */
-        vnc_write_u8(vs, vs->vd->auth);
+        vnc_write_u8(vs, vs->auth);
         vnc_read_when(vs, protocol_client_auth, 1);
         vnc_flush(vs);
     }
@@ -2494,12 +2494,25 @@ static void vnc_remove_timer(VncDisplay *vd)
     }
 }
 
-static void vnc_connect(VncDisplay *vd, int csock)
+static void vnc_connect(VncDisplay *vd, int csock, int skipauth)
 {
     VncState *vs = qemu_mallocz(sizeof(VncState));
     int i;
 
     vs->csock = csock;
+
+    if (skipauth) {
+	vs->auth = VNC_AUTH_NONE;
+#ifdef CONFIG_VNC_TLS
+	vs->subauth = VNC_AUTH_INVALID;
+#endif
+    } else {
+	vs->auth = vd->auth;
+#ifdef CONFIG_VNC_TLS
+	vs->subauth = vd->subauth;
+#endif
+    }
+
     vs->lossy_rect = qemu_mallocz(VNC_STAT_ROWS * sizeof (*vs->lossy_rect));
     for (i = 0; i < VNC_STAT_ROWS; ++i) {
         vs->lossy_rect[i] = qemu_mallocz(VNC_STAT_COLS * sizeof (uint8_t));
@@ -2557,7 +2570,7 @@ static void vnc_listen_read(void *opaque)
 
     int csock = qemu_accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
     if (csock != -1) {
-        vnc_connect(vs, csock);
+        vnc_connect(vs, csock, 0);
     }
 }
 
@@ -2887,7 +2900,7 @@ int vnc_display_open(DisplayState *ds, const char *display)
         } else {
             int csock = vs->lsock;
             vs->lsock = -1;
-            vnc_connect(vs, csock);
+            vnc_connect(vs, csock, 0);
         }
         return 0;
 
diff --git a/ui/vnc.h b/ui/vnc.h
index f10c5dc..66689f1 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -256,8 +256,10 @@ struct VncState
     int major;
     int minor;
 
+    int auth;
     char challenge[VNC_AUTH_CHALLENGE_SIZE];
 #ifdef CONFIG_VNC_TLS
+    int subauth; /* Used by VeNCrypt */
     VncStateTLS tls;
 #endif
 #ifdef CONFIG_VNC_SASL
commit e69ae5c49af45a67ebdf6a7cf465eb91b5c8ee11
Author: Wen Congyang <wency at cn.fujitsu.com>
Date:   Fri Jun 17 10:25:22 2011 +0800

    do not reset no_shutdown after we shutdown the vm
    
    Daniel P. Berrange sent a libvirt's patch to support
    reboots with the QEMU driver. He implements it in
    json model like this:
    1. add -no-shutdown in the qemu's option:
       qemu -no-shutdown xxxx
    2. shutdown the vm by monitor command system_powerdown
    3. wait for shutdown event
    4. reset the vm by monitor command system_reset
    
    no_shutdown will be reset to 0 if the vm is powered down.
    We only can reboot the vm once.
    
    If no_shutdown is not reset to 0, we can reboot the vm
    many times.
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index 65438b3..99d9201 100644
--- a/vl.c
+++ b/vl.c
@@ -1398,7 +1398,6 @@ static void main_loop(void)
             monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
             if (no_shutdown) {
                 vm_stop(VMSTOP_SHUTDOWN);
-                no_shutdown = 0;
             } else
                 break;
         }
commit ea0e541812c515e0bbdf598d3237d6f0bee3fbbf
Author: Sasha Levin <levinsasha928 at gmail.com>
Date:   Wed Jun 29 23:29:39 2011 -0400

    vl.c: Don't limit node count by smp count
    
    [I've sent this patch couple of months ago and noticed it
     didn't make it's way in - so I'm sending it again]
    
    It is possible to create CPU-less NUMA nodes, node amount shouldn't be
    limited by amount of CPUs.
    
    Tested-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Acked-by: Andre Przywara <andre.przywara at amd.com>
    Signed-off-by: Sasha Levin <levinsasha928 at gmail.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index acfff85..65438b3 100644
--- a/vl.c
+++ b/vl.c
@@ -3129,8 +3129,8 @@ int main(int argc, char **argv, char **envp)
     if (nb_numa_nodes > 0) {
         int i;
 
-        if (nb_numa_nodes > smp_cpus) {
-            nb_numa_nodes = smp_cpus;
+        if (nb_numa_nodes > MAX_NODES) {
+            nb_numa_nodes = MAX_NODES;
         }
 
         /* If no memory size if given for any node, assume the default case
commit 0fe28e0d9f549fab79793d3fa2f139e643d3f134
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Jun 14 12:53:08 2011 -0700

    vga: Fix type of lfb/map_addr/end.
    
    These addresses have been passed through pci_to_cpu_addr,
    and thus need to be full target_phys_addr_t.
    
    Acked-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Cc: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/vga_int.h b/hw/vga_int.h
index d2811bd..eee91a8 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -106,13 +106,13 @@ typedef void (* vga_update_retrace_info_fn)(struct VGACommonState *s);
 typedef struct VGACommonState {
     uint8_t *vram_ptr;
     ram_addr_t vram_offset;
+    target_phys_addr_t lfb_addr;
+    target_phys_addr_t lfb_end;
+    target_phys_addr_t map_addr;
+    target_phys_addr_t map_end;
     uint32_t vram_size;
-    uint32_t lfb_addr;
-    uint32_t lfb_end;
-    uint32_t map_addr;
-    uint32_t map_end;
-    uint32_t lfb_vram_mapped; /* whether 0xa0000 is mapped as ram */
     uint32_t latch;
+    uint32_t lfb_vram_mapped; /* whether 0xa0000 is mapped as ram */
     uint8_t sr_index;
     uint8_t sr[256];
     uint8_t gr_index;
commit 6e1db57b2ac9025c2443c665a0d9e78748637b26
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Jun 1 13:29:11 2011 +0200

    qemu-char: Print strerror message on failure
    
    The only way for chardev drivers to communicate an error was to return a NULL
    pointer, which resulted in an error message that said _that_ something went
    wrong, but not _why_.
    
    This patch changes the interface to return 0/-errno and updates
    qemu_chr_open_opts to use strerror to display a more helpful error message.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/console.c b/console.c
index acd8ca1..242086c 100644
--- a/console.c
+++ b/console.c
@@ -1514,7 +1514,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
         chr->init(chr);
 }
 
-CharDriverState *text_console_init(QemuOpts *opts)
+int text_console_init(QemuOpts *opts, CharDriverState **_chr)
 {
     CharDriverState *chr;
     TextConsole *s;
@@ -1546,7 +1546,7 @@ CharDriverState *text_console_init(QemuOpts *opts)
 
     if (!s) {
         free(chr);
-        return NULL;
+        return -EBUSY;
     }
 
     s->chr = chr;
@@ -1554,7 +1554,9 @@ CharDriverState *text_console_init(QemuOpts *opts)
     s->g_height = height;
     chr->opaque = s;
     chr->chr_set_echo = text_console_set_echo;
-    return chr;
+
+    *_chr = chr;
+    return 0;
 }
 
 void text_consoles_set_display(DisplayState *ds)
diff --git a/console.h b/console.h
index 64d1f09..c09537b 100644
--- a/console.h
+++ b/console.h
@@ -354,7 +354,7 @@ void vga_hw_text_update(console_ch_t *chardata);
 
 int is_graphic_console(void);
 int is_fixedsize_console(void);
-CharDriverState *text_console_init(QemuOpts *opts);
+int text_console_init(QemuOpts *opts, CharDriverState **_chr);
 void text_consoles_set_display(DisplayState *ds);
 void console_select(unsigned int index);
 void console_color_init(DisplayState *ds);
diff --git a/hw/baum.c b/hw/baum.c
index 2aaf5ff..33a22a7 100644
--- a/hw/baum.c
+++ b/hw/baum.c
@@ -576,7 +576,7 @@ static void baum_close(struct CharDriverState *chr)
     qemu_free(baum);
 }
 
-CharDriverState *chr_baum_init(QemuOpts *opts)
+int chr_baum_init(QemuOpts *opts, CharDriverState **_chr)
 {
     BaumDriverState *baum;
     CharDriverState *chr;
@@ -629,7 +629,8 @@ CharDriverState *chr_baum_init(QemuOpts *opts)
 
     qemu_chr_generic_open(chr);
 
-    return chr;
+    *_chr = chr;
+    return 0;
 
 fail:
     qemu_free_timer(baum->cellCount_timer);
@@ -638,5 +639,5 @@ fail_handle:
     qemu_free(handle);
     qemu_free(chr);
     qemu_free(baum);
-    return NULL;
+    return -EIO;
 }
diff --git a/hw/msmouse.c b/hw/msmouse.c
index 05f893c..67c6cd4 100644
--- a/hw/msmouse.c
+++ b/hw/msmouse.c
@@ -64,7 +64,7 @@ static void msmouse_chr_close (struct CharDriverState *chr)
     qemu_free (chr);
 }
 
-CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts)
+int qemu_chr_open_msmouse(QemuOpts *opts, CharDriverState **_chr)
 {
     CharDriverState *chr;
 
@@ -74,5 +74,6 @@ CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts)
 
     qemu_add_mouse_event_handler(msmouse_event, chr, 0, "QEMU Microsoft Mouse");
 
-    return chr;
+    *_chr = chr;
+    return 0;
 }
diff --git a/hw/msmouse.h b/hw/msmouse.h
index 456cb21..8b853b3 100644
--- a/hw/msmouse.h
+++ b/hw/msmouse.h
@@ -1,2 +1,2 @@
 /* msmouse.c */
-CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts);
+int qemu_chr_open_msmouse(QemuOpts *opts, CharDriverState **_chr);
diff --git a/qemu-char.c b/qemu-char.c
index fb13b28..926987b 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -219,13 +219,15 @@ static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
     return len;
 }
 
-static CharDriverState *qemu_chr_open_null(QemuOpts *opts)
+static int qemu_chr_open_null(QemuOpts *opts, CharDriverState **_chr)
 {
     CharDriverState *chr;
 
     chr = qemu_mallocz(sizeof(CharDriverState));
     chr->chr_write = null_chr_write;
-    return chr;
+
+    *_chr= chr;
+    return 0;
 }
 
 /* MUX driver for serial I/O splitting */
@@ -634,18 +636,21 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
     return chr;
 }
 
-static CharDriverState *qemu_chr_open_file_out(QemuOpts *opts)
+static int qemu_chr_open_file_out(QemuOpts *opts, CharDriverState **_chr)
 {
     int fd_out;
 
     TFR(fd_out = qemu_open(qemu_opt_get(opts, "path"),
                       O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666));
-    if (fd_out < 0)
-        return NULL;
-    return qemu_chr_open_fd(-1, fd_out);
+    if (fd_out < 0) {
+        return -errno;
+    }
+
+    *_chr = qemu_chr_open_fd(-1, fd_out);
+    return 0;
 }
 
-static CharDriverState *qemu_chr_open_pipe(QemuOpts *opts)
+static int qemu_chr_open_pipe(QemuOpts *opts, CharDriverState **_chr)
 {
     int fd_in, fd_out;
     char filename_in[256], filename_out[256];
@@ -653,7 +658,7 @@ static CharDriverState *qemu_chr_open_pipe(QemuOpts *opts)
 
     if (filename == NULL) {
         fprintf(stderr, "chardev: pipe: no filename given\n");
-        return NULL;
+        return -EINVAL;
     }
 
     snprintf(filename_in, 256, "%s.in", filename);
@@ -665,11 +670,14 @@ static CharDriverState *qemu_chr_open_pipe(QemuOpts *opts)
 	    close(fd_in);
 	if (fd_out >= 0)
 	    close(fd_out);
-        TFR(fd_in = fd_out = open(filename, O_RDWR | O_BINARY));
-        if (fd_in < 0)
-            return NULL;
+        TFR(fd_in = fd_out = qemu_open(filename, O_RDWR | O_BINARY));
+        if (fd_in < 0) {
+            return -errno;
+        }
     }
-    return qemu_chr_open_fd(fd_in, fd_out);
+
+    *_chr = qemu_chr_open_fd(fd_in, fd_out);
+    return 0;
 }
 
 
@@ -760,12 +768,14 @@ static void qemu_chr_close_stdio(struct CharDriverState *chr)
     fd_chr_close(chr);
 }
 
-static CharDriverState *qemu_chr_open_stdio(QemuOpts *opts)
+static int qemu_chr_open_stdio(QemuOpts *opts, CharDriverState **_chr)
 {
     CharDriverState *chr;
 
-    if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
-        return NULL;
+    if (stdio_nb_clients >= STDIO_MAX_CLIENTS) {
+        return -EBUSY;
+    }
+
     if (stdio_nb_clients == 0) {
         old_fd0_flags = fcntl(0, F_GETFL);
         tcgetattr (0, &oldtty);
@@ -782,7 +792,8 @@ static CharDriverState *qemu_chr_open_stdio(QemuOpts *opts)
                                            display_type != DT_NOGRAPHIC);
     qemu_chr_set_echo(chr, false);
 
-    return chr;
+    *_chr = chr;
+    return 0;
 }
 
 #ifdef __sun__
@@ -969,7 +980,7 @@ static void pty_chr_close(struct CharDriverState *chr)
     qemu_chr_event(chr, CHR_EVENT_CLOSED);
 }
 
-static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
+static int qemu_chr_open_pty(QemuOpts *opts, CharDriverState **_chr)
 {
     CharDriverState *chr;
     PtyCharDriver *s;
@@ -987,7 +998,7 @@ static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
     s = qemu_mallocz(sizeof(PtyCharDriver));
 
     if (openpty(&s->fd, &slave_fd, pty_name, NULL, NULL) < 0) {
-        return NULL;
+        return -errno;
     }
 
     /* Set raw attributes on the pty. */
@@ -1009,7 +1020,8 @@ static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
 
     s->timer = qemu_new_timer_ms(rt_clock, pty_chr_timer, chr);
 
-    return chr;
+    *_chr = chr;
+    return 0;
 }
 
 static void tty_serial_init(int fd, int speed,
@@ -1210,30 +1222,28 @@ static void qemu_chr_close_tty(CharDriverState *chr)
     }
 }
 
-static CharDriverState *qemu_chr_open_tty(QemuOpts *opts)
+static int qemu_chr_open_tty(QemuOpts *opts, CharDriverState **_chr)
 {
     const char *filename = qemu_opt_get(opts, "path");
     CharDriverState *chr;
     int fd;
 
-    TFR(fd = open(filename, O_RDWR | O_NONBLOCK));
+    TFR(fd = qemu_open(filename, O_RDWR | O_NONBLOCK));
     if (fd < 0) {
-        return NULL;
+        return -errno;
     }
     tty_serial_init(fd, 115200, 'N', 8, 1);
     chr = qemu_chr_open_fd(fd, fd);
-    if (!chr) {
-        close(fd);
-        return NULL;
-    }
     chr->chr_ioctl = tty_serial_ioctl;
     chr->chr_close = qemu_chr_close_tty;
-    return chr;
+
+    *_chr = chr;
+    return 0;
 }
 #else  /* ! __linux__ && ! __sun__ */
-static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
+static int qemu_chr_open_pty(QemuOpts *opts, CharDriverState **_chr)
 {
-    return NULL;
+    return -ENOTSUP;
 }
 #endif /* __linux__ || __sun__ */
 
@@ -1347,7 +1357,7 @@ static void pp_close(CharDriverState *chr)
     qemu_chr_event(chr, CHR_EVENT_CLOSED);
 }
 
-static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
+static int qemu_chr_open_pp(QemuOpts *opts, CharDriverState **_chr)
 {
     const char *filename = qemu_opt_get(opts, "path");
     CharDriverState *chr;
@@ -1355,12 +1365,13 @@ static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
     int fd;
 
     TFR(fd = open(filename, O_RDWR));
-    if (fd < 0)
-        return NULL;
+    if (fd < 0) {
+        return -errno;
+    }
 
     if (ioctl(fd, PPCLAIM) < 0) {
         close(fd);
-        return NULL;
+        return -errno;
     }
 
     drv = qemu_mallocz(sizeof(ParallelCharDriver));
@@ -1375,7 +1386,8 @@ static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
 
     qemu_chr_generic_open(chr);
 
-    return chr;
+    *_chr = chr;
+    return 0;
 }
 #endif /* __linux__ */
 
@@ -1417,21 +1429,24 @@ static int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
     return 0;
 }
 
-static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
+static int qemu_chr_open_pp(QemuOpts *opts, CharDriverState **_chr)
 {
     const char *filename = qemu_opt_get(opts, "path");
     CharDriverState *chr;
     int fd;
 
-    fd = open(filename, O_RDWR);
-    if (fd < 0)
-        return NULL;
+    fd = qemu_open(filename, O_RDWR);
+    if (fd < 0) {
+        return -errno;
+    }
 
     chr = qemu_mallocz(sizeof(CharDriverState));
     chr->opaque = (void *)(intptr_t)fd;
     chr->chr_write = null_chr_write;
     chr->chr_ioctl = pp_ioctl;
-    return chr;
+
+    *_chr = chr;
+    return 0;
 }
 #endif
 
@@ -1637,7 +1652,7 @@ static int win_chr_poll(void *opaque)
     return 0;
 }
 
-static CharDriverState *qemu_chr_open_win(QemuOpts *opts)
+static int qemu_chr_open_win(QemuOpts *opts, CharDriverState **_chr)
 {
     const char *filename = qemu_opt_get(opts, "path");
     CharDriverState *chr;
@@ -1652,10 +1667,12 @@ static CharDriverState *qemu_chr_open_win(QemuOpts *opts)
     if (win_chr_init(chr, filename) < 0) {
         free(s);
         free(chr);
-        return NULL;
+        return -EIO;
     }
     qemu_chr_generic_open(chr);
-    return chr;
+
+    *_chr = chr;
+    return 0;
 }
 
 static int win_chr_pipe_poll(void *opaque)
@@ -1737,7 +1754,7 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
 }
 
 
-static CharDriverState *qemu_chr_open_win_pipe(QemuOpts *opts)
+static int qemu_chr_open_win_pipe(QemuOpts *opts, CharDriverState **_chr)
 {
     const char *filename = qemu_opt_get(opts, "path");
     CharDriverState *chr;
@@ -1752,10 +1769,12 @@ static CharDriverState *qemu_chr_open_win_pipe(QemuOpts *opts)
     if (win_chr_pipe_init(chr, filename) < 0) {
         free(s);
         free(chr);
-        return NULL;
+        return -EIO;
     }
     qemu_chr_generic_open(chr);
-    return chr;
+
+    *_chr = chr;
+    return 0;
 }
 
 static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
@@ -1772,22 +1791,23 @@ static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
     return chr;
 }
 
-static CharDriverState *qemu_chr_open_win_con(QemuOpts *opts)
+static int qemu_chr_open_win_con(QemuOpts *opts, CharDriverState **_chr)
 {
-    return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE));
+    return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE), chr);
 }
 
-static CharDriverState *qemu_chr_open_win_file_out(QemuOpts *opts)
+static int qemu_chr_open_win_file_out(QemuOpts *opts, CharDriverState **_chr)
 {
     const char *file_out = qemu_opt_get(opts, "path");
     HANDLE fd_out;
 
     fd_out = CreateFile(file_out, GENERIC_WRITE, FILE_SHARE_READ, NULL,
                         OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
-    if (fd_out == INVALID_HANDLE_VALUE)
-        return NULL;
+    if (fd_out == INVALID_HANDLE_VALUE) {
+        return -EIO;
+    }
 
-    return qemu_chr_open_win_file(fd_out);
+    return qemu_chr_open_win_file(fd_out, _chr);
 }
 #endif /* !_WIN32 */
 
@@ -1868,11 +1888,12 @@ static void udp_chr_close(CharDriverState *chr)
     qemu_chr_event(chr, CHR_EVENT_CLOSED);
 }
 
-static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
+static int qemu_chr_open_udp(QemuOpts *opts, CharDriverState **_chr)
 {
     CharDriverState *chr = NULL;
     NetCharDriver *s = NULL;
     int fd = -1;
+    int ret;
 
     chr = qemu_mallocz(sizeof(CharDriverState));
     s = qemu_mallocz(sizeof(NetCharDriver));
@@ -1880,6 +1901,7 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
     fd = inet_dgram_opts(opts);
     if (fd < 0) {
         fprintf(stderr, "inet_dgram_opts failed\n");
+        ret = -errno;
         goto return_err;
     }
 
@@ -1890,16 +1912,17 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
     chr->chr_write = udp_chr_write;
     chr->chr_update_read_handler = udp_chr_update_read_handler;
     chr->chr_close = udp_chr_close;
-    return chr;
+
+    *_chr = chr;
+    return 0;
 
 return_err:
-    if (chr)
-        free(chr);
-    if (s)
-        free(s);
-    if (fd >= 0)
+    qemu_free(chr);
+    qemu_free(s);
+    if (fd >= 0) {
         closesocket(fd);
-    return NULL;
+    }
+    return ret;
 }
 
 /***********************************************************/
@@ -2178,7 +2201,7 @@ static void tcp_chr_close(CharDriverState *chr)
     qemu_chr_event(chr, CHR_EVENT_CLOSED);
 }
 
-static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
+static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
 {
     CharDriverState *chr = NULL;
     TCPCharDriver *s = NULL;
@@ -2188,6 +2211,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     int do_nodelay;
     int is_unix;
     int is_telnet;
+    int ret;
 
     is_listen      = qemu_opt_get_bool(opts, "server", 0);
     is_waitconnect = qemu_opt_get_bool(opts, "wait", 1);
@@ -2213,8 +2237,10 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
             fd = inet_connect_opts(opts);
         }
     }
-    if (fd < 0)
+    if (fd < 0) {
+        ret = -errno;
         goto fail;
+    }
 
     if (!is_waitconnect)
         socket_set_nonblock(fd);
@@ -2266,14 +2292,16 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
         tcp_chr_accept(chr);
         socket_set_nonblock(s->listen_fd);
     }
-    return chr;
+
+    *_chr = chr;
+    return 0;
 
  fail:
     if (fd >= 0)
         closesocket(fd);
     qemu_free(s);
     qemu_free(chr);
-    return NULL;
+    return ret;
 }
 
 /***********************************************************/
@@ -2466,7 +2494,7 @@ fail:
 
 static const struct {
     const char *name;
-    CharDriverState *(*open)(QemuOpts *opts);
+    int (*open)(QemuOpts *opts, CharDriverState **chr);
 } backend_table[] = {
     { .name = "null",      .open = qemu_chr_open_null },
     { .name = "socket",    .open = qemu_chr_open_socket },
@@ -2506,6 +2534,7 @@ CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
 {
     CharDriverState *chr;
     int i;
+    int ret;
 
     if (qemu_opts_id(opts) == NULL) {
         fprintf(stderr, "chardev: no id specified\n");
@@ -2527,10 +2556,10 @@ CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
         return NULL;
     }
 
-    chr = backend_table[i].open(opts);
-    if (!chr) {
-        fprintf(stderr, "chardev: opening backend \"%s\" failed\n",
-                qemu_opt_get(opts, "backend"));
+    ret = backend_table[i].open(opts, &chr);
+    if (ret < 0) {
+        fprintf(stderr, "chardev: opening backend \"%s\" failed: %s\n",
+                qemu_opt_get(opts, "backend"), strerror(-ret));
         return NULL;
     }
 
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index 605c241..95bf6b6 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -159,7 +159,7 @@ static void print_allowed_subtypes(void)
     fprintf(stderr, "\n");
 }
 
-CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
+int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr)
 {
     CharDriverState *chr;
     SpiceCharDriver *s;
@@ -171,7 +171,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
     if (name == NULL) {
         fprintf(stderr, "spice-qemu-char: missing name parameter\n");
         print_allowed_subtypes();
-        return NULL;
+        return -EINVAL;
     }
     for(;*psubtype != NULL; ++psubtype) {
         if (strcmp(name, *psubtype) == 0) {
@@ -182,7 +182,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
     if (subtype == NULL) {
         fprintf(stderr, "spice-qemu-char: unsupported name\n");
         print_allowed_subtypes();
-        return NULL;
+        return -EINVAL;
     }
 
     chr = qemu_mallocz(sizeof(CharDriverState));
@@ -199,5 +199,6 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
 
     qemu_chr_generic_open(chr);
 
-    return chr;
+    *_chr = chr;
+    return 0;
 }
diff --git a/ui/qemu-spice.h b/ui/qemu-spice.h
index 3c6f1fe..f34be69 100644
--- a/ui/qemu-spice.h
+++ b/ui/qemu-spice.h
@@ -42,7 +42,7 @@ int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
 void do_info_spice_print(Monitor *mon, const QObject *data);
 void do_info_spice(Monitor *mon, QObject **ret_data);
 
-CharDriverState *qemu_chr_open_spice(QemuOpts *opts);
+int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr);
 
 #else  /* CONFIG_SPICE */
 
commit 84682834eb8f654da5e03a92930d80b8ae0d3065
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Jun 9 13:10:25 2011 +0200

    qemu-timer: change unix timer to dynticks
    
    A timer that wakes up every millisecond puts a lot of stress on the
    iothread.  The large amount of IPIs causes very high context switch
    activity, making emulation slow and the UI unusable.  This is by the
    way the same reason why the Windows timers were switched to dynticks.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Tested-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index 72066c7..67c2974 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -218,6 +218,7 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t);
 
 static int unix_start_timer(struct qemu_alarm_timer *t);
 static void unix_stop_timer(struct qemu_alarm_timer *t);
+static void unix_rearm_timer(struct qemu_alarm_timer *t);
 
 #ifdef __linux__
 
@@ -290,7 +291,7 @@ static struct qemu_alarm_timer alarm_timers[] = {
     {"dynticks", dynticks_start_timer,
      dynticks_stop_timer, dynticks_rearm_timer},
 #endif
-    {"unix", unix_start_timer, unix_stop_timer, NULL},
+    {"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},
@@ -890,8 +891,6 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
 static int unix_start_timer(struct qemu_alarm_timer *t)
 {
     struct sigaction act;
-    struct itimerval itv;
-    int err;
 
     /* timer signal */
     sigfillset(&act.sa_mask);
@@ -899,18 +898,35 @@ static int unix_start_timer(struct qemu_alarm_timer *t)
     act.sa_handler = host_alarm_handler;
 
     sigaction(SIGALRM, &act, NULL);
+    return 0;
+}
 
-    itv.it_interval.tv_sec = 0;
-    /* for i386 kernel 2.6 to get 1 ms */
-    itv.it_interval.tv_usec = 999;
-    itv.it_value.tv_sec = 0;
-    itv.it_value.tv_usec = 10 * 1000;
+static void unix_rearm_timer(struct qemu_alarm_timer *t)
+{
+    struct itimerval itv;
+    int64_t nearest_delta_ns = INT64_MAX;
+    int err;
 
-    err = setitimer(ITIMER_REAL, &itv, NULL);
-    if (err)
-        return -1;
+    assert(alarm_has_dynticks(t));
+    if (!active_timers[QEMU_CLOCK_REALTIME] &&
+        !active_timers[QEMU_CLOCK_VIRTUAL] &&
+        !active_timers[QEMU_CLOCK_HOST])
+        return;
 
-    return 0;
+    nearest_delta_ns = qemu_next_alarm_deadline();
+    if (nearest_delta_ns < MIN_TIMER_REARM_NS)
+        nearest_delta_ns = MIN_TIMER_REARM_NS;
+
+    itv.it_interval.tv_sec = 0;
+    itv.it_interval.tv_usec = 0; /* 0 for one-shot timer */
+    itv.it_value.tv_sec =  nearest_delta_ns / 1000000000;
+    itv.it_value.tv_usec = (nearest_delta_ns % 1000000000) / 1000;
+    err = setitimer(ITIMER_REAL, &itv, NULL);
+    if (err) {
+        perror("setitimer");
+        fprintf(stderr, "Internal timer error: aborting\n");
+        exit(1);
+    }
 }
 
 static void unix_stop_timer(struct qemu_alarm_timer *t)
commit 46daff13c854769bfa8c51e77719325ea0f47b1b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Jun 9 13:10:24 2011 +0200

    iothread: replace fair_mutex with a condition variable
    
    This conveys the intention better, and scales to more than >1
    threads contending the mutex with the iothread (as long as all
    of them have a "quiescent point" like the TCG thread has).
    
    Also, on Mac OS X the fair_mutex somehow didn't work as intended
    and deadlocked.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Tested-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/cpus.c b/cpus.c
index 3035314..6bf4e3f 100644
--- a/cpus.c
+++ b/cpus.c
@@ -636,7 +636,8 @@ void vm_stop(int reason)
 #else /* CONFIG_IOTHREAD */
 
 QemuMutex qemu_global_mutex;
-static QemuMutex qemu_fair_mutex;
+static QemuCond qemu_io_proceeded_cond;
+static bool iothread_requesting_mutex;
 
 static QemuThread io_thread;
 
@@ -672,7 +673,7 @@ int qemu_init_main_loop(void)
     qemu_cond_init(&qemu_system_cond);
     qemu_cond_init(&qemu_pause_cond);
     qemu_cond_init(&qemu_work_cond);
-    qemu_mutex_init(&qemu_fair_mutex);
+    qemu_cond_init(&qemu_io_proceeded_cond);
     qemu_mutex_init(&qemu_global_mutex);
     qemu_mutex_lock(&qemu_global_mutex);
 
@@ -755,17 +756,9 @@ static void qemu_tcg_wait_io_event(void)
         qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex);
     }
 
-    qemu_mutex_unlock(&qemu_global_mutex);
-
-    /*
-     * Users of qemu_global_mutex can be starved, having no chance
-     * to acquire it since this path will get to it first.
-     * So use another lock to provide fairness.
-     */
-    qemu_mutex_lock(&qemu_fair_mutex);
-    qemu_mutex_unlock(&qemu_fair_mutex);
-
-    qemu_mutex_lock(&qemu_global_mutex);
+    while (iothread_requesting_mutex) {
+        qemu_cond_wait(&qemu_io_proceeded_cond, &qemu_global_mutex);
+    }
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         qemu_wait_io_event_common(env);
@@ -908,12 +901,13 @@ void qemu_mutex_lock_iothread(void)
     if (kvm_enabled()) {
         qemu_mutex_lock(&qemu_global_mutex);
     } else {
-        qemu_mutex_lock(&qemu_fair_mutex);
+        iothread_requesting_mutex = true;
         if (qemu_mutex_trylock(&qemu_global_mutex)) {
             qemu_cpu_kick_thread(first_cpu);
             qemu_mutex_lock(&qemu_global_mutex);
         }
-        qemu_mutex_unlock(&qemu_fair_mutex);
+        iothread_requesting_mutex = false;
+        qemu_cond_broadcast(&qemu_io_proceeded_cond);
     }
 }
 
commit 49e40b6627ea92c246b3903d171c88480b782512
Author: Adam Lackorzynski <adam at os.inf.tu-dresden.de>
Date:   Wed Jul 6 10:03:57 2011 +0200

    multiboot: Support commas in module parameters
    
    Support commas in the parameter list of multiboot modules as well as for the
    kernel command line, by using double commas (via get_opt_value()).
    
    Signed-off-by: Adam Lackorzynski <adam at os.inf.tu-dresden.de>
    Reviewed-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/multiboot.c b/hw/multiboot.c
index 6e6cfb9..2426e84 100644
--- a/hw/multiboot.c
+++ b/hw/multiboot.c
@@ -97,11 +97,11 @@ typedef struct {
 
 static uint32_t mb_add_cmdline(MultibootState *s, const char *cmdline)
 {
-    int len = strlen(cmdline) + 1;
     target_phys_addr_t p = s->offset_cmdlines;
+    char *b = (char *)s->mb_buf + p;
 
-    pstrcpy((char *)s->mb_buf + p, len, cmdline);
-    s->offset_cmdlines += len;
+    get_opt_value(b, strlen(cmdline) + 1, cmdline);
+    s->offset_cmdlines += strlen(b) + 1;
     return s->mb_buf_phys + p;
 }
 
@@ -238,7 +238,7 @@ int load_multiboot(void *fw_cfg,
         const char *r = initrd_filename;
         mbs.mb_buf_size += strlen(r) + 1;
         mbs.mb_mods_avail = 1;
-        while ((r = strchr(r, ','))) {
+        while (*(r = get_opt_value(NULL, 0, r))) {
            mbs.mb_mods_avail++;
            r++;
         }
@@ -252,7 +252,7 @@ int load_multiboot(void *fw_cfg,
     mbs.offset_cmdlines = mbs.offset_mbinfo + mbs.mb_mods_avail * MB_MOD_SIZE;
 
     if (initrd_filename) {
-        char *next_initrd;
+        char *next_initrd, not_last;
 
         mbs.offset_mods = mbs.mb_buf_size;
 
@@ -261,9 +261,9 @@ int load_multiboot(void *fw_cfg,
             int mb_mod_length;
             uint32_t offs = mbs.mb_buf_size;
 
-            next_initrd = strchr(initrd_filename, ',');
-            if (next_initrd)
-                *next_initrd = '\0';
+            next_initrd = (char *)get_opt_value(NULL, 0, initrd_filename);
+            not_last = *next_initrd;
+            *next_initrd = '\0';
             /* if a space comes after the module filename, treat everything
                after that as parameters */
             target_phys_addr_t c = mb_add_cmdline(&mbs, initrd_filename);
@@ -287,7 +287,7 @@ int load_multiboot(void *fw_cfg,
                      (char *)mbs.mb_buf + offs,
                      (char *)mbs.mb_buf + offs + mb_mod_length, c);
             initrd_filename = next_initrd+1;
-        } while (next_initrd);
+        } while (not_last);
     }
 
     /* Commandline support */
commit 6141dbfe0a595076310f690ec8db84ad5be2cde5
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Jul 15 17:10:15 2011 +0200

    report serial devices created with -device in the PIIX4 config space
    
    Serial and parallel devices created with -device are not reported in
    the PIIX4 configuration space, and are hence not picked up by the DSDT.
    This upsets Windows, which hides them altogether from the guest.
    
    To avoid this, check at the end of machine initialization whether the
    corresponding I/O ports have been registered.  The new function in
    ioport.c does this; this also requires a tweak to isa_unassign_ioport.
    
    I left the comment in piix4_pm_initfn since the registers I moved do
    seem to match the 82371AB datasheet.  There are some quirks though.
    We are setting this bit:
    
        "Device 8 EIO Enable (EIO_EN_DEV8)—R/W. 1=Enable PCI access to the
        device 8 enabled I/O ranges to be claimed by PIIX4 and forwarded
        to the ISA/EIO bus. 0=Disable. The LPT_MON_EN must be set to enable
        the decode."
    
    but not LPT_MON_EN (bit 18 at 50h):
    
        LPT Port Enable (LPT_MON_EN)—R/W. 1=Enable accesses to parallel
        port address range (LPT_DEC_SEL) to generate a device 8 (parallel
        port) decode event. 0=Disable.
    
    We're also setting the LPT_DEC_SEL field (that's the 0x60 written to
    63h) to 11, which means reserved, rather than to 01 (378h-37Fh).
    
    Likewise we're not setting SA_MON_EN, SB_MON_EN (respectively bit 14
    and bit 16 at address 50h) for the serial ports.  However, we're setting
    COMA_DEC_SEL and COMB_DEC_SEL correctly, unlike the corresponding register
    for the parallel port.
    
    All these fields are left as they are, since they are probably only
    meant to be used in the DSDT.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 350558b..03bd768 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -23,6 +23,7 @@
 #include "acpi.h"
 #include "sysemu.h"
 #include "range.h"
+#include "ioport.h"
 
 //#define DEBUG
 
@@ -63,6 +64,7 @@ typedef struct PIIX4PMState {
     qemu_irq irq;
     qemu_irq smi_irq;
     int kvm_enabled;
+    Notifier machine_ready;
 
     /* for pci hotplug */
     ACPIGPE gpe;
@@ -311,6 +313,19 @@ static void piix4_powerdown(void *opaque, int irq, int power_failing)
     acpi_pm1_evt_power_down(pm1a, tmr);
 }
 
+static void piix4_pm_machine_ready(struct Notifier* n)
+{
+    PIIX4PMState *s = container_of(n, PIIX4PMState, machine_ready);
+    uint8_t *pci_conf;
+
+    pci_conf = s->dev.config;
+    pci_conf[0x5f] = (isa_is_ioport_assigned(0x378) ? 0x80 : 0) | 0x10;
+    pci_conf[0x63] = 0x60;
+    pci_conf[0x67] = (isa_is_ioport_assigned(0x3f8) ? 0x08 : 0) |
+	(isa_is_ioport_assigned(0x2f8) ? 0x90 : 0);
+
+}
+
 static int piix4_pm_initfn(PCIDevice *dev)
 {
     PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev, dev);
@@ -337,11 +352,6 @@ static int piix4_pm_initfn(PCIDevice *dev)
 
     /* XXX: which specification is used ? The i82731AB has different
        mappings */
-    pci_conf[0x5f] = (parallel_hds[0] != NULL ? 0x80 : 0) | 0x10;
-    pci_conf[0x63] = 0x60;
-    pci_conf[0x67] = (serial_hds[0] != NULL ? 0x08 : 0) |
-	(serial_hds[1] != NULL ? 0x90 : 0);
-
     pci_conf[0x90] = s->smb_io_base | 1;
     pci_conf[0x91] = s->smb_io_base >> 8;
     pci_conf[0xd2] = 0x09;
@@ -354,6 +364,8 @@ static int piix4_pm_initfn(PCIDevice *dev)
     qemu_system_powerdown = *qemu_allocate_irqs(piix4_powerdown, s, 1);
 
     pm_smbus_init(&s->dev.qdev, &s->smb);
+    s->machine_ready.notify = piix4_pm_machine_ready;
+    qemu_add_machine_init_done_notifier(&s->machine_ready);
     qemu_register_reset(piix4_reset, s);
     piix4_acpi_system_hot_add_init(dev->bus, s);
 
diff --git a/ioport.c b/ioport.c
index 2e971fa..0d2611d 100644
--- a/ioport.c
+++ b/ioport.c
@@ -245,18 +245,25 @@ void isa_unassign_ioport(pio_addr_t start, int length)
     int i;
 
     for(i = start; i < start + length; i++) {
-        ioport_read_table[0][i] = default_ioport_readb;
-        ioport_read_table[1][i] = default_ioport_readw;
-        ioport_read_table[2][i] = default_ioport_readl;
+        ioport_read_table[0][i] = NULL;
+        ioport_read_table[1][i] = NULL;
+        ioport_read_table[2][i] = NULL;
 
-        ioport_write_table[0][i] = default_ioport_writeb;
-        ioport_write_table[1][i] = default_ioport_writew;
-        ioport_write_table[2][i] = default_ioport_writel;
+        ioport_write_table[0][i] = NULL;
+        ioport_write_table[1][i] = NULL;
+        ioport_write_table[2][i] = NULL;
 
         ioport_opaque[i] = NULL;
     }
 }
 
+bool isa_is_ioport_assigned(pio_addr_t start)
+{
+    return (ioport_read_table[0][start] || ioport_write_table[0][start] ||
+	    ioport_read_table[1][start] || ioport_write_table[1][start] ||
+	    ioport_read_table[2][start] || ioport_write_table[2][start]);
+}
+
 /***********************************************************/
 
 void cpu_outb(pio_addr_t addr, uint8_t val)
diff --git a/ioport.h b/ioport.h
index 5ae62a3..82ffd9d 100644
--- a/ioport.h
+++ b/ioport.h
@@ -43,7 +43,7 @@ int register_ioport_read(pio_addr_t start, int length, int size,
 int register_ioport_write(pio_addr_t start, int length, int size,
                           IOPortWriteFunc *func, void *opaque);
 void isa_unassign_ioport(pio_addr_t start, int length);
-
+bool isa_is_ioport_assigned(pio_addr_t start);
 
 void cpu_outb(pio_addr_t addr, uint8_t val);
 void cpu_outw(pio_addr_t addr, uint16_t val);
commit 5bda29da18eb5104718cad9810b625a0105cb0d2
Author: Alexandre Raymond <cerbere at gmail.com>
Date:   Sat Jul 23 01:41:57 2011 -0400

    .gitignore: ignore qemu-ga and qapi-generated
    
    Add a new binary and generation directory to the gitignore file
    
    Signed-off-by: Alexandre Raymond <cerbere at gmail.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/.gitignore b/.gitignore
index 08013fc..54835bc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,7 @@ libdis*
 libhw32
 libhw64
 libuser
+qapi-generated
 qemu-doc.html
 qemu-tech.html
 qemu-doc.info
@@ -32,6 +33,7 @@ qemu-options.texi
 qemu-img-cmds.texi
 qemu-img-cmds.h
 qemu-io
+qemu-ga
 qemu-monitor.texi
 QMP/qmp-commands.txt
 .gdbinit
commit 9af99f1daf8e9bf0fecddcde35273383ec02cd45
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Fri Jul 22 16:42:00 2011 -0500

    guest agent: use QERR_UNSUPPORTED for disabled RPCs
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qga/guest-agent-commands.c b/qga/guest-agent-commands.c
index e215bd3..624972e 100644
--- a/qga/guest-agent-commands.c
+++ b/qga/guest-agent-commands.c
@@ -521,7 +521,7 @@ static void guest_fsfreeze_cleanup(void)
  */
 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
 {
-    error_set(err, QERR_COMMAND_NOT_FOUND, "guest_fsfreeze_status");
+    error_set(err, QERR_UNSUPPORTED);
 
     return 0;
 }
@@ -532,7 +532,7 @@ GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
  */
 int64_t qmp_guest_fsfreeze_freeze(Error **err)
 {
-    error_set(err, QERR_COMMAND_NOT_FOUND, "guest_fsfreeze_freeze");
+    error_set(err, QERR_UNSUPPORTED);
 
     return 0;
 }
@@ -542,7 +542,7 @@ int64_t qmp_guest_fsfreeze_freeze(Error **err)
  */
 int64_t qmp_guest_fsfreeze_thaw(Error **err)
 {
-    error_set(err, QERR_COMMAND_NOT_FOUND, "guest_fsfreeze_thaw");
+    error_set(err, QERR_UNSUPPORTED);
 
     return 0;
 }
commit 6eed18568d985f5e091e96205f5ebf50fb823f4e
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Jul 20 12:20:22 2011 +0200

    net: Consistently use qemu_macaddr_default_if_unset
    
    Drop the open-coded MAC assignment from net_init_nic and replace it with
    standard qemu_macaddr_default_if_unset which is also used by qdev. That
    avoid creating colliding MACs when instantiating NICs via different
    mechanisms.
    
    This change requires to store the MAC as MACAddr in NICInfo, and the
    remaining nd_table users need to be updated.
    
    Based on suggestion by Peter Maydell.
    
    CC: Markus Armbruster <armbru at redhat.com>
    CC: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/dp8393x.c b/hw/dp8393x.c
index c332dd5..1bcd8ee 100644
--- a/hw/dp8393x.c
+++ b/hw/dp8393x.c
@@ -898,7 +898,7 @@ void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift,
     s->watchdog = qemu_new_timer_ns(vm_clock, dp8393x_watchdog, s);
     s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */
 
-    memcpy(s->conf.macaddr.a, nd->macaddr, sizeof(s->conf.macaddr));
+    s->conf.macaddr = nd->macaddr;
     s->conf.vlan = nd->vlan;
     s->conf.peer = nd->netdev;
 
diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c
index 6aa4007..dff5f55 100644
--- a/hw/etraxfs_eth.c
+++ b/hw/etraxfs_eth.c
@@ -602,7 +602,7 @@ void *etraxfs_eth_init(NICInfo *nd, target_phys_addr_t base, int phyaddr)
                                               DEVICE_NATIVE_ENDIAN);
 	cpu_register_physical_memory (base, 0x5c, eth->ethregs);
 
-	memcpy(eth->conf.macaddr.a, nd->macaddr, sizeof(nd->macaddr));
+	eth->conf.macaddr = nd->macaddr;
 	eth->conf.vlan = nd->vlan;
 	eth->conf.peer = nd->netdev;
 
diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c
index 21035da..5477e0e 100644
--- a/hw/mcf_fec.c
+++ b/hw/mcf_fec.c
@@ -471,7 +471,7 @@ void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq)
                                            DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x400, s->mmio_index);
 
-    memcpy(s->conf.macaddr.a, nd->macaddr, sizeof(nd->macaddr));
+    s->conf.macaddr = nd->macaddr;
     s->conf.vlan = nd->vlan;
     s->conf.peer = nd->netdev;
 
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index 26aad51..0db3ba7 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -258,7 +258,7 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
     s->irq = irq;
 
     if (nd) {
-        memcpy(s->conf.macaddr.a, nd->macaddr, sizeof(nd->macaddr));
+        s->conf.macaddr = nd->macaddr;
         s->conf.vlan = nd->vlan;
         s->conf.peer = nd->netdev;
 
diff --git a/hw/qdev.c b/hw/qdev.c
index 292b52f..a0fcd06 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -459,7 +459,7 @@ void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
 
 void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
 {
-    qdev_prop_set_macaddr(dev, "mac", nd->macaddr);
+    qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
     if (nd->vlan)
         qdev_prop_set_vlan(dev, "vlan", nd->vlan);
     if (nd->netdev)
diff --git a/hw/stellaris.c b/hw/stellaris.c
index ac9fcc1..b8a7ceb 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -1230,7 +1230,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
         }
     }
 
-    stellaris_sys_init(0x400fe000, pic[28], board, nd_table[0].macaddr);
+    stellaris_sys_init(0x400fe000, pic[28], board, nd_table[0].macaddr.a);
 
     for (i = 0; i < 7; i++) {
         if (board->dc4 & (1 << i)) {
diff --git a/hw/xen_devconfig.c b/hw/xen_devconfig.c
index 3a92155..6926c54 100644
--- a/hw/xen_devconfig.c
+++ b/hw/xen_devconfig.c
@@ -126,8 +126,8 @@ int xen_config_dev_nic(NICInfo *nic)
     char mac[20];
 
     snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x",
-	     nic->macaddr[0], nic->macaddr[1], nic->macaddr[2],
-	     nic->macaddr[3], nic->macaddr[4], nic->macaddr[5]);
+             nic->macaddr.a[0], nic->macaddr.a[1], nic->macaddr.a[2],
+             nic->macaddr.a[3], nic->macaddr.a[4], nic->macaddr.a[5]);
     xen_be_printf(NULL, 1, "config nic %d: mac=\"%s\"\n", nic->vlan->id, mac);
     xen_config_dev_dirs("vif", "qnic", nic->vlan->id, fe, be, sizeof(fe));
 
diff --git a/net.c b/net.c
index 12701af..31c2338 100644
--- a/net.c
+++ b/net.c
@@ -776,18 +776,12 @@ static int net_init_nic(QemuOpts *opts,
         nd->devaddr = qemu_strdup(qemu_opt_get(opts, "addr"));
     }
 
-    nd->macaddr[0] = 0x52;
-    nd->macaddr[1] = 0x54;
-    nd->macaddr[2] = 0x00;
-    nd->macaddr[3] = 0x12;
-    nd->macaddr[4] = 0x34;
-    nd->macaddr[5] = 0x56 + idx;
-
     if (qemu_opt_get(opts, "macaddr") &&
-        net_parse_macaddr(nd->macaddr, qemu_opt_get(opts, "macaddr")) < 0) {
+        net_parse_macaddr(nd->macaddr.a, qemu_opt_get(opts, "macaddr")) < 0) {
         error_report("invalid syntax for ethernet address");
         return -1;
     }
+    qemu_macaddr_default_if_unset(&nd->macaddr);
 
     nd->nvectors = qemu_opt_get_number(opts, "vectors",
                                        DEV_NVECTORS_UNSPECIFIED);
diff --git a/net.h b/net.h
index 4fdd942..5a7881c 100644
--- a/net.h
+++ b/net.h
@@ -129,7 +129,7 @@ int do_set_link(Monitor *mon, const QDict *qdict, QObject **ret_data);
 #define MAX_NICS 8
 
 struct NICInfo {
-    uint8_t macaddr[6];
+    MACAddr macaddr;
     char *model;
     char *name;
     char *devaddr;
commit 44e798d3959e6face1adc0b2fd1873b25f66a5e7
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Jul 20 12:20:21 2011 +0200

    net: Dump client type 'info network'
    
    Include the client type name into the output of 'info network'. The
    result looks like this:
    
    (qemu) info network
    VLAN 0 devices:
      rtl8139.0: type=nic,model=rtl8139,macaddr=52:54:00:12:34:57
    Devices not on any VLAN:
      virtio-net-pci.0: type=nic,model=virtio-net-pci,macaddr=52:54:00:12:34:56
       \ network1: type=tap,fd=5
    
    CC: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/net.c b/net.c
index 05fc685..12701af 100644
--- a/net.c
+++ b/net.c
@@ -1227,6 +1227,12 @@ int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return 0;
 }
 
+static void print_net_client(Monitor *mon, VLANClientState *vc)
+{
+    monitor_printf(mon, "%s: type=%s,%s\n", vc->name,
+                   net_client_types[vc->info->type].type, vc->info_str);
+}
+
 void do_info_network(Monitor *mon)
 {
     VLANState *vlan;
@@ -1237,7 +1243,8 @@ void do_info_network(Monitor *mon)
         monitor_printf(mon, "VLAN %d devices:\n", vlan->id);
 
         QTAILQ_FOREACH(vc, &vlan->clients, next) {
-            monitor_printf(mon, "  %s: %s\n", vc->name, vc->info_str);
+            monitor_printf(mon, "  ");
+            print_net_client(mon, vc);
         }
     }
     monitor_printf(mon, "Devices not on any VLAN:\n");
@@ -1245,10 +1252,12 @@ void do_info_network(Monitor *mon)
         peer = vc->peer;
         type = vc->info->type;
         if (!peer || type == NET_CLIENT_TYPE_NIC) {
-            monitor_printf(mon, "  %s: %s\n", vc->name, vc->info_str);
+            monitor_printf(mon, "  ");
+            print_net_client(mon, vc);
         } /* else it's a netdev connected to a NIC, printed with the NIC */
         if (peer && type == NET_CLIENT_TYPE_NIC) {
-            monitor_printf(mon, "   \\ %s: %s\n", peer->name, peer->info_str);
+            monitor_printf(mon, "   \\ ");
+            print_net_client(mon, peer);
         }
     }
 }
commit 6f7b3b1be229e3a686a4507d6c11dfcf5f12cef4
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Jul 20 12:20:20 2011 +0200

    net: Refactor net_client_types
    
    Position entries of net_client_types according to the corresponding
    values of NET_CLIENT_TYPE_*. The array size is now defined by
    NET_CLIENT_TYPE_MAX. This will allow to obtain entries based on type
    value in later patches.
    
    At this chance rename NET_CLIENT_TYPE_SLIRP to NET_CLIENT_TYPE_USER for
    the sake of consistency.
    
    CC: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/net.c b/net.c
index 43627ad..05fc685 100644
--- a/net.c
+++ b/net.c
@@ -830,14 +830,15 @@ static const struct {
     const char *type;
     net_client_init_func init;
     QemuOptDesc desc[NET_MAX_DESC];
-} net_client_types[] = {
-    {
+} net_client_types[NET_CLIENT_TYPE_MAX] = {
+    [NET_CLIENT_TYPE_NONE] = {
         .type = "none",
         .desc = {
             NET_COMMON_PARAMS_DESC,
             { /* end of list */ }
         },
-    }, {
+    },
+    [NET_CLIENT_TYPE_NIC] = {
         .type = "nic",
         .init = net_init_nic,
         .desc = {
@@ -866,8 +867,9 @@ static const struct {
             },
             { /* end of list */ }
         },
+    },
 #ifdef CONFIG_SLIRP
-    }, {
+    [NET_CLIENT_TYPE_USER] = {
         .type = "user",
         .init = net_init_slirp,
         .desc = {
@@ -927,8 +929,9 @@ static const struct {
             },
             { /* end of list */ }
         },
+    },
 #endif
-    }, {
+    [NET_CLIENT_TYPE_TAP] = {
         .type = "tap",
         .init = net_init_tap,
         .desc = {
@@ -975,7 +978,8 @@ static const struct {
 #endif /* _WIN32 */
             { /* end of list */ }
         },
-    }, {
+    },
+    [NET_CLIENT_TYPE_SOCKET] = {
         .type = "socket",
         .init = net_init_socket,
         .desc = {
@@ -1003,8 +1007,9 @@ static const struct {
             },
             { /* end of list */ }
         },
+    },
 #ifdef CONFIG_VDE
-    }, {
+    [NET_CLIENT_TYPE_VDE] = {
         .type = "vde",
         .init = net_init_vde,
         .desc = {
@@ -1028,8 +1033,9 @@ static const struct {
             },
             { /* end of list */ }
         },
+    },
 #endif
-    }, {
+    [NET_CLIENT_TYPE_DUMP] = {
         .type = "dump",
         .init = net_init_dump,
         .desc = {
@@ -1046,7 +1052,6 @@ static const struct {
             { /* end of list */ }
         },
     },
-    { /* end of list */ }
 };
 
 int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
@@ -1094,8 +1099,9 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
         name = qemu_opt_get(opts, "name");
     }
 
-    for (i = 0; net_client_types[i].type != NULL; i++) {
-        if (!strcmp(net_client_types[i].type, type)) {
+    for (i = 0; i < NET_CLIENT_TYPE_MAX; i++) {
+        if (net_client_types[i].type != NULL &&
+            !strcmp(net_client_types[i].type, type)) {
             VLANState *vlan = NULL;
             int ret;
 
@@ -1330,7 +1336,7 @@ void net_check_clients(void)
             case NET_CLIENT_TYPE_NIC:
                 has_nic = 1;
                 break;
-            case NET_CLIENT_TYPE_SLIRP:
+            case NET_CLIENT_TYPE_USER:
             case NET_CLIENT_TYPE_TAP:
             case NET_CLIENT_TYPE_SOCKET:
             case NET_CLIENT_TYPE_VDE:
diff --git a/net.h b/net.h
index 5b883a9..4fdd942 100644
--- a/net.h
+++ b/net.h
@@ -31,11 +31,13 @@ typedef struct NICConf {
 typedef enum {
     NET_CLIENT_TYPE_NONE,
     NET_CLIENT_TYPE_NIC,
-    NET_CLIENT_TYPE_SLIRP,
+    NET_CLIENT_TYPE_USER,
     NET_CLIENT_TYPE_TAP,
     NET_CLIENT_TYPE_SOCKET,
     NET_CLIENT_TYPE_VDE,
-    NET_CLIENT_TYPE_DUMP
+    NET_CLIENT_TYPE_DUMP,
+
+    NET_CLIENT_TYPE_MAX
 } net_client_type;
 
 typedef void (NetPoll)(VLANClientState *, bool enable);
diff --git a/net/slirp.c b/net/slirp.c
index 71e2577..157b80a 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -128,7 +128,7 @@ static void net_slirp_cleanup(VLANClientState *nc)
 }
 
 static NetClientInfo net_slirp_info = {
-    .type = NET_CLIENT_TYPE_SLIRP,
+    .type = NET_CLIENT_TYPE_USER,
     .size = sizeof(SlirpState),
     .receive = net_slirp_receive,
     .cleanup = net_slirp_cleanup,
commit 19061e63c04810cb24769e9d92d943079206297a
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Jul 20 12:20:19 2011 +0200

    net: Improve layout of 'info network'
    
    Improve the layout when listing non-vlan clients via 'info network'. The
    result looks like this:
    
    (qemu) info network
    Devices not on any VLAN:
      orphan: net=10.0.2.0, restricted=n
      virtio-net-pci.0: model=virtio-net-pci,macaddr=52:54:00:12:34:56
       \ network2: fd=5
      e1000.0: model=e1000,macaddr=52:54:00:12:34:57
       \ network1: net=10.0.2.0, restricted=n
      rtl8139.0: model=rtl8139,macaddr=52:54:00:12:34:58
    
    ie. peers are grouped, orphans are listed as before.
    
    CC: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/net.c b/net.c
index 66123ad..43627ad 100644
--- a/net.c
+++ b/net.c
@@ -1224,7 +1224,8 @@ int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 void do_info_network(Monitor *mon)
 {
     VLANState *vlan;
-    VLANClientState *vc;
+    VLANClientState *vc, *peer;
+    net_client_type type;
 
     QTAILQ_FOREACH(vlan, &vlans, next) {
         monitor_printf(mon, "VLAN %d devices:\n", vlan->id);
@@ -1235,11 +1236,14 @@ void do_info_network(Monitor *mon)
     }
     monitor_printf(mon, "Devices not on any VLAN:\n");
     QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
-        monitor_printf(mon, "  %s: %s", vc->name, vc->info_str);
-        if (vc->peer) {
-            monitor_printf(mon, " peer=%s", vc->peer->name);
+        peer = vc->peer;
+        type = vc->info->type;
+        if (!peer || type == NET_CLIENT_TYPE_NIC) {
+            monitor_printf(mon, "  %s: %s\n", vc->name, vc->info_str);
+        } /* else it's a netdev connected to a NIC, printed with the NIC */
+        if (peer && type == NET_CLIENT_TYPE_NIC) {
+            monitor_printf(mon, "   \\ %s: %s\n", peer->name, peer->info_str);
         }
-        monitor_printf(mon, "\n");
     }
 }
 
commit e6d43cfb1f937898dc031c7b38a23e5ccad8bd9a
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Jul 20 12:20:18 2011 +0200

    slirp: Forward ICMP echo requests via unprivileged sockets
    
    Linux 3.0 gained support for unprivileged ICMP ping sockets. Use this
    feature to forward guest pings to the outer world. The host admin has to
    set the ping_group_range in order to grant access to those sockets. To
    allow ping for the users group (GID 100):
    
    echo 100 100 > /proc/sys/net/ipv4/ping_group_range
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c
index 4f10826..14a5312 100644
--- a/slirp/ip_icmp.c
+++ b/slirp/ip_icmp.c
@@ -60,6 +60,52 @@ static const int icmp_flush[19] = {
 /* ADDR MASK REPLY (18) */ 0
 };
 
+void icmp_init(Slirp *slirp)
+{
+    slirp->icmp.so_next = slirp->icmp.so_prev = &slirp->icmp;
+    slirp->icmp_last_so = &slirp->icmp;
+}
+
+static int icmp_send(struct socket *so, struct mbuf *m, int hlen)
+{
+    struct ip *ip = mtod(m, struct ip *);
+    struct sockaddr_in addr;
+
+    so->s = qemu_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
+    if (so->s == -1) {
+        return -1;
+    }
+
+    so->so_m = m;
+    so->so_faddr = ip->ip_dst;
+    so->so_laddr = ip->ip_src;
+    so->so_iptos = ip->ip_tos;
+    so->so_type = IPPROTO_ICMP;
+    so->so_state = SS_ISFCONNECTED;
+    so->so_expire = curtime + SO_EXPIRE;
+
+    addr.sin_family = AF_INET;
+    addr.sin_addr = so->so_faddr;
+
+    insque(so, &so->slirp->icmp);
+
+    if (sendto(so->s, m->m_data + hlen, m->m_len - hlen, 0,
+               (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+        DEBUG_MISC((dfd, "icmp_input icmp sendto tx errno = %d-%s\n",
+                    errno, strerror(errno)));
+        icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno));
+        icmp_detach(so);
+    }
+
+    return 0;
+}
+
+void icmp_detach(struct socket *so)
+{
+    closesocket(so->s);
+    sofree(so);
+}
+
 /*
  * Process a received ICMP message.
  */
@@ -97,7 +143,6 @@ icmp_input(struct mbuf *m, int hlen)
   DEBUG_ARG("icmp_type = %d", icp->icmp_type);
   switch (icp->icmp_type) {
   case ICMP_ECHO:
-    icp->icmp_type = ICMP_ECHOREPLY;
     ip->ip_len += hlen;	             /* since ip_input subtracts this */
     if (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) {
       icmp_reflect(m);
@@ -107,6 +152,9 @@ icmp_input(struct mbuf *m, int hlen)
       struct socket *so;
       struct sockaddr_in addr;
       if ((so = socreate(slirp)) == NULL) goto freeit;
+      if (icmp_send(so, m, hlen) == 0) {
+        return;
+      }
       if(udp_attach(so) == -1) {
 	DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n",
 		    errno,strerror(errno)));
@@ -321,6 +369,7 @@ icmp_reflect(struct mbuf *m)
   m->m_len -= hlen;
   icp = mtod(m, struct icmp *);
 
+  icp->icmp_type = ICMP_ECHOREPLY;
   icp->icmp_cksum = 0;
   icp->icmp_cksum = cksum(m, ip->ip_len - hlen);
 
@@ -351,3 +400,39 @@ icmp_reflect(struct mbuf *m)
 
   (void ) ip_output((struct socket *)NULL, m);
 }
+
+void icmp_receive(struct socket *so)
+{
+    struct mbuf *m = so->so_m;
+    struct ip *ip = mtod(m, struct ip *);
+    int hlen = ip->ip_hl << 2;
+    u_char error_code;
+    struct icmp *icp;
+    int id, len;
+
+    m->m_data += hlen;
+    m->m_len -= hlen;
+    icp = mtod(m, struct icmp *);
+
+    id = icp->icmp_id;
+    len = recv(so->s, icp, m->m_len, 0);
+    icp->icmp_id = id;
+
+    m->m_data -= hlen;
+    m->m_len += hlen;
+
+    if (len == -1 || len == 0) {
+        if (errno == ENETUNREACH) {
+            error_code = ICMP_UNREACH_NET;
+        } else {
+            error_code = ICMP_UNREACH_HOST;
+        }
+        DEBUG_MISC((dfd, " udp icmp rx errno = %d-%s\n", errno,
+                    strerror(errno)));
+        icmp_error(so->so_m, ICMP_UNREACH, error_code, 0, strerror(errno));
+    } else {
+        icmp_reflect(so->so_m);
+        so->so_m = NULL; /* Don't m_free() it again! */
+    }
+    icmp_detach(so);
+}
diff --git a/slirp/ip_icmp.h b/slirp/ip_icmp.h
index 2692822..b3da1f2 100644
--- a/slirp/ip_icmp.h
+++ b/slirp/ip_icmp.h
@@ -153,9 +153,12 @@ struct icmp {
 	(type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
 	(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
 
+void icmp_init(Slirp *slirp);
 void icmp_input(struct mbuf *, int);
 void icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
                 const char *message);
 void icmp_reflect(struct mbuf *);
+void icmp_receive(struct socket *so);
+void icmp_detach(struct socket *so);
 
 #endif
diff --git a/slirp/ip_input.c b/slirp/ip_input.c
index 46c60b0..5e67631 100644
--- a/slirp/ip_input.c
+++ b/slirp/ip_input.c
@@ -58,6 +58,7 @@ ip_init(Slirp *slirp)
     slirp->ipq.ip_link.next = slirp->ipq.ip_link.prev = &slirp->ipq.ip_link;
     udp_init(slirp);
     tcp_init(slirp);
+    icmp_init(slirp);
 }
 
 /*
diff --git a/slirp/misc.c b/slirp/misc.c
index 34179e2..6002550 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -407,4 +407,17 @@ void slirp_connection_info(Slirp *slirp, Monitor *mon)
                        inet_ntoa(dst_addr), ntohs(dst_port),
                        so->so_rcv.sb_cc, so->so_snd.sb_cc);
     }
+
+    for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so->so_next) {
+        n = snprintf(buf, sizeof(buf), "  ICMP[%d sec]",
+                     (so->so_expire - curtime) / 1000);
+        src.sin_addr = so->so_laddr;
+        dst_addr = so->so_faddr;
+        memset(&buf[n], ' ', 19 - n);
+        buf[19] = 0;
+        monitor_printf(mon, "%s %3d %15s  -    ", buf, so->s,
+                       src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*");
+        monitor_printf(mon, "%15s  -    %5d %5d\n", inet_ntoa(dst_addr),
+                       so->so_rcv.sb_cc, so->so_snd.sb_cc);
+    }
 }
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 1593be1..faaa2f3 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -373,6 +373,31 @@ void slirp_select_fill(int *pnfds,
 				UPD_NFDS(so->s);
 			}
 		}
+
+                /*
+                 * ICMP sockets
+                 */
+                for (so = slirp->icmp.so_next; so != &slirp->icmp;
+                     so = so_next) {
+                    so_next = so->so_next;
+
+                    /*
+                     * See if it's timed out
+                     */
+                    if (so->so_expire) {
+                        if (so->so_expire <= curtime) {
+                            icmp_detach(so);
+                            continue;
+                        } else {
+                            do_slowtimo = 1; /* Let socket expire */
+                        }
+                    }
+
+                    if (so->so_state & SS_ISFCONNECTED) {
+                        FD_SET(so->s, readfds);
+                        UPD_NFDS(so->s);
+                    }
+                }
 	}
 
         *pnfds = nfds;
@@ -542,6 +567,18 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
                             sorecvfrom(so);
                         }
 		}
+
+                /*
+                 * Check incoming ICMP relies.
+                 */
+                for (so = slirp->icmp.so_next; so != &slirp->icmp;
+                     so = so_next) {
+                     so_next = so->so_next;
+
+                    if (so->s != -1 && FD_ISSET(so->s, readfds)) {
+                        icmp_receive(so);
+                    }
+                }
 	}
 
 	/*
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 954289a..16bb6ba 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -152,6 +152,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
 #include "tcp_var.h"
 #include "tcpip.h"
 #include "udp.h"
+#include "ip_icmp.h"
 #include "mbuf.h"
 #include "sbuf.h"
 #include "socket.h"
@@ -218,6 +219,10 @@ struct Slirp {
     struct socket udb;
     struct socket *udp_last_so;
 
+    /* icmp states */
+    struct socket icmp;
+    struct socket *icmp_last_so;
+
     /* tftp states */
     char *tftp_prefix;
     struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
diff --git a/slirp/socket.c b/slirp/socket.c
index 6119234..9b8ae13 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -71,6 +71,8 @@ sofree(struct socket *so)
       slirp->tcp_last_so = &slirp->tcb;
   } else if (so == slirp->udp_last_so) {
       slirp->udp_last_so = &slirp->udb;
+  } else if (so == slirp->icmp_last_so) {
+      slirp->icmp_last_so = &slirp->icmp;
   }
   m_free(so->so_m);
 
commit 565465fcae755fbdb11c2f65ec5f0ae62c78db3a
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Jul 20 12:20:17 2011 +0200

    slirp: Put forked exec into separate process group
    
    Recent smb daemons tend to terminate themselves via a process group
    SIGTERM. If the daemon is still in qemu's group by that time, qemu will
    die as well. Avoid this by always pushing fork_exec processes into a
    group of their own, not just (unused) type 2 execs.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/slirp/misc.c b/slirp/misc.c
index 08eba6a..34179e2 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -153,11 +153,12 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
 		return 0;
 
 	 case 0:
+                setsid();
+
 		/* Set the DISPLAY */
 		if (do_pty == 2) {
 			(void) close(master);
 #ifdef TIOCSCTTY /* XXXXX */
-			(void) setsid();
 			ioctl(s, TIOCSCTTY, (char *)NULL);
 #endif
 		} else {
commit 3acccfc67d3aa4611142e2171337c7c494b52efb
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Jul 20 12:20:16 2011 +0200

    slirp: Replace m_freem with m_free
    
    Remove this pointless wrapping.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c
index 0cd129c..4f10826 100644
--- a/slirp/ip_icmp.c
+++ b/slirp/ip_icmp.c
@@ -81,7 +81,7 @@ icmp_input(struct mbuf *m, int hlen)
    */
   if (icmplen < ICMP_MINLEN) {          /* min 8 bytes payload */
   freeit:
-    m_freem(m);
+    m_free(m);
     goto end_error;
   }
 
@@ -155,11 +155,11 @@ icmp_input(struct mbuf *m, int hlen)
   case ICMP_TSTAMP:
   case ICMP_MASKREQ:
   case ICMP_REDIRECT:
-    m_freem(m);
+    m_free(m);
     break;
 
   default:
-    m_freem(m);
+    m_free(m);
   } /* swith */
 
 end_error:
diff --git a/slirp/ip_input.c b/slirp/ip_input.c
index 2ff6adb..46c60b0 100644
--- a/slirp/ip_input.c
+++ b/slirp/ip_input.c
@@ -204,7 +204,7 @@ ip_input(struct mbuf *m)
 	}
 	return;
 bad:
-	m_freem(m);
+	m_free(m);
 	return;
 }
 
@@ -297,7 +297,7 @@ ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp)
 			break;
 		}
 		q = q->ipf_next;
-		m_freem(dtom(slirp, q->ipf_prev));
+		m_free(dtom(slirp, q->ipf_prev));
 		ip_deq(q->ipf_prev);
 	}
 
@@ -363,7 +363,7 @@ insert:
 	return ip;
 
 dropfrag:
-	m_freem(m);
+	m_free(m);
         return NULL;
 }
 
@@ -379,7 +379,7 @@ ip_freef(Slirp *slirp, struct ipq *fp)
 	for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link; q = p) {
 		p = q->ipf_next;
 		ip_deq(q);
-		m_freem(dtom(slirp, q));
+		m_free(dtom(slirp, q));
 	}
 	remque(&fp->ip_link);
 	(void) m_free(dtom(slirp, fp));
diff --git a/slirp/ip_output.c b/slirp/ip_output.c
index 542f318..c82830f 100644
--- a/slirp/ip_output.c
+++ b/slirp/ip_output.c
@@ -159,7 +159,7 @@ sendorfree:
 		if (error == 0)
 			if_output(so, m);
 		else
-			m_freem(m);
+			m_free(m);
 	}
     }
 
@@ -167,6 +167,6 @@ done:
 	return (error);
 
 bad:
-	m_freem(m0);
+	m_free(m0);
 	goto done;
 }
diff --git a/slirp/mbuf.h b/slirp/mbuf.h
index 97729e2..b74544b 100644
--- a/slirp/mbuf.h
+++ b/slirp/mbuf.h
@@ -33,9 +33,6 @@
 #ifndef _MBUF_H_
 #define _MBUF_H_
 
-#define m_freem m_free
-
-
 #define MINCSIZE 4096	/* Amount to increase mbuf if too small */
 
 /*
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index e4a7731..c1214c0 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -136,7 +136,7 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti,
 		i = q->ti_seq + q->ti_len - ti->ti_seq;
 		if (i > 0) {
 			if (i >= ti->ti_len) {
-				m_freem(m);
+				m_free(m);
 				/*
 				 * Try to present any queued data
 				 * at the left window edge to the user.
@@ -170,7 +170,7 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti,
 		q = tcpiphdr_next(q);
 		m = tcpiphdr_prev(q)->ti_mbuf;
 		remque(tcpiphdr2qlink(tcpiphdr_prev(q)));
-		m_freem(m);
+		m_free(m);
 	}
 
 	/*
@@ -197,7 +197,7 @@ present:
 		m = ti->ti_mbuf;
 		ti = tcpiphdr_next(ti);
 		if (so->so_state & SS_FCANTSENDMORE)
-			m_freem(m);
+			m_free(m);
 		else {
 			if (so->so_emu) {
 				if (tcp_emu(so,m)) sbappend(so, m);
@@ -451,7 +451,7 @@ findso:
 				acked = ti->ti_ack - tp->snd_una;
 				sbdrop(&so->so_snd, acked);
 				tp->snd_una = ti->ti_ack;
-				m_freem(m);
+				m_free(m);
 
 				/*
 				 * If all outstanding data are acked, stop
@@ -1260,7 +1260,7 @@ dropafterack:
 	 */
 	if (tiflags & TH_RST)
 		goto drop;
-	m_freem(m);
+	m_free(m);
 	tp->t_flags |= TF_ACKNOW;
 	(void) tcp_output(tp);
 	return;
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index b661d26..61079b1 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -250,7 +250,7 @@ tcp_close(struct tcpcb *tp)
 		t = tcpiphdr_next(t);
 		m = tcpiphdr_prev(t)->ti_mbuf;
 		remque(tcpiphdr2qlink(tcpiphdr_prev(t)));
-		m_freem(m);
+		m_free(m);
 	}
 	free(tp);
         so->so_tcpcb = NULL;
diff --git a/slirp/udp.c b/slirp/udp.c
index cefd50b..5b060f3 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -222,7 +222,7 @@ udp_input(register struct mbuf *m, int iphlen)
 
 	return;
 bad:
-	m_freem(m);
+	m_free(m);
 	return;
 }
 
commit 5a82362ad0bf06bba3377d63ca0ecd05fb74f322
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Jul 20 12:20:15 2011 +0200

    slirp: Strictly associate DHCP/BOOTP and TFTP with virtual host
    
    Instead of accepting every DHCP/BOOTP and TFTP packet, only invoke the
    built-in servers if the target is the virtual host.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/slirp/udp.c b/slirp/udp.c
index f1a9a10..cefd50b 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -120,15 +120,18 @@ udp_input(register struct mbuf *m, int iphlen)
         /*
          *  handle DHCP/BOOTP
          */
-        if (ntohs(uh->uh_dport) == BOOTP_SERVER) {
-            bootp_input(m);
-            goto bad;
-        }
+        if (ntohs(uh->uh_dport) == BOOTP_SERVER &&
+            (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr ||
+             ip->ip_dst.s_addr == 0xffffffff)) {
+                bootp_input(m);
+                goto bad;
+            }
 
         /*
          *  handle TFTP
          */
-        if (ntohs(uh->uh_dport) == TFTP_SERVER) {
+        if (ntohs(uh->uh_dport) == TFTP_SERVER &&
+            ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) {
             tftp_input(m);
             goto bad;
         }
commit c54ed5bcdd8ed29f9cdfcfc0e456b6ec1f25d2c3
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Jul 20 12:20:14 2011 +0200

    slirp: Canonicalize restrict syntax
    
    All other boolean arguments accept on|off - except for slirp's restrict.
    Fix that while still accepting the formerly allowed yes|y|no|n, but
    reject everything else. This avoids accidentally allowing external
    connections because syntax errors were so far interpreted as
    'restrict=no'.
    
    CC: Gleb Natapov <gleb at redhat.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/net/slirp.c b/net/slirp.c
index e057a14..71e2577 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -240,7 +240,8 @@ static int net_slirp_init(VLANState *vlan, const char *model,
     nc = qemu_new_net_client(&net_slirp_info, vlan, NULL, model, name);
 
     snprintf(nc->info_str, sizeof(nc->info_str),
-             "net=%s, restricted=%c", inet_ntoa(net), restricted ? 'y' : 'n');
+             "net=%s,restrict=%s", inet_ntoa(net),
+             restricted ? "on" : "off");
 
     s = DO_UPCAST(SlirpState, nc, nc);
 
@@ -689,6 +690,7 @@ int net_init_slirp(QemuOpts *opts,
     const char *bootfile;
     const char *smb_export;
     const char *vsmbsrv;
+    const char *restrict_opt;
     char *vnet = NULL;
     int restricted = 0;
     int ret;
@@ -702,6 +704,18 @@ int net_init_slirp(QemuOpts *opts,
     smb_export  = qemu_opt_get(opts, "smb");
     vsmbsrv     = qemu_opt_get(opts, "smbserver");
 
+    restrict_opt = qemu_opt_get(opts, "restrict");
+    if (restrict_opt) {
+        if (!strcmp(restrict_opt, "on") ||
+            !strcmp(restrict_opt, "yes") || !strcmp(restrict_opt, "y")) {
+            restricted = 1;
+        } else if (strcmp(restrict_opt, "off") &&
+            strcmp(restrict_opt, "no") && strcmp(restrict_opt, "n")) {
+            error_report("invalid option: 'restrict=%s'", restrict_opt);
+            return -1;
+        }
+    }
+
     if (qemu_opt_get(opts, "ip")) {
         const char *ip = qemu_opt_get(opts, "ip");
         int l = strlen(ip) + strlen("/24") + 1;
@@ -720,11 +734,6 @@ int net_init_slirp(QemuOpts *opts,
         vnet = qemu_strdup(qemu_opt_get(opts, "net"));
     }
 
-    if (qemu_opt_get(opts, "restrict") &&
-        qemu_opt_get(opts, "restrict")[0] == 'y') {
-        restricted = 1;
-    }
-
     qemu_opt_foreach(opts, net_init_slirp_configs, NULL, 0);
 
     ret = net_slirp_init(vlan, "user", name, restricted, vnet, vhost,
diff --git a/qemu-options.hx b/qemu-options.hx
index 1233f83..1d57f64 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1115,7 +1115,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
     "-net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
     "                create a new Network Interface Card and connect it to VLAN 'n'\n"
 #ifdef CONFIG_SLIRP
-    "-net user[,vlan=n][,name=str][,net=addr[/mask]][,host=addr][,restrict=y|n]\n"
+    "-net user[,vlan=n][,name=str][,net=addr[/mask]][,host=addr][,restrict=on|off]\n"
     "         [,hostname=host][,dhcpstart=addr][,dns=addr][,tftp=dir][,bootfile=f]\n"
     "         [,hostfwd=rule][,guestfwd=rule]"
 #ifndef _WIN32
@@ -1208,7 +1208,7 @@ either in the form a.b.c.d or as number of valid top-most bits. Default is
 Specify the guest-visible address of the host. Default is the 2nd IP in the
 guest network, i.e. x.x.x.2.
 
- at item restrict=y|yes|n|no
+ at item restrict=on|off
 If this option is enabled, the guest will be isolated, i.e. it will not be
 able to contact the host and no guest IP packets will be routed over the host
 to the outside. This option does not affect any explicitly set forwarding rules.
commit 12b513d837c9da5277390ddaf98ca0058339977a
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Jul 20 12:20:13 2011 +0200

    slirp: Fix restricted mode
    
    This aligns the code to what the documentation claims: Allow everything
    but requests that would have to be routed outside of the virtual LAN.
    
    So we need to drop the unneeded IP-level filter, allow TFTP requests,
    and add the missing protocol-level filter to ICMP.
    
    CC: Gleb Natapov <gleb at redhat.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c
index 751a8e2..0cd129c 100644
--- a/slirp/ip_icmp.c
+++ b/slirp/ip_icmp.c
@@ -101,6 +101,8 @@ icmp_input(struct mbuf *m, int hlen)
     ip->ip_len += hlen;	             /* since ip_input subtracts this */
     if (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) {
       icmp_reflect(m);
+    } else if (slirp->restricted) {
+        goto freeit;
     } else {
       struct socket *so;
       struct sockaddr_in addr;
diff --git a/slirp/ip_input.c b/slirp/ip_input.c
index 768ab0c..2ff6adb 100644
--- a/slirp/ip_input.c
+++ b/slirp/ip_input.c
@@ -118,27 +118,6 @@ ip_input(struct mbuf *m)
 		goto bad;
 	}
 
-    if (slirp->restricted) {
-        if ((ip->ip_dst.s_addr & slirp->vnetwork_mask.s_addr) ==
-            slirp->vnetwork_addr.s_addr) {
-            if (ip->ip_dst.s_addr == 0xffffffff && ip->ip_p != IPPROTO_UDP)
-                goto bad;
-        } else {
-            uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr;
-            struct ex_list *ex_ptr;
-
-            if ((ip->ip_dst.s_addr & inv_mask) == inv_mask) {
-                goto bad;
-            }
-            for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
-                if (ex_ptr->ex_addr.s_addr == ip->ip_dst.s_addr)
-                    break;
-
-            if (!ex_ptr)
-                goto bad;
-        }
-    }
-
 	/* Should drop packet if mbuf too long? hmmm... */
 	if (m->m_len > ip->ip_len)
 	   m_adj(m, ip->ip_len - m->m_len);
diff --git a/slirp/udp.c b/slirp/udp.c
index 02b3793..f1a9a10 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -125,10 +125,6 @@ udp_input(register struct mbuf *m, int iphlen)
             goto bad;
         }
 
-        if (slirp->restricted) {
-            goto bad;
-        }
-
         /*
          *  handle TFTP
          */
@@ -137,6 +133,10 @@ udp_input(register struct mbuf *m, int iphlen)
             goto bad;
         }
 
+        if (slirp->restricted) {
+            goto bad;
+        }
+
 	/*
 	 * Locate pcb for datagram.
 	 */
commit 80f52a6694423da7a40e2ec39e14a5817184c7ef
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sat Jul 23 12:39:46 2011 +0200

    Deprecate -M command line options
    
    Superseded by -machine. Therefore, this patch removes -M from the help
    list and pushes -machine at the same place in the output.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index 195943b..1233f83 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -27,14 +27,29 @@ STEXI
 Display version information and exit
 ETEXI
 
-DEF("M", HAS_ARG, QEMU_OPTION_M,
-    "-M machine      select emulated machine (-M ? for list)\n", QEMU_ARCH_ALL)
+DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
+    "-machine [type=]name[,prop[=value][,...]]\n"
+    "                selects emulated machine (-machine ? for list)\n"
+    "                property accel=accel1[:accel2[:...]] selects accelerator\n"
+    "                supported accelerators are kvm, xen, tcg (default: tcg)\n",
+    QEMU_ARCH_ALL)
 STEXI
- at item -M @var{machine}
- at findex -M
-Select the emulated @var{machine} (@code{-M ?} for list)
+ at item -machine [type=]@var{name}[,prop=@var{value}[,...]]
+ at findex -machine
+Select the emulated machine by @var{name}. Use @code{-machine ?} to list
+available machines. Supported machine properties are:
+ at table @option
+ at item accel=@var{accels1}[:@var{accels2}[:...]]
+This is used to enable an accelerator. Depending on the target architecture,
+kvm, xen, or tcg can be available. By default, tcg is used. If there is more
+than one accelerator specified, the next one is used if the previous one fails
+to initialize.
+ at end table
 ETEXI
 
+HXCOMM Deprecated by -machine
+DEF("M", HAS_ARG, QEMU_OPTION_M, "", QEMU_ARCH_ALL)
+
 DEF("cpu", HAS_ARG, QEMU_OPTION_cpu,
     "-cpu cpu        select CPU (-cpu ? for list)\n", QEMU_ARCH_ALL)
 STEXI
@@ -2074,26 +2089,6 @@ Enable KVM full virtualization support. This option is only available
 if KVM support is enabled when compiling.
 ETEXI
 
-DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
-    "-machine [type=]name[,prop[=value][,...]]\n"
-    "                selects emulated machine (-machine ? for list)\n"
-    "                property accel=accel1[:accel2[:...]] selects accelerator\n"
-    "                supported accelerators are kvm, xen, tcg (default: tcg)\n",
-    QEMU_ARCH_ALL)
-STEXI
- at item -machine [type=]@var{name}[,prop=@var{value}[,...]]
- at findex -machine
-Select the emulated machine by @var{name}. Use @code{-machine ?} to list
-available machines. Supported machine properties are:
- at table @option
- at item accel=@var{accels1}[:@var{accels2}[:...]]
-This is used to enable an accelerator. Depending on the target architecture,
-kvm, xen, or tcg can be available. By default, tcg is used. If there is more
-than one accelerator specified, the next one is used if the previous one fails
-to initialize.
- at end table
-ETEXI
-
 DEF("xen-domid", HAS_ARG, QEMU_OPTION_xen_domid,
     "-xen-domid id   specify xen guest domain id\n", QEMU_ARCH_ALL)
 DEF("xen-create", 0, QEMU_OPTION_xen_create,
commit 9052ea6bf4962b1342aa56d4341bb55176ed9e45
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sat Jul 23 12:38:37 2011 +0200

    Generalize -machine command line option
    
    -machine somehow suggests that it selects the machine, but it doesn't.
    Fix that before this command is set in stone.
    
    Actually, -machine should supersede -M and allow to introduce arbitrary
    per-machine options to the command line. That will change the internal
    realization again, but we will be able to keep the user interface
    stable.
    
    Tested-by: Ian Campbell <ian.campbell at citrix.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-config.c b/qemu-config.c
index 93d20c6..b2ec40b 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -464,9 +464,14 @@ QemuOptsList qemu_option_rom_opts = {
 
 static QemuOptsList qemu_machine_opts = {
     .name = "machine",
+    .implied_opt_name = "type",
     .head = QTAILQ_HEAD_INITIALIZER(qemu_machine_opts.head),
     .desc = {
         {
+            .name = "type",
+            .type = QEMU_OPT_STRING,
+            .help = "emulated machine"
+        }, {
             .name = "accel",
             .type = QEMU_OPT_STRING,
             .help = "accelerator list",
diff --git a/qemu-options.hx b/qemu-options.hx
index 64114dd..195943b 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2075,13 +2075,23 @@ if KVM support is enabled when compiling.
 ETEXI
 
 DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
-    "-machine accel=accel1[:accel2]    use an accelerator (kvm,xen,tcg), default is tcg\n", QEMU_ARCH_ALL)
+    "-machine [type=]name[,prop[=value][,...]]\n"
+    "                selects emulated machine (-machine ? for list)\n"
+    "                property accel=accel1[:accel2[:...]] selects accelerator\n"
+    "                supported accelerators are kvm, xen, tcg (default: tcg)\n",
+    QEMU_ARCH_ALL)
 STEXI
- at item -machine accel=@var{accels}
+ at item -machine [type=]@var{name}[,prop=@var{value}[,...]]
 @findex -machine
-This is use to enable an accelerator, in kvm,xen,tcg.
-By default, it use only tcg. If there a more than one accelerator
-specified, the next one is used if the first don't work.
+Select the emulated machine by @var{name}. Use @code{-machine ?} to list
+available machines. Supported machine properties are:
+ at table @option
+ at item accel=@var{accels1}[:@var{accels2}[:...]]
+This is used to enable an accelerator. Depending on the target architecture,
+kvm, xen, or tcg can be available. By default, tcg is used. If there is more
+than one accelerator specified, the next one is used if the previous one fails
+to initialize.
+ at end table
 ETEXI
 
 DEF("xen-domid", HAS_ARG, QEMU_OPTION_xen_domid,
diff --git a/vl.c b/vl.c
index fcd7395..acfff85 100644
--- a/vl.c
+++ b/vl.c
@@ -1899,6 +1899,27 @@ static int debugcon_parse(const char *devname)
     return 0;
 }
 
+static QEMUMachine *machine_parse(const char *name)
+{
+    QEMUMachine *m, *machine = NULL;
+
+    if (name) {
+        machine = find_machine(name);
+    }
+    if (machine) {
+        return machine;
+    }
+    printf("Supported machines are:\n");
+    for (m = first_machine; m != NULL; m = m->next) {
+        if (m->alias) {
+            printf("%-10s %s (alias of %s)\n", m->alias, m->desc, m->name);
+        }
+        printf("%-10s %s%s\n", m->name, m->desc,
+               m->is_default ? " (default)" : "");
+    }
+    exit(!name || *name != '?');
+}
+
 static int tcg_init(void)
 {
     return 0;
@@ -2155,20 +2176,7 @@ int main(int argc, char **argv, char **envp)
             }
             switch(popt->index) {
             case QEMU_OPTION_M:
-                machine = find_machine(optarg);
-                if (!machine) {
-                    QEMUMachine *m;
-                    printf("Supported machines are:\n");
-                    for(m = first_machine; m != NULL; m = m->next) {
-                        if (m->alias)
-                            printf("%-10s %s (alias of %s)\n",
-                                   m->alias, m->desc, m->name);
-                        printf("%-10s %s%s\n",
-                               m->name, m->desc,
-                               m->is_default ? " (default)" : "");
-                    }
-                    exit(*optarg != '?');
-                }
+                machine = machine_parse(optarg);
                 break;
             case QEMU_OPTION_cpu:
                 /* hw initialization will check this */
@@ -2698,11 +2706,12 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_machine:
                 olist = qemu_find_opts("machine");
                 qemu_opts_reset(olist);
-                opts = qemu_opts_parse(olist, optarg, 0);
+                opts = qemu_opts_parse(olist, optarg, 1);
                 if (!opts) {
                     fprintf(stderr, "parse error: %s\n", optarg);
                     exit(1);
                 }
+                machine = machine_parse(qemu_opt_get(opts, "type"));
                 break;
             case QEMU_OPTION_usb:
                 usb_enabled = 1;
@@ -2976,8 +2985,8 @@ int main(int argc, char **argv, char **envp)
             p = qemu_opt_get(QTAILQ_FIRST(&list->head), "accel");
         }
         if (p == NULL) {
-            opts = qemu_opts_parse(qemu_find_opts("machine"),
-                                   machine->default_machine_opts, 0);
+            qemu_opts_reset(list);
+            opts = qemu_opts_parse(list, machine->default_machine_opts, 0);
             if (!opts) {
                 fprintf(stderr, "parse error for machine %s: %s\n",
                         machine->name, machine->default_machine_opts);
commit 7006b9cff356233c3db0150ec55fd999c49dfae3
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jul 22 14:14:17 2011 -0500

    guest-agent: fix build with OpenBSD
    
    FS-Freeze only works with Linux.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qga/guest-agent-commands.c b/qga/guest-agent-commands.c
index 8c0d67e..e215bd3 100644
--- a/qga/guest-agent-commands.c
+++ b/qga/guest-agent-commands.c
@@ -10,11 +10,17 @@
  * See the COPYING file in the top-level directory.
  */
 
+#if defined(__linux__)
+#define CONFIG_FSFREEZE
+#endif
+
 #include <glib.h>
+#if defined(CONFIG_FSFREEZE)
 #include <mntent.h>
+#include <linux/fs.h>
+#endif
 #include <sys/types.h>
 #include <sys/ioctl.h>
-#include <linux/fs.h>
 #include "qga/guest-agent-core.h"
 #include "qga-qmp-commands.h"
 #include "qerror.h"
@@ -22,16 +28,6 @@
 
 static GAState *ga_state;
 
-static void disable_logging(void)
-{
-    ga_disable_logging(ga_state);
-}
-
-static void enable_logging(void)
-{
-    ga_enable_logging(ga_state);
-}
-
 /* Note: in some situations, like with the fsfreeze, logging may be
  * temporarilly disabled. if it is necessary that a command be able
  * to log for accounting purposes, check ga_logging_enabled() beforehand,
@@ -323,6 +319,17 @@ static void guest_file_init(void)
     QTAILQ_INIT(&guest_file_state.filehandles);
 }
 
+#if defined(CONFIG_FSFREEZE)
+static void disable_logging(void)
+{
+    ga_disable_logging(ga_state);
+}
+
+static void enable_logging(void)
+{
+    ga_enable_logging(ga_state);
+}
+
 typedef struct GuestFsfreezeMount {
     char *dirname;
     char *devtype;
@@ -508,11 +515,45 @@ static void guest_fsfreeze_cleanup(void)
         }
     }
 }
+#else
+/*
+ * Return status of freeze/thaw
+ */
+GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
+{
+    error_set(err, QERR_COMMAND_NOT_FOUND, "guest_fsfreeze_status");
+
+    return 0;
+}
+
+/*
+ * Walk list of mounted file systems in the guest, and freeze the ones which
+ * are real local file systems.
+ */
+int64_t qmp_guest_fsfreeze_freeze(Error **err)
+{
+    error_set(err, QERR_COMMAND_NOT_FOUND, "guest_fsfreeze_freeze");
+
+    return 0;
+}
+
+/*
+ * Walk list of frozen file systems in the guest, and thaw them.
+ */
+int64_t qmp_guest_fsfreeze_thaw(Error **err)
+{
+    error_set(err, QERR_COMMAND_NOT_FOUND, "guest_fsfreeze_thaw");
+
+    return 0;
+}
+#endif
 
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
     ga_state = s;
+#if defined(CONFIG_FSFREEZE)
     ga_command_state_add(cs, guest_fsfreeze_init, guest_fsfreeze_cleanup);
+#endif
     ga_command_state_add(cs, guest_file_init, NULL);
 }
commit fd2a9d2fc719d53caeb37c28440a0e9d34c1b563
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Jul 20 12:14:06 2011 +0300

    xen: fix xen-mapcache build on non-Xen capable targets
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/xen-mapcache.h b/xen-mapcache.h
index 606b8af..da874ca 100644
--- a/xen-mapcache.h
+++ b/xen-mapcache.h
@@ -9,6 +9,10 @@
 #ifndef XEN_MAPCACHE_H
 #define XEN_MAPCACHE_H
 
+#include <stdlib.h>
+
+#ifdef CONFIG_XEN
+
 void xen_map_cache_init(void);
 uint8_t *xen_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size,
                        uint8_t lock);
@@ -16,4 +20,32 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr);
 void xen_invalidate_map_cache_entry(uint8_t *buffer);
 void xen_invalidate_map_cache(void);
 
+#else
+
+static inline void xen_map_cache_init(void)
+{
+}
+
+static inline uint8_t *xen_map_cache(target_phys_addr_t phys_addr,
+                                     target_phys_addr_t size,
+                                     uint8_t lock)
+{
+    abort();
+}
+
+static inline ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
+{
+    abort();
+}
+
+static inline void xen_invalidate_map_cache_entry(uint8_t *buffer)
+{
+}
+
+static inline void xen_invalidate_map_cache(void)
+{
+}
+
+#endif
+
 #endif /* !XEN_MAPCACHE_H */
commit bb5df884db32114a4a0129c9927793ebcf7c089a
Merge: e07fc40... 3b8b030...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jul 22 11:07:08 2011 -0500

    Merge remote-tracking branch 'origin/master' into staging

commit 3b8b030a280f3b496602dc7d2ee5c68e480ec10b
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Fri Jul 22 07:44:27 2011 +0200

    target-sparc: Fix compiler errors (format strings)
    
    This change is needed because commit 06e12b65
    now uses an unsigned long long value
    (uint64_t && unsigned long long => unsigned long long).
    
    Cc: Tsuneo Saito <tsnsaito at gmail.com>
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index acc07f5..efab885 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -700,7 +700,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
                 break;
             }
             if (TTE_IS_VALID(env->dtlb[i].tte)) {
-                (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
+                (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %llx"
                                ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
                                i,
                                env->dtlb[i].tag & (uint64_t)~0x1fffULL,
@@ -737,7 +737,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
                 break;
             }
             if (TTE_IS_VALID(env->itlb[i].tte)) {
-                (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
+                (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %llx"
                                ", %s, %s, %s, ctx %" PRId64 " %s\n",
                                i,
                                env->itlb[i].tag & (uint64_t)~0x1fffULL,
commit 2b56cb87e46fbfc5dca31ed13ffc9a5422e1e405
Author: Christophe Fergeau <cfergeau at redhat.com>
Date:   Fri Jul 22 13:42:20 2011 +0200

    libcacard: replace copy_string with strndup
    
    copy_string reimplements strndup, this commit removes it and
    replaces all copy_string uses with strndup.
    
    Signed-off-by: Christophe Fergeau <cfergeau at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>

diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index 1a24acf..84fc490 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -1055,17 +1055,6 @@ vcard_emul_replay_insertion_events(void)
 /*
  *  Silly little functions to help parsing our argument string
  */
-static char *
-copy_string(const char *str, int str_len)
-{
-    char *new_str;
-
-    new_str = qemu_malloc(str_len+1);
-    memcpy(new_str, str, str_len);
-    new_str[str_len] = 0;
-    return new_str;
-}
-
 static int
 count_tokens(const char *str, char token, char token_end)
 {
@@ -1184,18 +1173,18 @@ vcard_emul_options(const char *args)
             }
             opts->vreader = vreaderOpt;
             vreaderOpt = &vreaderOpt[opts->vreader_count];
-            vreaderOpt->name = copy_string(name, name_length);
-            vreaderOpt->vname = copy_string(vname, vname_length);
+            vreaderOpt->name = qemu_strndup(name, name_length);
+            vreaderOpt->vname = qemu_strndup(vname, vname_length);
             vreaderOpt->card_type = type;
             vreaderOpt->type_params =
-                copy_string(type_params, type_params_length);
+                qemu_strndup(type_params, type_params_length);
             count = count_tokens(args, ',', ')') + 1;
             vreaderOpt->cert_count = count;
             vreaderOpt->cert_name = (char **)qemu_malloc(count*sizeof(char *));
             for (i = 0; i < count; i++) {
                 const char *cert = args;
                 args = strpbrk(args, ",)");
-                vreaderOpt->cert_name[i] = copy_string(cert, args - cert);
+                vreaderOpt->cert_name[i] = qemu_strndup(cert, args - cert);
                 args = strip(args+1);
             }
             if (*args == ')') {
@@ -1222,7 +1211,7 @@ vcard_emul_options(const char *args)
             args = strip(args+10);
             params = args;
             args = find_blank(args);
-            opts->hw_type_params = copy_string(params, args-params);
+            opts->hw_type_params = qemu_strndup(params, args-params);
         /* db="/data/base/path" */
         } else if (strncmp(args, "db=", 3) == 0) {
             const char *db;
@@ -1233,7 +1222,7 @@ vcard_emul_options(const char *args)
             args++;
             db = args;
             args = strpbrk(args, "\"\n");
-            opts->nss_db = copy_string(db, args-db);
+            opts->nss_db = qemu_strndup(db, args-db);
             if (*args != 0) {
                 args++;
             }
commit d246b3cfd5378e45895b0834a8b8762733c0148f
Author: Christophe Fergeau <cfergeau at redhat.com>
Date:   Fri Jul 22 13:42:19 2011 +0200

    libcacard: introduce NEXT_TOKEN macro
    
    vcard_emul_options now has repetitive code to read the current
    token and advance to the next. After the previous changes,
    this repetitive code can be moved in a NEXT_TOKEN macro to
    avoid having this code duplicated.
    
    Signed-off-by: Christophe Fergeau <cfergeau at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>

diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index 3360f6c..1a24acf 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -1105,6 +1105,26 @@ find_blank(const char *str)
 static VCardEmulOptions options;
 #define READER_STEP 4
 
+/* Expects "args" to be at the beginning of a token (ie right after the ','
+ * ending the previous token), and puts the next token start in "token",
+ * and its length in "token_length". "token" will not be nul-terminated.
+ * After calling the macro, "args" will be advanced to the beginning of
+ * the next token.
+ * This macro may call continue or break.
+ */
+#define NEXT_TOKEN(token) \
+            (token) = args; \
+            args = strpbrk(args, ",)"); \
+            if (*args == 0) { \
+                break; \
+            } \
+            if (*args == ')') { \
+                args++; \
+                continue; \
+            } \
+            (token##_length) = args - (token); \
+            args = strip(args+1);
+
 VCardEmulOptions *
 vcard_emul_options(const char *args)
 {
@@ -1140,58 +1160,15 @@ vcard_emul_options(const char *args)
             }
             args = strip(args+1);
 
-            name = args;
-            args = strpbrk(args, ",)");
-            if (*args == 0) {
-                break;
-            }
-            if (*args == ')') {
-                args++;
-                continue;
-            }
-            name_length = args - name;
-            args = strip(args+1);
-
-            vname = args;
-            args = strpbrk(args, ",)");
-            if (*args == 0) {
-                break;
-            }
-            if (*args == ')') {
-                args++;
-                continue;
-            }
-            vname_length = args - vname;
-            args = strip(args+1);
-
-            type_params = args;
-            args = strpbrk(args, ",)");
-            if (*args == 0) {
-                break;
-            }
-            if (*args == ')') {
-                args++;
-                continue;
-            }
-            type_params_length = args - type_params;
-            args = strip(args+1);
-
+            NEXT_TOKEN(name)
+            NEXT_TOKEN(vname)
+            NEXT_TOKEN(type_params)
             type_params_length = MIN(type_params_length, sizeof(type_str)-1);
             strncpy(type_str, type_params, type_params_length);
             type_str[type_params_length] = 0;
             type = vcard_emul_type_from_string(type_str);
 
-            type_params = args;
-            args = strpbrk(args, ",)");
-            if (*args == 0) {
-                break;
-            }
-            if (*args == ')') {
-                args++;
-                continue;
-            }
-            type_params_length = args - type_params;
-            args = strip(args+1);
+            NEXT_TOKEN(type_params)
 
             if (*args == 0) {
                 break;
commit a5aa842a0597ef9a24e80966b02ca01f287fb334
Author: Christophe Fergeau <cfergeau at redhat.com>
Date:   Fri Jul 22 13:42:18 2011 +0200

    libcacard: fix soft=... parsing in vcard_emul_options
    
    The previous parser had copy and paste errors when computing
    vname_length and type_params_length, "name" was used instead
    of respectively vname and type_params. This led to length that could
    be bigger than the input string, and to access out of the array
    bounds when trying to copy these strings. valgrind rightfully
    complained about this. It also didn't handle empty fields correctly,
    
    Signed-off-by: Christophe Fergeau <cfergeau at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>

diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index 8c59eff..3360f6c 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -1110,8 +1110,6 @@ vcard_emul_options(const char *args)
 {
     int reader_count = 0;
     VCardEmulOptions *opts;
-    char type_str[100];
-    int type_len;
 
     /* Allow the future use of allocating the options structure on the fly */
     memcpy(&options, &default_options, sizeof(options));
@@ -1126,18 +1124,24 @@ vcard_emul_options(const char *args)
          *       cert_2,cert_3...) */
         if (strncmp(args, "soft=", 5) == 0) {
             const char *name;
+            size_t name_length;
             const char *vname;
+            size_t vname_length;
             const char *type_params;
+            size_t type_params_length;
+            char type_str[100];
             VCardEmulType type;
-            int name_length, vname_length, type_params_length, count, i;
+            int count, i;
             VirtualReaderOptions *vreaderOpt = NULL;
 
             args = strip(args + 5);
             if (*args != '(') {
                 continue;
             }
+            args = strip(args+1);
+
             name = args;
-            args = strpbrk(args + 1, ",)");
+            args = strpbrk(args, ",)");
             if (*args == 0) {
                 break;
             }
@@ -1145,10 +1149,11 @@ vcard_emul_options(const char *args)
                 args++;
                 continue;
             }
+            name_length = args - name;
             args = strip(args+1);
-            name_length = args - name - 2;
+
             vname = args;
-            args = strpbrk(args + 1, ",)");
+            args = strpbrk(args, ",)");
             if (*args == 0) {
                 break;
             }
@@ -1156,13 +1161,10 @@ vcard_emul_options(const char *args)
                 args++;
                 continue;
             }
-            vname_length = args - name - 2;
+            vname_length = args - vname;
             args = strip(args+1);
-            type_len = strpbrk(args, ",)") - args;
-            assert(sizeof(type_str) > type_len);
-            strncpy(type_str, args, type_len);
-            type_str[type_len] = 0;
-            type = vcard_emul_type_from_string(type_str);
+
+            type_params = args;
             args = strpbrk(args, ",)");
             if (*args == 0) {
                 break;
@@ -1171,9 +1173,16 @@ vcard_emul_options(const char *args)
                 args++;
                 continue;
             }
+            type_params_length = args - type_params;
             args = strip(args+1);
+
+            type_params_length = MIN(type_params_length, sizeof(type_str)-1);
+            strncpy(type_str, type_params, type_params_length);
+            type_str[type_params_length] = 0;
+            type = vcard_emul_type_from_string(type_str);
+
             type_params = args;
-            args = strpbrk(args + 1, ",)");
+            args = strpbrk(args, ",)");
             if (*args == 0) {
                 break;
             }
@@ -1181,8 +1190,9 @@ vcard_emul_options(const char *args)
                 args++;
                 continue;
             }
-            type_params_length = args - name;
+            type_params_length = args - type_params;
             args = strip(args+1);
+
             if (*args == 0) {
                 break;
             }
@@ -1202,13 +1212,14 @@ vcard_emul_options(const char *args)
             vreaderOpt->card_type = type;
             vreaderOpt->type_params =
                 copy_string(type_params, type_params_length);
-            count = count_tokens(args, ',', ')');
+            count = count_tokens(args, ',', ')') + 1;
             vreaderOpt->cert_count = count;
             vreaderOpt->cert_name = (char **)qemu_malloc(count*sizeof(char *));
             for (i = 0; i < count; i++) {
-                const char *cert = args + 1;
-                args = strpbrk(args + 1, ",)");
+                const char *cert = args;
+                args = strpbrk(args, ",)");
                 vreaderOpt->cert_name[i] = copy_string(cert, args - cert);
+                args = strip(args+1);
             }
             if (*args == ')') {
                 args++;
commit 009651675afc775fc77018273a47fb36c28a8100
Author: Christophe Fergeau <cfergeau at redhat.com>
Date:   Fri Jul 22 13:42:17 2011 +0200

    libcacard: s/strip(args++)/strip(args+1)
    
    vcard_emul_options used args = strip(args++) a few times, which
    was not returning the expected result since the rest of the code
    expected args to be increased by at least 1, which is not the case
    if *args is not a blank space when this function is called.
    Replace these calls by "strip(args+1)" which will do what we expect.
    
    Signed-off-by: Christophe Fergeau <cfergeau at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>

diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index f1763f5..8c59eff 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -1171,7 +1171,7 @@ vcard_emul_options(const char *args)
                 args++;
                 continue;
             }
-            args = strip(args++);
+            args = strip(args+1);
             type_params = args;
             args = strpbrk(args + 1, ",)");
             if (*args == 0) {
@@ -1182,7 +1182,7 @@ vcard_emul_options(const char *args)
                 continue;
             }
             type_params_length = args - name;
-            args = strip(args++);
+            args = strip(args+1);
             if (*args == 0) {
                 break;
             }
commit ee83d41466ab393d82d9abf57b9ec24d4e6633be
Author: Christophe Fergeau <cfergeau at redhat.com>
Date:   Mon Jul 4 18:10:43 2011 +0200

    libcacard: don't leak vcard_emul_alloc_arrays mem
    
    vcard_emul_mirror_card and vcard_emul_init use
    vcard_emul_alloc_arrays to allocate memory for temporary arrays
    which will contain elements that in the end will be used one by
    one in cac_card_init. The arrays themselves are never stored
    anywhere, they are only used as temporary containers. Hence
    the memory that was allocated for these arrays should be freed
    after use or they will be leaked.

diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index 0f50954..f1763f5 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -597,6 +597,7 @@ vcard_emul_mirror_card(VReader *vreader)
     VCardKey **keys;
     PK11SlotInfo *slot;
     PRBool ret;
+    VCard *card;
 
     slot = vcard_emul_reader_get_slot(vreader);
     if (slot == NULL) {
@@ -656,7 +657,12 @@ vcard_emul_mirror_card(VReader *vreader)
     }
 
     /* now create the card */
-    return vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count);
+    card = vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count);
+    qemu_free(certs);
+    qemu_free(cert_len);
+    qemu_free(keys);
+
+    return card;
 }
 
 static VCardEmulType default_card_type = VCARD_EMUL_NONE;
@@ -941,6 +947,9 @@ vcard_emul_init(const VCardEmulOptions *options)
             vreader_free(vreader);
             has_readers = PR_TRUE;
         }
+        qemu_free(certs);
+        qemu_free(cert_len);
+        qemu_free(keys);
     }
 
     /* if we aren't suppose to use hw, skip looking up hardware tokens */
commit 010debef6111c6776cda7ad8d00737f2d1dbb164
Author: Robert Relyea <rrelyea at redhat.com>
Date:   Tue Jun 28 17:28:22 2011 +0200

    libcacard/vcard_emul_nss: support cards lying about CKM_RSA_X_509 support
    
    Some tokens claim to do CKM_RSA_X_509, but then choke when they try to do the
    actual operations. Try to detect those cases and treat them as if the token
    didn't claim support for X_509.
    
    Signed-off-by: Robert Relyea <rrelyea at redhat.com>

diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index f3db657..0f50954 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -33,10 +33,17 @@
 #include "vreader.h"
 #include "vevent.h"
 
+typedef enum {
+    VCardEmulUnknown = -1,
+    VCardEmulFalse = 0,
+    VCardEmulTrue = 1
+} VCardEmulTriState;
+
 struct VCardKeyStruct {
     CERTCertificate *cert;
     PK11SlotInfo *slot;
     SECKEYPrivateKey *key;
+    VCardEmulTriState failedX509;
 };
 
 
@@ -140,6 +147,7 @@ vcard_emul_make_key(PK11SlotInfo *slot, CERTCertificate *cert)
     /* NOTE: the cert is a temp cert, not necessarily the cert in the token,
      * use the DER version of this function */
     key->key = PK11_FindKeyByDERCert(slot, cert, NULL);
+    key->failedX509 = VCardEmulUnknown;
     return key;
 }
 
@@ -208,13 +216,23 @@ vcard_emul_rsa_op(VCard *card, VCardKey *key,
 {
     SECKEYPrivateKey *priv_key;
     unsigned signature_len;
+    PK11SlotInfo *slot;
     SECStatus rv;
+    unsigned char buf[2048];
+    unsigned char *bp = NULL;
+    int pad_len;
+    vcard_7816_status_t ret = VCARD7816_STATUS_SUCCESS;
 
     if ((!nss_emul_init) || (key == NULL)) {
         /* couldn't get the key, indicate that we aren't logged in */
         return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
     }
     priv_key = vcard_emul_get_nss_key(key);
+    if (priv_key == NULL) {
+        /* couldn't get the key, indicate that we aren't logged in */
+        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
+    }
+    slot = vcard_emul_card_get_slot(card);
 
     /*
      * this is only true of the rsa signature
@@ -223,13 +241,116 @@ vcard_emul_rsa_op(VCard *card, VCardKey *key,
     if (buffer_size != signature_len) {
         return  VCARD7816_STATUS_ERROR_DATA_INVALID;
     }
-    rv = PK11_PrivDecryptRaw(priv_key, buffer, &signature_len, signature_len,
-                             buffer, buffer_size);
-    if (rv != SECSuccess) {
-        return vcard_emul_map_error(PORT_GetError());
+    /* be able to handle larger keys if necessariy */
+    bp = &buf[0];
+    if (sizeof(buf) < signature_len) {
+        bp = qemu_malloc(signature_len);
     }
-    assert(buffer_size == signature_len);
-    return VCARD7816_STATUS_SUCCESS;
+
+    /*
+     * do the raw operations. Some tokens claim to do CKM_RSA_X_509, but then
+     * choke when they try to do the actual operations. Try to detect
+     * those cases and treat them as if the token didn't claim support for
+     * X_509.
+     */
+    if (key->failedX509 != VCardEmulTrue
+                              && PK11_DoesMechanism(slot, CKM_RSA_X_509)) {
+        rv = PK11_PrivDecryptRaw(priv_key, bp, &signature_len, signature_len,
+                                 buffer, buffer_size);
+        if (rv == SECSuccess) {
+            assert(buffer_size == signature_len);
+            memcpy(buffer, bp, signature_len);
+            key->failedX509 = VCardEmulFalse;
+            goto cleanup;
+        }
+        /*
+         * we've had a successful X509 operation, this failure must be
+         * somethine else
+         */
+        if (key->failedX509 == VCardEmulFalse) {
+            ret = vcard_emul_map_error(PORT_GetError());
+            goto cleanup;
+        }
+        /*
+         * key->failedX509 must be Unknown at this point, try the
+         * non-x_509 case
+         */
+    }
+    /* token does not support CKM_RSA_X509, emulate that with CKM_RSA_PKCS */
+    /* is this a PKCS #1 formatted signature? */
+    if ((buffer[0] == 0) && (buffer[1] == 1)) {
+        int i;
+
+        for (i = 2; i < buffer_size; i++) {
+            /* rsa signature pad */
+            if (buffer[i] != 0xff) {
+                break;
+            }
+        }
+        if ((i < buffer_size) && (buffer[i] == 0)) {
+            /* yes, we have a properly formated PKCS #1 signature */
+            /*
+             * NOTE: even if we accidentally got an encrypt buffer, which
+             * through shear luck started with 00, 01, ff, 00, it won't matter
+             * because the resulting Sign operation will effectively decrypt
+             * the real buffer.
+             */
+            SECItem signature;
+            SECItem hash;
+
+            i++;
+            hash.data = &buffer[i];
+            hash.len = buffer_size - i;
+            signature.data = bp;
+            signature.len = signature_len;
+            rv = PK11_Sign(priv_key,  &signature, &hash);
+            if (rv != SECSuccess) {
+                ret = vcard_emul_map_error(PORT_GetError());
+                goto cleanup;
+            }
+            assert(buffer_size == signature.len);
+            memcpy(buffer, bp, signature.len);
+            /*
+             * we got here because either the X509 attempt failed, or the
+             * token couldn't do the X509 operation, in either case stay
+             * with the PKCS version for future operations on this key
+             */
+            key->failedX509 = VCardEmulTrue;
+            goto cleanup;
+        }
+    }
+    pad_len = buffer_size - signature_len;
+    assert(pad_len < 4);
+    /*
+     * OK now we've decrypted the payload, package it up in PKCS #1 for the
+     * upper layer.
+     */
+    buffer[0] = 0;
+    buffer[1] = 2; /* RSA_encrypt  */
+    pad_len -= 3; /* format is 0 || 2 || pad || 0 || data */
+    /*
+     * padding for PKCS #1 encrypted data is a string of random bytes. The
+     * random butes protect against potential decryption attacks against RSA.
+     * Since PrivDecrypt has already stripped those bytes, we can't reconstruct
+     * them. This shouldn't matter to the upper level code which should just
+     * strip this code out anyway, so We'll pad with a constant 3.
+     */
+    memset(&buffer[2], 0x03, pad_len);
+    pad_len += 2; /* index to the end of the pad */
+    buffer[pad_len] = 0;
+    pad_len++; /* index to the start of the data */
+    memcpy(&buffer[pad_len], bp, signature_len);
+    /*
+     * we got here because either the X509 attempt failed, or the
+     * token couldn't do the X509 operation, in either case stay
+     * with the PKCS version for future operations on this key
+     */
+    key->failedX509 = VCardEmulTrue;
+cleanup:
+    if (bp != buf) {
+        qemu_free(bp);
+    }
+    return ret;
 }
 
 /*
commit e07fc405dc0432c712c9e36c70229f0428f86fa1
Merge: 4412953... 8927cfb...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jul 22 09:24:07 2011 -0500

    Merge remote-tracking branch 'spice/spice.v39' into staging

commit 44129530ddf9edcc95913a4c05c755fb732c2bfe
Merge: cfe7bb1... e3d4d25...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jul 22 09:23:53 2011 -0500

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

commit cfe7bb19d2e717c4ad763879515a8b8bd1ca19c5
Merge: bf1cd9b... 69354a8...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jul 22 09:23:49 2011 -0500

    Merge remote-tracking branch 'kraxel/usb.21' into staging

commit bf1cd9b4f54c8f630291dcd057c3aa293a510bcb
Merge: d1afc48... aaf55b4...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jul 22 09:23:43 2011 -0500

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

commit 69354a83346da2d4d8eb9cda18b639794566c902
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Jul 19 11:04:10 2011 +0200

    USB: add usb network redirection support
    
    This patch adds support for a usb-redir device, which takes a chardev
    as a communication channel to an actual usbdevice using the usbredir protocol.
    
    Compiling the usb-redir device requires usbredir-0.3 to be installed for
    the usbredir protocol parser, usbredir-0.3 also contains a server for
    redirecting usb traffic from an actual usb device. You can get the 0.3
    release of usbredir here:
    http://people.fedoraproject.org/~jwrdegoede/usbredir-0.3.tar.bz2
    (getting a more formal site for it is a WIP)
    
    Example usage:
    1) Start usbredirserver for a usb device:
    sudo usbredirserver 045e:0772
    2) Start qemu with usb2 support + a chardev talking to usbredirserver +
       a usb-redir device using this chardev:
    qemu ... \
      -readconfig docs/ich9-ehci-uhci.cfg \
      -chardev socket,id=usbredirchardev,host=localhost,port=4000 \
      -device usb-redir,chardev=usbredirchardev,id=usbredirdev
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index c43ed05..a82974b 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -205,6 +205,7 @@ hw-obj-$(CONFIG_HPET) += hpet.o
 hw-obj-$(CONFIG_APPLESMC) += applesmc.o
 hw-obj-$(CONFIG_SMARTCARD) += usb-ccid.o ccid-card-passthru.o
 hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
+hw-obj-$(CONFIG_USB_REDIR) += usb-redir.o
 
 # PPC devices
 hw-obj-$(CONFIG_OPENPIC) += openpic.o
diff --git a/configure b/configure
index e57efb1..3a76bb8 100755
--- a/configure
+++ b/configure
@@ -177,6 +177,7 @@ spice=""
 rbd=""
 smartcard=""
 smartcard_nss=""
+usb_redir=""
 opengl=""
 
 # parse CC options first
@@ -743,6 +744,10 @@ for opt do
   ;;
   --enable-smartcard-nss) smartcard_nss="yes"
   ;;
+  --disable-usb-redir) usb_redir="no"
+  ;;
+  --enable-usb-redir) usb_redir="yes"
+  ;;
   *) echo "ERROR: unknown option $opt"; show_help="yes"
   ;;
   esac
@@ -1018,6 +1023,8 @@ echo "  --disable-smartcard      disable smartcard support"
 echo "  --enable-smartcard       enable smartcard support"
 echo "  --disable-smartcard-nss  disable smartcard nss support"
 echo "  --enable-smartcard-nss   enable smartcard nss support"
+echo "  --disable-usb-redir      disable usb network redirection support"
+echo "  --enable-usb-redir       enable usb network redirection support"
 echo ""
 echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
@@ -2371,6 +2378,22 @@ if test "$smartcard" = "no" ; then
     smartcard_nss="no"
 fi
 
+# check for usbredirparser for usb network redirection support
+if test "$usb_redir" != "no" ; then
+    if $pkg_config libusbredirparser >/dev/null 2>&1 ; then
+        usb_redir="yes"
+        usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null)
+        usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null)
+        QEMU_CFLAGS="$QEMU_CFLAGS $usb_redir_cflags"
+        LIBS="$LIBS $usb_redir_libs"
+    else
+        if test "$usb_redir" = "yes"; then
+            feature_not_found "usb-redir"
+        fi
+        usb_redir="no"
+    fi
+fi
+
 ##########################################
 
 ##########################################
@@ -2617,6 +2640,7 @@ echo "spice support     $spice"
 echo "rbd support       $rbd"
 echo "xfsctl support    $xfs"
 echo "nss used          $smartcard_nss"
+echo "usb net redir     $usb_redir"
 echo "OpenGL support    $opengl"
 
 if test $sdl_too_old = "yes"; then
@@ -2910,6 +2934,10 @@ if test "$smartcard_nss" = "yes" ; then
   echo "CONFIG_SMARTCARD_NSS=y" >> $config_host_mak
 fi
 
+if test "$usb_redir" = "yes" ; then
+  echo "CONFIG_USB_REDIR=y" >> $config_host_mak
+fi
+
 if test "$opengl" = "yes" ; then
   echo "CONFIG_OPENGL=y" >> $config_host_mak
 fi
diff --git a/usb-redir.c b/usb-redir.c
new file mode 100644
index 0000000..e212993
--- /dev/null
+++ b/usb-redir.c
@@ -0,0 +1,1218 @@
+/*
+ * USB redirector usb-guest
+ *
+ * Copyright (c) 2011 Red Hat, Inc.
+ *
+ * Red Hat Authors:
+ * Hans de Goede <hdegoede at redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu-common.h"
+#include "qemu-timer.h"
+#include "monitor.h"
+#include "sysemu.h"
+
+#include <dirent.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <usbredirparser.h>
+
+#include "hw/usb.h"
+
+#define MAX_ENDPOINTS 32
+#define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f))
+#define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f))
+
+typedef struct AsyncURB AsyncURB;
+typedef struct USBRedirDevice USBRedirDevice;
+
+/* Struct to hold buffered packets (iso or int input packets) */
+struct buf_packet {
+    uint8_t *data;
+    int len;
+    int status;
+    QTAILQ_ENTRY(buf_packet)next;
+};
+
+struct endp_data {
+    uint8_t type;
+    uint8_t interval;
+    uint8_t interface; /* bInterfaceNumber this ep belongs to */
+    uint8_t iso_started;
+    uint8_t iso_error; /* For reporting iso errors to the HC */
+    uint8_t interrupt_started;
+    uint8_t interrupt_error;
+    QTAILQ_HEAD(, buf_packet) bufpq;
+};
+
+struct USBRedirDevice {
+    USBDevice dev;
+    /* Properties */
+    CharDriverState *cs;
+    uint8_t debug;
+    /* Data passed from chardev the fd_read cb to the usbredirparser read cb */
+    const uint8_t *read_buf;
+    int read_buf_size;
+    /* For async handling of open/close */
+    QEMUBH *open_close_bh;
+    /* To delay the usb attach in case of quick chardev close + open */
+    QEMUTimer *attach_timer;
+    int64_t next_attach_time;
+    struct usbredirparser *parser;
+    struct endp_data endpoint[MAX_ENDPOINTS];
+    uint32_t packet_id;
+    QTAILQ_HEAD(, AsyncURB) asyncq;
+};
+
+struct AsyncURB {
+    USBRedirDevice *dev;
+    USBPacket *packet;
+    uint32_t packet_id;
+    int get;
+    union {
+        struct usb_redir_control_packet_header control_packet;
+        struct usb_redir_bulk_packet_header bulk_packet;
+        struct usb_redir_interrupt_packet_header interrupt_packet;
+    };
+    QTAILQ_ENTRY(AsyncURB)next;
+};
+
+static void usbredir_device_connect(void *priv,
+    struct usb_redir_device_connect_header *device_connect);
+static void usbredir_device_disconnect(void *priv);
+static void usbredir_interface_info(void *priv,
+    struct usb_redir_interface_info_header *interface_info);
+static void usbredir_ep_info(void *priv,
+    struct usb_redir_ep_info_header *ep_info);
+static void usbredir_configuration_status(void *priv, uint32_t id,
+    struct usb_redir_configuration_status_header *configuration_status);
+static void usbredir_alt_setting_status(void *priv, uint32_t id,
+    struct usb_redir_alt_setting_status_header *alt_setting_status);
+static void usbredir_iso_stream_status(void *priv, uint32_t id,
+    struct usb_redir_iso_stream_status_header *iso_stream_status);
+static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
+    struct usb_redir_interrupt_receiving_status_header
+    *interrupt_receiving_status);
+static void usbredir_bulk_streams_status(void *priv, uint32_t id,
+    struct usb_redir_bulk_streams_status_header *bulk_streams_status);
+static void usbredir_control_packet(void *priv, uint32_t id,
+    struct usb_redir_control_packet_header *control_packet,
+    uint8_t *data, int data_len);
+static void usbredir_bulk_packet(void *priv, uint32_t id,
+    struct usb_redir_bulk_packet_header *bulk_packet,
+    uint8_t *data, int data_len);
+static void usbredir_iso_packet(void *priv, uint32_t id,
+    struct usb_redir_iso_packet_header *iso_packet,
+    uint8_t *data, int data_len);
+static void usbredir_interrupt_packet(void *priv, uint32_t id,
+    struct usb_redir_interrupt_packet_header *interrupt_header,
+    uint8_t *data, int data_len);
+
+static int usbredir_handle_status(USBRedirDevice *dev,
+                                       int status, int actual_len);
+
+#define VERSION "qemu usb-redir guest " QEMU_VERSION
+
+/*
+ * Logging stuff
+ */
+
+#define ERROR(...) \
+    do { \
+        if (dev->debug >= usbredirparser_error) { \
+            error_report("usb-redir error: " __VA_ARGS__); \
+        } \
+    } while (0)
+#define WARNING(...) \
+    do { \
+        if (dev->debug >= usbredirparser_warning) { \
+            error_report("usb-redir warning: " __VA_ARGS__); \
+        } \
+    } while (0)
+#define INFO(...) \
+    do { \
+        if (dev->debug >= usbredirparser_info) { \
+            error_report("usb-redir: " __VA_ARGS__); \
+        } \
+    } while (0)
+#define DPRINTF(...) \
+    do { \
+        if (dev->debug >= usbredirparser_debug) { \
+            error_report("usb-redir: " __VA_ARGS__); \
+        } \
+    } while (0)
+#define DPRINTF2(...) \
+    do { \
+        if (dev->debug >= usbredirparser_debug_data) { \
+            error_report("usb-redir: " __VA_ARGS__); \
+        } \
+    } while (0)
+
+static void usbredir_log(void *priv, int level, const char *msg)
+{
+    USBRedirDevice *dev = priv;
+
+    if (dev->debug < level) {
+        return;
+    }
+
+    error_report("%s\n", msg);
+}
+
+static void usbredir_log_data(USBRedirDevice *dev, const char *desc,
+    const uint8_t *data, int len)
+{
+    int i, j, n;
+
+    if (dev->debug < usbredirparser_debug_data) {
+        return;
+    }
+
+    for (i = 0; i < len; i += j) {
+        char buf[128];
+
+        n = sprintf(buf, "%s", desc);
+        for (j = 0; j < 8 && i + j < len; j++) {
+            n += sprintf(buf + n, " %02X", data[i + j]);
+        }
+        error_report("%s\n", buf);
+    }
+}
+
+/*
+ * usbredirparser io functions
+ */
+
+static int usbredir_read(void *priv, uint8_t *data, int count)
+{
+    USBRedirDevice *dev = priv;
+
+    if (dev->read_buf_size < count) {
+        count = dev->read_buf_size;
+    }
+
+    memcpy(data, dev->read_buf, count);
+
+    dev->read_buf_size -= count;
+    if (dev->read_buf_size) {
+        dev->read_buf += count;
+    } else {
+        dev->read_buf = NULL;
+    }
+
+    return count;
+}
+
+static int usbredir_write(void *priv, uint8_t *data, int count)
+{
+    USBRedirDevice *dev = priv;
+
+    return qemu_chr_write(dev->cs, data, count);
+}
+
+/*
+ * Async and buffered packets helpers
+ */
+
+static AsyncURB *async_alloc(USBRedirDevice *dev, USBPacket *p)
+{
+    AsyncURB *aurb = (AsyncURB *) qemu_mallocz(sizeof(AsyncURB));
+    aurb->dev = dev;
+    aurb->packet = p;
+    aurb->packet_id = dev->packet_id;
+    QTAILQ_INSERT_TAIL(&dev->asyncq, aurb, next);
+    dev->packet_id++;
+
+    return aurb;
+}
+
+static void async_free(USBRedirDevice *dev, AsyncURB *aurb)
+{
+    QTAILQ_REMOVE(&dev->asyncq, aurb, next);
+    qemu_free(aurb);
+}
+
+static AsyncURB *async_find(USBRedirDevice *dev, uint32_t packet_id)
+{
+    AsyncURB *aurb;
+
+    QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
+        if (aurb->packet_id == packet_id) {
+            return aurb;
+        }
+    }
+    ERROR("could not find async urb for packet_id %u\n", packet_id);
+    return NULL;
+}
+
+static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
+{
+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    AsyncURB *aurb;
+
+    QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
+        if (p != aurb->packet) {
+            continue;
+        }
+
+        DPRINTF("async cancel id %u\n", aurb->packet_id);
+        usbredirparser_send_cancel_data_packet(dev->parser, aurb->packet_id);
+        usbredirparser_do_write(dev->parser);
+
+        /* Mark it as dead */
+        aurb->packet = NULL;
+        break;
+    }
+}
+
+static struct buf_packet *bufp_alloc(USBRedirDevice *dev,
+    uint8_t *data, int len, int status, uint8_t ep)
+{
+    struct buf_packet *bufp = qemu_malloc(sizeof(struct buf_packet));
+    bufp->data   = data;
+    bufp->len    = len;
+    bufp->status = status;
+    QTAILQ_INSERT_TAIL(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
+    return bufp;
+}
+
+static void bufp_free(USBRedirDevice *dev, struct buf_packet *bufp,
+    uint8_t ep)
+{
+    QTAILQ_REMOVE(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
+    free(bufp->data);
+    qemu_free(bufp);
+}
+
+static void usbredir_free_bufpq(USBRedirDevice *dev, uint8_t ep)
+{
+    struct buf_packet *buf, *buf_next;
+
+    QTAILQ_FOREACH_SAFE(buf, &dev->endpoint[EP2I(ep)].bufpq, next, buf_next) {
+        bufp_free(dev, buf, ep);
+    }
+}
+
+/*
+ * USBDevice callbacks
+ */
+
+static void usbredir_handle_reset(USBDevice *udev)
+{
+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+
+    DPRINTF("reset device\n");
+    usbredirparser_send_reset(dev->parser);
+    usbredirparser_do_write(dev->parser);
+}
+
+static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
+                                     uint8_t ep)
+{
+    int status, len;
+
+    if (!dev->endpoint[EP2I(ep)].iso_started &&
+            !dev->endpoint[EP2I(ep)].iso_error) {
+        struct usb_redir_start_iso_stream_header start_iso = {
+            .endpoint = ep,
+            /* TODO maybe do something with these depending on ep interval? */
+            .pkts_per_urb = 32,
+            .no_urbs = 3,
+        };
+        /* No id, we look at the ep when receiving a status back */
+        usbredirparser_send_start_iso_stream(dev->parser, 0, &start_iso);
+        usbredirparser_do_write(dev->parser);
+        DPRINTF("iso stream started ep %02X\n", ep);
+        dev->endpoint[EP2I(ep)].iso_started = 1;
+    }
+
+    if (ep & USB_DIR_IN) {
+        struct buf_packet *isop;
+
+        isop = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
+        if (isop == NULL) {
+            DPRINTF2("iso-token-in ep %02X, no isop\n", ep);
+            /* Check iso_error for stream errors, otherwise its an underrun */
+            status = dev->endpoint[EP2I(ep)].iso_error;
+            dev->endpoint[EP2I(ep)].iso_error = 0;
+            return usbredir_handle_status(dev, status, 0);
+        }
+        DPRINTF2("iso-token-in ep %02X status %d len %d\n", ep, isop->status,
+                 isop->len);
+
+        status = isop->status;
+        if (status != usb_redir_success) {
+            bufp_free(dev, isop, ep);
+            return usbredir_handle_status(dev, status, 0);
+        }
+
+        len = isop->len;
+        if (len > p->len) {
+            ERROR("received iso data is larger then packet ep %02X\n", ep);
+            bufp_free(dev, isop, ep);
+            return USB_RET_NAK;
+        }
+        memcpy(p->data, isop->data, len);
+        bufp_free(dev, isop, ep);
+        return len;
+    } else {
+        /* If the stream was not started because of a pending error don't
+           send the packet to the usb-host */
+        if (dev->endpoint[EP2I(ep)].iso_started) {
+            struct usb_redir_iso_packet_header iso_packet = {
+                .endpoint = ep,
+                .length = p->len
+            };
+            /* No id, we look at the ep when receiving a status back */
+            usbredirparser_send_iso_packet(dev->parser, 0, &iso_packet,
+                                           p->data, p->len);
+            usbredirparser_do_write(dev->parser);
+        }
+        status = dev->endpoint[EP2I(ep)].iso_error;
+        dev->endpoint[EP2I(ep)].iso_error = 0;
+        DPRINTF2("iso-token-out ep %02X status %d len %d\n", ep, status,
+                 p->len);
+        return usbredir_handle_status(dev, status, p->len);
+    }
+}
+
+static void usbredir_stop_iso_stream(USBRedirDevice *dev, uint8_t ep)
+{
+    struct usb_redir_stop_iso_stream_header stop_iso_stream = {
+        .endpoint = ep
+    };
+    if (dev->endpoint[EP2I(ep)].iso_started) {
+        usbredirparser_send_stop_iso_stream(dev->parser, 0, &stop_iso_stream);
+        DPRINTF("iso stream stopped ep %02X\n", ep);
+        dev->endpoint[EP2I(ep)].iso_started = 0;
+    }
+    usbredir_free_bufpq(dev, ep);
+}
+
+static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
+                                      uint8_t ep)
+{
+    AsyncURB *aurb = async_alloc(dev, p);
+    struct usb_redir_bulk_packet_header bulk_packet;
+
+    DPRINTF("bulk-out ep %02X len %d id %u\n", ep, p->len, aurb->packet_id);
+
+    bulk_packet.endpoint  = ep;
+    bulk_packet.length    = p->len;
+    bulk_packet.stream_id = 0;
+    aurb->bulk_packet = bulk_packet;
+
+    if (ep & USB_DIR_IN) {
+        usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
+                                        &bulk_packet, NULL, 0);
+    } else {
+        usbredir_log_data(dev, "bulk data out:", p->data, p->len);
+        usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
+                                        &bulk_packet, p->data, p->len);
+    }
+    usbredirparser_do_write(dev->parser);
+    return USB_RET_ASYNC;
+}
+
+static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
+                                           USBPacket *p, uint8_t ep)
+{
+    if (ep & USB_DIR_IN) {
+        /* Input interrupt endpoint, buffered packet input */
+        struct buf_packet *intp;
+        int status, len;
+
+        if (!dev->endpoint[EP2I(ep)].interrupt_started &&
+                !dev->endpoint[EP2I(ep)].interrupt_error) {
+            struct usb_redir_start_interrupt_receiving_header start_int = {
+                .endpoint = ep,
+            };
+            /* No id, we look at the ep when receiving a status back */
+            usbredirparser_send_start_interrupt_receiving(dev->parser, 0,
+                                                          &start_int);
+            usbredirparser_do_write(dev->parser);
+            DPRINTF("interrupt recv started ep %02X\n", ep);
+            dev->endpoint[EP2I(ep)].interrupt_started = 1;
+        }
+
+        intp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
+        if (intp == NULL) {
+            DPRINTF2("interrupt-token-in ep %02X, no intp\n", ep);
+            /* Check interrupt_error for stream errors */
+            status = dev->endpoint[EP2I(ep)].interrupt_error;
+            dev->endpoint[EP2I(ep)].interrupt_error = 0;
+            return usbredir_handle_status(dev, status, 0);
+        }
+        DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep,
+                intp->status, intp->len);
+
+        status = intp->status;
+        if (status != usb_redir_success) {
+            bufp_free(dev, intp, ep);
+            return usbredir_handle_status(dev, status, 0);
+        }
+
+        len = intp->len;
+        if (len > p->len) {
+            ERROR("received int data is larger then packet ep %02X\n", ep);
+            bufp_free(dev, intp, ep);
+            return USB_RET_NAK;
+        }
+        memcpy(p->data, intp->data, len);
+        bufp_free(dev, intp, ep);
+        return len;
+    } else {
+        /* Output interrupt endpoint, normal async operation */
+        AsyncURB *aurb = async_alloc(dev, p);
+        struct usb_redir_interrupt_packet_header interrupt_packet;
+
+        DPRINTF("interrupt-out ep %02X len %d id %u\n", ep, p->len,
+                aurb->packet_id);
+
+        interrupt_packet.endpoint  = ep;
+        interrupt_packet.length    = p->len;
+        aurb->interrupt_packet     = interrupt_packet;
+
+        usbredir_log_data(dev, "interrupt data out:", p->data, p->len);
+        usbredirparser_send_interrupt_packet(dev->parser, aurb->packet_id,
+                                        &interrupt_packet, p->data, p->len);
+        usbredirparser_do_write(dev->parser);
+        return USB_RET_ASYNC;
+    }
+}
+
+static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev,
+    uint8_t ep)
+{
+    struct usb_redir_stop_interrupt_receiving_header stop_interrupt_recv = {
+        .endpoint = ep
+    };
+    if (dev->endpoint[EP2I(ep)].interrupt_started) {
+        usbredirparser_send_stop_interrupt_receiving(dev->parser, 0,
+                                                     &stop_interrupt_recv);
+        DPRINTF("interrupt recv stopped ep %02X\n", ep);
+        dev->endpoint[EP2I(ep)].interrupt_started = 0;
+    }
+    usbredir_free_bufpq(dev, ep);
+}
+
+static int usbredir_handle_data(USBDevice *udev, USBPacket *p)
+{
+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    uint8_t ep;
+
+    ep = p->devep;
+    if (p->pid == USB_TOKEN_IN) {
+        ep |= USB_DIR_IN;
+    }
+
+    switch (dev->endpoint[EP2I(ep)].type) {
+    case USB_ENDPOINT_XFER_CONTROL:
+        ERROR("handle_data called for control transfer on ep %02X\n", ep);
+        return USB_RET_NAK;
+    case USB_ENDPOINT_XFER_ISOC:
+        return usbredir_handle_iso_data(dev, p, ep);
+    case USB_ENDPOINT_XFER_BULK:
+        return usbredir_handle_bulk_data(dev, p, ep);;
+    case USB_ENDPOINT_XFER_INT:
+        return usbredir_handle_interrupt_data(dev, p, ep);;
+    default:
+        ERROR("handle_data ep %02X has unknown type %d\n", ep,
+              dev->endpoint[EP2I(ep)].type);
+        return USB_RET_NAK;
+    }
+}
+
+static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p,
+                                int config)
+{
+    struct usb_redir_set_configuration_header set_config;
+    AsyncURB *aurb = async_alloc(dev, p);
+    int i;
+
+    DPRINTF("set config %d id %u\n", config, aurb->packet_id);
+
+    for (i = 0; i < MAX_ENDPOINTS; i++) {
+        switch (dev->endpoint[i].type) {
+        case USB_ENDPOINT_XFER_ISOC:
+            usbredir_stop_iso_stream(dev, I2EP(i));
+            break;
+        case USB_ENDPOINT_XFER_INT:
+            if (i & 0x10) {
+                usbredir_stop_interrupt_receiving(dev, I2EP(i));
+            }
+            break;
+        }
+        usbredir_free_bufpq(dev, I2EP(i));
+    }
+
+    set_config.configuration = config;
+    usbredirparser_send_set_configuration(dev->parser, aurb->packet_id,
+                                          &set_config);
+    usbredirparser_do_write(dev->parser);
+    return USB_RET_ASYNC;
+}
+
+static int usbredir_get_config(USBRedirDevice *dev, USBPacket *p)
+{
+    AsyncURB *aurb = async_alloc(dev, p);
+
+    DPRINTF("get config id %u\n", aurb->packet_id);
+
+    aurb->get = 1;
+    usbredirparser_send_get_configuration(dev->parser, aurb->packet_id);
+    usbredirparser_do_write(dev->parser);
+    return USB_RET_ASYNC;
+}
+
+static int usbredir_set_interface(USBRedirDevice *dev, USBPacket *p,
+                                   int interface, int alt)
+{
+    struct usb_redir_set_alt_setting_header set_alt;
+    AsyncURB *aurb = async_alloc(dev, p);
+    int i;
+
+    DPRINTF("set interface %d alt %d id %u\n", interface, alt,
+            aurb->packet_id);
+
+    for (i = 0; i < MAX_ENDPOINTS; i++) {
+        if (dev->endpoint[i].interface == interface) {
+            switch (dev->endpoint[i].type) {
+            case USB_ENDPOINT_XFER_ISOC:
+                usbredir_stop_iso_stream(dev, I2EP(i));
+                break;
+            case USB_ENDPOINT_XFER_INT:
+                if (i & 0x10) {
+                    usbredir_stop_interrupt_receiving(dev, I2EP(i));
+                }
+                break;
+            }
+            usbredir_free_bufpq(dev, I2EP(i));
+        }
+    }
+
+    set_alt.interface = interface;
+    set_alt.alt = alt;
+    usbredirparser_send_set_alt_setting(dev->parser, aurb->packet_id,
+                                        &set_alt);
+    usbredirparser_do_write(dev->parser);
+    return USB_RET_ASYNC;
+}
+
+static int usbredir_get_interface(USBRedirDevice *dev, USBPacket *p,
+                                   int interface)
+{
+    struct usb_redir_get_alt_setting_header get_alt;
+    AsyncURB *aurb = async_alloc(dev, p);
+
+    DPRINTF("get interface %d id %u\n", interface, aurb->packet_id);
+
+    get_alt.interface = interface;
+    aurb->get = 1;
+    usbredirparser_send_get_alt_setting(dev->parser, aurb->packet_id,
+                                        &get_alt);
+    usbredirparser_do_write(dev->parser);
+    return USB_RET_ASYNC;
+}
+
+static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
+        int request, int value, int index, int length, uint8_t *data)
+{
+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    struct usb_redir_control_packet_header control_packet;
+    AsyncURB *aurb;
+
+    /* Special cases for certain standard device requests */
+    switch (request) {
+    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
+        DPRINTF("set address %d\n", value);
+        dev->dev.addr = value;
+        return 0;
+    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+        return usbredir_set_config(dev, p, value & 0xff);
+    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
+        return usbredir_get_config(dev, p);
+    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
+        return usbredir_set_interface(dev, p, index, value);
+    case InterfaceRequest | USB_REQ_GET_INTERFACE:
+        return usbredir_get_interface(dev, p, index);
+    }
+
+    /* "Normal" ctrl requests */
+    aurb = async_alloc(dev, p);
+
+    /* Note request is (bRequestType << 8) | bRequest */
+    DPRINTF("ctrl-out type 0x%x req 0x%x val 0x%x index %d len %d id %u\n",
+            request >> 8, request & 0xff, value, index, length,
+            aurb->packet_id);
+
+    control_packet.request     = request & 0xFF;
+    control_packet.requesttype = request >> 8;
+    control_packet.endpoint    = control_packet.requesttype & USB_DIR_IN;
+    control_packet.value       = value;
+    control_packet.index       = index;
+    control_packet.length      = length;
+    aurb->control_packet       = control_packet;
+
+    if (control_packet.requesttype & USB_DIR_IN) {
+        usbredirparser_send_control_packet(dev->parser, aurb->packet_id,
+                                           &control_packet, NULL, 0);
+    } else {
+        usbredir_log_data(dev, "ctrl data out:", data, length);
+        usbredirparser_send_control_packet(dev->parser, aurb->packet_id,
+                                           &control_packet, data, length);
+    }
+    usbredirparser_do_write(dev->parser);
+    return USB_RET_ASYNC;
+}
+
+/*
+ * Close events can be triggered by usbredirparser_do_write which gets called
+ * from within the USBDevice data / control packet callbacks and doing a
+ * usb_detach from within these callbacks is not a good idea.
+ *
+ * So we use a bh handler to take care of close events. We also handle
+ * open events from this callback to make sure that a close directly followed
+ * by an open gets handled in the right order.
+ */
+static void usbredir_open_close_bh(void *opaque)
+{
+    USBRedirDevice *dev = opaque;
+
+    usbredir_device_disconnect(dev);
+
+    if (dev->parser) {
+        usbredirparser_destroy(dev->parser);
+        dev->parser = NULL;
+    }
+
+    if (dev->cs->opened) {
+        dev->parser = qemu_oom_check(usbredirparser_create());
+        dev->parser->priv = dev;
+        dev->parser->log_func = usbredir_log;
+        dev->parser->read_func = usbredir_read;
+        dev->parser->write_func = usbredir_write;
+        dev->parser->device_connect_func = usbredir_device_connect;
+        dev->parser->device_disconnect_func = usbredir_device_disconnect;
+        dev->parser->interface_info_func = usbredir_interface_info;
+        dev->parser->ep_info_func = usbredir_ep_info;
+        dev->parser->configuration_status_func = usbredir_configuration_status;
+        dev->parser->alt_setting_status_func = usbredir_alt_setting_status;
+        dev->parser->iso_stream_status_func = usbredir_iso_stream_status;
+        dev->parser->interrupt_receiving_status_func =
+            usbredir_interrupt_receiving_status;
+        dev->parser->bulk_streams_status_func = usbredir_bulk_streams_status;
+        dev->parser->control_packet_func = usbredir_control_packet;
+        dev->parser->bulk_packet_func = usbredir_bulk_packet;
+        dev->parser->iso_packet_func = usbredir_iso_packet;
+        dev->parser->interrupt_packet_func = usbredir_interrupt_packet;
+        dev->read_buf = NULL;
+        dev->read_buf_size = 0;
+        usbredirparser_init(dev->parser, VERSION, NULL, 0, 0);
+        usbredirparser_do_write(dev->parser);
+    }
+}
+
+static void usbredir_do_attach(void *opaque)
+{
+    USBRedirDevice *dev = opaque;
+
+    usb_device_attach(&dev->dev);
+}
+
+/*
+ * chardev callbacks
+ */
+
+static int usbredir_chardev_can_read(void *opaque)
+{
+    USBRedirDevice *dev = opaque;
+
+    if (dev->parser) {
+        /* usbredir_parser_do_read will consume *all* data we give it */
+        return 1024 * 1024;
+    } else {
+        /* usbredir_open_close_bh hasn't handled the open event yet */
+        return 0;
+    }
+}
+
+static void usbredir_chardev_read(void *opaque, const uint8_t *buf, int size)
+{
+    USBRedirDevice *dev = opaque;
+
+    /* No recursion allowed! */
+    assert(dev->read_buf == NULL);
+
+    dev->read_buf = buf;
+    dev->read_buf_size = size;
+
+    usbredirparser_do_read(dev->parser);
+    /* Send any acks, etc. which may be queued now */
+    usbredirparser_do_write(dev->parser);
+}
+
+static void usbredir_chardev_event(void *opaque, int event)
+{
+    USBRedirDevice *dev = opaque;
+
+    switch (event) {
+    case CHR_EVENT_OPENED:
+    case CHR_EVENT_CLOSED:
+        qemu_bh_schedule(dev->open_close_bh);
+        break;
+    }
+}
+
+/*
+ * init + destroy
+ */
+
+static int usbredir_initfn(USBDevice *udev)
+{
+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    int i;
+
+    if (dev->cs == NULL) {
+        qerror_report(QERR_MISSING_PARAMETER, "chardev");
+        return -1;
+    }
+
+    dev->open_close_bh = qemu_bh_new(usbredir_open_close_bh, dev);
+    dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
+
+    QTAILQ_INIT(&dev->asyncq);
+    for (i = 0; i < MAX_ENDPOINTS; i++) {
+        QTAILQ_INIT(&dev->endpoint[i].bufpq);
+    }
+
+    /* We'll do the attach once we receive the speed from the usb-host */
+    udev->auto_attach = 0;
+
+    qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
+                          usbredir_chardev_read, usbredir_chardev_event, dev);
+
+    return 0;
+}
+
+static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
+{
+    AsyncURB *aurb, *next_aurb;
+    int i;
+
+    QTAILQ_FOREACH_SAFE(aurb, &dev->asyncq, next, next_aurb) {
+        async_free(dev, aurb);
+    }
+    for (i = 0; i < MAX_ENDPOINTS; i++) {
+        usbredir_free_bufpq(dev, I2EP(i));
+    }
+}
+
+static void usbredir_handle_destroy(USBDevice *udev)
+{
+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+
+    qemu_chr_close(dev->cs);
+    /* Note must be done after qemu_chr_close, as that causes a close event */
+    qemu_bh_delete(dev->open_close_bh);
+
+    qemu_del_timer(dev->attach_timer);
+    qemu_free_timer(dev->attach_timer);
+
+    usbredir_cleanup_device_queues(dev);
+
+    if (dev->parser) {
+        usbredirparser_destroy(dev->parser);
+    }
+}
+
+/*
+ * usbredirparser packet complete callbacks
+ */
+
+static int usbredir_handle_status(USBRedirDevice *dev,
+                                       int status, int actual_len)
+{
+    switch (status) {
+    case usb_redir_success:
+        return actual_len;
+    case usb_redir_stall:
+        return USB_RET_STALL;
+    case usb_redir_cancelled:
+        WARNING("returning cancelled packet to HC?\n");
+    case usb_redir_inval:
+    case usb_redir_ioerror:
+    case usb_redir_timeout:
+    default:
+        return USB_RET_NAK;
+    }
+}
+
+static void usbredir_device_connect(void *priv,
+    struct usb_redir_device_connect_header *device_connect)
+{
+    USBRedirDevice *dev = priv;
+
+    switch (device_connect->speed) {
+    case usb_redir_speed_low:
+        DPRINTF("attaching low speed device\n");
+        dev->dev.speed = USB_SPEED_LOW;
+        break;
+    case usb_redir_speed_full:
+        DPRINTF("attaching full speed device\n");
+        dev->dev.speed = USB_SPEED_FULL;
+        break;
+    case usb_redir_speed_high:
+        DPRINTF("attaching high speed device\n");
+        dev->dev.speed = USB_SPEED_HIGH;
+        break;
+    case usb_redir_speed_super:
+        DPRINTF("attaching super speed device\n");
+        dev->dev.speed = USB_SPEED_SUPER;
+        break;
+    default:
+        DPRINTF("attaching unknown speed device, assuming full speed\n");
+        dev->dev.speed = USB_SPEED_FULL;
+    }
+    dev->dev.speedmask = (1 << dev->dev.speed);
+    qemu_mod_timer(dev->attach_timer, dev->next_attach_time);
+}
+
+static void usbredir_device_disconnect(void *priv)
+{
+    USBRedirDevice *dev = priv;
+
+    /* 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;
+    }
+}
+
+static void usbredir_interface_info(void *priv,
+    struct usb_redir_interface_info_header *interface_info)
+{
+    /* The intention is to allow specifying acceptable interface classes
+       for redirection on the cmdline and in the future verify this here,
+       and disconnect (or never connect) the device if a not accepted
+       interface class is detected */
+}
+
+static void usbredir_ep_info(void *priv,
+    struct usb_redir_ep_info_header *ep_info)
+{
+    USBRedirDevice *dev = priv;
+    int i;
+
+    for (i = 0; i < MAX_ENDPOINTS; i++) {
+        dev->endpoint[i].type = ep_info->type[i];
+        dev->endpoint[i].interval = ep_info->interval[i];
+        dev->endpoint[i].interface = ep_info->interface[i];
+        if (dev->endpoint[i].type != usb_redir_type_invalid) {
+            DPRINTF("ep: %02X type: %d interface: %d\n", I2EP(i),
+                    dev->endpoint[i].type, dev->endpoint[i].interface);
+        }
+    }
+}
+
+static void usbredir_configuration_status(void *priv, uint32_t id,
+    struct usb_redir_configuration_status_header *config_status)
+{
+    USBRedirDevice *dev = priv;
+    AsyncURB *aurb;
+    int len = 0;
+
+    DPRINTF("set config status %d config %d id %u\n", config_status->status,
+            config_status->configuration, id);
+
+    aurb = async_find(dev, id);
+    if (!aurb) {
+        return;
+    }
+    if (aurb->packet) {
+        if (aurb->get) {
+            dev->dev.data_buf[0] = config_status->configuration;
+            len = 1;
+        }
+        aurb->packet->len =
+            usbredir_handle_status(dev, config_status->status, len);
+        usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
+    }
+    async_free(dev, aurb);
+}
+
+static void usbredir_alt_setting_status(void *priv, uint32_t id,
+    struct usb_redir_alt_setting_status_header *alt_setting_status)
+{
+    USBRedirDevice *dev = priv;
+    AsyncURB *aurb;
+    int len = 0;
+
+    DPRINTF("alt status %d intf %d alt %d id: %u\n",
+            alt_setting_status->status,
+            alt_setting_status->interface,
+            alt_setting_status->alt, id);
+
+    aurb = async_find(dev, id);
+    if (!aurb) {
+        return;
+    }
+    if (aurb->packet) {
+        if (aurb->get) {
+            dev->dev.data_buf[0] = alt_setting_status->alt;
+            len = 1;
+        }
+        aurb->packet->len =
+            usbredir_handle_status(dev, alt_setting_status->status, len);
+        usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
+    }
+    async_free(dev, aurb);
+}
+
+static void usbredir_iso_stream_status(void *priv, uint32_t id,
+    struct usb_redir_iso_stream_status_header *iso_stream_status)
+{
+    USBRedirDevice *dev = priv;
+    uint8_t ep = iso_stream_status->endpoint;
+
+    DPRINTF("iso status %d ep %02X id %u\n", iso_stream_status->status,
+            ep, id);
+
+    dev->endpoint[EP2I(ep)].iso_error = iso_stream_status->status;
+    if (iso_stream_status->status == usb_redir_stall) {
+        DPRINTF("iso stream stopped by peer ep %02X\n", ep);
+        dev->endpoint[EP2I(ep)].iso_started = 0;
+    }
+}
+
+static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
+    struct usb_redir_interrupt_receiving_status_header
+    *interrupt_receiving_status)
+{
+    USBRedirDevice *dev = priv;
+    uint8_t ep = interrupt_receiving_status->endpoint;
+
+    DPRINTF("interrupt recv status %d ep %02X id %u\n",
+            interrupt_receiving_status->status, ep, id);
+
+    dev->endpoint[EP2I(ep)].interrupt_error =
+        interrupt_receiving_status->status;
+    if (interrupt_receiving_status->status == usb_redir_stall) {
+        DPRINTF("interrupt receiving stopped by peer ep %02X\n", ep);
+        dev->endpoint[EP2I(ep)].interrupt_started = 0;
+    }
+}
+
+static void usbredir_bulk_streams_status(void *priv, uint32_t id,
+    struct usb_redir_bulk_streams_status_header *bulk_streams_status)
+{
+}
+
+static void usbredir_control_packet(void *priv, uint32_t id,
+    struct usb_redir_control_packet_header *control_packet,
+    uint8_t *data, int data_len)
+{
+    USBRedirDevice *dev = priv;
+    int len = control_packet->length;
+    AsyncURB *aurb;
+
+    DPRINTF("ctrl-in status %d len %d id %u\n", control_packet->status,
+            len, id);
+
+    aurb = async_find(dev, id);
+    if (!aurb) {
+        free(data);
+        return;
+    }
+
+    aurb->control_packet.status = control_packet->status;
+    aurb->control_packet.length = control_packet->length;
+    if (memcmp(&aurb->control_packet, control_packet,
+               sizeof(*control_packet))) {
+        ERROR("return control packet mismatch, please report this!\n");
+        len = USB_RET_NAK;
+    }
+
+    if (aurb->packet) {
+        len = usbredir_handle_status(dev, control_packet->status, len);
+        if (len > 0) {
+            usbredir_log_data(dev, "ctrl data in:", data, data_len);
+            if (data_len <= sizeof(dev->dev.data_buf)) {
+                memcpy(dev->dev.data_buf, data, data_len);
+            } else {
+                ERROR("ctrl buffer too small (%d > %zu)\n",
+                      data_len, sizeof(dev->dev.data_buf));
+                len = USB_RET_STALL;
+            }
+        }
+        aurb->packet->len = len;
+        usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
+    }
+    async_free(dev, aurb);
+    free(data);
+}
+
+static void usbredir_bulk_packet(void *priv, uint32_t id,
+    struct usb_redir_bulk_packet_header *bulk_packet,
+    uint8_t *data, int data_len)
+{
+    USBRedirDevice *dev = priv;
+    uint8_t ep = bulk_packet->endpoint;
+    int len = bulk_packet->length;
+    AsyncURB *aurb;
+
+    DPRINTF("bulk-in status %d ep %02X len %d id %u\n", bulk_packet->status,
+            ep, len, id);
+
+    aurb = async_find(dev, id);
+    if (!aurb) {
+        free(data);
+        return;
+    }
+
+    if (aurb->bulk_packet.endpoint != bulk_packet->endpoint ||
+            aurb->bulk_packet.stream_id != bulk_packet->stream_id) {
+        ERROR("return bulk packet mismatch, please report this!\n");
+        len = USB_RET_NAK;
+    }
+
+    if (aurb->packet) {
+        len = usbredir_handle_status(dev, bulk_packet->status, len);
+        if (len > 0) {
+            usbredir_log_data(dev, "bulk data in:", data, data_len);
+            if (data_len <= aurb->packet->len) {
+                memcpy(aurb->packet->data, data, data_len);
+            } else {
+                ERROR("bulk buffer too small (%d > %d)\n", data_len,
+                      aurb->packet->len);
+                len = USB_RET_STALL;
+            }
+        }
+        aurb->packet->len = len;
+        usb_packet_complete(&dev->dev, aurb->packet);
+    }
+    async_free(dev, aurb);
+    free(data);
+}
+
+static void usbredir_iso_packet(void *priv, uint32_t id,
+    struct usb_redir_iso_packet_header *iso_packet,
+    uint8_t *data, int data_len)
+{
+    USBRedirDevice *dev = priv;
+    uint8_t ep = iso_packet->endpoint;
+
+    DPRINTF2("iso-in status %d ep %02X len %d id %u\n", iso_packet->status, ep,
+             data_len, id);
+
+    if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_ISOC) {
+        ERROR("received iso packet for non iso endpoint %02X\n", ep);
+        free(data);
+        return;
+    }
+
+    if (dev->endpoint[EP2I(ep)].iso_started == 0) {
+        DPRINTF("received iso packet for non started stream ep %02X\n", ep);
+        free(data);
+        return;
+    }
+
+    /* bufp_alloc also adds the packet to the ep queue */
+    bufp_alloc(dev, data, data_len, iso_packet->status, ep);
+}
+
+static void usbredir_interrupt_packet(void *priv, uint32_t id,
+    struct usb_redir_interrupt_packet_header *interrupt_packet,
+    uint8_t *data, int data_len)
+{
+    USBRedirDevice *dev = priv;
+    uint8_t ep = interrupt_packet->endpoint;
+
+    DPRINTF("interrupt-in status %d ep %02X len %d id %u\n",
+            interrupt_packet->status, ep, data_len, id);
+
+    if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_INT) {
+        ERROR("received int packet for non interrupt endpoint %02X\n", ep);
+        free(data);
+        return;
+    }
+
+    if (ep & USB_DIR_IN) {
+        if (dev->endpoint[EP2I(ep)].interrupt_started == 0) {
+            DPRINTF("received int packet while not started ep %02X\n", ep);
+            free(data);
+            return;
+        }
+
+        /* bufp_alloc also adds the packet to the ep queue */
+        bufp_alloc(dev, data, data_len, interrupt_packet->status, ep);
+    } else {
+        int len = interrupt_packet->length;
+
+        AsyncURB *aurb = async_find(dev, id);
+        if (!aurb) {
+            return;
+        }
+
+        if (aurb->interrupt_packet.endpoint != interrupt_packet->endpoint) {
+            ERROR("return int packet mismatch, please report this!\n");
+            len = USB_RET_NAK;
+        }
+
+        if (aurb->packet) {
+            aurb->packet->len = usbredir_handle_status(dev,
+                                               interrupt_packet->status, len);
+            usb_packet_complete(&dev->dev, aurb->packet);
+        }
+        async_free(dev, aurb);
+    }
+}
+
+static struct USBDeviceInfo usbredir_dev_info = {
+    .product_desc   = "USB Redirection Device",
+    .qdev.name      = "usb-redir",
+    .qdev.size      = sizeof(USBRedirDevice),
+    .init           = usbredir_initfn,
+    .handle_destroy = usbredir_handle_destroy,
+    .handle_packet  = usb_generic_handle_packet,
+    .cancel_packet  = usbredir_cancel_packet,
+    .handle_reset   = usbredir_handle_reset,
+    .handle_data    = usbredir_handle_data,
+    .handle_control = usbredir_handle_control,
+    .qdev.props     = (Property[]) {
+        DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
+        DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
+static void usbredir_register_devices(void)
+{
+    usb_qdev_register(&usbredir_dev_info);
+}
+device_init(usbredir_register_devices);
commit 2e97f03ed7719d95e739c4050459b5026ef3cc6c
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jul 20 15:44:01 2011 +0200

    usb-ehci: trace: rename "next" to "nxt".
    
    "next" is reserved in systemtap thus using this as a
    trace parameter name causes trouble when trying to trace
    with systemtap.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/trace-events b/trace-events
index 99a4a2b..713f042 100644
--- a/trace-events
+++ b/trace-events
@@ -216,13 +216,13 @@ disable usb_ehci_mmio_writel(uint32_t addr, const char *str, uint32_t val) "wr m
 disable usb_ehci_mmio_change(uint32_t addr, const char *str, uint32_t new, uint32_t old) "ch mmio %04x [%s] = %x (old: %x)"
 disable usb_ehci_usbsts(const char *sts, int state) "usbsts %s %d"
 disable usb_ehci_state(const char *schedule, const char *state) "%s schedule %s"
-disable usb_ehci_qh_ptrs(void *q, uint32_t addr, uint32_t next, uint32_t c_qtd, uint32_t n_qtd, uint32_t a_qtd) "q %p - QH @ %08x: next %08x qtds %08x,%08x,%08x"
+disable usb_ehci_qh_ptrs(void *q, uint32_t addr, uint32_t nxt, uint32_t c_qtd, uint32_t n_qtd, uint32_t a_qtd) "q %p - QH @ %08x: next %08x qtds %08x,%08x,%08x"
 disable usb_ehci_qh_fields(uint32_t addr, int rl, int mplen, int eps, int ep, int devaddr) "QH @ %08x - rl %d, mplen %d, eps %d, ep %d, dev %d"
 disable usb_ehci_qh_bits(uint32_t addr, int c, int h, int dtc, int i) "QH @ %08x - c %d, h %d, dtc %d, i %d"
-disable usb_ehci_qtd_ptrs(void *q, uint32_t addr, uint32_t next, uint32_t altnext) "q %p - QTD @ %08x: next %08x altnext %08x"
+disable usb_ehci_qtd_ptrs(void *q, uint32_t addr, uint32_t nxt, uint32_t altnext) "q %p - QTD @ %08x: next %08x altnext %08x"
 disable usb_ehci_qtd_fields(uint32_t addr, int tbytes, int cpage, int cerr, int pid) "QTD @ %08x - tbytes %d, cpage %d, cerr %d, pid %d"
 disable usb_ehci_qtd_bits(uint32_t addr, int ioc, int active, int halt, int babble, int xacterr) "QTD @ %08x - ioc %d, active %d, halt %d, babble %d, xacterr %d"
-disable usb_ehci_itd(uint32_t addr, uint32_t next, uint32_t mplen, uint32_t mult, uint32_t ep, uint32_t devaddr) "ITD @ %08x: next %08x - mplen %d, mult %d, ep %d, dev %d"
+disable usb_ehci_itd(uint32_t addr, uint32_t nxt, uint32_t mplen, uint32_t mult, uint32_t ep, uint32_t devaddr) "ITD @ %08x: next %08x - mplen %d, mult %d, ep %d, dev %d"
 disable usb_ehci_port_attach(uint32_t port, const char *device) "attach port #%d - %s"
 disable usb_ehci_port_detach(uint32_t port) "detach port #%d"
 disable usb_ehci_port_reset(uint32_t port, int enable) "reset port #%d - %d"
commit 0070f095d9aa216ebe4c06c43d0072275f23c8af
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jul 8 17:28:11 2011 +0200

    usb-uhci: fix irq handling on error.
    
    Spec on UHCI_STS_USBERR: "If the TD on which the error interrupt
    occurred also had its IOC bit set, both this bit and Bit 0 are set."
    
    Make UHCI emulation do that.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 2ef4c5b..da74c57 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -730,6 +730,9 @@ out:
         td->ctrl |= TD_CTRL_STALL;
         td->ctrl &= ~TD_CTRL_ACTIVE;
         s->status |= UHCI_STS_USBERR;
+        if (td->ctrl & TD_CTRL_IOC) {
+            *int_mask |= 0x01;
+        }
         uhci_update_irq(s);
         return 1;
 
@@ -737,6 +740,9 @@ out:
         td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
         td->ctrl &= ~TD_CTRL_ACTIVE;
         s->status |= UHCI_STS_USBERR;
+        if (td->ctrl & TD_CTRL_IOC) {
+            *int_mask |= 0x01;
+        }
         uhci_update_irq(s);
         /* frame interrupted */
         return -1;
commit e7e73892a66dd3850eb723ee2ef9ef3f4569529f
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jul 8 13:19:01 2011 +0200

    usb-hid: fixup changed tracking.
    
    Remove leftover calls to usb_hid_changed().
    
    Take care to update the changed flag after delivering a event via
    GET_REPORT like we do when sending events via interrupt endpoint.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index d711b5c..b812da2 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -531,18 +531,15 @@ static void usb_keyboard_process_keycode(USBHIDState *hs)
     case 0xe0:
         if (s->modifiers & (1 << 9)) {
             s->modifiers ^= 3 << 8;
-            usb_hid_changed(hs);
             return;
         }
     case 0xe1 ... 0xe7:
         if (keycode & (1 << 7)) {
             s->modifiers &= ~(1 << (hid_code & 0x0f));
-            usb_hid_changed(hs);
             return;
         }
     case 0xe8 ... 0xef:
         s->modifiers |= 1 << (hid_code & 0x0f);
-        usb_hid_changed(hs);
         return;
     }
 
@@ -769,10 +766,12 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
         }
         break;
     case GET_REPORT:
-        if (s->kind == USB_MOUSE || s->kind == USB_TABLET)
+        if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
             ret = usb_pointer_poll(s, data, length);
-        else if (s->kind == USB_KEYBOARD)
+        } else if (s->kind == USB_KEYBOARD) {
             ret = usb_keyboard_poll(s, data, length);
+        }
+        s->changed = s->n > 0;
         break;
     case SET_REPORT:
         if (s->kind == USB_KEYBOARD)
commit d1afc48b7cfdb4490f322d5d82a2aae6d545ec06
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Fri Jul 22 00:16:33 2011 +0900

    SPARC64: implement addtional MMU faults related to nonfaulting load
    
    This patch implements MMU faults caused by TTE.NFO and TTE.E:
    - access other than nonfaulting load to a page marked NFO should
      raise data_access_exception
    - nonfaulting load to a page marked with E bit should raise
      data_access_exception
    
    To distinguish nonfaulting loads, this patch extends (abuses?) the rw
    argument of get_physical_address_data().  rw is set to 4 on nonfaulting
    loads.
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index f4eeff5..a51863c 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -290,15 +290,19 @@ enum {
 #endif
 
 #define TTE_VALID_BIT       (1ULL << 63)
+#define TTE_NFO_BIT         (1ULL << 60)
 #define TTE_USED_BIT        (1ULL << 41)
 #define TTE_LOCKED_BIT      (1ULL <<  6)
+#define TTE_SIDEEFFECT_BIT  (1ULL <<  3)
 #define TTE_PRIV_BIT        (1ULL <<  2)
 #define TTE_W_OK_BIT        (1ULL <<  1)
 #define TTE_GLOBAL_BIT      (1ULL <<  0)
 
 #define TTE_IS_VALID(tte)   ((tte) & TTE_VALID_BIT)
+#define TTE_IS_NFO(tte)     ((tte) & TTE_NFO_BIT)
 #define TTE_IS_USED(tte)    ((tte) & TTE_USED_BIT)
 #define TTE_IS_LOCKED(tte)  ((tte) & TTE_LOCKED_BIT)
+#define TTE_IS_SIDEEFFECT(tte) ((tte) & TTE_SIDEEFFECT_BIT)
 #define TTE_IS_PRIV(tte)    ((tte) & TTE_PRIV_BIT)
 #define TTE_IS_W_OK(tte)    ((tte) & TTE_W_OK_BIT)
 #define TTE_IS_GLOBAL(tte)  ((tte) & TTE_GLOBAL_BIT)
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index b6e62a7..acc07f5 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -445,27 +445,50 @@ static int get_physical_address_data(CPUState *env,
 
     if (rw == 1) {
         sfsr |= SFSR_WRITE_BIT;
+    } else if (rw == 4) {
+        sfsr |= SFSR_NF_BIT;
     }
 
     for (i = 0; i < 64; i++) {
         // ctx match, vaddr match, valid?
         if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
+            int do_fault = 0;
 
             // access ok?
+            /* multiple bits in SFSR.FT may be set on TT_DFAULT */
             if (TTE_IS_PRIV(env->dtlb[i].tte) && is_user) {
+                do_fault = 1;
                 sfsr |= SFSR_FT_PRIV_BIT; /* privilege violation */
-                env->exception_index = TT_DFAULT;
 
                 DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
                             " mmu_idx=%d tl=%d\n",
                             address, context, mmu_idx, env->tl);
+            }
+            if (rw == 4) {
+                if (TTE_IS_SIDEEFFECT(env->dtlb[i].tte)) {
+                    do_fault = 1;
+                    sfsr |= SFSR_FT_NF_E_BIT;
+                }
+            } else {
+                if (TTE_IS_NFO(env->dtlb[i].tte)) {
+                    do_fault = 1;
+                    sfsr |= SFSR_FT_NFO_BIT;
+                }
+            }
+
+            if (do_fault) {
+                /* faults above are reported with TT_DFAULT. */
+                env->exception_index = TT_DFAULT;
             } else if (!TTE_IS_W_OK(env->dtlb[i].tte) && (rw == 1)) {
+                do_fault = 1;
                 env->exception_index = TT_DPROT;
 
                 DPRINTF_MMU("DPROT at %" PRIx64 " context %" PRIx64
                             " mmu_idx=%d tl=%d\n",
                             address, context, mmu_idx, env->tl);
-            } else {
+            }
+
+            if (!do_fault) {
                 *prot = PAGE_READ;
                 if (TTE_IS_W_OK(env->dtlb[i].tte)) {
                     *prot |= PAGE_WRITE;
@@ -752,7 +775,7 @@ target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
 {
     target_phys_addr_t phys_addr;
 
-    if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 0, mmu_idx) != 0) {
+    if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 4, mmu_idx) != 0) {
         return -1;
     }
     return phys_addr;
commit b7785d2072164fa8576767853af9ed517508ee57
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Fri Jul 22 00:16:32 2011 +0900

    SPARC64: implement MMU miss traps on nonfaulting loads
    
    Nonfaulting loads should raise fast_data_access_MMU_miss traps as
    normal loads do.  It is up to the guest OS kernel that detect MMU misses
    on nonfaulting load instructions and make them complete without signaling.
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 3b7f9ca..8962e38 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -2567,24 +2567,30 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
     helper_check_align(addr, size - 1);
     addr = asi_address_mask(env, asi, addr);
 
-    switch (asi) {
-    case 0x82: // Primary no-fault
-    case 0x8a: // Primary no-fault LE
-    case 0x83: // Secondary no-fault
-    case 0x8b: // Secondary no-fault LE
-        {
-            /* secondary space access has lowest asi bit equal to 1 */
-            int access_mmu_idx = ( asi & 1 ) ? MMU_KERNEL_IDX
-                                             : MMU_KERNEL_SECONDARY_IDX;
+    /* process nonfaulting loads first */
+    if ((asi & 0xf6) == 0x82) {
+        int mmu_idx;
+
+        /* secondary space access has lowest asi bit equal to 1 */
+        if (env->pstate & PS_PRIV) {
+            mmu_idx = (asi & 1) ? MMU_KERNEL_SECONDARY_IDX : MMU_KERNEL_IDX;
+        } else {
+            mmu_idx = (asi & 1) ? MMU_USER_SECONDARY_IDX : MMU_USER_IDX;
+        }
 
-            if (cpu_get_phys_page_nofault(env, addr, access_mmu_idx) == -1ULL) {
+        if (cpu_get_phys_page_nofault(env, addr, mmu_idx) == -1ULL) {
 #ifdef DEBUG_ASI
-                dump_asi("read ", last_addr, asi, size, ret);
+            dump_asi("read ", last_addr, asi, size, ret);
 #endif
-                return 0;
-            }
+            /* env->exception_index is set in get_physical_address_data(). */
+            raise_exception(env->exception_index);
         }
-        // Fall through
+
+        /* convert nonfaulting load ASIs to normal load ASIs */
+        asi &= ~0x02;
+    }
+
+    switch (asi) {
     case 0x10: // As if user primary
     case 0x11: // As if user secondary
     case 0x18: // As if user primary LE
@@ -2862,8 +2868,6 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
     case 0x1d: // Bypass, non-cacheable LE
     case 0x88: // Primary LE
     case 0x89: // Secondary LE
-    case 0x8a: // Primary no-fault LE
-    case 0x8b: // Secondary no-fault LE
         switch(size) {
         case 2:
             ret = bswap16(ret);
commit 103dcbe581524ba777ccee1ca8ef7c3838c4d4de
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Fri Jul 22 00:16:31 2011 +0900

    SPARC64: fix fault status overwritten on nonfaulting load
    
    cpu_get_phys_page_nofault() calls get_physical_address() twice,
    that results in overwriting the fault status in the SFSR.
    We need this change in order for nonfaulting loads to raising MMU faults
    as normal loads do.
    Also removed the call to cpu_get_physical_page_desc() since we are
    going to modify nonfaulting loads raising MMU faults.
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index cb8d706..b6e62a7 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -752,13 +752,9 @@ target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
 {
     target_phys_addr_t phys_addr;
 
-    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)
+    if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 0, mmu_idx) != 0) {
         return -1;
+    }
     return phys_addr;
 }
 #endif
commit b64b64361413808bee8e6213095e2e3a18b3358f
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Fri Jul 22 00:16:30 2011 +0900

    SPARC64: split cpu_get_phys_page_debug() from cpu_get_phys_page_nofault()
    
    This patch makes cpu_get_phys_page_debug() independent from
    cpu_get_phys_page_nofault() in advance of implementing nonfaulting load.
    This also modifies cpu_get_phys_page_nofault() to be compiled only on
    TARGET_SPARC64 because it is not required on SPARC32.
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 348858e..f4eeff5 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -541,10 +541,12 @@ static inline int tlb_compare_context(const SparcTLBEntry *tlb,
 #if !defined(CONFIG_USER_ONLY)
 void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
                            int is_write, int is_exec, int is_asi, int size);
+#if defined(TARGET_SPARC64)
 target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
                                            int mmu_idx);
 
 #endif
+#endif
 int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
 
 #define cpu_init cpu_sparc_init
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 9acbcae..cb8d706 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -746,6 +746,7 @@ static int cpu_sparc_get_phys_page(CPUState *env, target_phys_addr_t *phys,
                                 mmu_idx, &page_size);
 }
 
+#if defined(TARGET_SPARC64)
 target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
                                            int mmu_idx)
 {
@@ -760,10 +761,22 @@ target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
         return -1;
     return phys_addr;
 }
+#endif
 
 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
-    return cpu_get_phys_page_nofault(env, addr, cpu_mmu_index(env));
+    target_phys_addr_t phys_addr;
+    int mmu_idx = cpu_mmu_index(env);
+
+    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) {
+        return -1;
+    }
+    return phys_addr;
 }
 #endif
 
commit 321365ab1734cb151090fc0b5a7bef3b97807115
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Fri Jul 22 00:16:29 2011 +0900

    SPARC64: introduce a convenience function for getting physical addresses
    
    Introduce cpu_sparc_get_phys_page() to be used as a help for splitting
    cpu_get_phys_page_debug() from cpu_get_phys_page_nofault().
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index f9b7fe2..9acbcae 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -736,18 +736,26 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
 
 
 #if !defined(CONFIG_USER_ONLY)
+static int cpu_sparc_get_phys_page(CPUState *env, target_phys_addr_t *phys,
+                                   target_ulong addr, int rw, int mmu_idx)
+{
+    target_ulong page_size;
+    int prot, access_index;
+
+    return get_physical_address(env, phys, &prot, &access_index, addr, rw,
+                                mmu_idx, &page_size);
+}
+
 target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
                                            int mmu_idx)
 {
     target_phys_addr_t phys_addr;
-    target_ulong page_size;
-    int prot, access_index;
 
-    if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
-                             mmu_idx, &page_size) != 0)
-        if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
-                                 0, mmu_idx, &page_size) != 0)
+    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)
         return -1;
     return phys_addr;
commit ccc76c24efdb06b895b8ff3d0a932c905ff483d4
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Fri Jul 22 00:16:28 2011 +0900

    SPARC64: SFSR cleanup and fix
    
    Add macros for SFSR fields and use macros instead of magic numbers.
    Also fix the update of the register fields on MMU faults.
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index b2160e9..348858e 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -309,6 +309,28 @@ enum {
 #define TTE_PGSIZE(tte)     (((tte) >> 61) & 3ULL)
 #define TTE_PA(tte)         ((tte) & 0x1ffffffe000ULL)
 
+#define SFSR_NF_BIT         (1ULL << 24)   /* JPS1 NoFault */
+#define SFSR_TM_BIT         (1ULL << 15)   /* JPS1 TLB Miss */
+#define SFSR_FT_VA_IMMU_BIT (1ULL << 13)   /* USIIi VA out of range (IMMU) */
+#define SFSR_FT_VA_DMMU_BIT (1ULL << 12)   /* USIIi VA out of range (DMMU) */
+#define SFSR_FT_NFO_BIT     (1ULL << 11)   /* NFO page access */
+#define SFSR_FT_ILL_BIT     (1ULL << 10)   /* illegal LDA/STA ASI */
+#define SFSR_FT_ATOMIC_BIT  (1ULL <<  9)   /* atomic op on noncacheable area */
+#define SFSR_FT_NF_E_BIT    (1ULL <<  8)   /* NF access on side effect area */
+#define SFSR_FT_PRIV_BIT    (1ULL <<  7)   /* privilege violation */
+#define SFSR_PR_BIT         (1ULL <<  3)   /* privilege mode */
+#define SFSR_WRITE_BIT      (1ULL <<  2)   /* write access mode */
+#define SFSR_OW_BIT         (1ULL <<  1)   /* status overwritten */
+#define SFSR_VALID_BIT      (1ULL <<  0)   /* status valid */
+
+#define SFSR_ASI_SHIFT      16             /* 23:16 ASI value */
+#define SFSR_ASI_MASK       (0xffULL << SFSR_ASI_SHIFT)
+#define SFSR_CT_PRIMARY     (0ULL <<  4)   /* 5:4 context type */
+#define SFSR_CT_SECONDARY   (1ULL <<  4)
+#define SFSR_CT_NUCLEUS     (2ULL <<  4)
+#define SFSR_CT_NOTRANS     (3ULL <<  4)
+#define SFSR_CT_MASK        (3ULL <<  4)
+
 typedef struct SparcTLBEntry {
     uint64_t tag;
     uint64_t tte;
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 0a4cfc5..f9b7fe2 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -413,6 +413,7 @@ static int get_physical_address_data(CPUState *env,
 {
     unsigned int i;
     uint64_t context;
+    uint64_t sfsr = 0;
 
     int is_user = (mmu_idx == MMU_USER_IDX ||
                    mmu_idx == MMU_USER_SECONDARY_IDX);
@@ -427,26 +428,32 @@ static int get_physical_address_data(CPUState *env,
     case MMU_USER_IDX:
     case MMU_KERNEL_IDX:
         context = env->dmmu.mmu_primary_context & 0x1fff;
+        sfsr |= SFSR_CT_PRIMARY;
         break;
     case MMU_USER_SECONDARY_IDX:
     case MMU_KERNEL_SECONDARY_IDX:
         context = env->dmmu.mmu_secondary_context & 0x1fff;
+        sfsr |= SFSR_CT_SECONDARY;
         break;
     case MMU_NUCLEUS_IDX:
+        sfsr |= SFSR_CT_NUCLEUS;
+        /* FALLTHRU */
     default:
         context = 0;
         break;
     }
 
+    if (rw == 1) {
+        sfsr |= SFSR_WRITE_BIT;
+    }
+
     for (i = 0; i < 64; i++) {
         // ctx match, vaddr match, valid?
         if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
 
-            uint8_t fault_type = 0;
-
             // access ok?
             if (TTE_IS_PRIV(env->dtlb[i].tte) && is_user) {
-                fault_type |= 1; /* privilege violation */
+                sfsr |= SFSR_FT_PRIV_BIT; /* privilege violation */
                 env->exception_index = TT_DFAULT;
 
                 DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
@@ -469,13 +476,17 @@ static int get_physical_address_data(CPUState *env,
                 return 0;
             }
 
-            if (env->dmmu.sfsr & 1) /* Fault status register */
-                env->dmmu.sfsr = 2; /* overflow (not read before
-                                             another fault) */
+            if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register */
+                sfsr |= SFSR_OW_BIT; /* overflow (not read before
+                                        another fault) */
+            }
 
-            env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
+            if (env->pstate & PS_PRIV) {
+                sfsr |= SFSR_PR_BIT;
+            }
 
-            env->dmmu.sfsr |= (fault_type << 7);
+            /* FIXME: ASI field in SFSR must be set */
+            env->dmmu.sfsr = sfsr | SFSR_VALID_BIT;
 
             env->dmmu.sfar = address; /* Fault address register */
 
@@ -488,6 +499,11 @@ static int get_physical_address_data(CPUState *env,
     DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n",
                 address, context);
 
+    /*
+     * On MMU misses:
+     * - UltraSPARC IIi: SFSR and SFAR unmodified
+     * - JPS1: SFAR updated and some fields of SFSR updated
+     */
     env->dmmu.tag_access = (address & ~0x1fffULL) | context;
     env->exception_index = TT_DMISS;
     return 1;
@@ -524,10 +540,22 @@ static int get_physical_address_code(CPUState *env,
                                  address, context, physical)) {
             // access ok?
             if (TTE_IS_PRIV(env->itlb[i].tte) && is_user) {
-                if (env->immu.sfsr) /* Fault status register */
-                    env->immu.sfsr = 2; /* overflow (not read before
-                                             another fault) */
-                env->immu.sfsr |= (is_user << 3) | 1;
+                /* Fault status register */
+                if (env->immu.sfsr & SFSR_VALID_BIT) {
+                    env->immu.sfsr = SFSR_OW_BIT; /* overflow (not read before
+                                                     another fault) */
+                } else {
+                    env->immu.sfsr = 0;
+                }
+                if (env->pstate & PS_PRIV) {
+                    env->immu.sfsr |= SFSR_PR_BIT;
+                }
+                if (env->tl > 0) {
+                    env->immu.sfsr |= SFSR_CT_NUCLEUS;
+                }
+
+                /* FIXME: ASI field in SFSR must be set */
+                env->immu.sfsr |= SFSR_FT_PRIV_BIT | SFSR_VALID_BIT;
                 env->exception_index = TT_TFAULT;
 
                 env->immu.tag_access = (address & ~0x1fffULL) | context;
commit 06e12b6503d08bbc27f256b9f5d7d211420b3c41
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Fri Jul 22 00:16:27 2011 +0900

    SPARC64: TTE bits cleanup
    
    Add macros for TTE bits and modify to use macros instead of
    magic numbers.
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 0084b67..b2160e9 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -292,16 +292,23 @@ enum {
 #define TTE_VALID_BIT       (1ULL << 63)
 #define TTE_USED_BIT        (1ULL << 41)
 #define TTE_LOCKED_BIT      (1ULL <<  6)
+#define TTE_PRIV_BIT        (1ULL <<  2)
+#define TTE_W_OK_BIT        (1ULL <<  1)
 #define TTE_GLOBAL_BIT      (1ULL <<  0)
 
 #define TTE_IS_VALID(tte)   ((tte) & TTE_VALID_BIT)
 #define TTE_IS_USED(tte)    ((tte) & TTE_USED_BIT)
 #define TTE_IS_LOCKED(tte)  ((tte) & TTE_LOCKED_BIT)
+#define TTE_IS_PRIV(tte)    ((tte) & TTE_PRIV_BIT)
+#define TTE_IS_W_OK(tte)    ((tte) & TTE_W_OK_BIT)
 #define TTE_IS_GLOBAL(tte)  ((tte) & TTE_GLOBAL_BIT)
 
 #define TTE_SET_USED(tte)   ((tte) |= TTE_USED_BIT)
 #define TTE_SET_UNUSED(tte) ((tte) &= ~TTE_USED_BIT)
 
+#define TTE_PGSIZE(tte)     (((tte) >> 61) & 3ULL)
+#define TTE_PA(tte)         ((tte) & 0x1ffffffe000ULL)
+
 typedef struct SparcTLBEntry {
     uint64_t tag;
     uint64_t tte;
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 7eea1ac..0a4cfc5 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -378,7 +378,7 @@ static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
 {
     uint64_t mask;
 
-    switch ((tlb->tte >> 61) & 3) {
+    switch (TTE_PGSIZE(tlb->tte)) {
     default:
     case 0x0: // 8k
         mask = 0xffffffffffffe000ULL;
@@ -445,14 +445,14 @@ static int get_physical_address_data(CPUState *env,
             uint8_t fault_type = 0;
 
             // access ok?
-            if ((env->dtlb[i].tte & 0x4) && is_user) {
+            if (TTE_IS_PRIV(env->dtlb[i].tte) && is_user) {
                 fault_type |= 1; /* privilege violation */
                 env->exception_index = TT_DFAULT;
 
                 DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
                             " mmu_idx=%d tl=%d\n",
                             address, context, mmu_idx, env->tl);
-            } else if (!(env->dtlb[i].tte & 0x2) && (rw == 1)) {
+            } else if (!TTE_IS_W_OK(env->dtlb[i].tte) && (rw == 1)) {
                 env->exception_index = TT_DPROT;
 
                 DPRINTF_MMU("DPROT at %" PRIx64 " context %" PRIx64
@@ -460,8 +460,9 @@ static int get_physical_address_data(CPUState *env,
                             address, context, mmu_idx, env->tl);
             } else {
                 *prot = PAGE_READ;
-                if (env->dtlb[i].tte & 0x2)
+                if (TTE_IS_W_OK(env->dtlb[i].tte)) {
                     *prot |= PAGE_WRITE;
+                }
 
                 TTE_SET_USED(env->dtlb[i].tte);
 
@@ -522,7 +523,7 @@ static int get_physical_address_code(CPUState *env,
         if (ultrasparc_tag_match(&env->itlb[i],
                                  address, context, physical)) {
             // access ok?
-            if ((env->itlb[i].tte & 0x4) && is_user) {
+            if (TTE_IS_PRIV(env->itlb[i].tte) && is_user) {
                 if (env->immu.sfsr) /* Fault status register */
                     env->immu.sfsr = 2; /* overflow (not read before
                                              another fault) */
@@ -632,7 +633,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
     } else {
         (*cpu_fprintf)(f, "DMMU dump\n");
         for (i = 0; i < 64; i++) {
-            switch ((env->dtlb[i].tte >> 61) & 3) {
+            switch (TTE_PGSIZE(env->dtlb[i].tte)) {
             default:
             case 0x0:
                 mask = "  8k";
@@ -647,16 +648,17 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
                 mask = "  4M";
                 break;
             }
-            if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
+            if (TTE_IS_VALID(env->dtlb[i].tte)) {
                 (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
                                ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
                                i,
                                env->dtlb[i].tag & (uint64_t)~0x1fffULL,
-                               env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
+                               TTE_PA(env->dtlb[i].tte),
                                mask,
-                               env->dtlb[i].tte & 0x4? "priv": "user",
-                               env->dtlb[i].tte & 0x2? "RW": "RO",
-                               env->dtlb[i].tte & 0x40? "locked": "unlocked",
+                               TTE_IS_PRIV(env->dtlb[i].tte) ? "priv" : "user",
+                               TTE_IS_W_OK(env->dtlb[i].tte) ? "RW" : "RO",
+                               TTE_IS_LOCKED(env->dtlb[i].tte) ?
+                               "locked" : "unlocked",
                                env->dtlb[i].tag & (uint64_t)0x1fffULL,
                                TTE_IS_GLOBAL(env->dtlb[i].tte)?
                                "global" : "local");
@@ -668,7 +670,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
     } else {
         (*cpu_fprintf)(f, "IMMU dump\n");
         for (i = 0; i < 64; i++) {
-            switch ((env->itlb[i].tte >> 61) & 3) {
+            switch (TTE_PGSIZE(env->itlb[i].tte)) {
             default:
             case 0x0:
                 mask = "  8k";
@@ -683,15 +685,16 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
                 mask = "  4M";
                 break;
             }
-            if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
+            if (TTE_IS_VALID(env->itlb[i].tte)) {
                 (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
                                ", %s, %s, %s, ctx %" PRId64 " %s\n",
                                i,
                                env->itlb[i].tag & (uint64_t)~0x1fffULL,
-                               env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
+                               TTE_PA(env->itlb[i].tte),
                                mask,
-                               env->itlb[i].tte & 0x4? "priv": "user",
-                               env->itlb[i].tte & 0x40? "locked": "unlocked",
+                               TTE_IS_PRIV(env->itlb[i].tte) ? "priv" : "user",
+                               TTE_IS_LOCKED(env->itlb[i].tte) ?
+                               "locked" : "unlocked",
                                env->itlb[i].tag & (uint64_t)0x1fffULL,
                                TTE_IS_GLOBAL(env->itlb[i].tte)?
                                "global" : "local");
commit e3d4d25206a13ca48936e4357a53591997ce6d57
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 15:41:55 2011 -0500

    guest agent: add guest agent RPCs/commands
    
    This adds the initial set of QMP/QAPI commands provided by the guest
    agent:
    
    guest-sync
    guest-ping
    guest-info
    guest-shutdown
    guest-file-open
    guest-file-read
    guest-file-write
    guest-file-seek
    guest-file-flush
    guest-file-close
    guest-fsfreeze-freeze
    guest-fsfreeze-thaw
    guest-fsfreeze-status
    
    The input/output specification for these commands are documented in the
    schema.
    
    Example usage:
    
      host:
        qemu -device virtio-serial \
             -chardev socket,path=/tmp/vs0.sock,server,nowait,id=qga0 \
             -device virtserialport,chardev=qga0,name=org.qemu.quest_agent.0
             ...
    
        echo "{'execute':'guest-info'}" | socat stdio unix-connect:/tmp/qga0.sock
    
      guest:
        qemu-ga -m virtio-serial -p /dev/virtio-ports/org.qemu.guest_agent.0 \
                -p /var/run/qemu-guest-agent.pid -d
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/Makefile b/Makefile
index 0d2e33d..f3a03ad 100644
--- a/Makefile
+++ b/Makefile
@@ -164,7 +164,7 @@ check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjs
 
 $(qapi-obj-y): $(GENERATED_HEADERS)
 qapi-dir := qapi-generated
-test-visitor.o test-qmp-commands.o: QEMU_CFLAGS += -I $(qapi-dir)
+test-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
 $(qapi-dir)/test-qapi-types.h: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
@@ -176,15 +176,25 @@ $(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
 	    $(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
+	$(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
+	$(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "qga-" < $<, "  GEN   $@")
+$(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   $@")
+
 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 qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(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 qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
 
-QGALIB=qga/guest-agent-command-state.o
+QGALIB=qga/guest-agent-command-state.o qga/guest-agent-commands.o
 
-qemu-ga$(EXESUF): qemu-ga.o $(QGALIB) qemu-tool.o qemu-error.o error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) $(qapi-obj-y) qemu-timer-common.o qemu-sockets.o module.o qapi/qmp-dispatch.o qapi/qmp-registry.o
+qemu-ga.o: $(addprefix $(qapi-dir)/, qga-qapi-types.c qga-qapi-types.h qga-qapi-visit.c qga-qmp-marshal.c) $(qapi-obj-y)
+qemu-ga$(EXESUF): qemu-ga.o $(QGALIB) qemu-tool.o qemu-error.o error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) $(qapi-obj-y) qemu-timer-common.o qemu-sockets.o module.o qapi/qmp-dispatch.o qapi/qmp-registry.o $(qapi-dir)/qga-qapi-visit.o $(qapi-dir)/qga-qapi-types.o $(qapi-dir)/qga-qmp-marshal.o
 
 QEMULIBS=libhw32 libhw64 libuser libdis libdis-user
 
diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json
new file mode 100644
index 0000000..fde5971
--- /dev/null
+++ b/qapi-schema-guest.json
@@ -0,0 +1,217 @@
+# *-*- Mode: Python -*-*
+
+##
+# @guest-sync:
+#
+# Echo back a unique integer value
+#
+# This is used by clients talking to the guest agent over the
+# wire to ensure the stream is in sync and doesn't contain stale
+# data from previous client. All guest agent responses should be
+# ignored until the provided unique integer value is returned,
+# and it is up to the client to handle stale whole or
+# partially-delivered JSON text in such a way that this response
+# can be obtained.
+#
+# Such clients should also preceed this command
+# with a 0xFF byte to make such the guest agent flushes any
+# partially read JSON data from a previous session.
+#
+# @id: randomly generated 64-bit integer
+#
+# Returns: The unique integer id passed in by the client
+#
+# Since: 0.15.0
+##
+{ 'command': 'guest-sync'
+  'data':    { 'id': 'int' },
+  'returns': 'int' }
+
+##
+# @guest-ping:
+#
+# Ping the guest agent, a non-error return implies success
+#
+# Since: 0.15.0
+##
+{ 'command': 'guest-ping' }
+
+##
+# @guest-info:
+#
+# Get some information about the guest agent.
+#
+# Since: 0.15.0
+##
+{ 'type': 'GuestAgentInfo', 'data': {'version': 'str'} }
+{ 'command': 'guest-info',
+  'returns': 'GuestAgentInfo' }
+
+##
+# @guest-shutdown:
+#
+# Initiate guest-activated shutdown. Note: this is an asynchronous
+# shutdown request, with no guaruntee of successful shutdown. Errors
+# will be logged to guest's syslog.
+#
+# @mode: #optional "halt", "powerdown" (default), or "reboot"
+#
+# Returns: Nothing on success
+#
+# Since: 0.15.0
+##
+{ 'command': 'guest-shutdown', 'data': { '*mode': 'str' } }
+
+##
+# @guest-file-open:
+#
+# Open a file in the guest and retrieve a file handle for it
+#
+# @filepath: Full path to the file in the guest to open.
+#
+# @mode: #optional open mode, as per fopen(), "r" is the default.
+#
+# Returns: Guest file handle on success.
+#
+# Since: 0.15.0
+##
+{ 'command': 'guest-file-open',
+  'data':    { 'path': 'str', '*mode': 'str' },
+  'returns': 'int' }
+
+##
+# @guest-file-close:
+#
+# Close an open file in the guest
+#
+# @handle: filehandle returned by guest-file-open
+#
+# Returns: Nothing on success.
+#
+# Since: 0.15.0
+##
+{ 'command': 'guest-file-close',
+  'data': { 'handle': 'int' } }
+
+##
+# @guest-file-read:
+#
+# Read from an open file in the guest. Data will be base64-encoded
+#
+# @handle: filehandle returned by guest-file-open
+#
+# @count: #optional maximum number of bytes to read (default is 4KB)
+#
+# Returns: GuestFileRead on success. Note: count is number of bytes read
+#          *before* base64 encoding bytes read.
+#
+# Since: 0.15.0
+##
+{ 'type': 'GuestFileRead',
+  'data': { 'count': 'int', 'buf-b64': 'str', 'eof': 'bool' } }
+
+{ 'command': 'guest-file-read',
+  'data':    { 'handle': 'int', '*count': 'int' },
+  'returns': 'GuestFileRead' }
+
+##
+# @guest-file-write:
+#
+# Write to an open file in the guest.
+#
+# @handle: filehandle returned by guest-file-open
+#
+# @buf-b64: base64-encoded string representing data to be written
+#
+# @count: #optional bytes to write (actual bytes, after base64-decode),
+#         default is all content in buf-b64 buffer after base64 decoding
+#
+# Returns: GuestFileWrite on success. Note: count is the number of bytes
+#          base64-decoded bytes written
+#
+# Since: 0.15.0
+##
+{ 'type': 'GuestFileWrite',
+  'data': { 'count': 'int', 'eof': 'bool' } }
+{ 'command': 'guest-file-write',
+  'data':    { 'handle': 'int', 'buf-b64': 'str', '*count': 'int' },
+  'returns': 'GuestFileWrite' }
+
+##
+# @guest-file-seek:
+#
+# Seek to a position in the file, as with fseek(), and return the
+# current file position afterward. Also encapsulates ftell()'s
+# functionality, just Set offset=0, whence=SEEK_CUR.
+#
+# @handle: filehandle returned by guest-file-open
+#
+# @offset: bytes to skip over in the file stream
+#
+# @whence: SEEK_SET, SEEK_CUR, or SEEK_END, as with fseek()
+#
+# Returns: GuestFileSeek on success.
+#
+# Since: 0.15.0
+##
+{ 'type': 'GuestFileSeek',
+  'data': { 'position': 'int', 'eof': 'bool' } }
+
+{ 'command': 'guest-file-seek',
+  'data':    { 'handle': 'int', 'offset': 'int', 'whence': 'int' },
+  'returns': 'GuestFileSeek' }
+
+##
+# @guest-file-flush:
+#
+# Write file changes bufferred in userspace to disk/kernel buffers
+#
+# @handle: filehandle returned by guest-file-open
+#
+# Returns: Nothing on success.
+#
+# Since: 0.15.0
+##
+{ 'command': 'guest-file-flush',
+  'data': { 'handle': 'int' } }
+
+##
+# @guest-fsfreeze-status:
+#
+# Get guest fsfreeze state. error state indicates failure to thaw 1 or more
+# previously frozen filesystems, or failure to open a previously cached
+# filesytem (filesystem unmounted/directory changes, etc).
+#
+# Returns: GuestFsfreezeStatus ("thawed", "frozen", etc., as defined below)
+#
+# Since: 0.15.0
+##
+{ 'enum': 'GuestFsfreezeStatus',
+  'data': [ 'thawed', 'frozen', 'error' ] }
+{ 'command': 'guest-fsfreeze-status',
+  'returns': 'GuestFsfreezeStatus' }
+
+##
+# @guest-fsfreeze-freeze:
+#
+# Sync and freeze all non-network guest filesystems
+#
+# Returns: Number of file systems frozen on success
+#
+# Since: 0.15.0
+##
+{ 'command': 'guest-fsfreeze-freeze',
+  'returns': 'int' }
+
+##
+# @guest-fsfreeze-thaw:
+#
+# Unfreeze frozen guest fileystems
+#
+# Returns: Number of file systems thawed
+#          If error, -1 (unknown error) or -errno
+#
+# Since: 0.15.0
+##
+{ 'command': 'guest-fsfreeze-thaw',
+  'returns': 'int' }
diff --git a/qemu-ga.c b/qemu-ga.c
index 1f3585c..6e2f61f 100644
--- a/qemu-ga.c
+++ b/qemu-ga.c
@@ -636,6 +636,9 @@ int main(int argc, char **argv)
     g_log_set_default_handler(ga_log, s);
     g_log_set_fatal_mask(NULL, G_LOG_LEVEL_ERROR);
     s->logging_enabled = true;
+    s->command_state = ga_command_state_new();
+    ga_command_state_init(s, s->command_state);
+    ga_command_state_init_all(s->command_state);
     ga_state = s;
 
     module_call_init(MODULE_INIT_QAPI);
@@ -644,6 +647,7 @@ int main(int argc, char **argv)
 
     g_main_loop_run(ga_state->main_loop);
 
+    ga_command_state_cleanup_all(ga_state->command_state);
     unlink(pidfile);
 
     return 0;
diff --git a/qerror.c b/qerror.c
index c92adfc..229d0d6 100644
--- a/qerror.c
+++ b/qerror.c
@@ -218,6 +218,14 @@ static const QErrorStringTable qerror_table[] = {
         .error_fmt = QERR_VNC_SERVER_FAILED,
         .desc      = "Could not start VNC server on %(target)",
     },
+    {
+        .error_fmt = QERR_QGA_LOGGING_FAILED,
+        .desc      = "Guest agent failed to log non-optional log statement",
+    },
+    {
+        .error_fmt = QERR_QGA_COMMAND_FAILED,
+        .desc      = "Guest agent command failed, error was '%(message)'",
+    },
     {}
 };
 
diff --git a/qerror.h b/qerror.h
index 9a9fa5b..7ec0fc1 100644
--- a/qerror.h
+++ b/qerror.h
@@ -184,4 +184,10 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_FEATURE_DISABLED \
     "{ 'class': 'FeatureDisabled', 'data': { 'name': %s } }"
 
+#define QERR_QGA_LOGGING_FAILED \
+    "{ 'class': 'QgaLoggingFailed', 'data': {} }"
+
+#define QERR_QGA_COMMAND_FAILED \
+    "{ 'class': 'QgaCommandFailed', 'data': { 'message': %s } }"
+
 #endif /* QERROR_H */
diff --git a/qga/guest-agent-commands.c b/qga/guest-agent-commands.c
new file mode 100644
index 0000000..8c0d67e
--- /dev/null
+++ b/qga/guest-agent-commands.c
@@ -0,0 +1,518 @@
+/*
+ * QEMU Guest Agent commands
+ *
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ *  Michael Roth      <mdroth at linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+#include <mntent.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#include "qga/guest-agent-core.h"
+#include "qga-qmp-commands.h"
+#include "qerror.h"
+#include "qemu-queue.h"
+
+static GAState *ga_state;
+
+static void disable_logging(void)
+{
+    ga_disable_logging(ga_state);
+}
+
+static void enable_logging(void)
+{
+    ga_enable_logging(ga_state);
+}
+
+/* Note: in some situations, like with the fsfreeze, logging may be
+ * temporarilly disabled. if it is necessary that a command be able
+ * to log for accounting purposes, check ga_logging_enabled() beforehand,
+ * and use the QERR_QGA_LOGGING_DISABLED to generate an error
+ */
+static void slog(const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    g_logv("syslog", G_LOG_LEVEL_INFO, fmt, ap);
+    va_end(ap);
+}
+
+int64_t qmp_guest_sync(int64_t id, Error **errp)
+{
+    return id;
+}
+
+void qmp_guest_ping(Error **err)
+{
+    slog("guest-ping called");
+}
+
+struct GuestAgentInfo *qmp_guest_info(Error **err)
+{
+    GuestAgentInfo *info = qemu_mallocz(sizeof(GuestAgentInfo));
+
+    info->version = g_strdup(QGA_VERSION);
+
+    return info;
+}
+
+void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
+{
+    int ret;
+    const char *shutdown_flag;
+
+    slog("guest-shutdown called, mode: %s", mode);
+    if (!has_mode || strcmp(mode, "powerdown") == 0) {
+        shutdown_flag = "-P";
+    } else if (strcmp(mode, "halt") == 0) {
+        shutdown_flag = "-H";
+    } else if (strcmp(mode, "reboot") == 0) {
+        shutdown_flag = "-r";
+    } else {
+        error_set(err, QERR_INVALID_PARAMETER_VALUE, "mode",
+                  "halt|powerdown|reboot");
+        return;
+    }
+
+    ret = fork();
+    if (ret == 0) {
+        /* child, start the shutdown */
+        setsid();
+        fclose(stdin);
+        fclose(stdout);
+        fclose(stderr);
+
+        ret = execl("/sbin/shutdown", "shutdown", shutdown_flag, "+0",
+                    "hypervisor initiated shutdown", (char*)NULL);
+        if (ret) {
+            slog("guest-shutdown failed: %s", strerror(errno));
+        }
+        exit(!!ret);
+    } else if (ret < 0) {
+        error_set(err, QERR_UNDEFINED_ERROR);
+    }
+}
+
+typedef struct GuestFileHandle {
+    uint64_t id;
+    FILE *fh;
+    QTAILQ_ENTRY(GuestFileHandle) next;
+} GuestFileHandle;
+
+static struct {
+    QTAILQ_HEAD(, GuestFileHandle) filehandles;
+} guest_file_state;
+
+static void guest_file_handle_add(FILE *fh)
+{
+    GuestFileHandle *gfh;
+
+    gfh = qemu_mallocz(sizeof(GuestFileHandle));
+    gfh->id = fileno(fh);
+    gfh->fh = fh;
+    QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next);
+}
+
+static GuestFileHandle *guest_file_handle_find(int64_t id)
+{
+    GuestFileHandle *gfh;
+
+    QTAILQ_FOREACH(gfh, &guest_file_state.filehandles, next)
+    {
+        if (gfh->id == id) {
+            return gfh;
+        }
+    }
+
+    return NULL;
+}
+
+int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, Error **err)
+{
+    FILE *fh;
+    int fd;
+    int64_t ret = -1;
+
+    if (!has_mode) {
+        mode = "r";
+    }
+    slog("guest-file-open called, filepath: %s, mode: %s", path, mode);
+    fh = fopen(path, mode);
+    if (!fh) {
+        error_set(err, QERR_OPEN_FILE_FAILED, path);
+        return -1;
+    }
+
+    /* set fd non-blocking to avoid common use cases (like reading from a
+     * named pipe) from hanging the agent
+     */
+    fd = fileno(fh);
+    ret = fcntl(fd, F_GETFL);
+    ret = fcntl(fd, F_SETFL, ret | O_NONBLOCK);
+    if (ret == -1) {
+        error_set(err, QERR_QGA_COMMAND_FAILED, "fcntl() failed");
+        fclose(fh);
+        return -1;
+    }
+
+    guest_file_handle_add(fh);
+    slog("guest-file-open, handle: %d", fd);
+    return fd;
+}
+
+void qmp_guest_file_close(int64_t handle, Error **err)
+{
+    GuestFileHandle *gfh = guest_file_handle_find(handle);
+    int ret;
+
+    slog("guest-file-close called, handle: %ld", handle);
+    if (!gfh) {
+        error_set(err, QERR_FD_NOT_FOUND, "handle");
+        return;
+    }
+
+    ret = fclose(gfh->fh);
+    if (ret == -1) {
+        error_set(err, QERR_QGA_COMMAND_FAILED, "fclose() failed");
+        return;
+    }
+
+    QTAILQ_REMOVE(&guest_file_state.filehandles, gfh, next);
+    qemu_free(gfh);
+}
+
+struct GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count,
+                                          int64_t count, Error **err)
+{
+    GuestFileHandle *gfh = guest_file_handle_find(handle);
+    GuestFileRead *read_data = NULL;
+    guchar *buf;
+    FILE *fh;
+    size_t read_count;
+
+    if (!gfh) {
+        error_set(err, QERR_FD_NOT_FOUND, "handle");
+        return NULL;
+    }
+
+    if (!has_count) {
+        count = QGA_READ_COUNT_DEFAULT;
+    } else if (count < 0) {
+        error_set(err, QERR_INVALID_PARAMETER, "count");
+        return NULL;
+    }
+
+    fh = gfh->fh;
+    buf = qemu_mallocz(count+1);
+    read_count = fread(buf, 1, count, fh);
+    if (ferror(fh)) {
+        slog("guest-file-read failed, handle: %ld", handle);
+        error_set(err, QERR_QGA_COMMAND_FAILED, "fread() failed");
+    } else {
+        buf[read_count] = 0;
+        read_data = qemu_mallocz(sizeof(GuestFileRead));
+        read_data->count = read_count;
+        read_data->eof = feof(fh);
+        if (read_count) {
+            read_data->buf_b64 = g_base64_encode(buf, read_count);
+        }
+    }
+    qemu_free(buf);
+    clearerr(fh);
+
+    return read_data;
+}
+
+GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64,
+                                     bool has_count, int64_t count, Error **err)
+{
+    GuestFileWrite *write_data = NULL;
+    guchar *buf;
+    gsize buf_len;
+    int write_count;
+    GuestFileHandle *gfh = guest_file_handle_find(handle);
+    FILE *fh;
+
+    if (!gfh) {
+        error_set(err, QERR_FD_NOT_FOUND, "handle");
+        return NULL;
+    }
+
+    fh = gfh->fh;
+    buf = g_base64_decode(buf_b64, &buf_len);
+
+    if (!has_count) {
+        count = buf_len;
+    } else if (count < 0 || count > buf_len) {
+        qemu_free(buf);
+        error_set(err, QERR_INVALID_PARAMETER, "count");
+        return NULL;
+    }
+
+    write_count = fwrite(buf, 1, count, fh);
+    if (ferror(fh)) {
+        slog("guest-file-write failed, handle: %ld", handle);
+        error_set(err, QERR_QGA_COMMAND_FAILED, "fwrite() error");
+    } else {
+        write_data = qemu_mallocz(sizeof(GuestFileWrite));
+        write_data->count = write_count;
+        write_data->eof = feof(fh);
+    }
+    qemu_free(buf);
+    clearerr(fh);
+
+    return write_data;
+}
+
+struct GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset,
+                                          int64_t whence, Error **err)
+{
+    GuestFileHandle *gfh = guest_file_handle_find(handle);
+    GuestFileSeek *seek_data = NULL;
+    FILE *fh;
+    int ret;
+
+    if (!gfh) {
+        error_set(err, QERR_FD_NOT_FOUND, "handle");
+        return NULL;
+    }
+
+    fh = gfh->fh;
+    ret = fseek(fh, offset, whence);
+    if (ret == -1) {
+        error_set(err, QERR_QGA_COMMAND_FAILED, strerror(errno));
+    } else {
+        seek_data = qemu_mallocz(sizeof(GuestFileRead));
+        seek_data->position = ftell(fh);
+        seek_data->eof = feof(fh);
+    }
+    clearerr(fh);
+
+    return seek_data;
+}
+
+void qmp_guest_file_flush(int64_t handle, Error **err)
+{
+    GuestFileHandle *gfh = guest_file_handle_find(handle);
+    FILE *fh;
+    int ret;
+
+    if (!gfh) {
+        error_set(err, QERR_FD_NOT_FOUND, "handle");
+        return;
+    }
+
+    fh = gfh->fh;
+    ret = fflush(fh);
+    if (ret == EOF) {
+        error_set(err, QERR_QGA_COMMAND_FAILED, strerror(errno));
+    }
+}
+
+static void guest_file_init(void)
+{
+    QTAILQ_INIT(&guest_file_state.filehandles);
+}
+
+typedef struct GuestFsfreezeMount {
+    char *dirname;
+    char *devtype;
+    QTAILQ_ENTRY(GuestFsfreezeMount) next;
+} GuestFsfreezeMount;
+
+struct {
+    GuestFsfreezeStatus status;
+    QTAILQ_HEAD(, GuestFsfreezeMount) mount_list;
+} guest_fsfreeze_state;
+
+/*
+ * Walk the mount table and build a list of local file systems
+ */
+static int guest_fsfreeze_build_mount_list(void)
+{
+    struct mntent *ment;
+    GuestFsfreezeMount *mount, *temp;
+    char const *mtab = MOUNTED;
+    FILE *fp;
+
+    QTAILQ_FOREACH_SAFE(mount, &guest_fsfreeze_state.mount_list, next, temp) {
+        QTAILQ_REMOVE(&guest_fsfreeze_state.mount_list, mount, next);
+        qemu_free(mount->dirname);
+        qemu_free(mount->devtype);
+        qemu_free(mount);
+    }
+
+    fp = setmntent(mtab, "r");
+    if (!fp) {
+        g_warning("fsfreeze: unable to read mtab");
+        return -1;
+    }
+
+    while ((ment = getmntent(fp))) {
+        /*
+         * An entry which device name doesn't start with a '/' is
+         * either a dummy file system or a network file system.
+         * Add special handling for smbfs and cifs as is done by
+         * coreutils as well.
+         */
+        if ((ment->mnt_fsname[0] != '/') ||
+            (strcmp(ment->mnt_type, "smbfs") == 0) ||
+            (strcmp(ment->mnt_type, "cifs") == 0)) {
+            continue;
+        }
+
+        mount = qemu_mallocz(sizeof(GuestFsfreezeMount));
+        mount->dirname = qemu_strdup(ment->mnt_dir);
+        mount->devtype = qemu_strdup(ment->mnt_type);
+
+        QTAILQ_INSERT_TAIL(&guest_fsfreeze_state.mount_list, mount, next);
+    }
+
+    endmntent(fp);
+
+    return 0;
+}
+
+/*
+ * Return status of freeze/thaw
+ */
+GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
+{
+    return guest_fsfreeze_state.status;
+}
+
+/*
+ * Walk list of mounted file systems in the guest, and freeze the ones which
+ * are real local file systems.
+ */
+int64_t qmp_guest_fsfreeze_freeze(Error **err)
+{
+    int ret = 0, i = 0;
+    struct GuestFsfreezeMount *mount, *temp;
+    int fd;
+    char err_msg[512];
+
+    slog("guest-fsfreeze called");
+
+    if (guest_fsfreeze_state.status == GUEST_FSFREEZE_STATUS_FROZEN) {
+        return 0;
+    }
+
+    ret = guest_fsfreeze_build_mount_list();
+    if (ret < 0) {
+        return ret;
+    }
+
+    /* cannot risk guest agent blocking itself on a write in this state */
+    disable_logging();
+
+    QTAILQ_FOREACH_SAFE(mount, &guest_fsfreeze_state.mount_list, next, temp) {
+        fd = qemu_open(mount->dirname, O_RDONLY);
+        if (fd == -1) {
+            sprintf(err_msg, "failed to open %s, %s", mount->dirname, strerror(errno));
+            error_set(err, QERR_QGA_COMMAND_FAILED, err_msg);
+            goto error;
+        }
+
+        /* we try to cull filesytems we know won't work in advance, but other
+         * filesytems may not implement fsfreeze for less obvious reasons.
+         * these will report EOPNOTSUPP, so we simply ignore them. when
+         * thawing, these filesystems will return an EINVAL instead, due to
+         * not being in a frozen state. Other filesystem-specific
+         * errors may result in EINVAL, however, so the user should check the
+         * number * of filesystems returned here against those returned by the
+         * thaw operation to determine whether everything completed
+         * successfully
+         */
+        ret = ioctl(fd, FIFREEZE);
+        if (ret < 0 && errno != EOPNOTSUPP) {
+            sprintf(err_msg, "failed to freeze %s, %s", mount->dirname, strerror(errno));
+            error_set(err, QERR_QGA_COMMAND_FAILED, err_msg);
+            close(fd);
+            goto error;
+        }
+        close(fd);
+
+        i++;
+    }
+
+    guest_fsfreeze_state.status = GUEST_FSFREEZE_STATUS_FROZEN;
+    return i;
+
+error:
+    if (i > 0) {
+        qmp_guest_fsfreeze_thaw(NULL);
+    }
+    return 0;
+}
+
+/*
+ * Walk list of frozen file systems in the guest, and thaw them.
+ */
+int64_t qmp_guest_fsfreeze_thaw(Error **err)
+{
+    int ret;
+    GuestFsfreezeMount *mount, *temp;
+    int fd, i = 0;
+    bool has_error = false;
+
+    QTAILQ_FOREACH_SAFE(mount, &guest_fsfreeze_state.mount_list, next, temp) {
+        fd = qemu_open(mount->dirname, O_RDONLY);
+        if (fd == -1) {
+            has_error = true;
+            continue;
+        }
+        ret = ioctl(fd, FITHAW);
+        if (ret < 0 && errno != EOPNOTSUPP && errno != EINVAL) {
+            has_error = true;
+            close(fd);
+            continue;
+        }
+        close(fd);
+        i++;
+    }
+
+    if (has_error) {
+        guest_fsfreeze_state.status = GUEST_FSFREEZE_STATUS_ERROR;
+    } else {
+        guest_fsfreeze_state.status = GUEST_FSFREEZE_STATUS_THAWED;
+    }
+    enable_logging();
+    return i;
+}
+
+static void guest_fsfreeze_init(void)
+{
+    guest_fsfreeze_state.status = GUEST_FSFREEZE_STATUS_THAWED;
+    QTAILQ_INIT(&guest_fsfreeze_state.mount_list);
+}
+
+static void guest_fsfreeze_cleanup(void)
+{
+    int64_t ret;
+    Error *err = NULL;
+
+    if (guest_fsfreeze_state.status == GUEST_FSFREEZE_STATUS_FROZEN) {
+        ret = qmp_guest_fsfreeze_thaw(&err);
+        if (ret < 0 || err) {
+            slog("failed to clean up frozen filesystems");
+        }
+    }
+}
+
+/* register init/cleanup routines for stateful command groups */
+void ga_command_state_init(GAState *s, GACommandState *cs)
+{
+    ga_state = s;
+    ga_command_state_add(cs, guest_fsfreeze_init, guest_fsfreeze_cleanup);
+    ga_command_state_add(cs, guest_file_init, NULL);
+}
diff --git a/qga/guest-agent-core.h b/qga/guest-agent-core.h
index 66d1729..e42b91d 100644
--- a/qga/guest-agent-core.h
+++ b/qga/guest-agent-core.h
@@ -14,10 +14,12 @@
 #include "qemu-common.h"
 
 #define QGA_VERSION "1.0"
+#define QGA_READ_COUNT_DEFAULT 4 << 10
 
 typedef struct GAState GAState;
 typedef struct GACommandState GACommandState;
 
+void ga_command_state_init(GAState *s, GACommandState *cs);
 void ga_command_state_add(GACommandState *cs,
                           void (*init)(void),
                           void (*cleanup)(void));
commit 48ff7a625b3611d075d8798585df86455bb2d1fd
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Wed Jul 20 15:19:37 2011 -0500

    guest agent: qemu-ga daemon
    
    This is the actual guest daemon, it listens for requests over a
    virtio-serial/isa-serial/unix socket channel and routes them through
    to dispatch routines, and writes the results back to the channel in
    a manner similar to QMP.
    
    A shorthand invocation:
    
      qemu-ga -d
    
    Is equivalent to:
    
      qemu-ga -m virtio-serial -p /dev/virtio-ports/org.qemu.guest_agent.0 \
              -f /var/run/qemu-ga.pid -d
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/Makefile b/Makefile
index b8cdf0e..0d2e33d 100644
--- a/Makefile
+++ b/Makefile
@@ -140,7 +140,7 @@ endif
 ######################################################################
 
 qemu-img.o: qemu-img-cmds.h
-qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o cmd.o: $(GENERATED_HEADERS)
+qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o cmd.o qemu-ga.o: $(GENERATED_HEADERS)
 
 qemu-img$(EXESUF): qemu-img.o qemu-tool.o qemu-error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o
 
@@ -184,13 +184,15 @@ test-qmp-commands: test-qmp-commands.o qfloat.o qint.o qdict.o qstring.o qlist.o
 
 QGALIB=qga/guest-agent-command-state.o
 
+qemu-ga$(EXESUF): qemu-ga.o $(QGALIB) qemu-tool.o qemu-error.o error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) $(qapi-obj-y) qemu-timer-common.o qemu-sockets.o module.o qapi/qmp-dispatch.o qapi/qmp-registry.o
+
 QEMULIBS=libhw32 libhw64 libuser libdis libdis-user
 
 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) 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
@@ -386,4 +388,4 @@ tarbin:
 	$(mandir)/man8/qemu-nbd.8
 
 # Include automatically generated dependency files
--include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d qapi/*.d)
+-include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d qapi/*.d qga/*.d)
diff --git a/configure b/configure
index 796f706..f9be709 100755
--- a/configure
+++ b/configure
@@ -2532,6 +2532,7 @@ if test "$softmmu" = yes ; then
   tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
   if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
       tools="qemu-nbd\$(EXESUF) $tools"
+      tools="qemu-ga\$(EXESUF) $tools"
     if [ "$check_utests" = "yes" ]; then
       tools="check-qint check-qstring check-qdict check-qlist $tools"
       tools="check-qfloat check-qjson $tools"
diff --git a/qemu-ga.c b/qemu-ga.c
new file mode 100644
index 0000000..1f3585c
--- /dev/null
+++ b/qemu-ga.c
@@ -0,0 +1,650 @@
+/*
+ * QEMU Guest Agent
+ *
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ *  Adam Litke        <aglitke at linux.vnet.ibm.com>
+ *  Michael Roth      <mdroth at linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <getopt.h>
+#include <termios.h>
+#include <syslog.h>
+#include "qemu_socket.h"
+#include "json-streamer.h"
+#include "json-parser.h"
+#include "qint.h"
+#include "qjson.h"
+#include "qga/guest-agent-core.h"
+#include "module.h"
+#include "signal.h"
+#include "qerror.h"
+#include "error_int.h"
+
+#define QGA_VIRTIO_PATH_DEFAULT "/dev/virtio-ports/org.qemu.guest_agent.0"
+#define QGA_PIDFILE_DEFAULT "/var/run/qemu-ga.pid"
+#define QGA_BAUDRATE_DEFAULT B38400 /* for isa-serial channels */
+#define QGA_TIMEOUT_DEFAULT 30*1000 /* ms */
+
+struct GAState {
+    JSONMessageParser parser;
+    GMainLoop *main_loop;
+    GSocket *conn_sock;
+    GIOChannel *conn_channel;
+    GSocket *listen_sock;
+    GIOChannel *listen_channel;
+    const char *path;
+    const char *method;
+    bool virtio; /* fastpath to check for virtio to deal with poll() quirks */
+    GACommandState *command_state;
+    GLogLevelFlags log_level;
+    FILE *log_file;
+    bool logging_enabled;
+};
+
+static struct GAState *ga_state;
+
+static void quit_handler(int sig)
+{
+    g_debug("recieved signal num %d, quitting", sig);
+
+    if (g_main_loop_is_running(ga_state->main_loop)) {
+        g_main_loop_quit(ga_state->main_loop);
+    }
+}
+
+static void register_signal_handlers(void)
+{
+    struct sigaction sigact;
+    int ret;
+
+    memset(&sigact, 0, sizeof(struct sigaction));
+    sigact.sa_handler = quit_handler;
+
+    ret = sigaction(SIGINT, &sigact, NULL);
+    if (ret == -1) {
+        g_error("error configuring signal handler: %s", strerror(errno));
+        exit(EXIT_FAILURE);
+    }
+    ret = sigaction(SIGTERM, &sigact, NULL);
+    if (ret == -1) {
+        g_error("error configuring signal handler: %s", strerror(errno));
+    }
+}
+
+static void usage(const char *cmd)
+{
+    printf(
+"Usage: %s -c <channel_opts>\n"
+"QEMU Guest Agent %s\n"
+"\n"
+"  -m, --method      transport method: one of unix-listen, virtio-serial, or\n"
+"                    isa-serial (virtio-serial is the default)\n"
+"  -p, --path        device/socket path (%s is the default for virtio-serial)\n"
+"  -l, --logfile     set logfile path, logs to stderr by default\n"
+"  -f, --pidfile     specify pidfile (default is %s)\n"
+"  -v, --verbose     log extra debugging information\n"
+"  -V, --version     print version information and exit\n"
+"  -d, --daemonize   become a daemon\n"
+"  -h, --help        display this help and exit\n"
+"\n"
+"Report bugs to <mdroth at linux.vnet.ibm.com>\n"
+    , cmd, QGA_VERSION, QGA_VIRTIO_PATH_DEFAULT, QGA_PIDFILE_DEFAULT);
+}
+
+static void conn_channel_close(GAState *s);
+
+static const char *ga_log_level_str(GLogLevelFlags level)
+{
+    switch (level & G_LOG_LEVEL_MASK) {
+        case G_LOG_LEVEL_ERROR:
+            return "error";
+        case G_LOG_LEVEL_CRITICAL:
+            return "critical";
+        case G_LOG_LEVEL_WARNING:
+            return "warning";
+        case G_LOG_LEVEL_MESSAGE:
+            return "message";
+        case G_LOG_LEVEL_INFO:
+            return "info";
+        case G_LOG_LEVEL_DEBUG:
+            return "debug";
+        default:
+            return "user";
+    }
+}
+
+bool ga_logging_enabled(GAState *s)
+{
+    return s->logging_enabled;
+}
+
+void ga_disable_logging(GAState *s)
+{
+    s->logging_enabled = false;
+}
+
+void ga_enable_logging(GAState *s)
+{
+    s->logging_enabled = true;
+}
+
+static void ga_log(const gchar *domain, GLogLevelFlags level,
+                   const gchar *msg, gpointer opaque)
+{
+    GAState *s = opaque;
+    GTimeVal time;
+    const char *level_str = ga_log_level_str(level);
+
+    if (!ga_logging_enabled(s)) {
+        return;
+    }
+
+    level &= G_LOG_LEVEL_MASK;
+    if (g_strcmp0(domain, "syslog") == 0) {
+        syslog(LOG_INFO, "%s: %s", level_str, msg);
+    } else if (level & s->log_level) {
+        g_get_current_time(&time);
+        fprintf(s->log_file,
+                "%lu.%lu: %s: %s\n", time.tv_sec, time.tv_usec, level_str, msg);
+        fflush(s->log_file);
+    }
+}
+
+static void become_daemon(const char *pidfile)
+{
+    pid_t pid, sid;
+    int pidfd;
+    char *pidstr = NULL;
+
+    pid = fork();
+    if (pid < 0) {
+        exit(EXIT_FAILURE);
+    }
+    if (pid > 0) {
+        exit(EXIT_SUCCESS);
+    }
+
+    pidfd = open(pidfile, O_CREAT|O_WRONLY|O_EXCL, S_IRUSR|S_IWUSR);
+    if (pidfd == -1) {
+        g_critical("Cannot create pid file, %s", strerror(errno));
+        exit(EXIT_FAILURE);
+    }
+
+    if (asprintf(&pidstr, "%d", getpid()) == -1) {
+        g_critical("Cannot allocate memory");
+        goto fail;
+    }
+    if (write(pidfd, pidstr, strlen(pidstr)) != strlen(pidstr)) {
+        free(pidstr);
+        g_critical("Failed to write pid file");
+        goto fail;
+    }
+
+    umask(0);
+    sid = setsid();
+    if (sid < 0) {
+        goto fail;
+    }
+    if ((chdir("/")) < 0) {
+        goto fail;
+    }
+
+    close(STDIN_FILENO);
+    close(STDOUT_FILENO);
+    close(STDERR_FILENO);
+    free(pidstr);
+    return;
+
+fail:
+    unlink(pidfile);
+    g_critical("failed to daemonize");
+    exit(EXIT_FAILURE);
+}
+
+static int conn_channel_send_buf(GIOChannel *channel, const char *buf,
+                                 gsize count)
+{
+    GError *err = NULL;
+    gsize written = 0;
+    GIOStatus status;
+
+    while (count) {
+        status = g_io_channel_write_chars(channel, buf, count, &written, &err);
+        g_debug("sending data, count: %d", (int)count);
+        if (err != NULL) {
+            g_warning("error sending newline: %s", err->message);
+            return err->code;
+        }
+        if (status == G_IO_STATUS_ERROR || status == G_IO_STATUS_EOF) {
+            return -EPIPE;
+        }
+
+        if (status == G_IO_STATUS_NORMAL) {
+            count -= written;
+        }
+    }
+
+    return 0;
+}
+
+static int conn_channel_send_payload(GIOChannel *channel, QObject *payload)
+{
+    int ret = 0;
+    const char *buf;
+    QString *payload_qstr;
+    GError *err = NULL;
+
+    g_assert(payload && channel);
+
+    payload_qstr = qobject_to_json(payload);
+    if (!payload_qstr) {
+        return -EINVAL;
+    }
+
+    qstring_append_chr(payload_qstr, '\n');
+    buf = qstring_get_str(payload_qstr);
+    ret = conn_channel_send_buf(channel, buf, strlen(buf));
+    if (ret) {
+        goto out_free;
+    }
+
+    g_io_channel_flush(channel, &err);
+    if (err != NULL) {
+        g_warning("error flushing payload: %s", err->message);
+        ret = err->code;
+        goto out_free;
+    }
+
+out_free:
+    QDECREF(payload_qstr);
+    if (err) {
+        g_error_free(err);
+    }
+    return ret;
+}
+
+static void process_command(GAState *s, QDict *req)
+{
+    QObject *rsp = NULL;
+    int ret;
+
+    g_assert(req);
+    g_debug("processing command");
+    rsp = qmp_dispatch(QOBJECT(req));
+    if (rsp) {
+        ret = conn_channel_send_payload(s->conn_channel, rsp);
+        if (ret) {
+            g_warning("error sending payload: %s", strerror(ret));
+        }
+        qobject_decref(rsp);
+    } else {
+        g_warning("error getting response");
+    }
+}
+
+/* handle requests/control events coming in over the channel */
+static void process_event(JSONMessageParser *parser, QList *tokens)
+{
+    GAState *s = container_of(parser, GAState, parser);
+    QObject *obj;
+    QDict *qdict;
+    Error *err = NULL;
+    int ret;
+
+    g_assert(s && parser);
+
+    g_debug("process_event: called");
+    obj = json_parser_parse_err(tokens, NULL, &err);
+    if (err || !obj || qobject_type(obj) != QTYPE_QDICT) {
+        qobject_decref(obj);
+        qdict = qdict_new();
+        if (!err) {
+            g_warning("failed to parse event: unknown error");
+            error_set(&err, QERR_JSON_PARSING);
+        } else {
+            g_warning("failed to parse event: %s", error_get_pretty(err));
+        }
+        qdict_put_obj(qdict, "error", error_get_qobject(err));
+        error_free(err);
+    } else {
+        qdict = qobject_to_qdict(obj);
+    }
+
+    g_assert(qdict);
+
+    /* handle host->guest commands */
+    if (qdict_haskey(qdict, "execute")) {
+        process_command(s, qdict);
+    } else {
+        if (!qdict_haskey(qdict, "error")) {
+            QDECREF(qdict);
+            qdict = qdict_new();
+            g_warning("unrecognized payload format");
+            error_set(&err, QERR_UNSUPPORTED);
+            qdict_put_obj(qdict, "error", error_get_qobject(err));
+            error_free(err);
+        }
+        ret = conn_channel_send_payload(s->conn_channel, QOBJECT(qdict));
+        if (ret) {
+            g_warning("error sending payload: %s", strerror(ret));
+        }
+    }
+
+    QDECREF(qdict);
+}
+
+static gboolean conn_channel_read(GIOChannel *channel, GIOCondition condition,
+                                  gpointer data)
+{
+    GAState *s = data;
+    gchar buf[1024];
+    gsize count;
+    GError *err = NULL;
+    memset(buf, 0, 1024);
+    GIOStatus status = g_io_channel_read_chars(channel, buf, 1024,
+                                               &count, &err);
+    if (err != NULL) {
+        g_warning("error reading channel: %s", err->message);
+        conn_channel_close(s);
+        g_error_free(err);
+        return false;
+    }
+    switch (status) {
+    case G_IO_STATUS_ERROR:
+        g_warning("problem");
+        return false;
+    case G_IO_STATUS_NORMAL:
+        g_debug("read data, count: %d, data: %s", (int)count, buf);
+        json_message_parser_feed(&s->parser, (char *)buf, (int)count);
+    case G_IO_STATUS_AGAIN:
+        /* virtio causes us to spin here when no process is attached to
+         * host-side chardev. sleep a bit to mitigate this
+         */
+        if (s->virtio) {
+            usleep(100*1000);
+        }
+        return true;
+    case G_IO_STATUS_EOF:
+        g_debug("received EOF");
+        conn_channel_close(s);
+        if (s->virtio) {
+            return true;
+        }
+        return false;
+    default:
+        g_warning("unknown channel read status, closing");
+        conn_channel_close(s);
+        return false;
+    }
+    return true;
+}
+
+static int conn_channel_add(GAState *s, int fd)
+{
+    GIOChannel *conn_channel;
+    GError *err = NULL;
+
+    g_assert(s && !s->conn_channel);
+    conn_channel = g_io_channel_unix_new(fd);
+    g_assert(conn_channel);
+    g_io_channel_set_encoding(conn_channel, NULL, &err);
+    if (err != NULL) {
+        g_warning("error setting channel encoding to binary");
+        g_error_free(err);
+        return -1;
+    }
+    g_io_add_watch(conn_channel, G_IO_IN | G_IO_HUP,
+                   conn_channel_read, s);
+    s->conn_channel = conn_channel;
+    return 0;
+}
+
+static gboolean listen_channel_accept(GIOChannel *channel,
+                                      GIOCondition condition, gpointer data)
+{
+    GAState *s = data;
+    GError *err = NULL;
+    g_assert(channel != NULL);
+    int ret;
+    bool accepted = false;
+
+    s->conn_sock = g_socket_accept(s->listen_sock, NULL, &err);
+    if (err != NULL) {
+        g_warning("error converting fd to gsocket: %s", err->message);
+        g_error_free(err);
+        goto out;
+    }
+    ret = conn_channel_add(s, g_socket_get_fd(s->conn_sock));
+    if (ret) {
+        g_warning("error setting up connection");
+        goto out;
+    }
+    accepted = true;
+
+out:
+    /* only accept 1 connection at a time */
+    return !accepted;
+}
+
+/* start polling for readable events on listen fd, new==true
+ * indicates we should use the existing s->listen_channel
+ */
+static int listen_channel_add(GAState *s, int listen_fd, bool new)
+{
+    GError *err = NULL;
+
+    if (new) {
+        s->listen_channel = g_io_channel_unix_new(listen_fd);
+        if (s->listen_sock) {
+            g_object_unref(s->listen_sock);
+        }
+        s->listen_sock = g_socket_new_from_fd(listen_fd, &err);
+        if (err != NULL) {
+            g_warning("error converting fd to gsocket: %s", err->message);
+            g_error_free(err);
+            return -1;
+        }
+    }
+    g_io_add_watch(s->listen_channel, G_IO_IN,
+                   listen_channel_accept, s);
+    return 0;
+}
+
+/* cleanup state for closed connection/session, start accepting new
+ * connections if we're in listening mode
+ */
+static void conn_channel_close(GAState *s)
+{
+    if (strcmp(s->method, "unix-listen") == 0) {
+        g_io_channel_shutdown(s->conn_channel, true, NULL);
+        g_object_unref(s->conn_sock);
+        s->conn_sock = NULL;
+        listen_channel_add(s, 0, false);
+    } else if (strcmp(s->method, "virtio-serial") == 0) {
+        /* we spin on EOF for virtio-serial, so back off a bit. also,
+         * dont close the connection in this case, it'll resume normal
+         * operation when another process connects to host chardev
+         */
+        usleep(100*1000);
+        goto out_noclose;
+    }
+    g_io_channel_unref(s->conn_channel);
+    s->conn_channel = NULL;
+out_noclose:
+    return;
+}
+
+static void init_guest_agent(GAState *s)
+{
+    struct termios tio;
+    int ret, fd;
+
+    if (s->method == NULL) {
+        /* try virtio-serial as our default */
+        s->method = "virtio-serial";
+    }
+
+    if (s->path == NULL) {
+        if (strcmp(s->method, "virtio-serial") != 0) {
+            g_critical("must specify a path for this channel");
+            exit(EXIT_FAILURE);
+        }
+        /* try the default path for the virtio-serial port */
+        s->path = QGA_VIRTIO_PATH_DEFAULT;
+    }
+
+    if (strcmp(s->method, "virtio-serial") == 0) {
+        s->virtio = true;
+        fd = qemu_open(s->path, O_RDWR | O_NONBLOCK | O_ASYNC);
+        if (fd == -1) {
+            g_critical("error opening channel: %s", strerror(errno));
+            exit(EXIT_FAILURE);
+        }
+        ret = conn_channel_add(s, fd);
+        if (ret) {
+            g_critical("error adding channel to main loop");
+            exit(EXIT_FAILURE);
+        }
+    } else if (strcmp(s->method, "isa-serial") == 0) {
+        fd = qemu_open(s->path, O_RDWR | O_NOCTTY);
+        if (fd == -1) {
+            g_critical("error opening channel: %s", strerror(errno));
+            exit(EXIT_FAILURE);
+        }
+        tcgetattr(fd, &tio);
+        /* set up serial port for non-canonical, dumb byte streaming */
+        tio.c_iflag &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP |
+                         INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY |
+                         IMAXBEL);
+        tio.c_oflag = 0;
+        tio.c_lflag = 0;
+        tio.c_cflag |= QGA_BAUDRATE_DEFAULT;
+        /* 1 available byte min or reads will block (we'll set non-blocking
+         * elsewhere, else we have to deal with read()=0 instead)
+         */
+        tio.c_cc[VMIN] = 1;
+        tio.c_cc[VTIME] = 0;
+        /* flush everything waiting for read/xmit, it's garbage at this point */
+        tcflush(fd, TCIFLUSH);
+        tcsetattr(fd, TCSANOW, &tio);
+        ret = conn_channel_add(s, fd);
+        if (ret) {
+            g_error("error adding channel to main loop");
+        }
+    } else if (strcmp(s->method, "unix-listen") == 0) {
+        fd = unix_listen(s->path, NULL, strlen(s->path));
+        if (fd == -1) {
+            g_critical("error opening path: %s", strerror(errno));
+            exit(EXIT_FAILURE);
+        }
+        ret = listen_channel_add(s, fd, true);
+        if (ret) {
+            g_critical("error binding/listening to specified socket");
+            exit(EXIT_FAILURE);
+        }
+    } else {
+        g_critical("unsupported channel method/type: %s", s->method);
+        exit(EXIT_FAILURE);
+    }
+
+    json_message_parser_init(&s->parser, process_event);
+    s->main_loop = g_main_loop_new(NULL, false);
+}
+
+int main(int argc, char **argv)
+{
+    const char *sopt = "hVvdm:p:l:f:";
+    const char *method = NULL, *path = NULL, *pidfile = QGA_PIDFILE_DEFAULT;
+    const struct option lopt[] = {
+        { "help", 0, NULL, 'h' },
+        { "version", 0, NULL, 'V' },
+        { "logfile", 0, NULL, 'l' },
+        { "pidfile", 0, NULL, 'f' },
+        { "verbose", 0, NULL, 'v' },
+        { "method", 0, NULL, 'm' },
+        { "path", 0, NULL, 'p' },
+        { "daemonize", 0, NULL, 'd' },
+        { NULL, 0, NULL, 0 }
+    };
+    int opt_ind = 0, ch, daemonize = 0;
+    GLogLevelFlags log_level = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL;
+    FILE *log_file = stderr;
+    GAState *s;
+
+    while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
+        switch (ch) {
+        case 'm':
+            method = optarg;
+            break;
+        case 'p':
+            path = optarg;
+            break;
+        case 'l':
+            log_file = fopen(optarg, "a");
+            if (!log_file) {
+                g_critical("unable to open specified log file: %s",
+                           strerror(errno));
+                return EXIT_FAILURE;
+            }
+            break;
+        case 'f':
+            pidfile = optarg;
+            break;
+        case 'v':
+            /* enable all log levels */
+            log_level = G_LOG_LEVEL_MASK;
+            break;
+        case 'V':
+            printf("QEMU Guest Agent %s\n", QGA_VERSION);
+            return 0;
+        case 'd':
+            daemonize = 1;
+            break;
+        case 'h':
+            usage(argv[0]);
+            return 0;
+        case '?':
+            g_print("Unknown option, try '%s --help' for more information.\n",
+                    argv[0]);
+            return EXIT_FAILURE;
+        }
+    }
+
+    if (daemonize) {
+        g_debug("starting daemon");
+        become_daemon(pidfile);
+    }
+
+    g_type_init();
+    g_thread_init(NULL);
+
+    s = qemu_mallocz(sizeof(GAState));
+    s->conn_channel = NULL;
+    s->path = path;
+    s->method = method;
+    s->log_file = log_file;
+    s->log_level = log_level;
+    g_log_set_default_handler(ga_log, s);
+    g_log_set_fatal_mask(NULL, G_LOG_LEVEL_ERROR);
+    s->logging_enabled = true;
+    ga_state = s;
+
+    module_call_init(MODULE_INIT_QAPI);
+    init_guest_agent(ga_state);
+    register_signal_handlers();
+
+    g_main_loop_run(ga_state->main_loop);
+
+    unlink(pidfile);
+
+    return 0;
+}
diff --git a/qga/guest-agent-core.h b/qga/guest-agent-core.h
index 688f120..66d1729 100644
--- a/qga/guest-agent-core.h
+++ b/qga/guest-agent-core.h
@@ -15,6 +15,7 @@
 
 #define QGA_VERSION "1.0"
 
+typedef struct GAState GAState;
 typedef struct GACommandState GACommandState;
 
 void ga_command_state_add(GACommandState *cs,
@@ -23,3 +24,6 @@ void ga_command_state_add(GACommandState *cs,
 void ga_command_state_init_all(GACommandState *cs);
 void ga_command_state_cleanup_all(GACommandState *cs);
 GACommandState *ga_command_state_new(void);
+bool ga_logging_enabled(GAState *s);
+void ga_disable_logging(GAState *s);
+void ga_enable_logging(GAState *s);
commit 13a286d57bb5f50dbceea1fc45060a69bcb23fd1
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 15:41:53 2011 -0500

    guest agent: command state class
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/Makefile b/Makefile
index d7c8567..b8cdf0e 100644
--- a/Makefile
+++ b/Makefile
@@ -182,6 +182,8 @@ test-visitor: test-visitor.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.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 qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
 
+QGALIB=qga/guest-agent-command-state.o
+
 QEMULIBS=libhw32 libhw64 libuser libdis libdis-user
 
 clean:
@@ -190,7 +192,7 @@ clean:
 	rm -f qemu-options.def
 	rm -f *.o *.d *.a *.lo $(TOOLS) 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
+	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
 	rm -f trace.c trace.h trace.c-timestamp trace.h-timestamp
 	rm -f trace-dtrace.dtrace trace-dtrace.dtrace-timestamp
diff --git a/configure b/configure
index ad1e1e1..796f706 100755
--- a/configure
+++ b/configure
@@ -3487,6 +3487,7 @@ DIRS="$DIRS pc-bios/spapr-rtas"
 DIRS="$DIRS roms/seabios roms/vgabios"
 DIRS="$DIRS fsdev ui"
 DIRS="$DIRS qapi"
+DIRS="$DIRS qga"
 FILES="Makefile tests/Makefile"
 FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
 FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
diff --git a/qga/guest-agent-command-state.c b/qga/guest-agent-command-state.c
new file mode 100644
index 0000000..bc6e0bd
--- /dev/null
+++ b/qga/guest-agent-command-state.c
@@ -0,0 +1,73 @@
+/*
+ * QEMU Guest Agent command state interfaces
+ *
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ *  Michael Roth      <mdroth at linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include <glib.h>
+#include "qga/guest-agent-core.h"
+
+struct GACommandState {
+    GSList *groups;
+};
+
+typedef struct GACommandGroup {
+    void (*init)(void);
+    void (*cleanup)(void);
+} GACommandGroup;
+
+/* handle init/cleanup for stateful guest commands */
+
+void ga_command_state_add(GACommandState *cs,
+                          void (*init)(void),
+                          void (*cleanup)(void))
+{
+    GACommandGroup *cg = qemu_mallocz(sizeof(GACommandGroup));
+    cg->init = init;
+    cg->cleanup = cleanup;
+    cs->groups = g_slist_append(cs->groups, cg);
+}
+
+static void ga_command_group_init(gpointer opaque, gpointer unused)
+{
+    GACommandGroup *cg = opaque;
+
+    g_assert(cg);
+    if (cg->init) {
+        cg->init();
+    }
+}
+
+void ga_command_state_init_all(GACommandState *cs)
+{
+    g_assert(cs);
+    g_slist_foreach(cs->groups, ga_command_group_init, NULL);
+}
+
+static void ga_command_group_cleanup(gpointer opaque, gpointer unused)
+{
+    GACommandGroup *cg = opaque;
+
+    g_assert(cg);
+    if (cg->cleanup) {
+        cg->cleanup();
+    }
+}
+
+void ga_command_state_cleanup_all(GACommandState *cs)
+{
+    g_assert(cs);
+    g_slist_foreach(cs->groups, ga_command_group_cleanup, NULL);
+}
+
+GACommandState *ga_command_state_new(void)
+{
+    GACommandState *cs = qemu_mallocz(sizeof(GACommandState));
+    cs->groups = NULL;
+    return cs;
+}
diff --git a/qga/guest-agent-core.h b/qga/guest-agent-core.h
new file mode 100644
index 0000000..688f120
--- /dev/null
+++ b/qga/guest-agent-core.h
@@ -0,0 +1,25 @@
+/*
+ * QEMU Guest Agent core declarations
+ *
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ *  Adam Litke        <aglitke at linux.vnet.ibm.com>
+ *  Michael Roth      <mdroth at linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qapi/qmp-core.h"
+#include "qemu-common.h"
+
+#define QGA_VERSION "1.0"
+
+typedef struct GACommandState GACommandState;
+
+void ga_command_state_add(GACommandState *cs,
+                          void (*init)(void),
+                          void (*cleanup)(void));
+void ga_command_state_init_all(GACommandState *cs);
+void ga_command_state_cleanup_all(GACommandState *cs);
+GACommandState *ga_command_state_new(void);
commit ac32c7807640f04682ea17bca17c22f8b9264d62
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 15:41:52 2011 -0500

    qerror: add QERR_JSON_PARSE_ERROR to qerror.c
    
    Missing from previous addition of error to qerror.h. Needed for
    qerror_format() and friends.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/qerror.c b/qerror.c
index d7fcd93..c92adfc 100644
--- a/qerror.c
+++ b/qerror.c
@@ -141,6 +141,11 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Invalid JSON syntax",
     },
     {
+        .error_fmt = QERR_JSON_PARSE_ERROR,
+        .desc      = "JSON parse error, %(message)",
+
+    },
+    {
         .error_fmt = QERR_KVM_MISSING_CAP,
         .desc      = "Using KVM without %(capability), %(feature) unavailable",
     },
commit b84da8319586e31c2065b1a39aca5ff15e204d5a
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 14:50:46 2011 -0500

    qapi: add QAPI code generation documentation
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
new file mode 100644
index 0000000..b7befb5
--- /dev/null
+++ b/docs/qapi-code-gen.txt
@@ -0,0 +1,316 @@
+= How to use the QAPI code generator =
+
+* Note: as of this writing, QMP does not use QAPI. Eventually QMP
+commands will be converted to use QAPI internally. The following
+information describes QMP/QAPI as it will exist after the
+conversion.
+
+QAPI is a native C API within QEMU which provides management-level
+functionality to internal/external users. For external
+users/processes, this interface is made available by a JSON-based
+QEMU Monitor protocol that is provided by the QMP server.
+
+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
+marshaling/dispatch code for the guest agent server running in the
+guest.
+
+This document will describe how the schemas, scripts, and resulting
+code is used.
+
+
+== QMP/Guest agent schema ==
+
+This file defines the types, commands, and events used by QMP.  It should
+fully describe the interface used by QMP.
+
+This file is designed to be loosely based on JSON although it's technically
+executable Python.  While dictionaries are used, they are parsed as
+OrderedDicts so that ordering is preserved.
+
+There are two basic syntaxes used, type definitions and command definitions.
+
+The first syntax defines a type and is represented by a dictionary.  There are
+two kinds of types that are supported: complex user-defined types, and enums.
+
+A complex type is a dictionary containing a single key who's value is a
+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 } }
+
+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
+backwards compatibility.
+
+An enumeration type is a dictionary containing a single key who's value is a
+list of strings.  An example enumeration is:
+
+ { 'enum': 'MyEnum', 'data': [ 'value1', 'value2', 'value3' ] }
+
+Generally speaking, complex types and enums should always use CamelCase for
+the type names.
+
+Commands are defined by using a list containing three members.  The first
+member is the command name, the second member is a dictionary containing
+arguments, and the third member is the return type.
+
+An example command is:
+
+ { 'command': 'my-command',
+   'data': { 'arg1': 'str', '*arg2': 'str' },
+   'returns': 'str' ]
+
+Command names should be all lower case with words separated by a hyphen.
+
+
+== Code generation ==
+
+Schemas are fed into 3 scripts to generate all the code/files that, paired
+with the core QAPI libraries, comprise everything required to take JSON
+commands read in by a QMP/guest agent server, unmarshal the arguments into
+the underlying C types, call into the corresponding C function, and map the
+response back to a QMP/guest agent response to be returned to the user.
+
+As an example, we'll use the following schema, which describes a single
+complex user-defined type (which will produce a C struct, along with a list
+node structure that can be used to chain together a list of such types in
+case we want to accept/return a list of this type with a command), and a
+command which takes that type as a parameter and returns the same type:
+
+    mdroth at illuin:~/w/qemu2.git$ cat example-schema.json
+    { 'type': 'UserDefOne',
+      'data': { 'integer': 'int', 'string': 'str' } }
+
+    { 'command': 'my-command',
+      'data':    {'arg1': 'UserDefOne'},
+      'returns': 'UserDefOne' }
+    mdroth at illuin:~/w/qemu2.git$
+
+=== scripts/qapi-types.py ===
+
+Used to generate the C types defined by a schema. The following files are
+created:
+
+$(prefix)qapi-types.h - C types corresponding to types defined in
+                        the schema you pass in
+$(prefix)qapi-types.c - Cleanup functions for the above C types
+
+The $(prefix) is an optional parameter used as a namespace to keep the
+generated code from one schema/code-generation separated from others so code
+can be generated/used from multiple schemas without clobbering previously
+created code.
+
+Example:
+
+    mdroth at illuin:~/w/qemu2.git$ python scripts/qapi-types.py \
+      --output-dir="qapi-generated" --prefix="example-" < example-schema.json
+    mdroth at illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.c
+    /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+    #include "qapi/qapi-dealloc-visitor.h"
+    #include "example-qapi-types.h"
+    #include "example-qapi-visit.h"
+
+    void qapi_free_UserDefOne(UserDefOne * obj)
+    {
+        QapiDeallocVisitor *md;
+        Visitor *v;
+
+        if (!obj) {
+            return;
+        }
+
+        md = qapi_dealloc_visitor_new();
+        v = qapi_dealloc_get_visitor(md);
+        visit_type_UserDefOne(v, &obj, NULL, NULL);
+        qapi_dealloc_visitor_cleanup(md);
+    }
+
+    mdroth at illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.h
+    /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
+    #ifndef QAPI_GENERATED_EXAMPLE_QAPI_TYPES
+    #define QAPI_GENERATED_EXAMPLE_QAPI_TYPES
+
+    #include "qapi/qapi-types-core.h"
+
+    typedef struct UserDefOne UserDefOne;
+
+    typedef struct UserDefOneList
+    {
+        UserDefOne *value;
+        struct UserDefOneList *next;
+    } UserDefOneList;
+
+    struct UserDefOne
+    {
+        int64_t integer;
+        char * string;
+    };
+
+    void qapi_free_UserDefOne(UserDefOne * obj);
+
+    #endif
+
+
+=== scripts/qapi-visit.py ===
+
+Used to generate the visitor functions used to walk through and convert
+a QObject (as provided by QMP) to a native C data structure and
+vice-versa, as well as the visitor function used to dealloc a complex
+schema-defined C type.
+
+The following files are generated:
+
+$(prefix)qapi-visit.c: visitor function for a particular C type, used
+                       to automagically convert QObjects into the
+                       corresponding C type and vice-versa, as well
+                       as for deallocating memory for an existing C
+                       type
+
+$(prefix)qapi-visit.h: declarations for previously mentioned visitor
+                       functions
+
+Example:
+
+    mdroth at illuin:~/w/qemu2.git$ python scripts/qapi-visit.py \
+        --output-dir="qapi-generated" --prefix="example-" < example-schema.json
+    mdroth at illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.c
+    /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+    #include "example-qapi-visit.h"
+
+    void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp)
+    {
+        visit_start_struct(m, (void **)obj, "UserDefOne", name, sizeof(UserDefOne), errp);
+        visit_type_int(m, (obj && *obj) ? &(*obj)->integer : NULL, "integer", errp);
+        visit_type_str(m, (obj && *obj) ? &(*obj)->string : NULL, "string", errp);
+        visit_end_struct(m, errp);
+    }
+
+    void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp)
+    {
+        GenericList *i;
+
+        visit_start_list(m, name, errp);
+
+        for (i = visit_next_list(m, (GenericList **)obj, errp); i; i = visit_next_list(m, &i, errp)) {
+            UserDefOneList *native_i = (UserDefOneList *)i;
+            visit_type_UserDefOne(m, &native_i->value, NULL, errp);
+        }
+
+        visit_end_list(m, errp);
+    }
+    mdroth at illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.h
+    /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+    #ifndef QAPI_GENERATED_EXAMPLE_QAPI_VISIT
+    #define QAPI_GENERATED_EXAMPLE_QAPI_VISIT
+
+    #include "qapi/qapi-visit-core.h"
+    #include "example-qapi-types.h"
+
+    void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp);
+    void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp);
+
+    #endif
+    mdroth at illuin:~/w/qemu2.git$
+
+
+=== scripts/qapi-commands.py ===
+
+Used to generate the marshaling/dispatch functions for the commands defined
+in the schema. The following files are generated:
+
+$(prefix)qmp-marshal.c: command marshal/dispatch functions for each
+                        QMP command defined in the schema. Functions
+                        generated by qapi-visit.py are used to
+                        convert QObjects recieved from the wire into
+                        function parameters, and uses the same
+                        visitor functions to convert native C return
+                        values to QObjects from transmission back
+                        over the wire.
+
+$(prefix)qmp-commands.h: Function prototypes for the QMP commands
+                         specified in the schema.
+
+Example:
+
+    mdroth at illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-marshal.c
+    /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+    #include "qemu-objects.h"
+    #include "qapi/qmp-core.h"
+    #include "qapi/qapi-visit-core.h"
+    #include "qapi/qmp-output-visitor.h"
+    #include "qapi/qmp-input-visitor.h"
+    #include "qapi/qapi-dealloc-visitor.h"
+    #include "example-qapi-types.h"
+    #include "example-qapi-visit.h"
+
+    #include "example-qmp-commands.h"
+    static void qmp_marshal_output_my_command(UserDefOne * ret_in, QObject **ret_out, Error **errp)
+    {
+        QapiDeallocVisitor *md = qapi_dealloc_visitor_new();
+        QmpOutputVisitor *mo = qmp_output_visitor_new();
+        Visitor *v;
+
+        v = qmp_output_get_visitor(mo);
+        visit_type_UserDefOne(v, &ret_in, "unused", errp);
+        v = qapi_dealloc_get_visitor(md);
+        visit_type_UserDefOne(v, &ret_in, "unused", errp);
+        qapi_dealloc_visitor_cleanup(md);
+
+
+        *ret_out = qmp_output_get_qobject(mo);
+    }
+
+    static void qmp_marshal_input_my_command(QmpState *qmp__sess, QDict *args, QObject **ret, Error **errp)
+    {
+        UserDefOne * retval = NULL;
+        QmpInputVisitor *mi;
+        QapiDeallocVisitor *md;
+        Visitor *v;
+        UserDefOne * arg1 = NULL;
+
+        mi = qmp_input_visitor_new(QOBJECT(args));
+        v = qmp_input_get_visitor(mi);
+        visit_type_UserDefOne(v, &arg1, "arg1", errp);
+
+        if (error_is_set(errp)) {
+            goto out;
+        }
+        retval = qmp_my_command(arg1, errp);
+        qmp_marshal_output_my_command(retval, ret, errp);
+
+    out:
+        md = qapi_dealloc_visitor_new();
+        v = qapi_dealloc_get_visitor(md);
+        visit_type_UserDefOne(v, &arg1, "arg1", errp);
+        qapi_dealloc_visitor_cleanup(md);
+        return;
+    }
+
+    static void qmp_init_marshal(void)
+    {
+        qmp_register_command("my-command", qmp_marshal_input_my_command);
+    }
+
+    qapi_init(qmp_init_marshal);
+    mdroth at illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-commands.h
+    /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+    #ifndef QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
+    #define QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
+
+    #include "example-qapi-types.h"
+    #include "error.h"
+
+    UserDefOne * qmp_my_command(UserDefOne * arg1, Error **errp);
+
+    #endif
+    mdroth at illuin:~/w/qemu2.git$
commit 69ed8366b1e8602b6b7555902f453d3e5df5dd41
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 14:50:45 2011 -0500

    qapi: add test-qmp-commands, tests for gen. marshalling/dispatch code
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/Makefile b/Makefile
index 5d2cf5b..d7c8567 100644
--- a/Makefile
+++ b/Makefile
@@ -164,7 +164,7 @@ check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjs
 
 $(qapi-obj-y): $(GENERATED_HEADERS)
 qapi-dir := qapi-generated
-test-visitor.o: QEMU_CFLAGS += -I $(qapi-dir)
+test-visitor.o test-qmp-commands.o: QEMU_CFLAGS += -I $(qapi-dir)
 
 $(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
@@ -172,10 +172,16 @@ $(qapi-dir)/test-qapi-types.h: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scr
 $(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
 	$(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
+	    $(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "test-" < $<, "  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 qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(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 qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
+
 QEMULIBS=libhw32 libhw64 libuser libdis libdis-user
 
 clean:
diff --git a/test-qmp-commands.c b/test-qmp-commands.c
new file mode 100644
index 0000000..7752904
--- /dev/null
+++ b/test-qmp-commands.c
@@ -0,0 +1,113 @@
+#include <glib.h>
+#include "qemu-objects.h"
+#include "test-qmp-commands.h"
+#include "qapi/qmp-core.h"
+#include "module.h"
+
+void qmp_user_def_cmd(Error **errp)
+{
+}
+
+void qmp_user_def_cmd1(UserDefOne * ud1, Error **errp)
+{
+}
+
+UserDefTwo * qmp_user_def_cmd2(UserDefOne * ud1a, UserDefOne * ud1b, Error **errp)
+{
+    UserDefTwo *ret;
+    UserDefOne *ud1c = qemu_mallocz(sizeof(UserDefOne));
+    UserDefOne *ud1d = qemu_mallocz(sizeof(UserDefOne));
+
+    ud1c->string = strdup(ud1a->string);
+    ud1c->integer = ud1a->integer;
+    ud1d->string = strdup(ud1b->string);
+    ud1d->integer = ud1b->integer;
+
+    ret = qemu_mallocz(sizeof(UserDefTwo));
+    ret->string = strdup("blah1");
+    ret->dict.string = strdup("blah2");
+    ret->dict.dict.userdef = ud1c;
+    ret->dict.dict.string = strdup("blah3");
+    ret->dict.has_dict2 = true;
+    ret->dict.dict2.userdef = ud1d;
+    ret->dict.dict2.string = strdup("blah4");
+
+    return ret;
+}
+
+/* test commands with no input and no return value */
+static void test_dispatch_cmd(void)
+{
+    QDict *req = qdict_new();
+    QObject *resp;
+
+    qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd")));
+
+    resp = qmp_dispatch(QOBJECT(req));
+    assert(resp != NULL);
+    assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
+    g_print("\nresp: %s\n", qstring_get_str(qobject_to_json(resp)));
+
+    qobject_decref(resp);
+    QDECREF(req);
+}
+
+/* test commands that return an error due to invalid parameters */
+static void test_dispatch_cmd_error(void)
+{
+    QDict *req = qdict_new();
+    QObject *resp;
+
+    qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2")));
+
+    resp = qmp_dispatch(QOBJECT(req));
+    assert(resp != NULL);
+    assert(qdict_haskey(qobject_to_qdict(resp), "error"));
+    g_print("\nresp: %s\n", qstring_get_str(qobject_to_json_pretty(resp)));
+
+    qobject_decref(resp);
+    QDECREF(req);
+}
+
+/* test commands that involve both input parameters and return values */
+static void test_dispatch_cmd_io(void)
+{
+    QDict *req = qdict_new();
+    QDict *args = qdict_new();
+    QDict *ud1a = qdict_new();
+    QDict *ud1b = qdict_new();
+    QObject *resp;
+
+    qdict_put_obj(ud1a, "integer", QOBJECT(qint_from_int(42)));
+    qdict_put_obj(ud1a, "string", QOBJECT(qstring_from_str("hello")));
+    qdict_put_obj(ud1b, "integer", QOBJECT(qint_from_int(422)));
+    qdict_put_obj(ud1b, "string", QOBJECT(qstring_from_str("hello2")));
+    qdict_put_obj(args, "ud1a", QOBJECT(ud1a));
+    qdict_put_obj(args, "ud1b", QOBJECT(ud1b));
+    qdict_put_obj(req, "arguments", QOBJECT(args));
+
+    qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2")));
+
+    /* TODO: put in full payload and check for errors */
+    resp = qmp_dispatch(QOBJECT(req));
+    assert(resp != NULL);
+    assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
+    g_print("\nresp: %s\n", qstring_get_str(qobject_to_json_pretty(resp)));
+
+    qobject_decref(resp);
+    QDECREF(req);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/0.15/dispatch_cmd", test_dispatch_cmd);
+    g_test_add_func("/0.15/dispatch_cmd_error", test_dispatch_cmd_error);
+    g_test_add_func("/0.15/dispatch_cmd_io", test_dispatch_cmd_io);
+
+    module_call_init(MODULE_INIT_QAPI);
+    g_test_run();
+
+    return 0;
+}
commit 640e540446d174144784225bfe223d8e40e7736d
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 14:50:44 2011 -0500

    qapi: add test-visitor, tests for gen. visitor code
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/Makefile b/Makefile
index 42ae4e5..5d2cf5b 100644
--- a/Makefile
+++ b/Makefile
@@ -162,6 +162,20 @@ check-qlist: check-qlist.o qlist.o qint.o $(CHECK_PROG_DEPS)
 check-qfloat: check-qfloat.o qfloat.o $(CHECK_PROG_DEPS)
 check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o error.o qerror.o qemu-error.o $(CHECK_PROG_DEPS)
 
+$(qapi-obj-y): $(GENERATED_HEADERS)
+qapi-dir := qapi-generated
+test-visitor.o: QEMU_CFLAGS += -I $(qapi-dir)
+
+$(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
+	$(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
+	$(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "test-" < $<, "  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 qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+
 QEMULIBS=libhw32 libhw64 libuser libdis libdis-user
 
 clean:
@@ -170,11 +184,12 @@ clean:
 	rm -f qemu-options.def
 	rm -f *.o *.d *.a *.lo $(TOOLS) 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
+	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
 	rm -f qemu-img-cmds.h
 	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 -rf $(qapi-dir)
 	$(MAKE) -C tests clean
 	for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard; do \
 	if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
@@ -363,4 +378,4 @@ tarbin:
 	$(mandir)/man8/qemu-nbd.8
 
 # Include automatically generated dependency files
--include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d)
+-include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d qapi/*.d)
diff --git a/test-visitor.c b/test-visitor.c
new file mode 100644
index 0000000..5133ad6
--- /dev/null
+++ b/test-visitor.c
@@ -0,0 +1,306 @@
+#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;
+
+    visit_start_list(m, name, errp);
+
+    for (i = visit_next_list(m, (GenericList **)obj, 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;
+    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);
+
+    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);
+
+    lts = lts->next;
+    g_assert(lts != NULL);
+    g_assert(lts->value->x == 12);
+    g_assert(lts->value->y == 24);
+
+    g_assert(lts->next == NULL);
+
+    qobject_decref(obj);
+}
+
+/* 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("fourty 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("fourty three");
+    ud2.dict.string = strdup("fourty four");
+    ud2.dict.dict.userdef = ud1_p;
+    ud2.dict.dict.string = strdup("fourty five");
+    ud2.dict.has_dict2 = true;
+    ud2.dict.dict2.userdef = ud1_p;
+    ud2.dict.dict2.string = strdup("fourty 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));
+    qemu_free(ud1.string);
+    qemu_free(ud2.string);
+    qemu_free(ud2.dict.string);
+    qemu_free(ud2.dict.dict.string);
+    qemu_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 = qemu_mallocz(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);
+
+    qobject_decref(obj);
+    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 501e5104490fca89ad31e6a430e2cf01f928d5d1
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 14:50:43 2011 -0500

    qapi: test schema used for unit tests
    
    This is how QMP commands/parameters/types would be defined. We use a
    subset of that functionality here to implement functions/types for unit
    testing.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/qapi-schema-test.json b/qapi-schema-test.json
new file mode 100644
index 0000000..3acedad
--- /dev/null
+++ b/qapi-schema-test.json
@@ -0,0 +1,22 @@
+# *-*- Mode: Python -*-*
+
+# for testing enums
+{ 'enum': 'EnumOne',
+  'data': [ 'value1', 'value2', 'value3' ] }
+{ 'type': 'NestedEnumsOne',
+  'data': { 'enum1': 'EnumOne', '*enum2': 'EnumOne', 'enum3': 'EnumOne', '*enum4': 'EnumOne' } }
+
+# for testing nested structs
+{ 'type': 'UserDefOne',
+  'data': { 'integer': 'int', 'string': 'str' } }
+
+{ 'type': 'UserDefTwo',
+  'data': { 'string': 'str',
+            'dict': { 'string': 'str',
+                      'dict': { 'userdef': 'UserDefOne', 'string': 'str' },
+                      '*dict2': { 'userdef': 'UserDefOne', 'string': 'str' } } } }
+
+# testing commands
+{ 'command': 'user_def_cmd', 'data': {} }
+{ 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} }
+{ 'command': 'user_def_cmd2', 'data': {'ud1a': 'UserDefOne', 'ud1b': 'UserDefOne'}, 'returns': 'UserDefTwo' }
commit c17d9908a942e355c70bfb32b6ebdc0e6e5daa87
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 14:50:42 2011 -0500

    qapi: add qapi-commands.py code generator
    
    This is the code generator for qapi command marshaling/dispatch.
    Currently only generators for synchronous qapi/qmp functions are
    supported. This script generates the following files:
    
      $(prefix)qmp-marshal.c: command marshal/dispatch functions for each
                              QMP command defined in the schema. Functions
                              generated by qapi-visit.py are used to
                              convert qobjects recieved from the wire into
                              function parameters, and uses the same
                              visiter functions to convert native C return
                              values to qobjects from transmission back
                              over the wire.
    
      $(prefix)qmp-commands.h: Function prototypes for the QMP commands
                               specified in the schema.
    
    $(prefix) is used in the same manner as with qapi-types.py
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
new file mode 100644
index 0000000..9ad4c54
--- /dev/null
+++ b/scripts/qapi-commands.py
@@ -0,0 +1,385 @@
+#
+# QAPI command marshaller generator
+#
+# Copyright IBM, Corp. 2011
+#
+# Authors:
+#  Anthony Liguori <aliguori at us.ibm.com>
+#  Michael Roth    <mdroth at linux.vnet.ibm.com>
+#
+# This work is licensed under the terms of the GNU GPLv2.
+# See the COPYING.LIB file in the top-level directory.
+
+from ordereddict import OrderedDict
+from qapi import *
+import sys
+import os
+import getopt
+import errno
+
+def generate_decl_enum(name, members, genlist=True):
+    return mcgen('''
+
+void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **errp);
+''',
+                name=name)
+
+def generate_command_decl(name, args, ret_type):
+    arglist=""
+    for argname, argtype, optional, structured in parse_args(args):
+        argtype = c_type(argtype)
+        if argtype == "char *":
+            argtype = "const char *"
+        if optional:
+            arglist += "bool has_%s, " % c_var(argname)
+        arglist += "%s %s, " % (argtype, c_var(argname))
+    return mcgen('''
+%(ret_type)s qmp_%(name)s(%(args)sError **errp);
+''',
+                 ret_type=c_type(ret_type), name=c_var(name), args=arglist).strip()
+
+def gen_sync_call(name, args, ret_type, indent=0):
+    ret = ""
+    arglist=""
+    retval=""
+    if ret_type:
+        retval = "retval = "
+    for argname, argtype, optional, structured in parse_args(args):
+        if optional:
+            arglist += "has_%s, " % c_var(argname)
+        arglist += "%s, " % (c_var(argname))
+    push_indent(indent)
+    ret = mcgen('''
+%(retval)sqmp_%(name)s(%(args)serrp);
+
+''',
+                name=c_var(name), args=arglist, retval=retval).rstrip()
+    if ret_type:
+        ret += "\n" + mcgen(''''
+%(marshal_output_call)s
+''',
+                            marshal_output_call=gen_marshal_output_call(name, ret_type)).rstrip()
+    pop_indent(indent)
+    return ret.rstrip()
+
+
+def gen_marshal_output_call(name, ret_type):
+    if not ret_type:
+        return ""
+    return "qmp_marshal_output_%s(retval, ret, errp);" % c_var(name)
+
+def gen_visitor_output_containers_decl(ret_type):
+    ret = ""
+    push_indent()
+    if ret_type:
+        ret += mcgen('''
+QmpOutputVisitor *mo;
+QapiDeallocVisitor *md;
+Visitor *v;
+''')
+    pop_indent()
+
+    return ret
+
+def gen_visitor_input_containers_decl(args):
+    ret = ""
+
+    push_indent()
+    if len(args) > 0:
+        ret += mcgen('''
+QmpInputVisitor *mi;
+QapiDeallocVisitor *md;
+Visitor *v;
+''')
+    pop_indent()
+
+    return ret.rstrip()
+
+def gen_visitor_input_vars_decl(args):
+    ret = ""
+    push_indent()
+    for argname, argtype, optional, structured in parse_args(args):
+        if optional:
+            ret += mcgen('''
+bool has_%(argname)s = false;
+''',
+                         argname=c_var(argname))
+        if c_type(argtype).endswith("*"):
+            ret += mcgen('''
+%(argtype)s %(argname)s = NULL;
+''',
+                         argname=c_var(argname), argtype=c_type(argtype))
+        else:
+            ret += mcgen('''
+%(argtype)s %(argname)s;
+''',
+                         argname=c_var(argname), argtype=c_type(argtype))
+
+    pop_indent()
+    return ret.rstrip()
+
+def gen_visitor_input_block(args, obj, dealloc=False):
+    ret = ""
+    if len(args) == 0:
+        return ret
+
+    push_indent()
+
+    if dealloc:
+        ret += mcgen('''
+md = qapi_dealloc_visitor_new();
+v = qapi_dealloc_get_visitor(md);
+''')
+    else:
+        ret += mcgen('''
+mi = qmp_input_visitor_new(%(obj)s);
+v = qmp_input_get_visitor(mi);
+''',
+                     obj=obj)
+
+    for argname, argtype, optional, structured in parse_args(args):
+        if optional:
+            ret += mcgen('''
+visit_start_optional(v, &has_%(c_name)s, "%(name)s", errp);
+if (has_%(c_name)s) {
+''',
+                         c_name=c_var(argname), name=argname)
+            push_indent()
+        ret += mcgen('''
+visit_type_%(argtype)s(v, &%(c_name)s, "%(name)s", errp);
+''',
+                      c_name=c_var(argname), name=argname, argtype=argtype)
+        if optional:
+            pop_indent()
+            ret += mcgen('''
+}
+visit_end_optional(v, errp);
+''')
+
+    if dealloc:
+        ret += mcgen('''
+qapi_dealloc_visitor_cleanup(md);
+''')
+    else:
+        ret += mcgen('''
+qmp_input_visitor_cleanup(mi);
+''')
+    pop_indent()
+    return ret.rstrip()
+
+def gen_marshal_output(name, args, ret_type):
+    if not ret_type:
+        return ""
+    ret = mcgen('''
+static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_out, Error **errp)
+{
+    QapiDeallocVisitor *md = qapi_dealloc_visitor_new();
+    QmpOutputVisitor *mo = qmp_output_visitor_new();
+    Visitor *v;
+
+    v = qmp_output_get_visitor(mo);
+    visit_type_%(ret_type)s(v, &ret_in, "unused", errp);
+    if (!error_is_set(errp)) {
+        *ret_out = qmp_output_get_qobject(mo);
+    }
+    qmp_output_visitor_cleanup(mo);
+    v = qapi_dealloc_get_visitor(md);
+    visit_type_%(ret_type)s(v, &ret_in, "unused", errp);
+    qapi_dealloc_visitor_cleanup(md);
+}
+''',
+            c_ret_type=c_type(ret_type), c_name=c_var(name), ret_type=ret_type)
+
+    return ret
+
+def gen_marshal_input(name, args, ret_type):
+    ret = mcgen('''
+static void qmp_marshal_input_%(c_name)s(QDict *args, QObject **ret, Error **errp)
+{
+''',
+                c_name=c_var(name))
+
+    if ret_type:
+        if c_type(ret_type).endswith("*"):
+            retval = "    %s retval = NULL;" % c_type(ret_type)
+        else:
+            retval = "    %s retval;" % c_type(ret_type)
+        ret += mcgen('''
+%(retval)s
+''',
+                     retval=retval)
+
+    if len(args) > 0:
+        ret += mcgen('''
+%(visitor_input_containers_decl)s
+%(visitor_input_vars_decl)s
+
+%(visitor_input_block)s
+
+''',
+                     visitor_input_containers_decl=gen_visitor_input_containers_decl(args),
+                     visitor_input_vars_decl=gen_visitor_input_vars_decl(args),
+                     visitor_input_block=gen_visitor_input_block(args, "QOBJECT(args)"))
+
+    ret += mcgen('''
+    if (error_is_set(errp)) {
+        goto out;
+    }
+%(sync_call)s
+''',
+                 sync_call=gen_sync_call(name, args, ret_type, indent=4))
+    ret += mcgen('''
+
+out:
+''')
+    ret += mcgen('''
+%(visitor_input_block_cleanup)s
+    return;
+}
+''',
+                 visitor_input_block_cleanup=gen_visitor_input_block(args, None, dealloc=True))
+    return ret
+
+def gen_registry(commands):
+    registry=""
+    push_indent()
+    for cmd in commands:
+        registry += mcgen('''
+qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s);
+''',
+                     name=cmd['command'], c_name=c_var(cmd['command']))
+    pop_indent()
+    ret = mcgen('''
+static void qmp_init_marshal(void)
+{
+%(registry)s
+}
+
+qapi_init(qmp_init_marshal);
+''',
+                registry=registry.rstrip())
+    return ret
+
+def gen_command_decl_prologue(header, guard, prefix=""):
+    ret = mcgen('''
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+/*
+ * schema-defined QAPI function prototypes
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef %(guard)s
+#define %(guard)s
+
+#include "%(prefix)sqapi-types.h"
+#include "error.h"
+
+''',
+                 header=basename(h_file), guard=guardname(h_file), prefix=prefix)
+    return ret
+
+def gen_command_def_prologue(prefix="", proxy=False):
+    ret = mcgen('''
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+/*
+ * schema-defined QMP->QAPI command dispatch
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu-objects.h"
+#include "qapi/qmp-core.h"
+#include "qapi/qapi-visit-core.h"
+#include "qapi/qmp-output-visitor.h"
+#include "qapi/qmp-input-visitor.h"
+#include "qapi/qapi-dealloc-visitor.h"
+#include "%(prefix)sqapi-types.h"
+#include "%(prefix)sqapi-visit.h"
+
+''',
+                prefix=prefix)
+    if not proxy:
+        ret += '#include "%sqmp-commands.h"' % prefix
+    return ret + "\n"
+
+
+try:
+    opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:", ["prefix=", "output-dir=", "type="])
+except getopt.GetoptError, err:
+    print str(err)
+    sys.exit(1)
+
+output_dir = ""
+prefix = ""
+dispatch_type = "sync"
+c_file = 'qmp-marshal.c'
+h_file = 'qmp-commands.h'
+
+for o, a in opts:
+    if o in ("-p", "--prefix"):
+        prefix = a
+    elif o in ("-o", "--output-dir"):
+        output_dir = a + "/"
+    elif o in ("-t", "--type"):
+        dispatch_type = a
+
+c_file = output_dir + prefix + c_file
+h_file = output_dir + prefix + h_file
+
+try:
+    os.makedirs(output_dir)
+except os.error, e:
+    if e.errno != errno.EEXIST:
+        raise
+
+exprs = parse_schema(sys.stdin)
+commands = filter(lambda expr: expr.has_key('command'), exprs)
+
+if dispatch_type == "sync":
+    fdecl = open(h_file, 'w')
+    fdef = open(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)
+    fdef.write(ret)
+
+    for cmd in commands:
+        arglist = []
+        ret_type = None
+        if cmd.has_key('data'):
+            arglist = cmd['data']
+        if cmd.has_key('returns'):
+            ret_type = cmd['returns']
+        ret = generate_command_decl(cmd['command'], arglist, ret_type) + "\n"
+        fdecl.write(ret)
+        if ret_type:
+            ret = gen_marshal_output(cmd['command'], arglist, ret_type) + "\n"
+            fdef.write(ret)
+        ret = gen_marshal_input(cmd['command'], arglist, ret_type) + "\n"
+        fdef.write(ret)
+
+    fdecl.write("\n#endif");
+    ret = gen_registry(commands)
+    fdef.write(ret)
+
+    fdef.flush()
+    fdef.close()
+    fdecl.flush()
+    fdecl.close()
commit 06d64c62ddc38c77af775c16165d4b38f43d02e9
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 14:50:41 2011 -0500

    qapi: add qapi-visit.py code generator
    
    This is the code generator for qapi visiter functions used to
    marshal/unmarshal/dealloc qapi types. It generates the following 2
    files:
    
      $(prefix)qapi-visit.c: visiter function for a particular c type, used
                             to automagically convert qobjects into the
                             corresponding C type and vice-versa, and well
                             as for deallocation memory for an existing C
                             type
    
      $(prefix)qapi-visit.h: declarations for previously mentioned visiter
                             functions
    
    $(prefix) is used as decribed for qapi-types.py
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
new file mode 100644
index 0000000..252230e
--- /dev/null
+++ b/scripts/qapi-visit.py
@@ -0,0 +1,246 @@
+#
+# QAPI visitor generator
+#
+# Copyright IBM, Corp. 2011
+#
+# Authors:
+#  Anthony Liguori <aliguori at us.ibm.com>
+#  Michael Roth    <mdroth at linux.vnet.ibm.com>
+#
+# This work is licensed under the terms of the GNU GPLv2.
+# See the COPYING.LIB file in the top-level directory.
+
+from ordereddict import OrderedDict
+from qapi import *
+import sys
+import os
+import getopt
+import errno
+
+def generate_visit_struct_body(field_prefix, members):
+    ret = ""
+    if len(field_prefix):
+        field_prefix = field_prefix + "."
+    for argname, argentry, optional, structured in parse_args(members):
+        if optional:
+            ret += mcgen('''
+visit_start_optional(m, (obj && *obj) ? &(*obj)->%(c_prefix)shas_%(c_name)s : NULL, "%(name)s", errp);
+if ((*obj)->%(prefix)shas_%(c_name)s) {
+''',
+                         c_prefix=c_var(field_prefix), prefix=field_prefix,
+                         c_name=c_var(argname), name=argname)
+            push_indent()
+
+        if structured:
+            ret += mcgen('''
+visit_start_struct(m, NULL, "", "%(name)s", 0, errp);
+''',
+                         name=argname)
+            ret += generate_visit_struct_body(field_prefix + argname, argentry)
+            ret += mcgen('''
+visit_end_struct(m, errp);
+''')
+        else:
+            ret += mcgen('''
+visit_type_%(type)s(m, (obj && *obj) ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, "%(name)s", errp);
+''',
+                         c_prefix=c_var(field_prefix), prefix=field_prefix,
+                         type=type_name(argentry), c_name=c_var(argname),
+                         name=argname)
+
+        if optional:
+            pop_indent()
+            ret += mcgen('''
+}
+visit_end_optional(m, errp);
+''')
+    return ret
+
+def generate_visit_struct(name, members):
+    ret = mcgen('''
+
+void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp)
+{
+    visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), errp);
+''',
+                name=name)
+    push_indent()
+    ret += generate_visit_struct_body("", members)
+    pop_indent()
+
+    ret += mcgen('''
+    visit_end_struct(m, errp);
+}
+''')
+    return ret
+
+def generate_visit_list(name, members):
+    return mcgen('''
+
+void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp)
+{
+    GenericList *i;
+
+    visit_start_list(m, name, errp);
+
+    for (i = visit_next_list(m, (GenericList **)obj, errp); i; i = visit_next_list(m, &i, errp)) {
+        %(name)sList *native_i = (%(name)sList *)i;
+        visit_type_%(name)s(m, &native_i->value, NULL, errp);
+    }
+
+    visit_end_list(m, errp);
+}
+''',
+                name=name)
+
+def generate_visit_enum(name, members):
+    return mcgen('''
+
+void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **errp)
+{
+    visit_type_enum(m, (int *)obj, %(name)s_lookup, "%(name)s", name, errp);
+}
+''',
+                 name=name)
+
+def generate_visit_union(name, members):
+    ret = generate_visit_enum('%sKind' % name, members.keys())
+
+    ret += mcgen('''
+
+void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp)
+{
+}
+''',
+                 name=name)
+
+    return ret
+
+def generate_declaration(name, members, genlist=True):
+    ret = mcgen('''
+
+void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp);
+''',
+                name=name)
+
+    if genlist:
+        ret += mcgen('''
+void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp);
+''',
+                 name=name)
+
+    return ret
+
+def generate_decl_enum(name, members, genlist=True):
+    return mcgen('''
+
+void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **errp);
+''',
+                name=name)
+
+try:
+    opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:", ["prefix=", "output-dir="])
+except getopt.GetoptError, err:
+    print str(err)
+    sys.exit(1)
+
+output_dir = ""
+prefix = ""
+c_file = 'qapi-visit.c'
+h_file = 'qapi-visit.h'
+
+for o, a in opts:
+    if o in ("-p", "--prefix"):
+        prefix = a
+    elif o in ("-o", "--output-dir"):
+        output_dir = a + "/"
+
+c_file = output_dir + prefix + c_file
+h_file = output_dir + prefix + h_file
+
+try:
+    os.makedirs(output_dir)
+except os.error, e:
+    if e.errno != errno.EEXIST:
+        raise
+
+fdef = open(c_file, 'w')
+fdecl = open(h_file, 'w')
+
+fdef.write(mcgen('''
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+/*
+ * schema-defined QAPI visitor functions
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "%(header)s"
+''',
+                 header=basename(h_file)))
+
+fdecl.write(mcgen('''
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+/*
+ * schema-defined QAPI visitor function
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef %(guard)s
+#define %(guard)s
+
+#include "qapi/qapi-visit-core.h"
+#include "%(prefix)sqapi-types.h"
+''',
+                  prefix=prefix, guard=guardname(h_file)))
+
+exprs = parse_schema(sys.stdin)
+
+for expr in exprs:
+    if expr.has_key('type'):
+        ret = generate_visit_struct(expr['type'], expr['data'])
+        ret += generate_visit_list(expr['type'], expr['data'])
+        fdef.write(ret)
+
+        ret = generate_declaration(expr['type'], expr['data'])
+        fdecl.write(ret)
+    elif expr.has_key('union'):
+        ret = generate_visit_union(expr['union'], expr['data'])
+        fdef.write(ret)
+
+        ret = generate_decl_enum('%sKind' % expr['union'], expr['data'].keys())
+        ret += generate_declaration(expr['union'], expr['data'])
+        fdecl.write(ret)
+    elif expr.has_key('enum'):
+        ret = generate_visit_enum(expr['enum'], expr['data'])
+        fdef.write(ret)
+
+        ret = generate_decl_enum(expr['enum'], expr['data'])
+        fdecl.write(ret)
+
+fdecl.write('''
+#endif
+''')
+
+fdecl.flush()
+fdecl.close()
+
+fdef.flush()
+fdef.close()
commit fb3182ce6e200a0fedc603d444034d6cbc3d3f0f
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 14:50:40 2011 -0500

    qapi: add qapi-types.py code generator
    
    This is the code generator for qapi types. It will generation the
    following files:
    
      $(prefix)qapi-types.h - C types corresponding to types defined in
                              the schema you pass in
      $(prefix)qapi-types.c - Cleanup functions for the above C types
    
    The $(prefix) is used to as a namespace to keep the generated code from
    one schema/code-generation separated from others so code and be
    generated from multiple schemas with clobbering previously created code.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
new file mode 100644
index 0000000..cece325
--- /dev/null
+++ b/scripts/qapi-types.py
@@ -0,0 +1,270 @@
+#
+# QAPI types generator
+#
+# Copyright IBM, Corp. 2011
+#
+# Authors:
+#  Anthony Liguori <aliguori at us.ibm.com>
+#
+# This work is licensed under the terms of the GNU GPLv2.
+# See the COPYING.LIB file in the top-level directory.
+
+from ordereddict import OrderedDict
+from qapi import *
+import sys
+import os
+import getopt
+import errno
+
+def generate_fwd_struct(name, members):
+    return mcgen('''
+typedef struct %(name)s %(name)s;
+
+typedef struct %(name)sList
+{
+    %(name)s *value;
+    struct %(name)sList *next;
+} %(name)sList;
+''',
+                 name=name)
+
+def generate_struct(structname, fieldname, members):
+    ret = mcgen('''
+struct %(name)s
+{
+''',
+          name=structname)
+
+    for argname, argentry, optional, structured in parse_args(members):
+        if optional:
+            ret += mcgen('''
+    bool has_%(c_name)s;
+''',
+                         c_name=c_var(argname))
+        if structured:
+            push_indent()
+            ret += generate_struct("", argname, argentry)
+            pop_indent()
+        else:
+            ret += mcgen('''
+    %(c_type)s %(c_name)s;
+''',
+                     c_type=c_type(argentry), c_name=c_var(argname))
+
+    if len(fieldname):
+        fieldname = " " + fieldname
+    ret += mcgen('''
+}%(field)s;
+''',
+            field=fieldname)
+
+    return ret
+
+def generate_enum_lookup(name, values):
+    ret = mcgen('''
+const char *%(name)s_lookup[] = {
+''',
+                         name=name)
+    i = 0
+    for value in values:
+        ret += mcgen('''
+    "%(value)s",
+''',
+                     value=c_var(value).lower())
+
+    ret += mcgen('''
+    NULL,
+};
+
+''')
+    return ret
+
+def generate_enum(name, values):
+    lookup_decl = mcgen('''
+extern const char *%(name)s_lookup[];
+''',
+                name=name)
+
+    enum_decl = mcgen('''
+typedef enum %(name)s
+{
+''',
+                name=name)
+
+    i = 0
+    for value in values:
+        enum_decl += mcgen('''
+    %(abbrev)s_%(value)s = %(i)d,
+''',
+                     abbrev=de_camel_case(name).upper(),
+                     value=c_var(value).upper(),
+                     i=i)
+        i += 1
+
+    enum_decl += mcgen('''
+} %(name)s;
+''',
+                 name=name)
+
+    return lookup_decl + enum_decl
+
+def generate_union(name, typeinfo):
+    ret = mcgen('''
+struct %(name)s
+{
+    %(name)sKind kind;
+    union {
+''',
+                name=name)
+
+    for key in typeinfo:
+        ret += mcgen('''
+        %(c_type)s %(c_name)s;
+''',
+                     c_type=c_type(typeinfo[key]),
+                     c_name=c_var(key))
+
+    ret += mcgen('''
+    };
+};
+''')
+
+    return ret
+
+def generate_type_cleanup_decl(name):
+    ret = mcgen('''
+void qapi_free_%(type)s(%(c_type)s obj);
+''',
+                c_type=c_type(name),type=name)
+    return ret
+
+def generate_type_cleanup(name):
+    ret = mcgen('''
+void qapi_free_%(type)s(%(c_type)s obj)
+{
+    QapiDeallocVisitor *md;
+    Visitor *v;
+
+    if (!obj) {
+        return;
+    }
+
+    md = qapi_dealloc_visitor_new();
+    v = qapi_dealloc_get_visitor(md);
+    visit_type_%(type)s(v, &obj, NULL, NULL);
+    qapi_dealloc_visitor_cleanup(md);
+}
+''',
+                c_type=c_type(name),type=name)
+    return ret
+
+
+try:
+    opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:", ["prefix=", "output-dir="])
+except getopt.GetoptError, err:
+    print str(err)
+    sys.exit(1)
+
+output_dir = ""
+prefix = ""
+c_file = 'qapi-types.c'
+h_file = 'qapi-types.h'
+
+for o, a in opts:
+    if o in ("-p", "--prefix"):
+        prefix = a
+    elif o in ("-o", "--output-dir"):
+        output_dir = a + "/"
+
+c_file = output_dir + prefix + c_file
+h_file = output_dir + prefix + h_file
+
+try:
+    os.makedirs(output_dir)
+except os.error, e:
+    if e.errno != errno.EEXIST:
+        raise
+
+fdef = open(c_file, 'w')
+fdecl = open(h_file, 'w')
+
+fdef.write(mcgen('''
+/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+/*
+ * deallocation functions for schema-defined QAPI types
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *  Michael Roth      <mdroth at linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qapi/qapi-dealloc-visitor.h"
+#include "%(prefix)sqapi-types.h"
+#include "%(prefix)sqapi-visit.h"
+
+''',             prefix=prefix))
+
+fdecl.write(mcgen('''
+/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+/*
+ * schema-defined QAPI types
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef %(guard)s
+#define %(guard)s
+
+#include "qapi/qapi-types-core.h"
+''',
+                  guard=guardname(h_file)))
+
+exprs = parse_schema(sys.stdin)
+
+for expr in exprs:
+    ret = "\n"
+    if expr.has_key('type'):
+        ret += generate_fwd_struct(expr['type'], expr['data'])
+    elif expr.has_key('enum'):
+        ret += generate_enum(expr['enum'], expr['data'])
+        fdef.write(generate_enum_lookup(expr['enum'], expr['data']))
+    elif expr.has_key('union'):
+        ret += generate_fwd_struct(expr['union'], expr['data']) + "\n"
+        ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
+    else:
+        continue
+    fdecl.write(ret)
+
+for expr in exprs:
+    ret = "\n"
+    if expr.has_key('type'):
+        ret += generate_struct(expr['type'], "", expr['data']) + "\n"
+        ret += generate_type_cleanup_decl(expr['type'])
+        fdef.write(generate_type_cleanup(expr['type']) + "\n")
+    elif expr.has_key('union'):
+        ret += generate_union(expr['union'], expr['data'])
+    else:
+        continue
+    fdecl.write(ret)
+
+fdecl.write('''
+#endif
+''')
+
+fdecl.flush()
+fdecl.close()
commit 0f923be25321a479405443f33c50c79ee9f5b628
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 14:50:39 2011 -0500

    qapi: add qapi.py helper libraries
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/scripts/qapi.py b/scripts/qapi.py
new file mode 100644
index 0000000..56af232
--- /dev/null
+++ b/scripts/qapi.py
@@ -0,0 +1,203 @@
+#
+# QAPI helper library
+#
+# Copyright IBM, Corp. 2011
+#
+# Authors:
+#  Anthony Liguori <aliguori at us.ibm.com>
+#
+# This work is licensed under the terms of the GNU GPLv2.
+# See the COPYING.LIB file in the top-level directory.
+
+from ordereddict import OrderedDict
+
+def tokenize(data):
+    while len(data):
+        if data[0] in ['{', '}', ':', ',', '[', ']']:
+            yield data[0]
+            data = data[1:]
+        elif data[0] in ' \n':
+            data = data[1:]
+        elif data[0] == "'":
+            data = data[1:]
+            string = ''
+            while data[0] != "'":
+                string += data[0]
+                data = data[1:]
+            data = data[1:]
+            yield string
+
+def parse(tokens):
+    if tokens[0] == '{':
+        ret = OrderedDict()
+        tokens = tokens[1:]
+        while tokens[0] != '}':
+            key = tokens[0]
+            tokens = tokens[1:]
+
+            tokens = tokens[1:] # :
+
+            value, tokens = parse(tokens)
+
+            if tokens[0] == ',':
+                tokens = tokens[1:]
+
+            ret[key] = value
+        tokens = tokens[1:]
+        return ret, tokens
+    elif tokens[0] == '[':
+        ret = []
+        tokens = tokens[1:]
+        while tokens[0] != ']':
+            value, tokens = parse(tokens)
+            if tokens[0] == ',':
+                tokens = tokens[1:]
+            ret.append(value)
+        tokens = tokens[1:]
+        return ret, tokens
+    else:
+        return tokens[0], tokens[1:]
+
+def evaluate(string):
+    return parse(map(lambda x: x, tokenize(string)))[0]
+
+def parse_schema(fp):
+    exprs = []
+    expr = ''
+    expr_eval = None
+
+    for line in fp:
+        if line.startswith('#') or line == '\n':
+            continue
+
+        if line.startswith(' '):
+            expr += line
+        elif expr:
+            expr_eval = evaluate(expr)
+            if expr_eval.has_key('enum'):
+                add_enum(expr_eval['enum'])
+            elif expr_eval.has_key('union'):
+                add_enum('%sKind' % expr_eval['union'])
+            exprs.append(expr_eval)
+            expr = line
+        else:
+            expr += line
+
+    if expr:
+        expr_eval = evaluate(expr)
+        if expr_eval.has_key('enum'):
+            add_enum(expr_eval['enum'])
+        elif expr_eval.has_key('union'):
+            add_enum('%sKind' % expr_eval['union'])
+        exprs.append(expr_eval)
+
+    return exprs
+
+def parse_args(typeinfo):
+    for member in typeinfo:
+        argname = member
+        argentry = typeinfo[member]
+        optional = False
+        structured = False
+        if member.startswith('*'):
+            argname = member[1:]
+            optional = True
+        if isinstance(argentry, OrderedDict):
+            structured = True
+        yield (argname, argentry, optional, structured)
+
+def de_camel_case(name):
+    new_name = ''
+    for ch in name:
+        if ch.isupper() and new_name:
+            new_name += '_'
+        if ch == '-':
+            new_name += '_'
+        else:
+            new_name += ch.lower()
+    return new_name
+
+def camel_case(name):
+    new_name = ''
+    first = True
+    for ch in name:
+        if ch in ['_', '-']:
+            first = True
+        elif first:
+            new_name += ch.upper()
+            first = False
+        else:
+            new_name += ch.lower()
+    return new_name
+
+def c_var(name):
+    return '_'.join(name.split('-')).lstrip("*")
+
+def c_list_type(name):
+    return '%sList' % name
+
+def type_name(name):
+    if type(name) == list:
+        return c_list_type(name[0])
+    return name
+
+enum_types = []
+
+def add_enum(name):
+    global enum_types
+    enum_types.append(name)
+
+def is_enum(name):
+    global enum_types
+    return (name in enum_types)
+
+def c_type(name):
+    if name == 'str':
+        return 'char *'
+    elif name == 'int':
+        return 'int64_t'
+    elif name == 'bool':
+        return 'bool'
+    elif name == 'number':
+        return 'double'
+    elif type(name) == list:
+        return '%s *' % c_list_type(name[0])
+    elif is_enum(name):
+        return name
+    elif name == None or len(name) == 0:
+        return 'void'
+    elif name == name.upper():
+        return '%sEvent *' % camel_case(name)
+    else:
+        return '%s *' % name
+
+def genindent(count):
+    ret = ""
+    for i in range(count):
+        ret += " "
+    return ret
+
+indent_level = 0
+
+def push_indent(indent_amount=4):
+    global indent_level
+    indent_level += indent_amount
+
+def pop_indent(indent_amount=4):
+    global indent_level
+    indent_level -= indent_amount
+
+def cgen(code, **kwds):
+    indent = genindent(indent_level)
+    lines = code.split('\n')
+    lines = map(lambda x: indent + x, lines)
+    return '\n'.join(lines) % kwds + '\n'
+
+def mcgen(code, **kwds):
+    return cgen('\n'.join(code.split('\n')[1:-1]), **kwds)
+
+def basename(filename):
+    return filename.split("/")[-1]
+
+def guardname(filename):
+    return filename.replace("/", "_").replace("-", "_").split(".")[0].upper()
commit e89ac222aa3fe37b0cb0a98c572d80cd6b1729aa
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 14:50:38 2011 -0500

    qapi: add ordereddict.py helper library
    
    We need this to parse dictionaries with schema ordering intact so that C
    prototypes can be generated deterministically.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/scripts/ordereddict.py b/scripts/ordereddict.py
new file mode 100644
index 0000000..7242b50
--- /dev/null
+++ b/scripts/ordereddict.py
@@ -0,0 +1,127 @@
+# Copyright (c) 2009 Raymond Hettinger
+#
+# 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.
+
+from UserDict import DictMixin
+
+class OrderedDict(dict, DictMixin):
+
+    def __init__(self, *args, **kwds):
+        if len(args) > 1:
+            raise TypeError('expected at most 1 arguments, got %d' % len(args))
+        try:
+            self.__end
+        except AttributeError:
+            self.clear()
+        self.update(*args, **kwds)
+
+    def clear(self):
+        self.__end = end = []
+        end += [None, end, end]         # sentinel node for doubly linked list
+        self.__map = {}                 # key --> [key, prev, next]
+        dict.clear(self)
+
+    def __setitem__(self, key, value):
+        if key not in self:
+            end = self.__end
+            curr = end[1]
+            curr[2] = end[1] = self.__map[key] = [key, curr, end]
+        dict.__setitem__(self, key, value)
+
+    def __delitem__(self, key):
+        dict.__delitem__(self, key)
+        key, prev, next = self.__map.pop(key)
+        prev[2] = next
+        next[1] = prev
+
+    def __iter__(self):
+        end = self.__end
+        curr = end[2]
+        while curr is not end:
+            yield curr[0]
+            curr = curr[2]
+
+    def __reversed__(self):
+        end = self.__end
+        curr = end[1]
+        while curr is not end:
+            yield curr[0]
+            curr = curr[1]
+
+    def popitem(self, last=True):
+        if not self:
+            raise KeyError('dictionary is empty')
+        if last:
+            key = reversed(self).next()
+        else:
+            key = iter(self).next()
+        value = self.pop(key)
+        return key, value
+
+    def __reduce__(self):
+        items = [[k, self[k]] for k in self]
+        tmp = self.__map, self.__end
+        del self.__map, self.__end
+        inst_dict = vars(self).copy()
+        self.__map, self.__end = tmp
+        if inst_dict:
+            return (self.__class__, (items,), inst_dict)
+        return self.__class__, (items,)
+
+    def keys(self):
+        return list(self)
+
+    setdefault = DictMixin.setdefault
+    update = DictMixin.update
+    pop = DictMixin.pop
+    values = DictMixin.values
+    items = DictMixin.items
+    iterkeys = DictMixin.iterkeys
+    itervalues = DictMixin.itervalues
+    iteritems = DictMixin.iteritems
+
+    def __repr__(self):
+        if not self:
+            return '%s()' % (self.__class__.__name__,)
+        return '%s(%r)' % (self.__class__.__name__, self.items())
+
+    def copy(self):
+        return self.__class__(self)
+
+    @classmethod
+    def fromkeys(cls, iterable, value=None):
+        d = cls()
+        for key in iterable:
+            d[key] = value
+        return d
+
+    def __eq__(self, other):
+        if isinstance(other, OrderedDict):
+            if len(self) != len(other):
+                return False
+            for p, q in  zip(self.items(), other.items()):
+                if p != q:
+                    return False
+            return True
+        return dict.__eq__(self, other)
+
+    def __ne__(self, other):
+        return not self == other
commit ab02ab2aa7a36d78a579642caa404abd99acdc6e
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 14:50:37 2011 -0500

    qapi: add QMP dispatch functions
    
    Given an object recieved via QMP, this code uses the dispatch table
    provided by qmp_registry.c to call the corresponding marshalling/dispatch
    function and format return values/errors for delivery to the QMP.
    Currently only synchronous QMP functions are supported, but this will
    also be used for async QMP functions and QMP guest proxy dispatch as
    well.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index c918ee7..52ad77b 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -376,7 +376,7 @@ libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o
 # qapi
 
 qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o qmp-output-visitor.o qapi-dealloc-visitor.o
-qapi-nested-y += qmp-registry.o
+qapi-nested-y += qmp-registry.o qmp-dispatch.o
 qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))
 
 vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
diff --git a/qapi/qmp-core.h b/qapi/qmp-core.h
index 8b96d2c..f1c26e4 100644
--- a/qapi/qmp-core.h
+++ b/qapi/qmp-core.h
@@ -35,5 +35,7 @@ typedef struct QmpCommand
 
 void qmp_register_command(const char *name, QmpCommandFunc *fn);
 QmpCommand *qmp_find_command(const char *name);
+QObject *qmp_dispatch(QObject *request);
 
 #endif
+
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
new file mode 100644
index 0000000..5584693
--- /dev/null
+++ b/qapi/qmp-dispatch.c
@@ -0,0 +1,124 @@
+/*
+ * Core Definitions for QAPI/QMP Dispatch
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu-objects.h"
+#include "qapi/qmp-core.h"
+#include "json-parser.h"
+#include "error.h"
+#include "error_int.h"
+#include "qerror.h"
+
+static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp)
+{
+    const QDictEntry *ent;
+    const char *arg_name;
+    const QObject *arg_obj;
+    bool has_exec_key = false;
+    QDict *dict = NULL;
+
+    if (qobject_type(request) != QTYPE_QDICT) {
+        error_set(errp, QERR_QMP_BAD_INPUT_OBJECT,
+                  "request is not a dictionary");
+        return NULL;
+    }
+
+    dict = qobject_to_qdict(request);
+
+    for (ent = qdict_first(dict); ent;
+         ent = qdict_next(dict, ent)) {
+        arg_name = qdict_entry_key(ent);
+        arg_obj = qdict_entry_value(ent);
+
+        if (!strcmp(arg_name, "execute")) {
+            if (qobject_type(arg_obj) != QTYPE_QSTRING) {
+                error_set(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute",
+                          "string");
+                return NULL;
+            }
+            has_exec_key = true;
+        } else if (strcmp(arg_name, "arguments")) {
+            error_set(errp, QERR_QMP_EXTRA_MEMBER, arg_name);
+            return NULL;
+        }
+    }
+
+    if (!has_exec_key) {
+        error_set(errp, QERR_QMP_BAD_INPUT_OBJECT, "execute");
+        return NULL;
+    }
+
+    return dict;
+}
+
+static QObject *do_qmp_dispatch(QObject *request, Error **errp)
+{
+    const char *command;
+    QDict *args, *dict;
+    QmpCommand *cmd;
+    QObject *ret = NULL;
+
+
+    dict = qmp_dispatch_check_obj(request, errp);
+    if (!dict || error_is_set(errp)) {
+        return NULL;
+    }
+
+    command = qdict_get_str(dict, "execute");
+    cmd = qmp_find_command(command);
+    if (cmd == NULL) {
+        error_set(errp, QERR_COMMAND_NOT_FOUND, command);
+        return NULL;
+    }
+
+    if (!qdict_haskey(dict, "arguments")) {
+        args = qdict_new();
+    } else {
+        args = qdict_get_qdict(dict, "arguments");
+        QINCREF(args);
+    }
+
+    switch (cmd->type) {
+    case QCT_NORMAL:
+        cmd->fn(args, &ret, errp);
+        if (!error_is_set(errp) && ret == NULL) {
+            ret = QOBJECT(qdict_new());
+        }
+        break;
+    }
+
+    QDECREF(args);
+
+    return ret;
+}
+
+QObject *qmp_dispatch(QObject *request)
+{
+    Error *err = NULL;
+    QObject *ret;
+    QDict *rsp;
+
+    ret = do_qmp_dispatch(request, &err);
+
+    rsp = qdict_new();
+    if (err) {
+        qdict_put_obj(rsp, "error", error_get_qobject(err));
+        error_free(err);
+    } else if (ret) {
+        qdict_put_obj(rsp, "return", ret);
+    } else {
+        QDECREF(rsp);
+        return NULL;
+    }
+
+    return QOBJECT(rsp);
+}
commit 43c20a43ca4b3fa265469887186eb0fee68e4a0d
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 14:50:36 2011 -0500

    qapi: add QMP command registration/lookup functions
    
    Registration/lookup functions for that provide a lookup table for
    dispatching QMP commands.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index 92c7b56..c918ee7 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -376,6 +376,7 @@ libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o
 # qapi
 
 qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o qmp-output-visitor.o qapi-dealloc-visitor.o
+qapi-nested-y += qmp-registry.o
 qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))
 
 vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
diff --git a/qapi/qmp-core.h b/qapi/qmp-core.h
new file mode 100644
index 0000000..8b96d2c
--- /dev/null
+++ b/qapi/qmp-core.h
@@ -0,0 +1,39 @@
+/*
+ * Core Definitions for QAPI/QMP Dispatch
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef QMP_CORE_H
+#define QMP_CORE_H
+
+#include "qobject.h"
+#include "qdict.h"
+#include "error.h"
+
+typedef void (QmpCommandFunc)(QDict *, QObject **, Error **);
+
+typedef enum QmpCommandType
+{
+    QCT_NORMAL,
+} QmpCommandType;
+
+typedef struct QmpCommand
+{
+    const char *name;
+    QmpCommandType type;
+    QmpCommandFunc *fn;
+    QTAILQ_ENTRY(QmpCommand) node;
+} QmpCommand;
+
+void qmp_register_command(const char *name, QmpCommandFunc *fn);
+QmpCommand *qmp_find_command(const char *name);
+
+#endif
diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c
new file mode 100644
index 0000000..3fe8866
--- /dev/null
+++ b/qapi/qmp-registry.c
@@ -0,0 +1,40 @@
+/*
+ * Core Definitions for QAPI/QMP Dispatch
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *  Michael Roth      <mdroth at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qapi/qmp-core.h"
+
+static QTAILQ_HEAD(, QmpCommand) qmp_commands =
+    QTAILQ_HEAD_INITIALIZER(qmp_commands);
+
+void qmp_register_command(const char *name, QmpCommandFunc *fn)
+{
+    QmpCommand *cmd = qemu_mallocz(sizeof(*cmd));
+
+    cmd->name = name;
+    cmd->type = QCT_NORMAL;
+    cmd->fn = fn;
+    QTAILQ_INSERT_TAIL(&qmp_commands, cmd, node);
+}
+
+QmpCommand *qmp_find_command(const char *name)
+{
+    QmpCommand *i;
+
+    QTAILQ_FOREACH(i, &qmp_commands, node) {
+        if (strcmp(i->name, name) == 0) {
+            return i;
+        }
+    }
+    return NULL;
+}
commit d5f3c29cf8d59fad4f3c657fc0a26510043bec65
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 14:50:35 2011 -0500

    qapi: add QAPI dealloc visitor
    
    Type of Visitor class that can be passed into a qapi-generated C
    type's visitor function to free() any heap-allocated data types.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index 301d565..92c7b56 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -375,7 +375,7 @@ libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o
 ######################################################################
 # qapi
 
-qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o qmp-output-visitor.o
+qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o qmp-output-visitor.o qapi-dealloc-visitor.o
 qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))
 
 vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c
new file mode 100644
index 0000000..8cde4dd
--- /dev/null
+++ b/qapi/qapi-dealloc-visitor.c
@@ -0,0 +1,147 @@
+/*
+ * Dealloc Visitor
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Michael Roth   <mdroth at linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qapi-dealloc-visitor.h"
+#include "qemu-queue.h"
+#include "qemu-common.h"
+#include "qemu-objects.h"
+
+typedef struct StackEntry
+{
+    void *value;
+    QTAILQ_ENTRY(StackEntry) node;
+} StackEntry;
+
+struct QapiDeallocVisitor
+{
+    Visitor visitor;
+    QTAILQ_HEAD(, StackEntry) stack;
+};
+
+static QapiDeallocVisitor *to_qov(Visitor *v)
+{
+    return container_of(v, QapiDeallocVisitor, visitor);
+}
+
+static void qapi_dealloc_push(QapiDeallocVisitor *qov, void *value)
+{
+    StackEntry *e = qemu_mallocz(sizeof(*e));
+
+    e->value = value;
+    QTAILQ_INSERT_HEAD(&qov->stack, e, node);
+}
+
+static void *qapi_dealloc_pop(QapiDeallocVisitor *qov)
+{
+    StackEntry *e = QTAILQ_FIRST(&qov->stack);
+    QObject *value;
+    QTAILQ_REMOVE(&qov->stack, e, node);
+    value = e->value;
+    qemu_free(e);
+    return value;
+}
+
+static void qapi_dealloc_start_struct(Visitor *v, void **obj, const char *kind,
+                                      const char *name, size_t unused,
+                                      Error **errp)
+{
+    QapiDeallocVisitor *qov = to_qov(v);
+    qapi_dealloc_push(qov, obj);
+}
+
+static void qapi_dealloc_end_struct(Visitor *v, Error **errp)
+{
+    QapiDeallocVisitor *qov = to_qov(v);
+    void **obj = qapi_dealloc_pop(qov);
+    if (obj) {
+        qemu_free(*obj);
+    }
+}
+
+static void qapi_dealloc_start_list(Visitor *v, const char *name, Error **errp)
+{
+}
+
+static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **list,
+                                           Error **errp)
+{
+    GenericList *retval = *list;
+    qemu_free(retval->value);
+    *list = retval->next;
+    return retval;
+}
+
+static void qapi_dealloc_end_list(Visitor *v, Error **errp)
+{
+}
+
+static void qapi_dealloc_type_str(Visitor *v, char **obj, const char *name,
+                                  Error **errp)
+{
+    if (obj) {
+        qemu_free(*obj);
+    }
+}
+
+static void qapi_dealloc_type_int(Visitor *v, int64_t *obj, const char *name,
+                                  Error **errp)
+{
+}
+
+static void qapi_dealloc_type_bool(Visitor *v, bool *obj, const char *name,
+                                   Error **errp)
+{
+}
+
+static void qapi_dealloc_type_number(Visitor *v, double *obj, const char *name,
+                                     Error **errp)
+{
+}
+
+static void qapi_dealloc_type_enum(Visitor *v, int *obj, const char *strings[],
+                                   const char *kind, const char *name,
+                                   Error **errp)
+{
+}
+
+Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v)
+{
+    return &v->visitor;
+}
+
+void qapi_dealloc_visitor_cleanup(QapiDeallocVisitor *v)
+{
+    qemu_free(v);
+}
+
+QapiDeallocVisitor *qapi_dealloc_visitor_new(void)
+{
+    QapiDeallocVisitor *v;
+
+    v = qemu_mallocz(sizeof(*v));
+
+    v->visitor.start_struct = qapi_dealloc_start_struct;
+    v->visitor.end_struct = qapi_dealloc_end_struct;
+    v->visitor.start_list = qapi_dealloc_start_list;
+    v->visitor.next_list = qapi_dealloc_next_list;
+    v->visitor.end_list = qapi_dealloc_end_list;
+    v->visitor.type_enum = qapi_dealloc_type_enum;
+    v->visitor.type_int = qapi_dealloc_type_int;
+    v->visitor.type_bool = qapi_dealloc_type_bool;
+    v->visitor.type_str = qapi_dealloc_type_str;
+    v->visitor.type_number = qapi_dealloc_type_number;
+
+    QTAILQ_INIT(&v->stack);
+
+    return v;
+}
diff --git a/qapi/qapi-dealloc-visitor.h b/qapi/qapi-dealloc-visitor.h
new file mode 100644
index 0000000..5842bc7
--- /dev/null
+++ b/qapi/qapi-dealloc-visitor.h
@@ -0,0 +1,26 @@
+/*
+ * Dealloc Visitor
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Michael Roth   <mdroth at linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef QAPI_DEALLOC_VISITOR_H
+#define QAPI_DEALLOC_VISITOR_H
+
+#include "qapi-visit-core.h"
+
+typedef struct QapiDeallocVisitor QapiDeallocVisitor;
+
+QapiDeallocVisitor *qapi_dealloc_visitor_new(void);
+void qapi_dealloc_visitor_cleanup(QapiDeallocVisitor *d);
+
+Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v);
+
+#endif
commit e4e6aa14ed377d808aba4643cd922403606d4dee
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 14:50:34 2011 -0500

    qapi: add QMP output visitor
    
    Type of Visiter class that serves as the inverse of the input visitor:
    it takes a series of native C types and uses their values to construct a
    corresponding QObject. The command marshaling/dispatcher functions will
    use this to convert the output of QMP functions into a QObject that can
    be sent over the wire.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index d86ecc1..301d565 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -375,7 +375,7 @@ libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o
 ######################################################################
 # qapi
 
-qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o
+qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o qmp-output-visitor.o
 qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))
 
 vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
diff --git a/qapi/qmp-output-visitor.c b/qapi/qmp-output-visitor.c
new file mode 100644
index 0000000..c398cac
--- /dev/null
+++ b/qapi/qmp-output-visitor.c
@@ -0,0 +1,239 @@
+/*
+ * Core Definitions for QAPI/QMP Command Registry
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qmp-output-visitor.h"
+#include "qemu-queue.h"
+#include "qemu-common.h"
+#include "qemu-objects.h"
+#include "qerror.h"
+
+typedef struct QStackEntry
+{
+    QObject *value;
+    QTAILQ_ENTRY(QStackEntry) node;
+} QStackEntry;
+
+typedef QTAILQ_HEAD(QStack, QStackEntry) QStack;
+
+struct QmpOutputVisitor
+{
+    Visitor visitor;
+    QStack stack;
+};
+
+#define qmp_output_add(qov, name, value) \
+    qmp_output_add_obj(qov, name, QOBJECT(value))
+#define qmp_output_push(qov, value) qmp_output_push_obj(qov, QOBJECT(value))
+
+static QmpOutputVisitor *to_qov(Visitor *v)
+{
+    return container_of(v, QmpOutputVisitor, visitor);
+}
+
+static void qmp_output_push_obj(QmpOutputVisitor *qov, QObject *value)
+{
+    QStackEntry *e = qemu_mallocz(sizeof(*e));
+
+    e->value = value;
+    QTAILQ_INSERT_HEAD(&qov->stack, e, node);
+}
+
+static QObject *qmp_output_pop(QmpOutputVisitor *qov)
+{
+    QStackEntry *e = QTAILQ_FIRST(&qov->stack);
+    QObject *value;
+    QTAILQ_REMOVE(&qov->stack, e, node);
+    value = e->value;
+    qemu_free(e);
+    return value;
+}
+
+static QObject *qmp_output_first(QmpOutputVisitor *qov)
+{
+    QStackEntry *e = QTAILQ_LAST(&qov->stack, QStack);
+    return e->value;
+}
+
+static QObject *qmp_output_last(QmpOutputVisitor *qov)
+{
+    QStackEntry *e = QTAILQ_FIRST(&qov->stack);
+    return e->value;
+}
+
+static void qmp_output_add_obj(QmpOutputVisitor *qov, const char *name,
+                               QObject *value)
+{
+    QObject *cur;
+
+    if (QTAILQ_EMPTY(&qov->stack)) {
+        qmp_output_push_obj(qov, value);
+        return;
+    }
+
+    cur = qmp_output_last(qov);
+
+    switch (qobject_type(cur)) {
+    case QTYPE_QDICT:
+        qdict_put_obj(qobject_to_qdict(cur), name, value);
+        break;
+    case QTYPE_QLIST:
+        qlist_append_obj(qobject_to_qlist(cur), value);
+        break;
+    default:
+        qobject_decref(qmp_output_pop(qov));
+        qmp_output_push_obj(qov, value);
+        break;
+    }
+}
+
+static void qmp_output_start_struct(Visitor *v, void **obj, const char *kind,
+                                    const char *name, size_t unused,
+                                    Error **errp)
+{
+    QmpOutputVisitor *qov = to_qov(v);
+    QDict *dict = qdict_new();
+
+    qmp_output_add(qov, name, dict);
+    qmp_output_push(qov, dict);
+}
+
+static void qmp_output_end_struct(Visitor *v, Error **errp)
+{
+    QmpOutputVisitor *qov = to_qov(v);
+    qmp_output_pop(qov);
+}
+
+static void qmp_output_start_list(Visitor *v, const char *name, Error **errp)
+{
+    QmpOutputVisitor *qov = to_qov(v);
+    QList *list = qlist_new();
+
+    qmp_output_add(qov, name, list);
+    qmp_output_push(qov, list);
+}
+
+static GenericList *qmp_output_next_list(Visitor *v, GenericList **list,
+                                         Error **errp)
+{
+    GenericList *retval = *list;
+    *list = retval->next;
+    return retval;
+}
+
+static void qmp_output_end_list(Visitor *v, Error **errp)
+{
+    QmpOutputVisitor *qov = to_qov(v);
+    qmp_output_pop(qov);
+}
+
+static void qmp_output_type_int(Visitor *v, int64_t *obj, const char *name,
+                                Error **errp)
+{
+    QmpOutputVisitor *qov = to_qov(v);
+    qmp_output_add(qov, name, qint_from_int(*obj));
+}
+
+static void qmp_output_type_bool(Visitor *v, bool *obj, const char *name,
+                                 Error **errp)
+{
+    QmpOutputVisitor *qov = to_qov(v);
+    qmp_output_add(qov, name, qbool_from_int(*obj));
+}
+
+static void qmp_output_type_str(Visitor *v, char **obj, const char *name,
+                                Error **errp)
+{
+    QmpOutputVisitor *qov = to_qov(v);
+    if (*obj) {
+        qmp_output_add(qov, name, qstring_from_str(*obj));
+    } else {
+        qmp_output_add(qov, name, qstring_from_str(""));
+    }
+}
+
+static void qmp_output_type_number(Visitor *v, double *obj, const char *name,
+                                   Error **errp)
+{
+    QmpOutputVisitor *qov = to_qov(v);
+    qmp_output_add(qov, name, qfloat_from_double(*obj));
+}
+
+static void qmp_output_type_enum(Visitor *v, int *obj, const char *strings[],
+                                 const char *kind, const char *name,
+                                 Error **errp)
+{
+    int i = 0;
+    int value = *obj;
+    char *enum_str;
+
+    assert(strings);
+    while (strings[i++] != NULL);
+    if (value >= i - 1) {
+        error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
+        return;
+    }
+
+    enum_str = (char *)strings[value];
+    qmp_output_type_str(v, &enum_str, name, errp);
+}
+
+QObject *qmp_output_get_qobject(QmpOutputVisitor *qov)
+{
+    QObject *obj = qmp_output_first(qov);
+    if (obj) {
+        qobject_incref(obj);
+    }
+    return obj;
+}
+
+Visitor *qmp_output_get_visitor(QmpOutputVisitor *v)
+{
+    return &v->visitor;
+}
+
+void qmp_output_visitor_cleanup(QmpOutputVisitor *v)
+{
+    QStackEntry *e, *tmp;
+
+    QTAILQ_FOREACH_SAFE(e, &v->stack, node, tmp) {
+        QTAILQ_REMOVE(&v->stack, e, node);
+        if (e->value) {
+            qobject_decref(e->value);
+        }
+        qemu_free(e);
+    }
+
+    qemu_free(v);
+}
+
+QmpOutputVisitor *qmp_output_visitor_new(void)
+{
+    QmpOutputVisitor *v;
+
+    v = qemu_mallocz(sizeof(*v));
+
+    v->visitor.start_struct = qmp_output_start_struct;
+    v->visitor.end_struct = qmp_output_end_struct;
+    v->visitor.start_list = qmp_output_start_list;
+    v->visitor.next_list = qmp_output_next_list;
+    v->visitor.end_list = qmp_output_end_list;
+    v->visitor.type_enum = qmp_output_type_enum;
+    v->visitor.type_int = qmp_output_type_int;
+    v->visitor.type_bool = qmp_output_type_bool;
+    v->visitor.type_str = qmp_output_type_str;
+    v->visitor.type_number = qmp_output_type_number;
+
+    QTAILQ_INIT(&v->stack);
+
+    return v;
+}
diff --git a/qapi/qmp-output-visitor.h b/qapi/qmp-output-visitor.h
new file mode 100644
index 0000000..4a649c2
--- /dev/null
+++ b/qapi/qmp-output-visitor.h
@@ -0,0 +1,28 @@
+/*
+ * Output Visitor
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef QMP_OUTPUT_VISITOR_H
+#define QMP_OUTPUT_VISITOR_H
+
+#include "qapi-visit-core.h"
+#include "qobject.h"
+
+typedef struct QmpOutputVisitor QmpOutputVisitor;
+
+QmpOutputVisitor *qmp_output_visitor_new(void);
+void qmp_output_visitor_cleanup(QmpOutputVisitor *v);
+
+QObject *qmp_output_get_qobject(QmpOutputVisitor *v);
+Visitor *qmp_output_get_visitor(QmpOutputVisitor *v);
+
+#endif
commit c40cc0a0ddbcda2af446b40271025b3dbee119ce
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 14:50:33 2011 -0500

    qapi: add QMP input visitor
    
    A type of Visiter class that is used to walk a qobject's
    structure and assign each entry to the corresponding native C type.
    Command marshaling function will use this to pull out QMP command
    parameters recieved over the wire and pass them as native arguments
    to the corresponding C functions.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index 3b68f59..d86ecc1 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -375,7 +375,7 @@ libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o
 ######################################################################
 # qapi
 
-qapi-nested-y = qapi-visit-core.o
+qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o
 qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))
 
 vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
new file mode 100644
index 0000000..6a1adc9
--- /dev/null
+++ b/qapi/qmp-input-visitor.c
@@ -0,0 +1,301 @@
+/*
+ * Input Visitor
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qmp-input-visitor.h"
+#include "qemu-queue.h"
+#include "qemu-common.h"
+#include "qemu-objects.h"
+#include "qerror.h"
+
+#define QIV_STACK_SIZE 1024
+
+typedef struct StackObject
+{
+    const QObject *obj;
+    const  QListEntry *entry;
+} StackObject;
+
+struct QmpInputVisitor
+{
+    Visitor visitor;
+    QObject *obj;
+    StackObject stack[QIV_STACK_SIZE];
+    int nb_stack;
+};
+
+static QmpInputVisitor *to_qiv(Visitor *v)
+{
+    return container_of(v, QmpInputVisitor, visitor);
+}
+
+static const QObject *qmp_input_get_object(QmpInputVisitor *qiv,
+                                           const char *name)
+{
+    const QObject *qobj;
+
+    if (qiv->nb_stack == 0) {
+        qobj = qiv->obj;
+    } else {
+        qobj = qiv->stack[qiv->nb_stack - 1].obj;
+    }
+
+    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;
+}
+
+static void qmp_input_push(QmpInputVisitor *qiv, const QObject *obj, Error **errp)
+{
+    qiv->stack[qiv->nb_stack].obj = obj;
+    if (qobject_type(obj) == QTYPE_QLIST) {
+        qiv->stack[qiv->nb_stack].entry = qlist_first(qobject_to_qlist(obj));
+    }
+    qiv->nb_stack++;
+
+    if (qiv->nb_stack >= QIV_STACK_SIZE) {
+        error_set(errp, QERR_BUFFER_OVERRUN);
+        return;
+    }
+}
+
+static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp)
+{
+    qiv->nb_stack--;
+    if (qiv->nb_stack < 0) {
+        error_set(errp, QERR_BUFFER_OVERRUN);
+        return;
+    }
+}
+
+static void qmp_input_start_struct(Visitor *v, void **obj, const char *kind,
+                                   const char *name, size_t size, Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+    const QObject *qobj = qmp_input_get_object(qiv, name);
+
+    if (!qobj || qobject_type(qobj) != QTYPE_QDICT) {
+        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+                  "QDict");
+        return;
+    }
+
+    qmp_input_push(qiv, qobj, errp);
+    if (error_is_set(errp)) {
+        return;
+    }
+
+    if (obj) {
+        *obj = qemu_mallocz(size);
+    }
+}
+
+static void qmp_input_end_struct(Visitor *v, Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+
+    qmp_input_pop(qiv, errp);
+}
+
+static void qmp_input_start_list(Visitor *v, const char *name, Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+    const QObject *qobj = qmp_input_get_object(qiv, name);
+
+    if (!qobj || qobject_type(qobj) != QTYPE_QLIST) {
+        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+                  "list");
+        return;
+    }
+
+    qmp_input_push(qiv, qobj, errp);
+}
+
+static GenericList *qmp_input_next_list(Visitor *v, GenericList **list,
+                                        Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+    GenericList *entry;
+    StackObject *so = &qiv->stack[qiv->nb_stack - 1];
+
+    if (so->entry == NULL) {
+        return NULL;
+    }
+
+    entry = qemu_mallocz(sizeof(*entry));
+    if (*list) {
+        so->entry = qlist_next(so->entry);
+        if (so->entry == NULL) {
+            qemu_free(entry);
+            return NULL;
+        }
+        (*list)->next = entry;
+    }
+    *list = entry;
+
+
+    return entry;
+}
+
+static void qmp_input_end_list(Visitor *v, Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+
+    qmp_input_pop(qiv, errp);
+}
+
+static void qmp_input_type_int(Visitor *v, int64_t *obj, const char *name,
+                               Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+    const QObject *qobj = qmp_input_get_object(qiv, name);
+
+    if (!qobj || qobject_type(qobj) != QTYPE_QINT) {
+        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+                  "integer");
+        return;
+    }
+
+    *obj = qint_get_int(qobject_to_qint(qobj));
+}
+
+static void qmp_input_type_bool(Visitor *v, bool *obj, const char *name,
+                                Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+    const QObject *qobj = qmp_input_get_object(qiv, name);
+
+    if (!qobj || qobject_type(qobj) != QTYPE_QBOOL) {
+        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+                  "boolean");
+        return;
+    }
+
+    *obj = qbool_get_int(qobject_to_qbool(qobj));
+}
+
+static void qmp_input_type_str(Visitor *v, char **obj, const char *name,
+                               Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+    const QObject *qobj = qmp_input_get_object(qiv, name);
+
+    if (!qobj || qobject_type(qobj) != QTYPE_QSTRING) {
+        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+                  "string");
+        return;
+    }
+
+    *obj = qemu_strdup(qstring_get_str(qobject_to_qstring(qobj)));
+}
+
+static void qmp_input_type_number(Visitor *v, double *obj, const char *name,
+                                  Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+    const QObject *qobj = qmp_input_get_object(qiv, name);
+
+    if (!qobj || qobject_type(qobj) != QTYPE_QFLOAT) {
+        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+                  "double");
+        return;
+    }
+
+    *obj = qfloat_get_double(qobject_to_qfloat(qobj));
+}
+
+static void qmp_input_type_enum(Visitor *v, int *obj, const char *strings[],
+                                const char *kind, const char *name,
+                                Error **errp)
+{
+    int64_t value = 0;
+    char *enum_str;
+
+    assert(strings);
+
+    qmp_input_type_str(v, &enum_str, name, errp);
+    if (error_is_set(errp)) {
+        return;
+    }
+
+    while (strings[value] != NULL) {
+        if (strcmp(strings[value], enum_str) == 0) {
+            break;
+        }
+        value++;
+    }
+
+    if (strings[value] == NULL) {
+        error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
+        return;
+    }
+
+    *obj = value;
+}
+
+static void qmp_input_start_optional(Visitor *v, bool *present,
+                                     const char *name, Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+    const QObject *qobj = qmp_input_get_object(qiv, name);
+
+    if (!qobj) {
+        *present = false;
+        return;
+    }
+
+    *present = true;
+}
+
+static void qmp_input_end_optional(Visitor *v, Error **errp)
+{
+}
+
+Visitor *qmp_input_get_visitor(QmpInputVisitor *v)
+{
+    return &v->visitor;
+}
+
+void qmp_input_visitor_cleanup(QmpInputVisitor *v)
+{
+    qobject_decref(v->obj);
+    qemu_free(v);
+}
+
+QmpInputVisitor *qmp_input_visitor_new(QObject *obj)
+{
+    QmpInputVisitor *v;
+
+    v = qemu_mallocz(sizeof(*v));
+
+    v->visitor.start_struct = qmp_input_start_struct;
+    v->visitor.end_struct = qmp_input_end_struct;
+    v->visitor.start_list = qmp_input_start_list;
+    v->visitor.next_list = qmp_input_next_list;
+    v->visitor.end_list = qmp_input_end_list;
+    v->visitor.type_enum = qmp_input_type_enum;
+    v->visitor.type_int = qmp_input_type_int;
+    v->visitor.type_bool = qmp_input_type_bool;
+    v->visitor.type_str = qmp_input_type_str;
+    v->visitor.type_number = qmp_input_type_number;
+    v->visitor.start_optional = qmp_input_start_optional;
+    v->visitor.end_optional = qmp_input_end_optional;
+
+    v->obj = obj;
+    qobject_incref(v->obj);
+
+    return v;
+}
diff --git a/qapi/qmp-input-visitor.h b/qapi/qmp-input-visitor.h
new file mode 100644
index 0000000..3f798f0
--- /dev/null
+++ b/qapi/qmp-input-visitor.h
@@ -0,0 +1,27 @@
+/*
+ * Input Visitor
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef QMP_INPUT_VISITOR_H
+#define QMP_INPUT_VISITOR_H
+
+#include "qapi-visit-core.h"
+#include "qobject.h"
+
+typedef struct QmpInputVisitor QmpInputVisitor;
+
+QmpInputVisitor *qmp_input_visitor_new(QObject *obj);
+void qmp_input_visitor_cleanup(QmpInputVisitor *v);
+
+Visitor *qmp_input_get_visitor(QmpInputVisitor *v);
+
+#endif
diff --git a/qerror.h b/qerror.h
index 16c830d..9a9fa5b 100644
--- a/qerror.h
+++ b/qerror.h
@@ -124,6 +124,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_JSON_PARSE_ERROR \
     "{ 'class': 'JSONParseError', 'data': { 'message': %s } }"
 
+#define QERR_BUFFER_OVERRUN \
+    "{ 'class': 'BufferOverrun', 'data': {} }"
+
 #define QERR_KVM_MISSING_CAP \
     "{ 'class': 'KVMMissingCap', 'data': { 'capability': %s, 'feature': %s } }"
 
commit 2345c77c6d383bd804527720551b79b1d0400693
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 14:50:32 2011 -0500

    qapi: add QAPI visitor core
    
    Base definitions/includes for Visiter interface used by generated
    visiter/marshalling code.
    
    Includes a GenericList type. Our lists require an embedded element.
    Since these types are generated, if you want to use them in a different
    type of data structure, there's no easy way to add another embedded
    element. The solution is to have non-embedded lists and that what this is.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index 55d18bb..3b68f59 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -372,6 +372,12 @@ endif
 
 libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o card_7816.o
 
+######################################################################
+# qapi
+
+qapi-nested-y = qapi-visit-core.o
+qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))
+
 vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 
 vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
diff --git a/configure b/configure
index c0c8fdf..ad1e1e1 100755
--- a/configure
+++ b/configure
@@ -3486,6 +3486,7 @@ DIRS="tests tests/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"
 FILES="Makefile tests/Makefile"
 FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
 FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
diff --git a/qapi/qapi-types-core.h b/qapi/qapi-types-core.h
new file mode 100644
index 0000000..a79bc2b
--- /dev/null
+++ b/qapi/qapi-types-core.h
@@ -0,0 +1,20 @@
+/*
+ * Core Definitions for QAPI-generated Types
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef QAPI_TYPES_CORE_H
+#define QAPI_TYPES_CORE_H
+
+#include "qemu-common.h"
+#include "error.h"
+
+#endif
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
new file mode 100644
index 0000000..ddef3ed
--- /dev/null
+++ b/qapi/qapi-visit-core.c
@@ -0,0 +1,118 @@
+/*
+ * Core Definitions for QAPI Visitor Classes
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qapi/qapi-visit-core.h"
+
+void visit_start_handle(Visitor *v, void **obj, const char *kind,
+                        const char *name, Error **errp)
+{
+    if (!error_is_set(errp) && v->start_handle) {
+        v->start_handle(v, obj, kind, name, errp);
+    }
+}
+
+void visit_end_handle(Visitor *v, Error **errp)
+{
+    if (!error_is_set(errp) && v->end_handle) {
+        v->end_handle(v, errp);
+    }
+}
+
+void visit_start_struct(Visitor *v, void **obj, const char *kind,
+                        const char *name, size_t size, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->start_struct(v, obj, kind, name, size, errp);
+    }
+}
+
+void visit_end_struct(Visitor *v, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->end_struct(v, errp);
+    }
+}
+
+void visit_start_list(Visitor *v, const char *name, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->start_list(v, name, errp);
+    }
+}
+
+GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        return v->next_list(v, list, errp);
+    }
+
+    return 0;
+}
+
+void visit_end_list(Visitor *v, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->end_list(v, errp);
+    }
+}
+
+void visit_start_optional(Visitor *v, bool *present, const char *name,
+                          Error **errp)
+{
+    if (!error_is_set(errp) && v->start_optional) {
+        v->start_optional(v, present, name, errp);
+    }
+}
+
+void visit_end_optional(Visitor *v, Error **errp)
+{
+    if (!error_is_set(errp) && v->end_optional) {
+        v->end_optional(v, errp);
+    }
+}
+
+void visit_type_enum(Visitor *v, int *obj, const char *strings[],
+                     const char *kind, const char *name, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->type_enum(v, obj, strings, kind, name, errp);
+    }
+}
+
+void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->type_int(v, obj, name, errp);
+    }
+}
+
+void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->type_bool(v, obj, name, errp);
+    }
+}
+
+void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->type_str(v, obj, name, errp);
+    }
+}
+
+void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->type_number(v, obj, name, errp);
+    }
+}
diff --git a/qapi/qapi-visit-core.h b/qapi/qapi-visit-core.h
new file mode 100644
index 0000000..e850746
--- /dev/null
+++ b/qapi/qapi-visit-core.h
@@ -0,0 +1,76 @@
+/*
+ * Core Definitions for QAPI Visitor Classes
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+#ifndef QAPI_VISITOR_CORE_H
+#define QAPI_VISITOR_CORE_H
+
+#include "qapi/qapi-types-core.h"
+#include <stdlib.h>
+
+typedef struct GenericList
+{
+    void *value;
+    struct GenericList *next;
+} GenericList;
+
+typedef struct Visitor Visitor;
+
+struct Visitor
+{
+    /* Must be set */
+    void (*start_struct)(Visitor *v, void **obj, const char *kind,
+                         const char *name, size_t size, Error **errp);
+    void (*end_struct)(Visitor *v, Error **errp);
+
+    void (*start_list)(Visitor *v, const char *name, Error **errp);
+    GenericList *(*next_list)(Visitor *v, GenericList **list, Error **errp);
+    void (*end_list)(Visitor *v, Error **errp);
+
+    void (*type_enum)(Visitor *v, int *obj, const char *strings[],
+                      const char *kind, const char *name, Error **errp);
+
+    void (*type_int)(Visitor *v, int64_t *obj, const char *name, Error **errp);
+    void (*type_bool)(Visitor *v, bool *obj, const char *name, Error **errp);
+    void (*type_str)(Visitor *v, char **obj, const char *name, Error **errp);
+    void (*type_number)(Visitor *v, double *obj, const char *name,
+                        Error **errp);
+
+    /* May be NULL */
+    void (*start_optional)(Visitor *v, bool *present, const char *name,
+                           Error **errp);
+    void (*end_optional)(Visitor *v, Error **errp);
+
+    void (*start_handle)(Visitor *v, void **obj, const char *kind,
+                         const char *name, Error **errp);
+    void (*end_handle)(Visitor *v, Error **errp);
+};
+
+void visit_start_handle(Visitor *v, void **obj, const char *kind,
+                        const char *name, Error **errp);
+void visit_end_handle(Visitor *v, Error **errp);
+void visit_start_struct(Visitor *v, void **obj, const char *kind,
+                        const char *name, size_t size, Error **errp);
+void visit_end_struct(Visitor *v, Error **errp);
+void visit_start_list(Visitor *v, const char *name, Error **errp);
+GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp);
+void visit_end_list(Visitor *v, Error **errp);
+void visit_start_optional(Visitor *v, bool *present, const char *name,
+                          Error **errp);
+void visit_end_optional(Visitor *v, Error **errp);
+void visit_type_enum(Visitor *v, int *obj, const char *strings[],
+                     const char *kind, const char *name, Error **errp);
+void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp);
+void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp);
+void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp);
+void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp);
+
+#endif
commit c7aa841e9f75f0ff77fec9f918779b1951ab6b9d
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 14:50:31 2011 -0500

    qapi: add module init types for qapi
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/module.h b/module.h
index 9263f1c..ef66730 100644
--- a/module.h
+++ b/module.h
@@ -24,12 +24,14 @@ typedef enum {
     MODULE_INIT_BLOCK,
     MODULE_INIT_DEVICE,
     MODULE_INIT_MACHINE,
+    MODULE_INIT_QAPI,
     MODULE_INIT_MAX
 } module_init_type;
 
 #define block_init(function) module_init(function, MODULE_INIT_BLOCK)
 #define device_init(function) module_init(function, MODULE_INIT_DEVICE)
 #define machine_init(function) module_init(function, MODULE_INIT_MACHINE)
+#define qapi_init(function) module_init(function, MODULE_INIT_QAPI)
 
 void register_module_init(void (*fn)(void), module_init_type type);
 
commit 54d83804a1f69e932e014842e7e7a4744334123d
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Jul 19 14:50:30 2011 -0500

    qlist: add qlist_first()/qlist_next()
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/qlist.h b/qlist.h
index dbe7b92..d426bd4 100644
--- a/qlist.h
+++ b/qlist.h
@@ -16,6 +16,7 @@
 #include "qobject.h"
 #include "qemu-queue.h"
 #include "qemu-common.h"
+#include "qemu-queue.h"
 
 typedef struct QListEntry {
     QObject *value;
@@ -50,4 +51,14 @@ QObject *qlist_peek(QList *qlist);
 int qlist_empty(const QList *qlist);
 QList *qobject_to_qlist(const QObject *obj);
 
+static inline const QListEntry *qlist_first(const QList *qlist)
+{
+    return QTAILQ_FIRST(&qlist->head);
+}
+
+static inline const QListEntry *qlist_next(const QListEntry *entry)
+{
+    return QTAILQ_NEXT(entry, next);
+}
+
 #endif /* QLIST_H */
commit e18df14185e817ba735bce57ecdef9a55fb3d093
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jul 19 14:50:29 2011 -0500

    Add hard build dependency on glib
    
    GLib is an extremely common library that has a portable thread implementation
    along with tons of other goodies.
    
    GLib and GObject have a fantastic amount of infrastructure we can leverage in
    QEMU including an object oriented programming infrastructure.
    
    Short term, it has a very nice thread pool implementation that we could leverage
    in something like virtio-9p.  It also has a test harness implementation that
    this series will use.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/Makefile b/Makefile
index b3ffbe2..42ae4e5 100644
--- a/Makefile
+++ b/Makefile
@@ -106,6 +106,8 @@ audio/audio.o audio/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS)
 
 QEMU_CFLAGS+=$(CURL_CFLAGS)
 
+QEMU_CFLAGS+=$(GLIB_CFLAGS)
+
 ui/cocoa.o: ui/cocoa.m
 
 ui/sdl.o audio/sdlaudio.o ui/sdl_zoom.o baum.o: QEMU_CFLAGS += $(SDL_CFLAGS)
diff --git a/Makefile.objs b/Makefile.objs
index c43ed05..55d18bb 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -376,3 +376,4 @@ vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 
 vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
 
+vl.o: QEMU_CFLAGS+=$(GLIB_CFLAGS)
diff --git a/Makefile.target b/Makefile.target
index e20a313..cde509b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -204,6 +204,7 @@ QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
 QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
 QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
 QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
+QEMU_CFLAGS += $(GLIB_CFLAGS)
 
 # xen support
 obj-$(CONFIG_XEN) += xen-all.o xen_machine_pv.o xen_domainbuild.o xen-mapcache.o
diff --git a/configure b/configure
index e57efb1..c0c8fdf 100755
--- a/configure
+++ b/configure
@@ -1803,6 +1803,18 @@ EOF
 fi
 
 ##########################################
+# glib support probe
+if $pkg_config --modversion gthread-2.0 gio-2.0 > /dev/null 2>&1 ; then
+    glib_cflags=`$pkg_config --cflags gthread-2.0 gio-2.0 2>/dev/null`
+    glib_libs=`$pkg_config --libs gthread-2.0 gio-2.0 2>/dev/null`
+    libs_softmmu="$glib_libs $libs_softmmu"
+    libs_tools="$glib_libs $libs_tools"
+else
+    echo "glib-2.0 required to compile QEMU"
+    exit 1
+fi
+
+##########################################
 # pthread probe
 PTHREADLIBS_LIST="-lpthread -lpthreadGC2"
 
@@ -2849,6 +2861,7 @@ if test "$bluez" = "yes" ; then
   echo "CONFIG_BLUEZ=y" >> $config_host_mak
   echo "BLUEZ_CFLAGS=$bluez_cflags" >> $config_host_mak
 fi
+echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak
 if test "$xen" = "yes" ; then
   echo "CONFIG_XEN_BACKEND=y" >> $config_host_mak
   echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version" >> $config_host_mak
commit d3608b7cc6f84caf9bc2b42e0a942ff561b73c4f
Author: Luiz Capitulino <lcapitulino at gmail.com>
Date:   Mon Jul 11 15:01:57 2011 -0300

    Error: Fix build when qemu-common.h is not included
    
    Commit e4ea5e2d0e0e4c5188ab45b66f3195062ae059dc added the use of
    the macro GCC_FMT_ATTR to error.h, however compiler.h is not
    included by error.h
    
    This will cause a build error when files including error.h
    don't include qemu-common.h (or compiler.h). Not an issue today
    because the only file including it is json-parser.h and it does
    include qemu-common.h, but let's get it fixed.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/error.h b/error.h
index 0f92a6f..6361f40 100644
--- a/error.h
+++ b/error.h
@@ -12,6 +12,7 @@
 #ifndef ERROR_H
 #define ERROR_H
 
+#include "compiler.h"
 #include <stdbool.h>
 
 /**
commit 5c0263204da1870243107acd6c73b21f2e7b78f0
Author: Luiz Capitulino <lcapitulino at gmail.com>
Date:   Mon Jul 11 14:24:44 2011 -0300

    Introduce compiler.h header file
    
    This moves compiler related macros from qemu-common.h to compiler.h.
    
    The reason for this change is that there are simple header files that
    depend only on the compiler macros, so including qemu-common.h is overkill.
    
    Besides, qemu-common.h is bloated and will benefit from some splitting.
    
    Please, also note that the QEMU_BUILD_BUG_ON() macro is being fixed to
    not use double underscores as a prefix and the license text was added
    by Vassili Karpov (malc), who is one of the authors of the new file.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/compiler.h b/compiler.h
new file mode 100644
index 0000000..9af5dc6
--- /dev/null
+++ b/compiler.h
@@ -0,0 +1,34 @@
+/* public domain */
+
+#ifndef COMPILER_H
+#define COMPILER_H
+
+#include "config-host.h"
+
+#define QEMU_NORETURN __attribute__ ((__noreturn__))
+#ifdef CONFIG_GCC_ATTRIBUTE_WARN_UNUSED_RESULT
+#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#else
+#define QEMU_WARN_UNUSED_RESULT
+#endif
+
+#define QEMU_BUILD_BUG_ON(x) \
+    typedef char qemu_build_bug_on__##__LINE__[(x)?-1:1];
+
+#if defined __GNUC__
+# if (__GNUC__ < 4) || \
+     defined(__GNUC_MINOR__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 4)
+   /* gcc versions before 4.4.x don't support gnu_printf, so use printf. */
+#  define GCC_ATTR __attribute__((__unused__, format(printf, 1, 2)))
+#  define GCC_FMT_ATTR(n, m) __attribute__((format(printf, n, m)))
+# else
+   /* Use gnu_printf when supported (qemu uses standard format strings). */
+#  define GCC_ATTR __attribute__((__unused__, format(gnu_printf, 1, 2)))
+#  define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m)))
+# endif
+#else
+#define GCC_ATTR /**/
+#define GCC_FMT_ATTR(n, m)
+#endif
+
+#endif /* COMPILER_H */
diff --git a/qemu-common.h b/qemu-common.h
index c2b79bd..ba55719 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -2,16 +2,9 @@
 #ifndef QEMU_COMMON_H
 #define QEMU_COMMON_H
 
+#include "compiler.h"
 #include "config-host.h"
 
-#define QEMU_NORETURN __attribute__ ((__noreturn__))
-#ifdef CONFIG_GCC_ATTRIBUTE_WARN_UNUSED_RESULT
-#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
-#else
-#define QEMU_WARN_UNUSED_RESULT
-#endif
-
-#define QEMU_BUILD_BUG_ON(x) typedef char __build_bug_on__##__LINE__[(x)?-1:1];
 #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
 
 typedef struct QEMUTimer QEMUTimer;
@@ -82,22 +75,6 @@ struct iovec {
 #include <sys/uio.h>
 #endif
 
-#if defined __GNUC__
-# if (__GNUC__ < 4) || \
-     defined(__GNUC_MINOR__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 4)
-   /* gcc versions before 4.4.x don't support gnu_printf, so use printf. */
-#  define GCC_ATTR __attribute__((__unused__, format(printf, 1, 2)))
-#  define GCC_FMT_ATTR(n, m) __attribute__((format(printf, n, m)))
-# else
-   /* Use gnu_printf when supported (qemu uses standard format strings). */
-#  define GCC_ATTR __attribute__((__unused__, format(gnu_printf, 1, 2)))
-#  define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m)))
-# endif
-#else
-#define GCC_ATTR /**/
-#define GCC_FMT_ATTR(n, m)
-#endif
-
 typedef int (*fprintf_function)(FILE *f, const char *fmt, ...)
     GCC_FMT_ATTR(2, 3);
 
commit d967b2f14f238c24264fa73d02e9b0dde0b19506
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Mon Jul 11 20:01:09 2011 +0200

    QMP: add snapshot-blkdev-sync command
    
    Add QMP bits for snapshot_blkdev command. This is the same as
    snapshot_blkdev in the human monitor. The command is synchronous.
    
    In the future async commands and or a break down of the functionality
    into multiple commands might be added.
    
    Also change the 'snapshot_file' argument to 'snapshot-file' in
    the human monitor, so that it matches QMP.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>

diff --git a/blockdev.c b/blockdev.c
index a97a801..0b8d3a4 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -568,7 +568,7 @@ void do_commit(Monitor *mon, const QDict *qdict)
 int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     const char *device = qdict_get_str(qdict, "device");
-    const char *filename = qdict_get_try_str(qdict, "snapshot_file");
+    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;
@@ -577,7 +577,7 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
     char old_filename[1024];
 
     if (!filename) {
-        qerror_report(QERR_MISSING_PARAMETER, "snapshot_file");
+        qerror_report(QERR_MISSING_PARAMETER, "snapshot-file");
         ret = -1;
         goto out;
     }
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 6ad8806..c857827 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -840,7 +840,7 @@ ETEXI
 
     {
         .name       = "snapshot_blkdev",
-        .args_type  = "device:B,snapshot_file:s?,format:s?",
+        .args_type  = "device:B,snapshot-file:s?,format:s?",
         .params     = "device [new-image-file] [format]",
         .help       = "initiates a live snapshot\n\t\t\t"
                       "of device. If a new image file is specified, the\n\t\t\t"
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 92c5c3a..5d44edf 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -694,6 +694,40 @@ Example:
 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,
+    },
+
+SQMP
+blockdev-snapshot-sync
+----------------------
+
+Synchronous snapshot of a block device. snapshot-file specifies 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 specifies the format of the
+snapshot image, default is qcow2.
+
+Arguments:
+
+- "device": device name to snapshot (json-string)
+- "snapshot-file": name of new image file (json-string)
+- "format": format of new image (json-string, optional)
+
+Example:
+
+-> { "execute": "blockdev-snapshot", "arguments": { "device": "ide-hd0",
+                                                    "snapshot-file":
+                                                    "/some/place/my-image",
+                                                    "format": "qcow2" } }
+<- { "return": {} }
+
+EQMP
+
+    {
         .name       = "balloon",
         .args_type  = "value:M",
         .params     = "target",
commit 6c916eda22e7ef180bb2dd183bbef85f9ff006c6
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Wed Jul 20 22:06:33 2011 +0000

    Update OpenBIOS images for Sparc32 and Sparc64
    
    Update Sparc32 and Sparc64 OpenBIOS images to SVN revision 1045.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/pc-bios/README b/pc-bios/README
index 40568f8..f74b246 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -10,10 +10,9 @@
 - OpenBIOS (http://www.openbios.org/) is a free (GPL v2) portable
   firmware implementation. The goal is to implement a 100% IEEE
   1275-1994 (referred to as Open Firmware) compliant firmware.
-  The included image for PowerPC (for 32 and 64 bit PPC CPUs),
-
-  PowerPC is built from OpenBIOS SVN revision 1044
-  Sparc32 and Sparc64 are built from OpenBIOS SVN revision 1018.
+  The included image for PowerPC (for 32 and 64 bit PPC CPUs)
+  is built from OpenBIOS SVN revision 1044 and Sparc32 and Sparc64
+  images are built from OpenBIOS SVN revision 1045.
 
 - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
   implementation for certain IBM POWER hardware.  The sources are at
diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
index b2dc5c5..ea9cc32 100644
Binary files a/pc-bios/openbios-sparc32 and b/pc-bios/openbios-sparc32 differ
diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64
index 70a223d..7e746b4 100644
Binary files a/pc-bios/openbios-sparc64 and b/pc-bios/openbios-sparc64 differ
commit b14ef7c9ab41ea824c3ccadb070ad95567cca84e
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Jul 3 08:53:46 2011 +0000

    Fix unassigned memory access handling
    
    cea5f9a28faa528b6b1b117c9ab2d8828f473fef exposed bugs in unassigned memory
    access handling. Fix them by always passing CPUState to the handlers.
    
    Reported-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/exec-all.h b/exec-all.h
index 69acf3b..9b8d62c 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -323,7 +323,7 @@ static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong add
     pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK;
     if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
 #if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)
-        do_unassigned_access(addr, 0, 1, 0, 4);
+        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
diff --git a/exec.c b/exec.c
index 8277900..2160ded 100644
--- a/exec.c
+++ b/exec.c
@@ -3238,7 +3238,7 @@ static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
     printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
 #endif
 #if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
-    do_unassigned_access(addr, 0, 0, 0, 1);
+    cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 1);
 #endif
     return 0;
 }
@@ -3249,7 +3249,7 @@ static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr)
     printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
 #endif
 #if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
-    do_unassigned_access(addr, 0, 0, 0, 2);
+    cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 2);
 #endif
     return 0;
 }
@@ -3260,7 +3260,7 @@ static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
     printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
 #endif
 #if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
-    do_unassigned_access(addr, 0, 0, 0, 4);
+    cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 4);
 #endif
     return 0;
 }
@@ -3271,7 +3271,7 @@ static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_
     printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
 #endif
 #if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
-    do_unassigned_access(addr, 1, 0, 0, 1);
+    cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 1);
 #endif
 }
 
@@ -3281,7 +3281,7 @@ static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_
     printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
 #endif
 #if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
-    do_unassigned_access(addr, 1, 0, 0, 2);
+    cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 2);
 #endif
 }
 
@@ -3291,7 +3291,7 @@ static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_
     printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
 #endif
 #if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
-    do_unassigned_access(addr, 1, 0, 0, 4);
+    cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 4);
 #endif
 }
 
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 78caa79..919be12 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -434,8 +434,9 @@ uint64_t cpu_alpha_load_fpcr (CPUState *env);
 void cpu_alpha_store_fpcr (CPUState *env, uint64_t val);
 #ifndef CONFIG_USER_ONLY
 void swap_shadow_regs(CPUState *env);
-extern QEMU_NORETURN void do_unassigned_access(target_phys_addr_t addr,
-                                               int, int, int, int);
+QEMU_NORETURN void cpu_unassigned_access(CPUState *env1,
+                                         target_phys_addr_t addr, int is_write,
+                                         int is_exec, int unused, int size);
 #endif
 
 /* Bits in TB->FLAGS that control how translation is processed.  */
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 51d1bd7..8f39154 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1301,9 +1301,11 @@ static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
     helper_excp(EXCP_UNALIGN, 0);
 }
 
-void QEMU_NORETURN do_unassigned_access(target_phys_addr_t addr, int is_write,
-                                        int is_exec, int unused, int size)
+void QEMU_NORETURN cpu_unassigned_access(CPUState *env1,
+                                         target_phys_addr_t addr, int is_write,
+                                         int is_exec, int unused, int size)
 {
+    env = env1;
     env->trap_arg0 = addr;
     env->trap_arg1 = is_write;
     dynamic_excp(EXCP_MCHK, 0);
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 51a13e3..76f4fc4 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -347,8 +347,8 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
 }
 
 #if !defined(CONFIG_USER_ONLY)
-void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
-                          int is_asi, int size);
+void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
+                           int is_write, int is_exec, int is_asi, int size);
 #endif
 
 static inline bool cpu_has_work(CPUState *env)
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index 1a0a476..664ffe5 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -488,20 +488,14 @@ void helper_mmu_write(uint32_t rn, uint32_t v)
     mmu_write(env, rn, v);
 }
 
-void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
-                          int is_asi, int size)
+void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
+                           int is_write, int is_exec, int is_asi, int size)
 {
     CPUState *saved_env;
 
-    if (!cpu_single_env) {
-        /* XXX: ???   */
-        return;
-    }
-
-    /* XXX: hack to restore env in all cases, even if not called from
-       generated code */
     saved_env = env;
-    env = cpu_single_env;
+    env = env1;
+
     qemu_log_mask(CPU_LOG_INT, "Unassigned " TARGET_FMT_plx " wr=%d exe=%d\n",
              addr, is_write, is_exec);
     if (!(env->sregs[SR_MSR] & MSR_EE)) {
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index b0ac4da..33be296 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -493,8 +493,8 @@ void r4k_helper_tlbwr (void);
 void r4k_helper_tlbp (void);
 void r4k_helper_tlbr (void);
 
-void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
-                          int unused, int size);
+void cpu_unassigned_access(CPUState *env, target_phys_addr_t addr,
+                           int is_write, int is_exec, int unused, int size);
 #endif
 
 void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf);
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 6b966b1..01315ef 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1980,9 +1980,11 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
     env = saved_env;
 }
 
-void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
-                          int unused, int size)
+void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
+                           int is_write, int is_exec, int unused, int size)
 {
+    env = env1;
+
     if (is_exec)
         helper_raise_exception(EXCP_IBE);
     else
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 22ee274..0084b67 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -510,8 +510,8 @@ static inline int tlb_compare_context(const SparcTLBEntry *tlb,
 
 /* cpu-exec.c */
 #if !defined(CONFIG_USER_ONLY)
-void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
-                          int is_asi, int size);
+void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
+                           int is_write, int is_exec, int is_asi, int size);
 target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
                                            int mmu_idx);
 
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 8b0df68..3b7f9ca 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -79,9 +79,14 @@
 #define CACHE_CTRL_FD (1 << 22)  /* Flush Data cache (Write only) */
 #define CACHE_CTRL_DS (1 << 23)  /* Data cache snoop enable */
 
-#if defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
+#if !defined(CONFIG_USER_ONLY)
+static void do_unassigned_access(target_phys_addr_t addr, int is_write,
+                                 int is_exec, int is_asi, int size);
+#else
+#ifdef TARGET_SPARC64
 static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
-                          int is_asi, int size);
+                                 int is_asi, int size);
+#endif
 #endif
 
 #if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
@@ -4235,8 +4240,8 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
 
 #ifndef TARGET_SPARC64
 #if !defined(CONFIG_USER_ONLY)
-void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
-                          int is_asi, int size)
+static void do_unassigned_access(target_phys_addr_t addr, int is_write,
+                                 int is_exec, int is_asi, int size)
 {
     CPUState *saved_env;
     int fault_type;
@@ -4301,8 +4306,8 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
 static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
                           int is_asi, int size)
 #else
-void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
-                          int is_asi, int size)
+static void do_unassigned_access(target_phys_addr_t addr, int is_write,
+                                 int is_exec, int is_asi, int size)
 #endif
 {
     CPUState *saved_env;
@@ -4351,3 +4356,12 @@ void helper_tick_set_limit(void *opaque, uint64_t limit)
 #endif
 }
 #endif
+
+#if !defined(CONFIG_USER_ONLY)
+void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
+                           int is_write, int is_exec, int is_asi, int size)
+{
+    env = env1;
+    do_unassigned_access(addr, is_write, is_exec, is_asi, size);
+}
+#endif
commit 21673cdecb9e9b5a22acaf0a44e47145beb1999e
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Thu Jul 14 15:22:20 2011 +0000

    Avoid CPU endian memory accesses in devices
    
    Don't compile virtio.c in hwlib, it depends on memory accesses
    performed in CPU endianness.
    
    Make loads and stores in CPU endianness unavailable to devices
    and poison them to avoid further bugs.
    
    Acked-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index 1635df6..c43ed05 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -171,7 +171,7 @@ user-obj-y += cutils.o cache-utils.o
 
 hw-obj-y =
 hw-obj-y += vl.o loader.o
-hw-obj-$(CONFIG_VIRTIO) += virtio.o virtio-console.o
+hw-obj-$(CONFIG_VIRTIO) += virtio-console.o
 hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
 hw-obj-y += fw_cfg.o
 hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o
diff --git a/Makefile.target b/Makefile.target
index fe78516..e20a313 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -191,7 +191,7 @@ obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
 obj-$(CONFIG_NO_PCI) += pci-stub.o
-obj-$(CONFIG_VIRTIO) += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
+obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
 obj-y += vhost_net.o
 obj-$(CONFIG_VHOST_NET) += vhost.o
 obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
diff --git a/cpu-common.h b/cpu-common.h
index a5b80e1..44b04b3 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -134,28 +134,31 @@ 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);
-uint32_t lduw_phys(target_phys_addr_t addr);
 uint32_t lduw_le_phys(target_phys_addr_t addr);
 uint32_t lduw_be_phys(target_phys_addr_t addr);
-uint32_t ldl_phys(target_phys_addr_t addr);
 uint32_t ldl_le_phys(target_phys_addr_t addr);
 uint32_t ldl_be_phys(target_phys_addr_t addr);
-uint64_t ldq_phys(target_phys_addr_t addr);
 uint64_t ldq_le_phys(target_phys_addr_t addr);
 uint64_t ldq_be_phys(target_phys_addr_t addr);
-void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val);
-void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val);
 void stb_phys(target_phys_addr_t addr, uint32_t val);
-void stw_phys(target_phys_addr_t addr, uint32_t val);
 void stw_le_phys(target_phys_addr_t addr, uint32_t val);
 void stw_be_phys(target_phys_addr_t addr, uint32_t val);
-void stl_phys(target_phys_addr_t addr, uint32_t val);
 void stl_le_phys(target_phys_addr_t addr, uint32_t val);
 void stl_be_phys(target_phys_addr_t addr, uint32_t val);
-void stq_phys(target_phys_addr_t addr, uint64_t val);
 void stq_le_phys(target_phys_addr_t addr, uint64_t val);
 void stq_be_phys(target_phys_addr_t addr, uint64_t val);
 
+#ifdef NEED_CPU_H
+uint32_t lduw_phys(target_phys_addr_t addr);
+uint32_t ldl_phys(target_phys_addr_t addr);
+uint64_t ldq_phys(target_phys_addr_t addr);
+void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val);
+void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val);
+void stw_phys(target_phys_addr_t addr, uint32_t val);
+void stl_phys(target_phys_addr_t addr, uint32_t val);
+void stq_phys(target_phys_addr_t addr, uint64_t val);
+#endif
+
 void cpu_physical_memory_write_rom(target_phys_addr_t addr,
                                    const uint8_t *buf, int len);
 
diff --git a/poison.h b/poison.h
index 2b18232..5354e77 100644
--- a/poison.h
+++ b/poison.h
@@ -37,6 +37,15 @@
 #pragma GCC poison CPUState
 #pragma GCC poison env
 
+#pragma GCC poison lduw_phys
+#pragma GCC poison ldl_phys
+#pragma GCC poison ldq_phys
+#pragma GCC poison stl_phys_notdirty
+#pragma GCC poison stq_phys_notdirty
+#pragma GCC poison stw_phys
+#pragma GCC poison stl_phys
+#pragma GCC poison stq_phys
+
 #pragma GCC poison CPU_INTERRUPT_HARD
 #pragma GCC poison CPU_INTERRUPT_EXITTB
 #pragma GCC poison CPU_INTERRUPT_HALT
commit b5176d279a81b3205a6f4e4757b39a4e4f8833e8
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Mon Jul 18 14:32:18 2011 +0900

    SPARC64: treat UA2007 ASI_BLK_* as translating ASIs.
    
    UA2007 ASI_BLK_* should be added in is_translating_asi().
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Acked-by: Artyom Tarasenko <atar4qemu at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index b99223e..8b0df68 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -287,7 +287,8 @@ static inline int is_translating_asi(int asi)
      */
     switch (asi) {
     case 0x04 ... 0x11:
-    case 0x18 ... 0x19:
+    case 0x16 ... 0x19:
+    case 0x1E ... 0x1F:
     case 0x24 ... 0x2C:
     case 0x70 ... 0x73:
     case 0x78 ... 0x79:
commit d0510af26d854f714114a312eb4aed0649447eb2
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Fri Jul 15 20:09:10 2011 +0000

    checkpatch: Fix bracing false positives on #if
    
    789f88d0b21fedfd4251d56bb7a9fbfbda7a4ac7 only fixed #else,
    fix also #if.
    
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 70a2111..3498425 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -2539,6 +2539,7 @@ sub process {
 		}
 		if (!defined $suppress_ifbraces{$linenr - 1} &&
 					$line =~ /\b(if|while|for|else)\b/ &&
+					$line !~ /\#\s*if/ &&
 					$line !~ /\#\s*else/) {
 			my $allowed = 0;
 
commit ea15fb067212bb79291f9b76c5c76d45b62f58e1
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Wed Jul 20 20:56:36 2011 +0200

    tcg/mips: Fix regression caused by typo (copy + paste bug)
    
    cppcheck reports an error:
    qemu/tcg/mips/tcg-target.c:1487: error: Invalid number of character (()
    
    The unpatched code won't compile on mips hosts starting with commit
    cea5f9a28faa528b6b1b117c9ab2d8828f473fef.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 12ff9d5..a33d21f 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -1484,7 +1484,7 @@ static void tcg_target_qemu_prologue(TCGContext *s)
     }
 
     /* Call generated code */
-    tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1]), 0);
+    tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
     tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
     tb_ret_addr = s->code_ptr;
 
commit cd3e2409a3605b89b6bea2e67fc128c6a9f8d921
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Mon Jul 18 23:34:22 2011 +0200

    ds1225y: convert to qdev device, and use it in MIPS Jazz emulation
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/ds1225y.c b/hw/ds1225y.c
index 5105b9b..662d7b5 100644
--- a/hw/ds1225y.c
+++ b/hw/ds1225y.c
@@ -22,21 +22,20 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "mips.h"
+#include "sysbus.h"
 #include "trace.h"
 
-typedef struct ds1225y_t
-{
+typedef struct {
+    DeviceState qdev;
     uint32_t chip_size;
+    char *filename;
     QEMUFile *file;
     uint8_t *contents;
-} ds1225y_t;
-
+} NvRamState;
 
 static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
 {
-    ds1225y_t *s = opaque;
+    NvRamState *s = opaque;
     uint32_t val;
 
     val = s->contents[addr];
@@ -64,7 +63,7 @@ static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
 
 static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t val)
 {
-    ds1225y_t *s = opaque;
+    NvRamState *s = opaque;
 
     val &= 0xff;
     trace_nvram_write(addr, s->contents[addr], val);
@@ -103,34 +102,83 @@ static CPUWriteMemoryFunc * const nvram_write[] = {
     &nvram_writel,
 };
 
-/* Initialisation routine */
-void *ds1225y_init(target_phys_addr_t mem_base, const char *filename)
+static int nvram_post_load(void *opaque, int version_id)
 {
-    ds1225y_t *s;
-    int mem_indexRW;
+    NvRamState *s = opaque;
+
+    /* Close file, as filename may has changed in load/store process */
+    if (s->file) {
+        qemu_fclose(s->file);
+    }
+
+    /* Write back nvram contents */
+    s->file = qemu_fopen(s->filename, "wb");
+    if (s->file) {
+        /* Write back contents, as 'wb' mode cleaned the file */
+        qemu_put_buffer(s->file, s->contents, s->chip_size);
+        qemu_fflush(s->file);
+    }
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_nvram = {
+    .name = "nvram",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .post_load = nvram_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_VARRAY_UINT32(contents, NvRamState, chip_size, 0,
+                              vmstate_info_uint8, uint8_t),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+typedef struct {
+    SysBusDevice busdev;
+    NvRamState nvram;
+} SysBusNvRamState;
+
+static int nvram_sysbus_initfn(SysBusDevice *dev)
+{
+    NvRamState *s = &FROM_SYSBUS(SysBusNvRamState, dev)->nvram;
     QEMUFile *file;
+    int s_io;
 
-    s = qemu_mallocz(sizeof(ds1225y_t));
-    s->chip_size = 0x2000; /* Fixed for ds1225y chip: 8 KiB */
     s->contents = qemu_mallocz(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);
+
     /* Read current file */
-    file = qemu_fopen(filename, "rb");
+    file = qemu_fopen(s->filename, "rb");
     if (file) {
         /* Read nvram contents */
         qemu_get_buffer(file, s->contents, s->chip_size);
         qemu_fclose(file);
     }
-    s->file = qemu_fopen(filename, "wb");
-    if (s->file) {
-        /* Write back contents, as 'wb' mode cleaned the file */
-        qemu_put_buffer(s->file, s->contents, s->chip_size);
-        qemu_fflush(s->file);
-    }
+    nvram_post_load(s, 0);
 
-    /* Read/write memory */
-    mem_indexRW = cpu_register_io_memory(nvram_read, nvram_write, s,
-                                         DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(mem_base, s->chip_size, mem_indexRW);
-    return s;
+    return 0;
 }
+
+static SysBusDeviceInfo nvram_sysbus_info = {
+    .qdev.name  = "ds1225y",
+    .qdev.size  = sizeof(SysBusNvRamState),
+    .qdev.vmsd  = &vmstate_nvram,
+    .init       = nvram_sysbus_initfn,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("size", SysBusNvRamState, nvram.chip_size, 0x2000),
+        DEFINE_PROP_STRING("filename", SysBusNvRamState, nvram.filename),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
+static void nvram_register(void)
+{
+    sysbus_register_withprop(&nvram_sysbus_info);
+}
+
+device_init(nvram_register)
diff --git a/hw/mips.h b/hw/mips.h
index 93c8831..cae5f4c 100644
--- a/hw/mips.h
+++ b/hw/mips.h
@@ -8,9 +8,6 @@ PCIBus *gt64120_register(qemu_irq *pic);
 /* bonito.c */
 PCIBus *bonito_init(qemu_irq *pic);
 
-/* ds1225y.c */
-void *ds1225y_init(target_phys_addr_t mem_base, const char *filename);
-
 /* g364fb.c */
 int g364fb_mm_init(target_phys_addr_t vram_base,
                    target_phys_addr_t ctrl_base, int it_shift,
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index a100394..f6ab6dc 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -37,6 +37,7 @@
 #include "loader.h"
 #include "mc146818rtc.h"
 #include "blockdev.h"
+#include "sysbus.h"
 
 enum jazz_model_e
 {
@@ -115,6 +116,8 @@ void mips_jazz_init (ram_addr_t ram_size,
     void* rc4030_opaque;
     int s_rtc, s_dma_dummy;
     NICInfo *nd;
+    DeviceState *dev;
+    SysBusDevice *sysbus;
     ISADevice *pit;
     DriveInfo *fds[MAX_FD];
     qemu_irq esp_reset, dma_enable;
@@ -266,8 +269,11 @@ void mips_jazz_init (ram_addr_t ram_size,
     /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */
     audio_init(i8259, NULL);
 
-    /* NVRAM: Unprotected at 0x9000, Protected at 0xa000, Read only at 0xb000 */
-    ds1225y_init(0x80009000, "nvram");
+    /* NVRAM */
+    dev = qdev_create(NULL, "ds1225y");
+    qdev_init_nofail(dev);
+    sysbus = sysbus_from_qdev(dev);
+    sysbus_mmio_map(sysbus, 0, 0x80009000);
 
     /* LED indicator */
     jazz_led_init(0x8000f000);
commit d43ed9ec2566922e76420b4ac914df6b2d473c4b
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Mon Jul 18 23:34:21 2011 +0200

    ds1225y: use trace framework
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/ds1225y.c b/hw/ds1225y.c
index 1fd7010..5105b9b 100644
--- a/hw/ds1225y.c
+++ b/hw/ds1225y.c
@@ -24,9 +24,7 @@
 
 #include "hw.h"
 #include "mips.h"
-#include "nvram.h"
-
-//#define DEBUG_NVRAM
+#include "trace.h"
 
 typedef struct ds1225y_t
 {
@@ -42,10 +40,7 @@ static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
     uint32_t val;
 
     val = s->contents[addr];
-
-#ifdef DEBUG_NVRAM
-    printf("nvram: read 0x%x at " TARGET_FMT_lx "\n", val, addr);
-#endif
+    trace_nvram_read(addr, val);
     return val;
 }
 
@@ -71,11 +66,10 @@ static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t val)
 {
     ds1225y_t *s = opaque;
 
-#ifdef DEBUG_NVRAM
-    printf("nvram: write 0x%x at " TARGET_FMT_lx "\n", val, addr);
-#endif
+    val &= 0xff;
+    trace_nvram_write(addr, s->contents[addr], val);
 
-    s->contents[addr] = val & 0xff;
+    s->contents[addr] = val;
     if (s->file) {
         qemu_fseek(s->file, addr, SEEK_SET);
         qemu_put_byte(s->file, (int)val);
diff --git a/trace-events b/trace-events
index ad11b09..99a4a2b 100644
--- a/trace-events
+++ b/trace-events
@@ -103,6 +103,10 @@ disable cs4231_mem_readl_reg(uint32_t reg, uint32_t ret) "read reg %d: 0x%08x"
 disable cs4231_mem_writel_reg(uint32_t reg, uint32_t old, uint32_t val) "write reg %d: 0x%08x -> 0x%08x"
 disable cs4231_mem_writel_dreg(uint32_t reg, uint32_t old, uint32_t val) "write dreg %d: 0x%02x -> 0x%02x"
 
+# hw/ds1225y.c
+disable nvram_read(uint32_t addr, uint32_t ret) "read addr %d: 0x%02x"
+disable nvram_write(uint32_t addr, uint32_t old, uint32_t val) "write addr %d: 0x%02x -> 0x%02x"
+
 # hw/eccmemctl.c
 disable ecc_mem_writel_mer(uint32_t val) "Write memory enable %08x"
 disable ecc_mem_writel_mdr(uint32_t val) "Write memory delay %08x"
commit 86f25c7c37c6f6250cfac4d0ee331af3ca73cac1
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Mon Jul 18 23:34:20 2011 +0200

    ds1225y: Remove protection stuff, which doesn't belong to this device
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/ds1225y.c b/hw/ds1225y.c
index b1c5232..1fd7010 100644
--- a/hw/ds1225y.c
+++ b/hw/ds1225y.c
@@ -33,7 +33,6 @@ typedef struct ds1225y_t
     uint32_t chip_size;
     QEMUFile *file;
     uint8_t *contents;
-    uint8_t protection;
 } ds1225y_t;
 
 
@@ -98,34 +97,6 @@ static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t val)
     nvram_writeb(opaque, addr + 3, (val >> 24) & 0xff);
 }
 
-static void nvram_writeb_protected (void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    ds1225y_t *s = opaque;
-
-    if (s->protection != 7) {
-#ifdef DEBUG_NVRAM
-    printf("nvram: prevent write of 0x%x at " TARGET_FMT_lx "\n", val, addr);
-#endif
-        return;
-    }
-
-    nvram_writeb(opaque, addr, val);
-}
-
-static void nvram_writew_protected (void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    nvram_writeb_protected(opaque, addr, val & 0xff);
-    nvram_writeb_protected(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void nvram_writel_protected (void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    nvram_writeb_protected(opaque, addr, val & 0xff);
-    nvram_writeb_protected(opaque, addr + 1, (val >> 8) & 0xff);
-    nvram_writeb_protected(opaque, addr + 2, (val >> 16) & 0xff);
-    nvram_writeb_protected(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
 static CPUReadMemoryFunc * const nvram_read[] = {
     &nvram_readb,
     &nvram_readw,
@@ -138,23 +109,16 @@ static CPUWriteMemoryFunc * const nvram_write[] = {
     &nvram_writel,
 };
 
-static CPUWriteMemoryFunc * const nvram_write_protected[] = {
-    &nvram_writeb_protected,
-    &nvram_writew_protected,
-    &nvram_writel_protected,
-};
-
 /* Initialisation routine */
 void *ds1225y_init(target_phys_addr_t mem_base, const char *filename)
 {
     ds1225y_t *s;
-    int mem_indexRW, mem_indexRP;
+    int mem_indexRW;
     QEMUFile *file;
 
     s = qemu_mallocz(sizeof(ds1225y_t));
     s->chip_size = 0x2000; /* Fixed for ds1225y chip: 8 KiB */
     s->contents = qemu_mallocz(s->chip_size);
-    s->protection = 7;
 
     /* Read current file */
     file = qemu_fopen(filename, "rb");
@@ -174,9 +138,5 @@ void *ds1225y_init(target_phys_addr_t mem_base, const char *filename)
     mem_indexRW = cpu_register_io_memory(nvram_read, nvram_write, s,
                                          DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(mem_base, s->chip_size, mem_indexRW);
-    /* Read/write protected memory */
-    mem_indexRP = cpu_register_io_memory(nvram_read, nvram_write_protected, s,
-                                         DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(mem_base + s->chip_size, s->chip_size, mem_indexRP);
     return s;
 }
diff --git a/hw/mips.h b/hw/mips.h
index 73aa8f8..93c8831 100644
--- a/hw/mips.h
+++ b/hw/mips.h
@@ -10,7 +10,6 @@ PCIBus *bonito_init(qemu_irq *pic);
 
 /* ds1225y.c */
 void *ds1225y_init(target_phys_addr_t mem_base, const char *filename);
-void ds1225y_set_protection(void *opaque, int protection);
 
 /* g364fb.c */
 int g364fb_mm_init(target_phys_addr_t vram_base,
commit b7d69dc233cee75cbdd3f9df12c6cda9a24ba37d
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Mon Jul 18 15:36:57 2011 +0900

    SPARC64: add missing break on fmovdcc
    
    "break" is missing on V9 fmovdcc (%icc).
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index a1a19c3..15967c5 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2864,6 +2864,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         break;
                     case 0x102: /* V9 fmovdcc %icc */
                         FMOVDCC(0);
+                        break;
                     case 0x103: /* V9 fmovqcc %icc */
                         CHECK_FPU_FEATURE(dc, FLOAT128);
                         FMOVQCC(0);
commit afcb7375123fcb73649dba56f5393e2f2e173b5e
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Mon Jul 18 15:00:00 2011 +0900

    SPARC64: fix VIS1 SIMD signed compare instructions
    
    The destination registers of SIMD signed compare instructions
    (fcmp*<16|32>) are not FP registers but general purpose r registers.
    Comparisons should be freg_rs1 CMP freg_rs2, that were reversed.
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 023f4d6..2d36af3 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -148,8 +148,8 @@ F_HELPER_0_0(expand);
 VIS_HELPER(padd);
 VIS_HELPER(psub);
 #define VIS_CMPHELPER(name)                              \
-    F_HELPER_0_0(name##16);                              \
-    F_HELPER_0_0(name##32)
+    DEF_HELPER_0(f##name##16, i64);                      \
+    DEF_HELPER_0(f##name##32, i64)
 VIS_CMPHELPER(cmpgt);
 VIS_CMPHELPER(cmpeq);
 VIS_CMPHELPER(cmple);
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 15af27b..b99223e 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -525,6 +525,7 @@ typedef union {
     uint16_t w[4];
     int16_t sw[4];
     uint32_t l[2];
+    uint64_t ll;
     float64 d;
 } vis64;
 
@@ -789,32 +790,34 @@ VIS_HELPER(helper_fpadd, FADD)
 VIS_HELPER(helper_fpsub, FSUB)
 
 #define VIS_CMPHELPER(name, F)                                        \
-    void name##16(void)                                           \
+    uint64_t name##16(void)                                       \
     {                                                             \
         vis64 s, d;                                               \
                                                                   \
         s.d = DT0;                                                \
         d.d = DT1;                                                \
                                                                   \
-        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
-        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
-        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
-        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
+        d.VIS_W64(0) = F(s.VIS_W64(0), d.VIS_W64(0)) ? 1 : 0;     \
+        d.VIS_W64(0) |= F(s.VIS_W64(1), d.VIS_W64(1)) ? 2 : 0;    \
+        d.VIS_W64(0) |= F(s.VIS_W64(2), d.VIS_W64(2)) ? 4 : 0;    \
+        d.VIS_W64(0) |= F(s.VIS_W64(3), d.VIS_W64(3)) ? 8 : 0;    \
+        d.VIS_W64(1) = d.VIS_W64(2) = d.VIS_W64(3) = 0;           \
                                                                   \
-        DT0 = d.d;                                                \
+        return d.ll;                                              \
     }                                                             \
                                                                   \
-    void name##32(void)                                           \
+    uint64_t name##32(void)                                       \
     {                                                             \
         vis64 s, d;                                               \
                                                                   \
         s.d = DT0;                                                \
         d.d = DT1;                                                \
                                                                   \
-        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
-        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
+        d.VIS_L64(0) = F(s.VIS_L64(0), d.VIS_L64(0)) ? 1 : 0;     \
+        d.VIS_L64(0) |= F(s.VIS_L64(1), d.VIS_L64(1)) ? 2 : 0;    \
+        d.VIS_L64(1) = 0;                                         \
                                                                   \
-        DT0 = d.d;                                                \
+        return d.ll;                                              \
     }
 
 #define FCMPGT(a, b) ((a) > (b))
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 27c2cf9..a1a19c3 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -3789,57 +3789,57 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fcmple16();
-                    gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_helper_fcmple16(cpu_dst);
+                    gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x022: /* VIS I fcmpne16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fcmpne16();
-                    gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_helper_fcmpne16(cpu_dst);
+                    gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x024: /* VIS I fcmple32 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fcmple32();
-                    gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_helper_fcmple32(cpu_dst);
+                    gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x026: /* VIS I fcmpne32 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fcmpne32();
-                    gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_helper_fcmpne32(cpu_dst);
+                    gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x028: /* VIS I fcmpgt16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fcmpgt16();
-                    gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_helper_fcmpgt16(cpu_dst);
+                    gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x02a: /* VIS I fcmpeq16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fcmpeq16();
-                    gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_helper_fcmpeq16(cpu_dst);
+                    gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x02c: /* VIS I fcmpgt32 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fcmpgt32();
-                    gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_helper_fcmpgt32(cpu_dst);
+                    gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x02e: /* VIS I fcmpeq32 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fcmpeq32();
-                    gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_helper_fcmpeq32(cpu_dst);
+                    gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x031: /* VIS I fmul8x16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
commit a3ce3668ccff7d350a4f795ad99a012a6d41caef
Merge: 03ff095... 8284582...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Wed Jul 20 20:23:01 2011 +0000

    Merge branch 'for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm
    
    * 'for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm:
      target-arm: Fix BASEPRI, BASEPRI_MAX, and FAULTMASK access
      target-arm: Minimal implementation of performance counters
      Revert "Makefile.target: Allow target helpers to be in any *_helper.c file"
      Revert "target-arm: Use global env in neon_helper.c helpers"
      target-arm: Pass fp status pointer explicitly to neon fp helpers
      target-arm: Make VFP binop helpers take pointer to fpstatus, not CPUState
      target-arm: Add helper function to generate code to get fpstatus pointer
      Revert "target-arm: Use global env in iwmmxt_helper.c helpers"
    
    Conflicts:
    	Makefile.target

diff --cc Makefile.target
index c566eb1,37bb28e..fe78516
--- a/Makefile.target
+++ b/Makefile.target
@@@ -95,7 -91,7 +95,7 @@@ tcg/tcg.o: cpu.
  
  # HELPER_CFLAGS is used for all the code compiled with static register
  # variables
- %_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 -op_helper.o cpu-exec.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
++op_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
  
  # Note: this is a workaround. The real fix is to avoid compiling
  # cpu_signal_handler() in user-exec.c.
commit 98e51ec92e678cf0e501b5ef013753ec8710e222
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jul 20 10:06:18 2011 +0200

    usb-serial doesn't support migration
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index 59cb0fb..70d694d 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -566,10 +566,16 @@ static USBDevice *usb_braille_init(const char *unused)
     return dev;
 }
 
+static const VMStateDescription vmstate_usb_serial = {
+    .name = "usb-serial",
+    .unmigratable = 1,
+};
+
 static struct USBDeviceInfo serial_info = {
     .product_desc   = "QEMU USB Serial",
     .qdev.name      = "usb-serial",
     .qdev.size      = sizeof(USBSerialState),
+    .qdev.vmsd      = &vmstate_usb_serial,
     .usb_desc       = &desc_serial,
     .init           = usb_serial_initfn,
     .handle_packet  = usb_generic_handle_packet,
@@ -589,6 +595,7 @@ static struct USBDeviceInfo braille_info = {
     .product_desc   = "QEMU USB Braille",
     .qdev.name      = "usb-braille",
     .qdev.size      = sizeof(USBSerialState),
+    .qdev.vmsd      = &vmstate_usb_serial,
     .usb_desc       = &desc_braille,
     .init           = usb_serial_initfn,
     .handle_packet  = usb_generic_handle_packet,
commit 4ab0ba9e26d52a272cadd5635437a341a4e7ff36
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jul 20 10:06:07 2011 +0200

    usb-net doesn't support migration
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-net.c b/hw/usb-net.c
index 9be709f..4212e5b 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1414,11 +1414,17 @@ static USBDevice *usb_net_init(const char *cmdline)
     return dev;
 }
 
+static const VMStateDescription vmstate_usb_net = {
+    .name = "usb-net",
+    .unmigratable = 1,
+};
+
 static struct USBDeviceInfo net_info = {
     .product_desc   = "QEMU USB Network Interface",
     .qdev.name      = "usb-net",
     .qdev.fw_name    = "network",
     .qdev.size      = sizeof(USBNetState),
+    .qdev.vmsd      = &vmstate_usb_net,
     .usb_desc       = &desc_net,
     .init           = usb_net_initfn,
     .handle_packet  = usb_generic_handle_packet,
commit 2474e5052b3987cbd7f41f6a2992ce691dc8cc0c
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jul 20 10:02:40 2011 +0200

    usb-bt doesn't support migration
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index e364513..4557802 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -548,10 +548,16 @@ USBDevice *usb_bt_init(HCIInfo *hci)
     return dev;
 }
 
+static const VMStateDescription vmstate_usb_bt = {
+    .name = "usb-bt",
+    .unmigratable = 1,
+};
+
 static struct USBDeviceInfo bt_info = {
     .product_desc   = "QEMU BT dongle",
     .qdev.name      = "usb-bt-dongle",
     .qdev.size      = sizeof(struct USBBtState),
+    .qdev.vmsd      = &vmstate_usb_bt,
     .usb_desc       = &desc_bluetooth,
     .init           = usb_bt_initfn,
     .handle_packet  = usb_generic_handle_packet,
commit ccce9fd205317f60dd30a986084eec39addbd09b
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jul 20 10:00:51 2011 +0200

    usb-wacom doesn't support migration
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index 9d348e1..d76ee97 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -349,6 +349,11 @@ static int usb_wacom_initfn(USBDevice *dev)
     return 0;
 }
 
+static const VMStateDescription vmstate_usb_wacom = {
+    .name = "usb-wacom",
+    .unmigratable = 1,
+};
+
 static struct USBDeviceInfo wacom_info = {
     .product_desc   = "QEMU PenPartner Tablet",
     .qdev.name      = "usb-wacom-tablet",
@@ -356,6 +361,7 @@ static struct USBDeviceInfo wacom_info = {
     .usbdevice_name = "wacom-tablet",
     .usb_desc       = &desc_wacom,
     .qdev.size      = sizeof(USBWacomState),
+    .qdev.vmsd      = &vmstate_usb_wacom,
     .init           = usb_wacom_initfn,
     .handle_packet  = usb_generic_handle_packet,
     .handle_reset   = usb_wacom_handle_reset,
commit f54b65630385d7dc7cf3442eb459d1a5b3d1a9c6
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Dec 10 14:58:41 2010 +0100

    usb storage: first migration support bits.
    
    Tag vmstate as unmigratable for the time being,
    to be removed when mgration support is finished.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 86582cc..8ed8594 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -623,11 +623,23 @@ static USBDevice *usb_msd_init(const char *filename)
     return dev;
 }
 
+static const VMStateDescription vmstate_usb_msd = {
+    .name = "usb-storage",
+    .unmigratable = 1, /* FIXME: handle transactions which are in flight */
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_USB_DEVICE(dev, MSDState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static struct USBDeviceInfo msd_info = {
     .product_desc   = "QEMU USB MSD",
     .qdev.name      = "usb-storage",
     .qdev.fw_name      = "storage",
     .qdev.size      = sizeof(MSDState),
+    .qdev.vmsd      = &vmstate_usb_msd,
     .usb_desc       = &desc,
     .init           = usb_msd_initfn,
     .handle_packet  = usb_generic_handle_packet,
commit 9490fb0624e67bce90297444fb960c2d9476239e
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jul 8 10:48:46 2011 +0200

    ehci doesn't support migration
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index a4758f9..8b0dcc3 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -2244,6 +2244,11 @@ static USBBusOps ehci_bus_ops = {
     .register_companion = ehci_register_companion,
 };
 
+static const VMStateDescription vmstate_ehci = {
+    .name = "ehci",
+    .unmigratable = 1,
+};
+
 static Property ehci_properties[] = {
     DEFINE_PROP_UINT32("freq",      EHCIState, freq, FRAME_TIMER_FREQ),
     DEFINE_PROP_UINT32("maxframes", EHCIState, maxframes, 128),
@@ -2254,6 +2259,7 @@ static PCIDeviceInfo ehci_info[] = {
     {
         .qdev.name    = "usb-ehci",
         .qdev.size    = sizeof(EHCIState),
+        .qdev.vmsd    = &vmstate_ehci,
         .init         = usb_ehci_initfn,
         .vendor_id    = PCI_VENDOR_ID_INTEL,
         .device_id    = PCI_DEVICE_ID_INTEL_82801D, /* ich4 */
@@ -2263,6 +2269,7 @@ static PCIDeviceInfo ehci_info[] = {
     },{
         .qdev.name    = "ich9-usb-ehci1",
         .qdev.size    = sizeof(EHCIState),
+        .qdev.vmsd    = &vmstate_ehci,
         .init         = usb_ehci_initfn,
         .vendor_id    = PCI_VENDOR_ID_INTEL,
         .device_id    = PCI_DEVICE_ID_INTEL_82801I_EHCI1,
commit b7ce1b27f652630e6bc201497ea451b67ad549fa
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jul 8 10:48:37 2011 +0200

    ahci doesn't support migration
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index 054e073..d241ea8 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -72,6 +72,11 @@
 #include <hw/ide/pci.h>
 #include <hw/ide/ahci.h>
 
+static const VMStateDescription vmstate_ahci = {
+    .name = "ahci",
+    .unmigratable = 1,
+};
+
 static int pci_ich9_ahci_init(PCIDevice *dev)
 {
     struct AHCIPCIState *d;
@@ -123,6 +128,7 @@ static PCIDeviceInfo ich_ahci_info[] = {
         .qdev.name    = "ich9-ahci",
         .qdev.alias   = "ahci",
         .qdev.size    = sizeof(AHCIPCIState),
+        .qdev.vmsd    = &vmstate_ahci,
         .init         = pci_ich9_ahci_init,
         .exit         = pci_ich9_uninit,
         .config_write = pci_ich9_write_config,
commit aaf55b4795d95d87353a08710f237f88d81a3c35
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Tue Jul 19 15:01:34 2011 +0200

    Add missing documentation for qemu-img -p
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index 2b70618..1299e83 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -30,7 +30,7 @@ ETEXI
 DEF("convert", img_convert,
     "convert [-c] [-p] [-f fmt] [-t cache] [-O output_fmt] [-o options] [-s snapshot_name] filename [filename2 [...]] output_filename")
 STEXI
- at item convert [-c] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] @var{filename} [@var{filename2} [...]] @var{output_filename}
+ at item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] @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}] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
+ at item rebase [-f @var{fmt}] [-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 526474c..495a1b6 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -38,6 +38,8 @@ by the used format or see the format descriptions below for details.
 indicates that target image must be compressed (qcow format only)
 @item -h
 with or without a command shows help and lists the supported formats
+ at item -p
+display progress bar (convert and rebase commands only)
 @end table
 
 Parameters to snapshot subcommand:
@@ -84,7 +86,7 @@ it doesn't need to be specified separately in this case.
 
 Commit the changes recorded in @var{filename} in its base image.
 
- at item convert [-c] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] @var{filename} [@var{filename2} [...]] @var{output_filename}
+ at item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] @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}
@@ -114,7 +116,7 @@ they are displayed too.
 
 List, apply, create or delete snapshots in image @var{filename}.
 
- at item rebase [-f @var{fmt}] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
+ at item rebase [-f @var{fmt}] [-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 8927cfbba232e28304734f7afd463c1b84134031
Author: Yonit Halperin <yhalperi at redhat.com>
Date:   Tue Jul 12 11:51:58 2011 +0300

    qxl: upon reset, if spice worker is stopped, the command rings can be not empty
    
    Spice worker does no longer process commands when it is stopped.
    Otherwise, it might crash during migration when attempting to process
    commands while the guest is not completely loaded.
    
    Cc: Alon Levy <alevy at redhat.com>
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index 0b9a4c7..a6fb7f0 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -656,8 +656,8 @@ static void qxl_reset_state(PCIQXLDevice *d)
     QXLRam *ram = d->ram;
     QXLRom *rom = d->rom;
 
-    assert(SPICE_RING_IS_EMPTY(&ram->cmd_ring));
-    assert(SPICE_RING_IS_EMPTY(&ram->cursor_ring));
+    assert(!d->ssd.running || SPICE_RING_IS_EMPTY(&ram->cmd_ring));
+    assert(!d->ssd.running || SPICE_RING_IS_EMPTY(&ram->cursor_ring));
     d->shadow_rom.update_id = cpu_to_le32(0);
     *rom = d->shadow_rom;
     qxl_rom_set_dirty(d);
commit df9cb669425051f4f4364cffb19c9b8089e04297
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Jul 7 17:04:17 2011 +0200

    spice: add sanity check for spice ports
    
    Make sure at least one port (port=.. or tls-port=...)
    is specified.  Also apply range checks to the port numbers.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/spice-core.c b/ui/spice-core.c
index e142452..1100417 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -480,7 +480,16 @@ void qemu_spice_init(void)
     port = qemu_opt_get_number(opts, "port", 0);
     tls_port = qemu_opt_get_number(opts, "tls-port", 0);
     if (!port && !tls_port) {
-        return;
+        fprintf(stderr, "neither port nor tls-port specified for spice.");
+        exit(1);
+    }
+    if (port < 0 || port > 65535) {
+        fprintf(stderr, "spice port is out of range");
+        exit(1);
+    }
+    if (tls_port < 0 || tls_port > 65535) {
+        fprintf(stderr, "spice tls-port is out of range");
+        exit(1);
     }
     password = qemu_opt_get(opts, "password");
 
commit 2837c8ea1f10c281c9ff68f397405f3596f8ce0b
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jul 8 10:44:35 2011 +0200

    vmstate: add no_migrate flag to VMStateDescription
    
    This allows to easily tag devices as non-migratable,
    so any attempt to migrate a virtual machine with the
    device in question active will make migration fail.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/hw.h b/hw/hw.h
index 9dd7096..df6ca65 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -324,6 +324,7 @@ typedef struct VMStateSubsection {
 
 struct VMStateDescription {
     const char *name;
+    int unmigratable;
     int version_id;
     int minimum_version_id;
     int minimum_version_id_old;
diff --git a/savevm.c b/savevm.c
index 8139bc7..1c5abe2 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1234,6 +1234,7 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
     se->opaque = opaque;
     se->vmsd = vmsd;
     se->alias_id = alias_id;
+    se->no_migrate = vmsd->unmigratable;
 
     if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
         char *id = dev->parent_bus->info->get_dev_path(dev);
commit 93913dfd8acbaddc8ef3716cd7b8a2830c99cb19
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Jul 19 13:01:48 2011 +0200

    qcow2: Use Qcow2Cache in writeback mode during loadvm/savevm
    
    In snapshotting there is no guest involved, so we can safely use a writeback
    mode and do the flushes in the right place (i.e. at the very end). This
    improves the time that creating/restoring an internal snapshot takes with an
    image in writethrough mode.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
index 3824739..8408847 100644
--- a/block/qcow2-cache.c
+++ b/block/qcow2-cache.c
@@ -312,3 +312,15 @@ found:
     c->entries[i].dirty = true;
 }
 
+bool qcow2_cache_set_writethrough(BlockDriverState *bs, Qcow2Cache *c,
+    bool enable)
+{
+    bool old = c->writethrough;
+
+    if (!old && enable) {
+        qcow2_cache_flush(bs, c);
+    }
+
+    c->writethrough = enable;
+    return old;
+}
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index ac95b88..14b2f67 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -705,8 +705,15 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
     BDRVQcowState *s = bs->opaque;
     uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2, l1_allocated;
     int64_t old_offset, old_l2_offset;
-    int i, j, l1_modified, nb_csectors, refcount;
+    int i, j, l1_modified = 0, nb_csectors, refcount;
     int ret;
+    bool old_l2_writethrough, old_refcount_writethrough;
+
+    /* Switch caches to writeback mode during update */
+    old_l2_writethrough =
+        qcow2_cache_set_writethrough(bs, s->l2_table_cache, false);
+    old_refcount_writethrough =
+        qcow2_cache_set_writethrough(bs, s->refcount_block_cache, false);
 
     l2_table = NULL;
     l1_table = NULL;
@@ -720,7 +727,11 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
         l1_allocated = 1;
         if (bdrv_pread(bs->file, l1_table_offset,
                        l1_table, l1_size2) != l1_size2)
+        {
+            ret = -EIO;
             goto fail;
+        }
+
         for(i = 0;i < l1_size; i++)
             be64_to_cpus(&l1_table[i]);
     } else {
@@ -729,7 +740,6 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
         l1_allocated = 0;
     }
 
-    l1_modified = 0;
     for(i = 0; i < l1_size; i++) {
         l2_offset = l1_table[i];
         if (l2_offset) {
@@ -773,6 +783,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
                         }
 
                         if (refcount < 0) {
+                            ret = -EIO;
                             goto fail;
                         }
                     }
@@ -803,6 +814,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
                 refcount = get_refcount(bs, l2_offset >> s->cluster_bits);
             }
             if (refcount < 0) {
+                ret = -EIO;
                 goto fail;
             } else if (refcount == 1) {
                 l2_offset |= QCOW_OFLAG_COPIED;
@@ -813,6 +825,18 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
             }
         }
     }
+
+    ret = 0;
+fail:
+    if (l2_table) {
+        qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
+    }
+
+    /* Enable writethrough cache mode again */
+    qcow2_cache_set_writethrough(bs, s->l2_table_cache, old_l2_writethrough);
+    qcow2_cache_set_writethrough(bs, s->refcount_block_cache,
+        old_refcount_writethrough);
+
     if (l1_modified) {
         for(i = 0; i < l1_size; i++)
             cpu_to_be64s(&l1_table[i]);
@@ -824,15 +848,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
     }
     if (l1_allocated)
         qemu_free(l1_table);
-    return 0;
- fail:
-    if (l2_table) {
-        qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
-    }
-
-    if (l1_allocated)
-        qemu_free(l1_table);
-    return -EIO;
+    return ret;
 }
 
 
diff --git a/block/qcow2.h b/block/qcow2.h
index e1ae3e8..6a0a21b 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -228,6 +228,8 @@ int qcow2_read_snapshots(BlockDriverState *bs);
 Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables,
     bool writethrough);
 int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c);
+bool qcow2_cache_set_writethrough(BlockDriverState *bs, Qcow2Cache *c,
+    bool enable);
 
 void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table);
 int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);
commit 4a1d5e1fded54358ddc4d8cbd53388ca7c93499b
Author: Fam Zheng <famcool at gmail.com>
Date:   Tue Jul 12 19:56:39 2011 +0800

    block: add bdrv_get_allocated_file_size() operation
    
    qemu-img.c wants to count allocated file size of image. Previously it
    counts a single bs->file by 'stat' or Window API. As VMDK introduces
    multiple file support, the operation becomes format specific with
    platform specific meanwhile.
    
    The functions are moved to block/raw-{posix,win32}.c and qemu-img.c calls
    bdrv_get_allocated_file_size to count the bs. And also added VMDK code
    to count his own extents.
    
    Signed-off-by: Fam Zheng <famcool at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 24a25d5..9549b9e 100644
--- a/block.c
+++ b/block.c
@@ -1147,6 +1147,25 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
 }
 
 /**
+ * Length of a allocated file in bytes. Sparse files are counted by actual
+ * allocated space. Return < 0 if error or unknown.
+ */
+int64_t bdrv_get_allocated_file_size(BlockDriverState *bs)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv) {
+        return -ENOMEDIUM;
+    }
+    if (drv->bdrv_get_allocated_file_size) {
+        return drv->bdrv_get_allocated_file_size(bs);
+    }
+    if (bs->file) {
+        return bdrv_get_allocated_file_size(bs->file);
+    }
+    return -ENOTSUP;
+}
+
+/**
  * Length of a file in bytes. Return < 0 if error or unknown.
  */
 int64_t bdrv_getlength(BlockDriverState *bs)
diff --git a/block.h b/block.h
index 859d1d9..59cc410 100644
--- a/block.h
+++ b/block.h
@@ -89,6 +89,7 @@ int bdrv_write_sync(BlockDriverState *bs, int64_t sector_num,
     const uint8_t *buf, int nb_sectors);
 int bdrv_truncate(BlockDriverState *bs, int64_t offset);
 int64_t bdrv_getlength(BlockDriverState *bs);
+int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
 void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
 void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs);
 int bdrv_commit(BlockDriverState *bs);
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 34b64aa..cd89c83 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -793,6 +793,17 @@ static int64_t raw_getlength(BlockDriverState *bs)
 }
 #endif
 
+static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
+{
+    struct stat st;
+    BDRVRawState *s = bs->opaque;
+
+    if (fstat(s->fd, &st) < 0) {
+        return -errno;
+    }
+    return (int64_t)st.st_blocks * 512;
+}
+
 static int raw_create(const char *filename, QEMUOptionParameter *options)
 {
     int fd;
@@ -888,6 +899,8 @@ static BlockDriver bdrv_file = {
 
     .bdrv_truncate = raw_truncate,
     .bdrv_getlength = raw_getlength,
+    .bdrv_get_allocated_file_size
+                        = raw_get_allocated_file_size,
 
     .create_options = raw_create_options,
 };
@@ -1156,6 +1169,8 @@ static BlockDriver bdrv_host_device = {
     .bdrv_read          = raw_read,
     .bdrv_write         = raw_write,
     .bdrv_getlength	= raw_getlength,
+    .bdrv_get_allocated_file_size
+                        = raw_get_allocated_file_size,
 
     /* generic scsi device */
 #ifdef __linux__
@@ -1277,6 +1292,8 @@ static BlockDriver bdrv_host_floppy = {
     .bdrv_read          = raw_read,
     .bdrv_write         = raw_write,
     .bdrv_getlength	= raw_getlength,
+    .bdrv_get_allocated_file_size
+                        = raw_get_allocated_file_size,
 
     /* removable device support */
     .bdrv_is_inserted   = floppy_is_inserted,
@@ -1380,6 +1397,8 @@ static BlockDriver bdrv_host_cdrom = {
     .bdrv_read          = raw_read,
     .bdrv_write         = raw_write,
     .bdrv_getlength     = raw_getlength,
+    .bdrv_get_allocated_file_size
+                        = raw_get_allocated_file_size,
 
     /* removable device support */
     .bdrv_is_inserted   = cdrom_is_inserted,
@@ -1503,6 +1522,8 @@ static BlockDriver bdrv_host_cdrom = {
     .bdrv_read          = raw_read,
     .bdrv_write         = raw_write,
     .bdrv_getlength     = raw_getlength,
+    .bdrv_get_allocated_file_size
+                        = raw_get_allocated_file_size,
 
     /* removable device support */
     .bdrv_is_inserted   = cdrom_is_inserted,
diff --git a/block/raw-win32.c b/block/raw-win32.c
index 56bd719..91067e7 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -213,6 +213,31 @@ static int64_t raw_getlength(BlockDriverState *bs)
     return l.QuadPart;
 }
 
+static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
+{
+    typedef DWORD (WINAPI * get_compressed_t)(const char *filename,
+                                              DWORD * high);
+    get_compressed_t get_compressed;
+    struct _stati64 st;
+    const char *filename = bs->filename;
+    /* WinNT support GetCompressedFileSize to determine allocate size */
+    get_compressed =
+        (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"),
+                                            "GetCompressedFileSizeA");
+    if (get_compressed) {
+        DWORD high, low;
+        low = get_compressed(filename, &high);
+        if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR) {
+            return (((int64_t) high) << 32) + low;
+        }
+    }
+
+    if (_stati64(filename, &st) < 0) {
+        return -1;
+    }
+    return st.st_size;
+}
+
 static int raw_create(const char *filename, QEMUOptionParameter *options)
 {
     int fd;
@@ -257,6 +282,8 @@ static BlockDriver bdrv_file = {
     .bdrv_write		= raw_write,
     .bdrv_truncate	= raw_truncate,
     .bdrv_getlength	= raw_getlength,
+    .bdrv_get_allocated_file_size
+                        = raw_get_allocated_file_size,
 
     .create_options = raw_create_options,
 };
@@ -419,6 +446,8 @@ static BlockDriver bdrv_host_device = {
     .bdrv_read		= raw_read,
     .bdrv_write	        = raw_write,
     .bdrv_getlength	= raw_getlength,
+    .bdrv_get_allocated_file_size
+                        = raw_get_allocated_file_size,
 };
 
 static void bdrv_file_init(void)
diff --git a/block/vmdk.c b/block/vmdk.c
index de08d0c..37478d2 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1289,6 +1289,29 @@ static int vmdk_flush(BlockDriverState *bs)
     return ret;
 }
 
+static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs)
+{
+    int i;
+    int64_t ret = 0;
+    int64_t r;
+    BDRVVmdkState *s = bs->opaque;
+
+    ret = bdrv_get_allocated_file_size(bs->file);
+    if (ret < 0) {
+        return ret;
+    }
+    for (i = 0; i < s->num_extents; i++) {
+        if (s->extents[i].file == bs->file) {
+            continue;
+        }
+        r = bdrv_get_allocated_file_size(s->extents[i].file);
+        if (r < 0) {
+            return r;
+        }
+        ret += r;
+    }
+    return ret;
+}
 
 static QEMUOptionParameter vmdk_create_options[] = {
     {
@@ -1327,6 +1350,7 @@ static BlockDriver bdrv_vmdk = {
     .bdrv_create    = vmdk_create,
     .bdrv_flush     = vmdk_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_int.h b/block_int.h
index 8a7b6cb..efb6803 100644
--- a/block_int.h
+++ b/block_int.h
@@ -86,6 +86,7 @@ struct BlockDriver {
     const char *protocol_name;
     int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
     int64_t (*bdrv_getlength)(BlockDriverState *bs);
+    int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs);
     int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
                                  const uint8_t *buf, int nb_sectors);
 
diff --git a/qemu-img.c b/qemu-img.c
index 54137a4..b205e98 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1024,35 +1024,6 @@ out:
     return 0;
 }
 
-#ifdef _WIN32
-static int64_t get_allocated_file_size(const char *filename)
-{
-    typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
-    get_compressed_t get_compressed;
-    struct _stati64 st;
-
-    /* WinNT support GetCompressedFileSize to determine allocate size */
-    get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
-    if (get_compressed) {
-    	DWORD high, low;
-    	low = get_compressed(filename, &high);
-    	if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
-	    return (((int64_t) high) << 32) + low;
-    }
-
-    if (_stati64(filename, &st) < 0)
-        return -1;
-    return st.st_size;
-}
-#else
-static int64_t get_allocated_file_size(const char *filename)
-{
-    struct stat st;
-    if (stat(filename, &st) < 0)
-        return -1;
-    return (int64_t)st.st_blocks * 512;
-}
-#endif
 
 static void dump_snapshots(BlockDriverState *bs)
 {
@@ -1112,7 +1083,7 @@ static int img_info(int argc, char **argv)
     bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
     bdrv_get_geometry(bs, &total_sectors);
     get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
-    allocated_size = get_allocated_file_size(filename);
+    allocated_size = bdrv_get_allocated_file_size(bs);
     if (allocated_size < 0) {
         snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
     } else {
commit ae261c86aaed62e7acddafab8262a2bf286d40b7
Author: Fam Zheng <famcool at gmail.com>
Date:   Tue Jul 12 19:56:38 2011 +0800

    VMDK: fix coding style
    
    Conform coding style in vmdk.c to pass scripts/checkpatch.pl checks.
    
    Signed-off-by: Fam Zheng <famcool at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index b53c5f5..de08d0c 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -102,8 +102,9 @@ static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
 {
     uint32_t magic;
 
-    if (buf_size < 4)
+    if (buf_size < 4) {
         return 0;
+    }
     magic = be32_to_cpu(*(uint32_t *)buf);
     if (magic == VMDK3_MAGIC ||
         magic == VMDK4_MAGIC) {
@@ -193,9 +194,10 @@ static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
         cid_str_size = sizeof("CID");
     }
 
-    if ((p_name = strstr(desc,cid_str)) != NULL) {
+    p_name = strstr(desc, cid_str);
+    if (p_name != NULL) {
         p_name += cid_str_size;
-        sscanf(p_name,"%x",&cid);
+        sscanf(p_name, "%x", &cid);
     }
 
     return cid;
@@ -212,9 +214,10 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
         return -EIO;
     }
 
-    tmp_str = strstr(desc,"parentCID");
+    tmp_str = strstr(desc, "parentCID");
     pstrcpy(tmp_desc, sizeof(tmp_desc), tmp_str);
-    if ((p_name = strstr(desc,"CID")) != NULL) {
+    p_name = strstr(desc, "CID");
+    if (p_name != NULL) {
         p_name += sizeof("CID");
         snprintf(p_name, sizeof(desc) - (p_name - desc), "%x\n", cid);
         pstrcat(desc, sizeof(desc), tmp_desc);
@@ -234,13 +237,14 @@ static int vmdk_is_cid_valid(BlockDriverState *bs)
     uint32_t cur_pcid;
 
     if (p_bs) {
-        cur_pcid = vmdk_read_cid(p_bs,0);
-        if (s->parent_cid != cur_pcid)
-            // CID not valid
+        cur_pcid = vmdk_read_cid(p_bs, 0);
+        if (s->parent_cid != cur_pcid) {
+            /* CID not valid */
             return 0;
+        }
     }
 #endif
-    // CID valid
+    /* CID valid */
     return 1;
 }
 
@@ -255,14 +259,18 @@ static int vmdk_parent_open(BlockDriverState *bs)
         return -1;
     }
 
-    if ((p_name = strstr(desc,"parentFileNameHint")) != NULL) {
+    p_name = strstr(desc, "parentFileNameHint");
+    if (p_name != NULL) {
         char *end_name;
 
         p_name += sizeof("parentFileNameHint") + 1;
-        if ((end_name = strchr(p_name,'\"')) == NULL)
+        end_name = strchr(p_name, '\"');
+        if (end_name == NULL) {
             return -1;
-        if ((end_name - p_name) > sizeof (bs->backing_file) - 1)
+        }
+        if ((end_name - p_name) > sizeof(bs->backing_file) - 1) {
             return -1;
+        }
 
         pstrcpy(bs->backing_file, end_name - p_name + 1, p_name);
     }
@@ -595,8 +603,9 @@ static int get_whole_cluster(BlockDriverState *bs,
     if (bs->backing_hd) {
         int ret;
 
-        if (!vmdk_is_cid_valid(bs))
+        if (!vmdk_is_cid_valid(bs)) {
             return -1;
+        }
 
         /* floor offset to cluster */
         offset -= offset % (extent->cluster_sectors * 512);
@@ -655,8 +664,9 @@ static int get_cluster_offset(BlockDriverState *bs,
     int min_index, i, j;
     uint32_t min_count, *l2_table, tmp = 0;
 
-    if (m_data)
+    if (m_data) {
         m_data->valid = 0;
+    }
     if (extent->flat) {
         *cluster_offset = extent->flat_start_offset;
         return 0;
@@ -712,7 +722,7 @@ static int get_cluster_offset(BlockDriverState *bs,
             return -1;
         }
 
-        // Avoid the L2 tables update for the images that have snapshots.
+        /* Avoid the L2 tables update for the images that have snapshots. */
         *cluster_offset = bdrv_getlength(extent->file);
         bdrv_truncate(
             extent->file,
@@ -729,8 +739,9 @@ static int get_cluster_offset(BlockDriverState *bs,
          * or inappropriate VM shutdown.
          */
         if (get_whole_cluster(
-                bs, extent, *cluster_offset, offset, allocate) == -1)
+                bs, extent, *cluster_offset, offset, allocate) == -1) {
             return -1;
+        }
 
         if (m_data) {
             m_data->offset = tmp;
@@ -780,8 +791,9 @@ static int vmdk_is_allocated(BlockDriverState *bs, int64_t sector_num,
 
     index_in_cluster = sector_num % extent->cluster_sectors;
     n = extent->cluster_sectors - index_in_cluster;
-    if (n > nb_sectors)
+    if (n > nb_sectors) {
         n = nb_sectors;
+    }
     *pnum = n;
     return ret;
 }
@@ -805,16 +817,19 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
                             sector_num << 9, 0, &cluster_offset);
         index_in_cluster = sector_num % extent->cluster_sectors;
         n = extent->cluster_sectors - index_in_cluster;
-        if (n > nb_sectors)
+        if (n > nb_sectors) {
             n = nb_sectors;
+        }
         if (ret) {
             /* if not allocated, try to read from parent image, if exist */
             if (bs->backing_hd) {
-                if (!vmdk_is_cid_valid(bs))
+                if (!vmdk_is_cid_valid(bs)) {
                     return -EINVAL;
+                }
                 ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
-                if (ret < 0)
+                if (ret < 0) {
                     return ret;
+                }
             } else {
                 memset(buf, 0, 512 * n);
             }
@@ -888,7 +903,8 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
         sector_num += n;
         buf += n * 512;
 
-        // update CID on the first write every time the virtual disk is opened
+        /* update CID on the first write every time the virtual disk is
+         * opened */
         if (!s->cid_updated) {
             vmdk_write_cid(bs, time(NULL));
             s->cid_updated = true;
@@ -1301,16 +1317,16 @@ static QEMUOptionParameter vmdk_create_options[] = {
 };
 
 static BlockDriver bdrv_vmdk = {
-    .format_name	= "vmdk",
-    .instance_size	= sizeof(BDRVVmdkState),
-    .bdrv_probe		= vmdk_probe,
+    .format_name    = "vmdk",
+    .instance_size  = sizeof(BDRVVmdkState),
+    .bdrv_probe     = vmdk_probe,
     .bdrv_open      = vmdk_open,
-    .bdrv_read		= vmdk_read,
-    .bdrv_write		= vmdk_write,
-    .bdrv_close		= vmdk_close,
-    .bdrv_create	= vmdk_create,
-    .bdrv_flush		= vmdk_flush,
-    .bdrv_is_allocated	= vmdk_is_allocated,
+    .bdrv_read      = vmdk_read,
+    .bdrv_write     = vmdk_write,
+    .bdrv_close     = vmdk_close,
+    .bdrv_create    = vmdk_create,
+    .bdrv_flush     = vmdk_flush,
+    .bdrv_is_allocated  = vmdk_is_allocated,
 
     .create_options = vmdk_create_options,
 };
commit f66fd6c383edc137fa618c250ea40c1936a52f1c
Author: Fam Zheng <famcool at gmail.com>
Date:   Tue Jul 19 08:45:23 2011 +0800

    VMDK: create different subformats
    
    Add create option 'format', with enums:
        monolithicSparse
        monolithicFlat
        twoGbMaxExtentSparse
        twoGbMaxExtentFlat
    Each creates a subformat image file. The default is monolithicSparse.
    
    Signed-off-by: Fam Zheng <famcool at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index e1fb962..b53c5f5 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -156,8 +156,9 @@ static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
 #define CHECK_CID 1
 
 #define SECTOR_SIZE 512
-#define DESC_SIZE 20*SECTOR_SIZE	// 20 sectors of 512 bytes each
-#define HEADER_SIZE 512   			// first sector of 512 bytes
+#define DESC_SIZE (20 * SECTOR_SIZE)    /* 20 sectors of 512 bytes each */
+#define BUF_SIZE 4096
+#define HEADER_SIZE 512                 /* first sector of 512 bytes */
 
 static void vmdk_free_extents(BlockDriverState *bs)
 {
@@ -243,168 +244,6 @@ static int vmdk_is_cid_valid(BlockDriverState *bs)
     return 1;
 }
 
-static int vmdk_snapshot_create(const char *filename, const char *backing_file)
-{
-    int snp_fd, p_fd;
-    int ret;
-    uint32_t p_cid;
-    char *p_name, *gd_buf, *rgd_buf;
-    const char *real_filename, *temp_str;
-    VMDK4Header header;
-    uint32_t gde_entries, gd_size;
-    int64_t gd_offset, rgd_offset, capacity, gt_size;
-    char p_desc[DESC_SIZE], s_desc[DESC_SIZE], hdr[HEADER_SIZE];
-    static const char desc_template[] =
-    "# Disk DescriptorFile\n"
-    "version=1\n"
-    "CID=%x\n"
-    "parentCID=%x\n"
-    "createType=\"monolithicSparse\"\n"
-    "parentFileNameHint=\"%s\"\n"
-    "\n"
-    "# Extent description\n"
-    "RW %u SPARSE \"%s\"\n"
-    "\n"
-    "# The Disk Data Base \n"
-    "#DDB\n"
-    "\n";
-
-    snp_fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644);
-    if (snp_fd < 0)
-        return -errno;
-    p_fd = open(backing_file, O_RDONLY | O_BINARY | O_LARGEFILE);
-    if (p_fd < 0) {
-        close(snp_fd);
-        return -errno;
-    }
-
-    /* read the header */
-    if (lseek(p_fd, 0x0, SEEK_SET) == -1) {
-        ret = -errno;
-        goto fail;
-    }
-    if (read(p_fd, hdr, HEADER_SIZE) != HEADER_SIZE) {
-        ret = -errno;
-        goto fail;
-    }
-
-    /* write the header */
-    if (lseek(snp_fd, 0x0, SEEK_SET) == -1) {
-        ret = -errno;
-        goto fail;
-    }
-    if (write(snp_fd, hdr, HEADER_SIZE) == -1) {
-        ret = -errno;
-        goto fail;
-    }
-
-    memset(&header, 0, sizeof(header));
-    memcpy(&header,&hdr[4], sizeof(header)); // skip the VMDK4_MAGIC
-
-    if (ftruncate(snp_fd, header.grain_offset << 9)) {
-        ret = -errno;
-        goto fail;
-    }
-    /* the descriptor offset = 0x200 */
-    if (lseek(p_fd, 0x200, SEEK_SET) == -1) {
-        ret = -errno;
-        goto fail;
-    }
-    if (read(p_fd, p_desc, DESC_SIZE) != DESC_SIZE) {
-        ret = -errno;
-        goto fail;
-    }
-
-    if ((p_name = strstr(p_desc,"CID")) != NULL) {
-        p_name += sizeof("CID");
-        sscanf(p_name,"%x",&p_cid);
-    }
-
-    real_filename = filename;
-    if ((temp_str = strrchr(real_filename, '\\')) != NULL)
-        real_filename = temp_str + 1;
-    if ((temp_str = strrchr(real_filename, '/')) != NULL)
-        real_filename = temp_str + 1;
-    if ((temp_str = strrchr(real_filename, ':')) != NULL)
-        real_filename = temp_str + 1;
-
-    snprintf(s_desc, sizeof(s_desc), desc_template, p_cid, p_cid, backing_file,
-             (uint32_t)header.capacity, real_filename);
-
-    /* write the descriptor */
-    if (lseek(snp_fd, 0x200, SEEK_SET) == -1) {
-        ret = -errno;
-        goto fail;
-    }
-    if (write(snp_fd, s_desc, strlen(s_desc)) == -1) {
-        ret = -errno;
-        goto fail;
-    }
-
-    gd_offset = header.gd_offset * SECTOR_SIZE;     // offset of GD table
-    rgd_offset = header.rgd_offset * SECTOR_SIZE;   // offset of RGD table
-    capacity = header.capacity * SECTOR_SIZE;       // Extent size
-    /*
-     * Each GDE span 32M disk, means:
-     * 512 GTE per GT, each GTE points to grain
-     */
-    gt_size = (int64_t)header.num_gtes_per_gte * header.granularity * SECTOR_SIZE;
-    if (!gt_size) {
-        ret = -EINVAL;
-        goto fail;
-    }
-    gde_entries = (uint32_t)(capacity / gt_size);  // number of gde/rgde
-    gd_size = gde_entries * sizeof(uint32_t);
-
-    /* write RGD */
-    rgd_buf = qemu_malloc(gd_size);
-    if (lseek(p_fd, rgd_offset, SEEK_SET) == -1) {
-        ret = -errno;
-        goto fail_rgd;
-    }
-    if (read(p_fd, rgd_buf, gd_size) != gd_size) {
-        ret = -errno;
-        goto fail_rgd;
-    }
-    if (lseek(snp_fd, rgd_offset, SEEK_SET) == -1) {
-        ret = -errno;
-        goto fail_rgd;
-    }
-    if (write(snp_fd, rgd_buf, gd_size) == -1) {
-        ret = -errno;
-        goto fail_rgd;
-    }
-
-    /* write GD */
-    gd_buf = qemu_malloc(gd_size);
-    if (lseek(p_fd, gd_offset, SEEK_SET) == -1) {
-        ret = -errno;
-        goto fail_gd;
-    }
-    if (read(p_fd, gd_buf, gd_size) != gd_size) {
-        ret = -errno;
-        goto fail_gd;
-    }
-    if (lseek(snp_fd, gd_offset, SEEK_SET) == -1) {
-        ret = -errno;
-        goto fail_gd;
-    }
-    if (write(snp_fd, gd_buf, gd_size) == -1) {
-        ret = -errno;
-        goto fail_gd;
-    }
-    ret = 0;
-
-fail_gd:
-    qemu_free(gd_buf);
-fail_rgd:
-    qemu_free(rgd_buf);
-fail:
-    close(p_fd);
-    close(snp_fd);
-    return ret;
-}
-
 static int vmdk_parent_open(BlockDriverState *bs)
 {
     char *p_name;
@@ -1058,68 +897,40 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
     return 0;
 }
 
-static int vmdk_create(const char *filename, QEMUOptionParameter *options)
+
+static int vmdk_create_extent(const char *filename, int64_t filesize, bool flat)
 {
-    int fd, i;
+    int ret, i;
+    int fd = 0;
     VMDK4Header header;
     uint32_t tmp, magic, grains, gd_size, gt_size, gt_count;
-    static const char desc_template[] =
-        "# Disk DescriptorFile\n"
-        "version=1\n"
-        "CID=%x\n"
-        "parentCID=ffffffff\n"
-        "createType=\"monolithicSparse\"\n"
-        "\n"
-        "# Extent description\n"
-        "RW %" PRId64 " SPARSE \"%s\"\n"
-        "\n"
-        "# The Disk Data Base \n"
-        "#DDB\n"
-        "\n"
-        "ddb.virtualHWVersion = \"%d\"\n"
-        "ddb.geometry.cylinders = \"%" PRId64 "\"\n"
-        "ddb.geometry.heads = \"16\"\n"
-        "ddb.geometry.sectors = \"63\"\n"
-        "ddb.adapterType = \"ide\"\n";
-    char desc[1024];
-    const char *real_filename, *temp_str;
-    int64_t total_size = 0;
-    const char *backing_file = NULL;
-    int flags = 0;
-    int ret;
 
-    // Read out options
-    while (options && options->name) {
-        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
-            total_size = options->value.n / 512;
-        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
-            backing_file = options->value.s;
-        } else if (!strcmp(options->name, BLOCK_OPT_COMPAT6)) {
-            flags |= options->value.n ? BLOCK_FLAG_COMPAT6: 0;
-        }
-        options++;
+    fd = open(
+        filename,
+        O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
+        0644);
+    if (fd < 0) {
+        return -errno;
     }
-
-    /* XXX: add support for backing file */
-    if (backing_file) {
-        return vmdk_snapshot_create(filename, backing_file);
+    if (flat) {
+        ret = ftruncate(fd, filesize);
+        if (ret < 0) {
+            ret = -errno;
+        }
+        goto exit;
     }
-
-    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
-              0644);
-    if (fd < 0)
-        return -errno;
     magic = cpu_to_be32(VMDK4_MAGIC);
     memset(&header, 0, sizeof(header));
     header.version = 1;
     header.flags = 3; /* ?? */
-    header.capacity = total_size;
+    header.capacity = filesize / 512;
     header.granularity = 128;
     header.num_gtes_per_gte = 512;
 
-    grains = (total_size + header.granularity - 1) / header.granularity;
+    grains = (filesize / 512 + header.granularity - 1) / header.granularity;
     gt_size = ((header.num_gtes_per_gte * sizeof(uint32_t)) + 511) >> 9;
-    gt_count = (grains + header.num_gtes_per_gte - 1) / header.num_gtes_per_gte;
+    gt_count =
+        (grains + header.num_gtes_per_gte - 1) / header.num_gtes_per_gte;
     gd_size = (gt_count * sizeof(uint32_t) + 511) >> 9;
 
     header.desc_offset = 1;
@@ -1130,7 +941,6 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options)
        ((header.gd_offset + gd_size + (gt_size * gt_count) +
          header.granularity - 1) / header.granularity) *
         header.granularity;
-
     /* swap endianness for all header fields */
     header.version = cpu_to_le32(header.version);
     header.flags = cpu_to_le32(header.flags);
@@ -1188,27 +998,255 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options)
         }
     }
 
-    /* compose the descriptor */
-    real_filename = filename;
-    if ((temp_str = strrchr(real_filename, '\\')) != NULL)
-        real_filename = temp_str + 1;
-    if ((temp_str = strrchr(real_filename, '/')) != NULL)
-        real_filename = temp_str + 1;
-    if ((temp_str = strrchr(real_filename, ':')) != NULL)
-        real_filename = temp_str + 1;
-    snprintf(desc, sizeof(desc), desc_template, (unsigned int)time(NULL),
-             total_size, real_filename,
-             (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4),
-             total_size / (int64_t)(63 * 16));
-
-    /* write the descriptor */
-    lseek(fd, le64_to_cpu(header.desc_offset) << 9, SEEK_SET);
+    ret = 0;
+ exit:
+    close(fd);
+    return ret;
+}
+
+static int filename_decompose(const char *filename, char *path, char *prefix,
+        char *postfix, size_t buf_len)
+{
+    const char *p, *q;
+
+    if (filename == NULL || !strlen(filename)) {
+        fprintf(stderr, "Vmdk: no filename provided.\n");
+        return -1;
+    }
+    p = strrchr(filename, '/');
+    if (p == NULL) {
+        p = strrchr(filename, '\\');
+    }
+    if (p == NULL) {
+        p = strrchr(filename, ':');
+    }
+    if (p != NULL) {
+        p++;
+        if (p - filename >= buf_len) {
+            return -1;
+        }
+        pstrcpy(path, p - filename + 1, filename);
+    } else {
+        p = filename;
+        path[0] = '\0';
+    }
+    q = strrchr(p, '.');
+    if (q == NULL) {
+        pstrcpy(prefix, buf_len, p);
+        postfix[0] = '\0';
+    } else {
+        if (q - p >= buf_len) {
+            return -1;
+        }
+        pstrcpy(prefix, q - p + 1, p);
+        pstrcpy(postfix, buf_len, q);
+    }
+    return 0;
+}
+
+static int relative_path(char *dest, int dest_size,
+        const char *base, const char *target)
+{
+    int i = 0;
+    int n = 0;
+    const char *p, *q;
+#ifdef _WIN32
+    const char *sep = "\\";
+#else
+    const char *sep = "/";
+#endif
+
+    if (!(dest && base && target)) {
+        return -1;
+    }
+    if (path_is_absolute(target)) {
+        dest[dest_size - 1] = '\0';
+        strncpy(dest, target, dest_size - 1);
+        return 0;
+    }
+    while (base[i] == target[i]) {
+        i++;
+    }
+    p = &base[i];
+    q = &target[i];
+    while (*p) {
+        if (*p == *sep) {
+            n++;
+        }
+        p++;
+    }
+    dest[0] = '\0';
+    for (; n; n--) {
+        pstrcat(dest, dest_size, "..");
+        pstrcat(dest, dest_size, sep);
+    }
+    pstrcat(dest, dest_size, q);
+    return 0;
+}
+
+static int vmdk_create(const char *filename, QEMUOptionParameter *options)
+{
+    int fd, idx = 0;
+    char desc[BUF_SIZE];
+    int64_t total_size = 0, filesize;
+    const char *backing_file = NULL;
+    const char *fmt = NULL;
+    int flags = 0;
+    int ret = 0;
+    bool flat, split;
+    char ext_desc_lines[BUF_SIZE] = "";
+    char path[PATH_MAX], prefix[PATH_MAX], postfix[PATH_MAX];
+    const int64_t split_size = 0x80000000;  /* VMDK has constant split size */
+    const char *desc_extent_line;
+    char parent_desc_line[BUF_SIZE] = "";
+    uint32_t parent_cid = 0xffffffff;
+    const char desc_template[] =
+        "# Disk DescriptorFile\n"
+        "version=1\n"
+        "CID=%x\n"
+        "parentCID=%x\n"
+        "createType=\"%s\"\n"
+        "%s"
+        "\n"
+        "# Extent description\n"
+        "%s"
+        "\n"
+        "# The Disk Data Base\n"
+        "#DDB\n"
+        "\n"
+        "ddb.virtualHWVersion = \"%d\"\n"
+        "ddb.geometry.cylinders = \"%" PRId64 "\"\n"
+        "ddb.geometry.heads = \"16\"\n"
+        "ddb.geometry.sectors = \"63\"\n"
+        "ddb.adapterType = \"ide\"\n";
+
+    if (filename_decompose(filename, path, prefix, postfix, PATH_MAX)) {
+        return -EINVAL;
+    }
+    /* Read out options */
+    while (options && options->name) {
+        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
+            total_size = options->value.n;
+        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
+            backing_file = options->value.s;
+        } else if (!strcmp(options->name, BLOCK_OPT_COMPAT6)) {
+            flags |= options->value.n ? BLOCK_FLAG_COMPAT6 : 0;
+        } else if (!strcmp(options->name, BLOCK_OPT_SUBFMT)) {
+            fmt = options->value.s;
+        }
+        options++;
+    }
+    if (!fmt) {
+        /* Default format to monolithicSparse */
+        fmt = "monolithicSparse";
+    } else if (strcmp(fmt, "monolithicFlat") &&
+               strcmp(fmt, "monolithicSparse") &&
+               strcmp(fmt, "twoGbMaxExtentSparse") &&
+               strcmp(fmt, "twoGbMaxExtentFlat")) {
+        fprintf(stderr, "VMDK: Unknown subformat: %s\n", fmt);
+        return -EINVAL;
+    }
+    split = !(strcmp(fmt, "twoGbMaxExtentFlat") &&
+              strcmp(fmt, "twoGbMaxExtentSparse"));
+    flat = !(strcmp(fmt, "monolithicFlat") &&
+             strcmp(fmt, "twoGbMaxExtentFlat"));
+    if (flat) {
+        desc_extent_line = "RW %lld FLAT \"%s\" 0\n";
+    } else {
+        desc_extent_line = "RW %lld SPARSE \"%s\"\n";
+    }
+    if (flat && backing_file) {
+        /* not supporting backing file for flat image */
+        return -ENOTSUP;
+    }
+    if (backing_file) {
+        char parent_filename[PATH_MAX];
+        BlockDriverState *bs = bdrv_new("");
+        ret = bdrv_open(bs, backing_file, 0, NULL);
+        if (ret != 0) {
+            bdrv_delete(bs);
+            return ret;
+        }
+        if (strcmp(bs->drv->format_name, "vmdk")) {
+            bdrv_delete(bs);
+            return -EINVAL;
+        }
+        filesize = bdrv_getlength(bs);
+        parent_cid = vmdk_read_cid(bs, 0);
+        bdrv_delete(bs);
+        relative_path(parent_filename, sizeof(parent_filename),
+                      filename, backing_file);
+        snprintf(parent_desc_line, sizeof(parent_desc_line),
+                "parentFileNameHint=\"%s\"", parent_filename);
+    }
+
+    /* Create extents */
+    filesize = total_size;
+    while (filesize > 0) {
+        char desc_line[BUF_SIZE];
+        char ext_filename[PATH_MAX];
+        char desc_filename[PATH_MAX];
+        int64_t size = filesize;
+
+        if (split && size > split_size) {
+            size = split_size;
+        }
+        if (split) {
+            snprintf(desc_filename, sizeof(desc_filename), "%s-%c%03d%s",
+                    prefix, flat ? 'f' : 's', ++idx, postfix);
+        } else if (flat) {
+            snprintf(desc_filename, sizeof(desc_filename), "%s-flat%s",
+                    prefix, postfix);
+        } else {
+            snprintf(desc_filename, sizeof(desc_filename), "%s%s",
+                    prefix, postfix);
+        }
+        snprintf(ext_filename, sizeof(ext_filename), "%s%s",
+                path, desc_filename);
+
+        if (vmdk_create_extent(ext_filename, size, flat)) {
+            return -EINVAL;
+        }
+        filesize -= size;
+
+        /* Format description line */
+        snprintf(desc_line, sizeof(desc_line),
+                    desc_extent_line, size / 512, desc_filename);
+        pstrcat(ext_desc_lines, sizeof(ext_desc_lines), desc_line);
+    }
+    /* generate descriptor file */
+    snprintf(desc, sizeof(desc), desc_template,
+            (unsigned int)time(NULL),
+            parent_cid,
+            fmt,
+            parent_desc_line,
+            ext_desc_lines,
+            (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4),
+            total_size / (int64_t)(63 * 16 * 512));
+    if (split || flat) {
+        fd = open(
+                filename,
+                O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
+                0644);
+    } else {
+        fd = open(
+                filename,
+                O_WRONLY | O_BINARY | O_LARGEFILE,
+                0644);
+    }
+    if (fd < 0) {
+        return -errno;
+    }
+    /* the descriptor offset = 0x200 */
+    if (!split && !flat && 0x200 != lseek(fd, 0x200, SEEK_SET)) {
+        ret = -errno;
+        goto exit;
+    }
     ret = qemu_write_full(fd, desc, strlen(desc));
     if (ret != strlen(desc)) {
         ret = -errno;
         goto exit;
     }
-
     ret = 0;
 exit:
     close(fd);
@@ -1252,6 +1290,13 @@ static QEMUOptionParameter vmdk_create_options[] = {
         .type = OPT_FLAG,
         .help = "VMDK version 6 image"
     },
+    {
+        .name = BLOCK_OPT_SUBFMT,
+        .type = OPT_STRING,
+        .help =
+            "VMDK flat extent format, can be one of "
+            "{monolithicSparse (default) | monolithicFlat | twoGbMaxExtentSparse | twoGbMaxExtentFlat} "
+    },
     { NULL }
 };
 
diff --git a/block_int.h b/block_int.h
index 1e265d2..8a7b6cb 100644
--- a/block_int.h
+++ b/block_int.h
@@ -39,6 +39,7 @@
 #define BLOCK_OPT_CLUSTER_SIZE  "cluster_size"
 #define BLOCK_OPT_TABLE_SIZE    "table_size"
 #define BLOCK_OPT_PREALLOC      "preallocation"
+#define BLOCK_OPT_SUBFMT        "subformat"
 
 typedef struct AIOPool {
     void (*cancel)(BlockDriverAIOCB *acb);
commit 7fa60fa3778f1c7336d4e91d4055773538609539
Author: Fam Zheng <famcool at gmail.com>
Date:   Tue Jul 19 08:38:22 2011 +0800

    VMDK: open/read/write for monolithicFlat image
    
    Parse vmdk decriptor file and open mono flat image.
    Read/write the flat extent.
    
    Signed-off-by: Fam Zheng <famcool at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index f637d98..e1fb962 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -65,6 +65,7 @@ typedef struct VmdkExtent {
     bool flat;
     int64_t sectors;
     int64_t end_sector;
+    int64_t flat_start_offset;
     int64_t l1_table_offset;
     int64_t l1_backup_table_offset;
     uint32_t *l1_table;
@@ -407,9 +408,10 @@ fail:
 static int vmdk_parent_open(BlockDriverState *bs)
 {
     char *p_name;
-    char desc[DESC_SIZE];
+    char desc[DESC_SIZE + 1];
     BDRVVmdkState *s = bs->opaque;
 
+    desc[DESC_SIZE] = '\0';
     if (bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE) != DESC_SIZE) {
         return -1;
     }
@@ -584,6 +586,144 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, int flags)
     return ret;
 }
 
+/* find an option value out of descriptor file */
+static int vmdk_parse_description(const char *desc, const char *opt_name,
+        char *buf, int buf_size)
+{
+    char *opt_pos, *opt_end;
+    const char *end = desc + strlen(desc);
+
+    opt_pos = strstr(desc, opt_name);
+    if (!opt_pos) {
+        return -1;
+    }
+    /* Skip "=\"" following opt_name */
+    opt_pos += strlen(opt_name) + 2;
+    if (opt_pos >= end) {
+        return -1;
+    }
+    opt_end = opt_pos;
+    while (opt_end < end && *opt_end != '"') {
+        opt_end++;
+    }
+    if (opt_end == end || buf_size < opt_end - opt_pos + 1) {
+        return -1;
+    }
+    pstrcpy(buf, opt_end - opt_pos + 1, opt_pos);
+    return 0;
+}
+
+static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
+        const char *desc_file_path)
+{
+    int ret;
+    char access[11];
+    char type[11];
+    char fname[512];
+    const char *p = desc;
+    int64_t sectors = 0;
+    int64_t flat_offset;
+
+    while (*p) {
+        /* parse extent line:
+         * RW [size in sectors] FLAT "file-name.vmdk" OFFSET
+         * or
+         * RW [size in sectors] SPARSE "file-name.vmdk"
+         */
+        flat_offset = -1;
+        ret = sscanf(p, "%10s %" SCNd64 " %10s %511s %" SCNd64,
+                access, &sectors, type, fname, &flat_offset);
+        if (ret < 4 || strcmp(access, "RW")) {
+            goto next_line;
+        } else if (!strcmp(type, "FLAT")) {
+            if (ret != 5 || flat_offset < 0) {
+                return -EINVAL;
+            }
+        } else if (ret != 4) {
+            return -EINVAL;
+        }
+
+        /* trim the quotation marks around */
+        if (fname[0] == '"') {
+            memmove(fname, fname + 1, strlen(fname));
+            if (strlen(fname) <= 1 || fname[strlen(fname) - 1] != '"') {
+                return -EINVAL;
+            }
+            fname[strlen(fname) - 1] = '\0';
+        }
+        if (sectors <= 0 ||
+            (strcmp(type, "FLAT") && strcmp(type, "SPARSE")) ||
+            (strcmp(access, "RW"))) {
+            goto next_line;
+        }
+
+        /* save to extents array */
+        if (!strcmp(type, "FLAT")) {
+            /* FLAT extent */
+            char extent_path[PATH_MAX];
+            BlockDriverState *extent_file;
+            VmdkExtent *extent;
+
+            path_combine(extent_path, sizeof(extent_path),
+                    desc_file_path, fname);
+            ret = bdrv_file_open(&extent_file, extent_path, bs->open_flags);
+            if (ret) {
+                return ret;
+            }
+            extent = vmdk_add_extent(bs, extent_file, true, sectors,
+                            0, 0, 0, 0, sectors);
+            extent->flat_start_offset = flat_offset;
+        } else {
+            /* SPARSE extent, not supported for now */
+            fprintf(stderr,
+                "VMDK: Not supported extent type \"%s\""".\n", type);
+            return -ENOTSUP;
+        }
+next_line:
+        /* move to next line */
+        while (*p && *p != '\n') {
+            p++;
+        }
+        p++;
+    }
+    return 0;
+}
+
+static int vmdk_open_desc_file(BlockDriverState *bs, int flags)
+{
+    int ret;
+    char buf[2048];
+    char ct[128];
+    BDRVVmdkState *s = bs->opaque;
+
+    ret = bdrv_pread(bs->file, 0, buf, sizeof(buf));
+    if (ret < 0) {
+        return ret;
+    }
+    buf[2047] = '\0';
+    if (vmdk_parse_description(buf, "createType", ct, sizeof(ct))) {
+        return -EINVAL;
+    }
+    if (strcmp(ct, "monolithicFlat")) {
+        fprintf(stderr,
+                "VMDK: Not supported image type \"%s\""".\n", ct);
+        return -ENOTSUP;
+    }
+    s->desc_offset = 0;
+    ret = vmdk_parse_extents(buf, bs, bs->file->filename);
+    if (ret) {
+        return ret;
+    }
+
+    /* try to open parent images, if exist */
+    if (vmdk_parent_open(bs)) {
+        qemu_free(s->extents);
+        return -EINVAL;
+    }
+    s->parent_cid = vmdk_read_cid(bs, 1);
+    return 0;
+}
+
 static int vmdk_open(BlockDriverState *bs, int flags)
 {
     uint32_t magic;
@@ -598,7 +738,7 @@ static int vmdk_open(BlockDriverState *bs, int flags)
     } else if (magic == VMDK4_MAGIC) {
         return vmdk_open_vmdk4(bs, flags);
     } else {
-        return -EINVAL;
+        return vmdk_open_desc_file(bs, flags);
     }
 }
 
@@ -679,7 +819,7 @@ static int get_cluster_offset(BlockDriverState *bs,
     if (m_data)
         m_data->valid = 0;
     if (extent->flat) {
-        *cluster_offset = 0;
+        *cluster_offset = extent->flat_start_offset;
         return 0;
     }
 
@@ -832,16 +972,20 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
             /* if not allocated, try to read from parent image, if exist */
             if (bs->backing_hd) {
                 if (!vmdk_is_cid_valid(bs))
-                    return -1;
+                    return -EINVAL;
                 ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
                 if (ret < 0)
-                    return -1;
+                    return ret;
             } else {
                 memset(buf, 0, 512 * n);
             }
         } else {
-            if(bdrv_pread(bs->file, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
-                return -1;
+            ret = bdrv_pread(extent->file,
+                            cluster_offset + index_in_cluster * 512,
+                            buf, n * 512);
+            if (ret < 0) {
+                return ret;
+            }
         }
         nb_sectors -= n;
         sector_num += n;
@@ -865,7 +1009,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
                 "(VMDK) Wrong offset: sector_num=0x%" PRIx64
                 " total_sectors=0x%" PRIx64 "\n",
                 sector_num, bs->total_sectors);
-        return -1;
+        return -EIO;
     }
 
     while (nb_sectors > 0) {
@@ -888,16 +1032,17 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
             n = nb_sectors;
         }
 
-        if (bdrv_pwrite(bs->file,
+        ret = bdrv_pwrite(extent->file,
                         cluster_offset + index_in_cluster * 512,
-                        buf, n * 512)
-                != n * 512) {
-            return -1;
+                        buf,
+                        n * 512);
+        if (ret < 0) {
+            return ret;
         }
         if (m_data.valid) {
             /* update L2 tables */
             if (vmdk_L2update(extent, &m_data) == -1) {
-                return -1;
+                return -EIO;
             }
         }
         nb_sectors -= n;
commit 91b85bd388c3767e6b63aaf33851dbfe87ea24d1
Author: Fam Zheng <famcool at gmail.com>
Date:   Tue Jul 12 19:56:35 2011 +0800

    VMDK: change get_cluster_offset return type
    
    The return type of get_cluster_offset was an offset that use 0 to denote
    'not allocated', this will be no longer true for flat extents, as we see
    flat extent file as a single huge cluster whose offset is 0 and length
    is the whole file length.
    So now we use int return value, 0 means success and otherwise offset
    invalid.
    
    Signed-off-by: Fam Zheng <famcool at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index 8dc58a8..f637d98 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -665,26 +665,31 @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data)
     return 0;
 }
 
-static uint64_t get_cluster_offset(BlockDriverState *bs,
+static int get_cluster_offset(BlockDriverState *bs,
                                     VmdkExtent *extent,
                                     VmdkMetaData *m_data,
-                                    uint64_t offset, int allocate)
+                                    uint64_t offset,
+                                    int allocate,
+                                    uint64_t *cluster_offset)
 {
     unsigned int l1_index, l2_offset, l2_index;
     int min_index, i, j;
     uint32_t min_count, *l2_table, tmp = 0;
-    uint64_t cluster_offset;
 
     if (m_data)
         m_data->valid = 0;
+    if (extent->flat) {
+        *cluster_offset = 0;
+        return 0;
+    }
 
     l1_index = (offset >> 9) / extent->l1_entry_sectors;
     if (l1_index >= extent->l1_size) {
-        return 0;
+        return -1;
     }
     l2_offset = extent->l1_table[l1_index];
     if (!l2_offset) {
-        return 0;
+        return -1;
     }
     for (i = 0; i < L2_CACHE_SIZE; i++) {
         if (l2_offset == extent->l2_cache_offsets[i]) {
@@ -714,28 +719,29 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
                 l2_table,
                 extent->l2_size * sizeof(uint32_t)
             ) != extent->l2_size * sizeof(uint32_t)) {
-        return 0;
+        return -1;
     }
 
     extent->l2_cache_offsets[min_index] = l2_offset;
     extent->l2_cache_counts[min_index] = 1;
  found:
     l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size;
-    cluster_offset = le32_to_cpu(l2_table[l2_index]);
+    *cluster_offset = le32_to_cpu(l2_table[l2_index]);
 
-    if (!cluster_offset) {
-        if (!allocate)
-            return 0;
+    if (!*cluster_offset) {
+        if (!allocate) {
+            return -1;
+        }
 
         // Avoid the L2 tables update for the images that have snapshots.
-        cluster_offset = bdrv_getlength(extent->file);
+        *cluster_offset = bdrv_getlength(extent->file);
         bdrv_truncate(
             extent->file,
-            cluster_offset + (extent->cluster_sectors << 9)
+            *cluster_offset + (extent->cluster_sectors << 9)
         );
 
-        cluster_offset >>= 9;
-        tmp = cpu_to_le32(cluster_offset);
+        *cluster_offset >>= 9;
+        tmp = cpu_to_le32(*cluster_offset);
         l2_table[l2_index] = tmp;
 
         /* First of all we write grain itself, to avoid race condition
@@ -744,8 +750,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
          * or inappropriate VM shutdown.
          */
         if (get_whole_cluster(
-                bs, extent, cluster_offset, offset, allocate) == -1)
-            return 0;
+                bs, extent, *cluster_offset, offset, allocate) == -1)
+            return -1;
 
         if (m_data) {
             m_data->offset = tmp;
@@ -755,8 +761,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
             m_data->valid = 1;
         }
     }
-    cluster_offset <<= 9;
-    return cluster_offset;
+    *cluster_offset <<= 9;
+    return 0;
 }
 
 static VmdkExtent *find_extent(BDRVVmdkState *s,
@@ -780,7 +786,6 @@ static int vmdk_is_allocated(BlockDriverState *bs, int64_t sector_num,
                              int nb_sectors, int *pnum)
 {
     BDRVVmdkState *s = bs->opaque;
-
     int64_t index_in_cluster, n, ret;
     uint64_t offset;
     VmdkExtent *extent;
@@ -789,15 +794,13 @@ static int vmdk_is_allocated(BlockDriverState *bs, int64_t sector_num,
     if (!extent) {
         return 0;
     }
-    if (extent->flat) {
-        n = extent->end_sector - sector_num;
-        ret = 1;
-    } else {
-        offset = get_cluster_offset(bs, extent, NULL, sector_num * 512, 0);
-        index_in_cluster = sector_num % extent->cluster_sectors;
-        n = extent->cluster_sectors - index_in_cluster;
-        ret = offset ? 1 : 0;
-    }
+    ret = get_cluster_offset(bs, extent, NULL,
+                            sector_num * 512, 0, &offset);
+    /* get_cluster_offset returning 0 means success */
+    ret = !ret;
+
+    index_in_cluster = sector_num % extent->cluster_sectors;
+    n = extent->cluster_sectors - index_in_cluster;
     if (n > nb_sectors)
         n = nb_sectors;
     *pnum = n;
@@ -818,14 +821,15 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
         if (!extent) {
             return -EIO;
         }
-        cluster_offset = get_cluster_offset(
-                            bs, extent, NULL, sector_num << 9, 0);
+        ret = get_cluster_offset(
+                            bs, extent, NULL,
+                            sector_num << 9, 0, &cluster_offset);
         index_in_cluster = sector_num % extent->cluster_sectors;
         n = extent->cluster_sectors - index_in_cluster;
         if (n > nb_sectors)
             n = nb_sectors;
-        if (!cluster_offset) {
-            // try to read from parent image, if exist
+        if (ret) {
+            /* if not allocated, try to read from parent image, if exist */
             if (bs->backing_hd) {
                 if (!vmdk_is_cid_valid(bs))
                     return -1;
@@ -851,7 +855,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
 {
     BDRVVmdkState *s = bs->opaque;
     VmdkExtent *extent = NULL;
-    int n;
+    int n, ret;
     int64_t index_in_cluster;
     uint64_t cluster_offset;
     VmdkMetaData m_data;
@@ -869,13 +873,14 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
         if (!extent) {
             return -EIO;
         }
-        cluster_offset = get_cluster_offset(
+        ret = get_cluster_offset(
                                 bs,
                                 extent,
                                 &m_data,
-                                sector_num << 9, 1);
-        if (!cluster_offset) {
-            return -1;
+                                sector_num << 9, 1,
+                                &cluster_offset);
+        if (ret) {
+            return -EINVAL;
         }
         index_in_cluster = sector_num % extent->cluster_sectors;
         n = extent->cluster_sectors - index_in_cluster;
commit 69b4d86d9f7feb6083cedb0c5fb65fdc30daf623
Author: Fam Zheng <famcool at gmail.com>
Date:   Tue Jul 12 19:56:34 2011 +0800

    VMDK: move 'static' cid_update flag to bs field
    
    Cid_update is the flag for updating CID on first write after opening the
    image. This should be per image open rather than per program life cycle,
    so change it from static var of vmdk_write to a field in BDRVVmdkState.
    
    Signed-off-by: Fam Zheng <famcool at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index f6d2986..8dc58a8 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -82,6 +82,7 @@ typedef struct VmdkExtent {
 
 typedef struct BDRVVmdkState {
     int desc_offset;
+    bool cid_updated;
     uint32_t parent_cid;
     int num_extents;
     /* Extent array with num_extents entries, ascend ordered by address */
@@ -853,7 +854,6 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
     int n;
     int64_t index_in_cluster;
     uint64_t cluster_offset;
-    static int cid_update = 0;
     VmdkMetaData m_data;
 
     if (sector_num > bs->total_sectors) {
@@ -900,9 +900,9 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
         buf += n * 512;
 
         // update CID on the first write every time the virtual disk is opened
-        if (!cid_update) {
+        if (!s->cid_updated) {
             vmdk_write_cid(bs, time(NULL));
-            cid_update++;
+            s->cid_updated = true;
         }
     }
     return 0;
commit 333c574d054f95912beef4f020f4128868463fd4
Author: Fam Zheng <famcool at gmail.com>
Date:   Tue Jul 12 19:56:33 2011 +0800

    VMDK: flush multiple extents
    
    Flush all the file that referenced by the image.
    
    Signed-off-by: Fam Zheng <famcool at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index 529ae90..f6d2986 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1072,7 +1072,17 @@ static void vmdk_close(BlockDriverState *bs)
 
 static int vmdk_flush(BlockDriverState *bs)
 {
-    return bdrv_flush(bs->file);
+    int i, ret, err;
+    BDRVVmdkState *s = bs->opaque;
+
+    ret = bdrv_flush(bs->file);
+    for (i = 0; i < s->num_extents; i++) {
+        err = bdrv_flush(s->extents[i].file);
+        if (err < 0) {
+            ret = err;
+        }
+    }
+    return ret;
 }
 
 
commit e1da9b2433f78c4de3bac8c2a97173c648d212c0
Author: Fam Zheng <famcool at gmail.com>
Date:   Tue Jul 12 19:56:32 2011 +0800

    VMDK: add field BDRVVmdkState.desc_offset
    
    There are several occurrence of magic number 0x200 as the descriptor
    offset within mono sparse image file. This is not the case for images
    with separate descriptor file. So a field is added to BDRVVmdkState to
    hold the correct value.
    
    Signed-off-by: Fam Zheng <famcool at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index 6d7b497..529ae90 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -81,6 +81,7 @@ typedef struct VmdkExtent {
 } VmdkExtent;
 
 typedef struct BDRVVmdkState {
+    int desc_offset;
     uint32_t parent_cid;
     int num_extents;
     /* Extent array with num_extents entries, ascend ordered by address */
@@ -175,10 +176,11 @@ static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
     uint32_t cid;
     const char *p_name, *cid_str;
     size_t cid_str_size;
+    BDRVVmdkState *s = bs->opaque;
 
-    /* the descriptor offset = 0x200 */
-    if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+    if (bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE) != DESC_SIZE) {
         return 0;
+    }
 
     if (parent) {
         cid_str = "parentCID";
@@ -200,10 +202,12 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
 {
     char desc[DESC_SIZE], tmp_desc[DESC_SIZE];
     char *p_name, *tmp_str;
+    BDRVVmdkState *s = bs->opaque;
 
-    /* the descriptor offset = 0x200 */
-    if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE)
-        return -1;
+    memset(desc, 0, sizeof(desc));
+    if (bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE) != DESC_SIZE) {
+        return -EIO;
+    }
 
     tmp_str = strstr(desc,"parentCID");
     pstrcpy(tmp_desc, sizeof(tmp_desc), tmp_str);
@@ -213,8 +217,9 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
         pstrcat(desc, sizeof(desc), tmp_desc);
     }
 
-    if (bdrv_pwrite_sync(bs->file, 0x200, desc, DESC_SIZE) < 0)
-        return -1;
+    if (bdrv_pwrite_sync(bs->file, s->desc_offset, desc, DESC_SIZE) < 0) {
+        return -EIO;
+    }
     return 0;
 }
 
@@ -402,10 +407,11 @@ static int vmdk_parent_open(BlockDriverState *bs)
 {
     char *p_name;
     char desc[DESC_SIZE];
+    BDRVVmdkState *s = bs->opaque;
 
-    /* the descriptor offset = 0x200 */
-    if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+    if (bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE) != DESC_SIZE) {
         return -1;
+    }
 
     if ((p_name = strstr(desc,"parentFileNameHint")) != NULL) {
         char *end_name;
@@ -506,8 +512,10 @@ static int vmdk_open_vmdk3(BlockDriverState *bs, int flags)
     int ret;
     uint32_t magic;
     VMDK3Header header;
+    BDRVVmdkState *s = bs->opaque;
     VmdkExtent *extent;
 
+    s->desc_offset = 0x200;
     ret = bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header));
     if (ret < 0) {
         goto fail;
@@ -539,6 +547,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, int flags)
     BDRVVmdkState *s = bs->opaque;
     VmdkExtent *extent;
 
+    s->desc_offset = 0x200;
     ret = bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header));
     if (ret < 0) {
         goto fail;
commit b4b3ab146c6d8a7ababc5760c9a0ef7cee78707e
Author: Fam Zheng <famcool at gmail.com>
Date:   Tue Jul 12 19:56:31 2011 +0800

    VMDK: separate vmdk_open by format version
    
    Separate vmdk_open by subformats to:
    * vmdk_open_vmdk3
    * vmdk_open_vmdk4
    
    Signed-off-by: Fam Zheng <famcool at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index f8a815c..6d7b497 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -458,67 +458,20 @@ static VmdkExtent *vmdk_add_extent(BlockDriverState *bs,
     return extent;
 }
 
-
-static int vmdk_open(BlockDriverState *bs, int flags)
+static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent)
 {
-    BDRVVmdkState *s = bs->opaque;
-    uint32_t magic;
-    int i;
-    uint32_t l1_size, l1_entry_sectors;
-    VmdkExtent *extent = NULL;
-
-    if (bdrv_pread(bs->file, 0, &magic, sizeof(magic)) != sizeof(magic))
-        goto fail;
-
-    magic = be32_to_cpu(magic);
-    if (magic == VMDK3_MAGIC) {
-        VMDK3Header header;
-        if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header))
-                != sizeof(header)) {
-            goto fail;
-        }
-        extent = vmdk_add_extent(bs, bs->file, false,
-                              le32_to_cpu(header.disk_sectors),
-                              le32_to_cpu(header.l1dir_offset) << 9, 0,
-                              1 << 6, 1 << 9, le32_to_cpu(header.granularity));
-    } else if (magic == VMDK4_MAGIC) {
-        VMDK4Header header;
-        if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header))
-                != sizeof(header)) {
-            goto fail;
-        }
-        l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
-                            * le64_to_cpu(header.granularity);
-        l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1)
-                    / l1_entry_sectors;
-        extent = vmdk_add_extent(bs, bs->file, false,
-                              le64_to_cpu(header.capacity),
-                              le64_to_cpu(header.gd_offset) << 9,
-                              le64_to_cpu(header.rgd_offset) << 9,
-                              l1_size,
-                              le32_to_cpu(header.num_gtes_per_gte),
-                              le64_to_cpu(header.granularity));
-        if (extent->l1_entry_sectors <= 0) {
-            goto fail;
-        }
-        // try to open parent images, if exist
-        if (vmdk_parent_open(bs) != 0)
-            goto fail;
-        // write the CID once after the image creation
-        s->parent_cid = vmdk_read_cid(bs,1);
-    } else {
-        goto fail;
-    }
+    int ret;
+    int l1_size, i;
 
     /* read the L1 table */
     l1_size = extent->l1_size * sizeof(uint32_t);
     extent->l1_table = qemu_malloc(l1_size);
-    if (bdrv_pread(bs->file,
-            extent->l1_table_offset,
-            extent->l1_table,
-            l1_size)
-        != l1_size) {
-        goto fail;
+    ret = bdrv_pread(extent->file,
+                    extent->l1_table_offset,
+                    extent->l1_table,
+                    l1_size);
+    if (ret < 0) {
+        goto fail_l1;
     }
     for (i = 0; i < extent->l1_size; i++) {
         le32_to_cpus(&extent->l1_table[i]);
@@ -526,12 +479,12 @@ static int vmdk_open(BlockDriverState *bs, int flags)
 
     if (extent->l1_backup_table_offset) {
         extent->l1_backup_table = qemu_malloc(l1_size);
-        if (bdrv_pread(bs->file,
-                    extent->l1_backup_table_offset,
-                    extent->l1_backup_table,
-                    l1_size)
-                != l1_size) {
-            goto fail;
+        ret = bdrv_pread(extent->file,
+                        extent->l1_backup_table_offset,
+                        extent->l1_backup_table,
+                        l1_size);
+        if (ret < 0) {
+            goto fail_l1b;
         }
         for (i = 0; i < extent->l1_size; i++) {
             le32_to_cpus(&extent->l1_backup_table[i]);
@@ -541,9 +494,102 @@ static int vmdk_open(BlockDriverState *bs, int flags)
     extent->l2_cache =
         qemu_malloc(extent->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
     return 0;
+ fail_l1b:
+    qemu_free(extent->l1_backup_table);
+ fail_l1:
+    qemu_free(extent->l1_table);
+    return ret;
+}
+
+static int vmdk_open_vmdk3(BlockDriverState *bs, int flags)
+{
+    int ret;
+    uint32_t magic;
+    VMDK3Header header;
+    VmdkExtent *extent;
+
+    ret = bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header));
+    if (ret < 0) {
+        goto fail;
+    }
+    extent = vmdk_add_extent(bs,
+                             bs->file, false,
+                             le32_to_cpu(header.disk_sectors),
+                             le32_to_cpu(header.l1dir_offset) << 9,
+                             0, 1 << 6, 1 << 9,
+                             le32_to_cpu(header.granularity));
+    ret = vmdk_init_tables(bs, extent);
+    if (ret) {
+        /* vmdk_init_tables cleans up on fail, so only free allocation of
+         * vmdk_add_extent here. */
+        goto fail;
+    }
+    return 0;
  fail:
     vmdk_free_extents(bs);
-    return -1;
+    return ret;
+}
+
+static int vmdk_open_vmdk4(BlockDriverState *bs, int flags)
+{
+    int ret;
+    uint32_t magic;
+    uint32_t l1_size, l1_entry_sectors;
+    VMDK4Header header;
+    BDRVVmdkState *s = bs->opaque;
+    VmdkExtent *extent;
+
+    ret = bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header));
+    if (ret < 0) {
+        goto fail;
+    }
+    l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
+                        * le64_to_cpu(header.granularity);
+    l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1)
+                / l1_entry_sectors;
+    extent = vmdk_add_extent(bs, bs->file, false,
+                          le64_to_cpu(header.capacity),
+                          le64_to_cpu(header.gd_offset) << 9,
+                          le64_to_cpu(header.rgd_offset) << 9,
+                          l1_size,
+                          le32_to_cpu(header.num_gtes_per_gte),
+                          le64_to_cpu(header.granularity));
+    if (extent->l1_entry_sectors <= 0) {
+        ret = -EINVAL;
+        goto fail;
+    }
+    /* try to open parent images, if exist */
+    ret = vmdk_parent_open(bs);
+    if (ret) {
+        goto fail;
+    }
+    s->parent_cid = vmdk_read_cid(bs, 1);
+    ret = vmdk_init_tables(bs, extent);
+    if (ret) {
+        goto fail;
+    }
+    return 0;
+ fail:
+    vmdk_free_extents(bs);
+    return ret;
+}
+
+static int vmdk_open(BlockDriverState *bs, int flags)
+{
+    uint32_t magic;
+
+    if (bdrv_pread(bs->file, 0, &magic, sizeof(magic)) != sizeof(magic)) {
+        return -EIO;
+    }
+
+    magic = be32_to_cpu(magic);
+    if (magic == VMDK3_MAGIC) {
+        return vmdk_open_vmdk3(bs, flags);
+    } else if (magic == VMDK4_MAGIC) {
+        return vmdk_open_vmdk4(bs, flags);
+    } else {
+        return -EINVAL;
+    }
 }
 
 static int get_whole_cluster(BlockDriverState *bs,
@@ -630,11 +676,11 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
     if (!l2_offset) {
         return 0;
     }
-    for(i = 0; i < L2_CACHE_SIZE; i++) {
+    for (i = 0; i < L2_CACHE_SIZE; i++) {
         if (l2_offset == extent->l2_cache_offsets[i]) {
             /* increment the hit count */
             if (++extent->l2_cache_counts[i] == 0xffffffff) {
-                for(j = 0; j < L2_CACHE_SIZE; j++) {
+                for (j = 0; j < L2_CACHE_SIZE; j++) {
                     extent->l2_cache_counts[j] >>= 1;
                 }
             }
@@ -645,7 +691,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
     /* not found: load a new entry in the least used one */
     min_index = 0;
     min_count = 0xffffffff;
-    for(i = 0; i < L2_CACHE_SIZE; i++) {
+    for (i = 0; i < L2_CACHE_SIZE; i++) {
         if (extent->l2_cache_counts[i] < min_count) {
             min_count = extent->l2_cache_counts[i];
             min_index = i;
commit 01fc99d6a8f56c8dc4a7466476d6dcb0ad91f589
Author: Fam Zheng <famcool at gmail.com>
Date:   Tue Jul 12 19:56:30 2011 +0800

    VMDK: probe for monolithicFlat images
    
    Probe as the same behavior as VMware does.
    Recognize image as monolithicFlat descriptor file when the file is text
    and the first effective line (not '#' leaded comment or space line) is
    either 'version=1' or 'version=2'. No space or upper case charactors
    accepted.
    
    Signed-off-by: Fam Zheng <famcool at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index 03a4619..f8a815c 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -103,10 +103,51 @@ static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
         return 0;
     magic = be32_to_cpu(*(uint32_t *)buf);
     if (magic == VMDK3_MAGIC ||
-        magic == VMDK4_MAGIC)
+        magic == VMDK4_MAGIC) {
         return 100;
-    else
+    } else {
+        const char *p = (const char *)buf;
+        const char *end = p + buf_size;
+        while (p < end) {
+            if (*p == '#') {
+                /* skip comment line */
+                while (p < end && *p != '\n') {
+                    p++;
+                }
+                p++;
+                continue;
+            }
+            if (*p == ' ') {
+                while (p < end && *p == ' ') {
+                    p++;
+                }
+                /* skip '\r' if windows line endings used. */
+                if (p < end && *p == '\r') {
+                    p++;
+                }
+                /* only accept blank lines before 'version=' line */
+                if (p == end || *p != '\n') {
+                    return 0;
+                }
+                p++;
+                continue;
+            }
+            if (end - p >= strlen("version=X\n")) {
+                if (strncmp("version=1\n", p, strlen("version=1\n")) == 0 ||
+                    strncmp("version=2\n", p, strlen("version=2\n")) == 0) {
+                    return 100;
+                }
+            }
+            if (end - p >= strlen("version=X\r\n")) {
+                if (strncmp("version=1\r\n", p, strlen("version=1\r\n")) == 0 ||
+                    strncmp("version=2\r\n", p, strlen("version=2\r\n")) == 0) {
+                    return 100;
+                }
+            }
+            return 0;
+        }
         return 0;
+    }
 }
 
 #define CHECK_CID 1
commit 0e69c543946957fe8450ebb13874bb1ef280d55b
Author: Fam Zheng <famcool at gmail.com>
Date:   Tue Jul 12 19:56:29 2011 +0800

    VMDK: bugfix, align offset to cluster in get_whole_cluster
    
    In get_whole_cluster, the offset is not aligned to cluster when reading
    from backing_hd. When the first write to child is not at the cluster
    boundary, wrong address data from parent is copied to child.
    
    Signed-off-by: Fam Zheng <famcool at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index 3b78583..03a4619 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -514,21 +514,23 @@ static int get_whole_cluster(BlockDriverState *bs,
     /* 128 sectors * 512 bytes each = grain size 64KB */
     uint8_t  whole_grain[extent->cluster_sectors * 512];
 
-    // we will be here if it's first write on non-exist grain(cluster).
-    // try to read from parent image, if exist
+    /* we will be here if it's first write on non-exist grain(cluster).
+     * try to read from parent image, if exist */
     if (bs->backing_hd) {
         int ret;
 
         if (!vmdk_is_cid_valid(bs))
             return -1;
 
+        /* floor offset to cluster */
+        offset -= offset % (extent->cluster_sectors * 512);
         ret = bdrv_read(bs->backing_hd, offset >> 9, whole_grain,
                 extent->cluster_sectors);
         if (ret < 0) {
             return -1;
         }
 
-        //Write grain only into the active image
+        /* Write grain only into the active image */
         ret = bdrv_write(extent->file, cluster_offset, whole_grain,
                 extent->cluster_sectors);
         if (ret < 0) {
commit b3976d3c8b895e8929d133b80ef5e373b60cf357
Author: Fam Zheng <famcool at gmail.com>
Date:   Tue Jul 12 19:56:28 2011 +0800

    VMDK: introduce VmdkExtent
    
    Introduced VmdkExtent array into BDRVVmdkState, enable holding multiple
    image extents for multiple file image support.
    
    Signed-off-by: Fam Zheng <famcool at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index 922b23d..3b78583 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -60,7 +60,11 @@ typedef struct {
 
 #define L2_CACHE_SIZE 16
 
-typedef struct BDRVVmdkState {
+typedef struct VmdkExtent {
+    BlockDriverState *file;
+    bool flat;
+    int64_t sectors;
+    int64_t end_sector;
     int64_t l1_table_offset;
     int64_t l1_backup_table_offset;
     uint32_t *l1_table;
@@ -74,7 +78,13 @@ typedef struct BDRVVmdkState {
     uint32_t l2_cache_counts[L2_CACHE_SIZE];
 
     unsigned int cluster_sectors;
+} VmdkExtent;
+
+typedef struct BDRVVmdkState {
     uint32_t parent_cid;
+    int num_extents;
+    /* Extent array with num_extents entries, ascend ordered by address */
+    VmdkExtent *extents;
 } BDRVVmdkState;
 
 typedef struct VmdkMetaData {
@@ -105,6 +115,19 @@ static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
 #define DESC_SIZE 20*SECTOR_SIZE	// 20 sectors of 512 bytes each
 #define HEADER_SIZE 512   			// first sector of 512 bytes
 
+static void vmdk_free_extents(BlockDriverState *bs)
+{
+    int i;
+    BDRVVmdkState *s = bs->opaque;
+
+    for (i = 0; i < s->num_extents; i++) {
+        qemu_free(s->extents[i].l1_table);
+        qemu_free(s->extents[i].l2_cache);
+        qemu_free(s->extents[i].l1_backup_table);
+    }
+    qemu_free(s->extents);
+}
+
 static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
 {
     char desc[DESC_SIZE];
@@ -358,11 +381,50 @@ static int vmdk_parent_open(BlockDriverState *bs)
     return 0;
 }
 
+/* Create and append extent to the extent array. Return the added VmdkExtent
+ * address. return NULL if allocation failed. */
+static VmdkExtent *vmdk_add_extent(BlockDriverState *bs,
+                           BlockDriverState *file, bool flat, int64_t sectors,
+                           int64_t l1_offset, int64_t l1_backup_offset,
+                           uint32_t l1_size,
+                           int l2_size, unsigned int cluster_sectors)
+{
+    VmdkExtent *extent;
+    BDRVVmdkState *s = bs->opaque;
+
+    s->extents = qemu_realloc(s->extents,
+                              (s->num_extents + 1) * sizeof(VmdkExtent));
+    extent = &s->extents[s->num_extents];
+    s->num_extents++;
+
+    memset(extent, 0, sizeof(VmdkExtent));
+    extent->file = file;
+    extent->flat = flat;
+    extent->sectors = sectors;
+    extent->l1_table_offset = l1_offset;
+    extent->l1_backup_table_offset = l1_backup_offset;
+    extent->l1_size = l1_size;
+    extent->l1_entry_sectors = l2_size * cluster_sectors;
+    extent->l2_size = l2_size;
+    extent->cluster_sectors = cluster_sectors;
+
+    if (s->num_extents > 1) {
+        extent->end_sector = (*(extent - 1)).end_sector + extent->sectors;
+    } else {
+        extent->end_sector = extent->sectors;
+    }
+    bs->total_sectors = extent->end_sector;
+    return extent;
+}
+
+
 static int vmdk_open(BlockDriverState *bs, int flags)
 {
     BDRVVmdkState *s = bs->opaque;
     uint32_t magic;
-    int l1_size, i;
+    int i;
+    uint32_t l1_size, l1_entry_sectors;
+    VmdkExtent *extent = NULL;
 
     if (bdrv_pread(bs->file, 0, &magic, sizeof(magic)) != sizeof(magic))
         goto fail;
@@ -370,32 +432,34 @@ static int vmdk_open(BlockDriverState *bs, int flags)
     magic = be32_to_cpu(magic);
     if (magic == VMDK3_MAGIC) {
         VMDK3Header header;
-
-        if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)) != sizeof(header))
+        if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header))
+                != sizeof(header)) {
             goto fail;
-        s->cluster_sectors = le32_to_cpu(header.granularity);
-        s->l2_size = 1 << 9;
-        s->l1_size = 1 << 6;
-        bs->total_sectors = le32_to_cpu(header.disk_sectors);
-        s->l1_table_offset = le32_to_cpu(header.l1dir_offset) << 9;
-        s->l1_backup_table_offset = 0;
-        s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
+        }
+        extent = vmdk_add_extent(bs, bs->file, false,
+                              le32_to_cpu(header.disk_sectors),
+                              le32_to_cpu(header.l1dir_offset) << 9, 0,
+                              1 << 6, 1 << 9, le32_to_cpu(header.granularity));
     } else if (magic == VMDK4_MAGIC) {
         VMDK4Header header;
-
-        if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)) != sizeof(header))
+        if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header))
+                != sizeof(header)) {
             goto fail;
-        bs->total_sectors = le64_to_cpu(header.capacity);
-        s->cluster_sectors = le64_to_cpu(header.granularity);
-        s->l2_size = le32_to_cpu(header.num_gtes_per_gte);
-        s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
-        if (s->l1_entry_sectors <= 0)
+        }
+        l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
+                            * le64_to_cpu(header.granularity);
+        l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1)
+                    / l1_entry_sectors;
+        extent = vmdk_add_extent(bs, bs->file, false,
+                              le64_to_cpu(header.capacity),
+                              le64_to_cpu(header.gd_offset) << 9,
+                              le64_to_cpu(header.rgd_offset) << 9,
+                              l1_size,
+                              le32_to_cpu(header.num_gtes_per_gte),
+                              le64_to_cpu(header.granularity));
+        if (extent->l1_entry_sectors <= 0) {
             goto fail;
-        s->l1_size = (bs->total_sectors + s->l1_entry_sectors - 1)
-            / s->l1_entry_sectors;
-        s->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9;
-        s->l1_backup_table_offset = le64_to_cpu(header.gd_offset) << 9;
-
+        }
         // try to open parent images, if exist
         if (vmdk_parent_open(bs) != 0)
             goto fail;
@@ -406,40 +470,49 @@ static int vmdk_open(BlockDriverState *bs, int flags)
     }
 
     /* read the L1 table */
-    l1_size = s->l1_size * sizeof(uint32_t);
-    s->l1_table = qemu_malloc(l1_size);
-    if (bdrv_pread(bs->file, s->l1_table_offset, s->l1_table, l1_size) != l1_size)
+    l1_size = extent->l1_size * sizeof(uint32_t);
+    extent->l1_table = qemu_malloc(l1_size);
+    if (bdrv_pread(bs->file,
+            extent->l1_table_offset,
+            extent->l1_table,
+            l1_size)
+        != l1_size) {
         goto fail;
-    for(i = 0; i < s->l1_size; i++) {
-        le32_to_cpus(&s->l1_table[i]);
+    }
+    for (i = 0; i < extent->l1_size; i++) {
+        le32_to_cpus(&extent->l1_table[i]);
     }
 
-    if (s->l1_backup_table_offset) {
-        s->l1_backup_table = qemu_malloc(l1_size);
-        if (bdrv_pread(bs->file, s->l1_backup_table_offset, s->l1_backup_table, l1_size) != l1_size)
+    if (extent->l1_backup_table_offset) {
+        extent->l1_backup_table = qemu_malloc(l1_size);
+        if (bdrv_pread(bs->file,
+                    extent->l1_backup_table_offset,
+                    extent->l1_backup_table,
+                    l1_size)
+                != l1_size) {
             goto fail;
-        for(i = 0; i < s->l1_size; i++) {
-            le32_to_cpus(&s->l1_backup_table[i]);
+        }
+        for (i = 0; i < extent->l1_size; i++) {
+            le32_to_cpus(&extent->l1_backup_table[i]);
         }
     }
 
-    s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
+    extent->l2_cache =
+        qemu_malloc(extent->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
     return 0;
  fail:
-    qemu_free(s->l1_backup_table);
-    qemu_free(s->l1_table);
-    qemu_free(s->l2_cache);
+    vmdk_free_extents(bs);
     return -1;
 }
 
-static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
-                                   uint64_t offset, int allocate);
-
-static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset,
-                             uint64_t offset, int allocate)
+static int get_whole_cluster(BlockDriverState *bs,
+                VmdkExtent *extent,
+                uint64_t cluster_offset,
+                uint64_t offset,
+                bool allocate)
 {
-    BDRVVmdkState *s = bs->opaque;
-    uint8_t  whole_grain[s->cluster_sectors*512];        // 128 sectors * 512 bytes each = grain size 64KB
+    /* 128 sectors * 512 bytes each = grain size 64KB */
+    uint8_t  whole_grain[extent->cluster_sectors * 512];
 
     // we will be here if it's first write on non-exist grain(cluster).
     // try to read from parent image, if exist
@@ -450,14 +523,14 @@ static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset,
             return -1;
 
         ret = bdrv_read(bs->backing_hd, offset >> 9, whole_grain,
-            s->cluster_sectors);
+                extent->cluster_sectors);
         if (ret < 0) {
             return -1;
         }
 
         //Write grain only into the active image
-        ret = bdrv_write(bs->file, cluster_offset, whole_grain,
-            s->cluster_sectors);
+        ret = bdrv_write(extent->file, cluster_offset, whole_grain,
+                extent->cluster_sectors);
         if (ret < 0) {
             return -1;
         }
@@ -465,29 +538,39 @@ static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset,
     return 0;
 }
 
-static int vmdk_L2update(BlockDriverState *bs, VmdkMetaData *m_data)
+static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data)
 {
-    BDRVVmdkState *s = bs->opaque;
-
     /* update L2 table */
-    if (bdrv_pwrite_sync(bs->file, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
-                    &(m_data->offset), sizeof(m_data->offset)) < 0)
+    if (bdrv_pwrite_sync(
+                extent->file,
+                ((int64_t)m_data->l2_offset * 512)
+                    + (m_data->l2_index * sizeof(m_data->offset)),
+                &(m_data->offset),
+                sizeof(m_data->offset)
+            ) < 0) {
         return -1;
+    }
     /* update backup L2 table */
-    if (s->l1_backup_table_offset != 0) {
-        m_data->l2_offset = s->l1_backup_table[m_data->l1_index];
-        if (bdrv_pwrite_sync(bs->file, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
-                        &(m_data->offset), sizeof(m_data->offset)) < 0)
+    if (extent->l1_backup_table_offset != 0) {
+        m_data->l2_offset = extent->l1_backup_table[m_data->l1_index];
+        if (bdrv_pwrite_sync(
+                    extent->file,
+                    ((int64_t)m_data->l2_offset * 512)
+                        + (m_data->l2_index * sizeof(m_data->offset)),
+                    &(m_data->offset), sizeof(m_data->offset)
+                ) < 0) {
             return -1;
+        }
     }
 
     return 0;
 }
 
-static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
-                                   uint64_t offset, int allocate)
+static uint64_t get_cluster_offset(BlockDriverState *bs,
+                                    VmdkExtent *extent,
+                                    VmdkMetaData *m_data,
+                                    uint64_t offset, int allocate)
 {
-    BDRVVmdkState *s = bs->opaque;
     unsigned int l1_index, l2_offset, l2_index;
     int min_index, i, j;
     uint32_t min_count, *l2_table, tmp = 0;
@@ -496,21 +579,23 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
     if (m_data)
         m_data->valid = 0;
 
-    l1_index = (offset >> 9) / s->l1_entry_sectors;
-    if (l1_index >= s->l1_size)
+    l1_index = (offset >> 9) / extent->l1_entry_sectors;
+    if (l1_index >= extent->l1_size) {
         return 0;
-    l2_offset = s->l1_table[l1_index];
-    if (!l2_offset)
+    }
+    l2_offset = extent->l1_table[l1_index];
+    if (!l2_offset) {
         return 0;
+    }
     for(i = 0; i < L2_CACHE_SIZE; i++) {
-        if (l2_offset == s->l2_cache_offsets[i]) {
+        if (l2_offset == extent->l2_cache_offsets[i]) {
             /* increment the hit count */
-            if (++s->l2_cache_counts[i] == 0xffffffff) {
+            if (++extent->l2_cache_counts[i] == 0xffffffff) {
                 for(j = 0; j < L2_CACHE_SIZE; j++) {
-                    s->l2_cache_counts[j] >>= 1;
+                    extent->l2_cache_counts[j] >>= 1;
                 }
             }
-            l2_table = s->l2_cache + (i * s->l2_size);
+            l2_table = extent->l2_cache + (i * extent->l2_size);
             goto found;
         }
     }
@@ -518,20 +603,25 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
     min_index = 0;
     min_count = 0xffffffff;
     for(i = 0; i < L2_CACHE_SIZE; i++) {
-        if (s->l2_cache_counts[i] < min_count) {
-            min_count = s->l2_cache_counts[i];
+        if (extent->l2_cache_counts[i] < min_count) {
+            min_count = extent->l2_cache_counts[i];
             min_index = i;
         }
     }
-    l2_table = s->l2_cache + (min_index * s->l2_size);
-    if (bdrv_pread(bs->file, (int64_t)l2_offset * 512, l2_table, s->l2_size * sizeof(uint32_t)) !=
-                                                                        s->l2_size * sizeof(uint32_t))
+    l2_table = extent->l2_cache + (min_index * extent->l2_size);
+    if (bdrv_pread(
+                extent->file,
+                (int64_t)l2_offset * 512,
+                l2_table,
+                extent->l2_size * sizeof(uint32_t)
+            ) != extent->l2_size * sizeof(uint32_t)) {
         return 0;
+    }
 
-    s->l2_cache_offsets[min_index] = l2_offset;
-    s->l2_cache_counts[min_index] = 1;
+    extent->l2_cache_offsets[min_index] = l2_offset;
+    extent->l2_cache_counts[min_index] = 1;
  found:
-    l2_index = ((offset >> 9) / s->cluster_sectors) % s->l2_size;
+    l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size;
     cluster_offset = le32_to_cpu(l2_table[l2_index]);
 
     if (!cluster_offset) {
@@ -539,8 +629,11 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
             return 0;
 
         // Avoid the L2 tables update for the images that have snapshots.
-        cluster_offset = bdrv_getlength(bs->file);
-        bdrv_truncate(bs->file, cluster_offset + (s->cluster_sectors << 9));
+        cluster_offset = bdrv_getlength(extent->file);
+        bdrv_truncate(
+            extent->file,
+            cluster_offset + (extent->cluster_sectors << 9)
+        );
 
         cluster_offset >>= 9;
         tmp = cpu_to_le32(cluster_offset);
@@ -551,7 +644,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
          * This problem may occur because of insufficient space on host disk
          * or inappropriate VM shutdown.
          */
-        if (get_whole_cluster(bs, cluster_offset, offset, allocate) == -1)
+        if (get_whole_cluster(
+                bs, extent, cluster_offset, offset, allocate) == -1)
             return 0;
 
         if (m_data) {
@@ -566,33 +660,69 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
     return cluster_offset;
 }
 
+static VmdkExtent *find_extent(BDRVVmdkState *s,
+                                int64_t sector_num, VmdkExtent *start_hint)
+{
+    VmdkExtent *extent = start_hint;
+
+    if (!extent) {
+        extent = &s->extents[0];
+    }
+    while (extent < &s->extents[s->num_extents]) {
+        if (sector_num < extent->end_sector) {
+            return extent;
+        }
+        extent++;
+    }
+    return NULL;
+}
+
 static int vmdk_is_allocated(BlockDriverState *bs, int64_t sector_num,
                              int nb_sectors, int *pnum)
 {
     BDRVVmdkState *s = bs->opaque;
-    int index_in_cluster, n;
-    uint64_t cluster_offset;
 
-    cluster_offset = get_cluster_offset(bs, NULL, sector_num << 9, 0);
-    index_in_cluster = sector_num % s->cluster_sectors;
-    n = s->cluster_sectors - index_in_cluster;
+    int64_t index_in_cluster, n, ret;
+    uint64_t offset;
+    VmdkExtent *extent;
+
+    extent = find_extent(s, sector_num, NULL);
+    if (!extent) {
+        return 0;
+    }
+    if (extent->flat) {
+        n = extent->end_sector - sector_num;
+        ret = 1;
+    } else {
+        offset = get_cluster_offset(bs, extent, NULL, sector_num * 512, 0);
+        index_in_cluster = sector_num % extent->cluster_sectors;
+        n = extent->cluster_sectors - index_in_cluster;
+        ret = offset ? 1 : 0;
+    }
     if (n > nb_sectors)
         n = nb_sectors;
     *pnum = n;
-    return (cluster_offset != 0);
+    return ret;
 }
 
 static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
                     uint8_t *buf, int nb_sectors)
 {
     BDRVVmdkState *s = bs->opaque;
-    int index_in_cluster, n, ret;
+    int ret;
+    uint64_t n, index_in_cluster;
+    VmdkExtent *extent = NULL;
     uint64_t cluster_offset;
 
     while (nb_sectors > 0) {
-        cluster_offset = get_cluster_offset(bs, NULL, sector_num << 9, 0);
-        index_in_cluster = sector_num % s->cluster_sectors;
-        n = s->cluster_sectors - index_in_cluster;
+        extent = find_extent(s, sector_num, extent);
+        if (!extent) {
+            return -EIO;
+        }
+        cluster_offset = get_cluster_offset(
+                            bs, extent, NULL, sector_num << 9, 0);
+        index_in_cluster = sector_num % extent->cluster_sectors;
+        n = extent->cluster_sectors - index_in_cluster;
         if (n > nb_sectors)
             n = nb_sectors;
         if (!cluster_offset) {
@@ -621,10 +751,12 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
                      const uint8_t *buf, int nb_sectors)
 {
     BDRVVmdkState *s = bs->opaque;
-    VmdkMetaData m_data;
-    int index_in_cluster, n;
+    VmdkExtent *extent = NULL;
+    int n;
+    int64_t index_in_cluster;
     uint64_t cluster_offset;
     static int cid_update = 0;
+    VmdkMetaData m_data;
 
     if (sector_num > bs->total_sectors) {
         fprintf(stderr,
@@ -635,20 +767,35 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
     }
 
     while (nb_sectors > 0) {
-        index_in_cluster = sector_num & (s->cluster_sectors - 1);
-        n = s->cluster_sectors - index_in_cluster;
-        if (n > nb_sectors)
-            n = nb_sectors;
-        cluster_offset = get_cluster_offset(bs, &m_data, sector_num << 9, 1);
-        if (!cluster_offset)
+        extent = find_extent(s, sector_num, extent);
+        if (!extent) {
+            return -EIO;
+        }
+        cluster_offset = get_cluster_offset(
+                                bs,
+                                extent,
+                                &m_data,
+                                sector_num << 9, 1);
+        if (!cluster_offset) {
             return -1;
+        }
+        index_in_cluster = sector_num % extent->cluster_sectors;
+        n = extent->cluster_sectors - index_in_cluster;
+        if (n > nb_sectors) {
+            n = nb_sectors;
+        }
 
-        if (bdrv_pwrite(bs->file, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
+        if (bdrv_pwrite(bs->file,
+                        cluster_offset + index_in_cluster * 512,
+                        buf, n * 512)
+                != n * 512) {
             return -1;
+        }
         if (m_data.valid) {
             /* update L2 tables */
-            if (vmdk_L2update(bs, &m_data) == -1)
+            if (vmdk_L2update(extent, &m_data) == -1) {
                 return -1;
+            }
         }
         nb_sectors -= n;
         sector_num += n;
@@ -822,10 +969,7 @@ exit:
 
 static void vmdk_close(BlockDriverState *bs)
 {
-    BDRVVmdkState *s = bs->opaque;
-
-    qemu_free(s->l1_table);
-    qemu_free(s->l2_cache);
+    vmdk_free_extents(bs);
 }
 
 static int vmdk_flush(BlockDriverState *bs)
commit 69d7e218fd9846b7f5946fe8e17ca609c7fd7ef1
Author: Luiz Capitulino <lcapitulino at gmail.com>
Date:   Tue Jul 12 17:35:09 2011 -0300

    qemu-config: Document -drive options
    
    Signed-off-by: Luiz Capitulino <lcapitulino at gmail.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-config.c b/qemu-config.c
index c63741c..93d20c6 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -23,6 +23,7 @@ static QemuOptsList qemu_drive_opts = {
         },{
             .name = "index",
             .type = QEMU_OPT_NUMBER,
+            .help = "index number",
         },{
             .name = "cyls",
             .type = QEMU_OPT_NUMBER,
@@ -46,6 +47,7 @@ static QemuOptsList qemu_drive_opts = {
         },{
             .name = "snapshot",
             .type = QEMU_OPT_BOOL,
+            .help = "enable/disable snapshot mode",
         },{
             .name = "file",
             .type = QEMU_OPT_STRING,
@@ -65,12 +67,15 @@ static QemuOptsList qemu_drive_opts = {
         },{
             .name = "serial",
             .type = QEMU_OPT_STRING,
+            .help = "disk serial number",
         },{
             .name = "rerror",
             .type = QEMU_OPT_STRING,
+            .help = "read error action",
         },{
             .name = "werror",
             .type = QEMU_OPT_STRING,
+            .help = "write error action",
         },{
             .name = "addr",
             .type = QEMU_OPT_STRING,
@@ -78,6 +83,7 @@ static QemuOptsList qemu_drive_opts = {
         },{
             .name = "readonly",
             .type = QEMU_OPT_BOOL,
+            .help = "open drive file as read-only",
         },
         { /* end of list */ }
     },
commit ae73e5919a75622d2c029d5a0e240115990fb735
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Tue Jul 12 17:35:08 2011 -0300

    qemu-options.hx: Document missing -drive options
    
    They are 'werror', 'rerror' and 'readonly'.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index e6d7adc..64114dd 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -160,6 +160,14 @@ an untrusted format header.
 This option specifies the serial number to assign to the device.
 @item addr=@var{addr}
 Specify the controller's PCI address (if=virtio only).
+ at item werror=@var{action},rerror=@var{action}
+Specify which @var{action} to take on write and read errors. Valid actions are:
+"ignore" (ignore the error and try to continue), "stop" (pause QEMU),
+"report" (report the error to the guest), "enospc" (pause QEMU only if the
+host disk is full; report the error to the guest otherwise).
+The default setting is @option{werror=enospc} and @option{rerror=report}.
+ at item readonly
+Open drive @option{file} as read-only. Guest write attempts will fail.
 @end table
 
 By default, writethrough caching is used for all block device.  This means that
commit 3e1c0c9a4bbaf90a96b14efb771d766fdd091b38
Author: Hannes Reinecke <hare at suse.de>
Date:   Mon Jul 11 15:02:26 2011 +0200

    scsi-disk: Mask out serial number EVPD
    
    If the serial number is not set we should mask it out in the
    list of supported VPD pages and mark it as not supported.
    
    Signed-off-by: Hannes Reinecke <hare at suse.de>
    Acked-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 5804662..05d14ab 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -398,7 +398,8 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
                     "buffer size %zd\n", req->cmd.xfer);
             pages = buflen++;
             outbuf[buflen++] = 0x00; // list of supported pages (this page)
-            outbuf[buflen++] = 0x80; // unit serial number
+            if (s->serial)
+                outbuf[buflen++] = 0x80; // unit serial number
             outbuf[buflen++] = 0x83; // device identification
             if (s->drive_kind == SCSI_HD) {
                 outbuf[buflen++] = 0xb0; // block limits
@@ -409,8 +410,14 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
         }
         case 0x80: /* Device serial number, optional */
         {
-            int l = strlen(s->serial);
+            int l;
 
+            if (!s->serial) {
+                DPRINTF("Inquiry (EVPD[Serial number] not supported\n");
+                return -1;
+            }
+
+            l = strlen(s->serial);
             if (l > req->cmd.xfer)
                 l = req->cmd.xfer;
             if (l > 20)
@@ -1203,7 +1210,9 @@ static int scsi_initfn(SCSIDevice *dev, SCSIDriveKind kind)
     if (!s->serial) {
         /* try to fall back to value set with legacy -drive serial=... */
         dinfo = drive_get_by_blockdev(s->bs);
-        s->serial = qemu_strdup(*dinfo->serial ? dinfo->serial : "0");
+        if (*dinfo->serial) {
+            s->serial = qemu_strdup(dinfo->serial);
+        }
     }
 
     if (!s->version) {
commit 653c1c3fb63ca56b9ea33bfd77065915bc02184f
Author: Hannes Reinecke <hare at suse.de>
Date:   Mon Jul 11 15:02:25 2011 +0200

    scsi-disk: Fixup debugging statement
    
    A debugging statement wasn't converted to the new interface.
    
    Signed-off-by: Hannes Reinecke <hare at suse.de>
    Acked-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 c2a99fe..5804662 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1007,7 +1007,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
 
     command = buf[0];
     outbuf = (uint8_t *)r->iov.iov_base;
-    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
+    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", req->lun, req->tag, buf[0]);
 
     if (scsi_req_parse(&r->req, buf) != 0) {
         BADF("Unsupported command length, command %x\n", command);
commit c5bf71a9a3b10c0cce877b7b3add4484322d3e2c
Author: Hannes Reinecke <hare at suse.de>
Date:   Mon Jul 11 15:02:24 2011 +0200

    scsi: Add 'hba_private' to SCSIRequest
    
    'tag' is just an abstraction to identify the command
    from the driver. So we should make that explicit by
    replacing 'tag' with a driver-defined pointer 'hba_private'.
    This saves the lookup for driver handling several commands
    in parallel.
    'tag' is still being kept for tracing purposes.
    
    Signed-off-by: Hannes Reinecke <hare at suse.de>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/esp.c b/hw/esp.c
index aa50800..9ddd637 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -244,7 +244,7 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
 
     DPRINTF("do_busid_cmd: busid 0x%x\n", busid);
     lun = busid & 7;
-    s->current_req = scsi_req_new(s->current_dev, 0, lun);
+    s->current_req = scsi_req_new(s->current_dev, 0, lun, NULL);
     datalen = scsi_req_enqueue(s->current_req, buf);
     s->ti_size = datalen;
     if (datalen != 0) {
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 940b43a..69eec1d 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -661,7 +661,7 @@ static lsi_request *lsi_find_by_tag(LSIState *s, uint32_t tag)
 static void lsi_request_cancelled(SCSIRequest *req)
 {
     LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
-    lsi_request *p;
+    lsi_request *p = req->hba_private;
 
     if (s->current && req == s->current->req) {
         scsi_req_unref(req);
@@ -670,7 +670,6 @@ static void lsi_request_cancelled(SCSIRequest *req)
         return;
     }
 
-    p = lsi_find_by_tag(s, req->tag);
     if (p) {
         QTAILQ_REMOVE(&s->queue, p, next);
         scsi_req_unref(req);
@@ -680,18 +679,12 @@ static void lsi_request_cancelled(SCSIRequest *req)
 
 /* Record that data is available for a queued command.  Returns zero if
    the device was reselected, nonzero if the IO is deferred.  */
-static int lsi_queue_tag(LSIState *s, uint32_t tag, uint32_t len)
+static int lsi_queue_req(LSIState *s, SCSIRequest *req, uint32_t len)
 {
-    lsi_request *p;
-
-    p = lsi_find_by_tag(s, tag);
-    if (!p) {
-        BADF("IO with unknown tag %d\n", tag);
-        return 1;
-    }
+    lsi_request *p = req->hba_private;
 
     if (p->pending) {
-        BADF("Multiple IO pending for tag %d\n", tag);
+        BADF("Multiple IO pending for request %p\n", p);
     }
     p->pending = len;
     /* Reselect if waiting for it, or if reselection triggers an IRQ
@@ -743,9 +736,9 @@ static void lsi_transfer_data(SCSIRequest *req, uint32_t len)
     LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
     int out;
 
-    if (s->waiting == 1 || !s->current || req->tag != s->current->tag ||
+    if (s->waiting == 1 || !s->current || req->hba_private != s->current ||
         (lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON))) {
-        if (lsi_queue_tag(s, req->tag, len)) {
+        if (lsi_queue_req(s, req, len)) {
             return;
         }
     }
@@ -789,7 +782,8 @@ static void lsi_do_command(LSIState *s)
     assert(s->current == NULL);
     s->current = qemu_mallocz(sizeof(lsi_request));
     s->current->tag = s->select_tag;
-    s->current->req = scsi_req_new(dev, s->current->tag, s->current_lun);
+    s->current->req = scsi_req_new(dev, s->current->tag, s->current_lun,
+                                   s->current);
 
     n = scsi_req_enqueue(s->current->req, buf);
     if (n) {
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index ad6a730..8b1a412 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -131,7 +131,8 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
     return res;
 }
 
-SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun)
+SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag,
+                            uint32_t lun, void *hba_private)
 {
     SCSIRequest *req;
 
@@ -141,14 +142,16 @@ SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t l
     req->dev = d;
     req->tag = tag;
     req->lun = lun;
+    req->hba_private = hba_private;
     req->status = -1;
     trace_scsi_req_alloc(req->dev->id, req->lun, req->tag);
     return req;
 }
 
-SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun)
+SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
+                          void *hba_private)
 {
-    return d->info->alloc_req(d, tag, lun);
+    return d->info->alloc_req(d, tag, lun, hba_private);
 }
 
 uint8_t *scsi_req_get_buf(SCSIRequest *req)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index a8c7372..c2a99fe 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -81,13 +81,13 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type);
 static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf);
 
 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag,
-        uint32_t lun)
+                                     uint32_t lun, void *hba_private)
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
     SCSIRequest *req;
     SCSIDiskReq *r;
 
-    req = scsi_req_alloc(sizeof(SCSIDiskReq), &s->qdev, tag, lun);
+    req = scsi_req_alloc(sizeof(SCSIDiskReq), &s->qdev, tag, lun, hba_private);
     r = DO_UPCAST(SCSIDiskReq, req, req);
     r->iov.iov_base = qemu_blockalign(s->bs, SCSI_DMA_BUF_SIZE);
     return req;
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 8e59c7e..90345a7 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -96,11 +96,12 @@ static int scsi_get_sense(SCSIRequest *req, uint8_t *outbuf, int len)
     return size;
 }
 
-static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
+static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
+                                     void *hba_private)
 {
     SCSIRequest *req;
 
-    req = scsi_req_alloc(sizeof(SCSIGenericReq), d, tag, lun);
+    req = scsi_req_alloc(sizeof(SCSIGenericReq), d, tag, lun, hba_private);
     return req;
 }
 
diff --git a/hw/scsi.h b/hw/scsi.h
index c1dca35..6b15bbc 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -43,6 +43,7 @@ struct SCSIRequest {
     } cmd;
     BlockDriverAIOCB  *aiocb;
     bool enqueued;
+    void *hba_private;
     QTAILQ_ENTRY(SCSIRequest) next;
 };
 
@@ -67,7 +68,8 @@ struct SCSIDeviceInfo {
     DeviceInfo qdev;
     scsi_qdev_initfn init;
     void (*destroy)(SCSIDevice *s);
-    SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun);
+    SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
+                              void *hba_private);
     void (*free_req)(SCSIRequest *req);
     int32_t (*send_command)(SCSIRequest *req, uint8_t *buf);
     void (*read_data)(SCSIRequest *req);
@@ -138,8 +140,10 @@ extern const struct SCSISense sense_code_LUN_FAILURE;
 int scsi_build_sense(SCSISense sense, uint8_t *buf, int len, int fixed);
 int scsi_sense_valid(SCSISense sense);
 
-SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun);
-SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun);
+SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag,
+                            uint32_t lun, void *hba_private);
+SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
+                          void *hba_private);
 int32_t scsi_req_enqueue(SCSIRequest *req, uint8_t *buf);
 void scsi_req_free(SCSIRequest *req);
 SCSIRequest *scsi_req_ref(SCSIRequest *req);
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index 1c901ef..646b1e3 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -121,7 +121,7 @@ static struct vscsi_req *vscsi_get_req(VSCSIState *s)
     return NULL;
 }
 
-static void vscsi_put_req(VSCSIState *s, vscsi_req *req)
+static void vscsi_put_req(vscsi_req *req)
 {
     if (req->sreq != NULL) {
         scsi_req_unref(req->sreq);
@@ -130,15 +130,6 @@ static void vscsi_put_req(VSCSIState *s, vscsi_req *req)
     req->active = 0;
 }
 
-static vscsi_req *vscsi_find_req(VSCSIState *s, SCSIRequest *req)
-{
-    uint32_t tag = req->tag;
-    if (tag >= VSCSI_REQ_LIMIT || !s->reqs[tag].active) {
-        return NULL;
-    }
-    return &s->reqs[tag];
-}
-
 static void vscsi_decode_id_lun(uint64_t srp_lun, int *id, int *lun)
 {
     /* XXX Figure that one out properly ! This is crackpot */
@@ -454,7 +445,7 @@ static void vscsi_send_request_sense(VSCSIState *s, vscsi_req *req)
     if (n) {
         req->senselen = n;
         vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0);
-        vscsi_put_req(s, req);
+        vscsi_put_req(req);
         return;
     }
 
@@ -483,7 +474,7 @@ static void vscsi_send_request_sense(VSCSIState *s, vscsi_req *req)
 static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len)
 {
     VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
-    vscsi_req *req = vscsi_find_req(s, sreq);
+    vscsi_req *req = sreq->hba_private;
     uint8_t *buf;
     int rc = 0;
 
@@ -531,7 +522,7 @@ static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len)
 static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status)
 {
     VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
-    vscsi_req *req = vscsi_find_req(s, sreq);
+    vscsi_req *req = sreq->hba_private;
     int32_t res_in = 0, res_out = 0;
 
     dprintf("VSCSI: SCSI cmd complete, r=0x%x tag=0x%x status=0x%x, req=%p\n",
@@ -563,15 +554,14 @@ static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status)
         }
     }
     vscsi_send_rsp(s, req, 0, res_in, res_out);
-    vscsi_put_req(s, req);
+    vscsi_put_req(req);
 }
 
 static void vscsi_request_cancelled(SCSIRequest *sreq)
 {
-    VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
-    vscsi_req *req = vscsi_find_req(s, sreq);
+    vscsi_req *req = sreq->hba_private;
 
-    vscsi_put_req(s, req);
+    vscsi_put_req(req);
 }
 
 static void vscsi_process_login(VSCSIState *s, vscsi_req *req)
@@ -659,7 +649,7 @@ static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
     }
 
     req->lun = lun;
-    req->sreq = scsi_req_new(sdev, req->qtag, lun);
+    req->sreq = scsi_req_new(sdev, req->qtag, lun, req);
     n = scsi_req_enqueue(req->sreq, srp->cmd.cdb);
 
     dprintf("VSCSI: Queued command tag 0x%x CMD 0x%x ID %d LUN %d ret: %d\n",
@@ -858,7 +848,7 @@ static void vscsi_got_payload(VSCSIState *s, vscsi_crq *crq)
     }
 
     if (done) {
-        vscsi_put_req(s, req);
+        vscsi_put_req(req);
     }
 }
 
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 86582cc..bfea096 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -216,10 +216,6 @@ static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
     MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
     USBPacket *p = s->packet;
 
-    if (req->tag != s->tag) {
-        fprintf(stderr, "usb-msd: Unexpected SCSI Tag 0x%x\n", req->tag);
-    }
-
     assert((s->mode == USB_MSDM_DATAOUT) == (req->cmd.mode == SCSI_XFER_TO_DEV));
     s->scsi_len = len;
     s->scsi_buf = scsi_req_get_buf(req);
@@ -241,9 +237,6 @@ 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;
 
-    if (req->tag != s->tag) {
-        fprintf(stderr, "usb-msd: Unexpected SCSI Tag 0x%x\n", req->tag);
-    }
     DPRINTF("Command complete %d\n", status);
     s->residue = s->data_len;
     s->result = status != 0;
@@ -387,7 +380,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
                     s->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);
+            s->req = scsi_req_new(s->scsi_dev, s->tag, 0, NULL);
             scsi_req_enqueue(s->req, cbw.cmd);
             /* ??? Should check that USB and SCSI data transfer
                directions match.  */
commit 348e7b8dcd1460df4d681105f63dd90bba70496d
Author: Hannes Reinecke <hare at suse.de>
Date:   Mon Jul 11 15:02:23 2011 +0200

    iov: Update parameter usage in iov_(to|from)_buf()
    
    iov_to_buf() has an 'offset' parameter, iov_from_buf() hasn't.
    This patch adds the missing parameter to iov_from_buf().
    It also renames the 'offset' parameter to 'iov_off' to
    emphasize it's the offset into the iovec and not the buffer.
    
    Signed-off-by: Hannes Reinecke <hare at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 6997e02..a32cc01 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -657,7 +657,7 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
 
         /* copy in packet.  ugh */
         len = iov_from_buf(sg, elem.in_num,
-                           buf + offset, size - offset);
+                           buf + offset, 0, size - offset);
         total += len;
         offset += len;
         /* If buffers can't be merged, at this point we
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 7f6db7b..53c58d0 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -103,7 +103,7 @@ static size_t write_to_port(VirtIOSerialPort *port,
         }
 
         len = iov_from_buf(elem.in_sg, elem.in_num,
-                           buf + offset, size - offset);
+                           buf + offset, 0, size - offset);
         offset += len;
 
         virtqueue_push(vq, &elem, len);
diff --git a/iov.c b/iov.c
index 588cd04..1e02791 100644
--- a/iov.c
+++ b/iov.c
@@ -14,56 +14,61 @@
 
 #include "iov.h"
 
-size_t iov_from_buf(struct iovec *iov, unsigned int iovcnt,
-                    const void *buf, size_t size)
+size_t iov_from_buf(struct iovec *iov, unsigned int iov_cnt,
+                    const void *buf, size_t iov_off, size_t size)
 {
-    size_t offset;
+    size_t iovec_off, buf_off;
     unsigned int i;
 
-    offset = 0;
-    for (i = 0; offset < size && i < iovcnt; i++) {
-        size_t len;
+    iovec_off = 0;
+    buf_off = 0;
+    for (i = 0; i < iov_cnt && size; i++) {
+        if (iov_off < (iovec_off + iov[i].iov_len)) {
+            size_t len = MIN((iovec_off + iov[i].iov_len) - iov_off, size);
 
-        len = MIN(iov[i].iov_len, size - offset);
+            memcpy(iov[i].iov_base + (iov_off - iovec_off), buf + buf_off, len);
 
-        memcpy(iov[i].iov_base, buf + offset, len);
-        offset += len;
+            buf_off += len;
+            iov_off += len;
+            size -= len;
+        }
+        iovec_off += iov[i].iov_len;
     }
-    return offset;
+    return buf_off;
 }
 
-size_t iov_to_buf(const struct iovec *iov, const unsigned int iovcnt,
-                  void *buf, size_t offset, size_t size)
+size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt,
+                  void *buf, size_t iov_off, size_t size)
 {
     uint8_t *ptr;
-    size_t iov_off, buf_off;
+    size_t iovec_off, buf_off;
     unsigned int i;
 
     ptr = buf;
-    iov_off = 0;
+    iovec_off = 0;
     buf_off = 0;
-    for (i = 0; i < iovcnt && size; i++) {
-        if (offset < (iov_off + iov[i].iov_len)) {
-            size_t len = MIN((iov_off + iov[i].iov_len) - offset , size);
+    for (i = 0; i < iov_cnt && size; i++) {
+        if (iov_off < (iovec_off + iov[i].iov_len)) {
+            size_t len = MIN((iovec_off + iov[i].iov_len) - iov_off , size);
 
-            memcpy(ptr + buf_off, iov[i].iov_base + (offset - iov_off), len);
+            memcpy(ptr + buf_off, iov[i].iov_base + (iov_off - iovec_off), len);
 
             buf_off += len;
-            offset += len;
+            iov_off += len;
             size -= len;
         }
-        iov_off += iov[i].iov_len;
+        iovec_off += iov[i].iov_len;
     }
     return buf_off;
 }
 
-size_t iov_size(const struct iovec *iov, const unsigned int iovcnt)
+size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt)
 {
     size_t len;
     unsigned int i;
 
     len = 0;
-    for (i = 0; i < iovcnt; i++) {
+    for (i = 0; i < iov_cnt; i++) {
         len += iov[i].iov_len;
     }
     return len;
diff --git a/iov.h b/iov.h
index 60a8547..110f67a 100644
--- a/iov.h
+++ b/iov.h
@@ -12,8 +12,8 @@
 
 #include "qemu-common.h"
 
-size_t iov_from_buf(struct iovec *iov, unsigned int iovcnt,
-                    const void *buf, size_t size);
-size_t iov_to_buf(const struct iovec *iov, const unsigned int iovcnt,
-                  void *buf, size_t offset, size_t size);
-size_t iov_size(const struct iovec *iov, const unsigned int iovcnt);
+size_t iov_from_buf(struct iovec *iov, unsigned int iov_cnt,
+                    const void *buf, size_t iov_off, size_t size);
+size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt,
+                  void *buf, size_t iov_off, size_t size);
+size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt);
commit 5afc8b3de9a8a472a45d2b980632a15cb7f1e1c3
Author: Devin Nakamura <devin122 at gmail.com>
Date:   Mon Jul 11 11:20:25 2011 -0400

    qemu-io: Fix if scoping bug
    
    Fix a bug caused by lack of braces in if statement
    
    Lack of braces means that if(count & 0x1ff) is never reached
    
    Signed-off-by: Devin Nakamura <devin122 at gmail.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-io.c b/qemu-io.c
index e3c825f..a553d0c 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -449,7 +449,7 @@ static int read_f(int argc, char **argv)
         return 0;
     }
 
-    if (!pflag)
+    if (!pflag) {
         if (offset & 0x1ff) {
             printf("offset %" PRId64 " is not sector aligned\n",
                    offset);
@@ -460,6 +460,7 @@ static int read_f(int argc, char **argv)
                    count);
             return 0;
         }
+    }
 
     buf = qemu_io_alloc(count, 0xab);
 
commit 43642b3803bef28018ca7736be83f2f886d8e42c
Author: Devin Nakamura <devin122 at gmail.com>
Date:   Mon Jul 11 11:22:16 2011 -0400

    qemu-io: Fix formatting
    
    Replaced tabs with spaces, 8 space indentations with 4 space
    indentation, and other fixes to better adhere to CODING_STYLE
    
    Signed-off-by: Devin Nakamura <devin122 at gmail.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-io.c b/qemu-io.c
index dd4ebf5..e3c825f 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -20,7 +20,7 @@
 
 #define VERSION	"0.0.1"
 
-#define CMD_NOFILE_OK	0x01
+#define CMD_NOFILE_OK   0x01
 
 char *progname;
 static BlockDriverState *bs;
@@ -35,16 +35,16 @@ static int misalign;
  */
 static int parse_pattern(const char *arg)
 {
-	char *endptr = NULL;
-	long pattern;
+    char *endptr = NULL;
+    long pattern;
 
-	pattern = strtol(arg, &endptr, 0);
-	if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
-		printf("%s is not a valid pattern byte\n", arg);
-		return -1;
-	}
+    pattern = strtol(arg, &endptr, 0);
+    if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
+        printf("%s is not a valid pattern byte\n", arg);
+        return -1;
+    }
 
-	return pattern;
+    return pattern;
 }
 
 /*
@@ -54,70 +54,73 @@ static int parse_pattern(const char *arg)
  * that is specified on the command line.
  */
 
-#define MISALIGN_OFFSET		16
+#define MISALIGN_OFFSET     16
 static void *qemu_io_alloc(size_t len, int pattern)
 {
-	void *buf;
-
-	if (misalign)
-		len += MISALIGN_OFFSET;
-	buf = qemu_blockalign(bs, len);
-	memset(buf, pattern, len);
-	if (misalign)
-		buf += MISALIGN_OFFSET;
-	return buf;
+    void *buf;
+
+    if (misalign) {
+        len += MISALIGN_OFFSET;
+    }
+    buf = qemu_blockalign(bs, len);
+    memset(buf, pattern, len);
+    if (misalign) {
+        buf += MISALIGN_OFFSET;
+    }
+    return buf;
 }
 
 static void qemu_io_free(void *p)
 {
-	if (misalign)
-		p -= MISALIGN_OFFSET;
-	qemu_vfree(p);
+    if (misalign) {
+        p -= MISALIGN_OFFSET;
+    }
+    qemu_vfree(p);
 }
 
-static void
-dump_buffer(const void *buffer, int64_t offset, int len)
+static void dump_buffer(const void *buffer, int64_t offset, int len)
 {
-	int i, j;
-	const uint8_t *p;
-
-	for (i = 0, p = buffer; i < len; i += 16) {
-		const uint8_t *s = p;
-
-                printf("%08" PRIx64 ":  ", offset + i);
-		for (j = 0; j < 16 && i + j < len; j++, p++)
-			printf("%02x ", *p);
-		printf(" ");
-		for (j = 0; j < 16 && i + j < len; j++, s++) {
-			if (isalnum(*s))
-				printf("%c", *s);
-			else
-				printf(".");
-		}
-		printf("\n");
-	}
+    int i, j;
+    const uint8_t *p;
+
+    for (i = 0, p = buffer; i < len; i += 16) {
+        const uint8_t *s = p;
+
+        printf("%08" PRIx64 ":  ", offset + i);
+        for (j = 0; j < 16 && i + j < len; j++, p++) {
+            printf("%02x ", *p);
+        }
+        printf(" ");
+        for (j = 0; j < 16 && i + j < len; j++, s++) {
+            if (isalnum(*s)) {
+                printf("%c", *s);
+            } else {
+                printf(".");
+            }
+        }
+        printf("\n");
+    }
 }
 
-static void
-print_report(const char *op, struct timeval *t, int64_t offset,
-		int count, int total, int cnt, int Cflag)
+static void print_report(const char *op, struct timeval *t, int64_t offset,
+                         int count, int total, int cnt, int Cflag)
 {
-	char s1[64], s2[64], ts[64];
-
-	timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
-	if (!Cflag) {
-		cvtstr((double)total, s1, sizeof(s1));
-		cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
-                printf("%s %d/%d bytes at offset %" PRId64 "\n",
-                       op, total, count, offset);
-		printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
-			s1, cnt, ts, s2, tdiv((double)cnt, *t));
-	} else {/* bytes,ops,time,bytes/sec,ops/sec */
-		printf("%d,%d,%s,%.3f,%.3f\n",
-			total, cnt, ts,
-			tdiv((double)total, *t),
-			tdiv((double)cnt, *t));
-	}
+    char s1[64], s2[64], ts[64];
+
+    timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
+    if (!Cflag) {
+        cvtstr((double)total, s1, sizeof(s1));
+        cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
+        printf("%s %d/%d bytes at offset %" PRId64 "\n",
+               op, total, count, offset);
+        printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
+               s1, cnt, ts, s2, tdiv((double)cnt, *t));
+    } else {/* bytes,ops,time,bytes/sec,ops/sec */
+        printf("%d,%d,%s,%.3f,%.3f\n",
+            total, cnt, ts,
+            tdiv((double)total, *t),
+            tdiv((double)cnt, *t));
+    }
 }
 
 /*
@@ -127,192 +130,200 @@ print_report(const char *op, struct timeval *t, int64_t offset,
 static void *
 create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern)
 {
-	size_t *sizes = calloc(nr_iov, sizeof(size_t));
-	size_t count = 0;
-	void *buf = NULL;
-	void *p;
-	int i;
-
-	for (i = 0; i < nr_iov; i++) {
-		char *arg = argv[i];
-                int64_t len;
-
-		len = cvtnum(arg);
-		if (len < 0) {
-			printf("non-numeric length argument -- %s\n", arg);
-			goto fail;
-		}
-
-		/* should be SIZE_T_MAX, but that doesn't exist */
-		if (len > INT_MAX) {
-			printf("too large length argument -- %s\n", arg);
-			goto fail;
-		}
-
-		if (len & 0x1ff) {
-                        printf("length argument %" PRId64
-                               " is not sector aligned\n", len);
-			goto fail;
-		}
-
-		sizes[i] = len;
-		count += len;
-	}
-
-	qemu_iovec_init(qiov, nr_iov);
-
-	buf = p = qemu_io_alloc(count, pattern);
-
-	for (i = 0; i < nr_iov; i++) {
-		qemu_iovec_add(qiov, p, sizes[i]);
-		p += sizes[i];
-	}
+    size_t *sizes = calloc(nr_iov, sizeof(size_t));
+    size_t count = 0;
+    void *buf = NULL;
+    void *p;
+    int i;
+
+    for (i = 0; i < nr_iov; i++) {
+        char *arg = argv[i];
+        int64_t len;
+
+        len = cvtnum(arg);
+        if (len < 0) {
+            printf("non-numeric length argument -- %s\n", arg);
+            goto fail;
+        }
+
+        /* should be SIZE_T_MAX, but that doesn't exist */
+        if (len > INT_MAX) {
+            printf("too large length argument -- %s\n", arg);
+            goto fail;
+        }
+
+        if (len & 0x1ff) {
+            printf("length argument %" PRId64
+                   " is not sector aligned\n", len);
+            goto fail;
+        }
+
+        sizes[i] = len;
+        count += len;
+    }
+
+    qemu_iovec_init(qiov, nr_iov);
+
+    buf = p = qemu_io_alloc(count, pattern);
+
+    for (i = 0; i < nr_iov; i++) {
+        qemu_iovec_add(qiov, p, sizes[i]);
+        p += sizes[i];
+    }
 
 fail:
-	free(sizes);
-	return buf;
+    free(sizes);
+    return buf;
 }
 
 static int do_read(char *buf, int64_t offset, int count, int *total)
 {
-	int ret;
+    int ret;
 
-	ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
-	if (ret < 0)
-		return ret;
-	*total = count;
-	return 1;
+    ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
+    if (ret < 0) {
+        return ret;
+    }
+    *total = count;
+    return 1;
 }
 
 static int do_write(char *buf, int64_t offset, int count, int *total)
 {
-	int ret;
+    int ret;
 
-	ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
-	if (ret < 0)
-		return ret;
-	*total = count;
-	return 1;
+    ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
+    if (ret < 0) {
+        return ret;
+    }
+    *total = count;
+    return 1;
 }
 
 static int do_pread(char *buf, int64_t offset, int count, int *total)
 {
-	*total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
-	if (*total < 0)
-		return *total;
-	return 1;
+    *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
+    if (*total < 0) {
+        return *total;
+    }
+    return 1;
 }
 
 static int do_pwrite(char *buf, int64_t offset, int count, int *total)
 {
-	*total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
-	if (*total < 0)
-		return *total;
-	return 1;
+    *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
+    if (*total < 0) {
+        return *total;
+    }
+    return 1;
 }
 
 static int do_load_vmstate(char *buf, int64_t offset, int count, int *total)
 {
-	*total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
-	if (*total < 0)
-		return *total;
-	return 1;
+    *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
+    if (*total < 0) {
+        return *total;
+    }
+    return 1;
 }
 
 static int do_save_vmstate(char *buf, int64_t offset, int count, int *total)
 {
-	*total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
-	if (*total < 0)
-		return *total;
-	return 1;
+    *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
+    if (*total < 0) {
+        return *total;
+    }
+    return 1;
 }
 
 #define NOT_DONE 0x7fffffff
 static void aio_rw_done(void *opaque, int ret)
 {
-	*(int *)opaque = ret;
+    *(int *)opaque = ret;
 }
 
 static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
 {
-	BlockDriverAIOCB *acb;
-	int async_ret = NOT_DONE;
+    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;
-
-	while (async_ret == NOT_DONE)
-		qemu_aio_wait();
+    acb = bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
+                         aio_rw_done, &async_ret);
+    if (!acb) {
+        return -EIO;
+    }
+    while (async_ret == NOT_DONE) {
+        qemu_aio_wait();
+    }
 
-	*total = qiov->size;
-	return async_ret < 0 ? async_ret : 1;
+    *total = qiov->size;
+    return async_ret < 0 ? async_ret : 1;
 }
 
 static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
 {
-	BlockDriverAIOCB *acb;
-	int async_ret = NOT_DONE;
+    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;
+    acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
+                          aio_rw_done, &async_ret);
+    if (!acb) {
+        return -EIO;
+    }
 
-	while (async_ret == NOT_DONE)
-		qemu_aio_wait();
+    while (async_ret == NOT_DONE) {
+        qemu_aio_wait();
+    }
 
-	*total = qiov->size;
-	return async_ret < 0 ? async_ret : 1;
+    *total = qiov->size;
+    return async_ret < 0 ? async_ret : 1;
 }
 
 struct multiwrite_async_ret {
-	int num_done;
-	int error;
+    int num_done;
+    int error;
 };
 
 static void multiwrite_cb(void *opaque, int ret)
 {
-	struct multiwrite_async_ret *async_ret = opaque;
+    struct multiwrite_async_ret *async_ret = opaque;
 
-	async_ret->num_done++;
-	if (ret < 0) {
-		async_ret->error = ret;
-	}
+    async_ret->num_done++;
+    if (ret < 0) {
+        async_ret->error = ret;
+    }
 }
 
 static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total)
 {
-	int i, ret;
-	struct multiwrite_async_ret async_ret = {
-		.num_done = 0,
-		.error = 0,
-	};
-
-	*total = 0;
-	for (i = 0; i < num_reqs; i++) {
-		reqs[i].cb = multiwrite_cb;
-		reqs[i].opaque = &async_ret;
-		*total += reqs[i].qiov->size;
-	}
-
-	ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
-	if (ret < 0) {
-		return ret;
-	}
-
-	while (async_ret.num_done < num_reqs) {
-		qemu_aio_wait();
-	}
-
-	return async_ret.error < 0 ? async_ret.error : 1;
+    int i, ret;
+    struct multiwrite_async_ret async_ret = {
+        .num_done = 0,
+        .error = 0,
+    };
+
+    *total = 0;
+    for (i = 0; i < num_reqs; i++) {
+        reqs[i].cb = multiwrite_cb;
+        reqs[i].opaque = &async_ret;
+        *total += reqs[i].qiov->size;
+    }
+
+    ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
+    if (ret < 0) {
+        return ret;
+    }
+
+    while (async_ret.num_done < num_reqs) {
+        qemu_aio_wait();
+    }
+
+    return async_ret.error < 0 ? async_ret.error : 1;
 }
 
-static void
-read_help(void)
+static void read_help(void)
 {
-	printf(
+    printf(
 "\n"
 " reads a range of bytes from the given offset\n"
 "\n"
@@ -335,94 +346,95 @@ read_help(void)
 static int read_f(int argc, char **argv);
 
 static const cmdinfo_t read_cmd = {
-	.name		= "read",
-	.altname	= "r",
-	.cfunc		= read_f,
-	.argmin		= 2,
-	.argmax		= -1,
-	.args		= "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
-	.oneline	= "reads a number of bytes at a specified offset",
-	.help		= read_help,
+    .name       = "read",
+    .altname    = "r",
+    .cfunc      = read_f,
+    .argmin     = 2,
+    .argmax     = -1,
+    .args       = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
+    .oneline    = "reads a number of bytes at a specified offset",
+    .help       = read_help,
 };
 
-static int
-read_f(int argc, char **argv)
+static int read_f(int argc, char **argv)
 {
-	struct timeval t1, t2;
-	int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
-	int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
-	int c, cnt;
-	char *buf;
-	int64_t offset;
-	int count;
-        /* Some compilers get confused and warn if this is not initialized.  */
-        int total = 0;
-	int pattern = 0, pattern_offset = 0, pattern_count = 0;
-
-	while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
-		switch (c) {
-		case 'b':
-			bflag = 1;
-			break;
-		case 'C':
-			Cflag = 1;
-			break;
-		case 'l':
-			lflag = 1;
-			pattern_count = cvtnum(optarg);
-			if (pattern_count < 0) {
-				printf("non-numeric length argument -- %s\n", optarg);
-				return 0;
-			}
-			break;
-		case 'p':
-			pflag = 1;
-			break;
-		case 'P':
-			Pflag = 1;
-			pattern = parse_pattern(optarg);
-			if (pattern < 0)
-				return 0;
-			break;
-		case 'q':
-			qflag = 1;
-			break;
-		case 's':
-			sflag = 1;
-			pattern_offset = cvtnum(optarg);
-			if (pattern_offset < 0) {
-				printf("non-numeric length argument -- %s\n", optarg);
-				return 0;
-			}
-			break;
-		case 'v':
-			vflag = 1;
-			break;
-		default:
-			return command_usage(&read_cmd);
-		}
-	}
-
-	if (optind != argc - 2)
-		return command_usage(&read_cmd);
-
-	if (bflag && pflag) {
-		printf("-b and -p cannot be specified at the same time\n");
-		return 0;
-	}
-
-	offset = cvtnum(argv[optind]);
-	if (offset < 0) {
-		printf("non-numeric length argument -- %s\n", argv[optind]);
-		return 0;
-	}
-
-	optind++;
-	count = cvtnum(argv[optind]);
-	if (count < 0) {
-		printf("non-numeric length argument -- %s\n", argv[optind]);
-		return 0;
-	}
+    struct timeval t1, t2;
+    int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
+    int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
+    int c, cnt;
+    char *buf;
+    int64_t offset;
+    int count;
+    /* Some compilers get confused and warn if this is not initialized.  */
+    int total = 0;
+    int pattern = 0, pattern_offset = 0, pattern_count = 0;
+
+    while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
+        switch (c) {
+        case 'b':
+            bflag = 1;
+            break;
+        case 'C':
+            Cflag = 1;
+            break;
+        case 'l':
+            lflag = 1;
+            pattern_count = cvtnum(optarg);
+            if (pattern_count < 0) {
+                printf("non-numeric length argument -- %s\n", optarg);
+                return 0;
+            }
+            break;
+        case 'p':
+            pflag = 1;
+            break;
+        case 'P':
+            Pflag = 1;
+            pattern = parse_pattern(optarg);
+            if (pattern < 0) {
+                return 0;
+            }
+            break;
+        case 'q':
+            qflag = 1;
+            break;
+        case 's':
+            sflag = 1;
+            pattern_offset = cvtnum(optarg);
+            if (pattern_offset < 0) {
+                printf("non-numeric length argument -- %s\n", optarg);
+                return 0;
+            }
+            break;
+        case 'v':
+            vflag = 1;
+            break;
+        default:
+            return command_usage(&read_cmd);
+        }
+    }
+
+    if (optind != argc - 2) {
+        return command_usage(&read_cmd);
+    }
+
+    if (bflag && pflag) {
+        printf("-b and -p cannot be specified at the same time\n");
+        return 0;
+    }
+
+    offset = cvtnum(argv[optind]);
+    if (offset < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        return 0;
+    }
+
+    optind++;
+    count = cvtnum(argv[optind]);
+    if (count < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        return 0;
+    }
 
     if (!Pflag && (lflag || sflag)) {
         return command_usage(&read_cmd);
@@ -437,66 +449,67 @@ read_f(int argc, char **argv)
         return 0;
     }
 
-	if (!pflag)
-		if (offset & 0x1ff) {
-                        printf("offset %" PRId64 " is not sector aligned\n",
-                               offset);
-			return 0;
-
-		if (count & 0x1ff) {
-			printf("count %d is not sector aligned\n",
-				count);
-			return 0;
-		}
-	}
-
-	buf = qemu_io_alloc(count, 0xab);
-
-	gettimeofday(&t1, NULL);
-	if (pflag)
-		cnt = do_pread(buf, offset, count, &total);
-	else if (bflag)
-		cnt = do_load_vmstate(buf, offset, count, &total);
-	else
-		cnt = do_read(buf, offset, count, &total);
-	gettimeofday(&t2, NULL);
-
-	if (cnt < 0) {
-		printf("read failed: %s\n", strerror(-cnt));
-		goto out;
-	}
-
-	if (Pflag) {
-		void* cmp_buf = malloc(pattern_count);
-		memset(cmp_buf, pattern, pattern_count);
-		if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
-			printf("Pattern verification failed at offset %"
-                               PRId64 ", %d bytes\n",
-                               offset + pattern_offset, pattern_count);
-		}
-		free(cmp_buf);
-	}
-
-	if (qflag)
-		goto out;
-
-        if (vflag)
-		dump_buffer(buf, offset, count);
-
-	/* Finally, report back -- -C gives a parsable format */
-	t2 = tsub(t2, t1);
-	print_report("read", &t2, offset, count, total, cnt, Cflag);
+    if (!pflag)
+        if (offset & 0x1ff) {
+            printf("offset %" PRId64 " is not sector aligned\n",
+                   offset);
+            return 0;
+        }
+        if (count & 0x1ff) {
+            printf("count %d is not sector aligned\n",
+                   count);
+            return 0;
+        }
+
+    buf = qemu_io_alloc(count, 0xab);
+
+    gettimeofday(&t1, NULL);
+    if (pflag) {
+        cnt = do_pread(buf, offset, count, &total);
+    } else if (bflag) {
+        cnt = do_load_vmstate(buf, offset, count, &total);
+    } else {
+        cnt = do_read(buf, offset, count, &total);
+    }
+    gettimeofday(&t2, NULL);
+
+    if (cnt < 0) {
+        printf("read failed: %s\n", strerror(-cnt));
+        goto out;
+    }
+
+    if (Pflag) {
+        void *cmp_buf = malloc(pattern_count);
+        memset(cmp_buf, pattern, pattern_count);
+        if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
+            printf("Pattern verification failed at offset %"
+                   PRId64 ", %d bytes\n",
+                   offset + pattern_offset, pattern_count);
+        }
+        free(cmp_buf);
+    }
+
+    if (qflag) {
+        goto out;
+    }
+
+    if (vflag) {
+        dump_buffer(buf, offset, count);
+    }
+
+    /* Finally, report back -- -C gives a parsable format */
+    t2 = tsub(t2, t1);
+    print_report("read", &t2, offset, count, total, cnt, Cflag);
 
 out:
-	qemu_io_free(buf);
+    qemu_io_free(buf);
 
-	return 0;
+    return 0;
 }
 
-static void
-readv_help(void)
+static void readv_help(void)
 {
-	printf(
+    printf(
 "\n"
 " reads a range of bytes from the given offset into multiple buffers\n"
 "\n"
@@ -516,111 +529,112 @@ readv_help(void)
 static int readv_f(int argc, char **argv);
 
 static const cmdinfo_t readv_cmd = {
-	.name		= "readv",
-	.cfunc		= readv_f,
-	.argmin		= 2,
-	.argmax		= -1,
-	.args		= "[-Cqv] [-P pattern ] off len [len..]",
-	.oneline	= "reads a number of bytes at a specified offset",
-	.help		= readv_help,
+    .name       = "readv",
+    .cfunc      = readv_f,
+    .argmin     = 2,
+    .argmax     = -1,
+    .args       = "[-Cqv] [-P pattern ] off len [len..]",
+    .oneline    = "reads a number of bytes at a specified offset",
+    .help       = readv_help,
 };
 
-static int
-readv_f(int argc, char **argv)
+static int readv_f(int argc, char **argv)
 {
-	struct timeval t1, t2;
-	int Cflag = 0, qflag = 0, vflag = 0;
-	int c, cnt;
-	char *buf;
-	int64_t offset;
-        /* Some compilers get confused and warn if this is not initialized.  */
-        int total = 0;
-	int nr_iov;
-	QEMUIOVector qiov;
-	int pattern = 0;
-	int Pflag = 0;
-
-	while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
-		switch (c) {
-		case 'C':
-			Cflag = 1;
-			break;
-		case 'P':
-			Pflag = 1;
-			pattern = parse_pattern(optarg);
-			if (pattern < 0)
-				return 0;
-			break;
-		case 'q':
-			qflag = 1;
-			break;
-		case 'v':
-			vflag = 1;
-			break;
-		default:
-			return command_usage(&readv_cmd);
-		}
-	}
-
-	if (optind > argc - 2)
-		return command_usage(&readv_cmd);
-
-
-	offset = cvtnum(argv[optind]);
-	if (offset < 0) {
-		printf("non-numeric length argument -- %s\n", argv[optind]);
-		return 0;
-	}
-	optind++;
-
-	if (offset & 0x1ff) {
-                printf("offset %" PRId64 " is not sector aligned\n",
-                       offset);
-		return 0;
-	}
-
-	nr_iov = argc - optind;
-	buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
-
-	gettimeofday(&t1, NULL);
-	cnt = do_aio_readv(&qiov, offset, &total);
-	gettimeofday(&t2, NULL);
-
-	if (cnt < 0) {
-		printf("readv failed: %s\n", strerror(-cnt));
-		goto out;
-	}
-
-	if (Pflag) {
-		void* cmp_buf = malloc(qiov.size);
-		memset(cmp_buf, pattern, qiov.size);
-		if (memcmp(buf, cmp_buf, qiov.size)) {
-			printf("Pattern verification failed at offset %"
-                               PRId64 ", %zd bytes\n",
-                               offset, qiov.size);
-		}
-		free(cmp_buf);
-	}
-
-	if (qflag)
-		goto out;
-
-        if (vflag)
-		dump_buffer(buf, offset, qiov.size);
-
-	/* Finally, report back -- -C gives a parsable format */
-	t2 = tsub(t2, t1);
-	print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
+    struct timeval t1, t2;
+    int Cflag = 0, qflag = 0, vflag = 0;
+    int c, cnt;
+    char *buf;
+    int64_t offset;
+    /* Some compilers get confused and warn if this is not initialized.  */
+    int total = 0;
+    int nr_iov;
+    QEMUIOVector qiov;
+    int pattern = 0;
+    int Pflag = 0;
+
+    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
+        switch (c) {
+        case 'C':
+            Cflag = 1;
+            break;
+        case 'P':
+            Pflag = 1;
+            pattern = parse_pattern(optarg);
+            if (pattern < 0) {
+                return 0;
+            }
+            break;
+        case 'q':
+            qflag = 1;
+            break;
+        case 'v':
+            vflag = 1;
+            break;
+        default:
+            return command_usage(&readv_cmd);
+        }
+    }
+
+    if (optind > argc - 2) {
+        return command_usage(&readv_cmd);
+    }
+
+
+    offset = cvtnum(argv[optind]);
+    if (offset < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        return 0;
+    }
+    optind++;
+
+    if (offset & 0x1ff) {
+        printf("offset %" PRId64 " is not sector aligned\n",
+               offset);
+        return 0;
+    }
+
+    nr_iov = argc - optind;
+    buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
+
+    gettimeofday(&t1, NULL);
+    cnt = do_aio_readv(&qiov, offset, &total);
+    gettimeofday(&t2, NULL);
+
+    if (cnt < 0) {
+        printf("readv failed: %s\n", strerror(-cnt));
+        goto out;
+    }
+
+    if (Pflag) {
+        void *cmp_buf = malloc(qiov.size);
+        memset(cmp_buf, pattern, qiov.size);
+        if (memcmp(buf, cmp_buf, qiov.size)) {
+            printf("Pattern verification failed at offset %"
+                   PRId64 ", %zd bytes\n", offset, qiov.size);
+        }
+        free(cmp_buf);
+    }
+
+    if (qflag) {
+        goto out;
+    }
+
+    if (vflag) {
+        dump_buffer(buf, offset, qiov.size);
+    }
+
+    /* Finally, report back -- -C gives a parsable format */
+    t2 = tsub(t2, t1);
+    print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
 
 out:
-	qemu_io_free(buf);
-	return 0;
+    qemu_io_free(buf);
+    return 0;
 }
 
-static void
-write_help(void)
+static void write_help(void)
 {
-	printf(
+    printf(
 "\n"
 " writes a range of bytes from the given offset\n"
 "\n"
@@ -640,121 +654,124 @@ write_help(void)
 static int write_f(int argc, char **argv);
 
 static const cmdinfo_t write_cmd = {
-	.name		= "write",
-	.altname	= "w",
-	.cfunc		= write_f,
-	.argmin		= 2,
-	.argmax		= -1,
-	.args		= "[-abCpq] [-P pattern ] off len",
-	.oneline	= "writes a number of bytes at a specified offset",
-	.help		= write_help,
+    .name       = "write",
+    .altname    = "w",
+    .cfunc      = write_f,
+    .argmin     = 2,
+    .argmax     = -1,
+    .args       = "[-abCpq] [-P pattern ] off len",
+    .oneline    = "writes a number of bytes at a specified offset",
+    .help       = write_help,
 };
 
-static int
-write_f(int argc, char **argv)
+static int write_f(int argc, char **argv)
 {
-	struct timeval t1, t2;
-	int Cflag = 0, pflag = 0, qflag = 0, bflag = 0;
-	int c, cnt;
-	char *buf;
-	int64_t offset;
-	int count;
-        /* Some compilers get confused and warn if this is not initialized.  */
-        int total = 0;
-	int pattern = 0xcd;
-
-	while ((c = getopt(argc, argv, "bCpP:q")) != EOF) {
-		switch (c) {
-		case 'b':
-			bflag = 1;
-			break;
-		case 'C':
-			Cflag = 1;
-			break;
-		case 'p':
-			pflag = 1;
-			break;
-		case 'P':
-			pattern = parse_pattern(optarg);
-			if (pattern < 0)
-				return 0;
-			break;
-		case 'q':
-			qflag = 1;
-			break;
-		default:
-			return command_usage(&write_cmd);
-		}
-	}
-
-	if (optind != argc - 2)
-		return command_usage(&write_cmd);
-
-	if (bflag && pflag) {
-		printf("-b and -p cannot be specified at the same time\n");
-		return 0;
-	}
-
-	offset = cvtnum(argv[optind]);
-	if (offset < 0) {
-		printf("non-numeric length argument -- %s\n", argv[optind]);
-		return 0;
-	}
-
-	optind++;
-	count = cvtnum(argv[optind]);
-	if (count < 0) {
-		printf("non-numeric length argument -- %s\n", argv[optind]);
-		return 0;
-	}
-
-	if (!pflag) {
-		if (offset & 0x1ff) {
-                        printf("offset %" PRId64 " is not sector aligned\n",
-                               offset);
-			return 0;
-		}
-
-		if (count & 0x1ff) {
-			printf("count %d is not sector aligned\n",
-				count);
-			return 0;
-		}
-	}
-
-	buf = qemu_io_alloc(count, pattern);
-
-	gettimeofday(&t1, NULL);
-	if (pflag)
-		cnt = do_pwrite(buf, offset, count, &total);
-	else if (bflag)
-		cnt = do_save_vmstate(buf, offset, count, &total);
-	else
-		cnt = do_write(buf, offset, count, &total);
-	gettimeofday(&t2, NULL);
-
-	if (cnt < 0) {
-		printf("write failed: %s\n", strerror(-cnt));
-		goto out;
-	}
-
-	if (qflag)
-		goto out;
-
-	/* Finally, report back -- -C gives a parsable format */
-	t2 = tsub(t2, t1);
-	print_report("wrote", &t2, offset, count, total, cnt, Cflag);
+    struct timeval t1, t2;
+    int Cflag = 0, pflag = 0, qflag = 0, bflag = 0;
+    int c, cnt;
+    char *buf;
+    int64_t offset;
+    int count;
+    /* Some compilers get confused and warn if this is not initialized.  */
+    int total = 0;
+    int pattern = 0xcd;
+
+    while ((c = getopt(argc, argv, "bCpP:q")) != EOF) {
+        switch (c) {
+        case 'b':
+            bflag = 1;
+            break;
+        case 'C':
+            Cflag = 1;
+            break;
+        case 'p':
+            pflag = 1;
+            break;
+        case 'P':
+            pattern = parse_pattern(optarg);
+            if (pattern < 0) {
+                return 0;
+            }
+            break;
+        case 'q':
+            qflag = 1;
+            break;
+        default:
+            return command_usage(&write_cmd);
+        }
+    }
+
+    if (optind != argc - 2) {
+        return command_usage(&write_cmd);
+    }
+
+    if (bflag && pflag) {
+        printf("-b and -p cannot be specified at the same time\n");
+        return 0;
+    }
+
+    offset = cvtnum(argv[optind]);
+    if (offset < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        return 0;
+    }
+
+    optind++;
+    count = cvtnum(argv[optind]);
+    if (count < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        return 0;
+    }
+
+    if (!pflag) {
+        if (offset & 0x1ff) {
+            printf("offset %" PRId64 " is not sector aligned\n",
+                   offset);
+            return 0;
+        }
+
+        if (count & 0x1ff) {
+            printf("count %d is not sector aligned\n",
+                   count);
+            return 0;
+        }
+    }
+
+    buf = qemu_io_alloc(count, pattern);
+
+    gettimeofday(&t1, NULL);
+    if (pflag) {
+        cnt = do_pwrite(buf, offset, count, &total);
+    } else if (bflag) {
+        cnt = do_save_vmstate(buf, offset, count, &total);
+    } else {
+        cnt = do_write(buf, offset, count, &total);
+    }
+    gettimeofday(&t2, NULL);
+
+    if (cnt < 0) {
+        printf("write failed: %s\n", strerror(-cnt));
+        goto out;
+    }
+
+    if (qflag) {
+        goto out;
+    }
+
+    /* Finally, report back -- -C gives a parsable format */
+    t2 = tsub(t2, t1);
+    print_report("wrote", &t2, offset, count, total, cnt, Cflag);
 
 out:
-	qemu_io_free(buf);
+    qemu_io_free(buf);
 
-	return 0;
+    return 0;
 }
 
 static void
 writev_help(void)
 {
-	printf(
+    printf(
 "\n"
 " writes a range of bytes from the given offset source from multiple buffers\n"
 "\n"
@@ -772,90 +789,91 @@ writev_help(void)
 static int writev_f(int argc, char **argv);
 
 static const cmdinfo_t writev_cmd = {
-	.name		= "writev",
-	.cfunc		= writev_f,
-	.argmin		= 2,
-	.argmax		= -1,
-	.args		= "[-Cq] [-P pattern ] off len [len..]",
-	.oneline	= "writes a number of bytes at a specified offset",
-	.help		= writev_help,
+    .name       = "writev",
+    .cfunc      = writev_f,
+    .argmin     = 2,
+    .argmax     = -1,
+    .args       = "[-Cq] [-P pattern ] off len [len..]",
+    .oneline    = "writes a number of bytes at a specified offset",
+    .help       = writev_help,
 };
 
-static int
-writev_f(int argc, char **argv)
+static int writev_f(int argc, char **argv)
 {
-	struct timeval t1, t2;
-	int Cflag = 0, qflag = 0;
-	int c, cnt;
-	char *buf;
-	int64_t offset;
-        /* Some compilers get confused and warn if this is not initialized.  */
-        int total = 0;
-	int nr_iov;
-	int pattern = 0xcd;
-	QEMUIOVector qiov;
-
-	while ((c = getopt(argc, argv, "CqP:")) != EOF) {
-		switch (c) {
-		case 'C':
-			Cflag = 1;
-			break;
-		case 'q':
-			qflag = 1;
-			break;
-		case 'P':
-			pattern = parse_pattern(optarg);
-			if (pattern < 0)
-				return 0;
-			break;
-		default:
-			return command_usage(&writev_cmd);
-		}
-	}
-
-	if (optind > argc - 2)
-		return command_usage(&writev_cmd);
-
-	offset = cvtnum(argv[optind]);
-	if (offset < 0) {
-		printf("non-numeric length argument -- %s\n", argv[optind]);
-		return 0;
-	}
-	optind++;
-
-	if (offset & 0x1ff) {
-                printf("offset %" PRId64 " is not sector aligned\n",
-                       offset);
-		return 0;
-	}
-
-	nr_iov = argc - optind;
-	buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
-
-	gettimeofday(&t1, NULL);
-	cnt = do_aio_writev(&qiov, offset, &total);
-	gettimeofday(&t2, NULL);
-
-	if (cnt < 0) {
-		printf("writev failed: %s\n", strerror(-cnt));
-		goto out;
-	}
-
-	if (qflag)
-		goto out;
-
-	/* Finally, report back -- -C gives a parsable format */
-	t2 = tsub(t2, t1);
-	print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
+    struct timeval t1, t2;
+    int Cflag = 0, qflag = 0;
+    int c, cnt;
+    char *buf;
+    int64_t offset;
+    /* Some compilers get confused and warn if this is not initialized.  */
+    int total = 0;
+    int nr_iov;
+    int pattern = 0xcd;
+    QEMUIOVector qiov;
+
+    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
+        switch (c) {
+        case 'C':
+            Cflag = 1;
+            break;
+        case 'q':
+            qflag = 1;
+            break;
+        case 'P':
+            pattern = parse_pattern(optarg);
+            if (pattern < 0) {
+                return 0;
+            }
+            break;
+        default:
+            return command_usage(&writev_cmd);
+        }
+    }
+
+    if (optind > argc - 2) {
+        return command_usage(&writev_cmd);
+    }
+
+    offset = cvtnum(argv[optind]);
+    if (offset < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        return 0;
+    }
+    optind++;
+
+    if (offset & 0x1ff) {
+        printf("offset %" PRId64 " is not sector aligned\n",
+               offset);
+        return 0;
+    }
+
+    nr_iov = argc - optind;
+    buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
+
+    gettimeofday(&t1, NULL);
+    cnt = do_aio_writev(&qiov, offset, &total);
+    gettimeofday(&t2, NULL);
+
+    if (cnt < 0) {
+        printf("writev failed: %s\n", strerror(-cnt));
+        goto out;
+    }
+
+    if (qflag) {
+        goto out;
+    }
+
+    /* Finally, report back -- -C gives a parsable format */
+    t2 = tsub(t2, t1);
+    print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
 out:
-	qemu_io_free(buf);
-	return 0;
+    qemu_io_free(buf);
+    return 0;
 }
 
-static void
-multiwrite_help(void)
+static void multiwrite_help(void)
 {
-	printf(
+    printf(
 "\n"
 " writes a range of bytes from the given offset source from multiple buffers,\n"
 " in a batch of requests that may be merged by qemu\n"
@@ -876,217 +894,215 @@ multiwrite_help(void)
 static int multiwrite_f(int argc, char **argv);
 
 static const cmdinfo_t multiwrite_cmd = {
-	.name		= "multiwrite",
-	.cfunc		= multiwrite_f,
-	.argmin		= 2,
-	.argmax		= -1,
-	.args		= "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
-	.oneline	= "issues multiple write requests at once",
-	.help		= multiwrite_help,
+    .name       = "multiwrite",
+    .cfunc      = multiwrite_f,
+    .argmin     = 2,
+    .argmax     = -1,
+    .args       = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
+    .oneline    = "issues multiple write requests at once",
+    .help       = multiwrite_help,
 };
 
-static int
-multiwrite_f(int argc, char **argv)
+static int multiwrite_f(int argc, char **argv)
 {
-	struct timeval t1, t2;
-	int Cflag = 0, qflag = 0;
-	int c, cnt;
-	char **buf;
-	int64_t offset, first_offset = 0;
-	/* Some compilers get confused and warn if this is not initialized.  */
-	int total = 0;
-	int nr_iov;
-	int nr_reqs;
-	int pattern = 0xcd;
-	QEMUIOVector *qiovs;
-	int i;
-	BlockRequest *reqs;
-
-	while ((c = getopt(argc, argv, "CqP:")) != EOF) {
-		switch (c) {
-		case 'C':
-			Cflag = 1;
-			break;
-		case 'q':
-			qflag = 1;
-			break;
-		case 'P':
-			pattern = parse_pattern(optarg);
-			if (pattern < 0)
-				return 0;
-			break;
-		default:
-			return command_usage(&writev_cmd);
-		}
-	}
-
-	if (optind > argc - 2)
-		return command_usage(&writev_cmd);
-
-	nr_reqs = 1;
-	for (i = optind; i < argc; i++) {
-		if (!strcmp(argv[i], ";")) {
-			nr_reqs++;
-		}
-	}
-
-	reqs = qemu_malloc(nr_reqs * sizeof(*reqs));
-	buf = qemu_malloc(nr_reqs * sizeof(*buf));
-	qiovs = qemu_malloc(nr_reqs * sizeof(*qiovs));
-
-	for (i = 0; i < nr_reqs; 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;
-		}
-		optind++;
-
-		if (offset & 0x1ff) {
-			printf("offset %lld is not sector aligned\n",
-				(long long)offset);
-			return 0;
-		}
+    struct timeval t1, t2;
+    int Cflag = 0, qflag = 0;
+    int c, cnt;
+    char **buf;
+    int64_t offset, first_offset = 0;
+    /* Some compilers get confused and warn if this is not initialized.  */
+    int total = 0;
+    int nr_iov;
+    int nr_reqs;
+    int pattern = 0xcd;
+    QEMUIOVector *qiovs;
+    int i;
+    BlockRequest *reqs;
+
+    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
+        switch (c) {
+        case 'C':
+            Cflag = 1;
+            break;
+        case 'q':
+            qflag = 1;
+            break;
+        case 'P':
+            pattern = parse_pattern(optarg);
+            if (pattern < 0) {
+                return 0;
+            }
+            break;
+        default:
+            return command_usage(&writev_cmd);
+        }
+    }
+
+    if (optind > argc - 2) {
+        return command_usage(&writev_cmd);
+    }
+
+    nr_reqs = 1;
+    for (i = optind; i < argc; i++) {
+        if (!strcmp(argv[i], ";")) {
+            nr_reqs++;
+        }
+    }
+
+    reqs = qemu_malloc(nr_reqs * sizeof(*reqs));
+    buf = qemu_malloc(nr_reqs * sizeof(*buf));
+    qiovs = qemu_malloc(nr_reqs * sizeof(*qiovs));
+
+    for (i = 0; i < nr_reqs; 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;
+        }
+        optind++;
+
+        if (offset & 0x1ff) {
+            printf("offset %lld is not sector aligned\n",
+                   (long long)offset);
+            return 0;
+        }
 
         if (i == 0) {
             first_offset = offset;
         }
 
-		/* Read lengths for qiov entries */
-		for (j = optind; j < argc; j++) {
-			if (!strcmp(argv[j], ";")) {
-				break;
-			}
-		}
+        /* Read lengths for qiov entries */
+        for (j = optind; j < argc; j++) {
+            if (!strcmp(argv[j], ";")) {
+                break;
+            }
+        }
 
-		nr_iov = j - optind;
+        nr_iov = j - optind;
 
-		/* Build request */
-		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;
+        /* Build request */
+        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;
 
-		optind = j + 1;
+        optind = j + 1;
 
-		offset += reqs[i].qiov->size;
-		pattern++;
-	}
+        offset += reqs[i].qiov->size;
+        pattern++;
+    }
 
-	gettimeofday(&t1, NULL);
-	cnt = do_aio_multiwrite(reqs, nr_reqs, &total);
-	gettimeofday(&t2, NULL);
+    gettimeofday(&t1, NULL);
+    cnt = do_aio_multiwrite(reqs, nr_reqs, &total);
+    gettimeofday(&t2, NULL);
 
-	if (cnt < 0) {
-		printf("aio_multiwrite failed: %s\n", strerror(-cnt));
-		goto out;
-	}
+    if (cnt < 0) {
+        printf("aio_multiwrite failed: %s\n", strerror(-cnt));
+        goto out;
+    }
 
-	if (qflag)
-		goto out;
+    if (qflag) {
+        goto out;
+    }
 
-	/* Finally, report back -- -C gives a parsable format */
-	t2 = tsub(t2, t1);
-	print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
+    /* Finally, report back -- -C gives a parsable format */
+    t2 = tsub(t2, t1);
+    print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
 out:
-	for (i = 0; i < nr_reqs; i++) {
-		qemu_io_free(buf[i]);
-		qemu_iovec_destroy(&qiovs[i]);
-	}
-	qemu_free(buf);
-	qemu_free(reqs);
-	qemu_free(qiovs);
-	return 0;
+    for (i = 0; i < nr_reqs; i++) {
+        qemu_io_free(buf[i]);
+        qemu_iovec_destroy(&qiovs[i]);
+    }
+    qemu_free(buf);
+    qemu_free(reqs);
+    qemu_free(qiovs);
+    return 0;
 }
 
 struct aio_ctx {
-	QEMUIOVector qiov;
-	int64_t offset;
-	char *buf;
-	int qflag;
-	int vflag;
-	int Cflag;
-	int Pflag;
-	int pattern;
-	struct timeval t1;
+    QEMUIOVector qiov;
+    int64_t offset;
+    char *buf;
+    int qflag;
+    int vflag;
+    int Cflag;
+    int Pflag;
+    int pattern;
+    struct timeval t1;
 };
 
-static void
-aio_write_done(void *opaque, int ret)
+static void aio_write_done(void *opaque, int ret)
 {
-	struct aio_ctx *ctx = opaque;
-	struct timeval t2;
+    struct aio_ctx *ctx = opaque;
+    struct timeval t2;
 
-	gettimeofday(&t2, NULL);
+    gettimeofday(&t2, NULL);
 
 
-	if (ret < 0) {
-		printf("aio_write failed: %s\n", strerror(-ret));
-		goto out;
-	}
+    if (ret < 0) {
+        printf("aio_write failed: %s\n", strerror(-ret));
+        goto out;
+    }
 
-	if (ctx->qflag) {
-		goto out;
-	}
+    if (ctx->qflag) {
+        goto out;
+    }
 
-	/* Finally, report back -- -C gives a parsable format */
-	t2 = tsub(t2, ctx->t1);
-	print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
-		     ctx->qiov.size, 1, ctx->Cflag);
+    /* Finally, report back -- -C gives a parsable format */
+    t2 = tsub(t2, ctx->t1);
+    print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
+                 ctx->qiov.size, 1, ctx->Cflag);
 out:
-	qemu_io_free(ctx->buf);
-	free(ctx);
+    qemu_io_free(ctx->buf);
+    free(ctx);
 }
 
-static void
-aio_read_done(void *opaque, int ret)
+static void aio_read_done(void *opaque, int ret)
 {
-	struct aio_ctx *ctx = opaque;
-	struct timeval t2;
-
-	gettimeofday(&t2, NULL);
-
-	if (ret < 0) {
-		printf("readv failed: %s\n", strerror(-ret));
-		goto out;
-	}
-
-	if (ctx->Pflag) {
-		void *cmp_buf = malloc(ctx->qiov.size);
-
-		memset(cmp_buf, ctx->pattern, ctx->qiov.size);
-		if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
-			printf("Pattern verification failed at offset %"
-                               PRId64 ", %zd bytes\n",
-                               ctx->offset, ctx->qiov.size);
-		}
-		free(cmp_buf);
-	}
-
-	if (ctx->qflag) {
-		goto out;
-	}
-
-	if (ctx->vflag) {
-		dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
-	}
-
-	/* Finally, report back -- -C gives a parsable format */
-	t2 = tsub(t2, ctx->t1);
-	print_report("read", &t2, ctx->offset, ctx->qiov.size,
-		     ctx->qiov.size, 1, ctx->Cflag);
+    struct aio_ctx *ctx = opaque;
+    struct timeval t2;
+
+    gettimeofday(&t2, NULL);
+
+    if (ret < 0) {
+        printf("readv failed: %s\n", strerror(-ret));
+        goto out;
+    }
+
+    if (ctx->Pflag) {
+        void *cmp_buf = malloc(ctx->qiov.size);
+
+        memset(cmp_buf, ctx->pattern, ctx->qiov.size);
+        if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
+            printf("Pattern verification failed at offset %"
+                   PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
+        }
+        free(cmp_buf);
+    }
+
+    if (ctx->qflag) {
+        goto out;
+    }
+
+    if (ctx->vflag) {
+        dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
+    }
+
+    /* Finally, report back -- -C gives a parsable format */
+    t2 = tsub(t2, ctx->t1);
+    print_report("read", &t2, ctx->offset, ctx->qiov.size,
+                 ctx->qiov.size, 1, ctx->Cflag);
 out:
-	qemu_io_free(ctx->buf);
-	free(ctx);
+    qemu_io_free(ctx->buf);
+    free(ctx);
 }
 
-static void
-aio_read_help(void)
+static void aio_read_help(void)
 {
-	printf(
+    printf(
 "\n"
 " asynchronously reads a range of bytes from the given offset\n"
 "\n"
@@ -1107,88 +1123,86 @@ aio_read_help(void)
 static int aio_read_f(int argc, char **argv);
 
 static const cmdinfo_t aio_read_cmd = {
-	.name		= "aio_read",
-	.cfunc		= aio_read_f,
-	.argmin		= 2,
-	.argmax		= -1,
-	.args		= "[-Cqv] [-P pattern ] off len [len..]",
-	.oneline	= "asynchronously reads a number of bytes",
-	.help		= aio_read_help,
+    .name       = "aio_read",
+    .cfunc      = aio_read_f,
+    .argmin     = 2,
+    .argmax     = -1,
+    .args       = "[-Cqv] [-P pattern ] off len [len..]",
+    .oneline    = "asynchronously reads a number of bytes",
+    .help       = aio_read_help,
 };
 
-static int
-aio_read_f(int argc, char **argv)
+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) {
-		case 'C':
-			ctx->Cflag = 1;
-			break;
-		case 'P':
-			ctx->Pflag = 1;
-			ctx->pattern = parse_pattern(optarg);
-			if (ctx->pattern < 0) {
-                                free(ctx);
-				return 0;
-                        }
-			break;
-		case 'q':
-			ctx->qflag = 1;
-			break;
-		case 'v':
-			ctx->vflag = 1;
-			break;
-		default:
-			free(ctx);
-			return command_usage(&aio_read_cmd);
-		}
-	}
-
-	if (optind > argc - 2) {
-		free(ctx);
-		return command_usage(&aio_read_cmd);
-	}
-
-	ctx->offset = cvtnum(argv[optind]);
-	if (ctx->offset < 0) {
-		printf("non-numeric length argument -- %s\n", argv[optind]);
-		free(ctx);
-		return 0;
-	}
-	optind++;
-
-	if (ctx->offset & 0x1ff) {
-		printf("offset %" PRId64 " is not sector aligned\n",
-                       ctx->offset);
-		free(ctx);
-		return 0;
-	}
-
-	nr_iov = argc - optind;
-	ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
-
-	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;
-	}
-
-	return 0;
+    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) {
+        case 'C':
+            ctx->Cflag = 1;
+            break;
+        case 'P':
+            ctx->Pflag = 1;
+            ctx->pattern = parse_pattern(optarg);
+            if (ctx->pattern < 0) {
+                free(ctx);
+                return 0;
+            }
+            break;
+        case 'q':
+            ctx->qflag = 1;
+            break;
+        case 'v':
+            ctx->vflag = 1;
+            break;
+        default:
+            free(ctx);
+            return command_usage(&aio_read_cmd);
+        }
+    }
+
+    if (optind > argc - 2) {
+        free(ctx);
+        return command_usage(&aio_read_cmd);
+    }
+
+    ctx->offset = cvtnum(argv[optind]);
+    if (ctx->offset < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        free(ctx);
+        return 0;
+    }
+    optind++;
+
+    if (ctx->offset & 0x1ff) {
+        printf("offset %" PRId64 " is not sector aligned\n",
+               ctx->offset);
+        free(ctx);
+        return 0;
+    }
+
+    nr_iov = argc - optind;
+    ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
+
+    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;
+    }
+
+    return 0;
 }
 
-static void
-aio_write_help(void)
+static void aio_write_help(void)
 {
-	printf(
+    printf(
 "\n"
-" asynchronously writes a range of bytes from the given offset source \n"
+" asynchronously writes a range of bytes from the given offset source\n"
 " from multiple buffers\n"
 "\n"
 " Example:\n"
@@ -1207,199 +1221,196 @@ aio_write_help(void)
 static int aio_write_f(int argc, char **argv);
 
 static const cmdinfo_t aio_write_cmd = {
-	.name		= "aio_write",
-	.cfunc		= aio_write_f,
-	.argmin		= 2,
-	.argmax		= -1,
-	.args		= "[-Cq] [-P pattern ] off len [len..]",
-	.oneline	= "asynchronously writes a number of bytes",
-	.help		= aio_write_help,
+    .name       = "aio_write",
+    .cfunc      = aio_write_f,
+    .argmin     = 2,
+    .argmax     = -1,
+    .args       = "[-Cq] [-P pattern ] off len [len..]",
+    .oneline    = "asynchronously writes a number of bytes",
+    .help       = aio_write_help,
 };
 
-static int
-aio_write_f(int argc, char **argv)
+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) {
-		case 'C':
-			ctx->Cflag = 1;
-			break;
-		case 'q':
-			ctx->qflag = 1;
-			break;
-		case 'P':
-			pattern = parse_pattern(optarg);
-			if (pattern < 0)
-				return 0;
-			break;
-		default:
-			free(ctx);
-			return command_usage(&aio_write_cmd);
-		}
-	}
-
-	if (optind > argc - 2) {
-		free(ctx);
-		return command_usage(&aio_write_cmd);
-	}
-
-	ctx->offset = cvtnum(argv[optind]);
-	if (ctx->offset < 0) {
-		printf("non-numeric length argument -- %s\n", argv[optind]);
-		free(ctx);
-		return 0;
-	}
-	optind++;
-
-	if (ctx->offset & 0x1ff) {
-		printf("offset %" PRId64 " is not sector aligned\n",
-                       ctx->offset);
-		free(ctx);
-		return 0;
-	}
-
-	nr_iov = argc - optind;
-	ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
-
-	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;
-	}
-
-	return 0;
+    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) {
+        case 'C':
+            ctx->Cflag = 1;
+            break;
+        case 'q':
+            ctx->qflag = 1;
+            break;
+        case 'P':
+            pattern = parse_pattern(optarg);
+            if (pattern < 0) {
+                return 0;
+            }
+            break;
+        default:
+            free(ctx);
+            return command_usage(&aio_write_cmd);
+        }
+    }
+
+    if (optind > argc - 2) {
+        free(ctx);
+        return command_usage(&aio_write_cmd);
+    }
+
+    ctx->offset = cvtnum(argv[optind]);
+    if (ctx->offset < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        free(ctx);
+        return 0;
+    }
+    optind++;
+
+    if (ctx->offset & 0x1ff) {
+        printf("offset %" PRId64 " is not sector aligned\n",
+               ctx->offset);
+        free(ctx);
+        return 0;
+    }
+
+    nr_iov = argc - optind;
+    ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
+
+    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;
+    }
+
+    return 0;
 }
 
-static int
-aio_flush_f(int argc, char **argv)
+static int aio_flush_f(int argc, char **argv)
 {
-	qemu_aio_flush();
-	return 0;
+    qemu_aio_flush();
+    return 0;
 }
 
 static const cmdinfo_t aio_flush_cmd = {
-	.name		= "aio_flush",
-	.cfunc		= aio_flush_f,
-	.oneline	= "completes all outstanding aio requests"
+    .name       = "aio_flush",
+    .cfunc      = aio_flush_f,
+    .oneline    = "completes all outstanding aio requests"
 };
 
-static int
-flush_f(int argc, char **argv)
+static int flush_f(int argc, char **argv)
 {
-	bdrv_flush(bs);
-	return 0;
+    bdrv_flush(bs);
+    return 0;
 }
 
 static const cmdinfo_t flush_cmd = {
-	.name		= "flush",
-	.altname	= "f",
-	.cfunc		= flush_f,
-	.oneline	= "flush all in-core file state to disk",
+    .name       = "flush",
+    .altname    = "f",
+    .cfunc      = flush_f,
+    .oneline    = "flush all in-core file state to disk",
 };
 
-static int
-truncate_f(int argc, char **argv)
+static int truncate_f(int argc, char **argv)
 {
-	int64_t offset;
-	int ret;
-
-	offset = cvtnum(argv[1]);
-	if (offset < 0) {
-		printf("non-numeric truncate argument -- %s\n", argv[1]);
-		return 0;
-	}
-
-	ret = bdrv_truncate(bs, offset);
-	if (ret < 0) {
-		printf("truncate: %s\n", strerror(-ret));
-		return 0;
-	}
-
-	return 0;
+    int64_t offset;
+    int ret;
+
+    offset = cvtnum(argv[1]);
+    if (offset < 0) {
+        printf("non-numeric truncate argument -- %s\n", argv[1]);
+        return 0;
+    }
+
+    ret = bdrv_truncate(bs, offset);
+    if (ret < 0) {
+        printf("truncate: %s\n", strerror(-ret));
+        return 0;
+    }
+
+    return 0;
 }
 
 static const cmdinfo_t truncate_cmd = {
-	.name		= "truncate",
-	.altname	= "t",
-	.cfunc		= truncate_f,
-	.argmin		= 1,
-	.argmax		= 1,
-	.args		= "off",
-	.oneline	= "truncates the current file at the given offset",
+    .name       = "truncate",
+    .altname    = "t",
+    .cfunc      = truncate_f,
+    .argmin     = 1,
+    .argmax     = 1,
+    .args       = "off",
+    .oneline    = "truncates the current file at the given offset",
 };
 
-static int
-length_f(int argc, char **argv)
+static int length_f(int argc, char **argv)
 {
-        int64_t size;
-	char s1[64];
-
-	size = bdrv_getlength(bs);
-	if (size < 0) {
-		printf("getlength: %s\n", strerror(-size));
-		return 0;
-	}
-
-	cvtstr(size, s1, sizeof(s1));
-	printf("%s\n", s1);
-	return 0;
+    int64_t size;
+    char s1[64];
+
+    size = bdrv_getlength(bs);
+    if (size < 0) {
+        printf("getlength: %s\n", strerror(-size));
+        return 0;
+    }
+
+    cvtstr(size, s1, sizeof(s1));
+    printf("%s\n", s1);
+    return 0;
 }
 
 
 static const cmdinfo_t length_cmd = {
-	.name		= "length",
-	.altname	= "l",
-	.cfunc		= length_f,
-	.oneline	= "gets the length of the current file",
+    .name   = "length",
+    .altname    = "l",
+    .cfunc      = length_f,
+    .oneline    = "gets the length of the current file",
 };
 
 
-static int
-info_f(int argc, char **argv)
+static int info_f(int argc, char **argv)
 {
-	BlockDriverInfo bdi;
-	char s1[64], s2[64];
-	int ret;
+    BlockDriverInfo bdi;
+    char s1[64], s2[64];
+    int ret;
 
-	if (bs->drv && bs->drv->format_name)
-		printf("format name: %s\n", bs->drv->format_name);
-	if (bs->drv && bs->drv->protocol_name)
-		printf("format name: %s\n", bs->drv->protocol_name);
+    if (bs->drv && bs->drv->format_name) {
+        printf("format name: %s\n", bs->drv->format_name);
+    }
+    if (bs->drv && bs->drv->protocol_name) {
+        printf("format name: %s\n", bs->drv->protocol_name);
+    }
 
-	ret = bdrv_get_info(bs, &bdi);
-	if (ret)
-		return 0;
+    ret = bdrv_get_info(bs, &bdi);
+    if (ret) {
+        return 0;
+    }
 
-	cvtstr(bdi.cluster_size, s1, sizeof(s1));
-	cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
+    cvtstr(bdi.cluster_size, s1, sizeof(s1));
+    cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
 
-	printf("cluster size: %s\n", s1);
-	printf("vm state offset: %s\n", s2);
+    printf("cluster size: %s\n", s1);
+    printf("vm state offset: %s\n", s2);
 
-	return 0;
+    return 0;
 }
 
 
 
 static const cmdinfo_t info_cmd = {
-	.name		= "info",
-	.altname	= "i",
-	.cfunc		= info_f,
-	.oneline	= "prints information about the current file",
+    .name       = "info",
+    .altname    = "i",
+    .cfunc      = info_f,
+    .oneline    = "prints information about the current file",
 };
 
-static void
-discard_help(void)
+static void discard_help(void)
 {
-	printf(
+    printf(
 "\n"
 " discards a range of bytes from the given offset\n"
 "\n"
@@ -1415,148 +1426,147 @@ discard_help(void)
 static int discard_f(int argc, char **argv);
 
 static const cmdinfo_t discard_cmd = {
-	.name		= "discard",
-	.altname	= "d",
-	.cfunc		= discard_f,
-	.argmin		= 2,
-	.argmax		= -1,
-	.args		= "[-Cq] off len",
-	.oneline	= "discards a number of bytes at a specified offset",
-	.help		= discard_help,
+    .name       = "discard",
+    .altname    = "d",
+    .cfunc      = discard_f,
+    .argmin     = 2,
+    .argmax     = -1,
+    .args       = "[-Cq] off len",
+    .oneline    = "discards a number of bytes at a specified offset",
+    .help       = discard_help,
 };
 
-static int
-discard_f(int argc, char **argv)
+static int discard_f(int argc, char **argv)
 {
-	struct timeval t1, t2;
-	int Cflag = 0, qflag = 0;
-	int c, ret;
-	int64_t offset;
-	int count;
-
-	while ((c = getopt(argc, argv, "Cq")) != EOF) {
-		switch (c) {
-		case 'C':
-			Cflag = 1;
-			break;
-		case 'q':
-			qflag = 1;
-			break;
-		default:
-			return command_usage(&discard_cmd);
-		}
-	}
-
-	if (optind != argc - 2) {
-		return command_usage(&discard_cmd);
-	}
-
-	offset = cvtnum(argv[optind]);
-	if (offset < 0) {
-		printf("non-numeric length argument -- %s\n", argv[optind]);
-		return 0;
-	}
-
-	optind++;
-	count = cvtnum(argv[optind]);
-	if (count < 0) {
-		printf("non-numeric length argument -- %s\n", argv[optind]);
-		return 0;
-	}
-
-	gettimeofday(&t1, NULL);
-	ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS, count >> BDRV_SECTOR_BITS);
-	gettimeofday(&t2, NULL);
-
-	if (ret < 0) {
-		printf("discard failed: %s\n", strerror(-ret));
-		goto out;
-	}
-
-	/* Finally, report back -- -C gives a parsable format */
-	if (!qflag) {
-		t2 = tsub(t2, t1);
-		print_report("discard", &t2, offset, count, count, 1, Cflag);
-	}
+    struct timeval t1, t2;
+    int Cflag = 0, qflag = 0;
+    int c, ret;
+    int64_t offset;
+    int count;
+
+    while ((c = getopt(argc, argv, "Cq")) != EOF) {
+        switch (c) {
+        case 'C':
+            Cflag = 1;
+            break;
+        case 'q':
+            qflag = 1;
+            break;
+        default:
+            return command_usage(&discard_cmd);
+        }
+    }
+
+    if (optind != argc - 2) {
+        return command_usage(&discard_cmd);
+    }
+
+    offset = cvtnum(argv[optind]);
+    if (offset < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        return 0;
+    }
+
+    optind++;
+    count = cvtnum(argv[optind]);
+    if (count < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        return 0;
+    }
+
+    gettimeofday(&t1, NULL);
+    ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
+                       count >> BDRV_SECTOR_BITS);
+    gettimeofday(&t2, NULL);
+
+    if (ret < 0) {
+        printf("discard failed: %s\n", strerror(-ret));
+        goto out;
+    }
+
+    /* Finally, report back -- -C gives a parsable format */
+    if (!qflag) {
+        t2 = tsub(t2, t1);
+        print_report("discard", &t2, offset, count, count, 1, Cflag);
+    }
 
 out:
-	return 0;
+    return 0;
 }
 
-static int
-alloc_f(int argc, char **argv)
+static int alloc_f(int argc, char **argv)
 {
-	int64_t offset;
-	int nb_sectors, remaining;
-	char s1[64];
-	int num, sum_alloc;
-	int ret;
-
-	offset = cvtnum(argv[1]);
-	if (offset & 0x1ff) {
-                printf("offset %" PRId64 " is not sector aligned\n",
-                       offset);
-		return 0;
-	}
-
-	if (argc == 3)
-		nb_sectors = cvtnum(argv[2]);
-	else
-		nb_sectors = 1;
-
-	remaining = nb_sectors;
-	sum_alloc = 0;
-	while (remaining) {
-		ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num);
-		remaining -= num;
-		if (ret) {
-			sum_alloc += num;
-		}
-	}
-
-	cvtstr(offset, s1, sizeof(s1));
-
-	printf("%d/%d sectors allocated at offset %s\n",
-	       sum_alloc, nb_sectors, s1);
-	return 0;
+    int64_t offset;
+    int nb_sectors, remaining;
+    char s1[64];
+    int num, sum_alloc;
+    int ret;
+
+    offset = cvtnum(argv[1]);
+    if (offset & 0x1ff) {
+        printf("offset %" PRId64 " is not sector aligned\n",
+               offset);
+        return 0;
+    }
+
+    if (argc == 3) {
+        nb_sectors = cvtnum(argv[2]);
+    } else {
+        nb_sectors = 1;
+    }
+
+    remaining = nb_sectors;
+    sum_alloc = 0;
+    while (remaining) {
+        ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num);
+        remaining -= num;
+        if (ret) {
+            sum_alloc += num;
+        }
+    }
+
+    cvtstr(offset, s1, sizeof(s1));
+
+    printf("%d/%d sectors allocated at offset %s\n",
+           sum_alloc, nb_sectors, s1);
+    return 0;
 }
 
 static const cmdinfo_t alloc_cmd = {
-	.name		= "alloc",
-	.altname	= "a",
-	.argmin		= 1,
-	.argmax		= 2,
-	.cfunc		= alloc_f,
-	.args		= "off [sectors]",
-	.oneline	= "checks if a sector is present in the file",
+    .name       = "alloc",
+    .altname    = "a",
+    .argmin     = 1,
+    .argmax     = 2,
+    .cfunc      = alloc_f,
+    .args       = "off [sectors]",
+    .oneline    = "checks if a sector is present in the file",
 };
 
-static int
-map_f(int argc, char **argv)
+static int map_f(int argc, char **argv)
 {
-	int64_t offset;
-	int64_t nb_sectors;
-	char s1[64];
-	int num, num_checked;
-	int ret;
-	const char *retstr;
-
-	offset = 0;
-	nb_sectors = bs->total_sectors;
-
-	do {
-		num_checked = MIN(nb_sectors, INT_MAX);
-		ret = bdrv_is_allocated(bs, offset, num_checked, &num);
-		retstr = ret ? "    allocated" : "not allocated";
-		cvtstr(offset << 9ULL, s1, sizeof(s1));
-		printf("[% 24" PRId64 "] % 8d/% 8d sectors %s at offset %s (%d)\n",
-				offset << 9ULL, num, num_checked, retstr, s1, ret);
-
-		offset += num;
-		nb_sectors -= num;
-	} while(offset < bs->total_sectors);
-
-	return 0;
+    int64_t offset;
+    int64_t nb_sectors;
+    char s1[64];
+    int num, num_checked;
+    int ret;
+    const char *retstr;
+
+    offset = 0;
+    nb_sectors = bs->total_sectors;
+
+    do {
+        num_checked = MIN(nb_sectors, INT_MAX);
+        ret = bdrv_is_allocated(bs, offset, num_checked, &num);
+        retstr = ret ? "    allocated" : "not allocated";
+        cvtstr(offset << 9ULL, s1, sizeof(s1));
+        printf("[% 24" PRId64 "] % 8d/% 8d sectors %s at offset %s (%d)\n",
+               offset << 9ULL, num, num_checked, retstr, s1, ret);
+
+        offset += num;
+        nb_sectors -= num;
+    } while (offset < bs->total_sectors);
+
+    return 0;
 }
 
 static const cmdinfo_t map_cmd = {
@@ -1569,50 +1579,48 @@ static const cmdinfo_t map_cmd = {
 };
 
 
-static int
-close_f(int argc, char **argv)
+static int close_f(int argc, char **argv)
 {
-	bdrv_close(bs);
-	bs = NULL;
-	return 0;
+    bdrv_close(bs);
+    bs = NULL;
+    return 0;
 }
 
 static const cmdinfo_t close_cmd = {
-	.name		= "close",
-	.altname	= "c",
-	.cfunc		= close_f,
-	.oneline	= "close the current open file",
+    .name       = "close",
+    .altname    = "c",
+    .cfunc      = close_f,
+    .oneline    = "close the current open file",
 };
 
 static int openfile(char *name, int flags, int growable)
 {
-	if (bs) {
-		fprintf(stderr, "file open already, try 'help close'\n");
-		return 1;
-	}
-
-	if (growable) {
-		if (bdrv_file_open(&bs, name, flags)) {
-			fprintf(stderr, "%s: can't open device %s\n", progname, name);
-			return 1;
-		}
-	} else {
-		bs = bdrv_new("hda");
-
-		if (bdrv_open(bs, name, flags, NULL) < 0) {
-			fprintf(stderr, "%s: can't open device %s\n", progname, name);
-			bs = NULL;
-			return 1;
-		}
-	}
-
-	return 0;
+    if (bs) {
+        fprintf(stderr, "file open already, try 'help close'\n");
+        return 1;
+    }
+
+    if (growable) {
+        if (bdrv_file_open(&bs, name, flags)) {
+            fprintf(stderr, "%s: can't open device %s\n", progname, name);
+            return 1;
+        }
+    } else {
+        bs = bdrv_new("hda");
+
+        if (bdrv_open(bs, name, flags, NULL) < 0) {
+            fprintf(stderr, "%s: can't open device %s\n", progname, name);
+            bs = NULL;
+            return 1;
+        }
+    }
+
+    return 0;
 }
 
-static void
-open_help(void)
+static void open_help(void)
 {
-	printf(
+    printf(
 "\n"
 " opens a new file in the requested mode\n"
 "\n"
@@ -1630,80 +1638,78 @@ open_help(void)
 static int open_f(int argc, char **argv);
 
 static const cmdinfo_t open_cmd = {
-	.name		= "open",
-	.altname	= "o",
-	.cfunc		= open_f,
-	.argmin		= 1,
-	.argmax		= -1,
-	.flags		= CMD_NOFILE_OK,
-	.args		= "[-Crsn] [path]",
-	.oneline	= "open the file specified by path",
-	.help		= open_help,
+    .name       = "open",
+    .altname    = "o",
+    .cfunc      = open_f,
+    .argmin     = 1,
+    .argmax     = -1,
+    .flags      = CMD_NOFILE_OK,
+    .args       = "[-Crsn] [path]",
+    .oneline    = "open the file specified by path",
+    .help       = open_help,
 };
 
-static int
-open_f(int argc, char **argv)
+static int open_f(int argc, char **argv)
 {
-	int flags = 0;
-	int readonly = 0;
-	int growable = 0;
-	int c;
-
-	while ((c = getopt(argc, argv, "snrg")) != EOF) {
-		switch (c) {
-		case 's':
-			flags |= BDRV_O_SNAPSHOT;
-			break;
-		case 'n':
-			flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB;
-			break;
-		case 'r':
-			readonly = 1;
-			break;
-		case 'g':
-			growable = 1;
-			break;
-		default:
-			return command_usage(&open_cmd);
-		}
-	}
-
-	if (!readonly) {
-            flags |= BDRV_O_RDWR;
+    int flags = 0;
+    int readonly = 0;
+    int growable = 0;
+    int c;
+
+    while ((c = getopt(argc, argv, "snrg")) != EOF) {
+        switch (c) {
+        case 's':
+            flags |= BDRV_O_SNAPSHOT;
+            break;
+        case 'n':
+            flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB;
+            break;
+        case 'r':
+            readonly = 1;
+            break;
+        case 'g':
+            growable = 1;
+            break;
+        default:
+            return command_usage(&open_cmd);
         }
+    }
+
+    if (!readonly) {
+        flags |= BDRV_O_RDWR;
+    }
 
-	if (optind != argc - 1)
-		return command_usage(&open_cmd);
+    if (optind != argc - 1) {
+        return command_usage(&open_cmd);
+    }
 
-	return openfile(argv[optind], flags, growable);
+    return openfile(argv[optind], flags, growable);
 }
 
-static int
-init_args_command(
-        int     index)
+static int init_args_command(int index)
 {
-	/* only one device allowed so far */
-	if (index >= 1)
-		return 0;
-	return ++index;
+    /* only one device allowed so far */
+    if (index >= 1) {
+        return 0;
+    }
+    return ++index;
 }
 
-static int
-init_check_command(
-	const cmdinfo_t *ct)
+static int init_check_command(const cmdinfo_t *ct)
 {
-	if (ct->flags & CMD_FLAG_GLOBAL)
-		return 1;
-	if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
-		fprintf(stderr, "no file open, try 'help open'\n");
-		return 0;
-	}
-	return 1;
+    if (ct->flags & CMD_FLAG_GLOBAL) {
+        return 1;
+    }
+    if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
+        fprintf(stderr, "no file open, try 'help open'\n");
+        return 0;
+    }
+    return 1;
 }
 
 static void usage(const char *name)
 {
-	printf(
+    printf(
 "Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n"
 "QEMU Disk exerciser\n"
 "\n"
@@ -1717,115 +1723,117 @@ static void usage(const char *name)
 "  -h, --help           display this help and exit\n"
 "  -V, --version        output version information and exit\n"
 "\n",
-	name);
+    name);
 }
 
 
 int main(int argc, char **argv)
 {
-	int readonly = 0;
-	int growable = 0;
-	const char *sopt = "hVc:rsnmgk";
-        const struct option lopt[] = {
-		{ "help", 0, NULL, 'h' },
-		{ "version", 0, NULL, 'V' },
-		{ "offset", 1, NULL, 'o' },
-		{ "cmd", 1, NULL, 'c' },
-		{ "read-only", 0, NULL, 'r' },
-		{ "snapshot", 0, NULL, 's' },
-		{ "nocache", 0, NULL, 'n' },
-		{ "misalign", 0, NULL, 'm' },
-		{ "growable", 0, NULL, 'g' },
-		{ "native-aio", 0, NULL, 'k' },
-		{ NULL, 0, NULL, 0 }
-	};
-	int c;
-	int opt_index = 0;
-	int flags = 0;
-
-	progname = basename(argv[0]);
-
-	while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
-		switch (c) {
-		case 's':
-			flags |= BDRV_O_SNAPSHOT;
-			break;
-		case 'n':
-			flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB;
-			break;
-		case 'c':
-			add_user_command(optarg);
-			break;
-		case 'r':
-			readonly = 1;
-			break;
-		case 'm':
-			misalign = 1;
-			break;
-		case 'g':
-			growable = 1;
-			break;
-		case 'k':
-			flags |= BDRV_O_NATIVE_AIO;
-			break;
-		case 'V':
-			printf("%s version %s\n", progname, VERSION);
-			exit(0);
-		case 'h':
-			usage(progname);
-			exit(0);
-		default:
-			usage(progname);
-			exit(1);
-		}
-	}
-
-	if ((argc - optind) > 1) {
-		usage(progname);
-		exit(1);
-	}
-
-	bdrv_init();
-
-	/* initialize commands */
-	quit_init();
-	help_init();
-	add_command(&open_cmd);
-	add_command(&close_cmd);
-	add_command(&read_cmd);
-	add_command(&readv_cmd);
-	add_command(&write_cmd);
-	add_command(&writev_cmd);
-	add_command(&multiwrite_cmd);
-	add_command(&aio_read_cmd);
-	add_command(&aio_write_cmd);
-	add_command(&aio_flush_cmd);
-	add_command(&flush_cmd);
-	add_command(&truncate_cmd);
-	add_command(&length_cmd);
-	add_command(&info_cmd);
-	add_command(&discard_cmd);
-	add_command(&alloc_cmd);
-	add_command(&map_cmd);
-
-	add_args_command(init_args_command);
-	add_check_command(init_check_command);
-
-	/* open the device */
-	if (!readonly) {
-            flags |= BDRV_O_RDWR;
+    int readonly = 0;
+    int growable = 0;
+    const char *sopt = "hVc:rsnmgk";
+    const struct option lopt[] = {
+        { "help", 0, NULL, 'h' },
+        { "version", 0, NULL, 'V' },
+        { "offset", 1, NULL, 'o' },
+        { "cmd", 1, NULL, 'c' },
+        { "read-only", 0, NULL, 'r' },
+        { "snapshot", 0, NULL, 's' },
+        { "nocache", 0, NULL, 'n' },
+        { "misalign", 0, NULL, 'm' },
+        { "growable", 0, NULL, 'g' },
+        { "native-aio", 0, NULL, 'k' },
+        { NULL, 0, NULL, 0 }
+    };
+    int c;
+    int opt_index = 0;
+    int flags = 0;
+
+    progname = basename(argv[0]);
+
+    while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
+        switch (c) {
+        case 's':
+            flags |= BDRV_O_SNAPSHOT;
+            break;
+        case 'n':
+            flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB;
+            break;
+        case 'c':
+            add_user_command(optarg);
+            break;
+        case 'r':
+            readonly = 1;
+            break;
+        case 'm':
+            misalign = 1;
+            break;
+        case 'g':
+            growable = 1;
+            break;
+        case 'k':
+            flags |= BDRV_O_NATIVE_AIO;
+            break;
+        case 'V':
+            printf("%s version %s\n", progname, VERSION);
+            exit(0);
+        case 'h':
+            usage(progname);
+            exit(0);
+        default:
+            usage(progname);
+            exit(1);
         }
+    }
+
+    if ((argc - optind) > 1) {
+        usage(progname);
+        exit(1);
+    }
 
-	if ((argc - optind) == 1)
-		openfile(argv[optind], flags, growable);
-	command_loop();
+    bdrv_init();
+
+    /* initialize commands */
+    quit_init();
+    help_init();
+    add_command(&open_cmd);
+    add_command(&close_cmd);
+    add_command(&read_cmd);
+    add_command(&readv_cmd);
+    add_command(&write_cmd);
+    add_command(&writev_cmd);
+    add_command(&multiwrite_cmd);
+    add_command(&aio_read_cmd);
+    add_command(&aio_write_cmd);
+    add_command(&aio_flush_cmd);
+    add_command(&flush_cmd);
+    add_command(&truncate_cmd);
+    add_command(&length_cmd);
+    add_command(&info_cmd);
+    add_command(&discard_cmd);
+    add_command(&alloc_cmd);
+    add_command(&map_cmd);
+
+    add_args_command(init_args_command);
+    add_check_command(init_check_command);
+
+    /* open the device */
+    if (!readonly) {
+        flags |= BDRV_O_RDWR;
+    }
+
+    if ((argc - optind) == 1) {
+        openfile(argv[optind], flags, growable);
+    }
+    command_loop();
 
-	/*
-	 * Make sure all outstanding requests get flushed the program exits.
-	 */
-	qemu_aio_flush();
+    /*
+     * Make sure all outstanding requests get flushed the program exits.
+     */
+    qemu_aio_flush();
 
-	if (bs)
-		bdrv_close(bs);
-	return 0;
+    if (bs) {
+        bdrv_close(bs);
+    }
+    return 0;
 }
commit a8e0fdd71596631141e8ad3947b115cf8dd3b681
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date:   Wed Jul 6 03:38:48 2011 +0900

    sheepdog: add full data preallocation support
    
    This introduces qemu-img create option for sheepdog which allows the
    data to be fully preallocated (note that sheepdog always preallocates
    metadata).
    
    The option is disabled by default and you need to enable it like the
    following:
    
    qemu-img create sheepdog:test -o preallocation=full 1G
    
    Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: FUJITA Tomonori <fujita.tomonori at lab.ntt.co.jp>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index 80d106c..77a4de5 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -1286,6 +1286,49 @@ static int do_sd_create(char *filename, int64_t vdi_size,
     return 0;
 }
 
+static int sd_prealloc(const char *filename)
+{
+    BlockDriverState *bs = NULL;
+    uint32_t idx, max_idx;
+    int64_t vdi_size;
+    void *buf = qemu_mallocz(SD_DATA_OBJ_SIZE);
+    int ret;
+
+    ret = bdrv_file_open(&bs, filename, BDRV_O_RDWR);
+    if (ret < 0) {
+        goto out;
+    }
+
+    vdi_size = bdrv_getlength(bs);
+    if (vdi_size < 0) {
+        ret = vdi_size;
+        goto out;
+    }
+    max_idx = DIV_ROUND_UP(vdi_size, SD_DATA_OBJ_SIZE);
+
+    for (idx = 0; idx < max_idx; idx++) {
+        /*
+         * The created image can be a cloned image, so we need to read
+         * a data from the source image.
+         */
+        ret = bdrv_pread(bs, idx * SD_DATA_OBJ_SIZE, buf, SD_DATA_OBJ_SIZE);
+        if (ret < 0) {
+            goto out;
+        }
+        ret = bdrv_pwrite(bs, idx * SD_DATA_OBJ_SIZE, buf, SD_DATA_OBJ_SIZE);
+        if (ret < 0) {
+            goto out;
+        }
+    }
+out:
+    if (bs) {
+        bdrv_delete(bs);
+    }
+    qemu_free(buf);
+
+    return ret;
+}
+
 static int sd_create(const char *filename, QEMUOptionParameter *options)
 {
     int ret;
@@ -1295,13 +1338,15 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
     BDRVSheepdogState s;
     char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
     uint32_t snapid;
+    int prealloc = 0;
+    const char *vdiname;
 
-    strstart(filename, "sheepdog:", (const char **)&filename);
+    strstart(filename, "sheepdog:", &vdiname);
 
     memset(&s, 0, sizeof(s));
     memset(vdi, 0, sizeof(vdi));
     memset(tag, 0, sizeof(tag));
-    if (parse_vdiname(&s, filename, vdi, &snapid, tag) < 0) {
+    if (parse_vdiname(&s, vdiname, vdi, &snapid, tag) < 0) {
         error_report("invalid filename");
         return -EINVAL;
     }
@@ -1311,6 +1356,16 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
             vdi_size = options->value.n;
         } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
             backing_file = options->value.s;
+        } else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
+            if (!options->value.s || !strcmp(options->value.s, "off")) {
+                prealloc = 0;
+            } else if (!strcmp(options->value.s, "full")) {
+                prealloc = 1;
+            } else {
+                error_report("Invalid preallocation mode: '%s'",
+                             options->value.s);
+                return -EINVAL;
+            }
         }
         options++;
     }
@@ -1348,7 +1403,12 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
         bdrv_delete(bs);
     }
 
-    return do_sd_create((char *)vdi, vdi_size, base_vid, &vid, 0, s.addr, s.port);
+    ret = do_sd_create(vdi, vdi_size, base_vid, &vid, 0, s.addr, s.port);
+    if (!prealloc || ret) {
+        return ret;
+    }
+
+    return sd_prealloc(filename);
 }
 
 static void sd_close(BlockDriverState *bs)
@@ -1984,6 +2044,11 @@ static QEMUOptionParameter sd_create_options[] = {
         .type = OPT_STRING,
         .help = "File name of a base image"
     },
+    {
+        .name = BLOCK_OPT_PREALLOC,
+        .type = OPT_STRING,
+        .help = "Preallocation mode (allowed values: off, full)"
+    },
     { NULL }
 };
 
commit 82845826e89fdc02f6f000fca5d5019ec9be4ab3
Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:   Sun May 29 02:58:41 2011 +0000

    target-arm: Fix BASEPRI, BASEPRI_MAX, and FAULTMASK access
    
    Correct the decode of the register numbers for BASEPRI, BASEPRI_MAX
    and FAULTMASK, according to "ARMv7-M Architecture Reference Manual"
    issue D section "B5.2.3 MRS" and "B5.2.3 MSR".
    
    Signed-off-by: Sebastian Huber <sebastian.huber at embedded-brains.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 9785cc5..a0f2314 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2128,11 +2128,11 @@ uint32_t HELPER(v7m_mrs)(CPUState *env, uint32_t reg)
         return env->v7m.current_sp ? env->regs[13] : env->v7m.other_sp;
     case 16: /* PRIMASK */
         return (env->uncached_cpsr & CPSR_I) != 0;
-    case 17: /* FAULTMASK */
-        return (env->uncached_cpsr & CPSR_F) != 0;
-    case 18: /* BASEPRI */
-    case 19: /* BASEPRI_MAX */
+    case 17: /* BASEPRI */
+    case 18: /* BASEPRI_MAX */
         return env->v7m.basepri;
+    case 19: /* FAULTMASK */
+        return (env->uncached_cpsr & CPSR_F) != 0;
     case 20: /* CONTROL */
         return env->v7m.control;
     default:
@@ -2184,20 +2184,20 @@ void HELPER(v7m_msr)(CPUState *env, uint32_t reg, uint32_t val)
         else
             env->uncached_cpsr &= ~CPSR_I;
         break;
-    case 17: /* FAULTMASK */
-        if (val & 1)
-            env->uncached_cpsr |= CPSR_F;
-        else
-            env->uncached_cpsr &= ~CPSR_F;
-        break;
-    case 18: /* BASEPRI */
+    case 17: /* BASEPRI */
         env->v7m.basepri = val & 0xff;
         break;
-    case 19: /* BASEPRI_MAX */
+    case 18: /* BASEPRI_MAX */
         val &= 0xff;
         if (val != 0 && (val < env->v7m.basepri || env->v7m.basepri == 0))
             env->v7m.basepri = val;
         break;
+    case 19: /* FAULTMASK */
+        if (val & 1)
+            env->uncached_cpsr |= CPSR_F;
+        else
+            env->uncached_cpsr &= ~CPSR_F;
+        break;
     case 20: /* CONTROL */
         env->v7m.control = val & 3;
         switch_v7m_sp(env, (val & 2) != 0);
commit 74594c9d813e4d14e9c16cc71824d8905bedc19d
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 22 12:16:16 2011 +0000

    target-arm: Minimal implementation of performance counters
    
    Newer Linux kernels assume the existence of the performance counter
    cp15 registers. Provide a minimal implementation of these registers.
    We support no events. This should be compliant with the ARM ARM,
    except that we don't implement the cycle counter.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 01f5b57..1276e69 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -133,6 +133,12 @@ typedef struct CPUARMState {
         uint32_t c7_par;  /* Translation result. */
         uint32_t c9_insn; /* Cache lockdown registers.  */
         uint32_t c9_data;
+        uint32_t c9_pmcr; /* performance monitor control register */
+        uint32_t c9_pmcnten; /* perf monitor counter enables */
+        uint32_t c9_pmovsr; /* perf monitor overflow status */
+        uint32_t c9_pmxevtyper; /* perf monitor event type */
+        uint32_t c9_pmuserenr; /* perf monitor user enable */
+        uint32_t c9_pminten; /* perf monitor interrupt enables */
         uint32_t c13_fcse; /* FCSE PID.  */
         uint32_t c13_context; /* Context ID.  */
         uint32_t c13_tls1; /* User RW Thread register.  */
@@ -438,7 +444,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 3
+#define CPU_SAVE_VERSION 4
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 9f14781..9785cc5 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -270,6 +270,10 @@ void cpu_reset(CPUARMState *env)
     }
     env->vfp.xregs[ARM_VFP_FPEXC] = 0;
     env->cp15.c2_base_mask = 0xffffc000u;
+    /* v7 performance monitor control register: same implementor
+     * field as main ID register, and we implement no event counters.
+     */
+    env->cp15.c9_pmcr = (id & 0xff000000);
 #endif
     set_flush_to_zero(1, &env->vfp.standard_fp_status);
     set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status);
@@ -1588,6 +1592,81 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
         case 1: /* TCM memory region registers.  */
             /* Not implemented.  */
             goto bad_reg;
+        case 12: /* Performance monitor control */
+            /* Performance monitors are implementation defined in v7,
+             * but with an ARM recommended set of registers, which we
+             * follow (although we don't actually implement any counters)
+             */
+            if (!arm_feature(env, ARM_FEATURE_V7)) {
+                goto bad_reg;
+            }
+            switch (op2) {
+            case 0: /* performance monitor control register */
+                /* only the DP, X, D and E bits are writable */
+                env->cp15.c9_pmcr &= ~0x39;
+                env->cp15.c9_pmcr |= (val & 0x39);
+                break;
+            case 1: /* Count enable set register */
+                val &= (1 << 31);
+                env->cp15.c9_pmcnten |= val;
+                break;
+            case 2: /* Count enable clear */
+                val &= (1 << 31);
+                env->cp15.c9_pmcnten &= ~val;
+                break;
+            case 3: /* Overflow flag status */
+                env->cp15.c9_pmovsr &= ~val;
+                break;
+            case 4: /* Software increment */
+                /* RAZ/WI since we don't implement the software-count event */
+                break;
+            case 5: /* Event counter selection register */
+                /* Since we don't implement any events, writing to this register
+                 * is actually UNPREDICTABLE. So we choose to RAZ/WI.
+                 */
+                break;
+            default:
+                goto bad_reg;
+            }
+            break;
+        case 13: /* Performance counters */
+            if (!arm_feature(env, ARM_FEATURE_V7)) {
+                goto bad_reg;
+            }
+            switch (op2) {
+            case 0: /* Cycle count register: not implemented, so RAZ/WI */
+                break;
+            case 1: /* Event type select */
+                env->cp15.c9_pmxevtyper = val & 0xff;
+                break;
+            case 2: /* Event count register */
+                /* Unimplemented (we have no events), RAZ/WI */
+                break;
+            default:
+                goto bad_reg;
+            }
+            break;
+        case 14: /* Performance monitor control */
+            if (!arm_feature(env, ARM_FEATURE_V7)) {
+                goto bad_reg;
+            }
+            switch (op2) {
+            case 0: /* user enable */
+                env->cp15.c9_pmuserenr = val & 1;
+                /* changes access rights for cp registers, so flush tbs */
+                tb_flush(env);
+                break;
+            case 1: /* interrupt enable set */
+                /* We have no event counters so only the C bit can be changed */
+                val &= (1 << 31);
+                env->cp15.c9_pminten |= val;
+                break;
+            case 2: /* interrupt enable clear */
+                val &= (1 << 31);
+                env->cp15.c9_pminten &= ~val;
+                break;
+            }
+            break;
         default:
             goto bad_reg;
         }
@@ -1879,27 +1958,81 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
         return 0;
     case 8: /* MMU TLB control.  */
         goto bad_reg;
-    case 9: /* Cache lockdown.  */
-        switch (op1) {
-        case 0: /* L1 cache.  */
-	    if (arm_feature(env, ARM_FEATURE_OMAPCP))
-		return 0;
+    case 9:
+        switch (crm) {
+        case 0: /* Cache lockdown */
+            switch (op1) {
+            case 0: /* L1 cache.  */
+                if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
+                    return 0;
+                }
+                switch (op2) {
+                case 0:
+                    return env->cp15.c9_data;
+                case 1:
+                    return env->cp15.c9_insn;
+                default:
+                    goto bad_reg;
+                }
+            case 1: /* L2 cache */
+                if (crm != 0) {
+                    goto bad_reg;
+                }
+                /* L2 Lockdown and Auxiliary control.  */
+                return 0;
+            default:
+                goto bad_reg;
+            }
+            break;
+        case 12: /* Performance monitor control */
+            if (!arm_feature(env, ARM_FEATURE_V7)) {
+                goto bad_reg;
+            }
             switch (op2) {
-            case 0:
-                return env->cp15.c9_data;
-            case 1:
-                return env->cp15.c9_insn;
+            case 0: /* performance monitor control register */
+                return env->cp15.c9_pmcr;
+            case 1: /* count enable set */
+            case 2: /* count enable clear */
+                return env->cp15.c9_pmcnten;
+            case 3: /* overflow flag status */
+                return env->cp15.c9_pmovsr;
+            case 4: /* software increment */
+            case 5: /* event counter selection register */
+                return 0; /* Unimplemented, RAZ/WI */
             default:
                 goto bad_reg;
             }
-        case 1: /* L2 cache */
-            if (crm != 0)
+        case 13: /* Performance counters */
+            if (!arm_feature(env, ARM_FEATURE_V7)) {
+                goto bad_reg;
+            }
+            switch (op2) {
+            case 1: /* Event type select */
+                return env->cp15.c9_pmxevtyper;
+            case 0: /* Cycle count register */
+            case 2: /* Event count register */
+                /* Unimplemented, so RAZ/WI */
+                return 0;
+            default:
                 goto bad_reg;
-            /* L2 Lockdown and Auxiliary control.  */
-            return 0;
+            }
+        case 14: /* Performance monitor control */
+            if (!arm_feature(env, ARM_FEATURE_V7)) {
+                goto bad_reg;
+            }
+            switch (op2) {
+            case 0: /* user enable */
+                return env->cp15.c9_pmuserenr;
+            case 1: /* interrupt enable set */
+            case 2: /* interrupt enable clear */
+                return env->cp15.c9_pminten;
+            default:
+                goto bad_reg;
+            }
         default:
             goto bad_reg;
         }
+        break;
     case 10: /* MMU TLB lockdown.  */
         /* ??? TLB lockdown not implemented.  */
         return 0;
diff --git a/target-arm/machine.c b/target-arm/machine.c
index a18b7dc..7d4fc54 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -44,6 +44,12 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_be32(f, env->cp15.c7_par);
     qemu_put_be32(f, env->cp15.c9_insn);
     qemu_put_be32(f, env->cp15.c9_data);
+    qemu_put_be32(f, env->cp15.c9_pmcr);
+    qemu_put_be32(f, env->cp15.c9_pmcnten);
+    qemu_put_be32(f, env->cp15.c9_pmovsr);
+    qemu_put_be32(f, env->cp15.c9_pmxevtyper);
+    qemu_put_be32(f, env->cp15.c9_pmuserenr);
+    qemu_put_be32(f, env->cp15.c9_pminten);
     qemu_put_be32(f, env->cp15.c13_fcse);
     qemu_put_be32(f, env->cp15.c13_context);
     qemu_put_be32(f, env->cp15.c13_tls1);
@@ -152,6 +158,12 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     env->cp15.c7_par = qemu_get_be32(f);
     env->cp15.c9_insn = qemu_get_be32(f);
     env->cp15.c9_data = qemu_get_be32(f);
+    env->cp15.c9_pmcr = qemu_get_be32(f);
+    env->cp15.c9_pmcnten = qemu_get_be32(f);
+    env->cp15.c9_pmovsr = qemu_get_be32(f);
+    env->cp15.c9_pmxevtyper = qemu_get_be32(f);
+    env->cp15.c9_pmuserenr = qemu_get_be32(f);
+    env->cp15.c9_pminten = qemu_get_be32(f);
     env->cp15.c13_fcse = qemu_get_be32(f);
     env->cp15.c13_context = qemu_get_be32(f);
     env->cp15.c13_tls1 = qemu_get_be32(f);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 0273deb..3e431e1 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2472,12 +2472,28 @@ static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
     return 0;
 }
 
-static int cp15_user_ok(uint32_t insn)
+static int cp15_user_ok(CPUState *env, uint32_t insn)
 {
     int cpn = (insn >> 16) & 0xf;
     int cpm = insn & 0xf;
     int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
 
+    if (arm_feature(env, ARM_FEATURE_V7) && cpn == 9) {
+        /* Performance monitor registers fall into three categories:
+         *  (a) always UNDEF in usermode
+         *  (b) UNDEF only if PMUSERENR.EN is 0
+         *  (c) always read OK and UNDEF on write (PMUSERENR only)
+         */
+        if ((cpm == 12 && (op < 6)) ||
+            (cpm == 13 && (op < 3))) {
+            return env->cp15.c9_pmuserenr;
+        } else if (cpm == 14 && op == 0 && (insn & ARM_CP_RW_BIT)) {
+            /* PMUSERENR, read only */
+            return 1;
+        }
+        return 0;
+    }
+
     if (cpn == 13 && cpm == 0) {
         /* TLS register.  */
         if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
@@ -2564,7 +2580,7 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
         /* cdp */
         return 1;
     }
-    if (IS_USER(s) && !cp15_user_ok(insn)) {
+    if (IS_USER(s) && !cp15_user_ok(env, insn)) {
         return 1;
     }
 
commit b501b5e461fbf3f5c6cd91c8c933e6f4de627bee
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed May 25 13:14:56 2011 +0000

    Revert "Makefile.target: Allow target helpers to be in any *_helper.c file"
    
    Reverts commit 348883d4828d7434e1053407818598f7fb15e594, so the
    global env is no longer available to helper.c files other than
    op_helper.c.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/Makefile.target b/Makefile.target
index 03d3646..37bb28e 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -91,7 +91,7 @@ tcg/tcg.o: cpu.h
 
 # HELPER_CFLAGS is used for all the code compiled with static register
 # variables
-%_helper.o cpu-exec.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+op_helper.o cpu-exec.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 
 # Note: this is a workaround. The real fix is to avoid compiling
 # cpu_signal_handler() in user-exec.c.
commit 02da0b2d7152f736b1fba95902f55db4fd7ea3a5
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed May 25 13:31:02 2011 +0000

    Revert "target-arm: Use global env in neon_helper.c helpers"
    
    This effectively reverts commit 2a3f75b42ac255be09ec2939b96c549ec830efd3
    so that we return to passing CPUState to helpers as an explicit parameter.
    (There were a number of conflicts in target-arm/translate.c which had
    to be resolved by hand so it is not a pure revert.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.h b/target-arm/helper.h
index c29efd5..3ad1cb0 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -154,22 +154,22 @@ DEF_HELPER_2(sar_cc, i32, i32, i32)
 DEF_HELPER_2(ror_cc, i32, i32, i32)
 
 /* neon_helper.c */
-DEF_HELPER_2(neon_qadd_u8, i32, i32, i32)
-DEF_HELPER_2(neon_qadd_s8, i32, i32, i32)
-DEF_HELPER_2(neon_qadd_u16, i32, i32, i32)
-DEF_HELPER_2(neon_qadd_s16, i32, i32, i32)
-DEF_HELPER_2(neon_qadd_u32, i32, i32, i32)
-DEF_HELPER_2(neon_qadd_s32, i32, i32, i32)
-DEF_HELPER_2(neon_qsub_u8, i32, i32, i32)
-DEF_HELPER_2(neon_qsub_s8, i32, i32, i32)
-DEF_HELPER_2(neon_qsub_u16, i32, i32, i32)
-DEF_HELPER_2(neon_qsub_s16, i32, i32, i32)
-DEF_HELPER_2(neon_qsub_u32, i32, i32, i32)
-DEF_HELPER_2(neon_qsub_s32, i32, i32, i32)
-DEF_HELPER_2(neon_qadd_u64, i64, i64, i64)
-DEF_HELPER_2(neon_qadd_s64, i64, i64, i64)
-DEF_HELPER_2(neon_qsub_u64, i64, i64, i64)
-DEF_HELPER_2(neon_qsub_s64, i64, i64, i64)
+DEF_HELPER_3(neon_qadd_u8, i32, env, i32, i32)
+DEF_HELPER_3(neon_qadd_s8, i32, env, i32, i32)
+DEF_HELPER_3(neon_qadd_u16, i32, env, i32, i32)
+DEF_HELPER_3(neon_qadd_s16, i32, env, i32, i32)
+DEF_HELPER_3(neon_qadd_u32, i32, env, i32, i32)
+DEF_HELPER_3(neon_qadd_s32, i32, env, i32, i32)
+DEF_HELPER_3(neon_qsub_u8, i32, env, i32, i32)
+DEF_HELPER_3(neon_qsub_s8, i32, env, i32, i32)
+DEF_HELPER_3(neon_qsub_u16, i32, env, i32, i32)
+DEF_HELPER_3(neon_qsub_s16, i32, env, i32, i32)
+DEF_HELPER_3(neon_qsub_u32, i32, env, i32, i32)
+DEF_HELPER_3(neon_qsub_s32, i32, env, i32, i32)
+DEF_HELPER_3(neon_qadd_u64, i64, env, i64, i64)
+DEF_HELPER_3(neon_qadd_s64, i64, env, i64, i64)
+DEF_HELPER_3(neon_qsub_u64, i64, env, i64, i64)
+DEF_HELPER_3(neon_qsub_s64, i64, env, i64, i64)
 
 DEF_HELPER_2(neon_hadd_s8, i32, i32, i32)
 DEF_HELPER_2(neon_hadd_u8, i32, i32, i32)
@@ -247,26 +247,26 @@ DEF_HELPER_2(neon_rshl_u32, i32, i32, i32)
 DEF_HELPER_2(neon_rshl_s32, i32, i32, i32)
 DEF_HELPER_2(neon_rshl_u64, i64, i64, i64)
 DEF_HELPER_2(neon_rshl_s64, i64, i64, i64)
-DEF_HELPER_2(neon_qshl_u8, i32, i32, i32)
-DEF_HELPER_2(neon_qshl_s8, i32, i32, i32)
-DEF_HELPER_2(neon_qshl_u16, i32, i32, i32)
-DEF_HELPER_2(neon_qshl_s16, i32, i32, i32)
-DEF_HELPER_2(neon_qshl_u32, i32, i32, i32)
-DEF_HELPER_2(neon_qshl_s32, i32, i32, i32)
-DEF_HELPER_2(neon_qshl_u64, i64, i64, i64)
-DEF_HELPER_2(neon_qshl_s64, i64, i64, i64)
-DEF_HELPER_2(neon_qshlu_s8, i32, i32, i32);
-DEF_HELPER_2(neon_qshlu_s16, i32, i32, i32);
-DEF_HELPER_2(neon_qshlu_s32, i32, i32, i32);
-DEF_HELPER_2(neon_qshlu_s64, i64, i64, i64);
-DEF_HELPER_2(neon_qrshl_u8, i32, i32, i32)
-DEF_HELPER_2(neon_qrshl_s8, i32, i32, i32)
-DEF_HELPER_2(neon_qrshl_u16, i32, i32, i32)
-DEF_HELPER_2(neon_qrshl_s16, i32, i32, i32)
-DEF_HELPER_2(neon_qrshl_u32, i32, i32, i32)
-DEF_HELPER_2(neon_qrshl_s32, i32, i32, i32)
-DEF_HELPER_2(neon_qrshl_u64, i64, i64, i64)
-DEF_HELPER_2(neon_qrshl_s64, i64, i64, i64)
+DEF_HELPER_3(neon_qshl_u8, i32, env, i32, i32)
+DEF_HELPER_3(neon_qshl_s8, i32, env, i32, i32)
+DEF_HELPER_3(neon_qshl_u16, i32, env, i32, i32)
+DEF_HELPER_3(neon_qshl_s16, i32, env, i32, i32)
+DEF_HELPER_3(neon_qshl_u32, i32, env, i32, i32)
+DEF_HELPER_3(neon_qshl_s32, i32, env, i32, i32)
+DEF_HELPER_3(neon_qshl_u64, i64, env, i64, i64)
+DEF_HELPER_3(neon_qshl_s64, i64, env, i64, i64)
+DEF_HELPER_3(neon_qshlu_s8, i32, env, i32, i32);
+DEF_HELPER_3(neon_qshlu_s16, i32, env, i32, i32);
+DEF_HELPER_3(neon_qshlu_s32, i32, env, i32, i32);
+DEF_HELPER_3(neon_qshlu_s64, i64, env, i64, i64);
+DEF_HELPER_3(neon_qrshl_u8, i32, env, i32, i32)
+DEF_HELPER_3(neon_qrshl_s8, i32, env, i32, i32)
+DEF_HELPER_3(neon_qrshl_u16, i32, env, i32, i32)
+DEF_HELPER_3(neon_qrshl_s16, i32, env, i32, i32)
+DEF_HELPER_3(neon_qrshl_u32, i32, env, i32, i32)
+DEF_HELPER_3(neon_qrshl_s32, i32, env, i32, i32)
+DEF_HELPER_3(neon_qrshl_u64, i64, env, i64, i64)
+DEF_HELPER_3(neon_qrshl_s64, i64, env, i64, i64)
 
 DEF_HELPER_2(neon_add_u8, i32, i32, i32)
 DEF_HELPER_2(neon_add_u16, i32, i32, i32)
@@ -295,22 +295,22 @@ DEF_HELPER_1(neon_cls_s16, i32, i32)
 DEF_HELPER_1(neon_cls_s32, i32, i32)
 DEF_HELPER_1(neon_cnt_u8, i32, i32)
 
-DEF_HELPER_2(neon_qdmulh_s16, i32, i32, i32)
-DEF_HELPER_2(neon_qrdmulh_s16, i32, i32, i32)
-DEF_HELPER_2(neon_qdmulh_s32, i32, i32, i32)
-DEF_HELPER_2(neon_qrdmulh_s32, i32, i32, i32)
+DEF_HELPER_3(neon_qdmulh_s16, i32, env, i32, i32)
+DEF_HELPER_3(neon_qrdmulh_s16, i32, env, i32, i32)
+DEF_HELPER_3(neon_qdmulh_s32, i32, env, i32, i32)
+DEF_HELPER_3(neon_qrdmulh_s32, i32, env, i32, i32)
 
 DEF_HELPER_1(neon_narrow_u8, i32, i64)
 DEF_HELPER_1(neon_narrow_u16, i32, i64)
-DEF_HELPER_1(neon_unarrow_sat8, i32, i64)
-DEF_HELPER_1(neon_narrow_sat_u8, i32, i64)
-DEF_HELPER_1(neon_narrow_sat_s8, i32, i64)
-DEF_HELPER_1(neon_unarrow_sat16, i32, i64)
-DEF_HELPER_1(neon_narrow_sat_u16, i32, i64)
-DEF_HELPER_1(neon_narrow_sat_s16, i32, i64)
-DEF_HELPER_1(neon_unarrow_sat32, i32, i64)
-DEF_HELPER_1(neon_narrow_sat_u32, i32, i64)
-DEF_HELPER_1(neon_narrow_sat_s32, i32, i64)
+DEF_HELPER_2(neon_unarrow_sat8, i32, env, i64)
+DEF_HELPER_2(neon_narrow_sat_u8, i32, env, i64)
+DEF_HELPER_2(neon_narrow_sat_s8, i32, env, i64)
+DEF_HELPER_2(neon_unarrow_sat16, i32, env, i64)
+DEF_HELPER_2(neon_narrow_sat_u16, i32, env, i64)
+DEF_HELPER_2(neon_narrow_sat_s16, i32, env, i64)
+DEF_HELPER_2(neon_unarrow_sat32, i32, env, i64)
+DEF_HELPER_2(neon_narrow_sat_u32, i32, env, i64)
+DEF_HELPER_2(neon_narrow_sat_s32, i32, env, i64)
 DEF_HELPER_1(neon_narrow_high_u8, i32, i64)
 DEF_HELPER_1(neon_narrow_high_u16, i32, i64)
 DEF_HELPER_1(neon_narrow_round_high_u8, i32, i64)
@@ -326,8 +326,8 @@ DEF_HELPER_2(neon_paddl_u16, i64, i64, i64)
 DEF_HELPER_2(neon_paddl_u32, i64, i64, i64)
 DEF_HELPER_2(neon_subl_u16, i64, i64, i64)
 DEF_HELPER_2(neon_subl_u32, i64, i64, i64)
-DEF_HELPER_2(neon_addl_saturate_s32, i64, i64, i64)
-DEF_HELPER_2(neon_addl_saturate_s64, i64, i64, i64)
+DEF_HELPER_3(neon_addl_saturate_s32, i64, env, i64, i64)
+DEF_HELPER_3(neon_addl_saturate_s64, i64, env, i64, i64)
 DEF_HELPER_2(neon_abdl_u16, i64, i32, i32)
 DEF_HELPER_2(neon_abdl_s16, i64, i32, i32)
 DEF_HELPER_2(neon_abdl_u32, i64, i32, i32)
@@ -343,12 +343,12 @@ DEF_HELPER_1(neon_negl_u16, i64, i64)
 DEF_HELPER_1(neon_negl_u32, i64, i64)
 DEF_HELPER_1(neon_negl_u64, i64, i64)
 
-DEF_HELPER_1(neon_qabs_s8, i32, i32)
-DEF_HELPER_1(neon_qabs_s16, i32, i32)
-DEF_HELPER_1(neon_qabs_s32, i32, i32)
-DEF_HELPER_1(neon_qneg_s8, i32, i32)
-DEF_HELPER_1(neon_qneg_s16, i32, i32)
-DEF_HELPER_1(neon_qneg_s32, i32, i32)
+DEF_HELPER_2(neon_qabs_s8, i32, env, i32)
+DEF_HELPER_2(neon_qabs_s16, i32, env, i32)
+DEF_HELPER_2(neon_qabs_s32, i32, env, i32)
+DEF_HELPER_2(neon_qneg_s8, i32, env, i32)
+DEF_HELPER_2(neon_qneg_s16, i32, env, i32)
+DEF_HELPER_2(neon_qneg_s32, i32, env, i32)
 
 DEF_HELPER_3(neon_min_f32, i32, i32, i32, ptr)
 DEF_HELPER_3(neon_max_f32, i32, i32, i32, ptr)
@@ -458,15 +458,15 @@ DEF_HELPER_3(iwmmxt_muladdswl, i64, i64, i32, i32)
 
 DEF_HELPER_2(set_teecr, void, env, i32)
 
-DEF_HELPER_2(neon_unzip8, void, i32, i32)
-DEF_HELPER_2(neon_unzip16, void, i32, i32)
-DEF_HELPER_2(neon_qunzip8, void, i32, i32)
-DEF_HELPER_2(neon_qunzip16, void, i32, i32)
-DEF_HELPER_2(neon_qunzip32, void, i32, i32)
-DEF_HELPER_2(neon_zip8, void, i32, i32)
-DEF_HELPER_2(neon_zip16, void, i32, i32)
-DEF_HELPER_2(neon_qzip8, void, i32, i32)
-DEF_HELPER_2(neon_qzip16, void, i32, i32)
-DEF_HELPER_2(neon_qzip32, void, i32, i32)
+DEF_HELPER_3(neon_unzip8, void, env, i32, i32)
+DEF_HELPER_3(neon_unzip16, void, env, i32, i32)
+DEF_HELPER_3(neon_qunzip8, void, env, i32, i32)
+DEF_HELPER_3(neon_qunzip16, void, env, i32, i32)
+DEF_HELPER_3(neon_qunzip32, void, env, i32, i32)
+DEF_HELPER_3(neon_zip8, void, env, i32, i32)
+DEF_HELPER_3(neon_zip16, void, env, i32, i32)
+DEF_HELPER_3(neon_qzip8, void, env, i32, i32)
+DEF_HELPER_3(neon_qzip16, void, env, i32, i32)
+DEF_HELPER_3(neon_qzip32, void, env, i32, i32)
 
 #include "def-helper.h"
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index fda4021..2830627 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -10,7 +10,7 @@
 #include <stdio.h>
 
 #include "cpu.h"
-#include "exec.h"
+#include "exec-all.h"
 #include "helper.h"
 
 #define SIGNBIT (uint32_t)0x80000000
@@ -113,6 +113,10 @@ NEON_TYPE1(u32, uint32_t)
 uint32_t HELPER(glue(neon_,name))(uint32_t arg1, uint32_t arg2) \
 NEON_VOP_BODY(vtype, n)
 
+#define NEON_VOP_ENV(name, vtype, n) \
+uint32_t HELPER(glue(neon_,name))(CPUState *env, uint32_t arg1, uint32_t arg2) \
+NEON_VOP_BODY(vtype, n)
+
 /* Pairwise operations.  */
 /* For 32-bit elements each segment only contains a single element, so
    the elementwise and pairwise operations are the same.  */
@@ -161,14 +165,14 @@ uint32_t HELPER(glue(neon_,name))(uint32_t arg) \
         dest = tmp; \
     }} while(0)
 #define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint8_t)
-NEON_VOP(qadd_u8, neon_u8, 4)
+NEON_VOP_ENV(qadd_u8, neon_u8, 4)
 #undef NEON_FN
 #define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint16_t)
-NEON_VOP(qadd_u16, neon_u16, 2)
+NEON_VOP_ENV(qadd_u16, neon_u16, 2)
 #undef NEON_FN
 #undef NEON_USAT
 
-uint32_t HELPER(neon_qadd_u32)(uint32_t a, uint32_t b)
+uint32_t HELPER(neon_qadd_u32)(CPUState *env, uint32_t a, uint32_t b)
 {
     uint32_t res = a + b;
     if (res < a) {
@@ -178,7 +182,7 @@ uint32_t HELPER(neon_qadd_u32)(uint32_t a, uint32_t b)
     return res;
 }
 
-uint64_t HELPER(neon_qadd_u64)(uint64_t src1, uint64_t src2)
+uint64_t HELPER(neon_qadd_u64)(CPUState *env, uint64_t src1, uint64_t src2)
 {
     uint64_t res;
 
@@ -203,14 +207,14 @@ uint64_t HELPER(neon_qadd_u64)(uint64_t src1, uint64_t src2)
     dest = tmp; \
     } while(0)
 #define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int8_t)
-NEON_VOP(qadd_s8, neon_s8, 4)
+NEON_VOP_ENV(qadd_s8, neon_s8, 4)
 #undef NEON_FN
 #define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int16_t)
-NEON_VOP(qadd_s16, neon_s16, 2)
+NEON_VOP_ENV(qadd_s16, neon_s16, 2)
 #undef NEON_FN
 #undef NEON_SSAT
 
-uint32_t HELPER(neon_qadd_s32)(uint32_t a, uint32_t b)
+uint32_t HELPER(neon_qadd_s32)(CPUState *env, uint32_t a, uint32_t b)
 {
     uint32_t res = a + b;
     if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) {
@@ -220,7 +224,7 @@ uint32_t HELPER(neon_qadd_s32)(uint32_t a, uint32_t b)
     return res;
 }
 
-uint64_t HELPER(neon_qadd_s64)(uint64_t src1, uint64_t src2)
+uint64_t HELPER(neon_qadd_s64)(CPUState *env, uint64_t src1, uint64_t src2)
 {
     uint64_t res;
 
@@ -241,14 +245,14 @@ uint64_t HELPER(neon_qadd_s64)(uint64_t src1, uint64_t src2)
         dest = tmp; \
     }} while(0)
 #define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint8_t)
-NEON_VOP(qsub_u8, neon_u8, 4)
+NEON_VOP_ENV(qsub_u8, neon_u8, 4)
 #undef NEON_FN
 #define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint16_t)
-NEON_VOP(qsub_u16, neon_u16, 2)
+NEON_VOP_ENV(qsub_u16, neon_u16, 2)
 #undef NEON_FN
 #undef NEON_USAT
 
-uint32_t HELPER(neon_qsub_u32)(uint32_t a, uint32_t b)
+uint32_t HELPER(neon_qsub_u32)(CPUState *env, uint32_t a, uint32_t b)
 {
     uint32_t res = a - b;
     if (res > a) {
@@ -258,7 +262,7 @@ uint32_t HELPER(neon_qsub_u32)(uint32_t a, uint32_t b)
     return res;
 }
 
-uint64_t HELPER(neon_qsub_u64)(uint64_t src1, uint64_t src2)
+uint64_t HELPER(neon_qsub_u64)(CPUState *env, uint64_t src1, uint64_t src2)
 {
     uint64_t res;
 
@@ -284,14 +288,14 @@ uint64_t HELPER(neon_qsub_u64)(uint64_t src1, uint64_t src2)
     dest = tmp; \
     } while(0)
 #define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int8_t)
-NEON_VOP(qsub_s8, neon_s8, 4)
+NEON_VOP_ENV(qsub_s8, neon_s8, 4)
 #undef NEON_FN
 #define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int16_t)
-NEON_VOP(qsub_s16, neon_s16, 2)
+NEON_VOP_ENV(qsub_s16, neon_s16, 2)
 #undef NEON_FN
 #undef NEON_SSAT
 
-uint32_t HELPER(neon_qsub_s32)(uint32_t a, uint32_t b)
+uint32_t HELPER(neon_qsub_s32)(CPUState *env, uint32_t a, uint32_t b)
 {
     uint32_t res = a - b;
     if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) {
@@ -301,7 +305,7 @@ uint32_t HELPER(neon_qsub_s32)(uint32_t a, uint32_t b)
     return res;
 }
 
-uint64_t HELPER(neon_qsub_s64)(uint64_t src1, uint64_t src2)
+uint64_t HELPER(neon_qsub_s64)(CPUState *env, uint64_t src1, uint64_t src2)
 {
     uint64_t res;
 
@@ -652,12 +656,12 @@ uint64_t HELPER(neon_rshl_u64)(uint64_t val, uint64_t shiftop)
             dest = ~0; \
         } \
     }} while (0)
-NEON_VOP(qshl_u8, neon_u8, 4)
-NEON_VOP(qshl_u16, neon_u16, 2)
-NEON_VOP(qshl_u32, neon_u32, 1)
+NEON_VOP_ENV(qshl_u8, neon_u8, 4)
+NEON_VOP_ENV(qshl_u16, neon_u16, 2)
+NEON_VOP_ENV(qshl_u32, neon_u32, 1)
 #undef NEON_FN
 
-uint64_t HELPER(neon_qshl_u64)(uint64_t val, uint64_t shiftop)
+uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
 {
     int8_t shift = (int8_t)shiftop;
     if (shift >= 64) {
@@ -707,12 +711,12 @@ uint64_t HELPER(neon_qshl_u64)(uint64_t val, uint64_t shiftop)
             } \
         } \
     }} while (0)
-NEON_VOP(qshl_s8, neon_s8, 4)
-NEON_VOP(qshl_s16, neon_s16, 2)
-NEON_VOP(qshl_s32, neon_s32, 1)
+NEON_VOP_ENV(qshl_s8, neon_s8, 4)
+NEON_VOP_ENV(qshl_s16, neon_s16, 2)
+NEON_VOP_ENV(qshl_s32, neon_s32, 1)
 #undef NEON_FN
 
-uint64_t HELPER(neon_qshl_s64)(uint64_t valop, uint64_t shiftop)
+uint64_t HELPER(neon_qshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
 {
     int8_t shift = (uint8_t)shiftop;
     int64_t val = valop;
@@ -762,26 +766,26 @@ uint64_t HELPER(neon_qshl_s64)(uint64_t valop, uint64_t shiftop)
             } \
         } \
     }} while (0)
-NEON_VOP(qshlu_s8, neon_u8, 4)
-NEON_VOP(qshlu_s16, neon_u16, 2)
+NEON_VOP_ENV(qshlu_s8, neon_u8, 4)
+NEON_VOP_ENV(qshlu_s16, neon_u16, 2)
 #undef NEON_FN
 
-uint32_t HELPER(neon_qshlu_s32)(uint32_t valop, uint32_t shiftop)
+uint32_t HELPER(neon_qshlu_s32)(CPUState *env, uint32_t valop, uint32_t shiftop)
 {
     if ((int32_t)valop < 0) {
         SET_QC();
         return 0;
     }
-    return helper_neon_qshl_u32(valop, shiftop);
+    return helper_neon_qshl_u32(env, valop, shiftop);
 }
 
-uint64_t HELPER(neon_qshlu_s64)(uint64_t valop, uint64_t shiftop)
+uint64_t HELPER(neon_qshlu_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
 {
     if ((int64_t)valop < 0) {
         SET_QC();
         return 0;
     }
-    return helper_neon_qshl_u64(valop, shiftop);
+    return helper_neon_qshl_u64(env, valop, shiftop);
 }
 
 /* FIXME: This is wrong.  */
@@ -808,13 +812,13 @@ uint64_t HELPER(neon_qshlu_s64)(uint64_t valop, uint64_t shiftop)
             dest = ~0; \
         } \
     }} while (0)
-NEON_VOP(qrshl_u8, neon_u8, 4)
-NEON_VOP(qrshl_u16, neon_u16, 2)
+NEON_VOP_ENV(qrshl_u8, neon_u8, 4)
+NEON_VOP_ENV(qrshl_u16, neon_u16, 2)
 #undef NEON_FN
 
 /* The addition of the rounding constant may overflow, so we use an
  * intermediate 64 bits accumulator.  */
-uint32_t HELPER(neon_qrshl_u32)(uint32_t val, uint32_t shiftop)
+uint32_t HELPER(neon_qrshl_u32)(CPUState *env, uint32_t val, uint32_t shiftop)
 {
     uint32_t dest;
     int8_t shift = (int8_t)shiftop;
@@ -844,7 +848,7 @@ uint32_t HELPER(neon_qrshl_u32)(uint32_t val, uint32_t shiftop)
 
 /* Handling addition overflow with 64 bits inputs values is more
  * tricky than with 32 bits values.  */
-uint64_t HELPER(neon_qrshl_u64)(uint64_t val, uint64_t shiftop)
+uint64_t HELPER(neon_qrshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
 {
     int8_t shift = (int8_t)shiftop;
     if (shift >= 64) {
@@ -905,13 +909,13 @@ uint64_t HELPER(neon_qrshl_u64)(uint64_t val, uint64_t shiftop)
             } \
         } \
     }} while (0)
-NEON_VOP(qrshl_s8, neon_s8, 4)
-NEON_VOP(qrshl_s16, neon_s16, 2)
+NEON_VOP_ENV(qrshl_s8, neon_s8, 4)
+NEON_VOP_ENV(qrshl_s16, neon_s16, 2)
 #undef NEON_FN
 
 /* The addition of the rounding constant may overflow, so we use an
  * intermediate 64 bits accumulator.  */
-uint32_t HELPER(neon_qrshl_s32)(uint32_t valop, uint32_t shiftop)
+uint32_t HELPER(neon_qrshl_s32)(CPUState *env, uint32_t valop, uint32_t shiftop)
 {
     int32_t dest;
     int32_t val = (int32_t)valop;
@@ -940,7 +944,7 @@ uint32_t HELPER(neon_qrshl_s32)(uint32_t valop, uint32_t shiftop)
 
 /* Handling addition overflow with 64 bits inputs values is more
  * tricky than with 32 bits values.  */
-uint64_t HELPER(neon_qrshl_s64)(uint64_t valop, uint64_t shiftop)
+uint64_t HELPER(neon_qrshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
 {
     int8_t shift = (uint8_t)shiftop;
     int64_t val = valop;
@@ -1149,10 +1153,10 @@ uint32_t HELPER(neon_cnt_u8)(uint32_t x)
     dest = tmp >> 16; \
     } while(0)
 #define NEON_FN(dest, src1, src2) NEON_QDMULH16(dest, src1, src2, 0)
-NEON_VOP(qdmulh_s16, neon_s16, 2)
+NEON_VOP_ENV(qdmulh_s16, neon_s16, 2)
 #undef NEON_FN
 #define NEON_FN(dest, src1, src2) NEON_QDMULH16(dest, src1, src2, 1)
-NEON_VOP(qrdmulh_s16, neon_s16, 2)
+NEON_VOP_ENV(qrdmulh_s16, neon_s16, 2)
 #undef NEON_FN
 #undef NEON_QDMULH16
 
@@ -1175,10 +1179,10 @@ NEON_VOP(qrdmulh_s16, neon_s16, 2)
     dest = tmp >> 32; \
     } while(0)
 #define NEON_FN(dest, src1, src2) NEON_QDMULH32(dest, src1, src2, 0)
-NEON_VOP(qdmulh_s32, neon_s32, 1)
+NEON_VOP_ENV(qdmulh_s32, neon_s32, 1)
 #undef NEON_FN
 #define NEON_FN(dest, src1, src2) NEON_QDMULH32(dest, src1, src2, 1)
-NEON_VOP(qrdmulh_s32, neon_s32, 1)
+NEON_VOP_ENV(qrdmulh_s32, neon_s32, 1)
 #undef NEON_FN
 #undef NEON_QDMULH32
 
@@ -1219,7 +1223,7 @@ uint32_t HELPER(neon_narrow_round_high_u16)(uint64_t x)
     return ((x >> 16) & 0xffff) | ((x >> 32) & 0xffff0000);
 }
 
-uint32_t HELPER(neon_unarrow_sat8)(uint64_t x)
+uint32_t HELPER(neon_unarrow_sat8)(CPUState *env, uint64_t x)
 {
     uint16_t s;
     uint8_t d;
@@ -1246,7 +1250,7 @@ uint32_t HELPER(neon_unarrow_sat8)(uint64_t x)
     return res;
 }
 
-uint32_t HELPER(neon_narrow_sat_u8)(uint64_t x)
+uint32_t HELPER(neon_narrow_sat_u8)(CPUState *env, uint64_t x)
 {
     uint16_t s;
     uint8_t d;
@@ -1269,7 +1273,7 @@ uint32_t HELPER(neon_narrow_sat_u8)(uint64_t x)
     return res;
 }
 
-uint32_t HELPER(neon_narrow_sat_s8)(uint64_t x)
+uint32_t HELPER(neon_narrow_sat_s8)(CPUState *env, uint64_t x)
 {
     int16_t s;
     uint8_t d;
@@ -1292,7 +1296,7 @@ uint32_t HELPER(neon_narrow_sat_s8)(uint64_t x)
     return res;
 }
 
-uint32_t HELPER(neon_unarrow_sat16)(uint64_t x)
+uint32_t HELPER(neon_unarrow_sat16)(CPUState *env, uint64_t x)
 {
     uint32_t high;
     uint32_t low;
@@ -1315,7 +1319,7 @@ uint32_t HELPER(neon_unarrow_sat16)(uint64_t x)
     return low | (high << 16);
 }
 
-uint32_t HELPER(neon_narrow_sat_u16)(uint64_t x)
+uint32_t HELPER(neon_narrow_sat_u16)(CPUState *env, uint64_t x)
 {
     uint32_t high;
     uint32_t low;
@@ -1332,7 +1336,7 @@ uint32_t HELPER(neon_narrow_sat_u16)(uint64_t x)
     return low | (high << 16);
 }
 
-uint32_t HELPER(neon_narrow_sat_s16)(uint64_t x)
+uint32_t HELPER(neon_narrow_sat_s16)(CPUState *env, uint64_t x)
 {
     int32_t low;
     int32_t high;
@@ -1349,7 +1353,7 @@ uint32_t HELPER(neon_narrow_sat_s16)(uint64_t x)
     return (uint16_t)low | (high << 16);
 }
 
-uint32_t HELPER(neon_unarrow_sat32)(uint64_t x)
+uint32_t HELPER(neon_unarrow_sat32)(CPUState *env, uint64_t x)
 {
     if (x & 0x8000000000000000ull) {
         SET_QC();
@@ -1362,7 +1366,7 @@ uint32_t HELPER(neon_unarrow_sat32)(uint64_t x)
     return x;
 }
 
-uint32_t HELPER(neon_narrow_sat_u32)(uint64_t x)
+uint32_t HELPER(neon_narrow_sat_u32)(CPUState *env, uint64_t x)
 {
     if (x > 0xffffffffu) {
         SET_QC();
@@ -1371,7 +1375,7 @@ uint32_t HELPER(neon_narrow_sat_u32)(uint64_t x)
     return x;
 }
 
-uint32_t HELPER(neon_narrow_sat_s32)(uint64_t x)
+uint32_t HELPER(neon_narrow_sat_s32)(CPUState *env, uint64_t x)
 {
     if ((int64_t)x != (int32_t)x) {
         SET_QC();
@@ -1478,7 +1482,7 @@ uint64_t HELPER(neon_subl_u32)(uint64_t a, uint64_t b)
     return (a - b) ^ mask;
 }
 
-uint64_t HELPER(neon_addl_saturate_s32)(uint64_t a, uint64_t b)
+uint64_t HELPER(neon_addl_saturate_s32)(CPUState *env, uint64_t a, uint64_t b)
 {
     uint32_t x, y;
     uint32_t low, high;
@@ -1500,7 +1504,7 @@ uint64_t HELPER(neon_addl_saturate_s32)(uint64_t a, uint64_t b)
     return low | ((uint64_t)high << 32);
 }
 
-uint64_t HELPER(neon_addl_saturate_s64)(uint64_t a, uint64_t b)
+uint64_t HELPER(neon_addl_saturate_s64)(CPUState *env, uint64_t a, uint64_t b)
 {
     uint64_t result;
 
@@ -1676,7 +1680,7 @@ uint64_t HELPER(neon_negl_u64)(uint64_t x)
     } else if (x < 0) { \
         x = -x; \
     }} while (0)
-uint32_t HELPER(neon_qabs_s8)(uint32_t x)
+uint32_t HELPER(neon_qabs_s8)(CPUState *env, uint32_t x)
 {
     neon_s8 vec;
     NEON_UNPACK(neon_s8, vec, x);
@@ -1696,7 +1700,7 @@ uint32_t HELPER(neon_qabs_s8)(uint32_t x)
     } else { \
         x = -x; \
     }} while (0)
-uint32_t HELPER(neon_qneg_s8)(uint32_t x)
+uint32_t HELPER(neon_qneg_s8)(CPUState *env, uint32_t x)
 {
     neon_s8 vec;
     NEON_UNPACK(neon_s8, vec, x);
@@ -1716,7 +1720,7 @@ uint32_t HELPER(neon_qneg_s8)(uint32_t x)
     } else if (x < 0) { \
         x = -x; \
     }} while (0)
-uint32_t HELPER(neon_qabs_s16)(uint32_t x)
+uint32_t HELPER(neon_qabs_s16)(CPUState *env, uint32_t x)
 {
     neon_s16 vec;
     NEON_UNPACK(neon_s16, vec, x);
@@ -1734,7 +1738,7 @@ uint32_t HELPER(neon_qabs_s16)(uint32_t x)
     } else { \
         x = -x; \
     }} while (0)
-uint32_t HELPER(neon_qneg_s16)(uint32_t x)
+uint32_t HELPER(neon_qneg_s16)(CPUState *env, uint32_t x)
 {
     neon_s16 vec;
     NEON_UNPACK(neon_s16, vec, x);
@@ -1745,7 +1749,7 @@ uint32_t HELPER(neon_qneg_s16)(uint32_t x)
 }
 #undef DO_QNEG16
 
-uint32_t HELPER(neon_qabs_s32)(uint32_t x)
+uint32_t HELPER(neon_qabs_s32)(CPUState *env, uint32_t x)
 {
     if (x == SIGNBIT) {
         SET_QC();
@@ -1756,7 +1760,7 @@ uint32_t HELPER(neon_qabs_s32)(uint32_t x)
     return x;
 }
 
-uint32_t HELPER(neon_qneg_s32)(uint32_t x)
+uint32_t HELPER(neon_qneg_s32)(CPUState *env, uint32_t x)
 {
     if (x == SIGNBIT) {
         SET_QC();
@@ -1828,7 +1832,7 @@ uint32_t HELPER(neon_acgt_f32)(uint32_t a, uint32_t b, void *fpstp)
 
 #define ELEM(V, N, SIZE) (((V) >> ((N) * (SIZE))) & ((1ull << (SIZE)) - 1))
 
-void HELPER(neon_qunzip8)(uint32_t rd, uint32_t rm)
+void HELPER(neon_qunzip8)(CPUState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1856,7 +1860,7 @@ void HELPER(neon_qunzip8)(uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_qunzip16)(uint32_t rd, uint32_t rm)
+void HELPER(neon_qunzip16)(CPUState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1876,7 +1880,7 @@ void HELPER(neon_qunzip16)(uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_qunzip32)(uint32_t rd, uint32_t rm)
+void HELPER(neon_qunzip32)(CPUState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1892,7 +1896,7 @@ void HELPER(neon_qunzip32)(uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_unzip8)(uint32_t rd, uint32_t rm)
+void HELPER(neon_unzip8)(CPUState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm = float64_val(env->vfp.regs[rm]);
     uint64_t zd = float64_val(env->vfp.regs[rd]);
@@ -1908,7 +1912,7 @@ void HELPER(neon_unzip8)(uint32_t rd, uint32_t rm)
     env->vfp.regs[rd] = make_float64(d0);
 }
 
-void HELPER(neon_unzip16)(uint32_t rd, uint32_t rm)
+void HELPER(neon_unzip16)(CPUState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm = float64_val(env->vfp.regs[rm]);
     uint64_t zd = float64_val(env->vfp.regs[rd]);
@@ -1920,7 +1924,7 @@ void HELPER(neon_unzip16)(uint32_t rd, uint32_t rm)
     env->vfp.regs[rd] = make_float64(d0);
 }
 
-void HELPER(neon_qzip8)(uint32_t rd, uint32_t rm)
+void HELPER(neon_qzip8)(CPUState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1948,7 +1952,7 @@ void HELPER(neon_qzip8)(uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_qzip16)(uint32_t rd, uint32_t rm)
+void HELPER(neon_qzip16)(CPUState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1968,7 +1972,7 @@ void HELPER(neon_qzip16)(uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_qzip32)(uint32_t rd, uint32_t rm)
+void HELPER(neon_qzip32)(CPUState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1984,7 +1988,7 @@ void HELPER(neon_qzip32)(uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_zip8)(uint32_t rd, uint32_t rm)
+void HELPER(neon_zip8)(CPUState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm = float64_val(env->vfp.regs[rm]);
     uint64_t zd = float64_val(env->vfp.regs[rd]);
@@ -2000,7 +2004,7 @@ void HELPER(neon_zip8)(uint32_t rd, uint32_t rm)
     env->vfp.regs[rd] = make_float64(d0);
 }
 
-void HELPER(neon_zip16)(uint32_t rd, uint32_t rm)
+void HELPER(neon_zip16)(CPUState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm = float64_val(env->vfp.regs[rm]);
     uint64_t zd = float64_val(env->vfp.regs[rd]);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 27d9887..0273deb 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3711,13 +3711,13 @@ static int gen_neon_unzip(int rd, int rm, int size, int q)
     if (q) {
         switch (size) {
         case 0:
-            gen_helper_neon_qunzip8(tmp, tmp2);
+            gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
             break;
         case 1:
-            gen_helper_neon_qunzip16(tmp, tmp2);
+            gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
             break;
         case 2:
-            gen_helper_neon_qunzip32(tmp, tmp2);
+            gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
             break;
         default:
             abort();
@@ -3725,10 +3725,10 @@ static int gen_neon_unzip(int rd, int rm, int size, int q)
     } else {
         switch (size) {
         case 0:
-            gen_helper_neon_unzip8(tmp, tmp2);
+            gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
             break;
         case 1:
-            gen_helper_neon_unzip16(tmp, tmp2);
+            gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
             break;
         default:
             abort();
@@ -3750,13 +3750,13 @@ static int gen_neon_zip(int rd, int rm, int size, int q)
     if (q) {
         switch (size) {
         case 0:
-            gen_helper_neon_qzip8(tmp, tmp2);
+            gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
             break;
         case 1:
-            gen_helper_neon_qzip16(tmp, tmp2);
+            gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
             break;
         case 2:
-            gen_helper_neon_qzip32(tmp, tmp2);
+            gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
             break;
         default:
             abort();
@@ -3764,10 +3764,10 @@ static int gen_neon_zip(int rd, int rm, int size, int q)
     } else {
         switch (size) {
         case 0:
-            gen_helper_neon_zip8(tmp, tmp2);
+            gen_helper_neon_zip8(cpu_env, tmp, tmp2);
             break;
         case 1:
-            gen_helper_neon_zip16(tmp, tmp2);
+            gen_helper_neon_zip16(cpu_env, tmp, tmp2);
             break;
         default:
             abort();
@@ -4167,9 +4167,9 @@ static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
 {
     switch (size) {
-    case 0: gen_helper_neon_narrow_sat_s8(dest, src); break;
-    case 1: gen_helper_neon_narrow_sat_s16(dest, src); break;
-    case 2: gen_helper_neon_narrow_sat_s32(dest, src); break;
+    case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
+    case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
+    case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
     default: abort();
     }
 }
@@ -4177,9 +4177,9 @@ static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
 {
     switch (size) {
-    case 0: gen_helper_neon_narrow_sat_u8(dest, src); break;
-    case 1: gen_helper_neon_narrow_sat_u16(dest, src); break;
-    case 2: gen_helper_neon_narrow_sat_u32(dest, src); break;
+    case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
+    case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
+    case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
     default: abort();
     }
 }
@@ -4187,9 +4187,9 @@ static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
 static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src)
 {
     switch (size) {
-    case 0: gen_helper_neon_unarrow_sat8(dest, src); break;
-    case 1: gen_helper_neon_unarrow_sat16(dest, src); break;
-    case 2: gen_helper_neon_unarrow_sat32(dest, src); break;
+    case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
+    case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
+    case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
     default: abort();
     }
 }
@@ -4281,8 +4281,8 @@ static inline void gen_neon_negl(TCGv_i64 var, int size)
 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
 {
     switch (size) {
-    case 1: gen_helper_neon_addl_saturate_s32(op0, op0, op1); break;
-    case 2: gen_helper_neon_addl_saturate_s64(op0, op0, op1); break;
+    case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
+    case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
     default: abort();
     }
 }
@@ -4558,16 +4558,20 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 switch (op) {
                 case NEON_3R_VQADD:
                     if (u) {
-                        gen_helper_neon_qadd_u64(cpu_V0, cpu_V0, cpu_V1);
+                        gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
+                                                 cpu_V0, cpu_V1);
                     } else {
-                        gen_helper_neon_qadd_s64(cpu_V0, cpu_V0, cpu_V1);
+                        gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
+                                                 cpu_V0, cpu_V1);
                     }
                     break;
                 case NEON_3R_VQSUB:
                     if (u) {
-                        gen_helper_neon_qsub_u64(cpu_V0, cpu_V0, cpu_V1);
+                        gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
+                                                 cpu_V0, cpu_V1);
                     } else {
-                        gen_helper_neon_qsub_s64(cpu_V0, cpu_V0, cpu_V1);
+                        gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
+                                                 cpu_V0, cpu_V1);
                     }
                     break;
                 case NEON_3R_VSHL:
@@ -4579,9 +4583,11 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     break;
                 case NEON_3R_VQSHL:
                     if (u) {
-                        gen_helper_neon_qshl_u64(cpu_V0, cpu_V1, cpu_V0);
+                        gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
+                                                 cpu_V1, cpu_V0);
                     } else {
-                        gen_helper_neon_qshl_s64(cpu_V0, cpu_V1, cpu_V0);
+                        gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
+                                                 cpu_V1, cpu_V0);
                     }
                     break;
                 case NEON_3R_VRSHL:
@@ -4593,9 +4599,11 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     break;
                 case NEON_3R_VQRSHL:
                     if (u) {
-                        gen_helper_neon_qrshl_u64(cpu_V0, cpu_V1, cpu_V0);
+                        gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
+                                                  cpu_V1, cpu_V0);
                     } else {
-                        gen_helper_neon_qrshl_s64(cpu_V0, cpu_V1, cpu_V0);
+                        gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
+                                                  cpu_V1, cpu_V0);
                     }
                     break;
                 case NEON_3R_VADD_VSUB:
@@ -4693,7 +4701,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             GEN_NEON_INTEGER_OP(hadd);
             break;
         case NEON_3R_VQADD:
-            GEN_NEON_INTEGER_OP(qadd);
+            GEN_NEON_INTEGER_OP_ENV(qadd);
             break;
         case NEON_3R_VRHADD:
             GEN_NEON_INTEGER_OP(rhadd);
@@ -4736,7 +4744,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             GEN_NEON_INTEGER_OP(hsub);
             break;
         case NEON_3R_VQSUB:
-            GEN_NEON_INTEGER_OP(qsub);
+            GEN_NEON_INTEGER_OP_ENV(qsub);
             break;
         case NEON_3R_VCGT:
             GEN_NEON_INTEGER_OP(cgt);
@@ -4748,13 +4756,13 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             GEN_NEON_INTEGER_OP(shl);
             break;
         case NEON_3R_VQSHL:
-            GEN_NEON_INTEGER_OP(qshl);
+            GEN_NEON_INTEGER_OP_ENV(qshl);
             break;
         case NEON_3R_VRSHL:
             GEN_NEON_INTEGER_OP(rshl);
             break;
         case NEON_3R_VQRSHL:
-            GEN_NEON_INTEGER_OP(qrshl);
+            GEN_NEON_INTEGER_OP_ENV(qrshl);
             break;
         case NEON_3R_VMAX:
             GEN_NEON_INTEGER_OP(max);
@@ -4836,14 +4844,22 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
         case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high.  */
             if (!u) { /* VQDMULH */
                 switch (size) {
-                case 1: gen_helper_neon_qdmulh_s16(tmp, tmp, tmp2); break;
-                case 2: gen_helper_neon_qdmulh_s32(tmp, tmp, tmp2); break;
+                case 1:
+                    gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
+                    break;
+                case 2:
+                    gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
+                    break;
                 default: abort();
                 }
             } else { /* VQRDMULH */
                 switch (size) {
-                case 1: gen_helper_neon_qrdmulh_s16(tmp, tmp, tmp2); break;
-                case 2: gen_helper_neon_qrdmulh_s32(tmp, tmp, tmp2); break;
+                case 1:
+                    gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
+                    break;
+                case 2:
+                    gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
+                    break;
                 default: abort();
                 }
             }
@@ -5035,14 +5051,15 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
                             break;
                         case 6: /* VQSHLU */
-                            gen_helper_neon_qshlu_s64(cpu_V0, cpu_V0, cpu_V1);
+                            gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
+                                                      cpu_V0, cpu_V1);
                             break;
                         case 7: /* VQSHL */
                             if (u) {
-                                gen_helper_neon_qshl_u64(cpu_V0,
+                                gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
                                                          cpu_V0, cpu_V1);
                             } else {
-                                gen_helper_neon_qshl_s64(cpu_V0,
+                                gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
                                                          cpu_V0, cpu_V1);
                             }
                             break;
@@ -5094,20 +5111,23 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         case 6: /* VQSHLU */
                             switch (size) {
                             case 0:
-                                gen_helper_neon_qshlu_s8(tmp, tmp, tmp2);
+                                gen_helper_neon_qshlu_s8(tmp, cpu_env,
+                                                         tmp, tmp2);
                                 break;
                             case 1:
-                                gen_helper_neon_qshlu_s16(tmp, tmp, tmp2);
+                                gen_helper_neon_qshlu_s16(tmp, cpu_env,
+                                                          tmp, tmp2);
                                 break;
                             case 2:
-                                gen_helper_neon_qshlu_s32(tmp, tmp, tmp2);
+                                gen_helper_neon_qshlu_s32(tmp, cpu_env,
+                                                          tmp, tmp2);
                                 break;
                             default:
                                 abort();
                             }
                             break;
                         case 7: /* VQSHL */
-                            GEN_NEON_INTEGER_OP(qshl);
+                            GEN_NEON_INTEGER_OP_ENV(qshl);
                             break;
                         }
                         tcg_temp_free_i32(tmp2);
@@ -5616,15 +5636,15 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         tmp2 = neon_load_reg(rn, pass);
                         if (op == 12) {
                             if (size == 1) {
-                                gen_helper_neon_qdmulh_s16(tmp, tmp, tmp2);
+                                gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
                             } else {
-                                gen_helper_neon_qdmulh_s32(tmp, tmp, tmp2);
+                                gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
                             }
                         } else if (op == 13) {
                             if (size == 1) {
-                                gen_helper_neon_qrdmulh_s16(tmp, tmp, tmp2);
+                                gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
                             } else {
-                                gen_helper_neon_qrdmulh_s32(tmp, tmp, tmp2);
+                                gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
                             }
                         } else if (op & 1) {
                             TCGv_ptr fpstatus = get_fpstatus_ptr(1);
@@ -5996,17 +6016,29 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             break;
                         case NEON_2RM_VQABS:
                             switch (size) {
-                            case 0: gen_helper_neon_qabs_s8(tmp, tmp); break;
-                            case 1: gen_helper_neon_qabs_s16(tmp, tmp); break;
-                            case 2: gen_helper_neon_qabs_s32(tmp, tmp); break;
+                            case 0:
+                                gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
+                                break;
+                            case 1:
+                                gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
+                                break;
+                            case 2:
+                                gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
+                                break;
                             default: abort();
                             }
                             break;
                         case NEON_2RM_VQNEG:
                             switch (size) {
-                            case 0: gen_helper_neon_qneg_s8(tmp, tmp); break;
-                            case 1: gen_helper_neon_qneg_s16(tmp, tmp); break;
-                            case 2: gen_helper_neon_qneg_s32(tmp, tmp); break;
+                            case 0:
+                                gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
+                                break;
+                            case 1:
+                                gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
+                                break;
+                            case 2:
+                                gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
+                                break;
                             default: abort();
                             }
                             break;
commit aa47cfdd178d8ea96b6e2f550742ddbb445fdacb
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed May 25 13:49:19 2011 +0000

    target-arm: Pass fp status pointer explicitly to neon fp helpers
    
    Make the Neon helpers for various floating point operations take an
    explicit pointer to the float_status they use, so they don't rely on
    the global environment pointer any more. This also allows us to drop
    the mul/sub/add helpers completely and just use the vfp versions.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.h b/target-arm/helper.h
index 40b4677..c29efd5 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -350,17 +350,14 @@ DEF_HELPER_1(neon_qneg_s8, i32, i32)
 DEF_HELPER_1(neon_qneg_s16, i32, i32)
 DEF_HELPER_1(neon_qneg_s32, i32, i32)
 
-DEF_HELPER_2(neon_min_f32, i32, i32, i32)
-DEF_HELPER_2(neon_max_f32, i32, i32, i32)
-DEF_HELPER_2(neon_abd_f32, i32, i32, i32)
-DEF_HELPER_2(neon_add_f32, i32, i32, i32)
-DEF_HELPER_2(neon_sub_f32, i32, i32, i32)
-DEF_HELPER_2(neon_mul_f32, i32, i32, i32)
-DEF_HELPER_2(neon_ceq_f32, i32, i32, i32)
-DEF_HELPER_2(neon_cge_f32, i32, i32, i32)
-DEF_HELPER_2(neon_cgt_f32, i32, i32, i32)
-DEF_HELPER_2(neon_acge_f32, i32, i32, i32)
-DEF_HELPER_2(neon_acgt_f32, i32, i32, i32)
+DEF_HELPER_3(neon_min_f32, i32, i32, i32, ptr)
+DEF_HELPER_3(neon_max_f32, i32, i32, i32, ptr)
+DEF_HELPER_3(neon_abd_f32, i32, i32, i32, ptr)
+DEF_HELPER_3(neon_ceq_f32, i32, i32, i32, ptr)
+DEF_HELPER_3(neon_cge_f32, i32, i32, i32, ptr)
+DEF_HELPER_3(neon_cgt_f32, i32, i32, i32, ptr)
+DEF_HELPER_3(neon_acge_f32, i32, i32, i32, ptr)
+DEF_HELPER_3(neon_acgt_f32, i32, i32, i32, ptr)
 
 /* iwmmxt_helper.c */
 DEF_HELPER_2(iwmmxt_maddsq, i64, i64, i64)
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 9165519..fda4021 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -18,8 +18,6 @@
 
 #define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] = CPSR_Q
 
-#define NFS (&env->vfp.standard_fp_status)
-
 #define NEON_TYPE1(name, type) \
 typedef struct \
 { \
@@ -1770,69 +1768,62 @@ uint32_t HELPER(neon_qneg_s32)(uint32_t x)
 }
 
 /* NEON Float helpers.  */
-uint32_t HELPER(neon_min_f32)(uint32_t a, uint32_t b)
+uint32_t HELPER(neon_min_f32)(uint32_t a, uint32_t b, void *fpstp)
 {
-    return float32_val(float32_min(make_float32(a), make_float32(b), NFS));
+    float_status *fpst = fpstp;
+    return float32_val(float32_min(make_float32(a), make_float32(b), fpst));
 }
 
-uint32_t HELPER(neon_max_f32)(uint32_t a, uint32_t b)
+uint32_t HELPER(neon_max_f32)(uint32_t a, uint32_t b, void *fpstp)
 {
-    return float32_val(float32_max(make_float32(a), make_float32(b), NFS));
+    float_status *fpst = fpstp;
+    return float32_val(float32_max(make_float32(a), make_float32(b), fpst));
 }
 
-uint32_t HELPER(neon_abd_f32)(uint32_t a, uint32_t b)
+uint32_t HELPER(neon_abd_f32)(uint32_t a, uint32_t b, void *fpstp)
 {
+    float_status *fpst = fpstp;
     float32 f0 = make_float32(a);
     float32 f1 = make_float32(b);
-    return float32_val(float32_abs(float32_sub(f0, f1, NFS)));
-}
-
-uint32_t HELPER(neon_add_f32)(uint32_t a, uint32_t b)
-{
-    return float32_val(float32_add(make_float32(a), make_float32(b), NFS));
-}
-
-uint32_t HELPER(neon_sub_f32)(uint32_t a, uint32_t b)
-{
-    return float32_val(float32_sub(make_float32(a), make_float32(b), NFS));
-}
-
-uint32_t HELPER(neon_mul_f32)(uint32_t a, uint32_t b)
-{
-    return float32_val(float32_mul(make_float32(a), make_float32(b), NFS));
+    return float32_val(float32_abs(float32_sub(f0, f1, fpst)));
 }
 
 /* Floating point comparisons produce an integer result.
  * Note that EQ doesn't signal InvalidOp for QNaNs but GE and GT do.
  * Softfloat routines return 0/1, which we convert to the 0/-1 Neon requires.
  */
-uint32_t HELPER(neon_ceq_f32)(uint32_t a, uint32_t b)
+uint32_t HELPER(neon_ceq_f32)(uint32_t a, uint32_t b, void *fpstp)
 {
-    return -float32_eq_quiet(make_float32(a), make_float32(b), NFS);
+    float_status *fpst = fpstp;
+    return -float32_eq_quiet(make_float32(a), make_float32(b), fpst);
 }
 
-uint32_t HELPER(neon_cge_f32)(uint32_t a, uint32_t b)
+uint32_t HELPER(neon_cge_f32)(uint32_t a, uint32_t b, void *fpstp)
 {
-    return -float32_le(make_float32(b), make_float32(a), NFS);
+    float_status *fpst = fpstp;
+    return -float32_le(make_float32(b), make_float32(a), fpst);
 }
 
-uint32_t HELPER(neon_cgt_f32)(uint32_t a, uint32_t b)
+uint32_t HELPER(neon_cgt_f32)(uint32_t a, uint32_t b, void *fpstp)
 {
-    return -float32_lt(make_float32(b), make_float32(a), NFS);
+    float_status *fpst = fpstp;
+    return -float32_lt(make_float32(b), make_float32(a), fpst);
 }
 
-uint32_t HELPER(neon_acge_f32)(uint32_t a, uint32_t b)
+uint32_t HELPER(neon_acge_f32)(uint32_t a, uint32_t b, void *fpstp)
 {
+    float_status *fpst = fpstp;
     float32 f0 = float32_abs(make_float32(a));
     float32 f1 = float32_abs(make_float32(b));
-    return -float32_le(f1, f0, NFS);
+    return -float32_le(f1, f0, fpst);
 }
 
-uint32_t HELPER(neon_acgt_f32)(uint32_t a, uint32_t b)
+uint32_t HELPER(neon_acgt_f32)(uint32_t a, uint32_t b, void *fpstp)
 {
+    float_status *fpst = fpstp;
     float32 f0 = float32_abs(make_float32(a));
     float32 f1 = float32_abs(make_float32(b));
-    return -float32_lt(f1, f0, NFS);
+    return -float32_lt(f1, f0, fpst);
 }
 
 #define ELEM(V, N, SIZE) (((V) >> ((N) * (SIZE))) & ((1ull << (SIZE)) - 1))
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 9ed747f..27d9887 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4857,57 +4857,78 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             }
             break;
         case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
+        {
+            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
             switch ((u << 2) | size) {
             case 0: /* VADD */
-                gen_helper_neon_add_f32(tmp, tmp, tmp2);
+            case 4: /* VPADD */
+                gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
                 break;
             case 2: /* VSUB */
-                gen_helper_neon_sub_f32(tmp, tmp, tmp2);
-                break;
-            case 4: /* VPADD */
-                gen_helper_neon_add_f32(tmp, tmp, tmp2);
+                gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
                 break;
             case 6: /* VABD */
-                gen_helper_neon_abd_f32(tmp, tmp, tmp2);
+                gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
                 break;
             default:
                 abort();
             }
+            tcg_temp_free_ptr(fpstatus);
             break;
+        }
         case NEON_3R_FLOAT_MULTIPLY:
-            gen_helper_neon_mul_f32(tmp, tmp, tmp2);
+        {
+            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+            gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
             if (!u) {
                 tcg_temp_free_i32(tmp2);
                 tmp2 = neon_load_reg(rd, pass);
                 if (size == 0) {
-                    gen_helper_neon_add_f32(tmp, tmp, tmp2);
+                    gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
                 } else {
-                    gen_helper_neon_sub_f32(tmp, tmp2, tmp);
+                    gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
                 }
             }
+            tcg_temp_free_ptr(fpstatus);
             break;
+        }
         case NEON_3R_FLOAT_CMP:
+        {
+            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
             if (!u) {
-                gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
+                gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
             } else {
-                if (size == 0)
-                    gen_helper_neon_cge_f32(tmp, tmp, tmp2);
-                else
-                    gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
+                if (size == 0) {
+                    gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
+                } else {
+                    gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
+                }
             }
+            tcg_temp_free_ptr(fpstatus);
             break;
+        }
         case NEON_3R_FLOAT_ACMP:
-            if (size == 0)
-                gen_helper_neon_acge_f32(tmp, tmp, tmp2);
-            else
-                gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
+        {
+            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+            if (size == 0) {
+                gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
+            } else {
+                gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
+            }
+            tcg_temp_free_ptr(fpstatus);
             break;
+        }
         case NEON_3R_FLOAT_MINMAX:
-            if (size == 0)
-                gen_helper_neon_max_f32(tmp, tmp, tmp2);
-            else
-                gen_helper_neon_min_f32(tmp, tmp, tmp2);
+        {
+            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+            if (size == 0) {
+                gen_helper_neon_max_f32(tmp, tmp, tmp2, fpstatus);
+            } else {
+                gen_helper_neon_min_f32(tmp, tmp, tmp2, fpstatus);
+            }
+            tcg_temp_free_ptr(fpstatus);
             break;
+        }
         case NEON_3R_VRECPS_VRSQRTS:
             if (size == 0)
                 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
@@ -5606,7 +5627,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                                 gen_helper_neon_qrdmulh_s32(tmp, tmp, tmp2);
                             }
                         } else if (op & 1) {
-                            gen_helper_neon_mul_f32(tmp, tmp, tmp2);
+                            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+                            gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
+                            tcg_temp_free_ptr(fpstatus);
                         } else {
                             switch (size) {
                             case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
@@ -5624,14 +5647,22 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                                 gen_neon_add(size, tmp, tmp2);
                                 break;
                             case 1:
-                                gen_helper_neon_add_f32(tmp, tmp, tmp2);
+                            {
+                                TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+                                gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
+                                tcg_temp_free_ptr(fpstatus);
                                 break;
+                            }
                             case 4:
                                 gen_neon_rsb(size, tmp, tmp2);
                                 break;
                             case 5:
-                                gen_helper_neon_sub_f32(tmp, tmp2, tmp);
+                            {
+                                TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+                                gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
+                                tcg_temp_free_ptr(fpstatus);
                                 break;
+                            }
                             default:
                                 abort();
                             }
@@ -6029,30 +6060,50 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             tcg_temp_free(tmp2);
                             break;
                         case NEON_2RM_VCGT0_F:
+                        {
+                            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
                             tmp2 = tcg_const_i32(0);
-                            gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
+                            gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
                             tcg_temp_free(tmp2);
+                            tcg_temp_free_ptr(fpstatus);
                             break;
+                        }
                         case NEON_2RM_VCGE0_F:
+                        {
+                            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
                             tmp2 = tcg_const_i32(0);
-                            gen_helper_neon_cge_f32(tmp, tmp, tmp2);
+                            gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
                             tcg_temp_free(tmp2);
+                            tcg_temp_free_ptr(fpstatus);
                             break;
+                        }
                         case NEON_2RM_VCEQ0_F:
+                        {
+                            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
                             tmp2 = tcg_const_i32(0);
-                            gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
+                            gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
                             tcg_temp_free(tmp2);
+                            tcg_temp_free_ptr(fpstatus);
                             break;
+                        }
                         case NEON_2RM_VCLE0_F:
+                        {
+                            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
                             tmp2 = tcg_const_i32(0);
-                            gen_helper_neon_cge_f32(tmp, tmp2, tmp);
+                            gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
                             tcg_temp_free(tmp2);
+                            tcg_temp_free_ptr(fpstatus);
                             break;
+                        }
                         case NEON_2RM_VCLT0_F:
+                        {
+                            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
                             tmp2 = tcg_const_i32(0);
-                            gen_helper_neon_cgt_f32(tmp, tmp2, tmp);
+                            gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
                             tcg_temp_free(tmp2);
+                            tcg_temp_free_ptr(fpstatus);
                             break;
+                        }
                         case NEON_2RM_VABS_F:
                             gen_vfp_abs(0);
                             break;
commit ae1857eca22b58d430941730bd097e95a484652c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed May 25 14:51:48 2011 +0000

    target-arm: Make VFP binop helpers take pointer to fpstatus, not CPUState
    
    Make the VFP binop helper functions take a pointer to the fp status, not
    the entire CPUState. This will allow us to use them for Neon operations too.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 1208416..9f14781 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2453,13 +2453,15 @@ void vfp_set_fpscr(CPUState *env, uint32_t val)
 #define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
 
 #define VFP_BINOP(name) \
-float32 VFP_HELPER(name, s)(float32 a, float32 b, CPUState *env) \
+float32 VFP_HELPER(name, s)(float32 a, float32 b, void *fpstp) \
 { \
-    return float32_ ## name (a, b, &env->vfp.fp_status); \
+    float_status *fpst = fpstp; \
+    return float32_ ## name(a, b, fpst); \
 } \
-float64 VFP_HELPER(name, d)(float64 a, float64 b, CPUState *env) \
+float64 VFP_HELPER(name, d)(float64 a, float64 b, void *fpstp) \
 { \
-    return float64_ ## name (a, b, &env->vfp.fp_status); \
+    float_status *fpst = fpstp; \
+    return float64_ ## name(a, b, fpst); \
 }
 VFP_BINOP(add)
 VFP_BINOP(sub)
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 44800b1..40b4677 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -74,14 +74,14 @@ DEF_HELPER_2(set_user_reg, void, i32, i32)
 DEF_HELPER_1(vfp_get_fpscr, i32, env)
 DEF_HELPER_2(vfp_set_fpscr, void, env, i32)
 
-DEF_HELPER_3(vfp_adds, f32, f32, f32, env)
-DEF_HELPER_3(vfp_addd, f64, f64, f64, env)
-DEF_HELPER_3(vfp_subs, f32, f32, f32, env)
-DEF_HELPER_3(vfp_subd, f64, f64, f64, env)
-DEF_HELPER_3(vfp_muls, f32, f32, f32, env)
-DEF_HELPER_3(vfp_muld, f64, f64, f64, env)
-DEF_HELPER_3(vfp_divs, f32, f32, f32, env)
-DEF_HELPER_3(vfp_divd, f64, f64, f64, env)
+DEF_HELPER_3(vfp_adds, f32, f32, f32, ptr)
+DEF_HELPER_3(vfp_addd, f64, f64, f64, ptr)
+DEF_HELPER_3(vfp_subs, f32, f32, f32, ptr)
+DEF_HELPER_3(vfp_subd, f64, f64, f64, ptr)
+DEF_HELPER_3(vfp_muls, f32, f32, f32, ptr)
+DEF_HELPER_3(vfp_muld, f64, f64, f64, ptr)
+DEF_HELPER_3(vfp_divs, f32, f32, f32, ptr)
+DEF_HELPER_3(vfp_divd, f64, f64, f64, ptr)
 DEF_HELPER_1(vfp_negs, f32, f32)
 DEF_HELPER_1(vfp_negd, f64, f64)
 DEF_HELPER_1(vfp_abss, f32, f32)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index e9d1549..9ed747f 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -909,10 +909,13 @@ static TCGv_ptr get_fpstatus_ptr(int neon)
 #define VFP_OP2(name)                                                 \
 static inline void gen_vfp_##name(int dp)                             \
 {                                                                     \
-    if (dp)                                                           \
-        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
-    else                                                              \
-        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
+    TCGv_ptr fpst = get_fpstatus_ptr(0);                              \
+    if (dp) {                                                         \
+        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst);    \
+    } else {                                                          \
+        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst);    \
+    }                                                                 \
+    tcg_temp_free_ptr(fpst);                                          \
 }
 
 VFP_OP2(add)
@@ -925,11 +928,13 @@ VFP_OP2(div)
 static inline void gen_vfp_F1_mul(int dp)
 {
     /* Like gen_vfp_mul() but put result in F1 */
+    TCGv_ptr fpst = get_fpstatus_ptr(0);
     if (dp) {
-        gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, cpu_env);
+        gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
     } else {
-        gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, cpu_env);
+        gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
     }
+    tcg_temp_free_ptr(fpst);
 }
 
 static inline void gen_vfp_F1_neg(int dp)
commit 5aaebd13da29a7157b757590284664dc42ea6a69
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed May 25 15:16:10 2011 +0000

    target-arm: Add helper function to generate code to get fpstatus pointer
    
    Add and use a helper function which returns a TCGv which is a pointer
    to the fp_status for either Neon or VFP operations.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 34993c4..e9d1549 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -893,6 +893,19 @@ static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
     }
 }
 
+static TCGv_ptr get_fpstatus_ptr(int neon)
+{
+    TCGv_ptr statusptr = tcg_temp_new_ptr();
+    int offset;
+    if (neon) {
+        offset = offsetof(CPUState, vfp.standard_fp_status);
+    } else {
+        offset = offsetof(CPUState, vfp.fp_status);
+    }
+    tcg_gen_addi_ptr(statusptr, cpu_env, offset);
+    return statusptr;
+}
+
 #define VFP_OP2(name)                                                 \
 static inline void gen_vfp_##name(int dp)                             \
 {                                                                     \
@@ -980,14 +993,7 @@ static inline void gen_vfp_F1_ld0(int dp)
 #define VFP_GEN_ITOF(name) \
 static inline void gen_vfp_##name(int dp, int neon) \
 { \
-    TCGv_ptr statusptr = tcg_temp_new_ptr(); \
-    int offset; \
-    if (neon) { \
-        offset = offsetof(CPUState, vfp.standard_fp_status); \
-    } else { \
-        offset = offsetof(CPUState, vfp.fp_status); \
-    } \
-    tcg_gen_addi_ptr(statusptr, cpu_env, offset); \
+    TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
     if (dp) { \
         gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
     } else { \
@@ -1003,14 +1009,7 @@ VFP_GEN_ITOF(sito)
 #define VFP_GEN_FTOI(name) \
 static inline void gen_vfp_##name(int dp, int neon) \
 { \
-    TCGv_ptr statusptr = tcg_temp_new_ptr(); \
-    int offset; \
-    if (neon) { \
-        offset = offsetof(CPUState, vfp.standard_fp_status); \
-    } else { \
-        offset = offsetof(CPUState, vfp.fp_status); \
-    } \
-    tcg_gen_addi_ptr(statusptr, cpu_env, offset); \
+    TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
     if (dp) { \
         gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
     } else { \
@@ -1029,14 +1028,7 @@ VFP_GEN_FTOI(tosiz)
 static inline void gen_vfp_##name(int dp, int shift, int neon) \
 { \
     TCGv tmp_shift = tcg_const_i32(shift); \
-    TCGv_ptr statusptr = tcg_temp_new_ptr(); \
-    int offset; \
-    if (neon) { \
-        offset = offsetof(CPUState, vfp.standard_fp_status); \
-    } else { \
-        offset = offsetof(CPUState, vfp.fp_status); \
-    } \
-    tcg_gen_addi_ptr(statusptr, cpu_env, offset); \
+    TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
     if (dp) { \
         gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \
     } else { \
commit 477955bd55e032374a41689bab77be5d4b0fb27a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed May 25 13:22:31 2011 +0000

    Revert "target-arm: Use global env in iwmmxt_helper.c helpers"
    
    This reverts commit 947a2fa21b61703802a660a938cabd7b3600ee79,
    returning the iwmmxt helpers to passing env in as a parameter.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.h b/target-arm/helper.h
index 7d5533f..44800b1 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -375,47 +375,47 @@ DEF_HELPER_2(iwmmxt_macsw, i64, i64, i64)
 DEF_HELPER_2(iwmmxt_macuw, i64, i64, i64)
 DEF_HELPER_1(iwmmxt_setpsr_nz, i32, i64)
 
-#define DEF_IWMMXT_HELPER_SIZE(name) \
-DEF_HELPER_2(iwmmxt_##name##b, i64, i64, i64) \
-DEF_HELPER_2(iwmmxt_##name##w, i64, i64, i64) \
-DEF_HELPER_2(iwmmxt_##name##l, i64, i64, i64) \
-
-DEF_IWMMXT_HELPER_SIZE(unpackl)
-DEF_IWMMXT_HELPER_SIZE(unpackh)
-
-DEF_HELPER_1(iwmmxt_unpacklub, i64, i64)
-DEF_HELPER_1(iwmmxt_unpackluw, i64, i64)
-DEF_HELPER_1(iwmmxt_unpacklul, i64, i64)
-DEF_HELPER_1(iwmmxt_unpackhub, i64, i64)
-DEF_HELPER_1(iwmmxt_unpackhuw, i64, i64)
-DEF_HELPER_1(iwmmxt_unpackhul, i64, i64)
-DEF_HELPER_1(iwmmxt_unpacklsb, i64, i64)
-DEF_HELPER_1(iwmmxt_unpacklsw, i64, i64)
-DEF_HELPER_1(iwmmxt_unpacklsl, i64, i64)
-DEF_HELPER_1(iwmmxt_unpackhsb, i64, i64)
-DEF_HELPER_1(iwmmxt_unpackhsw, i64, i64)
-DEF_HELPER_1(iwmmxt_unpackhsl, i64, i64)
-
-DEF_IWMMXT_HELPER_SIZE(cmpeq)
-DEF_IWMMXT_HELPER_SIZE(cmpgtu)
-DEF_IWMMXT_HELPER_SIZE(cmpgts)
-
-DEF_IWMMXT_HELPER_SIZE(mins)
-DEF_IWMMXT_HELPER_SIZE(minu)
-DEF_IWMMXT_HELPER_SIZE(maxs)
-DEF_IWMMXT_HELPER_SIZE(maxu)
-
-DEF_IWMMXT_HELPER_SIZE(subn)
-DEF_IWMMXT_HELPER_SIZE(addn)
-DEF_IWMMXT_HELPER_SIZE(subu)
-DEF_IWMMXT_HELPER_SIZE(addu)
-DEF_IWMMXT_HELPER_SIZE(subs)
-DEF_IWMMXT_HELPER_SIZE(adds)
-
-DEF_HELPER_2(iwmmxt_avgb0, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_avgb1, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_avgw0, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_avgw1, i64, i64, i64)
+#define DEF_IWMMXT_HELPER_SIZE_ENV(name) \
+DEF_HELPER_3(iwmmxt_##name##b, i64, env, i64, i64) \
+DEF_HELPER_3(iwmmxt_##name##w, i64, env, i64, i64) \
+DEF_HELPER_3(iwmmxt_##name##l, i64, env, i64, i64) \
+
+DEF_IWMMXT_HELPER_SIZE_ENV(unpackl)
+DEF_IWMMXT_HELPER_SIZE_ENV(unpackh)
+
+DEF_HELPER_2(iwmmxt_unpacklub, i64, env, i64)
+DEF_HELPER_2(iwmmxt_unpackluw, i64, env, i64)
+DEF_HELPER_2(iwmmxt_unpacklul, i64, env, i64)
+DEF_HELPER_2(iwmmxt_unpackhub, i64, env, i64)
+DEF_HELPER_2(iwmmxt_unpackhuw, i64, env, i64)
+DEF_HELPER_2(iwmmxt_unpackhul, i64, env, i64)
+DEF_HELPER_2(iwmmxt_unpacklsb, i64, env, i64)
+DEF_HELPER_2(iwmmxt_unpacklsw, i64, env, i64)
+DEF_HELPER_2(iwmmxt_unpacklsl, i64, env, i64)
+DEF_HELPER_2(iwmmxt_unpackhsb, i64, env, i64)
+DEF_HELPER_2(iwmmxt_unpackhsw, i64, env, i64)
+DEF_HELPER_2(iwmmxt_unpackhsl, i64, env, i64)
+
+DEF_IWMMXT_HELPER_SIZE_ENV(cmpeq)
+DEF_IWMMXT_HELPER_SIZE_ENV(cmpgtu)
+DEF_IWMMXT_HELPER_SIZE_ENV(cmpgts)
+
+DEF_IWMMXT_HELPER_SIZE_ENV(mins)
+DEF_IWMMXT_HELPER_SIZE_ENV(minu)
+DEF_IWMMXT_HELPER_SIZE_ENV(maxs)
+DEF_IWMMXT_HELPER_SIZE_ENV(maxu)
+
+DEF_IWMMXT_HELPER_SIZE_ENV(subn)
+DEF_IWMMXT_HELPER_SIZE_ENV(addn)
+DEF_IWMMXT_HELPER_SIZE_ENV(subu)
+DEF_IWMMXT_HELPER_SIZE_ENV(addu)
+DEF_IWMMXT_HELPER_SIZE_ENV(subs)
+DEF_IWMMXT_HELPER_SIZE_ENV(adds)
+
+DEF_HELPER_3(iwmmxt_avgb0, i64, env, i64, i64)
+DEF_HELPER_3(iwmmxt_avgb1, i64, env, i64, i64)
+DEF_HELPER_3(iwmmxt_avgw0, i64, env, i64, i64)
+DEF_HELPER_3(iwmmxt_avgw1, i64, env, i64, i64)
 
 DEF_HELPER_2(iwmmxt_msadb, i64, i64, i64)
 
@@ -434,26 +434,26 @@ DEF_HELPER_1(iwmmxt_msbb, i32, i64)
 DEF_HELPER_1(iwmmxt_msbw, i32, i64)
 DEF_HELPER_1(iwmmxt_msbl, i32, i64)
 
-DEF_HELPER_2(iwmmxt_srlw, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_srll, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_srlq, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_sllw, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_slll, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_sllq, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_sraw, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_sral, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_sraq, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_rorw, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_rorl, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_rorq, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_shufh, i64, i64, i32)
-
-DEF_HELPER_2(iwmmxt_packuw, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_packul, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_packuq, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_packsw, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_packsl, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_packsq, i64, i64, i64)
+DEF_HELPER_3(iwmmxt_srlw, i64, env, i64, i32)
+DEF_HELPER_3(iwmmxt_srll, i64, env, i64, i32)
+DEF_HELPER_3(iwmmxt_srlq, i64, env, i64, i32)
+DEF_HELPER_3(iwmmxt_sllw, i64, env, i64, i32)
+DEF_HELPER_3(iwmmxt_slll, i64, env, i64, i32)
+DEF_HELPER_3(iwmmxt_sllq, i64, env, i64, i32)
+DEF_HELPER_3(iwmmxt_sraw, i64, env, i64, i32)
+DEF_HELPER_3(iwmmxt_sral, i64, env, i64, i32)
+DEF_HELPER_3(iwmmxt_sraq, i64, env, i64, i32)
+DEF_HELPER_3(iwmmxt_rorw, i64, env, i64, i32)
+DEF_HELPER_3(iwmmxt_rorl, i64, env, i64, i32)
+DEF_HELPER_3(iwmmxt_rorq, i64, env, i64, i32)
+DEF_HELPER_3(iwmmxt_shufh, i64, env, i64, i32)
+
+DEF_HELPER_3(iwmmxt_packuw, i64, env, i64, i64)
+DEF_HELPER_3(iwmmxt_packul, i64, env, i64, i64)
+DEF_HELPER_3(iwmmxt_packuq, i64, env, i64, i64)
+DEF_HELPER_3(iwmmxt_packsw, i64, env, i64, i64)
+DEF_HELPER_3(iwmmxt_packsl, i64, env, i64, i64)
+DEF_HELPER_3(iwmmxt_packsq, i64, env, i64, i64)
 
 DEF_HELPER_3(iwmmxt_muladdsl, i64, i64, i32, i32)
 DEF_HELPER_3(iwmmxt_muladdsw, i64, i64, i32, i32)
diff --git a/target-arm/iwmmxt_helper.c b/target-arm/iwmmxt_helper.c
index ebe6eb9..843994d 100644
--- a/target-arm/iwmmxt_helper.c
+++ b/target-arm/iwmmxt_helper.c
@@ -23,7 +23,7 @@
 #include <stdio.h>
 
 #include "cpu.h"
-#include "exec.h"
+#include "exec-all.h"
 #include "helper.h"
 
 /* iwMMXt macros extracted from GNU gdb.  */
@@ -162,7 +162,8 @@ uint64_t HELPER(iwmmxt_macuw)(uint64_t a, uint64_t b)
     SIMD64_SET(NBIT64(x), SIMD_NBIT) | \
     SIMD64_SET(ZBIT64(x), SIMD_ZBIT)
 #define IWMMXT_OP_UNPACK(S, SH0, SH1, SH2, SH3)			\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, b)))(uint64_t a, uint64_t b) \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, b)))(CPUState *env, \
+                                                 uint64_t a, uint64_t b) \
 {								\
     a =							        \
         (((a >> SH0) & 0xff) << 0) | (((b >> SH0) & 0xff) << 8) |	\
@@ -176,7 +177,8 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, b)))(uint64_t a, uint64_t b) \
         NZBIT8(a >> 48, 6) | NZBIT8(a >> 56, 7);		\
     return a;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, w)))(uint64_t a, uint64_t b) \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, w)))(CPUState *env, \
+                                        uint64_t a, uint64_t b) \
 {								\
     a =							        \
         (((a >> SH0) & 0xffff) << 0) |				\
@@ -188,7 +190,8 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, w)))(uint64_t a, uint64_t b) \
         NZBIT8(a >> 32, 2) | NZBIT8(a >> 48, 3);		\
     return a;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, l)))(uint64_t a, uint64_t b) \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, l)))(CPUState *env, \
+                                        uint64_t a, uint64_t b) \
 {								\
     a =							        \
         (((a >> SH0) & 0xffffffff) << 0) |			\
@@ -197,7 +200,8 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, l)))(uint64_t a, uint64_t b) \
         NZBIT32(a >> 0, 0) | NZBIT32(a >> 32, 1);		\
     return a;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ub)))(uint64_t x)   \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ub)))(CPUState *env, \
+                                                  uint64_t x)   \
 {								\
     x =							        \
         (((x >> SH0) & 0xff) << 0) |				\
@@ -209,7 +213,8 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ub)))(uint64_t x)   \
         NZBIT16(x >> 32, 2) | NZBIT16(x >> 48, 3);		\
     return x;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, uw)))(uint64_t x)   \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, uw)))(CPUState *env, \
+                                                  uint64_t x)   \
 {								\
     x =							        \
         (((x >> SH0) & 0xffff) << 0) |				\
@@ -218,13 +223,15 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, uw)))(uint64_t x)   \
         NZBIT32(x >> 0, 0) | NZBIT32(x >> 32, 1);		\
     return x;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ul)))(uint64_t x)   \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ul)))(CPUState *env, \
+                                                  uint64_t x)   \
 {								\
     x = (((x >> SH0) & 0xffffffff) << 0);			\
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x >> 0);	\
     return x;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sb)))(uint64_t x)   \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sb)))(CPUState *env, \
+                                                  uint64_t x)   \
 {								\
     x =							        \
         ((uint64_t) EXTEND8H((x >> SH0) & 0xff) << 0) |	        \
@@ -236,7 +243,8 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sb)))(uint64_t x)   \
         NZBIT16(x >> 32, 2) | NZBIT16(x >> 48, 3);		\
     return x;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sw)))(uint64_t x)   \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sw)))(CPUState *env, \
+                                                  uint64_t x)   \
 {								\
     x =							        \
         ((uint64_t) EXTEND16((x >> SH0) & 0xffff) << 0) |	\
@@ -245,7 +253,8 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sw)))(uint64_t x)   \
         NZBIT32(x >> 0, 0) | NZBIT32(x >> 32, 1);		\
     return x;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sl)))(uint64_t x)   \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sl)))(CPUState *env, \
+                                                  uint64_t x)   \
 {								\
     x = EXTEND32((x >> SH0) & 0xffffffff);			\
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x >> 0);	\
@@ -255,7 +264,8 @@ IWMMXT_OP_UNPACK(l, 0, 8, 16, 24)
 IWMMXT_OP_UNPACK(h, 32, 40, 48, 56)
 
 #define IWMMXT_OP_CMP(SUFF, Tb, Tw, Tl, O)			\
-uint64_t HELPER(glue(iwmmxt_, glue(SUFF, b)))(uint64_t a, uint64_t b) \
+uint64_t HELPER(glue(iwmmxt_, glue(SUFF, b)))(CPUState *env,    \
+                                        uint64_t a, uint64_t b) \
 {								\
     a =							        \
         CMP(0, Tb, O, 0xff) | CMP(8, Tb, O, 0xff) |		\
@@ -269,7 +279,8 @@ uint64_t HELPER(glue(iwmmxt_, glue(SUFF, b)))(uint64_t a, uint64_t b) \
         NZBIT8(a >> 48, 6) | NZBIT8(a >> 56, 7);		\
     return a;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_, glue(SUFF, w)))(uint64_t a, uint64_t b) \
+uint64_t HELPER(glue(iwmmxt_, glue(SUFF, w)))(CPUState *env,    \
+                                        uint64_t a, uint64_t b) \
 {								\
     a = CMP(0, Tw, O, 0xffff) | CMP(16, Tw, O, 0xffff) |	\
         CMP(32, Tw, O, 0xffff) | CMP(48, Tw, O, 0xffff);	\
@@ -278,7 +289,8 @@ uint64_t HELPER(glue(iwmmxt_, glue(SUFF, w)))(uint64_t a, uint64_t b) \
         NZBIT16(a >> 32, 2) | NZBIT16(a >> 48, 3);		\
     return a;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_, glue(SUFF, l)))(uint64_t a, uint64_t b) \
+uint64_t HELPER(glue(iwmmxt_, glue(SUFF, l)))(CPUState *env,    \
+                                        uint64_t a, uint64_t b) \
 {								\
     a = CMP(0, Tl, O, 0xffffffff) |				\
         CMP(32, Tl, O, 0xffffffff);				\
@@ -317,7 +329,7 @@ IWMMXT_OP_CMP(adds, int8_t, int16_t, int32_t, +)
 #define AVGB(SHR) ((( \
         ((a >> SHR) & 0xff) + ((b >> SHR) & 0xff) + round) >> 1) << SHR)
 #define IWMMXT_OP_AVGB(r)                                                 \
-uint64_t HELPER(iwmmxt_avgb##r)(uint64_t a, uint64_t b)                   \
+uint64_t HELPER(iwmmxt_avgb##r)(CPUState *env, uint64_t a, uint64_t b)    \
 {                                                                         \
     const int round = r;                                                  \
     a = AVGB(0) | AVGB(8) | AVGB(16) | AVGB(24) |                         \
@@ -341,7 +353,7 @@ IWMMXT_OP_AVGB(1)
 #define AVGW(SHR) ((( \
         ((a >> SHR) & 0xffff) + ((b >> SHR) & 0xffff) + round) >> 1) << SHR)
 #define IWMMXT_OP_AVGW(r)                                               \
-uint64_t HELPER(iwmmxt_avgw##r)(uint64_t a, uint64_t b)                 \
+uint64_t HELPER(iwmmxt_avgw##r)(CPUState *env, uint64_t a, uint64_t b)  \
 {                                                                       \
     const int round = r;                                                \
     a = AVGW(0) | AVGW(16) | AVGW(32) | AVGW(48);                       \
@@ -452,7 +464,7 @@ uint32_t HELPER(iwmmxt_msbl)(uint64_t x)
 }
 
 /* FIXME: Split wCASF setting into a separate op to avoid env use.  */
-uint64_t HELPER(iwmmxt_srlw)(uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_srlw)(CPUState *env, uint64_t x, uint32_t n)
 {
     x = (((x & (0xffffll << 0)) >> n) & (0xffffll << 0)) |
         (((x & (0xffffll << 16)) >> n) & (0xffffll << 16)) |
@@ -464,7 +476,7 @@ uint64_t HELPER(iwmmxt_srlw)(uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_srll)(uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_srll)(CPUState *env, uint64_t x, uint32_t n)
 {
     x = ((x & (0xffffffffll << 0)) >> n) |
         ((x >> n) & (0xffffffffll << 32));
@@ -473,14 +485,14 @@ uint64_t HELPER(iwmmxt_srll)(uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_srlq)(uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_srlq)(CPUState *env, uint64_t x, uint32_t n)
 {
     x >>= n;
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x);
     return x;
 }
 
-uint64_t HELPER(iwmmxt_sllw)(uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_sllw)(CPUState *env, uint64_t x, uint32_t n)
 {
     x = (((x & (0xffffll << 0)) << n) & (0xffffll << 0)) |
         (((x & (0xffffll << 16)) << n) & (0xffffll << 16)) |
@@ -492,7 +504,7 @@ uint64_t HELPER(iwmmxt_sllw)(uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_slll)(uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_slll)(CPUState *env, uint64_t x, uint32_t n)
 {
     x = ((x << n) & (0xffffffffll << 0)) |
         ((x & (0xffffffffll << 32)) << n);
@@ -501,14 +513,14 @@ uint64_t HELPER(iwmmxt_slll)(uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_sllq)(uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_sllq)(CPUState *env, uint64_t x, uint32_t n)
 {
     x <<= n;
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x);
     return x;
 }
 
-uint64_t HELPER(iwmmxt_sraw)(uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_sraw)(CPUState *env, uint64_t x, uint32_t n)
 {
     x = ((uint64_t) ((EXTEND16(x >> 0) >> n) & 0xffff) << 0) |
         ((uint64_t) ((EXTEND16(x >> 16) >> n) & 0xffff) << 16) |
@@ -520,7 +532,7 @@ uint64_t HELPER(iwmmxt_sraw)(uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_sral)(uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_sral)(CPUState *env, uint64_t x, uint32_t n)
 {
     x = (((EXTEND32(x >> 0) >> n) & 0xffffffff) << 0) |
         (((EXTEND32(x >> 32) >> n) & 0xffffffff) << 32);
@@ -529,14 +541,14 @@ uint64_t HELPER(iwmmxt_sral)(uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_sraq)(uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_sraq)(CPUState *env, uint64_t x, uint32_t n)
 {
     x = (int64_t) x >> n;
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x);
     return x;
 }
 
-uint64_t HELPER(iwmmxt_rorw)(uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_rorw)(CPUState *env, uint64_t x, uint32_t n)
 {
     x = ((((x & (0xffffll << 0)) >> n) |
           ((x & (0xffffll << 0)) << (16 - n))) & (0xffffll << 0)) |
@@ -552,7 +564,7 @@ uint64_t HELPER(iwmmxt_rorw)(uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_rorl)(uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_rorl)(CPUState *env, uint64_t x, uint32_t n)
 {
     x = ((x & (0xffffffffll << 0)) >> n) |
         ((x >> n) & (0xffffffffll << 32)) |
@@ -563,14 +575,14 @@ uint64_t HELPER(iwmmxt_rorl)(uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_rorq)(uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_rorq)(CPUState *env, uint64_t x, uint32_t n)
 {
     x = (x >> n) | (x << (64 - n));
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x);
     return x;
 }
 
-uint64_t HELPER(iwmmxt_shufh)(uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_shufh)(CPUState *env, uint64_t x, uint32_t n)
 {
     x = (((x >> ((n << 4) & 0x30)) & 0xffff) << 0) |
         (((x >> ((n << 2) & 0x30)) & 0xffff) << 16) |
@@ -583,7 +595,7 @@ uint64_t HELPER(iwmmxt_shufh)(uint64_t x, uint32_t n)
 }
 
 /* TODO: Unsigned-Saturation */
-uint64_t HELPER(iwmmxt_packuw)(uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packuw)(CPUState *env, uint64_t a, uint64_t b)
 {
     a = (((a >> 0) & 0xff) << 0) | (((a >> 16) & 0xff) << 8) |
         (((a >> 32) & 0xff) << 16) | (((a >> 48) & 0xff) << 24) |
@@ -597,7 +609,7 @@ uint64_t HELPER(iwmmxt_packuw)(uint64_t a, uint64_t b)
     return a;
 }
 
-uint64_t HELPER(iwmmxt_packul)(uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packul)(CPUState *env, uint64_t a, uint64_t b)
 {
     a = (((a >> 0) & 0xffff) << 0) | (((a >> 32) & 0xffff) << 16) |
         (((b >> 0) & 0xffff) << 32) | (((b >> 32) & 0xffff) << 48);
@@ -607,7 +619,7 @@ uint64_t HELPER(iwmmxt_packul)(uint64_t a, uint64_t b)
     return a;
 }
 
-uint64_t HELPER(iwmmxt_packuq)(uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packuq)(CPUState *env, uint64_t a, uint64_t b)
 {
     a = (a & 0xffffffff) | ((b & 0xffffffff) << 32);
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
@@ -616,7 +628,7 @@ uint64_t HELPER(iwmmxt_packuq)(uint64_t a, uint64_t b)
 }
 
 /* TODO: Signed-Saturation */
-uint64_t HELPER(iwmmxt_packsw)(uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packsw)(CPUState *env, uint64_t a, uint64_t b)
 {
     a = (((a >> 0) & 0xff) << 0) | (((a >> 16) & 0xff) << 8) |
         (((a >> 32) & 0xff) << 16) | (((a >> 48) & 0xff) << 24) |
@@ -630,7 +642,7 @@ uint64_t HELPER(iwmmxt_packsw)(uint64_t a, uint64_t b)
     return a;
 }
 
-uint64_t HELPER(iwmmxt_packsl)(uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packsl)(CPUState *env, uint64_t a, uint64_t b)
 {
     a = (((a >> 0) & 0xffff) << 0) | (((a >> 32) & 0xffff) << 16) |
         (((b >> 0) & 0xffff) << 32) | (((b >> 32) & 0xffff) << 48);
@@ -640,7 +652,7 @@ uint64_t HELPER(iwmmxt_packsl)(uint64_t a, uint64_t b)
     return a;
 }
 
-uint64_t HELPER(iwmmxt_packsq)(uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packsq)(CPUState *env, uint64_t a, uint64_t b)
 {
     a = (a & 0xffffffff) | ((b & 0xffffffff) << 32);
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
diff --git a/target-arm/translate.c b/target-arm/translate.c
index f5507ec..34993c4 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -1207,15 +1207,22 @@ static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
     gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
 }
 
-#define IWMMXT_OP_SIZE(name) \
-IWMMXT_OP(name##b) \
-IWMMXT_OP(name##w) \
-IWMMXT_OP(name##l)
+#define IWMMXT_OP_ENV(name) \
+static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
+{ \
+    iwmmxt_load_reg(cpu_V1, rn); \
+    gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
+}
+
+#define IWMMXT_OP_ENV_SIZE(name) \
+IWMMXT_OP_ENV(name##b) \
+IWMMXT_OP_ENV(name##w) \
+IWMMXT_OP_ENV(name##l)
 
-#define IWMMXT_OP_1(name) \
+#define IWMMXT_OP_ENV1(name) \
 static inline void gen_op_iwmmxt_##name##_M0(void) \
 { \
-    gen_helper_iwmmxt_##name(cpu_M0, cpu_M0); \
+    gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
 }
 
 IWMMXT_OP(maddsq)
@@ -1229,51 +1236,51 @@ IWMMXT_OP(muluhw)
 IWMMXT_OP(macsw)
 IWMMXT_OP(macuw)
 
-IWMMXT_OP_SIZE(unpackl)
-IWMMXT_OP_SIZE(unpackh)
-
-IWMMXT_OP_1(unpacklub)
-IWMMXT_OP_1(unpackluw)
-IWMMXT_OP_1(unpacklul)
-IWMMXT_OP_1(unpackhub)
-IWMMXT_OP_1(unpackhuw)
-IWMMXT_OP_1(unpackhul)
-IWMMXT_OP_1(unpacklsb)
-IWMMXT_OP_1(unpacklsw)
-IWMMXT_OP_1(unpacklsl)
-IWMMXT_OP_1(unpackhsb)
-IWMMXT_OP_1(unpackhsw)
-IWMMXT_OP_1(unpackhsl)
-
-IWMMXT_OP_SIZE(cmpeq)
-IWMMXT_OP_SIZE(cmpgtu)
-IWMMXT_OP_SIZE(cmpgts)
-
-IWMMXT_OP_SIZE(mins)
-IWMMXT_OP_SIZE(minu)
-IWMMXT_OP_SIZE(maxs)
-IWMMXT_OP_SIZE(maxu)
-
-IWMMXT_OP_SIZE(subn)
-IWMMXT_OP_SIZE(addn)
-IWMMXT_OP_SIZE(subu)
-IWMMXT_OP_SIZE(addu)
-IWMMXT_OP_SIZE(subs)
-IWMMXT_OP_SIZE(adds)
-
-IWMMXT_OP(avgb0)
-IWMMXT_OP(avgb1)
-IWMMXT_OP(avgw0)
-IWMMXT_OP(avgw1)
+IWMMXT_OP_ENV_SIZE(unpackl)
+IWMMXT_OP_ENV_SIZE(unpackh)
+
+IWMMXT_OP_ENV1(unpacklub)
+IWMMXT_OP_ENV1(unpackluw)
+IWMMXT_OP_ENV1(unpacklul)
+IWMMXT_OP_ENV1(unpackhub)
+IWMMXT_OP_ENV1(unpackhuw)
+IWMMXT_OP_ENV1(unpackhul)
+IWMMXT_OP_ENV1(unpacklsb)
+IWMMXT_OP_ENV1(unpacklsw)
+IWMMXT_OP_ENV1(unpacklsl)
+IWMMXT_OP_ENV1(unpackhsb)
+IWMMXT_OP_ENV1(unpackhsw)
+IWMMXT_OP_ENV1(unpackhsl)
+
+IWMMXT_OP_ENV_SIZE(cmpeq)
+IWMMXT_OP_ENV_SIZE(cmpgtu)
+IWMMXT_OP_ENV_SIZE(cmpgts)
+
+IWMMXT_OP_ENV_SIZE(mins)
+IWMMXT_OP_ENV_SIZE(minu)
+IWMMXT_OP_ENV_SIZE(maxs)
+IWMMXT_OP_ENV_SIZE(maxu)
+
+IWMMXT_OP_ENV_SIZE(subn)
+IWMMXT_OP_ENV_SIZE(addn)
+IWMMXT_OP_ENV_SIZE(subu)
+IWMMXT_OP_ENV_SIZE(addu)
+IWMMXT_OP_ENV_SIZE(subs)
+IWMMXT_OP_ENV_SIZE(adds)
+
+IWMMXT_OP_ENV(avgb0)
+IWMMXT_OP_ENV(avgb1)
+IWMMXT_OP_ENV(avgw0)
+IWMMXT_OP_ENV(avgw1)
 
 IWMMXT_OP(msadb)
 
-IWMMXT_OP(packuw)
-IWMMXT_OP(packul)
-IWMMXT_OP(packuq)
-IWMMXT_OP(packsw)
-IWMMXT_OP(packsl)
-IWMMXT_OP(packsq)
+IWMMXT_OP_ENV(packuw)
+IWMMXT_OP_ENV(packul)
+IWMMXT_OP_ENV(packuq)
+IWMMXT_OP_ENV(packsw)
+IWMMXT_OP_ENV(packsl)
+IWMMXT_OP_ENV(packsq)
 
 static void gen_op_iwmmxt_set_mup(void)
 {
@@ -2007,13 +2014,13 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         }
         switch ((insn >> 22) & 3) {
         case 1:
-            gen_helper_iwmmxt_srlw(cpu_M0, cpu_M0, tmp);
+            gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         case 2:
-            gen_helper_iwmmxt_srll(cpu_M0, cpu_M0, tmp);
+            gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         case 3:
-            gen_helper_iwmmxt_srlq(cpu_M0, cpu_M0, tmp);
+            gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         }
         tcg_temp_free_i32(tmp);
@@ -2035,13 +2042,13 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         }
         switch ((insn >> 22) & 3) {
         case 1:
-            gen_helper_iwmmxt_sraw(cpu_M0, cpu_M0, tmp);
+            gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         case 2:
-            gen_helper_iwmmxt_sral(cpu_M0, cpu_M0, tmp);
+            gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         case 3:
-            gen_helper_iwmmxt_sraq(cpu_M0, cpu_M0, tmp);
+            gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         }
         tcg_temp_free_i32(tmp);
@@ -2063,13 +2070,13 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         }
         switch ((insn >> 22) & 3) {
         case 1:
-            gen_helper_iwmmxt_sllw(cpu_M0, cpu_M0, tmp);
+            gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         case 2:
-            gen_helper_iwmmxt_slll(cpu_M0, cpu_M0, tmp);
+            gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         case 3:
-            gen_helper_iwmmxt_sllq(cpu_M0, cpu_M0, tmp);
+            gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         }
         tcg_temp_free_i32(tmp);
@@ -2091,21 +2098,21 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
                 tcg_temp_free_i32(tmp);
                 return 1;
             }
-            gen_helper_iwmmxt_rorw(cpu_M0, cpu_M0, tmp);
+            gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         case 2:
             if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
                 tcg_temp_free_i32(tmp);
                 return 1;
             }
-            gen_helper_iwmmxt_rorl(cpu_M0, cpu_M0, tmp);
+            gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         case 3:
             if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
                 tcg_temp_free_i32(tmp);
                 return 1;
             }
-            gen_helper_iwmmxt_rorq(cpu_M0, cpu_M0, tmp);
+            gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         }
         tcg_temp_free_i32(tmp);
@@ -2239,7 +2246,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         rd0 = (insn >> 16) & 0xf;
         gen_op_iwmmxt_movq_M0_wRn(rd0);
         tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
-        gen_helper_iwmmxt_shufh(cpu_M0, cpu_M0, tmp);
+        gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
         tcg_temp_free(tmp);
         gen_op_iwmmxt_movq_wRn_M0(wrd);
         gen_op_iwmmxt_set_mup();


More information about the Spice-commits mailing list