[Spice-commits] 392 commits - .gitmodules Changelog MAINTAINERS Makefile QMP/README QMP/qemu-ga-client QMP/qmp QMP/qmp-events.txt QMP/qmp-shell QMP/qmp-spec.txt QMP/qmp.py QMP/qom-fuse QMP/qom-get QMP/qom-list QMP/qom-set README arch_init.c audio/mixeng.c block.c block/backup.c block/blkdebug.c block/blkverify.c block/commit.c block/gluster.c block/iscsi.c block/mirror.c block/qapi.c block/qcow2-cache.c block/qcow2-cluster.c block/qcow2-refcount.c block/qcow2-snapshot.c block/qcow2.c block/qcow2.h block/qed.h block/raw-posix.c block/raw-win32.c block/raw_bsd.c block/rbd.c block/sheepdog.c block/stream.c block/vdi.c block/vhdx.c block/vmdk.c block/vpc.c blockdev.c blockjob.c bsd-user/qemu.h configure cpu-exec.c cputlb.c docs/qapi-code-gen.txt docs/qmp docs/rdma.txt docs/specs exec.c gdbstub.c hmp.c hw/9pfs hw/acpi hw/alpha hw/audio hw/block hw/char hw/display hw/i386 hw/ide hw/misc hw/net hw/pci hw/pci-host hw/s390x hw/scsi hw/sd hw/usb hw/xen include/block include/exec include/hw in clude/migration include/qapi include/qemu include/sysemu kvm-all.c kvm-stub.c libcacard/Makefile libcacard/vscclient.c linux-headers/asm-arm64 linux-headers/asm-mips linux-headers/asm-x86 linux-headers/linux linux-user/alpha linux-user/ioctls.h linux-user/linuxload.c linux-user/main.c linux-user/qemu.h linux-user/strace.list linux-user/syscall.c linux-user/syscall_defs.h migration-rdma.c migration.c net/socket.c pc-bios/README pc-bios/acpi-dsdt.aml pc-bios/bios.bin pc-bios/openbios-ppc pc-bios/openbios-sparc32 pc-bios/openbios-sparc64 pc-bios/q35-acpi-dsdt.aml pc-bios/s390-ccw pc-bios/s390-ccw.img qapi-schema.json qapi/qmp-registry.c qdev-monitor.c qemu-char.c qemu-io-cmds.c qemu-io.c qemu-seccomp.c qemu-timer.c qemu.nsi qga/commands-posix.c qga/commands.c qga/main.c qga/qapi-schema.json qmp-commands.hx qobject/qdict.c qom/cpu.c roms/Makefile roms/config.vga-cirrus roms/config.vga-isavga roms/config.vga-qxl roms/config.vga-stdvga roms/config.vga-vmware roms/config.vga.cirrus roms/config.vga.isavga roms/config.vga.qxl roms/config.vga.stdvga roms/config.vga.vmware roms/openbios roms/seabios savevm.c scripts/get_maintainer.pl scripts/qapi-types.py scripts/qapi-visit.py scripts/qmp scripts/refresh-pxe-roms.sh slirp/misc.c slirp/socket.c slirp/tcp_subr.c slirp/udp.c target-alpha/cpu.c target-alpha/helper.h target-alpha/translate.c target-arm/helper.c target-arm/helper.h target-arm/iwmmxt_helper.c target-arm/translate.c target-cris/helper.h target-cris/translate.c target-i386/arch_memory_mapping.c target-i386/cpu-qom.h target-i386/cpu.c target-i386/helper.c target-i386/machine.c target-i386/translate.c target-m68k/helper.c target-m68k/helper.h target-m68k/helpers.h target-m68k/op_helper.c target-m68k/translate.c target-microblaze/translate.c target-mips/helper.h target-mips/translate.c target-moxie/cpu.c target-openrisc/cpu.c target-openrisc/mmu.c target-openrisc/translate.c target-ppc/helper.h target-ppc/translate.c target-ppc/translate_init.c targe t-s390x/arch_dump.c target-s390x/cpu.h target-s390x/helper.c target-s390x/ioinst.c target-s390x/ioinst.h target-s390x/kvm.c target-s390x/misc_helper.c target-s390x/translate.c target-sh4/cpu.c target-sh4/translate.c target-sparc/cpu.c target-sparc/helper.h target-sparc/translate.c target-unicore32/helper.c target-unicore32/translate.c target-xtensa/translate.c tcg/README tcg/aarch64 tcg/arm tcg/hppa tcg/i386 tcg/ia64 tcg/mips tcg/optimize.c tcg/ppc tcg/ppc64 tcg/s390 tcg/sparc tcg/tcg-be-ldst.h tcg/tcg-be-null.h tcg/tcg-op.h tcg/tcg-opc.h tcg/tcg.c tcg/tcg.h tcg/tci tci.c tests/.gitignore tests/Makefile tests/qemu-iotests tests/test-coroutine.c trace-events translate-all.c util/iov.c util/osdep.c util/oslib-posix.c util/oslib-win32.c util/path.c util/qemu-option.c util/qemu-sockets.c version.rc vl.c xen-all.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Thu Oct 17 12:44:09 CEST 2013


 .gitmodules                                                 |   14 
 Changelog                                                   |    2 
 MAINTAINERS                                                 |   56 
 Makefile                                                    |   11 
 QMP/README                                                  |   88 
 QMP/qemu-ga-client                                          |  301 -
 QMP/qmp                                                     |  126 
 QMP/qmp-events.txt                                          |  502 ---
 QMP/qmp-shell                                               |  286 -
 QMP/qmp-spec.txt                                            |  282 -
 QMP/qmp.py                                                  |  196 -
 QMP/qom-fuse                                                |  138 
 QMP/qom-get                                                 |   67 
 QMP/qom-list                                                |   64 
 QMP/qom-set                                                 |   64 
 README                                                      |    2 
 arch_init.c                                                 |   42 
 audio/mixeng.c                                              |    6 
 block.c                                                     |  100 
 block/backup.c                                              |    6 
 block/blkdebug.c                                            |    8 
 block/blkverify.c                                           |   13 
 block/commit.c                                              |    6 
 block/gluster.c                                             |    4 
 block/iscsi.c                                               |    7 
 block/mirror.c                                              |    6 
 block/qapi.c                                                |  124 
 block/qcow2-cache.c                                         |    8 
 block/qcow2-cluster.c                                       |  114 
 block/qcow2-refcount.c                                      |   46 
 block/qcow2-snapshot.c                                      |   30 
 block/qcow2.c                                               |  131 
 block/qcow2.h                                               |   32 
 block/qed.h                                                 |    2 
 block/raw-posix.c                                           |   77 
 block/raw-win32.c                                           |   18 
 block/raw_bsd.c                                             |    7 
 block/rbd.c                                                 |    4 
 block/sheepdog.c                                            |    3 
 block/stream.c                                              |   11 
 block/vdi.c                                                 |    2 
 block/vhdx.c                                                |   10 
 block/vmdk.c                                                |  131 
 block/vpc.c                                                 |   28 
 blockdev.c                                                  |  680 ++--
 blockjob.c                                                  |   22 
 bsd-user/qemu.h                                             |    6 
 configure                                                   |   55 
 cpu-exec.c                                                  |    4 
 cputlb.c                                                    |   15 
 docs/qapi-code-gen.txt                                      |   17 
 docs/qmp/README                                             |   87 
 docs/qmp/qmp-events.txt                                     |  502 +++
 docs/qmp/qmp-spec.txt                                       |  273 +
 docs/rdma.txt                                               |    2 
 docs/specs/acpi_cpu_hotplug.txt                             |    2 
 docs/specs/qcow2.txt                                        |    3 
 exec.c                                                      |   57 
 gdbstub.c                                                   |    6 
 hmp.c                                                       |    2 
 hw/9pfs/virtio-9p-xattr.c                                   |    6 
 hw/acpi/core.c                                              |    3 
 hw/acpi/piix4.c                                             |    1 
 hw/alpha/typhoon.c                                          |    2 
 hw/audio/hda-codec-common.h                                 |  456 ++
 hw/audio/hda-codec.c                                        |  454 --
 hw/block/m25p80.c                                           |    5 
 hw/block/virtio-blk.c                                       |   24 
 hw/block/xen_disk.c                                         |    6 
 hw/char/Makefile.objs                                       |    2 
 hw/char/sclpconsole-lm.c                                    |  398 ++
 hw/char/sclpconsole.c                                       |   88 
 hw/char/sh_serial.c                                         |    2 
 hw/display/Makefile.objs                                    |    3 
 hw/display/qxl.c                                            |   12 
 hw/display/qxl.h                                            |    3 
 hw/i386/kvm/clock.c                                         |    2 
 hw/i386/kvmvapic.c                                          |   17 
 hw/i386/pc_piix.c                                           |    1 
 hw/i386/smbios.c                                            |  339 +-
 hw/ide/ahci.c                                               |   10 
 hw/misc/vfio.c                                              |  627 +++
 hw/net/e1000.c                                              |   70 
 hw/net/pcnet-pci.c                                          |    4 
 hw/net/virtio-net.c                                         |    1 
 hw/pci-host/piix.c                                          |   14 
 hw/pci-host/q35.c                                           |   26 
 hw/pci/pci.c                                                |   56 
 hw/s390x/event-facility.c                                   |   17 
 hw/s390x/sclpquiesce.c                                      |   29 
 hw/scsi/lsi53c895a.c                                        |   32 
 hw/scsi/scsi-bus.c                                          |   45 
 hw/sd/milkymist-memcard.c                                   |    4 
 hw/sd/omap_mmc.c                                            |    6 
 hw/sd/pl181.c                                               |    4 
 hw/sd/pxa2xx_mmci.c                                         |    3 
 hw/sd/sd.c                                                  |    5 
 hw/sd/sdhci.c                                               |    3 
 hw/sd/ssi-sd.c                                              |    3 
 hw/usb/combined-packet.c                                    |    1 
 hw/usb/core.c                                               |    3 
 hw/usb/hcd-ohci.c                                           |    2 
 hw/usb/hcd-xhci.c                                           |   45 
 hw/usb/host-bsd.c                                           |  639 ----
 hw/usb/host-linux.c                                         | 1911 ------------
 hw/xen/xen_backend.c                                        |   19 
 include/block/block.h                                       |   19 
 include/block/block_int.h                                   |   13 
 include/block/blockjob.h                                    |   14 
 include/block/qapi.h                                        |    2 
 include/exec/cpu-defs.h                                     |    2 
 include/exec/def-helper.h                                   |    3 
 include/exec/exec-all.h                                     |   48 
 include/exec/softmmu_template.h                             |  286 +
 include/hw/i386/pc.h                                        |    8 
 include/hw/i386/smbios.h                                    |    5 
 include/hw/pci-host/q35.h                                   |    2 
 include/hw/pci/pci.h                                        |    1 
 include/hw/pci/pci_ids.h                                    |    1 
 include/hw/qdev-core.h                                      |   16 
 include/hw/s390x/ebcdic.h                                   |  104 
 include/hw/s390x/event-facility.h                           |   88 
 include/hw/scsi/scsi.h                                      |    2 
 include/hw/virtio/virtio-blk.h                              |    1 
 include/migration/vmstate.h                                 |   17 
 include/qapi/qmp/dispatch.h                                 |    7 
 include/qapi/qmp/qdict.h                                    |    2 
 include/qemu/bitops.h                                       |   80 
 include/qemu/option.h                                       |    1 
 include/qemu/range.h                                        |   20 
 include/qemu/sockets.h                                      |    1 
 include/qemu/timer.h                                        |   17 
 include/qemu/typedefs.h                                     |    1 
 include/sysemu/arch_init.h                                  |    2 
 include/sysemu/blockdev.h                                   |    1 
 include/sysemu/char.h                                       |    1 
 include/sysemu/kvm.h                                        |   29 
 include/sysemu/sysemu.h                                     |    5 
 kvm-all.c                                                   |   82 
 kvm-stub.c                                                  |    1 
 libcacard/Makefile                                          |    3 
 libcacard/vscclient.c                                       |    3 
 linux-headers/asm-arm64/kvm.h                               |  168 +
 linux-headers/asm-arm64/kvm_para.h                          |    1 
 linux-headers/asm-mips/kvm.h                                |   81 
 linux-headers/asm-x86/kvm_para.h                            |    1 
 linux-headers/linux/kvm.h                                   |    4 
 linux-headers/linux/kvm_para.h                              |    1 
 linux-headers/linux/vfio.h                                  |   80 
 linux-headers/linux/virtio_config.h                         |    3 
 linux-user/alpha/syscall_nr.h                               |    4 
 linux-user/ioctls.h                                         |    1 
 linux-user/linuxload.c                                      |    8 
 linux-user/main.c                                           |  125 
 linux-user/qemu.h                                           |    8 
 linux-user/strace.list                                      |    9 
 linux-user/syscall.c                                        |  210 +
 linux-user/syscall_defs.h                                   |   12 
 migration-rdma.c                                            |   17 
 migration.c                                                 |    4 
 net/socket.c                                                |   19 
 pc-bios/README                                              |    4 
 pc-bios/acpi-dsdt.aml                                       |binary
 pc-bios/bios.bin                                            |binary
 pc-bios/openbios-ppc                                        |binary
 pc-bios/openbios-sparc32                                    |binary
 pc-bios/openbios-sparc64                                    |binary
 pc-bios/q35-acpi-dsdt.aml                                   |binary
 pc-bios/s390-ccw.img                                        |binary
 pc-bios/s390-ccw/virtio.c                                   |    7 
 pc-bios/s390-ccw/virtio.h                                   |    1 
 qapi-schema.json                                            |  288 +
 qapi/qmp-registry.c                                         |   33 
 qdev-monitor.c                                              |   85 
 qemu-char.c                                                 |   93 
 qemu-io-cmds.c                                              |    9 
 qemu-io.c                                                   |   39 
 qemu-seccomp.c                                              |    1 
 qemu-timer.c                                                |   92 
 qemu.nsi                                                    |    2 
 qga/commands-posix.c                                        |    4 
 qga/commands.c                                              |   39 
 qga/main.c                                                  |   75 
 qga/qapi-schema.json                                        |    5 
 qmp-commands.hx                                             |   55 
 qobject/qdict.c                                             |   21 
 qom/cpu.c                                                   |    1 
 roms/Makefile                                               |   99 
 roms/config.vga-cirrus                                      |    3 
 roms/config.vga-isavga                                      |    3 
 roms/config.vga-qxl                                         |    6 
 roms/config.vga-stdvga                                      |    3 
 roms/config.vga-vmware                                      |    6 
 roms/config.vga.cirrus                                      |    3 
 roms/config.vga.isavga                                      |    3 
 roms/config.vga.qxl                                         |    6 
 roms/config.vga.stdvga                                      |    3 
 roms/config.vga.vmware                                      |    6 
 roms/openbios                                               |    2 
 roms/seabios                                                |    2 
 savevm.c                                                    |    9 
 scripts/get_maintainer.pl                                   |    2 
 scripts/qapi-types.py                                       |   15 
 scripts/qapi-visit.py                                       |   26 
 scripts/qmp/qemu-ga-client                                  |  301 +
 scripts/qmp/qmp                                             |  126 
 scripts/qmp/qmp-shell                                       |  286 +
 scripts/qmp/qmp.py                                          |  196 +
 scripts/qmp/qom-fuse                                        |  138 
 scripts/qmp/qom-get                                         |   67 
 scripts/qmp/qom-list                                        |   64 
 scripts/qmp/qom-set                                         |   64 
 scripts/refresh-pxe-roms.sh                                 |   80 
 slirp/misc.c                                                |    3 
 slirp/socket.c                                              |    4 
 slirp/tcp_subr.c                                            |    6 
 slirp/udp.c                                                 |    4 
 target-alpha/cpu.c                                          |    4 
 target-alpha/helper.h                                       |    2 
 target-alpha/translate.c                                    |   53 
 target-arm/helper.c                                         |    3 
 target-arm/helper.h                                         |    8 
 target-arm/iwmmxt_helper.c                                  |    2 
 target-arm/translate.c                                      |    3 
 target-cris/helper.h                                        |    8 
 target-cris/translate.c                                     |    3 
 target-i386/arch_memory_mapping.c                           |    2 
 target-i386/cpu-qom.h                                       |    3 
 target-i386/cpu.c                                           |   28 
 target-i386/helper.c                                        |    6 
 target-i386/machine.c                                       |    6 
 target-i386/translate.c                                     |    4 
 target-m68k/helper.c                                        |    3 
 target-m68k/helper.h                                        |   54 
 target-m68k/helpers.h                                       |   54 
 target-m68k/op_helper.c                                     |    2 
 target-m68k/translate.c                                     |    7 
 target-microblaze/translate.c                               |    2 
 target-mips/helper.h                                        |   12 
 target-mips/translate.c                                     |    5 
 target-moxie/cpu.c                                          |    1 
 target-openrisc/cpu.c                                       |    1 
 target-openrisc/mmu.c                                       |    9 
 target-openrisc/translate.c                                 |    2 
 target-ppc/helper.h                                         |   10 
 target-ppc/translate.c                                      |    6 
 target-ppc/translate_init.c                                 |    3 
 target-s390x/arch_dump.c                                    |    1 
 target-s390x/cpu.h                                          |   11 
 target-s390x/helper.c                                       |    3 
 target-s390x/ioinst.c                                       |  110 
 target-s390x/ioinst.h                                       |   26 
 target-s390x/kvm.c                                          |   58 
 target-s390x/misc_helper.c                                  |  107 
 target-s390x/translate.c                                    |    4 
 target-sh4/cpu.c                                            |    3 
 target-sh4/translate.c                                      |    4 
 target-sparc/cpu.c                                          |    1 
 target-sparc/helper.h                                       |   18 
 target-sparc/translate.c                                    |    5 
 target-unicore32/helper.c                                   |    1 
 target-unicore32/translate.c                                |    3 
 target-xtensa/translate.c                                   |    2 
 tcg/README                                                  |   43 
 tcg/aarch64/tcg-target.c                                    |   51 
 tcg/aarch64/tcg-target.h                                    |    2 
 tcg/arm/tcg-target.c                                        |  802 ++---
 tcg/arm/tcg-target.h                                        |    2 
 tcg/hppa/tcg-target.c                                       | 1831 -----------
 tcg/hppa/tcg-target.h                                       |  123 
 tcg/i386/tcg-target.c                                       |  671 +---
 tcg/i386/tcg-target.h                                       |    2 
 tcg/ia64/tcg-target.c                                       |    2 
 tcg/ia64/tcg-target.h                                       |    2 
 tcg/mips/tcg-target.c                                       |    2 
 tcg/mips/tcg-target.h                                       |    2 
 tcg/optimize.c                                              |   12 
 tcg/ppc/tcg-target.c                                        |  684 +---
 tcg/ppc/tcg-target.h                                        |    2 
 tcg/ppc64/tcg-target.c                                      | 1162 +++----
 tcg/ppc64/tcg-target.h                                      |    2 
 tcg/s390/tcg-target.c                                       |    2 
 tcg/s390/tcg-target.h                                       |    2 
 tcg/sparc/tcg-target.c                                      |    2 
 tcg/sparc/tcg-target.h                                      |    4 
 tcg/tcg-be-ldst.h                                           |   90 
 tcg/tcg-be-null.h                                           |   43 
 tcg/tcg-op.h                                                |  239 -
 tcg/tcg-opc.h                                               |   96 
 tcg/tcg.c                                                   |  338 +-
 tcg/tcg.h                                                   |  166 -
 tcg/tci/tcg-target.c                                        |    3 
 tcg/tci/tcg-target.h                                        |    2 
 tci.c                                                       |   26 
 tests/.gitignore                                            |    4 
 tests/Makefile                                              |   24 
 tests/qemu-iotests/.gitignore                               |    1 
 tests/qemu-iotests/001                                      |    6 
 tests/qemu-iotests/002                                      |   36 
 tests/qemu-iotests/003                                      |   10 
 tests/qemu-iotests/004                                      |   24 
 tests/qemu-iotests/005                                      |    4 
 tests/qemu-iotests/007                                      |    2 
 tests/qemu-iotests/008                                      |    6 
 tests/qemu-iotests/009                                      |    2 
 tests/qemu-iotests/010                                      |    2 
 tests/qemu-iotests/011                                      |    2 
 tests/qemu-iotests/012                                      |    4 
 tests/qemu-iotests/013                                      |    4 
 tests/qemu-iotests/014                                      |    2 
 tests/qemu-iotests/015                                      |   16 
 tests/qemu-iotests/016                                      |   12 
 tests/qemu-iotests/018                                      |    6 
 tests/qemu-iotests/019                                      |   12 
 tests/qemu-iotests/020                                      |   12 
 tests/qemu-iotests/021                                      |    2 
 tests/qemu-iotests/023                                      |    4 
 tests/qemu-iotests/024                                      |   12 
 tests/qemu-iotests/025                                      |    4 
 tests/qemu-iotests/026                                      |   20 
 tests/qemu-iotests/026.out                                  |   32 
 tests/qemu-iotests/026.out.nocache                          |   32 
 tests/qemu-iotests/027                                      |   10 
 tests/qemu-iotests/028                                      |    6 
 tests/qemu-iotests/029                                      |   12 
 tests/qemu-iotests/031                                      |   12 
 tests/qemu-iotests/032                                      |    4 
 tests/qemu-iotests/033                                      |   18 
 tests/qemu-iotests/034                                      |   64 
 tests/qemu-iotests/035                                      |    2 
 tests/qemu-iotests/036                                      |    6 
 tests/qemu-iotests/037                                      |   62 
 tests/qemu-iotests/038                                      |   10 
 tests/qemu-iotests/039                                      |   28 
 tests/qemu-iotests/042                                      |   10 
 tests/qemu-iotests/043                                      |   32 
 tests/qemu-iotests/046                                      |   10 
 tests/qemu-iotests/047                                      |    2 
 tests/qemu-iotests/048                                      |    8 
 tests/qemu-iotests/049                                      |   36 
 tests/qemu-iotests/050                                      |   20 
 tests/qemu-iotests/051                                      |   67 
 tests/qemu-iotests/051.out                                  |   18 
 tests/qemu-iotests/052                                      |    7 
 tests/qemu-iotests/053                                      |   10 
 tests/qemu-iotests/054                                      |    2 
 tests/qemu-iotests/059                                      |   21 
 tests/qemu-iotests/059.out                                  |   25 
 tests/qemu-iotests/060                                      |   47 
 tests/qemu-iotests/060.out                                  |   40 
 tests/qemu-iotests/061                                      |    9 
 tests/qemu-iotests/061.out                                  |   11 
 tests/qemu-iotests/063                                      |   28 
 tests/qemu-iotests/064                                      |   62 
 tests/qemu-iotests/064.out                                  |   14 
 tests/qemu-iotests/065                                      |  125 
 tests/qemu-iotests/065.out                                  |    5 
 tests/qemu-iotests/066                                      |   63 
 tests/qemu-iotests/066.out                                  |   13 
 tests/qemu-iotests/067                                      |  133 
 tests/qemu-iotests/067.out                                  |   80 
 tests/qemu-iotests/common                                   |    8 
 tests/qemu-iotests/common.config                            |   11 
 tests/qemu-iotests/common.filter                            |    8 
 tests/qemu-iotests/common.rc                                |   54 
 tests/qemu-iotests/group                                    |    4 
 tests/qemu-iotests/iotests.py                               |    6 
 tests/qemu-iotests/sample_images/README                     |    8 
 tests/qemu-iotests/sample_images/iotest-dynamic-1G.vhdx.bz2 |binary
 tests/test-coroutine.c                                      |   45 
 trace-events                                                |    9 
 translate-all.c                                             |   17 
 util/iov.c                                                  |   10 
 util/osdep.c                                                |    7 
 util/oslib-posix.c                                          |   12 
 util/oslib-win32.c                                          |   10 
 util/path.c                                                 |    4 
 util/qemu-option.c                                          |    6 
 util/qemu-sockets.c                                         |    6 
 version.rc                                                  |    2 
 vl.c                                                        |   26 
 xen-all.c                                                   |   19 
 382 files changed, 11299 insertions(+), 11820 deletions(-)

New commits:
commit 1680d485777ecf436d724631ea8722cc0c66990e
Merge: ded77da f8da40a
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Mon Oct 14 09:59:59 2013 -0700

    Merge remote-tracking branch 'rth/tcg-ldst-6' into staging
    
    # By Richard Henderson
    # Via Richard Henderson
    * rth/tcg-ldst-6:
      target-alpha: Convert to new ldst opcodes
      tcg-ppc64: Support new ldst opcodes
      tcg-ppc: Support new ldst opcodes
      tcg-ppc64: Convert to le/be ldst helpers
      tcg-ppc: Convert to le/be ldst helpers
      tcg-ppc64: Use TCGMemOp within qemu_ldst routines
      tcg-ppc: Use TCGMemOp within qemu_ldst routines
      tcg-arm: Improve GUEST_BASE qemu_ld/st
      tcg-arm: Convert to new ldst opcodes
      tcg-arm: Tidy variable naming convention in qemu_ld/st
      tcg-arm: Convert to le/be ldst helpers
      tcg-arm: Use TCGMemOp within qemu_ldst routines
      tcg-i386: Support new ldst opcodes
      tcg-i386: Remove "cb" output restriction from qemu_st8 for i386
      tcg-i386: Tidy softmmu routines
      tcg-i386: Use TCGMemOp within qemu_ldst routines
      tcg: Use TCGMemOp for TCGLabelQemuLdst.opc
    
    Message-id: 1381620683-4568-1-git-send-email-rth at twiddle.net
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit ded77da3cd6b6bcd201a4e36abb3294d725be644
Merge: 08683cb 6ef8263
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Mon Oct 14 09:15:47 2013 -0700

    Merge remote-tracking branch 'jliu/or32' into staging
    
    # By Sebastian Macke
    # Via Jia Liu
    * jliu/or32:
      target-openrisc: Removes a non-conforming behavior for the first page of the memory
      target-openrisc: Correct handling of page faults.
    
    Message-id: 1380789702-18935-1-git-send-email-proljc at gmail.com
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit 08683cb53286848913d4b58afb3f975a29d93535
Merge: 575ddeb b1c50c5
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Mon Oct 14 09:14:30 2013 -0700

    Merge remote-tracking branch 'awilliam/tags/vfio-pci-for-qemu-20131010.0' into staging
    
    vfio-pci updates include:
     - Forgotten MSI affinity patch posted several months ago
     - Lazy option ROM loading to delay load until after device/bus resets
     - Error reporting cleanups
     - PCI hot reset support introduced with Linux v3.12 development kernels
     - Debug build fix for int128
    
    The lazy ROM loading and hot reset should help VGA assignment as we can
    now do a bus reset when there are multiple devices on the bus, ex.
    multi-function graphics and audio cards.
    
    # gpg: Signature made Thu 10 Oct 2013 11:26:39 AM PDT using RSA key ID 3BB08B22
    # gpg: Can't check signature: public key not found
    
    # By Alex Williamson (7) and Alexey Kardashevskiy (1)
    # Via Alex Williamson
    * awilliam/tags/vfio-pci-for-qemu-20131010.0:
      vfio-pci: Fix endian issues in vfio_pci_size_rom()
      vfio-pci: Add dummy PCI ROM write accessor
      vfio: Fix debug output for int128 values
      vfio-pci: Implement PCI hot reset
      vfio-pci: Cleanup error_reports
      vfio-pci: Lazy PCI option ROM loading
      vfio-pci: Test device reset capabilities
      vfio-pci: Add support for MSI affinity
    
    Message-id: 20131010184122.31667.28382.stgit at bling.home
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit 575ddeb459f622a114cbfe37d220c0519ec9c2a4
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Sep 29 20:56:45 2013 +0200

    exec: Fix prototype of phys_mem_set_alloc and related functions
    
    phys_mem_alloc and its assigned values qemu_anon_ram_alloc and
    legacy_s390_alloc must have identical argument lists.
    
    legacy_s390_alloc uses the size parameter to call mmap, so size_t is
    good enough for all of them.
    
    This patch fixes compiler errors on i686 Linux hosts:
    
      CC    alpha-softmmu/exec.o
    exec.c:752:51: error:
     initialization from incompatible pointer type [-Werror]
    exec.c: In function 'qemu_ram_alloc_from_ptr':
    exec.c:1139:32: error:
     comparison of distinct pointer types lacks a cast [-Werror]
    exec.c: In function 'qemu_ram_remap':
    exec.c:1283:21: error:
     comparison of distinct pointer types lacks a cast [-Werror]
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Message-id: 1380481005-32399-1-git-send-email-sw at weilnetz.de
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

diff --git a/exec.c b/exec.c
index 35ce832..bea2cff 100644
--- a/exec.c
+++ b/exec.c
@@ -717,14 +717,14 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
                              uint16_t section);
 static subpage_t *subpage_init(AddressSpace *as, hwaddr base);
 
-static void *(*phys_mem_alloc)(ram_addr_t size) = qemu_anon_ram_alloc;
+static void *(*phys_mem_alloc)(size_t size) = qemu_anon_ram_alloc;
 
 /*
  * Set a custom physical guest memory alloator.
  * Accelerators with unusual needs may need this.  Hopefully, we can
  * get rid of it eventually.
  */
-void phys_mem_set_alloc(void *(*alloc)(ram_addr_t))
+void phys_mem_set_alloc(void *(*alloc)(size_t))
 {
     phys_mem_alloc = alloc;
 }
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 6ad05ca..ea90b64 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -322,7 +322,7 @@ extern uintptr_t tci_tb_ptr;
 
 #if !defined(CONFIG_USER_ONLY)
 
-void phys_mem_set_alloc(void *(*alloc)(ram_addr_t));
+void phys_mem_set_alloc(void *(*alloc)(size_t));
 
 struct MemoryRegion *iotlb_to_region(hwaddr index);
 bool io_mem_read(struct MemoryRegion *mr, hwaddr addr,
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index a444f69..02ac4ba 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -93,7 +93,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
 
 static int cap_sync_regs;
 
-static void *legacy_s390_alloc(ram_addr_t size);
+static void *legacy_s390_alloc(size_t size);
 
 int kvm_arch_init(KVMState *s)
 {
@@ -325,7 +325,7 @@ int kvm_s390_get_registers_partial(CPUState *cs)
  * to grow. We also have to use MAP parameters that avoid
  * read-only mapping of guest pages.
  */
-static void *legacy_s390_alloc(ram_addr_t size)
+static void *legacy_s390_alloc(size_t size)
 {
     void *mem;
 
commit f8da40aefbd1b40a0c5ab6fb25987943fe01125c
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Sep 10 13:11:56 2013 -0700

    target-alpha: Convert to new ldst opcodes
    
    Or, partially.  The fundamental primitives for the port are gen_load_mem
    and gen_store_mem, which take a callback to emit the memory operation.
    For that, we continue to use the original inline functions that forward
    to the new ops, rather than replicate the same thing privately.
    
    That said, all free-standing calls to tcg_gen_qemu_* have been converted.
    The 32-bit floating-point references now use _i32 opcodes, eliminating
    a truncate or extension.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 9cb8084..c24910f 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -168,44 +168,38 @@ static inline ExitStatus gen_invalid(DisasContext *ctx)
 
 static inline void gen_qemu_ldf(TCGv t0, TCGv t1, int flags)
 {
-    TCGv tmp = tcg_temp_new();
     TCGv_i32 tmp32 = tcg_temp_new_i32();
-    tcg_gen_qemu_ld32u(tmp, t1, flags);
-    tcg_gen_trunc_i64_i32(tmp32, tmp);
+    tcg_gen_qemu_ld_i32(tmp32, t1, flags, MO_LEUL);
     gen_helper_memory_to_f(t0, tmp32);
     tcg_temp_free_i32(tmp32);
-    tcg_temp_free(tmp);
 }
 
 static inline void gen_qemu_ldg(TCGv t0, TCGv t1, int flags)
 {
     TCGv tmp = tcg_temp_new();
-    tcg_gen_qemu_ld64(tmp, t1, flags);
+    tcg_gen_qemu_ld_i64(tmp, t1, flags, MO_LEQ);
     gen_helper_memory_to_g(t0, tmp);
     tcg_temp_free(tmp);
 }
 
 static inline void gen_qemu_lds(TCGv t0, TCGv t1, int flags)
 {
-    TCGv tmp = tcg_temp_new();
     TCGv_i32 tmp32 = tcg_temp_new_i32();
-    tcg_gen_qemu_ld32u(tmp, t1, flags);
-    tcg_gen_trunc_i64_i32(tmp32, tmp);
+    tcg_gen_qemu_ld_i32(tmp32, t1, flags, MO_LEUL);
     gen_helper_memory_to_s(t0, tmp32);
     tcg_temp_free_i32(tmp32);
-    tcg_temp_free(tmp);
 }
 
 static inline void gen_qemu_ldl_l(TCGv t0, TCGv t1, int flags)
 {
-    tcg_gen_qemu_ld32s(t0, t1, flags);
+    tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LESL);
     tcg_gen_mov_i64(cpu_lock_addr, t1);
     tcg_gen_mov_i64(cpu_lock_value, t0);
 }
 
 static inline void gen_qemu_ldq_l(TCGv t0, TCGv t1, int flags)
 {
-    tcg_gen_qemu_ld64(t0, t1, flags);
+    tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LEQ);
     tcg_gen_mov_i64(cpu_lock_addr, t1);
     tcg_gen_mov_i64(cpu_lock_value, t0);
 }
@@ -247,11 +241,8 @@ static inline void gen_load_mem(DisasContext *ctx,
 static inline void gen_qemu_stf(TCGv t0, TCGv t1, int flags)
 {
     TCGv_i32 tmp32 = tcg_temp_new_i32();
-    TCGv tmp = tcg_temp_new();
     gen_helper_f_to_memory(tmp32, t0);
-    tcg_gen_extu_i32_i64(tmp, tmp32);
-    tcg_gen_qemu_st32(tmp, t1, flags);
-    tcg_temp_free(tmp);
+    tcg_gen_qemu_st_i32(tmp32, t1, flags, MO_LEUL);
     tcg_temp_free_i32(tmp32);
 }
 
@@ -259,18 +250,15 @@ static inline void gen_qemu_stg(TCGv t0, TCGv t1, int flags)
 {
     TCGv tmp = tcg_temp_new();
     gen_helper_g_to_memory(tmp, t0);
-    tcg_gen_qemu_st64(tmp, t1, flags);
+    tcg_gen_qemu_st_i64(tmp, t1, flags, MO_LEQ);
     tcg_temp_free(tmp);
 }
 
 static inline void gen_qemu_sts(TCGv t0, TCGv t1, int flags)
 {
     TCGv_i32 tmp32 = tcg_temp_new_i32();
-    TCGv tmp = tcg_temp_new();
     gen_helper_s_to_memory(tmp32, t0);
-    tcg_gen_extu_i32_i64(tmp, tmp32);
-    tcg_gen_qemu_st32(tmp, t1, flags);
-    tcg_temp_free(tmp);
+    tcg_gen_qemu_st_i32(tmp32, t1, flags, MO_LEUL);
     tcg_temp_free_i32(tmp32);
 }
 
@@ -348,18 +336,11 @@ static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
         tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
 
         val = tcg_temp_new();
-        if (quad) {
-            tcg_gen_qemu_ld64(val, addr, ctx->mem_idx);
-        } else {
-            tcg_gen_qemu_ld32s(val, addr, ctx->mem_idx);
-        }
+        tcg_gen_qemu_ld_i64(val, addr, ctx->mem_idx, quad ? MO_LEQ : MO_LESL);
         tcg_gen_brcond_i64(TCG_COND_NE, val, cpu_lock_value, lab_fail);
 
-        if (quad) {
-            tcg_gen_qemu_st64(cpu_ir[ra], addr, ctx->mem_idx);
-        } else {
-            tcg_gen_qemu_st32(cpu_ir[ra], addr, ctx->mem_idx);
-        }
+        tcg_gen_qemu_st_i64(cpu_ir[ra], addr, ctx->mem_idx,
+                            quad ? MO_LEQ : MO_LEUL);
         tcg_gen_movi_i64(cpu_ir[ra], 1);
         tcg_gen_br(lab_done);
 
@@ -2966,11 +2947,11 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
                 goto invalid_opc;
             case 0xA:
                 /* Longword virtual access with protection check (hw_ldl/w) */
-                tcg_gen_qemu_ld32s(cpu_ir[ra], addr, MMU_KERNEL_IDX);
+                tcg_gen_qemu_ld_i64(cpu_ir[ra], addr, MMU_KERNEL_IDX, MO_LESL);
                 break;
             case 0xB:
                 /* Quadword virtual access with protection check (hw_ldq/w) */
-                tcg_gen_qemu_ld64(cpu_ir[ra], addr, MMU_KERNEL_IDX);
+                tcg_gen_qemu_ld_i64(cpu_ir[ra], addr, MMU_KERNEL_IDX, MO_LEQ);
                 break;
             case 0xC:
                 /* Longword virtual access with alt access mode (hw_ldl/a)*/
@@ -2981,12 +2962,12 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             case 0xE:
                 /* Longword virtual access with alternate access mode and
                    protection checks (hw_ldl/wa) */
-                tcg_gen_qemu_ld32s(cpu_ir[ra], addr, MMU_USER_IDX);
+                tcg_gen_qemu_ld_i64(cpu_ir[ra], addr, MMU_USER_IDX, MO_LESL);
                 break;
             case 0xF:
                 /* Quadword virtual access with alternate access mode and
                    protection checks (hw_ldq/wa) */
-                tcg_gen_qemu_ld64(cpu_ir[ra], addr, MMU_USER_IDX);
+                tcg_gen_qemu_ld_i64(cpu_ir[ra], addr, MMU_USER_IDX, MO_LEQ);
                 break;
             }
             tcg_temp_free(addr);
commit 1768ec0623c1253df3bf1424b07fbccb164e85fb
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Sep 10 10:15:25 2013 -0700

    tcg-ppc64: Support new ldst opcodes
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index be29139..6109d86 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -1007,22 +1007,17 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 }
 #endif /* SOFTMMU */
 
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
+static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
+                            TCGMemOp opc, int mem_index)
 {
-    TCGReg addr_reg, data_reg, rbase;
+    TCGReg rbase;
     uint32_t insn;
     TCGMemOp s_bits = opc & MO_SIZE;
 #ifdef CONFIG_SOFTMMU
-    int mem_index;
     void *label_ptr;
 #endif
 
-    data_reg = *args++;
-    addr_reg = *args++;
-
 #ifdef CONFIG_SOFTMMU
-    mem_index = *args;
-
     addr_reg = tcg_out_tlb_read(s, s_bits, addr_reg, mem_index, true);
 
     /* Load a pointer into the current opcode w/conditional branch-link. */
@@ -1059,21 +1054,16 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 #endif
 }
 
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGMemOp opc)
+static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
+                            TCGMemOp opc, int mem_index)
 {
-    TCGReg addr_reg, rbase, data_reg;
+    TCGReg rbase;
     uint32_t insn;
 #ifdef CONFIG_SOFTMMU
-    int mem_index;
     void *label_ptr;
 #endif
 
-    data_reg = *args++;
-    addr_reg = *args++;
-
 #ifdef CONFIG_SOFTMMU
-    mem_index = *args;
-
     addr_reg = tcg_out_tlb_read(s, opc & MO_SIZE, addr_reg, mem_index, false);
 
     /* Load a pointer into the current opcode w/conditional branch-link. */
@@ -1838,39 +1828,13 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
         tcg_out32(s, DIVDU | TAB(args[0], args[1], args[2]));
         break;
 
-    case INDEX_op_qemu_ld8u:
-        tcg_out_qemu_ld(s, args, MO_UB);
-        break;
-    case INDEX_op_qemu_ld8s:
-        tcg_out_qemu_ld(s, args, MO_SB);
-        break;
-    case INDEX_op_qemu_ld16u:
-        tcg_out_qemu_ld(s, args, MO_TEUW);
-        break;
-    case INDEX_op_qemu_ld16s:
-        tcg_out_qemu_ld(s, args, MO_TESW);
-        break;
-    case INDEX_op_qemu_ld32:
-    case INDEX_op_qemu_ld32u:
-        tcg_out_qemu_ld(s, args, MO_TEUL);
-        break;
-    case INDEX_op_qemu_ld32s:
-        tcg_out_qemu_ld(s, args, MO_TESL);
-        break;
-    case INDEX_op_qemu_ld64:
-        tcg_out_qemu_ld(s, args, MO_TEQ);
-        break;
-    case INDEX_op_qemu_st8:
-        tcg_out_qemu_st(s, args, MO_UB);
-        break;
-    case INDEX_op_qemu_st16:
-        tcg_out_qemu_st(s, args, MO_TEUW);
-        break;
-    case INDEX_op_qemu_st32:
-        tcg_out_qemu_st(s, args, MO_TEUL);
+    case INDEX_op_qemu_ld_i32:
+    case INDEX_op_qemu_ld_i64:
+        tcg_out_qemu_ld(s, args[0], args[1], args[2], args[3]);
         break;
-    case INDEX_op_qemu_st64:
-        tcg_out_qemu_st(s, args, MO_TEQ);
+    case INDEX_op_qemu_st_i32:
+    case INDEX_op_qemu_st_i64:
+        tcg_out_qemu_st(s, args[0], args[1], args[2], args[3]);
         break;
 
     case INDEX_op_ext8s_i32:
@@ -2133,19 +2097,10 @@ static const TCGTargetOpDef ppc_op_defs[] = {
     { INDEX_op_neg_i64, { "r", "r" } },
     { INDEX_op_not_i64, { "r", "r" } },
 
-    { INDEX_op_qemu_ld8u, { "r", "L" } },
-    { INDEX_op_qemu_ld8s, { "r", "L" } },
-    { INDEX_op_qemu_ld16u, { "r", "L" } },
-    { INDEX_op_qemu_ld16s, { "r", "L" } },
-    { INDEX_op_qemu_ld32, { "r", "L" } },
-    { INDEX_op_qemu_ld32u, { "r", "L" } },
-    { INDEX_op_qemu_ld32s, { "r", "L" } },
-    { INDEX_op_qemu_ld64, { "r", "L" } },
-
-    { INDEX_op_qemu_st8, { "S", "S" } },
-    { INDEX_op_qemu_st16, { "S", "S" } },
-    { INDEX_op_qemu_st32, { "S", "S" } },
-    { INDEX_op_qemu_st64, { "S", "S" } },
+    { INDEX_op_qemu_ld_i32, { "r", "L" } },
+    { INDEX_op_qemu_ld_i64, { "r", "L" } },
+    { INDEX_op_qemu_st_i32, { "S", "S" } },
+    { INDEX_op_qemu_st_i64, { "S", "S" } },
 
     { INDEX_op_ext8s_i32, { "r", "r" } },
     { INDEX_op_ext16s_i32, { "r", "r" } },
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
index 457ea69..7ee50b6 100644
--- a/tcg/ppc64/tcg-target.h
+++ b/tcg/ppc64/tcg-target.h
@@ -123,7 +123,7 @@ typedef enum {
 #define TCG_TARGET_HAS_muluh_i64        1
 #define TCG_TARGET_HAS_mulsh_i64        1
 
-#define TCG_TARGET_HAS_new_ldst         0
+#define TCG_TARGET_HAS_new_ldst         1
 
 #define TCG_AREG0 TCG_REG_R27
 
commit 5dd391604f590938dd9fd335102442f1612e5eed
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Sep 10 10:00:27 2013 -0700

    tcg-ppc: Support new ldst opcodes
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index dadc108..dc2c2df 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -653,27 +653,26 @@ static void tcg_out_tlb_check(TCGContext *s, TCGReg r0, TCGReg r1, TCGReg r2,
 }
 #endif
 
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
 {
-    TCGReg addrlo, datalo, datahi, rbase;
-    TCGMemOp bswap = opc & MO_BSWAP;
-    TCGMemOp s_bits = opc & MO_SIZE;
+    TCGReg addrlo, datalo, datahi, rbase, addrhi __attribute__((unused));
+    TCGMemOp opc, bswap;
 #ifdef CONFIG_SOFTMMU
     int mem_index;
-    TCGReg addrhi;
     uint8_t *label_ptr;
 #endif
 
     datalo = *args++;
-    datahi = (s_bits == MO_64 ? *args++ : 0);
+    datahi = (is64 ? *args++ : 0);
     addrlo = *args++;
+    addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
+    opc = *args++;
+    bswap = opc & MO_BSWAP;
 
 #ifdef CONFIG_SOFTMMU
-    addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
     mem_index = *args;
-
     tcg_out_tlb_check(s, TCG_REG_R3, TCG_REG_R4, TCG_REG_R0, addrlo,
-                      addrhi, s_bits, mem_index, 0, &label_ptr);
+                      addrhi, opc & MO_SIZE, mem_index, 0, &label_ptr);
     rbase = TCG_REG_R3;
 #else  /* !CONFIG_SOFTMMU */
     rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
@@ -726,25 +725,25 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 #endif
 }
 
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGMemOp opc)
+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
 {
-    TCGReg addrlo, datalo, datahi, rbase;
-    TCGMemOp bswap = opc & MO_BSWAP;
-    TCGMemOp s_bits = opc & MO_SIZE;
+    TCGReg addrlo, datalo, datahi, rbase, addrhi __attribute__((unused));
+    TCGMemOp opc, bswap, s_bits;
 #ifdef CONFIG_SOFTMMU
     int mem_index;
-    TCGReg addrhi;
     uint8_t *label_ptr;
 #endif
 
     datalo = *args++;
-    datahi = (s_bits == MO_64 ? *args++ : 0);
+    datahi = (is64 ? *args++ : 0);
     addrlo = *args++;
+    addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
+    opc = *args++;
+    bswap = opc & MO_BSWAP;
+    s_bits = opc & MO_SIZE;
 
 #ifdef CONFIG_SOFTMMU
-    addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
     mem_index = *args;
-
     tcg_out_tlb_check(s, TCG_REG_R3, TCG_REG_R4, TCG_REG_R0, addrlo,
                       addrhi, s_bits, mem_index, 0, &label_ptr);
     rbase = TCG_REG_R3;
@@ -1707,35 +1706,17 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
         tcg_out32 (s, NOR | SAB (args[1], args[0], args[1]));
         break;
 
-    case INDEX_op_qemu_ld8u:
-        tcg_out_qemu_ld(s, args, MO_UB);
-        break;
-    case INDEX_op_qemu_ld8s:
-        tcg_out_qemu_ld(s, args, MO_SB);
-        break;
-    case INDEX_op_qemu_ld16u:
-        tcg_out_qemu_ld(s, args, MO_TEUW);
-        break;
-    case INDEX_op_qemu_ld16s:
-        tcg_out_qemu_ld(s, args, MO_TESW);
-        break;
-    case INDEX_op_qemu_ld32:
-        tcg_out_qemu_ld(s, args, MO_TEUL);
-        break;
-    case INDEX_op_qemu_ld64:
-        tcg_out_qemu_ld(s, args, MO_TEQ);
-        break;
-    case INDEX_op_qemu_st8:
-        tcg_out_qemu_st(s, args, MO_UB);
+    case INDEX_op_qemu_ld_i32:
+        tcg_out_qemu_ld(s, args, 0);
         break;
-    case INDEX_op_qemu_st16:
-        tcg_out_qemu_st(s, args, MO_TEUW);
+    case INDEX_op_qemu_ld_i64:
+        tcg_out_qemu_ld(s, args, 1);
         break;
-    case INDEX_op_qemu_st32:
-        tcg_out_qemu_st(s, args, MO_TEUL);
+    case INDEX_op_qemu_st_i32:
+        tcg_out_qemu_st(s, args, 0);
         break;
-    case INDEX_op_qemu_st64:
-        tcg_out_qemu_st(s, args, MO_TEQ);
+    case INDEX_op_qemu_st_i64:
+        tcg_out_qemu_st(s, args, 1);
         break;
 
     case INDEX_op_ext8s_i32:
@@ -1920,29 +1901,15 @@ static const TCGTargetOpDef ppc_op_defs[] = {
     { INDEX_op_bswap32_i32, { "r", "r" } },
 
 #if TARGET_LONG_BITS == 32
-    { INDEX_op_qemu_ld8u, { "r", "L" } },
-    { INDEX_op_qemu_ld8s, { "r", "L" } },
-    { INDEX_op_qemu_ld16u, { "r", "L" } },
-    { INDEX_op_qemu_ld16s, { "r", "L" } },
-    { INDEX_op_qemu_ld32, { "r", "L" } },
-    { INDEX_op_qemu_ld64, { "L", "L", "L" } },
-
-    { INDEX_op_qemu_st8, { "K", "K" } },
-    { INDEX_op_qemu_st16, { "K", "K" } },
-    { INDEX_op_qemu_st32, { "K", "K" } },
-    { INDEX_op_qemu_st64, { "M", "M", "M" } },
+    { INDEX_op_qemu_ld_i32, { "r", "L" } },
+    { INDEX_op_qemu_ld_i64, { "L", "L", "L" } },
+    { INDEX_op_qemu_st_i32, { "K", "K" } },
+    { INDEX_op_qemu_st_i64, { "M", "M", "M" } },
 #else
-    { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
-    { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
-    { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
-    { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
-    { INDEX_op_qemu_ld32, { "r", "L", "L" } },
-    { INDEX_op_qemu_ld64, { "L", "L", "L", "L" } },
-
-    { INDEX_op_qemu_st8, { "K", "K", "K" } },
-    { INDEX_op_qemu_st16, { "K", "K", "K" } },
-    { INDEX_op_qemu_st32, { "K", "K", "K" } },
-    { INDEX_op_qemu_st64, { "M", "M", "M", "M" } },
+    { INDEX_op_qemu_ld_i32, { "r", "L", "L" } },
+    { INDEX_op_qemu_ld_i64, { "L", "L", "L", "L" } },
+    { INDEX_op_qemu_st_i32, { "K", "K", "K" } },
+    { INDEX_op_qemu_st_i64, { "M", "M", "M", "M" } },
 #endif
 
     { INDEX_op_ext8s_i32, { "r", "r" } },
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index e3ac629..e3395e3 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -99,7 +99,7 @@ typedef enum {
 #define TCG_TARGET_HAS_muluh_i32        0
 #define TCG_TARGET_HAS_mulsh_i32        0
 
-#define TCG_TARGET_HAS_new_ldst         0
+#define TCG_TARGET_HAS_new_ldst         1
 
 #define TCG_AREG0 TCG_REG_R27
 
commit e349a8d4ffb63e8e16c67d1702dd728d781424d6
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Sep 10 09:05:15 2013 -0700

    tcg-ppc64: Convert to le/be ldst helpers
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 499805f..be29139 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -841,21 +841,27 @@ static const uint32_t qemu_exts_opc[4] = {
 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
  *                                 int mmu_idx, uintptr_t ra)
  */
-static const void * const qemu_ld_helpers[4] = {
-    helper_ret_ldub_mmu,
-    helper_ret_lduw_mmu,
-    helper_ret_ldul_mmu,
-    helper_ret_ldq_mmu,
+static const void * const qemu_ld_helpers[16] = {
+    [MO_UB]   = helper_ret_ldub_mmu,
+    [MO_LEUW] = helper_le_lduw_mmu,
+    [MO_LEUL] = helper_le_ldul_mmu,
+    [MO_LEQ]  = helper_le_ldq_mmu,
+    [MO_BEUW] = helper_be_lduw_mmu,
+    [MO_BEUL] = helper_be_ldul_mmu,
+    [MO_BEQ]  = helper_be_ldq_mmu,
 };
 
 /* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
  *                                 uintxx_t val, int mmu_idx, uintptr_t ra)
  */
-static const void * const qemu_st_helpers[4] = {
-    helper_ret_stb_mmu,
-    helper_ret_stw_mmu,
-    helper_ret_stl_mmu,
-    helper_ret_stq_mmu,
+static const void * const qemu_st_helpers[16] = {
+    [MO_UB]   = helper_ret_stb_mmu,
+    [MO_LEUW] = helper_le_stw_mmu,
+    [MO_LEUL] = helper_le_stl_mmu,
+    [MO_LEQ]  = helper_le_stq_mmu,
+    [MO_BEUW] = helper_be_stw_mmu,
+    [MO_BEUL] = helper_be_stl_mmu,
+    [MO_BEQ]  = helper_be_stq_mmu,
 };
 
 /* Perform the TLB load and compare.  Places the result of the comparison
@@ -952,8 +958,7 @@ static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
 
 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 {
-    TCGMemOp opc = lb->opc & MO_SSIZE;
-    TCGMemOp s_bits = lb->opc & MO_SIZE;
+    TCGMemOp opc = lb->opc;
 
     reloc_pc14(lb->label_ptr[0], (uintptr_t)s->code_ptr);
 
@@ -966,10 +971,10 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R5, lb->mem_index);
     tcg_out32(s, MFSPR | RT(TCG_REG_R6) | LR);
 
-    tcg_out_call(s, (tcg_target_long)qemu_ld_helpers[s_bits], 1);
+    tcg_out_call(s, (tcg_target_long)qemu_ld_helpers[opc & ~MO_SIGN], 1);
 
     if (opc & MO_SIGN) {
-        uint32_t insn = qemu_exts_opc[s_bits];
+        uint32_t insn = qemu_exts_opc[opc & MO_SIZE];
         tcg_out32(s, insn | RA(lb->datalo_reg) | RS(TCG_REG_R3));
     } else {
         tcg_out_mov(s, TCG_TYPE_I64, lb->datalo_reg, TCG_REG_R3);
@@ -980,7 +985,8 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 
 static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 {
-    TCGMemOp s_bits = lb->opc & MO_SIZE;
+    TCGMemOp opc = lb->opc;
+    TCGMemOp s_bits = opc & MO_SIZE;
 
     reloc_pc14(lb->label_ptr[0], (uintptr_t)s->code_ptr);
 
@@ -995,7 +1001,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R6, lb->mem_index);
     tcg_out32(s, MFSPR | RT(TCG_REG_R7) | LR);
 
-    tcg_out_call(s, (tcg_target_long)qemu_st_helpers[s_bits], 1);
+    tcg_out_call(s, (tcg_target_long)qemu_st_helpers[opc], 1);
 
     tcg_out_b(s, 0, (uintptr_t)lb->raddr);
 }
commit 92d0acda271f54a96956b9aef5031e702e12a700
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Sep 10 08:54:04 2013 -0700

    tcg-ppc: Convert to le/be ldst helpers
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index c1b0908..dadc108 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -550,25 +550,31 @@ static void add_qemu_ldst_label (TCGContext *s,
 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
  *                                     int mmu_idx, uintptr_t ra)
  */
-static const void * const qemu_ld_helpers[4] = {
-    helper_ret_ldub_mmu,
-    helper_ret_lduw_mmu,
-    helper_ret_ldul_mmu,
-    helper_ret_ldq_mmu,
+static const void * const qemu_ld_helpers[16] = {
+    [MO_UB]   = helper_ret_ldub_mmu,
+    [MO_LEUW] = helper_le_lduw_mmu,
+    [MO_LEUL] = helper_le_ldul_mmu,
+    [MO_LEQ]  = helper_le_ldq_mmu,
+    [MO_BEUW] = helper_be_lduw_mmu,
+    [MO_BEUL] = helper_be_ldul_mmu,
+    [MO_BEQ]  = helper_be_ldq_mmu,
 };
 
 /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
  *                                     uintxx_t val, int mmu_idx, uintptr_t ra)
  */
-static const void * const qemu_st_helpers[4] = {
-    helper_ret_stb_mmu,
-    helper_ret_stw_mmu,
-    helper_ret_stl_mmu,
-    helper_ret_stq_mmu,
+static const void * const qemu_st_helpers[16] = {
+    [MO_UB]   = helper_ret_stb_mmu,
+    [MO_LEUW] = helper_le_stw_mmu,
+    [MO_LEUL] = helper_le_stl_mmu,
+    [MO_LEQ]  = helper_le_stq_mmu,
+    [MO_BEUW] = helper_be_stw_mmu,
+    [MO_BEUL] = helper_be_stl_mmu,
+    [MO_BEQ]  = helper_be_stq_mmu,
 };
 
-static void *ld_trampolines[4];
-static void *st_trampolines[4];
+static void *ld_trampolines[16];
+static void *st_trampolines[16];
 
 /* Perform the TLB load and compare.  Branches to the slow path, placing the
    address of the branch in *LABEL_PTR.  Loads the addend of the TLB into R0.
@@ -783,7 +789,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
 {
     TCGReg ir, datalo, datahi;
-    TCGMemOp opc = l->opc & MO_SSIZE;
+    TCGMemOp opc = l->opc;
 
     reloc_pc14 (l->label_ptr[0], (uintptr_t)s->code_ptr);
 
@@ -799,10 +805,10 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
     }
     tcg_out_movi(s, TCG_TYPE_I32, ir++, l->mem_index);
     tcg_out32(s, MFSPR | RT(ir++) | LR);
-    tcg_out_b(s, LK, (uintptr_t)ld_trampolines[opc & MO_SIZE]);
+    tcg_out_b(s, LK, (uintptr_t)ld_trampolines[opc & ~MO_SIGN]);
 
     datalo = l->datalo_reg;
-    switch (opc) {
+    switch (opc & MO_SSIZE) {
     case MO_SB:
         tcg_out32(s, EXTSB | RA(datalo) | RS(TCG_REG_R3));
         break;
@@ -833,7 +839,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
 static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
 {
     TCGReg ir, datalo;
-    TCGMemOp s_bits = l->opc & MO_SIZE;
+    TCGMemOp opc = l->opc;
 
     reloc_pc14 (l->label_ptr[0], (tcg_target_long) s->code_ptr);
 
@@ -849,7 +855,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
     }
 
     datalo = l->datalo_reg;
-    switch (s_bits) {
+    switch (opc & MO_SIZE) {
     case MO_8:
         tcg_out32(s, (RLWINM | RA (ir) | RS (datalo)
                       | SH (0) | MB (24) | ME (31)));
@@ -873,7 +879,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
 
     tcg_out_movi(s, TCG_TYPE_I32, ir++, l->mem_index);
     tcg_out32(s, MFSPR | RT(ir++) | LR);
-    tcg_out_b(s, LK, (uintptr_t)st_trampolines[l->opc]);
+    tcg_out_b(s, LK, (uintptr_t)st_trampolines[opc]);
     tcg_out_b(s, 0, (uintptr_t)l->raddr);
 }
 #endif
@@ -948,12 +954,15 @@ static void tcg_target_qemu_prologue (TCGContext *s)
     tcg_out32 (s, BCLR | BO_ALWAYS);
 
 #ifdef CONFIG_SOFTMMU
-    for (i = 0; i < 4; ++i) {
-        ld_trampolines[i] = s->code_ptr;
-        emit_ldst_trampoline (s, qemu_ld_helpers[i]);
-
-        st_trampolines[i] = s->code_ptr;
-        emit_ldst_trampoline (s, qemu_st_helpers[i]);
+    for (i = 0; i < 16; ++i) {
+        if (qemu_ld_helpers[i]) {
+            ld_trampolines[i] = s->code_ptr;
+            emit_ldst_trampoline(s, qemu_ld_helpers[i]);
+        }
+        if (qemu_st_helpers[i]) {
+            st_trampolines[i] = s->code_ptr;
+            emit_ldst_trampoline(s, qemu_st_helpers[i]);
+        }
     }
 #endif
 }
commit a058557381e6bb4c7688572bba7b3a4c01234955
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Sep 3 17:05:37 2013 -0700

    tcg-ppc64: Use TCGMemOp within qemu_ldst routines
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 12c1f61..499805f 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -809,22 +809,28 @@ static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
     }
 }
 
-static const uint32_t qemu_ldx_opc[8] = {
-#ifdef TARGET_WORDS_BIGENDIAN
-    LBZX, LHZX, LWZX, LDX,
-    0,    LHAX, LWAX, LDX
-#else
-    LBZX, LHBRX, LWBRX, LDBRX,
-    0,    0,     0,     LDBRX,
-#endif
+static const uint32_t qemu_ldx_opc[16] = {
+    [MO_UB] = LBZX,
+    [MO_UW] = LHZX,
+    [MO_UL] = LWZX,
+    [MO_Q]  = LDX,
+    [MO_SW] = LHAX,
+    [MO_SL] = LWAX,
+    [MO_BSWAP | MO_UB] = LBZX,
+    [MO_BSWAP | MO_UW] = LHBRX,
+    [MO_BSWAP | MO_UL] = LWBRX,
+    [MO_BSWAP | MO_Q]  = LDBRX,
 };
 
-static const uint32_t qemu_stx_opc[4] = {
-#ifdef TARGET_WORDS_BIGENDIAN
-    STBX, STHX, STWX, STDX
-#else
-    STBX, STHBRX, STWBRX, STDBRX,
-#endif
+static const uint32_t qemu_stx_opc[16] = {
+    [MO_UB] = STBX,
+    [MO_UW] = STHX,
+    [MO_UL] = STWX,
+    [MO_Q]  = STDX,
+    [MO_BSWAP | MO_UB] = STBX,
+    [MO_BSWAP | MO_UW] = STHBRX,
+    [MO_BSWAP | MO_UL] = STWBRX,
+    [MO_BSWAP | MO_Q]  = STDBRX,
 };
 
 static const uint32_t qemu_exts_opc[4] = {
@@ -856,7 +862,7 @@ static const void * const qemu_st_helpers[4] = {
    in CR7, loads the addend of the TLB into R3, and returns the register
    containing the guest address (zero-extended into R4).  Clobbers R0 and R2. */
 
-static TCGReg tcg_out_tlb_read(TCGContext *s, int s_bits, TCGReg addr_reg,
+static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits, TCGReg addr_reg,
                                int mem_index, bool is_read)
 {
     int cmp_off
@@ -929,7 +935,7 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, int s_bits, TCGReg addr_reg,
 /* Record the context of a call to the out of line helper code for the slow
    path for a load or store, so that we can later generate the correct
    helper code.  */
-static void add_qemu_ldst_label(TCGContext *s, bool is_ld, int opc,
+static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
                                 int data_reg, int addr_reg, int mem_index,
                                 uint8_t *raddr, uint8_t *label_ptr)
 {
@@ -946,8 +952,8 @@ static void add_qemu_ldst_label(TCGContext *s, bool is_ld, int opc,
 
 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 {
-    int opc = lb->opc;
-    int s_bits = opc & 3;
+    TCGMemOp opc = lb->opc & MO_SSIZE;
+    TCGMemOp s_bits = lb->opc & MO_SIZE;
 
     reloc_pc14(lb->label_ptr[0], (uintptr_t)s->code_ptr);
 
@@ -962,7 +968,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 
     tcg_out_call(s, (tcg_target_long)qemu_ld_helpers[s_bits], 1);
 
-    if (opc & 4) {
+    if (opc & MO_SIGN) {
         uint32_t insn = qemu_exts_opc[s_bits];
         tcg_out32(s, insn | RA(lb->datalo_reg) | RS(TCG_REG_R3));
     } else {
@@ -974,7 +980,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 
 static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 {
-    int opc = lb->opc;
+    TCGMemOp s_bits = lb->opc & MO_SIZE;
 
     reloc_pc14(lb->label_ptr[0], (uintptr_t)s->code_ptr);
 
@@ -985,20 +991,21 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
     tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R4, lb->addrlo_reg);
 
     tcg_out_rld(s, RLDICL, TCG_REG_R5, lb->datalo_reg,
-                0, 64 - (1 << (3 + opc)));
+                0, 64 - (1 << (3 + s_bits)));
     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R6, lb->mem_index);
     tcg_out32(s, MFSPR | RT(TCG_REG_R7) | LR);
 
-    tcg_out_call(s, (tcg_target_long)qemu_st_helpers[opc], 1);
+    tcg_out_call(s, (tcg_target_long)qemu_st_helpers[s_bits], 1);
 
     tcg_out_b(s, 0, (uintptr_t)lb->raddr);
 }
 #endif /* SOFTMMU */
 
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 {
     TCGReg addr_reg, data_reg, rbase;
-    uint32_t insn, s_bits;
+    uint32_t insn;
+    TCGMemOp s_bits = opc & MO_SIZE;
 #ifdef CONFIG_SOFTMMU
     int mem_index;
     void *label_ptr;
@@ -1006,7 +1013,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 
     data_reg = *args++;
     addr_reg = *args++;
-    s_bits = opc & 3;
 
 #ifdef CONFIG_SOFTMMU
     mem_index = *args;
@@ -1035,7 +1041,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     } else if (insn) {
         tcg_out32(s, insn | TAB(data_reg, rbase, addr_reg));
     } else {
-        insn = qemu_ldx_opc[s_bits];
+        insn = qemu_ldx_opc[opc & (MO_SIZE | MO_BSWAP)];
         tcg_out32(s, insn | TAB(data_reg, rbase, addr_reg));
         insn = qemu_exts_opc[s_bits];
         tcg_out32(s, insn | RA(data_reg) | RS(data_reg));
@@ -1047,7 +1053,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 #endif
 }
 
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 {
     TCGReg addr_reg, rbase, data_reg;
     uint32_t insn;
@@ -1062,7 +1068,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
 #ifdef CONFIG_SOFTMMU
     mem_index = *args;
 
-    addr_reg = tcg_out_tlb_read(s, opc, addr_reg, mem_index, false);
+    addr_reg = tcg_out_tlb_read(s, opc & MO_SIZE, addr_reg, mem_index, false);
 
     /* Load a pointer into the current opcode w/conditional branch-link. */
     label_ptr = s->code_ptr;
@@ -1827,38 +1833,38 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
         break;
 
     case INDEX_op_qemu_ld8u:
-        tcg_out_qemu_ld(s, args, 0);
+        tcg_out_qemu_ld(s, args, MO_UB);
         break;
     case INDEX_op_qemu_ld8s:
-        tcg_out_qemu_ld(s, args, 0 | 4);
+        tcg_out_qemu_ld(s, args, MO_SB);
         break;
     case INDEX_op_qemu_ld16u:
-        tcg_out_qemu_ld(s, args, 1);
+        tcg_out_qemu_ld(s, args, MO_TEUW);
         break;
     case INDEX_op_qemu_ld16s:
-        tcg_out_qemu_ld(s, args, 1 | 4);
+        tcg_out_qemu_ld(s, args, MO_TESW);
         break;
     case INDEX_op_qemu_ld32:
     case INDEX_op_qemu_ld32u:
-        tcg_out_qemu_ld(s, args, 2);
+        tcg_out_qemu_ld(s, args, MO_TEUL);
         break;
     case INDEX_op_qemu_ld32s:
-        tcg_out_qemu_ld(s, args, 2 | 4);
+        tcg_out_qemu_ld(s, args, MO_TESL);
         break;
     case INDEX_op_qemu_ld64:
-        tcg_out_qemu_ld(s, args, 3);
+        tcg_out_qemu_ld(s, args, MO_TEQ);
         break;
     case INDEX_op_qemu_st8:
-        tcg_out_qemu_st(s, args, 0);
+        tcg_out_qemu_st(s, args, MO_UB);
         break;
     case INDEX_op_qemu_st16:
-        tcg_out_qemu_st(s, args, 1);
+        tcg_out_qemu_st(s, args, MO_TEUW);
         break;
     case INDEX_op_qemu_st32:
-        tcg_out_qemu_st(s, args, 2);
+        tcg_out_qemu_st(s, args, MO_TEUL);
         break;
     case INDEX_op_qemu_st64:
-        tcg_out_qemu_st(s, args, 3);
+        tcg_out_qemu_st(s, args, MO_TEQ);
         break;
 
     case INDEX_op_ext8s_i32:
commit f1a16dcdd5d52aa92563c8798d1b3e304c1245f9
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Sep 3 17:05:31 2013 -0700

    tcg-ppc: Use TCGMemOp within qemu_ldst routines
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 68778c2..c1b0908 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -525,7 +525,7 @@ static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg,
 
 static void add_qemu_ldst_label (TCGContext *s,
                                  int is_ld,
-                                 int opc,
+                                 TCGMemOp opc,
                                  int data_reg,
                                  int data_reg2,
                                  int addrlo_reg,
@@ -575,7 +575,7 @@ static void *st_trampolines[4];
    Clobbers R1 and R2.  */
 
 static void tcg_out_tlb_check(TCGContext *s, TCGReg r0, TCGReg r1, TCGReg r2,
-                              TCGReg addrlo, TCGReg addrhi, int s_bits,
+                              TCGReg addrlo, TCGReg addrhi, TCGMemOp s_bits,
                               int mem_index, int is_load, uint8_t **label_ptr)
 {
     int cmp_off =
@@ -647,10 +647,11 @@ static void tcg_out_tlb_check(TCGContext *s, TCGReg r0, TCGReg r1, TCGReg r2,
 }
 #endif
 
-static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 {
     TCGReg addrlo, datalo, datahi, rbase;
-    int bswap;
+    TCGMemOp bswap = opc & MO_BSWAP;
+    TCGMemOp s_bits = opc & MO_SIZE;
 #ifdef CONFIG_SOFTMMU
     int mem_index;
     TCGReg addrhi;
@@ -658,7 +659,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
 #endif
 
     datalo = *args++;
-    datahi = (opc == 3 ? *args++ : 0);
+    datahi = (s_bits == MO_64 ? *args++ : 0);
     addrlo = *args++;
 
 #ifdef CONFIG_SOFTMMU
@@ -666,31 +667,25 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
     mem_index = *args;
 
     tcg_out_tlb_check(s, TCG_REG_R3, TCG_REG_R4, TCG_REG_R0, addrlo,
-                      addrhi, opc & 3, mem_index, 0, &label_ptr);
+                      addrhi, s_bits, mem_index, 0, &label_ptr);
     rbase = TCG_REG_R3;
 #else  /* !CONFIG_SOFTMMU */
     rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
 #endif
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    bswap = 0;
-#else
-    bswap = 1;
-#endif
-
-    switch (opc) {
+    switch (opc & MO_SSIZE) {
     default:
-    case 0:
+    case MO_UB:
         tcg_out32(s, LBZX | TAB(datalo, rbase, addrlo));
         break;
-    case 0|4:
+    case MO_SB:
         tcg_out32(s, LBZX | TAB(datalo, rbase, addrlo));
         tcg_out32(s, EXTSB | RA(datalo) | RS(datalo));
         break;
-    case 1:
+    case MO_UW:
         tcg_out32(s, (bswap ? LHBRX : LHZX) | TAB(datalo, rbase, addrlo));
         break;
-    case 1|4:
+    case MO_SW:
         if (bswap) {
             tcg_out32(s, LHBRX | TAB(datalo, rbase, addrlo));
             tcg_out32(s, EXTSH | RA(datalo) | RS(datalo));
@@ -698,10 +693,10 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
             tcg_out32(s, LHAX | TAB(datalo, rbase, addrlo));
         }
         break;
-    case 2:
+    case MO_UL:
         tcg_out32(s, (bswap ? LWBRX : LWZX) | TAB(datalo, rbase, addrlo));
         break;
-    case 3:
+    case MO_Q:
         if (bswap) {
             tcg_out32(s, ADDI | RT(TCG_REG_R0) | RA(addrlo) | 4);
             tcg_out32(s, LWBRX | TAB(datalo, rbase, addrlo));
@@ -725,10 +720,11 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
 #endif
 }
 
-static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 {
     TCGReg addrlo, datalo, datahi, rbase;
-    int bswap;
+    TCGMemOp bswap = opc & MO_BSWAP;
+    TCGMemOp s_bits = opc & MO_SIZE;
 #ifdef CONFIG_SOFTMMU
     int mem_index;
     TCGReg addrhi;
@@ -736,7 +732,7 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
 #endif
 
     datalo = *args++;
-    datahi = (opc == 3 ? *args++ : 0);
+    datahi = (s_bits == MO_64 ? *args++ : 0);
     addrlo = *args++;
 
 #ifdef CONFIG_SOFTMMU
@@ -744,28 +740,24 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
     mem_index = *args;
 
     tcg_out_tlb_check(s, TCG_REG_R3, TCG_REG_R4, TCG_REG_R0, addrlo,
-                      addrhi, opc & 3, mem_index, 0, &label_ptr);
+                      addrhi, s_bits, mem_index, 0, &label_ptr);
     rbase = TCG_REG_R3;
 #else  /* !CONFIG_SOFTMMU */
     rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
 #endif
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    bswap = 0;
-#else
-    bswap = 1;
-#endif
-    switch (opc) {
-    case 0:
+    switch (s_bits) {
+    case MO_8:
         tcg_out32(s, STBX | SAB(datalo, rbase, addrlo));
         break;
-    case 1:
+    case MO_16:
         tcg_out32(s, (bswap ? STHBRX : STHX) | SAB(datalo, rbase, addrlo));
         break;
-    case 2:
+    case MO_32:
+    default:
         tcg_out32(s, (bswap ? STWBRX : STWX) | SAB(datalo, rbase, addrlo));
         break;
-    case 3:
+    case MO_64:
         if (bswap) {
             tcg_out32(s, ADDI | RT(TCG_REG_R0) | RA(addrlo) | 4);
             tcg_out32(s, STWBRX | SAB(datalo, rbase, addrlo));
@@ -791,6 +783,7 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
 {
     TCGReg ir, datalo, datahi;
+    TCGMemOp opc = l->opc & MO_SSIZE;
 
     reloc_pc14 (l->label_ptr[0], (uintptr_t)s->code_ptr);
 
@@ -806,22 +799,20 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
     }
     tcg_out_movi(s, TCG_TYPE_I32, ir++, l->mem_index);
     tcg_out32(s, MFSPR | RT(ir++) | LR);
-    tcg_out_b(s, LK, (uintptr_t)ld_trampolines[l->opc & 3]);
+    tcg_out_b(s, LK, (uintptr_t)ld_trampolines[opc & MO_SIZE]);
 
     datalo = l->datalo_reg;
-    switch (l->opc) {
-    case 0|4:
+    switch (opc) {
+    case MO_SB:
         tcg_out32(s, EXTSB | RA(datalo) | RS(TCG_REG_R3));
         break;
-    case 1|4:
+    case MO_SW:
         tcg_out32(s, EXTSH | RA(datalo) | RS(TCG_REG_R3));
         break;
-    case 0:
-    case 1:
-    case 2:
+    default:
         tcg_out_mov(s, TCG_TYPE_I32, datalo, TCG_REG_R3);
         break;
-    case 3:
+    case MO_Q:
         datahi = l->datahi_reg;
         if (datalo != TCG_REG_R3) {
             tcg_out_mov(s, TCG_TYPE_I32, datalo, TCG_REG_R4);
@@ -842,6 +833,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
 static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
 {
     TCGReg ir, datalo;
+    TCGMemOp s_bits = l->opc & MO_SIZE;
 
     reloc_pc14 (l->label_ptr[0], (tcg_target_long) s->code_ptr);
 
@@ -857,19 +849,19 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
     }
 
     datalo = l->datalo_reg;
-    switch (l->opc) {
-    case 0:
+    switch (s_bits) {
+    case MO_8:
         tcg_out32(s, (RLWINM | RA (ir) | RS (datalo)
                       | SH (0) | MB (24) | ME (31)));
         break;
-    case 1:
+    case MO_16:
         tcg_out32(s, (RLWINM | RA (ir) | RS (datalo)
                       | SH (0) | MB (16) | ME (31)));
         break;
-    case 2:
+    default:
         tcg_out_mov(s, TCG_TYPE_I32, ir, datalo);
         break;
-    case 3:
+    case MO_64:
 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
         ir |= 1;
 #endif
@@ -1707,34 +1699,34 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
         break;
 
     case INDEX_op_qemu_ld8u:
-        tcg_out_qemu_ld(s, args, 0);
+        tcg_out_qemu_ld(s, args, MO_UB);
         break;
     case INDEX_op_qemu_ld8s:
-        tcg_out_qemu_ld(s, args, 0 | 4);
+        tcg_out_qemu_ld(s, args, MO_SB);
         break;
     case INDEX_op_qemu_ld16u:
-        tcg_out_qemu_ld(s, args, 1);
+        tcg_out_qemu_ld(s, args, MO_TEUW);
         break;
     case INDEX_op_qemu_ld16s:
-        tcg_out_qemu_ld(s, args, 1 | 4);
+        tcg_out_qemu_ld(s, args, MO_TESW);
         break;
     case INDEX_op_qemu_ld32:
-        tcg_out_qemu_ld(s, args, 2);
+        tcg_out_qemu_ld(s, args, MO_TEUL);
         break;
     case INDEX_op_qemu_ld64:
-        tcg_out_qemu_ld(s, args, 3);
+        tcg_out_qemu_ld(s, args, MO_TEQ);
         break;
     case INDEX_op_qemu_st8:
-        tcg_out_qemu_st(s, args, 0);
+        tcg_out_qemu_st(s, args, MO_UB);
         break;
     case INDEX_op_qemu_st16:
-        tcg_out_qemu_st(s, args, 1);
+        tcg_out_qemu_st(s, args, MO_TEUW);
         break;
     case INDEX_op_qemu_st32:
-        tcg_out_qemu_st(s, args, 2);
+        tcg_out_qemu_st(s, args, MO_TEUL);
         break;
     case INDEX_op_qemu_st64:
-        tcg_out_qemu_st(s, args, 3);
+        tcg_out_qemu_st(s, args, MO_TEQ);
         break;
 
     case INDEX_op_ext8s_i32:
commit 091d5677713d5e8e48ad670655d6bf1bac0b064d
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Sep 12 15:06:23 2013 -0700

    tcg-arm: Improve GUEST_BASE qemu_ld/st
    
    If we pull the code to emit the actual load/store into a subroutine,
    we can share the reg+reg addressing mode code between softmmu and
    usermode.  This lets us load GUEST_BASE into a temporary register
    rather than attempting to add it piece-wise to the address.
    
    Which lets us use movw+movt for armv7, rather than (up to) 4 adds.
    Code size for pre-armv7 stays the same.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index c3fd2b0..e93a4a2 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1367,33 +1367,11 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 }
 #endif /* SOFTMMU */
 
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
+static inline void tcg_out_qemu_ld_index(TCGContext *s, TCGMemOp opc,
+                                         TCGReg datalo, TCGReg datahi,
+                                         TCGReg addrlo, TCGReg addend)
 {
-    TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused));
-    TCGMemOp opc, bswap;
-#ifdef CONFIG_SOFTMMU
-    TCGMemOp s_bits;
-    int mem_index;
-    TCGReg addend;
-    uint8_t *label_ptr;
-#endif
-
-    datalo = *args++;
-    datahi = (is64 ? *args++ : 0);
-    addrlo = *args++;
-    addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
-    opc = *args++;
-    bswap = opc & MO_BSWAP;
-
-#ifdef CONFIG_SOFTMMU
-    s_bits = opc & MO_SIZE;
-    mem_index = *args;
-    addend = tcg_out_tlb_read(s, addrlo, addrhi, s_bits, mem_index, 1);
-
-    /* This a conditional BL only to load a pointer within this opcode into LR
-       for the slow path.  We will not be using the value for a tail call.  */
-    label_ptr = s->code_ptr;
-    tcg_out_bl_noaddr(s, COND_NE);
+    TCGMemOp bswap = opc & MO_BSWAP;
 
     switch (opc & MO_SSIZE) {
     case MO_UB:
@@ -1425,8 +1403,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
         break;
     case MO_Q:
         {
-            /* Be careful not to modify datalo and datahi
-               for the slow path below.  */
             TCGReg dl = (bswap ? datahi : datalo);
             TCGReg dh = (bswap ? datalo : datahi);
 
@@ -1442,30 +1418,20 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
                 tcg_out_ld32_12(s, COND_AL, dh, TCG_REG_TMP, 4);
             }
             if (bswap) {
-                tcg_out_bswap32(s, COND_AL, dh, dh);
                 tcg_out_bswap32(s, COND_AL, dl, dl);
+                tcg_out_bswap32(s, COND_AL, dh, dh);
             }
         }
         break;
     }
+}
 
-    add_qemu_ldst_label(s, 1, opc, datalo, datahi, addrlo, addrhi,
-                        mem_index, s->code_ptr, label_ptr);
-#else /* !CONFIG_SOFTMMU */
-    if (GUEST_BASE) {
-        uint32_t offset = GUEST_BASE;
-        int i, rot;
-
-        while (offset) {
-            i = ctz32(offset) & ~1;
-            rot = ((32 - i) << 7) & 0xf00;
+static inline void tcg_out_qemu_ld_direct(TCGContext *s, TCGMemOp opc,
+                                          TCGReg datalo, TCGReg datahi,
+                                          TCGReg addrlo)
+{
+    TCGMemOp bswap = opc & MO_BSWAP;
 
-            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_TMP, addrlo,
-                            ((offset >> i) & 0xff) | rot);
-            addrlo = TCG_REG_TMP;
-            offset &= ~(0xff << i);
-        }
-    }
     switch (opc & MO_SSIZE) {
     case MO_UB:
         tcg_out_ld8_12(s, COND_AL, datalo, addrlo, 0);
@@ -1495,32 +1461,32 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
         }
         break;
     case MO_Q:
-        if (use_armv6_instructions && !bswap
-            && (datalo & 1) == 0 && datahi == datalo + 1) {
-            tcg_out_ldrd_8(s, COND_AL, datalo, addrlo, 0);
-        } else if (use_armv6_instructions && bswap
-                   && (datahi & 1) == 0 && datalo == datahi + 1) {
-            tcg_out_ldrd_8(s, COND_AL, datahi, addrlo, 0);
-        } else if (datalo == addrlo) {
-            tcg_out_ld32_12(s, COND_AL, datahi, addrlo, bswap ? 0 : 4);
-            tcg_out_ld32_12(s, COND_AL, datalo, addrlo, bswap ? 4 : 0);
-        } else {
-            tcg_out_ld32_12(s, COND_AL, datalo, addrlo, bswap ? 4 : 0);
-            tcg_out_ld32_12(s, COND_AL, datahi, addrlo, bswap ? 0 : 4);
-        }
-        if (bswap) {
-            tcg_out_bswap32(s, COND_AL, datalo, datalo);
-            tcg_out_bswap32(s, COND_AL, datahi, datahi);
+        {
+            TCGReg dl = (bswap ? datahi : datalo);
+            TCGReg dh = (bswap ? datalo : datahi);
+
+            if (use_armv6_instructions && (dl & 1) == 0 && dh == dl + 1) {
+                tcg_out_ldrd_8(s, COND_AL, dl, addrlo, 0);
+            } else if (dl == addrlo) {
+                tcg_out_ld32_12(s, COND_AL, dh, addrlo, bswap ? 0 : 4);
+                tcg_out_ld32_12(s, COND_AL, dl, addrlo, bswap ? 4 : 0);
+            } else {
+                tcg_out_ld32_12(s, COND_AL, dl, addrlo, bswap ? 4 : 0);
+                tcg_out_ld32_12(s, COND_AL, dh, addrlo, bswap ? 0 : 4);
+            }
+            if (bswap) {
+                tcg_out_bswap32(s, COND_AL, dl, dl);
+                tcg_out_bswap32(s, COND_AL, dh, dh);
+            }
         }
         break;
     }
-#endif
 }
 
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
 {
     TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused));
-    TCGMemOp opc, bswap, s_bits;
+    TCGMemOp opc;
 #ifdef CONFIG_SOFTMMU
     int mem_index;
     TCGReg addend;
@@ -1532,73 +1498,81 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
     addrlo = *args++;
     addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
     opc = *args++;
-    bswap = opc & MO_BSWAP;
-    s_bits = opc & MO_SIZE;
 
 #ifdef CONFIG_SOFTMMU
     mem_index = *args;
-    addend = tcg_out_tlb_read(s, addrlo, addrhi, s_bits, mem_index, 0);
+    addend = tcg_out_tlb_read(s, addrlo, addrhi, opc & MO_SIZE, mem_index, 1);
+
+    /* This a conditional BL only to load a pointer within this opcode into LR
+       for the slow path.  We will not be using the value for a tail call.  */
+    label_ptr = s->code_ptr;
+    tcg_out_bl_noaddr(s, COND_NE);
+
+    tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, addend);
 
-    switch (s_bits) {
+    add_qemu_ldst_label(s, 1, opc, datalo, datahi, addrlo, addrhi,
+                        mem_index, s->code_ptr, label_ptr);
+#else /* !CONFIG_SOFTMMU */
+    if (GUEST_BASE) {
+        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP, GUEST_BASE);
+        tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, TCG_REG_TMP);
+    } else {
+        tcg_out_qemu_ld_direct(s, opc, datalo, datahi, addrlo);
+    }
+#endif
+}
+
+static inline void tcg_out_qemu_st_index(TCGContext *s, int cond, TCGMemOp opc,
+                                         TCGReg datalo, TCGReg datahi,
+                                         TCGReg addrlo, TCGReg addend)
+{
+    TCGMemOp bswap = opc & MO_BSWAP;
+
+    switch (opc & MO_SIZE) {
     case MO_8:
-        tcg_out_st8_r(s, COND_EQ, datalo, addrlo, addend);
+        tcg_out_st8_r(s, cond, datalo, addrlo, addend);
         break;
     case MO_16:
         if (bswap) {
-            tcg_out_bswap16st(s, COND_EQ, TCG_REG_R0, datalo);
-            tcg_out_st16_r(s, COND_EQ, TCG_REG_R0, addrlo, addend);
+            tcg_out_bswap16st(s, cond, TCG_REG_R0, datalo);
+            tcg_out_st16_r(s, cond, TCG_REG_R0, addrlo, addend);
         } else {
-            tcg_out_st16_r(s, COND_EQ, datalo, addrlo, addend);
+            tcg_out_st16_r(s, cond, datalo, addrlo, addend);
         }
         break;
     case MO_32:
     default:
         if (bswap) {
-            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, datalo);
-            tcg_out_st32_r(s, COND_EQ, TCG_REG_R0, addrlo, addend);
+            tcg_out_bswap32(s, cond, TCG_REG_R0, datalo);
+            tcg_out_st32_r(s, cond, TCG_REG_R0, addrlo, addend);
         } else {
-            tcg_out_st32_r(s, COND_EQ, datalo, addrlo, addend);
+            tcg_out_st32_r(s, cond, datalo, addrlo, addend);
         }
         break;
     case MO_64:
         if (bswap) {
-            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, datahi);
-            tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, addend, addrlo);
-            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, datalo);
-            tcg_out_st32_12(s, COND_EQ, TCG_REG_R0, addend, 4);
+            tcg_out_bswap32(s, cond, TCG_REG_R0, datahi);
+            tcg_out_st32_rwb(s, cond, TCG_REG_R0, addend, addrlo);
+            tcg_out_bswap32(s, cond, TCG_REG_R0, datalo);
+            tcg_out_st32_12(s, cond, TCG_REG_R0, addend, 4);
         } else if (use_armv6_instructions
                    && (datalo & 1) == 0 && datahi == datalo + 1) {
-            tcg_out_strd_r(s, COND_EQ, datalo, addrlo, addend);
+            tcg_out_strd_r(s, cond, datalo, addrlo, addend);
         } else {
-            tcg_out_st32_rwb(s, COND_EQ, datalo, addend, addrlo);
-            tcg_out_st32_12(s, COND_EQ, datahi, addend, 4);
+            tcg_out_st32_rwb(s, cond, datalo, addend, addrlo);
+            tcg_out_st32_12(s, cond, datahi, addend, 4);
         }
         break;
     }
+}
 
-    /* The conditional call must come last, as we're going to return here.  */
-    label_ptr = s->code_ptr;
-    tcg_out_bl_noaddr(s, COND_NE);
+static inline void tcg_out_qemu_st_direct(TCGContext *s, TCGMemOp opc,
+                                          TCGReg datalo, TCGReg datahi,
+                                          TCGReg addrlo)
+{
+    TCGMemOp bswap = opc & MO_BSWAP;
 
-    add_qemu_ldst_label(s, 0, opc, datalo, datahi, addrlo, addrhi,
-                        mem_index, s->code_ptr, label_ptr);
-#else /* !CONFIG_SOFTMMU */
-    if (GUEST_BASE) {
-        uint32_t offset = GUEST_BASE;
-        int i;
-        int rot;
-
-        while (offset) {
-            i = ctz32(offset) & ~1;
-            rot = ((32 - i) << 7) & 0xf00;
-
-            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R1, addrlo,
-                            ((offset >> i) & 0xff) | rot);
-            addrlo = TCG_REG_R1;
-            offset &= ~(0xff << i);
-        }
-    }
-    switch (s_bits) {
+    switch (opc & MO_SIZE) {
     case MO_8:
         tcg_out_st8_12(s, COND_AL, datalo, addrlo, 0);
         break;
@@ -1634,6 +1608,44 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
         }
         break;
     }
+}
+
+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
+{
+    TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused));
+    TCGMemOp opc;
+#ifdef CONFIG_SOFTMMU
+    int mem_index;
+    TCGReg addend;
+    uint8_t *label_ptr;
+#endif
+
+    datalo = *args++;
+    datahi = (is64 ? *args++ : 0);
+    addrlo = *args++;
+    addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
+    opc = *args++;
+
+#ifdef CONFIG_SOFTMMU
+    mem_index = *args;
+    addend = tcg_out_tlb_read(s, addrlo, addrhi, opc & MO_SIZE, mem_index, 0);
+
+    tcg_out_qemu_st_index(s, COND_EQ, opc, datalo, datahi, addrlo, addend);
+
+    /* The conditional call must come last, as we're going to return here.  */
+    label_ptr = s->code_ptr;
+    tcg_out_bl_noaddr(s, COND_NE);
+
+    add_qemu_ldst_label(s, 0, opc, datalo, datahi, addrlo, addrhi,
+                        mem_index, s->code_ptr, label_ptr);
+#else /* !CONFIG_SOFTMMU */
+    if (GUEST_BASE) {
+        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP, GUEST_BASE);
+        tcg_out_qemu_st_index(s, COND_AL, opc, datalo,
+                              datahi, addrlo, TCG_REG_TMP);
+    } else {
+        tcg_out_qemu_st_direct(s, opc, datalo, datahi, addrlo);
+    }
 #endif
 }
 
commit 15ecf6e3946b0d2f0b6deb95c321604b8741a882
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Sep 12 10:17:45 2013 -0700

    tcg-arm: Convert to new ldst opcodes
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index e7d6bf0..c3fd2b0 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1367,24 +1367,27 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 }
 #endif /* SOFTMMU */
 
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
 {
-    TCGReg addrlo, datalo, datahi;
-    TCGMemOp bswap = opc & MO_BSWAP;
-    TCGMemOp s_bits = opc & MO_SIZE;
+    TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused));
+    TCGMemOp opc, bswap;
 #ifdef CONFIG_SOFTMMU
+    TCGMemOp s_bits;
     int mem_index;
-    TCGReg addrhi, addend;
+    TCGReg addend;
     uint8_t *label_ptr;
 #endif
 
     datalo = *args++;
-    datahi = (s_bits == MO_64 ? *args++ : 0);
+    datahi = (is64 ? *args++ : 0);
     addrlo = *args++;
-#ifdef CONFIG_SOFTMMU
     addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
-    mem_index = *args;
+    opc = *args++;
+    bswap = opc & MO_BSWAP;
 
+#ifdef CONFIG_SOFTMMU
+    s_bits = opc & MO_SIZE;
+    mem_index = *args;
     addend = tcg_out_tlb_read(s, addrlo, addrhi, s_bits, mem_index, 1);
 
     /* This a conditional BL only to load a pointer within this opcode into LR
@@ -1514,29 +1517,26 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 #endif
 }
 
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGMemOp opc)
+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
 {
-    TCGReg addrlo, datalo, datahi;
-    TCGMemOp bswap = opc & MO_BSWAP;
-    TCGMemOp s_bits = opc & MO_SIZE;
+    TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused));
+    TCGMemOp opc, bswap, s_bits;
 #ifdef CONFIG_SOFTMMU
     int mem_index;
-    TCGReg addrhi, addend;
+    TCGReg addend;
     uint8_t *label_ptr;
 #endif
-#ifdef TARGET_WORDS_BIGENDIAN
-    bswap = 1;
-#else
-    bswap = 0;
-#endif
 
     datalo = *args++;
-    datahi = (s_bits == MO_64 ? *args++ : 0);
+    datahi = (is64 ? *args++ : 0);
     addrlo = *args++;
-#ifdef CONFIG_SOFTMMU
     addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
-    mem_index = *args;
+    opc = *args++;
+    bswap = opc & MO_BSWAP;
+    s_bits = opc & MO_SIZE;
 
+#ifdef CONFIG_SOFTMMU
+    mem_index = *args;
     addend = tcg_out_tlb_read(s, addrlo, addrhi, s_bits, mem_index, 0);
 
     switch (s_bits) {
@@ -1902,36 +1902,17 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
                         ARITH_MOV, args[0], 0, 0);
         break;
 
-    case INDEX_op_qemu_ld8u:
-        tcg_out_qemu_ld(s, args, MO_UB);
-        break;
-    case INDEX_op_qemu_ld8s:
-        tcg_out_qemu_ld(s, args, MO_SB);
-        break;
-    case INDEX_op_qemu_ld16u:
-        tcg_out_qemu_ld(s, args, MO_TEUW);
-        break;
-    case INDEX_op_qemu_ld16s:
-        tcg_out_qemu_ld(s, args, MO_TESW);
-        break;
-    case INDEX_op_qemu_ld32:
-        tcg_out_qemu_ld(s, args, MO_TEUL);
-        break;
-    case INDEX_op_qemu_ld64:
-        tcg_out_qemu_ld(s, args, MO_TEQ);
-        break;
-
-    case INDEX_op_qemu_st8:
-        tcg_out_qemu_st(s, args, MO_UB);
+    case INDEX_op_qemu_ld_i32:
+        tcg_out_qemu_ld(s, args, 0);
         break;
-    case INDEX_op_qemu_st16:
-        tcg_out_qemu_st(s, args, MO_TEUW);
+    case INDEX_op_qemu_ld_i64:
+        tcg_out_qemu_ld(s, args, 1);
         break;
-    case INDEX_op_qemu_st32:
-        tcg_out_qemu_st(s, args, MO_TEUL);
+    case INDEX_op_qemu_st_i32:
+        tcg_out_qemu_st(s, args, 0);
         break;
-    case INDEX_op_qemu_st64:
-        tcg_out_qemu_st(s, args, MO_TEQ);
+    case INDEX_op_qemu_st_i64:
+        tcg_out_qemu_st(s, args, 1);
         break;
 
     case INDEX_op_bswap16_i32:
@@ -2015,29 +1996,15 @@ static const TCGTargetOpDef arm_op_defs[] = {
     { INDEX_op_setcond2_i32, { "r", "r", "r", "rIN", "rIN" } },
 
 #if TARGET_LONG_BITS == 32
-    { INDEX_op_qemu_ld8u, { "r", "l" } },
-    { INDEX_op_qemu_ld8s, { "r", "l" } },
-    { INDEX_op_qemu_ld16u, { "r", "l" } },
-    { INDEX_op_qemu_ld16s, { "r", "l" } },
-    { INDEX_op_qemu_ld32, { "r", "l" } },
-    { INDEX_op_qemu_ld64, { "r", "r", "l" } },
-
-    { INDEX_op_qemu_st8, { "s", "s" } },
-    { INDEX_op_qemu_st16, { "s", "s" } },
-    { INDEX_op_qemu_st32, { "s", "s" } },
-    { INDEX_op_qemu_st64, { "s", "s", "s" } },
+    { INDEX_op_qemu_ld_i32, { "r", "l" } },
+    { INDEX_op_qemu_ld_i64, { "r", "r", "l" } },
+    { INDEX_op_qemu_st_i32, { "s", "s" } },
+    { INDEX_op_qemu_st_i64, { "s", "s", "s" } },
 #else
-    { INDEX_op_qemu_ld8u, { "r", "l", "l" } },
-    { INDEX_op_qemu_ld8s, { "r", "l", "l" } },
-    { INDEX_op_qemu_ld16u, { "r", "l", "l" } },
-    { INDEX_op_qemu_ld16s, { "r", "l", "l" } },
-    { INDEX_op_qemu_ld32, { "r", "l", "l" } },
-    { INDEX_op_qemu_ld64, { "r", "r", "l", "l" } },
-
-    { INDEX_op_qemu_st8, { "s", "s", "s" } },
-    { INDEX_op_qemu_st16, { "s", "s", "s" } },
-    { INDEX_op_qemu_st32, { "s", "s", "s" } },
-    { INDEX_op_qemu_st64, { "s", "s", "s", "s" } },
+    { INDEX_op_qemu_ld_i32, { "r", "l", "l" } },
+    { INDEX_op_qemu_ld_i64, { "r", "r", "l", "l" } },
+    { INDEX_op_qemu_st_i32, { "s", "s", "s" } },
+    { INDEX_op_qemu_st_i64, { "s", "s", "s", "s" } },
 #endif
 
     { INDEX_op_bswap16_i32, { "r", "r" } },
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 25e1e28..3746b6e 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -85,7 +85,7 @@ extern bool use_idiv_instructions;
 #define TCG_TARGET_HAS_div_i32          use_idiv_instructions
 #define TCG_TARGET_HAS_rem_i32          0
 
-#define TCG_TARGET_HAS_new_ldst         0
+#define TCG_TARGET_HAS_new_ldst         1
 
 extern bool tcg_target_deposit_valid(int ofs, int len);
 #define TCG_TARGET_deposit_i32_valid  tcg_target_deposit_valid
commit a485cff09c44fffea121401cd3dcea13b8d1fe27
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Sep 12 09:07:38 2013 -0700

    tcg-arm: Tidy variable naming convention in qemu_ld/st
    
    s/addr_reg2/addrhi/
    s/addr_reg/addrlo/
    s/data_reg2/datahi/
    s/data_reg/datalo/
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 4692859..e7d6bf0 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -186,7 +186,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
 #endif
         break;
 
-    /* qemu_st address & data_reg */
+    /* qemu_st address & data */
     case 's':
         ct->ct |= TCG_CT_REG;
         tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
@@ -1187,13 +1187,13 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
     int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
 
     /* Should generate something like the following:
-     *   shr    tmp, addr_reg, #TARGET_PAGE_BITS                  (1)
+     *   shr    tmp, addrlo, #TARGET_PAGE_BITS                    (1)
      *   add    r2, env, #high
      *   and    r0, tmp, #(CPU_TLB_SIZE - 1)                      (2)
      *   add    r2, r2, r0, lsl #CPU_TLB_ENTRY_BITS               (3)
      *   ldr    r0, [r2, #cmp]                                    (4)
-     *   tst    addr_reg, #s_mask
-     *   ldr    r1, [r2, #add]                                    (5)
+     *   tst    addrlo, #s_mask
+     *   ldr    r2, [r2, #add]                                    (5)
      *   cmpeq  r0, tmp, lsl #TARGET_PAGE_BITS
      */
     tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP,
@@ -1249,18 +1249,18 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
    path for a load or store, so that we can later generate the correct
    helper code.  */
 static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOp opc,
-                                int data_reg, int data_reg2, int addrlo_reg,
-                                int addrhi_reg, int mem_index,
+                                TCGReg datalo, TCGReg datahi, TCGReg addrlo,
+                                TCGReg addrhi, int mem_index,
                                 uint8_t *raddr, uint8_t *label_ptr)
 {
     TCGLabelQemuLdst *label = new_ldst_label(s);
 
     label->is_ld = is_ld;
     label->opc = opc;
-    label->datalo_reg = data_reg;
-    label->datahi_reg = data_reg2;
-    label->addrlo_reg = addrlo_reg;
-    label->addrhi_reg = addrhi_reg;
+    label->datalo_reg = datalo;
+    label->datahi_reg = datahi;
+    label->addrlo_reg = addrlo;
+    label->addrhi_reg = addrhi;
     label->mem_index = mem_index;
     label->raddr = raddr;
     label->label_ptr[0] = label_ptr;
@@ -1268,7 +1268,7 @@ static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOp opc,
 
 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 {
-    TCGReg argreg, data_reg, data_reg2;
+    TCGReg argreg, datalo, datahi;
     TCGMemOp opc = lb->opc;
     uintptr_t func;
 
@@ -1296,29 +1296,29 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
     }
     tcg_out_call(s, func);
 
-    data_reg = lb->datalo_reg;
-    data_reg2 = lb->datahi_reg;
+    datalo = lb->datalo_reg;
+    datahi = lb->datahi_reg;
     switch (opc & MO_SSIZE) {
     case MO_SB:
-        tcg_out_ext8s(s, COND_AL, data_reg, TCG_REG_R0);
+        tcg_out_ext8s(s, COND_AL, datalo, TCG_REG_R0);
         break;
     case MO_SW:
-        tcg_out_ext16s(s, COND_AL, data_reg, TCG_REG_R0);
+        tcg_out_ext16s(s, COND_AL, datalo, TCG_REG_R0);
         break;
     default:
-        tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
+        tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
         break;
     case MO_Q:
-        if (data_reg != TCG_REG_R1) {
-            tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
-            tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1);
-        } else if (data_reg2 != TCG_REG_R0) {
-            tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1);
-            tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
+        if (datalo != TCG_REG_R1) {
+            tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
+            tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
+        } else if (datahi != TCG_REG_R0) {
+            tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
+            tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
         } else {
             tcg_out_mov_reg(s, COND_AL, TCG_REG_TMP, TCG_REG_R0);
-            tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1);
-            tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_TMP);
+            tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
+            tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_TMP);
         }
         break;
     }
@@ -1328,7 +1328,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 
 static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 {
-    TCGReg argreg, data_reg, data_reg2;
+    TCGReg argreg, datalo, datahi;
     TCGMemOp opc = lb->opc;
 
     reloc_pc24(lb->label_ptr[0], (tcg_target_long)s->code_ptr);
@@ -1341,21 +1341,21 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
         argreg = tcg_out_arg_reg32(s, argreg, lb->addrlo_reg);
     }
 
-    data_reg = lb->datalo_reg;
-    data_reg2 = lb->datahi_reg;
+    datalo = lb->datalo_reg;
+    datahi = lb->datahi_reg;
     switch (opc & MO_SIZE) {
     case MO_8:
-        argreg = tcg_out_arg_reg8(s, argreg, data_reg);
+        argreg = tcg_out_arg_reg8(s, argreg, datalo);
         break;
     case MO_16:
-        argreg = tcg_out_arg_reg16(s, argreg, data_reg);
+        argreg = tcg_out_arg_reg16(s, argreg, datalo);
         break;
     case MO_32:
     default:
-        argreg = tcg_out_arg_reg32(s, argreg, data_reg);
+        argreg = tcg_out_arg_reg32(s, argreg, datalo);
         break;
     case MO_64:
-        argreg = tcg_out_arg_reg64(s, argreg, data_reg, data_reg2);
+        argreg = tcg_out_arg_reg64(s, argreg, datalo, datahi);
         break;
     }
 
@@ -1369,23 +1369,23 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 
 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 {
-    TCGReg addr_reg, data_reg, data_reg2;
+    TCGReg addrlo, datalo, datahi;
     TCGMemOp bswap = opc & MO_BSWAP;
     TCGMemOp s_bits = opc & MO_SIZE;
 #ifdef CONFIG_SOFTMMU
     int mem_index;
-    TCGReg addr_reg2, addend;
+    TCGReg addrhi, addend;
     uint8_t *label_ptr;
 #endif
 
-    data_reg = *args++;
-    data_reg2 = (s_bits == MO_64 ? *args++ : 0);
-    addr_reg = *args++;
+    datalo = *args++;
+    datahi = (s_bits == MO_64 ? *args++ : 0);
+    addrlo = *args++;
 #ifdef CONFIG_SOFTMMU
-    addr_reg2 = (TARGET_LONG_BITS == 64 ? *args++ : 0);
+    addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
     mem_index = *args;
 
-    addend = tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits, mem_index, 1);
+    addend = tcg_out_tlb_read(s, addrlo, addrhi, s_bits, mem_index, 1);
 
     /* This a conditional BL only to load a pointer within this opcode into LR
        for the slow path.  We will not be using the value for a tail call.  */
@@ -1394,47 +1394,47 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 
     switch (opc & MO_SSIZE) {
     case MO_UB:
-        tcg_out_ld8_r(s, COND_AL, data_reg, addr_reg, addend);
+        tcg_out_ld8_r(s, COND_AL, datalo, addrlo, addend);
         break;
     case MO_SB:
-        tcg_out_ld8s_r(s, COND_AL, data_reg, addr_reg, addend);
+        tcg_out_ld8s_r(s, COND_AL, datalo, addrlo, addend);
         break;
     case MO_UW:
-        tcg_out_ld16u_r(s, COND_AL, data_reg, addr_reg, addend);
+        tcg_out_ld16u_r(s, COND_AL, datalo, addrlo, addend);
         if (bswap) {
-            tcg_out_bswap16(s, COND_AL, data_reg, data_reg);
+            tcg_out_bswap16(s, COND_AL, datalo, datalo);
         }
         break;
     case MO_SW:
         if (bswap) {
-            tcg_out_ld16u_r(s, COND_AL, data_reg, addr_reg, addend);
-            tcg_out_bswap16s(s, COND_AL, data_reg, data_reg);
+            tcg_out_ld16u_r(s, COND_AL, datalo, addrlo, addend);
+            tcg_out_bswap16s(s, COND_AL, datalo, datalo);
         } else {
-            tcg_out_ld16s_r(s, COND_AL, data_reg, addr_reg, addend);
+            tcg_out_ld16s_r(s, COND_AL, datalo, addrlo, addend);
         }
         break;
     case MO_UL:
     default:
-        tcg_out_ld32_r(s, COND_AL, data_reg, addr_reg, addend);
+        tcg_out_ld32_r(s, COND_AL, datalo, addrlo, addend);
         if (bswap) {
-            tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
+            tcg_out_bswap32(s, COND_AL, datalo, datalo);
         }
         break;
     case MO_Q:
         {
-            /* Be careful not to modify data_reg and data_reg2
+            /* Be careful not to modify datalo and datahi
                for the slow path below.  */
-            TCGReg dl = (bswap ? data_reg2 : data_reg);
-            TCGReg dh = (bswap ? data_reg : data_reg2);
+            TCGReg dl = (bswap ? datahi : datalo);
+            TCGReg dh = (bswap ? datalo : datahi);
 
             if (use_armv6_instructions && (dl & 1) == 0 && dh == dl + 1) {
-                tcg_out_ldrd_r(s, COND_AL, dl, addr_reg, addend);
+                tcg_out_ldrd_r(s, COND_AL, dl, addrlo, addend);
             } else if (dl != addend) {
-                tcg_out_ld32_rwb(s, COND_AL, dl, addend, addr_reg);
+                tcg_out_ld32_rwb(s, COND_AL, dl, addend, addrlo);
                 tcg_out_ld32_12(s, COND_AL, dh, addend, 4);
             } else {
                 tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_TMP,
-                                addend, addr_reg, SHIFT_IMM_LSL(0));
+                                addend, addrlo, SHIFT_IMM_LSL(0));
                 tcg_out_ld32_12(s, COND_AL, dl, TCG_REG_TMP, 0);
                 tcg_out_ld32_12(s, COND_AL, dh, TCG_REG_TMP, 4);
             }
@@ -1446,7 +1446,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
         break;
     }
 
-    add_qemu_ldst_label(s, 1, opc, data_reg, data_reg2, addr_reg, addr_reg2,
+    add_qemu_ldst_label(s, 1, opc, datalo, datahi, addrlo, addrhi,
                         mem_index, s->code_ptr, label_ptr);
 #else /* !CONFIG_SOFTMMU */
     if (GUEST_BASE) {
@@ -1457,57 +1457,57 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
             i = ctz32(offset) & ~1;
             rot = ((32 - i) << 7) & 0xf00;
 
-            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_TMP, addr_reg,
+            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_TMP, addrlo,
                             ((offset >> i) & 0xff) | rot);
-            addr_reg = TCG_REG_TMP;
+            addrlo = TCG_REG_TMP;
             offset &= ~(0xff << i);
         }
     }
     switch (opc & MO_SSIZE) {
     case MO_UB:
-        tcg_out_ld8_12(s, COND_AL, data_reg, addr_reg, 0);
+        tcg_out_ld8_12(s, COND_AL, datalo, addrlo, 0);
         break;
     case MO_SB:
-        tcg_out_ld8s_8(s, COND_AL, data_reg, addr_reg, 0);
+        tcg_out_ld8s_8(s, COND_AL, datalo, addrlo, 0);
         break;
     case MO_UW:
-        tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
+        tcg_out_ld16u_8(s, COND_AL, datalo, addrlo, 0);
         if (bswap) {
-            tcg_out_bswap16(s, COND_AL, data_reg, data_reg);
+            tcg_out_bswap16(s, COND_AL, datalo, datalo);
         }
         break;
     case MO_SW:
         if (bswap) {
-            tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
-            tcg_out_bswap16s(s, COND_AL, data_reg, data_reg);
+            tcg_out_ld16u_8(s, COND_AL, datalo, addrlo, 0);
+            tcg_out_bswap16s(s, COND_AL, datalo, datalo);
         } else {
-            tcg_out_ld16s_8(s, COND_AL, data_reg, addr_reg, 0);
+            tcg_out_ld16s_8(s, COND_AL, datalo, addrlo, 0);
         }
         break;
     case MO_UL:
     default:
-        tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
+        tcg_out_ld32_12(s, COND_AL, datalo, addrlo, 0);
         if (bswap) {
-            tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
+            tcg_out_bswap32(s, COND_AL, datalo, datalo);
         }
         break;
     case MO_Q:
         if (use_armv6_instructions && !bswap
-            && (data_reg & 1) == 0 && data_reg2 == data_reg + 1) {
-            tcg_out_ldrd_8(s, COND_AL, data_reg, addr_reg, 0);
+            && (datalo & 1) == 0 && datahi == datalo + 1) {
+            tcg_out_ldrd_8(s, COND_AL, datalo, addrlo, 0);
         } else if (use_armv6_instructions && bswap
-                   && (data_reg2 & 1) == 0 && data_reg == data_reg2 + 1) {
-            tcg_out_ldrd_8(s, COND_AL, data_reg2, addr_reg, 0);
-        } else if (data_reg == addr_reg) {
-            tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
-            tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
+                   && (datahi & 1) == 0 && datalo == datahi + 1) {
+            tcg_out_ldrd_8(s, COND_AL, datahi, addrlo, 0);
+        } else if (datalo == addrlo) {
+            tcg_out_ld32_12(s, COND_AL, datahi, addrlo, bswap ? 0 : 4);
+            tcg_out_ld32_12(s, COND_AL, datalo, addrlo, bswap ? 4 : 0);
         } else {
-            tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
-            tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
+            tcg_out_ld32_12(s, COND_AL, datalo, addrlo, bswap ? 4 : 0);
+            tcg_out_ld32_12(s, COND_AL, datahi, addrlo, bswap ? 0 : 4);
         }
         if (bswap) {
-            tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
-            tcg_out_bswap32(s, COND_AL, data_reg2, data_reg2);
+            tcg_out_bswap32(s, COND_AL, datalo, datalo);
+            tcg_out_bswap32(s, COND_AL, datahi, datahi);
         }
         break;
     }
@@ -1516,12 +1516,12 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 
 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 {
-    TCGReg addr_reg, data_reg, data_reg2;
+    TCGReg addrlo, datalo, datahi;
     TCGMemOp bswap = opc & MO_BSWAP;
     TCGMemOp s_bits = opc & MO_SIZE;
 #ifdef CONFIG_SOFTMMU
     int mem_index;
-    TCGReg addr_reg2, addend;
+    TCGReg addrhi, addend;
     uint8_t *label_ptr;
 #endif
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -1530,48 +1530,48 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGMemOp opc)
     bswap = 0;
 #endif
 
-    data_reg = *args++;
-    data_reg2 = (s_bits == MO_64 ? *args++ : 0);
-    addr_reg = *args++;
+    datalo = *args++;
+    datahi = (s_bits == MO_64 ? *args++ : 0);
+    addrlo = *args++;
 #ifdef CONFIG_SOFTMMU
-    addr_reg2 = (TARGET_LONG_BITS == 64 ? *args++ : 0);
+    addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
     mem_index = *args;
 
-    addend = tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits, mem_index, 0);
+    addend = tcg_out_tlb_read(s, addrlo, addrhi, s_bits, mem_index, 0);
 
     switch (s_bits) {
     case MO_8:
-        tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, addend);
+        tcg_out_st8_r(s, COND_EQ, datalo, addrlo, addend);
         break;
     case MO_16:
         if (bswap) {
-            tcg_out_bswap16st(s, COND_EQ, TCG_REG_R0, data_reg);
-            tcg_out_st16_r(s, COND_EQ, TCG_REG_R0, addr_reg, addend);
+            tcg_out_bswap16st(s, COND_EQ, TCG_REG_R0, datalo);
+            tcg_out_st16_r(s, COND_EQ, TCG_REG_R0, addrlo, addend);
         } else {
-            tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, addend);
+            tcg_out_st16_r(s, COND_EQ, datalo, addrlo, addend);
         }
         break;
     case MO_32:
     default:
         if (bswap) {
-            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
-            tcg_out_st32_r(s, COND_EQ, TCG_REG_R0, addr_reg, addend);
+            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, datalo);
+            tcg_out_st32_r(s, COND_EQ, TCG_REG_R0, addrlo, addend);
         } else {
-            tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, addend);
+            tcg_out_st32_r(s, COND_EQ, datalo, addrlo, addend);
         }
         break;
     case MO_64:
         if (bswap) {
-            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg2);
-            tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, addend, addr_reg);
-            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
+            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, datahi);
+            tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, addend, addrlo);
+            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, datalo);
             tcg_out_st32_12(s, COND_EQ, TCG_REG_R0, addend, 4);
         } else if (use_armv6_instructions
-                   && (data_reg & 1) == 0 && data_reg2 == data_reg + 1) {
-            tcg_out_strd_r(s, COND_EQ, data_reg, addr_reg, addend);
+                   && (datalo & 1) == 0 && datahi == datalo + 1) {
+            tcg_out_strd_r(s, COND_EQ, datalo, addrlo, addend);
         } else {
-            tcg_out_st32_rwb(s, COND_EQ, data_reg, addend, addr_reg);
-            tcg_out_st32_12(s, COND_EQ, data_reg2, addend, 4);
+            tcg_out_st32_rwb(s, COND_EQ, datalo, addend, addrlo);
+            tcg_out_st32_12(s, COND_EQ, datahi, addend, 4);
         }
         break;
     }
@@ -1580,7 +1580,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGMemOp opc)
     label_ptr = s->code_ptr;
     tcg_out_bl_noaddr(s, COND_NE);
 
-    add_qemu_ldst_label(s, 0, opc, data_reg, data_reg2, addr_reg, addr_reg2,
+    add_qemu_ldst_label(s, 0, opc, datalo, datahi, addrlo, addrhi,
                         mem_index, s->code_ptr, label_ptr);
 #else /* !CONFIG_SOFTMMU */
     if (GUEST_BASE) {
@@ -1592,45 +1592,45 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGMemOp opc)
             i = ctz32(offset) & ~1;
             rot = ((32 - i) << 7) & 0xf00;
 
-            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R1, addr_reg,
+            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R1, addrlo,
                             ((offset >> i) & 0xff) | rot);
-            addr_reg = TCG_REG_R1;
+            addrlo = TCG_REG_R1;
             offset &= ~(0xff << i);
         }
     }
     switch (s_bits) {
     case MO_8:
-        tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0);
+        tcg_out_st8_12(s, COND_AL, datalo, addrlo, 0);
         break;
     case MO_16:
         if (bswap) {
-            tcg_out_bswap16st(s, COND_AL, TCG_REG_R0, data_reg);
-            tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addr_reg, 0);
+            tcg_out_bswap16st(s, COND_AL, TCG_REG_R0, datalo);
+            tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addrlo, 0);
         } else {
-            tcg_out_st16_8(s, COND_AL, data_reg, addr_reg, 0);
+            tcg_out_st16_8(s, COND_AL, datalo, addrlo, 0);
         }
         break;
     case MO_32:
     default:
         if (bswap) {
-            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
-            tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
+            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datalo);
+            tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 0);
         } else {
-            tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
+            tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
         }
         break;
     case MO_64:
         if (bswap) {
-            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg2);
-            tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
-            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
-            tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 4);
+            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datahi);
+            tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 0);
+            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datalo);
+            tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 4);
         } else if (use_armv6_instructions
-                   && (data_reg & 1) == 0 && data_reg2 == data_reg + 1) {
-            tcg_out_strd_8(s, COND_AL, data_reg, addr_reg, 0);
+                   && (datalo & 1) == 0 && datahi == datalo + 1) {
+            tcg_out_strd_8(s, COND_AL, datalo, addrlo, 0);
         } else {
-            tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
-            tcg_out_st32_12(s, COND_AL, data_reg2, addr_reg, 4);
+            tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
+            tcg_out_st32_12(s, COND_AL, datahi, addrlo, 4);
         }
         break;
     }
commit 0315c51ea954766df8ab6697502dff22f5364f77
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Sep 12 08:58:33 2013 -0700

    tcg-arm: Convert to le/be ldst helpers
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 980d030..4692859 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1079,26 +1079,34 @@ static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
  *                                     int mmu_idx, uintptr_t ra)
  */
-static const void * const qemu_ld_helpers[8] = {
-    helper_ret_ldub_mmu,
-    helper_ret_lduw_mmu,
-    helper_ret_ldul_mmu,
-    helper_ret_ldq_mmu,
-
-    helper_ret_ldsb_mmu,
-    helper_ret_ldsw_mmu,
-    helper_ret_ldul_mmu,
-    helper_ret_ldq_mmu,
+static const void * const qemu_ld_helpers[16] = {
+    [MO_UB]   = helper_ret_ldub_mmu,
+    [MO_SB]   = helper_ret_ldsb_mmu,
+
+    [MO_LEUW] = helper_le_lduw_mmu,
+    [MO_LEUL] = helper_le_ldul_mmu,
+    [MO_LEQ]  = helper_le_ldq_mmu,
+    [MO_LESW] = helper_le_ldsw_mmu,
+    [MO_LESL] = helper_le_ldul_mmu,
+
+    [MO_BEUW] = helper_be_lduw_mmu,
+    [MO_BEUL] = helper_be_ldul_mmu,
+    [MO_BEQ]  = helper_be_ldq_mmu,
+    [MO_BESW] = helper_be_ldsw_mmu,
+    [MO_BESL] = helper_be_ldul_mmu,
 };
 
 /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
  *                                     uintxx_t val, int mmu_idx, uintptr_t ra)
  */
-static const void * const qemu_st_helpers[4] = {
-    helper_ret_stb_mmu,
-    helper_ret_stw_mmu,
-    helper_ret_stl_mmu,
-    helper_ret_stq_mmu,
+static const void * const qemu_st_helpers[16] = {
+    [MO_UB]   = helper_ret_stb_mmu,
+    [MO_LEUW] = helper_le_stw_mmu,
+    [MO_LEUL] = helper_le_stl_mmu,
+    [MO_LEQ]  = helper_le_stq_mmu,
+    [MO_BEUW] = helper_be_stw_mmu,
+    [MO_BEUL] = helper_be_stl_mmu,
+    [MO_BEQ]  = helper_be_stq_mmu,
 };
 
 /* Helper routines for marshalling helper function arguments into
@@ -1261,7 +1269,7 @@ static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOp opc,
 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 {
     TCGReg argreg, data_reg, data_reg2;
-    TCGMemOp opc = lb->opc & MO_SSIZE;
+    TCGMemOp opc = lb->opc;
     uintptr_t func;
 
     reloc_pc24(lb->label_ptr[0], (tcg_target_long)s->code_ptr);
@@ -1279,7 +1287,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
        icache usage.  For pre-armv6, use the signed helpers since we do
        not have a single insn sign-extend.  */
     if (use_armv6_instructions) {
-        func = (uintptr_t)qemu_ld_helpers[opc & MO_SIZE];
+        func = (uintptr_t)qemu_ld_helpers[opc & ~MO_SIGN];
     } else {
         func = (uintptr_t)qemu_ld_helpers[opc];
         if (opc & MO_SIGN) {
@@ -1290,7 +1298,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 
     data_reg = lb->datalo_reg;
     data_reg2 = lb->datahi_reg;
-    switch (opc) {
+    switch (opc & MO_SSIZE) {
     case MO_SB:
         tcg_out_ext8s(s, COND_AL, data_reg, TCG_REG_R0);
         break;
@@ -1321,7 +1329,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 {
     TCGReg argreg, data_reg, data_reg2;
-    TCGMemOp s_bits = lb->opc & MO_SIZE;
+    TCGMemOp opc = lb->opc;
 
     reloc_pc24(lb->label_ptr[0], (tcg_target_long)s->code_ptr);
 
@@ -1335,7 +1343,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 
     data_reg = lb->datalo_reg;
     data_reg2 = lb->datahi_reg;
-    switch (s_bits) {
+    switch (opc & MO_SIZE) {
     case MO_8:
         argreg = tcg_out_arg_reg8(s, argreg, data_reg);
         break;
@@ -1355,7 +1363,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
     argreg = tcg_out_arg_reg32(s, argreg, TCG_REG_R14);
 
     /* Tail-call to the helper, which will return to the fast path.  */
-    tcg_out_goto(s, COND_AL, (tcg_target_long) qemu_st_helpers[s_bits]);
+    tcg_out_goto(s, COND_AL, (uintptr_t)qemu_st_helpers[opc]);
 }
 #endif /* SOFTMMU */
 
commit 099fcf2e3689a702a0948b53f3cd42926bbe044a
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Sep 3 16:16:47 2013 -0700

    tcg-arm: Use TCGMemOp within qemu_ldst routines
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index c0e1466..980d030 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1169,7 +1169,7 @@ QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1])
    containing the addend of the tlb entry.  Clobbers R0, R1, R2, TMP.  */
 
 static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
-                               int s_bits, int mem_index, bool is_load)
+                               TCGMemOp s_bits, int mem_index, bool is_load)
 {
     TCGReg base = TCG_AREG0;
     int cmp_off =
@@ -1240,7 +1240,7 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
 /* Record the context of a call to the out of line helper code for the slow
    path for a load or store, so that we can later generate the correct
    helper code.  */
-static void add_qemu_ldst_label(TCGContext *s, int is_ld, int opc,
+static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOp opc,
                                 int data_reg, int data_reg2, int addrlo_reg,
                                 int addrhi_reg, int mem_index,
                                 uint8_t *raddr, uint8_t *label_ptr)
@@ -1261,7 +1261,7 @@ static void add_qemu_ldst_label(TCGContext *s, int is_ld, int opc,
 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 {
     TCGReg argreg, data_reg, data_reg2;
-    int opc = lb->opc;
+    TCGMemOp opc = lb->opc & MO_SSIZE;
     uintptr_t func;
 
     reloc_pc24(lb->label_ptr[0], (tcg_target_long)s->code_ptr);
@@ -1279,11 +1279,11 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
        icache usage.  For pre-armv6, use the signed helpers since we do
        not have a single insn sign-extend.  */
     if (use_armv6_instructions) {
-        func = (uintptr_t)qemu_ld_helpers[opc & 3];
+        func = (uintptr_t)qemu_ld_helpers[opc & MO_SIZE];
     } else {
         func = (uintptr_t)qemu_ld_helpers[opc];
-        if (opc & 4) {
-            opc = 2;
+        if (opc & MO_SIGN) {
+            opc = MO_UL;
         }
     }
     tcg_out_call(s, func);
@@ -1291,16 +1291,16 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
     data_reg = lb->datalo_reg;
     data_reg2 = lb->datahi_reg;
     switch (opc) {
-    case 0 | 4:
+    case MO_SB:
         tcg_out_ext8s(s, COND_AL, data_reg, TCG_REG_R0);
         break;
-    case 1 | 4:
+    case MO_SW:
         tcg_out_ext16s(s, COND_AL, data_reg, TCG_REG_R0);
         break;
     default:
         tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
         break;
-    case 3:
+    case MO_Q:
         if (data_reg != TCG_REG_R1) {
             tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
             tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1);
@@ -1321,6 +1321,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 {
     TCGReg argreg, data_reg, data_reg2;
+    TCGMemOp s_bits = lb->opc & MO_SIZE;
 
     reloc_pc24(lb->label_ptr[0], (tcg_target_long)s->code_ptr);
 
@@ -1334,17 +1335,18 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 
     data_reg = lb->datalo_reg;
     data_reg2 = lb->datahi_reg;
-    switch (lb->opc) {
-    case 0:
+    switch (s_bits) {
+    case MO_8:
         argreg = tcg_out_arg_reg8(s, argreg, data_reg);
         break;
-    case 1:
+    case MO_16:
         argreg = tcg_out_arg_reg16(s, argreg, data_reg);
         break;
-    case 2:
+    case MO_32:
+    default:
         argreg = tcg_out_arg_reg32(s, argreg, data_reg);
         break;
-    case 3:
+    case MO_64:
         argreg = tcg_out_arg_reg64(s, argreg, data_reg, data_reg2);
         break;
     }
@@ -1353,32 +1355,27 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
     argreg = tcg_out_arg_reg32(s, argreg, TCG_REG_R14);
 
     /* Tail-call to the helper, which will return to the fast path.  */
-    tcg_out_goto(s, COND_AL, (tcg_target_long) qemu_st_helpers[lb->opc & 3]);
+    tcg_out_goto(s, COND_AL, (tcg_target_long) qemu_st_helpers[s_bits]);
 }
 #endif /* SOFTMMU */
 
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 {
     TCGReg addr_reg, data_reg, data_reg2;
-    bool bswap;
+    TCGMemOp bswap = opc & MO_BSWAP;
+    TCGMemOp s_bits = opc & MO_SIZE;
 #ifdef CONFIG_SOFTMMU
-    int mem_index, s_bits;
+    int mem_index;
     TCGReg addr_reg2, addend;
     uint8_t *label_ptr;
 #endif
-#ifdef TARGET_WORDS_BIGENDIAN
-    bswap = 1;
-#else
-    bswap = 0;
-#endif
 
     data_reg = *args++;
-    data_reg2 = (opc == 3 ? *args++ : 0);
+    data_reg2 = (s_bits == MO_64 ? *args++ : 0);
     addr_reg = *args++;
 #ifdef CONFIG_SOFTMMU
     addr_reg2 = (TARGET_LONG_BITS == 64 ? *args++ : 0);
     mem_index = *args;
-    s_bits = opc & 3;
 
     addend = tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits, mem_index, 1);
 
@@ -1387,20 +1384,20 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     label_ptr = s->code_ptr;
     tcg_out_bl_noaddr(s, COND_NE);
 
-    switch (opc) {
-    case 0:
+    switch (opc & MO_SSIZE) {
+    case MO_UB:
         tcg_out_ld8_r(s, COND_AL, data_reg, addr_reg, addend);
         break;
-    case 0 | 4:
+    case MO_SB:
         tcg_out_ld8s_r(s, COND_AL, data_reg, addr_reg, addend);
         break;
-    case 1:
+    case MO_UW:
         tcg_out_ld16u_r(s, COND_AL, data_reg, addr_reg, addend);
         if (bswap) {
             tcg_out_bswap16(s, COND_AL, data_reg, data_reg);
         }
         break;
-    case 1 | 4:
+    case MO_SW:
         if (bswap) {
             tcg_out_ld16u_r(s, COND_AL, data_reg, addr_reg, addend);
             tcg_out_bswap16s(s, COND_AL, data_reg, data_reg);
@@ -1408,14 +1405,14 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
             tcg_out_ld16s_r(s, COND_AL, data_reg, addr_reg, addend);
         }
         break;
-    case 2:
+    case MO_UL:
     default:
         tcg_out_ld32_r(s, COND_AL, data_reg, addr_reg, addend);
         if (bswap) {
             tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
         }
         break;
-    case 3:
+    case MO_Q:
         {
             /* Be careful not to modify data_reg and data_reg2
                for the slow path below.  */
@@ -1458,20 +1455,20 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
             offset &= ~(0xff << i);
         }
     }
-    switch (opc) {
-    case 0:
+    switch (opc & MO_SSIZE) {
+    case MO_UB:
         tcg_out_ld8_12(s, COND_AL, data_reg, addr_reg, 0);
         break;
-    case 0 | 4:
+    case MO_SB:
         tcg_out_ld8s_8(s, COND_AL, data_reg, addr_reg, 0);
         break;
-    case 1:
+    case MO_UW:
         tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
         if (bswap) {
             tcg_out_bswap16(s, COND_AL, data_reg, data_reg);
         }
         break;
-    case 1 | 4:
+    case MO_SW:
         if (bswap) {
             tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
             tcg_out_bswap16s(s, COND_AL, data_reg, data_reg);
@@ -1479,14 +1476,14 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
             tcg_out_ld16s_8(s, COND_AL, data_reg, addr_reg, 0);
         }
         break;
-    case 2:
+    case MO_UL:
     default:
         tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
         if (bswap) {
             tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
         }
         break;
-    case 3:
+    case MO_Q:
         if (use_armv6_instructions && !bswap
             && (data_reg & 1) == 0 && data_reg2 == data_reg + 1) {
             tcg_out_ldrd_8(s, COND_AL, data_reg, addr_reg, 0);
@@ -1509,12 +1506,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 #endif
 }
 
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 {
     TCGReg addr_reg, data_reg, data_reg2;
-    bool bswap;
+    TCGMemOp bswap = opc & MO_BSWAP;
+    TCGMemOp s_bits = opc & MO_SIZE;
 #ifdef CONFIG_SOFTMMU
-    int mem_index, s_bits;
+    int mem_index;
     TCGReg addr_reg2, addend;
     uint8_t *label_ptr;
 #endif
@@ -1525,20 +1523,19 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
 #endif
 
     data_reg = *args++;
-    data_reg2 = (opc == 3 ? *args++ : 0);
+    data_reg2 = (s_bits == MO_64 ? *args++ : 0);
     addr_reg = *args++;
 #ifdef CONFIG_SOFTMMU
     addr_reg2 = (TARGET_LONG_BITS == 64 ? *args++ : 0);
     mem_index = *args;
-    s_bits = opc & 3;
 
     addend = tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits, mem_index, 0);
 
-    switch (opc) {
-    case 0:
+    switch (s_bits) {
+    case MO_8:
         tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, addend);
         break;
-    case 1:
+    case MO_16:
         if (bswap) {
             tcg_out_bswap16st(s, COND_EQ, TCG_REG_R0, data_reg);
             tcg_out_st16_r(s, COND_EQ, TCG_REG_R0, addr_reg, addend);
@@ -1546,7 +1543,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
             tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, addend);
         }
         break;
-    case 2:
+    case MO_32:
     default:
         if (bswap) {
             tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
@@ -1555,7 +1552,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
             tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, addend);
         }
         break;
-    case 3:
+    case MO_64:
         if (bswap) {
             tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg2);
             tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, addend, addr_reg);
@@ -1593,11 +1590,11 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
             offset &= ~(0xff << i);
         }
     }
-    switch (opc) {
-    case 0:
+    switch (s_bits) {
+    case MO_8:
         tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0);
         break;
-    case 1:
+    case MO_16:
         if (bswap) {
             tcg_out_bswap16st(s, COND_AL, TCG_REG_R0, data_reg);
             tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addr_reg, 0);
@@ -1605,7 +1602,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
             tcg_out_st16_8(s, COND_AL, data_reg, addr_reg, 0);
         }
         break;
-    case 2:
+    case MO_32:
     default:
         if (bswap) {
             tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
@@ -1614,7 +1611,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
             tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
         }
         break;
-    case 3:
+    case MO_64:
         if (bswap) {
             tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg2);
             tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
@@ -1898,35 +1895,35 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         break;
 
     case INDEX_op_qemu_ld8u:
-        tcg_out_qemu_ld(s, args, 0);
+        tcg_out_qemu_ld(s, args, MO_UB);
         break;
     case INDEX_op_qemu_ld8s:
-        tcg_out_qemu_ld(s, args, 0 | 4);
+        tcg_out_qemu_ld(s, args, MO_SB);
         break;
     case INDEX_op_qemu_ld16u:
-        tcg_out_qemu_ld(s, args, 1);
+        tcg_out_qemu_ld(s, args, MO_TEUW);
         break;
     case INDEX_op_qemu_ld16s:
-        tcg_out_qemu_ld(s, args, 1 | 4);
+        tcg_out_qemu_ld(s, args, MO_TESW);
         break;
     case INDEX_op_qemu_ld32:
-        tcg_out_qemu_ld(s, args, 2);
+        tcg_out_qemu_ld(s, args, MO_TEUL);
         break;
     case INDEX_op_qemu_ld64:
-        tcg_out_qemu_ld(s, args, 3);
+        tcg_out_qemu_ld(s, args, MO_TEQ);
         break;
 
     case INDEX_op_qemu_st8:
-        tcg_out_qemu_st(s, args, 0);
+        tcg_out_qemu_st(s, args, MO_UB);
         break;
     case INDEX_op_qemu_st16:
-        tcg_out_qemu_st(s, args, 1);
+        tcg_out_qemu_st(s, args, MO_TEUW);
         break;
     case INDEX_op_qemu_st32:
-        tcg_out_qemu_st(s, args, 2);
+        tcg_out_qemu_st(s, args, MO_TEUL);
         break;
     case INDEX_op_qemu_st64:
-        tcg_out_qemu_st(s, args, 3);
+        tcg_out_qemu_st(s, args, MO_TEQ);
         break;
 
     case INDEX_op_bswap16_i32:
commit 8221a267fdc6e8eebbeb8d810b58efbe3a7d913e
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 4 09:35:37 2013 -0700

    tcg-i386: Support new ldst opcodes
    
    No support for helpers with non-default endianness yet,
    but good enough to test the opcodes.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index f4fdce5..7ac8e45 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -1026,21 +1026,27 @@ static void tcg_out_jmp(TCGContext *s, uintptr_t dest)
 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
  *                                     int mmu_idx, uintptr_t ra)
  */
-static const void * const qemu_ld_helpers[4] = {
-    helper_ret_ldub_mmu,
-    helper_ret_lduw_mmu,
-    helper_ret_ldul_mmu,
-    helper_ret_ldq_mmu,
+static const void * const qemu_ld_helpers[16] = {
+    [MO_UB]   = helper_ret_ldub_mmu,
+    [MO_LEUW] = helper_le_lduw_mmu,
+    [MO_LEUL] = helper_le_ldul_mmu,
+    [MO_LEQ]  = helper_le_ldq_mmu,
+    [MO_BEUW] = helper_be_lduw_mmu,
+    [MO_BEUL] = helper_be_ldul_mmu,
+    [MO_BEQ]  = helper_be_ldq_mmu,
 };
 
 /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
  *                                     uintxx_t val, int mmu_idx, uintptr_t ra)
  */
-static const void * const qemu_st_helpers[4] = {
-    helper_ret_stb_mmu,
-    helper_ret_stw_mmu,
-    helper_ret_stl_mmu,
-    helper_ret_stq_mmu,
+static const void * const qemu_st_helpers[16] = {
+    [MO_UB]   = helper_ret_stb_mmu,
+    [MO_LEUW] = helper_le_stw_mmu,
+    [MO_LEUL] = helper_le_stl_mmu,
+    [MO_LEQ]  = helper_le_stq_mmu,
+    [MO_BEUW] = helper_be_stw_mmu,
+    [MO_BEUL] = helper_be_stl_mmu,
+    [MO_BEQ]  = helper_be_stq_mmu,
 };
 
 /* Perform the TLB load and compare.
@@ -1165,7 +1171,6 @@ static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOp opc,
 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
 {
     TCGMemOp opc = l->opc;
-    TCGMemOp s_bits = opc & MO_SIZE;
     TCGReg data_reg;
     uint8_t **label_ptr = &l->label_ptr[0];
 
@@ -1202,7 +1207,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
                      (uintptr_t)l->raddr);
     }
 
-    tcg_out_calli(s, (uintptr_t)qemu_ld_helpers[s_bits]);
+    tcg_out_calli(s, (uintptr_t)qemu_ld_helpers[opc & ~MO_SIGN]);
 
     data_reg = l->datalo_reg;
     switch (opc & MO_SSIZE) {
@@ -1307,7 +1312,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
 
     /* "Tail call" to the helper, with the return address back inline.  */
     tcg_out_push(s, retaddr);
-    tcg_out_jmp(s, (uintptr_t)qemu_st_helpers[s_bits]);
+    tcg_out_jmp(s, (uintptr_t)qemu_st_helpers[opc]);
 }
 #elif defined(__x86_64__) && defined(__linux__)
 # include <asm/prctl.h>
@@ -1411,22 +1416,24 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
 /* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
    EAX. It will be useful once fixed registers globals are less
    common. */
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
 {
     TCGReg datalo, datahi, addrlo;
+    TCGReg addrhi __attribute__((unused));
+    TCGMemOp opc;
 #if defined(CONFIG_SOFTMMU)
-    TCGReg addrhi;
     int mem_index;
     TCGMemOp s_bits;
     uint8_t *label_ptr[2];
 #endif
 
     datalo = *args++;
-    datahi = (TCG_TARGET_REG_BITS == 32 && opc == 3 ? *args++ : 0);
+    datahi = (TCG_TARGET_REG_BITS == 32 && is64 ? *args++ : 0);
     addrlo = *args++;
+    addrhi = (TARGET_LONG_BITS > TCG_TARGET_REG_BITS ? *args++ : 0);
+    opc = *args++;
 
 #if defined(CONFIG_SOFTMMU)
-    addrhi = (TARGET_LONG_BITS > TCG_TARGET_REG_BITS ? *args++ : 0);
     mem_index = *args++;
     s_bits = opc & MO_SIZE;
 
@@ -1531,22 +1538,24 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
     }
 }
 
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGMemOp opc)
+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
 {
     TCGReg datalo, datahi, addrlo;
+    TCGReg addrhi __attribute__((unused));
+    TCGMemOp opc;
 #if defined(CONFIG_SOFTMMU)
-    TCGReg addrhi;
     int mem_index;
     TCGMemOp s_bits;
     uint8_t *label_ptr[2];
 #endif
 
     datalo = *args++;
-    datahi = (TCG_TARGET_REG_BITS == 32 && opc == 3 ? *args++ : 0);
+    datahi = (TCG_TARGET_REG_BITS == 32 && is64 ? *args++ : 0);
     addrlo = *args++;
+    addrhi = (TARGET_LONG_BITS > TCG_TARGET_REG_BITS ? *args++ : 0);
+    opc = *args++;
 
 #if defined(CONFIG_SOFTMMU)
-    addrhi = (TARGET_LONG_BITS > TCG_TARGET_REG_BITS ? *args++ : 0);
     mem_index = *args++;
     s_bits = opc & MO_SIZE;
 
@@ -1810,39 +1819,17 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         tcg_out_ext16u(s, args[0], args[1]);
         break;
 
-    case INDEX_op_qemu_ld8u:
-        tcg_out_qemu_ld(s, args, MO_UB);
-        break;
-    case INDEX_op_qemu_ld8s:
-        tcg_out_qemu_ld(s, args, MO_SB);
+    case INDEX_op_qemu_ld_i32:
+        tcg_out_qemu_ld(s, args, 0);
         break;
-    case INDEX_op_qemu_ld16u:
-        tcg_out_qemu_ld(s, args, MO_TEUW);
+    case INDEX_op_qemu_ld_i64:
+        tcg_out_qemu_ld(s, args, 1);
         break;
-    case INDEX_op_qemu_ld16s:
-        tcg_out_qemu_ld(s, args, MO_TESW);
+    case INDEX_op_qemu_st_i32:
+        tcg_out_qemu_st(s, args, 0);
         break;
-#if TCG_TARGET_REG_BITS == 64
-    case INDEX_op_qemu_ld32u:
-#endif
-    case INDEX_op_qemu_ld32:
-        tcg_out_qemu_ld(s, args, MO_TEUL);
-        break;
-    case INDEX_op_qemu_ld64:
-        tcg_out_qemu_ld(s, args, MO_TEQ);
-        break;
-
-    case INDEX_op_qemu_st8:
-        tcg_out_qemu_st(s, args, MO_UB);
-        break;
-    case INDEX_op_qemu_st16:
-        tcg_out_qemu_st(s, args, MO_TEUW);
-        break;
-    case INDEX_op_qemu_st32:
-        tcg_out_qemu_st(s, args, MO_TEUL);
-        break;
-    case INDEX_op_qemu_st64:
-        tcg_out_qemu_st(s, args, MO_TEQ);
+    case INDEX_op_qemu_st_i64:
+        tcg_out_qemu_st(s, args, 1);
         break;
 
     OP_32_64(mulu2):
@@ -1902,9 +1889,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
             tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]);
         }
         break;
-    case INDEX_op_qemu_ld32s:
-        tcg_out_qemu_ld(s, args, MO_TESL);
-        break;
 
     case INDEX_op_brcond_i64:
         tcg_out_brcond64(s, args[2], args[0], args[1], const_args[1],
@@ -2069,43 +2053,20 @@ static const TCGTargetOpDef x86_op_defs[] = {
 #endif
 
 #if TCG_TARGET_REG_BITS == 64
-    { INDEX_op_qemu_ld8u, { "r", "L" } },
-    { INDEX_op_qemu_ld8s, { "r", "L" } },
-    { INDEX_op_qemu_ld16u, { "r", "L" } },
-    { INDEX_op_qemu_ld16s, { "r", "L" } },
-    { INDEX_op_qemu_ld32, { "r", "L" } },
-    { INDEX_op_qemu_ld32u, { "r", "L" } },
-    { INDEX_op_qemu_ld32s, { "r", "L" } },
-    { INDEX_op_qemu_ld64, { "r", "L" } },
-
-    { INDEX_op_qemu_st8, { "L", "L" } },
-    { INDEX_op_qemu_st16, { "L", "L" } },
-    { INDEX_op_qemu_st32, { "L", "L" } },
-    { INDEX_op_qemu_st64, { "L", "L" } },
+    { INDEX_op_qemu_ld_i32, { "r", "L" } },
+    { INDEX_op_qemu_st_i32, { "L", "L" } },
+    { INDEX_op_qemu_ld_i64, { "r", "L" } },
+    { INDEX_op_qemu_st_i64, { "L", "L" } },
 #elif TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
-    { INDEX_op_qemu_ld8u, { "r", "L" } },
-    { INDEX_op_qemu_ld8s, { "r", "L" } },
-    { INDEX_op_qemu_ld16u, { "r", "L" } },
-    { INDEX_op_qemu_ld16s, { "r", "L" } },
-    { INDEX_op_qemu_ld32, { "r", "L" } },
-    { INDEX_op_qemu_ld64, { "r", "r", "L" } },
-
-    { INDEX_op_qemu_st8, { "L", "L" } },
-    { INDEX_op_qemu_st16, { "L", "L" } },
-    { INDEX_op_qemu_st32, { "L", "L" } },
-    { INDEX_op_qemu_st64, { "L", "L", "L" } },
+    { INDEX_op_qemu_ld_i32, { "r", "L" } },
+    { INDEX_op_qemu_st_i32, { "L", "L" } },
+    { INDEX_op_qemu_ld_i64, { "r", "r", "L" } },
+    { INDEX_op_qemu_st_i64, { "L", "L", "L" } },
 #else
-    { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
-    { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
-    { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
-    { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
-    { INDEX_op_qemu_ld32, { "r", "L", "L" } },
-    { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
-
-    { INDEX_op_qemu_st8, { "L", "L", "L" } },
-    { INDEX_op_qemu_st16, { "L", "L", "L" } },
-    { INDEX_op_qemu_st32, { "L", "L", "L" } },
-    { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
+    { INDEX_op_qemu_ld_i32, { "r", "L", "L" } },
+    { INDEX_op_qemu_st_i32, { "L", "L", "L" } },
+    { INDEX_op_qemu_ld_i64, { "r", "r", "L", "L" } },
+    { INDEX_op_qemu_st_i64, { "L", "L", "L", "L" } },
 #endif
     { -1 },
 };
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index fa7d966..92c0fcd 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -130,7 +130,7 @@ typedef enum {
 #define TCG_TARGET_HAS_mulsh_i64        0
 #endif
 
-#define TCG_TARGET_HAS_new_ldst         0
+#define TCG_TARGET_HAS_new_ldst         1
 
 #define TCG_TARGET_deposit_i32_valid(ofs, len) \
     (((ofs) == 0 && (len) == 8) || ((ofs) == 8 && (len) == 8) || \
commit b3e2bc500f5fe09763a107e2e28cb0e2d39ffb7c
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 4 08:51:07 2013 -0700

    tcg-i386: Remove "cb" output restriction from qemu_st8 for i386
    
    Once we form a combined qemu_st_i32 opcode, we won't be able to
    have separate constraints based on size.  This one is fairly easy
    to work around, since eax is available as a scratch register.
    
    When storing variable data, this tends to merely exchange one mov
    for another.  E.g.
    
    -:  mov    %esi,%ecx
    ...
    -:  mov    %cl,(%edx)
    +:  mov    %esi,%eax
    +:  mov    %al,(%edx)
    
    Where we do have a regression is when storing constant data, in which
    we may load the constant into edi, when only ecx/ebx ought to be used.
    
    The proper way to recover this regression is to allow constants as
    arguments to qemu_st_i32, so that we never load the constant data into
    a register at all, must less the wrong register.  TBD.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index a7ff8a3..f4fdce5 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -1479,6 +1479,12 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
 
     switch (memop & MO_SIZE) {
     case MO_8:
+        /* In 32-bit mode, 8-byte stores can only happen from [abcd]x.
+           Use the scratch register if necessary.  */
+        if (TCG_TARGET_REG_BITS == 32 && datalo >= 4) {
+            tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
+            datalo = scratch;
+        }
         tcg_out_modrm_offset(s, OPC_MOVB_EvGv + P_REXB_R + seg,
                              datalo, base, ofs);
         break;
@@ -2084,7 +2090,7 @@ static const TCGTargetOpDef x86_op_defs[] = {
     { INDEX_op_qemu_ld32, { "r", "L" } },
     { INDEX_op_qemu_ld64, { "r", "r", "L" } },
 
-    { INDEX_op_qemu_st8, { "cb", "L" } },
+    { INDEX_op_qemu_st8, { "L", "L" } },
     { INDEX_op_qemu_st16, { "L", "L" } },
     { INDEX_op_qemu_st32, { "L", "L" } },
     { INDEX_op_qemu_st64, { "L", "L", "L" } },
@@ -2096,7 +2102,7 @@ static const TCGTargetOpDef x86_op_defs[] = {
     { INDEX_op_qemu_ld32, { "r", "L", "L" } },
     { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
 
-    { INDEX_op_qemu_st8, { "cb", "L", "L" } },
+    { INDEX_op_qemu_st8, { "L", "L", "L" } },
     { INDEX_op_qemu_st16, { "L", "L", "L" } },
     { INDEX_op_qemu_st32, { "L", "L", "L" } },
     { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
commit 7352ee546ce0aba261d0e64595eae6e74e75e49d
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 4 08:13:42 2013 -0700

    tcg-i386: Tidy softmmu routines
    
    Pass two TCGReg to tcg_out_tlb_load, rather than idx+args.
    
    Move ldst_optimization routines just below tcg_out_tlb_load to avoid
    the need for forward declarations.
    
    Use TCGReg enum in preference to int where apprpriate.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 1b86009..a7ff8a3 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -1043,22 +1043,10 @@ static const void * const qemu_st_helpers[4] = {
     helper_ret_stq_mmu,
 };
 
-static void add_qemu_ldst_label(TCGContext *s,
-                                int is_ld,
-                                int opc,
-                                int data_reg,
-                                int data_reg2,
-                                int addrlo_reg,
-                                int addrhi_reg,
-                                int mem_index,
-                                uint8_t *raddr,
-                                uint8_t **label_ptr);
-
 /* Perform the TLB load and compare.
 
    Inputs:
-   ADDRLO_IDX contains the index into ARGS of the low part of the
-   address; the high part of the address is at ADDR_LOW_IDX+1.
+   ADDRLO and ADDRHI contain the low and high part of the address.
 
    MEM_INDEX and S_BITS are the memory context and log2 size of the load.
 
@@ -1076,14 +1064,12 @@ static void add_qemu_ldst_label(TCGContext *s,
 
    First argument register is clobbered.  */
 
-static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
+static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
                                     int mem_index, TCGMemOp s_bits,
-                                    const TCGArg *args,
                                     uint8_t **label_ptr, int which)
 {
-    const int addrlo = args[addrlo_idx];
-    const int r0 = TCG_REG_L0;
-    const int r1 = TCG_REG_L1;
+    const TCGReg r0 = TCG_REG_L0;
+    const TCGReg r1 = TCG_REG_L1;
     TCGType ttype = TCG_TYPE_I32;
     TCGType htype = TCG_TYPE_I32;
     int trexw = 0, hrexw = 0;
@@ -1132,7 +1118,7 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
 
     if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
         /* cmp 4(r0), addrhi */
-        tcg_out_modrm_offset(s, OPC_CMP_GvEv, args[addrlo_idx+1], r0, 4);
+        tcg_out_modrm_offset(s, OPC_CMP_GvEv, addrhi, r0, 4);
 
         /* jne slow_path */
         tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0);
@@ -1146,6 +1132,183 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
     tcg_out_modrm_offset(s, OPC_ADD_GvEv + hrexw, r1, r0,
                          offsetof(CPUTLBEntry, addend) - which);
 }
+
+/*
+ * Record the context of a call to the out of line helper code for the slow path
+ * for a load or store, so that we can later generate the correct helper code
+ */
+static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOp opc,
+                                TCGReg datalo, TCGReg datahi,
+                                TCGReg addrlo, TCGReg addrhi,
+                                int mem_index, uint8_t *raddr,
+                                uint8_t **label_ptr)
+{
+    TCGLabelQemuLdst *label = new_ldst_label(s);
+
+    label->is_ld = is_ld;
+    label->opc = opc;
+    label->datalo_reg = datalo;
+    label->datahi_reg = datahi;
+    label->addrlo_reg = addrlo;
+    label->addrhi_reg = addrhi;
+    label->mem_index = mem_index;
+    label->raddr = raddr;
+    label->label_ptr[0] = label_ptr[0];
+    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
+        label->label_ptr[1] = label_ptr[1];
+    }
+}
+
+/*
+ * Generate code for the slow path for a load at the end of block
+ */
+static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
+{
+    TCGMemOp opc = l->opc;
+    TCGMemOp s_bits = opc & MO_SIZE;
+    TCGReg data_reg;
+    uint8_t **label_ptr = &l->label_ptr[0];
+
+    /* resolve label address */
+    *(uint32_t *)label_ptr[0] = (uint32_t)(s->code_ptr - label_ptr[0] - 4);
+    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
+        *(uint32_t *)label_ptr[1] = (uint32_t)(s->code_ptr - label_ptr[1] - 4);
+    }
+
+    if (TCG_TARGET_REG_BITS == 32) {
+        int ofs = 0;
+
+        tcg_out_st(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP, ofs);
+        ofs += 4;
+
+        tcg_out_st(s, TCG_TYPE_I32, l->addrlo_reg, TCG_REG_ESP, ofs);
+        ofs += 4;
+
+        if (TARGET_LONG_BITS == 64) {
+            tcg_out_st(s, TCG_TYPE_I32, l->addrhi_reg, TCG_REG_ESP, ofs);
+            ofs += 4;
+        }
+
+        tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, l->mem_index);
+        ofs += 4;
+
+        tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, (uintptr_t)l->raddr);
+    } else {
+        tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
+        /* The second argument is already loaded with addrlo.  */
+        tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
+                     l->mem_index);
+        tcg_out_movi(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[3],
+                     (uintptr_t)l->raddr);
+    }
+
+    tcg_out_calli(s, (uintptr_t)qemu_ld_helpers[s_bits]);
+
+    data_reg = l->datalo_reg;
+    switch (opc & MO_SSIZE) {
+    case MO_SB:
+        tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW);
+        break;
+    case MO_SW:
+        tcg_out_ext16s(s, data_reg, TCG_REG_EAX, P_REXW);
+        break;
+#if TCG_TARGET_REG_BITS == 64
+    case MO_SL:
+        tcg_out_ext32s(s, data_reg, TCG_REG_EAX);
+        break;
+#endif
+    case MO_UB:
+    case MO_UW:
+        /* Note that the helpers have zero-extended to tcg_target_long.  */
+    case MO_UL:
+        tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
+        break;
+    case MO_Q:
+        if (TCG_TARGET_REG_BITS == 64) {
+            tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
+        } else if (data_reg == TCG_REG_EDX) {
+            /* xchg %edx, %eax */
+            tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX, 0, 0, 0);
+            tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_EAX);
+        } else {
+            tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
+            tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_EDX);
+        }
+        break;
+    default:
+        tcg_abort();
+    }
+
+    /* Jump to the code corresponding to next IR of qemu_st */
+    tcg_out_jmp(s, (uintptr_t)l->raddr);
+}
+
+/*
+ * Generate code for the slow path for a store at the end of block
+ */
+static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
+{
+    TCGMemOp opc = l->opc;
+    TCGMemOp s_bits = opc & MO_SIZE;
+    uint8_t **label_ptr = &l->label_ptr[0];
+    TCGReg retaddr;
+
+    /* resolve label address */
+    *(uint32_t *)label_ptr[0] = (uint32_t)(s->code_ptr - label_ptr[0] - 4);
+    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
+        *(uint32_t *)label_ptr[1] = (uint32_t)(s->code_ptr - label_ptr[1] - 4);
+    }
+
+    if (TCG_TARGET_REG_BITS == 32) {
+        int ofs = 0;
+
+        tcg_out_st(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP, ofs);
+        ofs += 4;
+
+        tcg_out_st(s, TCG_TYPE_I32, l->addrlo_reg, TCG_REG_ESP, ofs);
+        ofs += 4;
+
+        if (TARGET_LONG_BITS == 64) {
+            tcg_out_st(s, TCG_TYPE_I32, l->addrhi_reg, TCG_REG_ESP, ofs);
+            ofs += 4;
+        }
+
+        tcg_out_st(s, TCG_TYPE_I32, l->datalo_reg, TCG_REG_ESP, ofs);
+        ofs += 4;
+
+        if (s_bits == MO_64) {
+            tcg_out_st(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_ESP, ofs);
+            ofs += 4;
+        }
+
+        tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, l->mem_index);
+        ofs += 4;
+
+        retaddr = TCG_REG_EAX;
+        tcg_out_movi(s, TCG_TYPE_I32, retaddr, (uintptr_t)l->raddr);
+        tcg_out_st(s, TCG_TYPE_I32, retaddr, TCG_REG_ESP, ofs);
+    } else {
+        tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
+        /* The second argument is already loaded with addrlo.  */
+        tcg_out_mov(s, (s_bits == MO_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
+                    tcg_target_call_iarg_regs[2], l->datalo_reg);
+        tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
+                     l->mem_index);
+
+        if (ARRAY_SIZE(tcg_target_call_iarg_regs) > 4) {
+            retaddr = tcg_target_call_iarg_regs[4];
+            tcg_out_movi(s, TCG_TYPE_PTR, retaddr, (uintptr_t)l->raddr);
+        } else {
+            retaddr = TCG_REG_RAX;
+            tcg_out_movi(s, TCG_TYPE_PTR, retaddr, (uintptr_t)l->raddr);
+            tcg_out_st(s, TCG_TYPE_PTR, retaddr, TCG_REG_ESP, 0);
+        }
+    }
+
+    /* "Tail call" to the helper, with the return address back inline.  */
+    tcg_out_push(s, retaddr);
+    tcg_out_jmp(s, (uintptr_t)qemu_st_helpers[s_bits]);
+}
 #elif defined(__x86_64__) && defined(__linux__)
 # include <asm/prctl.h>
 # include <sys/prctl.h>
@@ -1250,46 +1413,36 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
    common. */
 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 {
-    int data_reg, data_reg2 = 0;
-    int addrlo_idx;
+    TCGReg datalo, datahi, addrlo;
 #if defined(CONFIG_SOFTMMU)
+    TCGReg addrhi;
     int mem_index;
     TCGMemOp s_bits;
     uint8_t *label_ptr[2];
 #endif
 
-    data_reg = args[0];
-    addrlo_idx = 1;
-    if (TCG_TARGET_REG_BITS == 32 && (opc & MO_SIZE) == MO_64) {
-        data_reg2 = args[1];
-        addrlo_idx = 2;
-    }
+    datalo = *args++;
+    datahi = (TCG_TARGET_REG_BITS == 32 && opc == 3 ? *args++ : 0);
+    addrlo = *args++;
 
 #if defined(CONFIG_SOFTMMU)
-    mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
+    addrhi = (TARGET_LONG_BITS > TCG_TARGET_REG_BITS ? *args++ : 0);
+    mem_index = *args++;
     s_bits = opc & MO_SIZE;
 
-    tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
+    tcg_out_tlb_load(s, addrlo, addrhi, mem_index, s_bits,
                      label_ptr, offsetof(CPUTLBEntry, addr_read));
 
     /* TLB Hit.  */
-    tcg_out_qemu_ld_direct(s, data_reg, data_reg2, TCG_REG_L1, 0, 0, opc);
+    tcg_out_qemu_ld_direct(s, datalo, datahi, TCG_REG_L1, 0, 0, opc);
 
     /* Record the current context of a load into ldst label */
-    add_qemu_ldst_label(s,
-                        1,
-                        opc,
-                        data_reg,
-                        data_reg2,
-                        args[addrlo_idx],
-                        args[addrlo_idx + 1],
-                        mem_index,
-                        s->code_ptr,
-                        label_ptr);
+    add_qemu_ldst_label(s, 1, opc, datalo, datahi, addrlo, addrhi,
+                        mem_index, s->code_ptr, label_ptr);
 #else
     {
         int32_t offset = GUEST_BASE;
-        int base = args[addrlo_idx];
+        TCGReg base = addrlo;
         int seg = 0;
 
         /* ??? We assume all operations have left us with register contents
@@ -1307,7 +1460,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
             offset = 0;
         }
 
-        tcg_out_qemu_ld_direct(s, data_reg, data_reg2, base, offset, seg, opc);
+        tcg_out_qemu_ld_direct(s, datalo, datahi, base, offset, seg, opc);
     }
 #endif
 }
@@ -1374,46 +1527,36 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
 
 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 {
-    int data_reg, data_reg2 = 0;
-    int addrlo_idx;
+    TCGReg datalo, datahi, addrlo;
 #if defined(CONFIG_SOFTMMU)
+    TCGReg addrhi;
     int mem_index;
     TCGMemOp s_bits;
     uint8_t *label_ptr[2];
 #endif
 
-    data_reg = args[0];
-    addrlo_idx = 1;
-    if (TCG_TARGET_REG_BITS == 32 && opc == 3) {
-        data_reg2 = args[1];
-        addrlo_idx = 2;
-    }
+    datalo = *args++;
+    datahi = (TCG_TARGET_REG_BITS == 32 && opc == 3 ? *args++ : 0);
+    addrlo = *args++;
 
 #if defined(CONFIG_SOFTMMU)
-    mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
+    addrhi = (TARGET_LONG_BITS > TCG_TARGET_REG_BITS ? *args++ : 0);
+    mem_index = *args++;
     s_bits = opc & MO_SIZE;
 
-    tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
+    tcg_out_tlb_load(s, addrlo, addrhi, mem_index, s_bits,
                      label_ptr, offsetof(CPUTLBEntry, addr_write));
 
     /* TLB Hit.  */
-    tcg_out_qemu_st_direct(s, data_reg, data_reg2, TCG_REG_L1, 0, 0, opc);
+    tcg_out_qemu_st_direct(s, datalo, datahi, TCG_REG_L1, 0, 0, opc);
 
     /* Record the current context of a store into ldst label */
-    add_qemu_ldst_label(s,
-                        0,
-                        opc,
-                        data_reg,
-                        data_reg2,
-                        args[addrlo_idx],
-                        args[addrlo_idx + 1],
-                        mem_index,
-                        s->code_ptr,
-                        label_ptr);
+    add_qemu_ldst_label(s, 0, opc, datalo, datahi, addrlo, addrhi,
+                        mem_index, s->code_ptr, label_ptr);
 #else
     {
         int32_t offset = GUEST_BASE;
-        int base = args[addrlo_idx];
+        TCGReg base = addrlo;
         int seg = 0;
 
         /* ??? We assume all operations have left us with register contents
@@ -1431,194 +1574,10 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGMemOp opc)
             offset = 0;
         }
 
-        tcg_out_qemu_st_direct(s, data_reg, data_reg2, base, offset, seg, opc);
-    }
-#endif
-}
-
-#if defined(CONFIG_SOFTMMU)
-/*
- * Record the context of a call to the out of line helper code for the slow path
- * for a load or store, so that we can later generate the correct helper code
- */
-static void add_qemu_ldst_label(TCGContext *s,
-                                int is_ld,
-                                int opc,
-                                int data_reg,
-                                int data_reg2,
-                                int addrlo_reg,
-                                int addrhi_reg,
-                                int mem_index,
-                                uint8_t *raddr,
-                                uint8_t **label_ptr)
-{
-    TCGLabelQemuLdst *label = new_ldst_label(s);
-
-    label->is_ld = is_ld;
-    label->opc = opc;
-    label->datalo_reg = data_reg;
-    label->datahi_reg = data_reg2;
-    label->addrlo_reg = addrlo_reg;
-    label->addrhi_reg = addrhi_reg;
-    label->mem_index = mem_index;
-    label->raddr = raddr;
-    label->label_ptr[0] = label_ptr[0];
-    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
-        label->label_ptr[1] = label_ptr[1];
-    }
-}
-
-/*
- * Generate code for the slow path for a load at the end of block
- */
-static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
-{
-    TCGMemOp opc = l->opc;
-    TCGMemOp s_bits = opc & MO_SIZE;
-    TCGReg data_reg;
-    uint8_t **label_ptr = &l->label_ptr[0];
-
-    /* resolve label address */
-    *(uint32_t *)label_ptr[0] = (uint32_t)(s->code_ptr - label_ptr[0] - 4);
-    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
-        *(uint32_t *)label_ptr[1] = (uint32_t)(s->code_ptr - label_ptr[1] - 4);
-    }
-
-    if (TCG_TARGET_REG_BITS == 32) {
-        int ofs = 0;
-
-        tcg_out_st(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP, ofs);
-        ofs += 4;
-
-        tcg_out_st(s, TCG_TYPE_I32, l->addrlo_reg, TCG_REG_ESP, ofs);
-        ofs += 4;
-
-        if (TARGET_LONG_BITS == 64) {
-            tcg_out_st(s, TCG_TYPE_I32, l->addrhi_reg, TCG_REG_ESP, ofs);
-            ofs += 4;
-        }
-
-        tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, l->mem_index);
-        ofs += 4;
-
-        tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, (uintptr_t)l->raddr);
-    } else {
-        tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
-        /* The second argument is already loaded with addrlo.  */
-        tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
-                     l->mem_index);
-        tcg_out_movi(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[3],
-                     (uintptr_t)l->raddr);
+        tcg_out_qemu_st_direct(s, datalo, datahi, base, offset, seg, opc);
     }
-
-    tcg_out_calli(s, (uintptr_t)qemu_ld_helpers[s_bits]);
-
-    data_reg = l->datalo_reg;
-    switch (opc & MO_SSIZE) {
-    case MO_SB:
-        tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW);
-        break;
-    case MO_SW:
-        tcg_out_ext16s(s, data_reg, TCG_REG_EAX, P_REXW);
-        break;
-#if TCG_TARGET_REG_BITS == 64
-    case MO_SL:
-        tcg_out_ext32s(s, data_reg, TCG_REG_EAX);
-        break;
 #endif
-    case MO_UB:
-    case MO_UW:
-        /* Note that the helpers have zero-extended to tcg_target_long.  */
-    case MO_UL:
-        tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
-        break;
-    case MO_Q:
-        if (TCG_TARGET_REG_BITS == 64) {
-            tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
-        } else if (data_reg == TCG_REG_EDX) {
-            /* xchg %edx, %eax */
-            tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX, 0, 0, 0);
-            tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_EAX);
-        } else {
-            tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
-            tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_EDX);
-        }
-        break;
-    default:
-        tcg_abort();
-    }
-
-    /* Jump to the code corresponding to next IR of qemu_st */
-    tcg_out_jmp(s, (uintptr_t)l->raddr);
-}
-
-/*
- * Generate code for the slow path for a store at the end of block
- */
-static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
-{
-    TCGMemOp opc = l->opc;
-    TCGMemOp s_bits = opc & MO_SIZE;
-    uint8_t **label_ptr = &l->label_ptr[0];
-    TCGReg retaddr;
-
-    /* resolve label address */
-    *(uint32_t *)label_ptr[0] = (uint32_t)(s->code_ptr - label_ptr[0] - 4);
-    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
-        *(uint32_t *)label_ptr[1] = (uint32_t)(s->code_ptr - label_ptr[1] - 4);
-    }
-
-    if (TCG_TARGET_REG_BITS == 32) {
-        int ofs = 0;
-
-        tcg_out_st(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP, ofs);
-        ofs += 4;
-
-        tcg_out_st(s, TCG_TYPE_I32, l->addrlo_reg, TCG_REG_ESP, ofs);
-        ofs += 4;
-
-        if (TARGET_LONG_BITS == 64) {
-            tcg_out_st(s, TCG_TYPE_I32, l->addrhi_reg, TCG_REG_ESP, ofs);
-            ofs += 4;
-        }
-
-        tcg_out_st(s, TCG_TYPE_I32, l->datalo_reg, TCG_REG_ESP, ofs);
-        ofs += 4;
-
-        if (s_bits == MO_64) {
-            tcg_out_st(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_ESP, ofs);
-            ofs += 4;
-        }
-
-        tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, l->mem_index);
-        ofs += 4;
-
-        retaddr = TCG_REG_EAX;
-        tcg_out_movi(s, TCG_TYPE_I32, retaddr, (uintptr_t)l->raddr);
-        tcg_out_st(s, TCG_TYPE_I32, retaddr, TCG_REG_ESP, ofs);
-    } else {
-        tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
-        /* The second argument is already loaded with addrlo.  */
-        tcg_out_mov(s, (s_bits == MO_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
-                    tcg_target_call_iarg_regs[2], l->datalo_reg);
-        tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
-                     l->mem_index);
-
-        if (ARRAY_SIZE(tcg_target_call_iarg_regs) > 4) {
-            retaddr = tcg_target_call_iarg_regs[4];
-            tcg_out_movi(s, TCG_TYPE_PTR, retaddr, (uintptr_t)l->raddr);
-        } else {
-            retaddr = TCG_REG_RAX;
-            tcg_out_movi(s, TCG_TYPE_PTR, retaddr, (uintptr_t)l->raddr);
-            tcg_out_st(s, TCG_TYPE_PTR, retaddr, TCG_REG_ESP, 0);
-        }
-    }
-
-    /* "Tail call" to the helper, with the return address back inline.  */
-    tcg_out_push(s, retaddr);
-    tcg_out_jmp(s, (uintptr_t)qemu_st_helpers[s_bits]);
 }
-#endif  /* CONFIG_SOFTMMU */
 
 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
                               const TCGArg *args, const int *const_args)
commit 37c5d0d5d1ad4e603dc50411c85bad6f726357a2
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Sep 3 13:54:21 2013 -0700

    tcg-i386: Use TCGMemOp within qemu_ldst routines
    
    Step one in the transition, with constants passed down from tcg_out_op.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index b865b4b..1b86009 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -1077,7 +1077,7 @@ static void add_qemu_ldst_label(TCGContext *s,
    First argument register is clobbered.  */
 
 static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
-                                    int mem_index, int s_bits,
+                                    int mem_index, TCGMemOp s_bits,
                                     const TCGArg *args,
                                     uint8_t **label_ptr, int which)
 {
@@ -1164,28 +1164,26 @@ static inline void setup_guest_base_seg(void)
 static inline void setup_guest_base_seg(void) { }
 #endif /* SOFTMMU */
 
-static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
-                                   int base, intptr_t ofs, int seg, int sizeop)
+static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
+                                   TCGReg base, intptr_t ofs, int seg,
+                                   TCGMemOp memop)
 {
-#ifdef TARGET_WORDS_BIGENDIAN
-    const int bswap = 1;
-#else
-    const int bswap = 0;
-#endif
-    switch (sizeop) {
-    case 0:
+    const TCGMemOp bswap = memop & MO_BSWAP;
+
+    switch (memop & MO_SSIZE) {
+    case MO_UB:
         tcg_out_modrm_offset(s, OPC_MOVZBL + seg, datalo, base, ofs);
         break;
-    case 0 | 4:
+    case MO_SB:
         tcg_out_modrm_offset(s, OPC_MOVSBL + P_REXW + seg, datalo, base, ofs);
         break;
-    case 1:
+    case MO_UW:
         tcg_out_modrm_offset(s, OPC_MOVZWL + seg, datalo, base, ofs);
         if (bswap) {
             tcg_out_rolw_8(s, datalo);
         }
         break;
-    case 1 | 4:
+    case MO_SW:
         if (bswap) {
             tcg_out_modrm_offset(s, OPC_MOVZWL + seg, datalo, base, ofs);
             tcg_out_rolw_8(s, datalo);
@@ -1195,14 +1193,14 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
                                  datalo, base, ofs);
         }
         break;
-    case 2:
+    case MO_UL:
         tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg, datalo, base, ofs);
         if (bswap) {
             tcg_out_bswap32(s, datalo);
         }
         break;
 #if TCG_TARGET_REG_BITS == 64
-    case 2 | 4:
+    case MO_SL:
         if (bswap) {
             tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg, datalo, base, ofs);
             tcg_out_bswap32(s, datalo);
@@ -1212,7 +1210,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
         }
         break;
 #endif
-    case 3:
+    case MO_Q:
         if (TCG_TARGET_REG_BITS == 64) {
             tcg_out_modrm_offset(s, OPC_MOVL_GvEv + P_REXW + seg,
                                  datalo, base, ofs);
@@ -1250,26 +1248,26 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
 /* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
    EAX. It will be useful once fixed registers globals are less
    common. */
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
-                            int opc)
+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 {
     int data_reg, data_reg2 = 0;
     int addrlo_idx;
 #if defined(CONFIG_SOFTMMU)
-    int mem_index, s_bits;
+    int mem_index;
+    TCGMemOp s_bits;
     uint8_t *label_ptr[2];
 #endif
 
     data_reg = args[0];
     addrlo_idx = 1;
-    if (TCG_TARGET_REG_BITS == 32 && opc == 3) {
+    if (TCG_TARGET_REG_BITS == 32 && (opc & MO_SIZE) == MO_64) {
         data_reg2 = args[1];
         addrlo_idx = 2;
     }
 
 #if defined(CONFIG_SOFTMMU)
     mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
-    s_bits = opc & 3;
+    s_bits = opc & MO_SIZE;
 
     tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
                      label_ptr, offsetof(CPUTLBEntry, addr_read));
@@ -1314,27 +1312,24 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
 #endif
 }
 
-static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
-                                   int base, intptr_t ofs, int seg,
-                                   int sizeop)
+static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
+                                   TCGReg base, intptr_t ofs, int seg,
+                                   TCGMemOp memop)
 {
-#ifdef TARGET_WORDS_BIGENDIAN
-    const int bswap = 1;
-#else
-    const int bswap = 0;
-#endif
+    const TCGMemOp bswap = memop & MO_BSWAP;
+
     /* ??? Ideally we wouldn't need a scratch register.  For user-only,
        we could perform the bswap twice to restore the original value
        instead of moving to the scratch.  But as it is, the L constraint
        means that TCG_REG_L0 is definitely free here.  */
-    const int scratch = TCG_REG_L0;
+    const TCGReg scratch = TCG_REG_L0;
 
-    switch (sizeop) {
-    case 0:
+    switch (memop & MO_SIZE) {
+    case MO_8:
         tcg_out_modrm_offset(s, OPC_MOVB_EvGv + P_REXB_R + seg,
                              datalo, base, ofs);
         break;
-    case 1:
+    case MO_16:
         if (bswap) {
             tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
             tcg_out_rolw_8(s, scratch);
@@ -1343,7 +1338,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
         tcg_out_modrm_offset(s, OPC_MOVL_EvGv + P_DATA16 + seg,
                              datalo, base, ofs);
         break;
-    case 2:
+    case MO_32:
         if (bswap) {
             tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
             tcg_out_bswap32(s, scratch);
@@ -1351,7 +1346,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
         }
         tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, datalo, base, ofs);
         break;
-    case 3:
+    case MO_64:
         if (TCG_TARGET_REG_BITS == 64) {
             if (bswap) {
                 tcg_out_mov(s, TCG_TYPE_I64, scratch, datalo);
@@ -1377,13 +1372,13 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
     }
 }
 
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
-                            int opc)
+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGMemOp opc)
 {
     int data_reg, data_reg2 = 0;
     int addrlo_idx;
 #if defined(CONFIG_SOFTMMU)
-    int mem_index, s_bits;
+    int mem_index;
+    TCGMemOp s_bits;
     uint8_t *label_ptr[2];
 #endif
 
@@ -1396,7 +1391,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
 
 #if defined(CONFIG_SOFTMMU)
     mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
-    s_bits = opc;
+    s_bits = opc & MO_SIZE;
 
     tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
                      label_ptr, offsetof(CPUTLBEntry, addr_write));
@@ -1478,8 +1473,8 @@ static void add_qemu_ldst_label(TCGContext *s,
  */
 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
 {
-    int opc = l->opc;
-    int s_bits = opc & 3;
+    TCGMemOp opc = l->opc;
+    TCGMemOp s_bits = opc & MO_SIZE;
     TCGReg data_reg;
     uint8_t **label_ptr = &l->label_ptr[0];
 
@@ -1519,25 +1514,25 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
     tcg_out_calli(s, (uintptr_t)qemu_ld_helpers[s_bits]);
 
     data_reg = l->datalo_reg;
-    switch(opc) {
-    case 0 | 4:
+    switch (opc & MO_SSIZE) {
+    case MO_SB:
         tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW);
         break;
-    case 1 | 4:
+    case MO_SW:
         tcg_out_ext16s(s, data_reg, TCG_REG_EAX, P_REXW);
         break;
 #if TCG_TARGET_REG_BITS == 64
-    case 2 | 4:
+    case MO_SL:
         tcg_out_ext32s(s, data_reg, TCG_REG_EAX);
         break;
 #endif
-    case 0:
-    case 1:
+    case MO_UB:
+    case MO_UW:
         /* Note that the helpers have zero-extended to tcg_target_long.  */
-    case 2:
+    case MO_UL:
         tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
         break;
-    case 3:
+    case MO_Q:
         if (TCG_TARGET_REG_BITS == 64) {
             tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
         } else if (data_reg == TCG_REG_EDX) {
@@ -1562,8 +1557,8 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
  */
 static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
 {
-    int opc = l->opc;
-    int s_bits = opc & 3;
+    TCGMemOp opc = l->opc;
+    TCGMemOp s_bits = opc & MO_SIZE;
     uint8_t **label_ptr = &l->label_ptr[0];
     TCGReg retaddr;
 
@@ -1590,7 +1585,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
         tcg_out_st(s, TCG_TYPE_I32, l->datalo_reg, TCG_REG_ESP, ofs);
         ofs += 4;
 
-        if (opc == 3) {
+        if (s_bits == MO_64) {
             tcg_out_st(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_ESP, ofs);
             ofs += 4;
         }
@@ -1604,7 +1599,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
     } else {
         tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
         /* The second argument is already loaded with addrlo.  */
-        tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
+        tcg_out_mov(s, (s_bits == MO_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
                     tcg_target_call_iarg_regs[2], l->datalo_reg);
         tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
                      l->mem_index);
@@ -1851,38 +1846,38 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         break;
 
     case INDEX_op_qemu_ld8u:
-        tcg_out_qemu_ld(s, args, 0);
+        tcg_out_qemu_ld(s, args, MO_UB);
         break;
     case INDEX_op_qemu_ld8s:
-        tcg_out_qemu_ld(s, args, 0 | 4);
+        tcg_out_qemu_ld(s, args, MO_SB);
         break;
     case INDEX_op_qemu_ld16u:
-        tcg_out_qemu_ld(s, args, 1);
+        tcg_out_qemu_ld(s, args, MO_TEUW);
         break;
     case INDEX_op_qemu_ld16s:
-        tcg_out_qemu_ld(s, args, 1 | 4);
+        tcg_out_qemu_ld(s, args, MO_TESW);
         break;
 #if TCG_TARGET_REG_BITS == 64
     case INDEX_op_qemu_ld32u:
 #endif
     case INDEX_op_qemu_ld32:
-        tcg_out_qemu_ld(s, args, 2);
+        tcg_out_qemu_ld(s, args, MO_TEUL);
         break;
     case INDEX_op_qemu_ld64:
-        tcg_out_qemu_ld(s, args, 3);
+        tcg_out_qemu_ld(s, args, MO_TEQ);
         break;
 
     case INDEX_op_qemu_st8:
-        tcg_out_qemu_st(s, args, 0);
+        tcg_out_qemu_st(s, args, MO_UB);
         break;
     case INDEX_op_qemu_st16:
-        tcg_out_qemu_st(s, args, 1);
+        tcg_out_qemu_st(s, args, MO_TEUW);
         break;
     case INDEX_op_qemu_st32:
-        tcg_out_qemu_st(s, args, 2);
+        tcg_out_qemu_st(s, args, MO_TEUL);
         break;
     case INDEX_op_qemu_st64:
-        tcg_out_qemu_st(s, args, 3);
+        tcg_out_qemu_st(s, args, MO_TEQ);
         break;
 
     OP_32_64(mulu2):
@@ -1943,7 +1938,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         }
         break;
     case INDEX_op_qemu_ld32s:
-        tcg_out_qemu_ld(s, args, 2 | 4);
+        tcg_out_qemu_ld(s, args, MO_TESL);
         break;
 
     case INDEX_op_brcond_i64:
commit d257e0d7aeb72f4280666590f81ca5f0a38697f8
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Oct 11 14:32:06 2013 -0700

    tcg: Use TCGMemOp for TCGLabelQemuLdst.opc
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/tcg-be-ldst.h b/tcg/tcg-be-ldst.h
index 2826d29..284db0c 100644
--- a/tcg/tcg-be-ldst.h
+++ b/tcg/tcg-be-ldst.h
@@ -25,7 +25,7 @@
 
 typedef struct TCGLabelQemuLdst {
     int is_ld:1;            /* qemu_ld: 1, qemu_st: 0 */
-    int opc:4;
+    TCGMemOp opc:4;
     TCGReg addrlo_reg;      /* reg index for low word of guest virtual addr */
     TCGReg addrhi_reg;      /* reg index for high word of guest virtual addr */
     TCGReg datalo_reg;      /* reg index for low word to be loaded or stored */
commit 1cdae4573d7613149348d834c605bfbe3c7d405b
Merge: ab1eb72 0106dc4
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Fri Oct 11 09:38:07 2013 -0700

    Merge remote-tracking branch 'mdroth/qga-pull-2013-10-10' into staging
    
    # By Mark Wu (2) and Tomoki Sekiyama (1)
    # Via Michael Roth
    * mdroth/qga-pull-2013-10-10:
      qemu-ga: Extend 'guest-info' command to expose flag 'success-response'
      qemu-ga: Add interface to traverse the qmp command list by QmpCommand
      qemu-ga: execute fsfreeze-freeze in reverse order of mounts
    
    Message-id: 1381435782-25524-1-git-send-email-mdroth at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit ab1eb72b1db1740093d52207887a2cfc8665bad6
Merge: a3400ae 867b320
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Fri Oct 11 09:36:52 2013 -0700

    Merge remote-tracking branch 'rth/tcg-pull' into staging
    
    # By Richard Henderson
    # Via Richard Henderson
    * rth/tcg-pull:
      exec: Add both big- and little-endian memory helpers
      tcg: Add qemu_ld_st_i32/64
      tcg: Add TCGMemOp
      configure: Remove CONFIG_QEMU_LDST_OPTIMIZATION
      tcg: Add tcg-be-ldst.h
      tcg: Add tcg-be-null.h
      exec: Delete is_tcg_gen_code and GETRA_EXT
      tcg-aarch64: Update to helper_ret_*_mmu routines
      tcg: Merge tcg_register_helper into tcg_context_init
      tcg: Add tcg-runtime.c helpers to all_helpers
      tcg: Put target helper data into an array.
      tcg: Remove stray semi-colons from target-*/helper.h
      tcg: Move helper registration into tcg_context_init
      target-m68k: Rename helpers.h to helper.h
      tcg: Use a GHashTable for tcg_find_helper
      tcg: Delete tcg_helper_get_name declaration
      tcg-hppa: Remove tcg backend
    
    Message-id: 1381440525-6666-1-git-send-email-rth at twiddle.net
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit a3400aeede46c6c30b6fefb20fc90a43f1f6e7b2
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu Oct 10 15:00:21 2013 +0200

    qdev-monitor: Group "device_add help" and "info qdm" by category
    
    Output is a long, unsorted list.  Not very helpful.  Print one list
    per device category instead, with a header line identifying the
    category, plus a list of uncategorized devices.  Print each list in
    case-insenitive alphabetical order.
    
    Devices with multiple categories are listed multiple times.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Marcel Apfelbaum <marcel.a at redhat.com>
    Message-id: 1381410021-1538-3-git-send-email-armbru at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

diff --git a/qdev-monitor.c b/qdev-monitor.c
index e5adf6c..a02c925 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -75,18 +75,9 @@ static bool qdev_class_has_alias(DeviceClass *dc)
     return (qdev_class_get_alias(dc) != NULL);
 }
 
-static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
+static void qdev_print_devinfo(DeviceClass *dc)
 {
-    DeviceClass *dc;
-    bool *show_no_user = opaque;
-
-    dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE);
-
-    if (!dc || (show_no_user && !*show_no_user && dc->no_user)) {
-        return;
-    }
-
-    error_printf("name \"%s\"", object_class_get_name(klass));
+    error_printf("name \"%s\"", object_class_get_name(OBJECT_CLASS(dc)));
     if (dc->bus_type) {
         error_printf(", bus %s", dc->bus_type);
     }
@@ -102,6 +93,55 @@ static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
     error_printf("\n");
 }
 
+static gint devinfo_cmp(gconstpointer a, gconstpointer b)
+{
+    return strcasecmp(object_class_get_name((ObjectClass *)a),
+                      object_class_get_name((ObjectClass *)b));
+}
+
+static void qdev_print_devinfos(bool show_no_user)
+{
+    static const char *cat_name[DEVICE_CATEGORY_MAX + 1] = {
+        [DEVICE_CATEGORY_BRIDGE]  = "Controller/Bridge/Hub",
+        [DEVICE_CATEGORY_USB]     = "USB",
+        [DEVICE_CATEGORY_STORAGE] = "Storage",
+        [DEVICE_CATEGORY_NETWORK] = "Network",
+        [DEVICE_CATEGORY_INPUT]   = "Input",
+        [DEVICE_CATEGORY_DISPLAY] = "Display",
+        [DEVICE_CATEGORY_SOUND]   = "Sound",
+        [DEVICE_CATEGORY_MISC]    = "Misc",
+        [DEVICE_CATEGORY_MAX]     = "Uncategorized",
+    };
+    GSList *list, *elt;
+    int i;
+    bool cat_printed;
+
+    list = g_slist_sort(object_class_get_list(TYPE_DEVICE, false),
+                        devinfo_cmp);
+
+    for (i = 0; i <= DEVICE_CATEGORY_MAX; i++) {
+        cat_printed = false;
+        for (elt = list; elt; elt = elt->next) {
+            DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, elt->data,
+                                                 TYPE_DEVICE);
+            if ((i < DEVICE_CATEGORY_MAX
+                 ? !test_bit(i, dc->categories)
+                 : !bitmap_empty(dc->categories, DEVICE_CATEGORY_MAX))
+                || (!show_no_user && dc->no_user)) {
+                continue;
+            }
+            if (!cat_printed) {
+                error_printf("%s%s devices:\n", i ? "\n" : "",
+                             cat_name[i]);
+                cat_printed = true;
+            }
+            qdev_print_devinfo(dc);
+        }
+    }
+
+    g_slist_free(list);
+}
+
 static int set_property(const char *name, const char *value, void *opaque)
 {
     DeviceState *dev = opaque;
@@ -147,8 +187,7 @@ int qdev_device_help(QemuOpts *opts)
 
     driver = qemu_opt_get(opts, "driver");
     if (driver && is_help_option(driver)) {
-        bool show_no_user = false;
-        object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user);
+        qdev_print_devinfos(false);
         return 1;
     }
 
@@ -587,7 +626,7 @@ void do_info_qtree(Monitor *mon, const QDict *qdict)
 
 void do_info_qdm(Monitor *mon, const QDict *qdict)
 {
-    object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, NULL);
+    qdev_print_devinfos(true);
 }
 
 int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
commit 1fc224b4b6d195fb7802d5ba1a0846a4e7a1e2af
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu Oct 10 15:00:20 2013 +0200

    Mostly revert "qemu-help: Sort devices by logical functionality"
    
    This reverts most of commit 3d1237fb2ab4edb926c717767bb5e31d6053a7c5.
    
    The commit claims to sort the output of "-device help" "by
    functionality rather than alphabetical".  Issues:
    
    * The output was unsorted before, not alphabetically sorted.
      Misleading, but harmless enough.
    
    * The commit doesn't just sort the output of "-device help" as it
      claims, it adds categories to each line of "-device help", and it
      prints devices once per category.  In particular, devices without a
      category aren't shown anymore.  Maybe such devices should not exist,
      but they do.  Regression.
    
    * Categories are also added to the output of "info qdm".  Silent
      change, not nice.  Output remains unsorted, unlike "-device help".
    
    I'm going to reimplement the feature we actually want, without the
    warts.  Reverting the flawed commit first should make it easier to
    review.  However, I can't revert it completely, since DeviceClass
    member categories has been put to use.  So leave that part in.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Marcel Apfelbaum <marcel.a at redhat.com>
    Message-id: 1381410021-1538-2-git-send-email-armbru at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index a62f231..e191ca0 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -30,22 +30,6 @@ typedef enum DeviceCategory {
     DEVICE_CATEGORY_MAX
 } DeviceCategory;
 
-static inline const char *qdev_category_get_name(DeviceCategory category)
-{
-    static const char *category_names[DEVICE_CATEGORY_MAX] = {
-        [DEVICE_CATEGORY_BRIDGE]  = "Controller/Bridge/Hub",
-        [DEVICE_CATEGORY_USB]     = "USB",
-        [DEVICE_CATEGORY_STORAGE] = "Storage",
-        [DEVICE_CATEGORY_NETWORK] = "Network",
-        [DEVICE_CATEGORY_INPUT]   = "Input",
-        [DEVICE_CATEGORY_DISPLAY] = "Display",
-        [DEVICE_CATEGORY_SOUND]   = "Sound",
-        [DEVICE_CATEGORY_MISC]    = "Misc",
-    };
-
-    return category_names[category];
-};
-
 typedef int (*qdev_initfn)(DeviceState *dev);
 typedef int (*qdev_event)(DeviceState *dev);
 typedef void (*qdev_resetfn)(DeviceState *dev);
diff --git a/qdev-monitor.c b/qdev-monitor.c
index 410cdcb..e5adf6c 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -75,27 +75,24 @@ static bool qdev_class_has_alias(DeviceClass *dc)
     return (qdev_class_get_alias(dc) != NULL);
 }
 
-static void qdev_print_class_devinfo(DeviceClass *dc)
+static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
 {
-    DeviceCategory category;
+    DeviceClass *dc;
+    bool *show_no_user = opaque;
+
+    dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE);
 
-    if (!dc) {
+    if (!dc || (show_no_user && !*show_no_user && dc->no_user)) {
         return;
     }
 
-    error_printf("name \"%s\"", object_class_get_name(OBJECT_CLASS(dc)));
+    error_printf("name \"%s\"", object_class_get_name(klass));
     if (dc->bus_type) {
         error_printf(", bus %s", dc->bus_type);
     }
     if (qdev_class_has_alias(dc)) {
         error_printf(", alias \"%s\"", qdev_class_get_alias(dc));
     }
-    error_printf(", categories");
-    for (category = 0; category < DEVICE_CATEGORY_MAX; ++category) {
-        if (test_bit(category, dc->categories)) {
-            error_printf(" \"%s\"", qdev_category_get_name(category));
-        }
-    }
     if (dc->desc) {
         error_printf(", desc \"%s\"", dc->desc);
     }
@@ -105,15 +102,6 @@ static void qdev_print_class_devinfo(DeviceClass *dc)
     error_printf("\n");
 }
 
-static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
-{
-    DeviceClass *dc;
-
-    dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE);
-
-    qdev_print_class_devinfo(dc);
-}
-
 static int set_property(const char *name, const char *value, void *opaque)
 {
     DeviceState *dev = opaque;
@@ -151,21 +139,6 @@ static const char *find_typename_by_alias(const char *alias)
     return NULL;
 }
 
-static void qdev_print_category_devices(DeviceCategory category)
-{
-    DeviceClass *dc;
-    GSList *list, *curr;
-
-    list = object_class_get_list(TYPE_DEVICE, false);
-    for (curr = list; curr; curr = g_slist_next(curr)) {
-        dc = (DeviceClass *)object_class_dynamic_cast(curr->data, TYPE_DEVICE);
-        if (!dc->no_user && test_bit(category, dc->categories)) {
-            qdev_print_class_devinfo(dc);
-        }
-    }
-    g_slist_free(list);
-}
-
 int qdev_device_help(QemuOpts *opts)
 {
     const char *driver;
@@ -174,11 +147,8 @@ int qdev_device_help(QemuOpts *opts)
 
     driver = qemu_opt_get(opts, "driver");
     if (driver && is_help_option(driver)) {
-        DeviceCategory category;
-        for (category = 0; category < DEVICE_CATEGORY_MAX; ++category) {
-            qdev_print_category_devices(category);
-        }
-
+        bool show_no_user = false;
+        object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user);
         return 1;
     }
 
commit 859389810910f232188675d2f10b15f1aad77660
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Oct 11 14:52:38 2013 +0200

    Use qemu-project.org domain name
    
    qemu.org is held by a third-party and no core community contributor has
    access to the DNS configuration.  This leaves the website exposed to
    outages due to DNS issues or IP address changes.  For example, if the
    web server IP address needs to change we cannot guarantee qemu.org will
    point to it!
    
    The newer qemu-project.org domain name is owned by Anthony Liguori
    <anthony at codemonkey.ws>.  You can confirm this by querying the whois
    information.  Also note that the #qemu IRC channel topic already
    references qemu-project.org.
    
    Short of having a dedicated legal entity to hold the domain name on
    behalf of the community, qemu-project.org seems like the safest bet.
    
    Let's replace references to qemu.org with qemu-project.org.
    
    Note that git-submodule(1) does not detect URL changes.  The following
    commands clear out and re-initialize all submodules to ensure you are
    using the latest URLs:
    
      $ git submodule deinit . # you'll be warned if you have local changes
      $ rm -rf .git/modules    # also clear cached .git/ directories
      $ git submodule update --init
    
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Message-id: 1381495958-8306-1-git-send-email-stefanha at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

diff --git a/.gitmodules b/.gitmodules
index d7e3f3c..45e51e7 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,27 +1,27 @@
 [submodule "roms/vgabios"]
 	path = roms/vgabios
-	url = git://git.qemu.org/vgabios.git/
+	url = git://git.qemu-project.org/vgabios.git/
 [submodule "roms/seabios"]
 	path = roms/seabios
-	url = git://git.qemu.org/seabios.git/
+	url = git://git.qemu-project.org/seabios.git/
 [submodule "roms/SLOF"]
 	path = roms/SLOF
-	url = git://git.qemu.org/SLOF.git
+	url = git://git.qemu-project.org/SLOF.git
 [submodule "roms/ipxe"]
 	path = roms/ipxe
-	url = git://git.qemu.org/ipxe.git
+	url = git://git.qemu-project.org/ipxe.git
 [submodule "roms/openbios"]
 	path = roms/openbios
-	url = git://git.qemu.org/openbios.git
+	url = git://git.qemu-project.org/openbios.git
 [submodule "roms/qemu-palcode"]
 	path = roms/qemu-palcode
 	url = git://github.com/rth7680/qemu-palcode.git
 [submodule "roms/sgabios"]
 	path = roms/sgabios
-	url = git://git.qemu.org/sgabios.git
+	url = git://git.qemu-project.org/sgabios.git
 [submodule "pixman"]
 	path = pixman
 	url = git://anongit.freedesktop.org/pixman
 [submodule "dtc"]
 	path = dtc
-	url = git://git.qemu.org/dtc.git
+	url = git://git.qemu-project.org/dtc.git
diff --git a/Changelog b/Changelog
index 13eebef..1249b8a 100644
--- a/Changelog
+++ b/Changelog
@@ -1,6 +1,6 @@
 This file documents changes for QEMU releases 0.12 and earlier.
 For changelog information for later releases, see
-http://wiki.qemu.org/ChangeLog or look at the git history for
+http://wiki.qemu-project.org/ChangeLog or look at the git history for
 more detailed information.
 
 
diff --git a/MAINTAINERS b/MAINTAINERS
index fbe1fd9..3c3e9fe 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -844,21 +844,21 @@ Stable branches
 ---------------
 Stable 1.0
 L: qemu-stable at nongnu.org
-T: git git://git.qemu.org/qemu-stable-1.0.git
+T: git git://git.qemu-project.org/qemu-stable-1.0.git
 S: Orphan
 
 Stable 0.15
 L: qemu-stable at nongnu.org
 M: Andreas Färber <afaerber at suse.de>
-T: git git://git.qemu.org/qemu-stable-0.15.git
+T: git git://git.qemu-project.org/qemu-stable-0.15.git
 S: Supported
 
 Stable 0.14
 L: qemu-stable at nongnu.org
-T: git git://git.qemu.org/qemu-stable-0.14.git
+T: git git://git.qemu-project.org/qemu-stable-0.14.git
 S: Orphan
 
 Stable 0.10
 L: qemu-stable at nongnu.org
-T: git git://git.qemu.org/qemu-stable-0.10.git
+T: git git://git.qemu-project.org/qemu-stable-0.10.git
 S: Orphan
diff --git a/README b/README
index c77d126..c7c990d 100644
--- a/README
+++ b/README
@@ -1,3 +1,3 @@
-Read the documentation in qemu-doc.html or on http://wiki.qemu.org
+Read the documentation in qemu-doc.html or on http://wiki.qemu-project.org
 
 - QEMU team
diff --git a/docs/qmp/README b/docs/qmp/README
index 85c4bc1..f6a3a03 100644
--- a/docs/qmp/README
+++ b/docs/qmp/README
@@ -84,4 +84,4 @@ Please, refer to the qapi-schema.json file for a complete command reference.
 QMP wiki page
 -------------
 
-http://wiki.qemu.org/QMP
+http://wiki.qemu-project.org/QMP
diff --git a/docs/rdma.txt b/docs/rdma.txt
index 8d1e003..2aca63b 100644
--- a/docs/rdma.txt
+++ b/docs/rdma.txt
@@ -1,7 +1,7 @@
 (RDMA: Remote Direct Memory Access)
 RDMA Live Migration Specification, Version # 1
 ==============================================
-Wiki: http://wiki.qemu.org/Features/RDMALiveMigration
+Wiki: http://wiki.qemu-project.org/Features/RDMALiveMigration
 Github: git at github.com:hinesmr/qemu.git, 'rdma' branch
 
 Copyright (C) 2013 Michael R. Hines <mrhines at us.ibm.com>
diff --git a/pc-bios/README b/pc-bios/README
index d70be16..be8dae0 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -23,7 +23,7 @@
   legacy x86 software to communicate with an attached serial console as
   if a video card were attached.  The master sources reside in a subversion
   repository at http://sgabios.googlecode.com/svn/trunk.  A git mirror is
-  available at git://git.qemu.org/sgabios.git.
+  available at git://git.qemu-project.org/sgabios.git.
 
 - The PXE roms come from the iPXE project. Built with BANNER_TIME 0.
   Sources available at http://ipxe.org.  Vendor:Device ID -> ROM mapping:
diff --git a/qemu.nsi b/qemu.nsi
index 1d57455..0dc1f52 100644
--- a/qemu.nsi
+++ b/qemu.nsi
@@ -20,7 +20,7 @@
 ; NSIS_WIN32_MAKENSIS
 
 !define PRODUCT "QEMU"
-!define URL     "http://www.qemu.org/"
+!define URL     "http://www.qemu-project.org/"
 
 !define UNINST_EXE "$INSTDIR\qemu-uninstall.exe"
 !define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT}"
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index bf5342a..38334de 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -1385,7 +1385,7 @@ sub vcs_exists {
 	warn("$P: No supported VCS found.  Add --nogit to options?\n");
 	warn("Using a git repository produces better results.\n");
 	warn("Try latest git repository using:\n");
-	warn("git clone git://git.qemu.org/qemu.git\n");
+	warn("git clone git://git.qemu-project.org/qemu.git\n");
 	$printed_novcs = 1;
     }
     return 0;
diff --git a/scripts/qmp/qemu-ga-client b/scripts/qmp/qemu-ga-client
index b5f7e7c..9908f21 100755
--- a/scripts/qmp/qemu-ga-client
+++ b/scripts/qmp/qemu-ga-client
@@ -33,7 +33,7 @@
 # $ qemu-ga-client fsfreeze freeze
 # 2 filesystems frozen
 #
-# See also: http://wiki.qemu.org/Features/QAPI/GuestAgent
+# See also: http://wiki.qemu-project.org/Features/QAPI/GuestAgent
 #
 
 import base64
diff --git a/version.rc b/version.rc
index a50d62f..d42ef62 100644
--- a/version.rc
+++ b/version.rc
@@ -13,7 +13,7 @@ FILESUBTYPE VFT2_UNKNOWN
   {
     BLOCK "040904E4"
     {
-      VALUE "CompanyName", "http://www.qemu.org"
+      VALUE "CompanyName", "http://www.qemu-project.org"
       VALUE "FileDescription", "QEMU machine emulators and tools"
       VALUE "FileVersion", QEMU_VERSION
       VALUE "LegalCopyright", "Copyright various authors. Released under the GNU General Public License."
commit 33c6cae44eccea5e627c2dc5cbf31456db90fc38
Merge: 39c153b 34eeb82
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Fri Oct 11 09:29:58 2013 -0700

    Merge remote-tracking branch 'kwolf/for-anthony' into staging
    
    # By Max Reitz (30) and others
    # Via Kevin Wolf
    * kwolf/for-anthony: (61 commits)
      qemu-iotests: Add test for inactive L2 overlap
      qemu-io: Let "open" pass options to block driver
      vmdk: Fix vmdk_parse_extents
      blockdev: blockdev_init() error conversion
      blockdev: Don't disable COR automatically with blockdev-add
      blockdev: Remove 'media' parameter from blockdev_init()
      qemu-iotests: Check autodel behaviour for device_del
      blockdev: Remove IF_* check for read-only blockdev_init
      blockdev: Move virtio-blk device creation to drive_init
      blockdev: Move bus/unit/index processing to drive_init
      blockdev: Move parsing of 'boot' option to drive_init
      blockdev: Moving parsing of geometry options to drive_init
      blockdev: Move parsing of 'if' option to drive_init
      blockdev: Move parsing of 'media' option to drive_init
      blockdev: Pass QDict to blockdev_init()
      blockdev: Separate ID generation from DriveInfo creation
      blockdev: 'blockdev-add' QMP command
      blockdev: Introduce DriveInfo.enable_auto_del
      qapi-types/visit.py: Inheritance for structs
      qapi-types/visit.py: Pass whole expr dict for structs
      ...
    
    Message-id: 1381503951-27985-1-git-send-email-kwolf at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit 34eeb82de65ce9f83081a3357b0afe80a6a1d86a
Author: Max Reitz <mreitz at redhat.com>
Date:   Fri Oct 11 14:02:11 2013 +0200

    qemu-iotests: Add test for inactive L2 overlap
    
    Extend 060 by a test which creates a corrupted image with an active L2
    entry pointing to an inactive L2 table and writes to the corresponding
    guest offset.
    
    Also, use overlap-check=all for all tests in 060.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060
index 9bbc43b..bbb1909 100755
--- a/tests/qemu-iotests/060
+++ b/tests/qemu-iotests/060
@@ -21,10 +21,10 @@
 # creator
 owner=mreitz at redhat.com
 
-seq=`basename $0`
+seq="$(basename $0)"
 echo "QA output created by $seq"
 
-here=`pwd`
+here="$PWD"
 tmp=/tmp/$$
 status=1	# failure is the default!
 
@@ -47,9 +47,15 @@ rt_offset=65536  # 0x10000 (XXX: just an assumption)
 rb_offset=131072 # 0x20000 (XXX: just an assumption)
 l1_offset=196608 # 0x30000 (XXX: just an assumption)
 l2_offset=262144 # 0x40000 (XXX: just an assumption)
+l2_offset_after_snapshot=524288 # 0x80000 (XXX: just an assumption)
 
 IMGOPTS="compat=1.1"
 
+OPEN_RW="open -o overlap-check=all $TEST_IMG"
+# Overlap checks are done before write operations only, therefore opening an
+# image read-only makes the overlap-check option irrelevant
+OPEN_RO="open -r $TEST_IMG"
+
 echo
 echo "=== Testing L2 reference into L1 ==="
 echo
@@ -65,16 +71,18 @@ _check_test_img
 ./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
 
 # Try to write something, thereby forcing the corrupt bit to be set
-$QEMU_IO -c "write -P 0x2a 0 512" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "$OPEN_RW" -c "write -P 0x2a 0 512" | _filter_qemu_io
 
 # The corrupt bit must now be set
 ./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
 
 # Try to open the image R/W (which should fail)
-$QEMU_IO -c "read 0 512" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir | _filter_imgfmt
+$QEMU_IO -c "$OPEN_RW" -c "read 0 512" 2>&1 | _filter_qemu_io \
+                                            | _filter_testdir \
+                                            | _filter_imgfmt
 
 # Try to open it RO (which should succeed)
-$QEMU_IO -c "read 0 512" -r "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "$OPEN_RO" -c "read 0 512" | _filter_qemu_io
 
 # We could now try to fix the image, but this would probably fail (how should an
 # L2 table linked onto the L1 table be fixed?)
@@ -92,7 +100,7 @@ poke_file "$TEST_IMG" "$(($rb_offset+8))" "\x00\x01"
 poke_file "$TEST_IMG" "$l2_offset" "\x80\x00\x00\x00\x00\x02\x00\x00"
 _check_test_img
 ./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
-$QEMU_IO -c "write -P 0x2a 0 512" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "$OPEN_RW" -c "write -P 0x2a 0 512" | _filter_qemu_io
 ./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
 
 # Try to fix it
@@ -102,8 +110,33 @@ _check_test_img -r all
 ./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
 
 # Look if it's really really fixed
-$QEMU_IO -c "write -P 0x2a 0 512" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "$OPEN_RW" -c "write -P 0x2a 0 512" | _filter_qemu_io
+./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+
+echo
+echo "=== Testing cluster data reference into inactive L2 table ==="
+echo
+_make_test_img 64M
+$QEMU_IO -c "$OPEN_RW" -c "write -P 1 0 512" | _filter_qemu_io
+$QEMU_IMG snapshot -c foo "$TEST_IMG"
+$QEMU_IO -c "$OPEN_RW" -c "write -P 2 0 512" | _filter_qemu_io
+# The inactive L2 table remains at its old offset
+poke_file "$TEST_IMG" "$l2_offset_after_snapshot" \
+                      "\x80\x00\x00\x00\x00\x04\x00\x00"
+_check_test_img
 ./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$QEMU_IO -c "$OPEN_RW" -c "write -P 3 0 512" | _filter_qemu_io
+./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+_check_test_img -r all
+./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$QEMU_IO -c "$OPEN_RW" -c "write -P 4 0 512" | _filter_qemu_io
+./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+
+# Check data
+$QEMU_IO -c "$OPEN_RO" -c "read -P 4 0 512" | _filter_qemu_io
+$QEMU_IMG snapshot -a foo "$TEST_IMG"
+_check_test_img
+$QEMU_IO -c "$OPEN_RO" -c "read -P 1 0 512" | _filter_qemu_io
 
 # success, all done
 echo "*** done"
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
index 648f743..6c7bdbb 100644
--- a/tests/qemu-iotests/060.out
+++ b/tests/qemu-iotests/060.out
@@ -12,7 +12,6 @@ qcow2: Preventing invalid write on metadata (overlaps with active L1 table); ima
 write failed: Input/output error
 incompatible_features     0x2
 qemu-io: can't open device TEST_DIR/t.IMGFMT: IMGFMT: Image is corrupt; cannot be opened read/write
-no file open, try 'help open'
 read 512/512 bytes at offset 0
 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
@@ -40,4 +39,43 @@ incompatible_features     0x0
 wrote 512/512 bytes at offset 0
 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 incompatible_features     0x0
+
+=== Testing cluster data reference into inactive L2 table ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ERROR cluster 4 refcount=1 reference=2
+Leaked cluster 9 refcount=1 reference=0
+
+1 errors were found on the image.
+Data may be corrupted, or further writes to the image may corrupt it.
+
+1 leaked clusters were found on the image.
+This means waste of disk space, but no harm to data.
+incompatible_features     0x0
+qcow2: Preventing invalid write on metadata (overlaps with inactive L2 table); image marked as corrupt.
+write failed: Input/output error
+incompatible_features     0x2
+Repairing cluster 4 refcount=1 reference=2
+Repairing cluster 9 refcount=1 reference=0
+Repairing OFLAG_COPIED data cluster: l2_entry=8000000000040000 refcount=2
+The following inconsistencies were found and repaired:
+
+    1 leaked clusters
+    2 corruptions
+
+Double checking the fixed image now...
+No errors were found on the image.
+incompatible_features     0x0
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+incompatible_features     0x0
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+No errors were found on the image.
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 *** done
commit b543c5cdcb818ffed90cfc97aa8e297214650d84
Author: Max Reitz <mreitz at redhat.com>
Date:   Fri Oct 11 14:02:10 2013 +0200

    qemu-io: Let "open" pass options to block driver
    
    Add an option to the open command to specify runtime options for the
    block driver used.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-io.c b/qemu-io.c
index f4b8efc..3b3340a 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -16,6 +16,8 @@
 
 #include "qemu-io.h"
 #include "qemu/main-loop.h"
+#include "qemu/option.h"
+#include "qemu/config-file.h"
 #include "block/block_int.h"
 #include "trace/control.h"
 
@@ -44,7 +46,7 @@ static const cmdinfo_t close_cmd = {
     .oneline    = "close the current open file",
 };
 
-static int openfile(char *name, int flags, int growable)
+static int openfile(char *name, int flags, int growable, QDict *opts)
 {
     Error *local_err = NULL;
 
@@ -54,7 +56,7 @@ static int openfile(char *name, int flags, int growable)
     }
 
     if (growable) {
-        if (bdrv_file_open(&qemuio_bs, name, NULL, flags, &local_err)) {
+        if (bdrv_file_open(&qemuio_bs, name, opts, flags, &local_err)) {
             fprintf(stderr, "%s: can't open device %s: %s\n", progname, name,
                     error_get_pretty(local_err));
             error_free(local_err);
@@ -63,7 +65,7 @@ static int openfile(char *name, int flags, int growable)
     } else {
         qemuio_bs = bdrv_new("hda");
 
-        if (bdrv_open(qemuio_bs, name, NULL, flags, NULL, &local_err) < 0) {
+        if (bdrv_open(qemuio_bs, name, opts, flags, NULL, &local_err) < 0) {
             fprintf(stderr, "%s: can't open device %s: %s\n", progname, name,
                     error_get_pretty(local_err));
             error_free(local_err);
@@ -89,7 +91,8 @@ static void open_help(void)
 " -r, -- open file read-only\n"
 " -s, -- use snapshot file\n"
 " -n, -- disable host cache\n"
-" -g, -- allow file to grow (only applies to protocols)"
+" -g, -- allow file to grow (only applies to protocols)\n"
+" -o, -- options to be given to the block driver"
 "\n");
 }
 
@@ -102,19 +105,30 @@ static const cmdinfo_t open_cmd = {
     .argmin     = 1,
     .argmax     = -1,
     .flags      = CMD_NOFILE_OK,
-    .args       = "[-Crsn] [path]",
+    .args       = "[-Crsn] [-o options] [path]",
     .oneline    = "open the file specified by path",
     .help       = open_help,
 };
 
+static QemuOptsList empty_opts = {
+    .name = "drive",
+    .head = QTAILQ_HEAD_INITIALIZER(empty_opts.head),
+    .desc = {
+        /* no elements => accept any params */
+        { /* end of list */ }
+    },
+};
+
 static int open_f(BlockDriverState *bs, int argc, char **argv)
 {
     int flags = 0;
     int readonly = 0;
     int growable = 0;
     int c;
+    QemuOpts *qopts;
+    QDict *opts = NULL;
 
-    while ((c = getopt(argc, argv, "snrg")) != EOF) {
+    while ((c = getopt(argc, argv, "snrgo:")) != EOF) {
         switch (c) {
         case 's':
             flags |= BDRV_O_SNAPSHOT;
@@ -128,6 +142,15 @@ static int open_f(BlockDriverState *bs, int argc, char **argv)
         case 'g':
             growable = 1;
             break;
+        case 'o':
+            qopts = qemu_opts_parse(&empty_opts, optarg, 0);
+            if (qopts == NULL) {
+                printf("could not parse option list -- %s\n", optarg);
+                return 0;
+            }
+            opts = qemu_opts_to_qdict(qopts, opts);
+            qemu_opts_del(qopts);
+            break;
         default:
             return qemuio_command_usage(&open_cmd);
         }
@@ -141,7 +164,7 @@ static int open_f(BlockDriverState *bs, int argc, char **argv)
         return qemuio_command_usage(&open_cmd);
     }
 
-    return openfile(argv[optind], flags, growable);
+    return openfile(argv[optind], flags, growable, opts);
 }
 
 static int quit_f(BlockDriverState *bs, int argc, char **argv)
@@ -418,7 +441,7 @@ int main(int argc, char **argv)
     }
 
     if ((argc - optind) == 1) {
-        openfile(argv[optind], flags, growable);
+        openfile(argv[optind], flags, growable, NULL);
     }
     command_loop();
 
commit 899f1ae219d5eaa96a53c996026cb0178d62a86d
Author: Fam Zheng <famz at redhat.com>
Date:   Fri Oct 11 19:48:29 2013 +0800

    vmdk: Fix vmdk_parse_extents
    
    An extra 'p++' after while loop when *p == '\n' will move p to unknown
    data position, risking parsing junk data or memory access violation.
    
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index 709aa3d..5a9f278 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -772,10 +772,13 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
         }
 next_line:
         /* move to next line */
-        while (*p && *p != '\n') {
+        while (*p) {
+            if (*p == '\n') {
+                p++;
+                break;
+            }
             p++;
         }
-        p++;
     }
     return 0;
 }
commit b681072d2005911b79835d2a6af208eba3983a48
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Sep 20 11:33:11 2013 +0200

    blockdev: blockdev_init() error conversion
    
    This gives us meaningful error messages for the blockdev-add QMP
    command.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 1f14514..4f76e28 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -272,7 +272,7 @@ static void bdrv_put_ref_bh_schedule(BlockDriverState *bs)
     qemu_bh_schedule(s->bh);
 }
 
-static int parse_block_error_action(const char *buf, bool is_read)
+static int parse_block_error_action(const char *buf, bool is_read, Error **errp)
 {
     if (!strcmp(buf, "ignore")) {
         return BLOCKDEV_ON_ERROR_IGNORE;
@@ -283,8 +283,8 @@ static int parse_block_error_action(const char *buf, bool is_read)
     } else if (!strcmp(buf, "report")) {
         return BLOCKDEV_ON_ERROR_REPORT;
     } else {
-        error_report("'%s' invalid %s error action",
-                     buf, is_read ? "read" : "write");
+        error_setg(errp, "'%s' invalid %s error action",
+                   buf, is_read ? "read" : "write");
         return -1;
     }
 }
@@ -309,7 +309,8 @@ typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType;
 
 /* Takes the ownership of bs_opts */
 static DriveInfo *blockdev_init(QDict *bs_opts,
-                                BlockInterfaceType type)
+                                BlockInterfaceType type,
+                                Error **errp)
 {
     const char *buf;
     const char *file = NULL;
@@ -333,15 +334,13 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
     id = qdict_get_try_str(bs_opts, "id");
     opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error);
     if (error_is_set(&error)) {
-        qerror_report_err(error);
-        error_free(error);
+        error_propagate(errp, error);
         return NULL;
     }
 
     qemu_opts_absorb_qdict(opts, bs_opts, &error);
     if (error_is_set(&error)) {
-        qerror_report_err(error);
-        error_free(error);
+        error_propagate(errp, error);
         return NULL;
     }
 
@@ -361,7 +360,7 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
 
     if ((buf = qemu_opt_get(opts, "discard")) != NULL) {
         if (bdrv_parse_discard_flags(buf, &bdrv_flags) != 0) {
-            error_report("invalid discard option");
+            error_setg(errp, "invalid discard option");
             return NULL;
         }
     }
@@ -383,7 +382,7 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
         } else if (!strcmp(buf, "threads")) {
             /* this is the default */
         } else {
-           error_report("invalid aio option");
+           error_setg(errp, "invalid aio option");
            return NULL;
         }
     }
@@ -399,7 +398,7 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
 
         drv = bdrv_find_format(buf);
         if (!drv) {
-            error_report("'%s' invalid format", buf);
+            error_setg(errp, "'%s' invalid format", buf);
             return NULL;
         }
     }
@@ -435,20 +434,20 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
     cfg.op_size = qemu_opt_get_number(opts, "throttling.iops-size", 0);
 
     if (!check_throttle_config(&cfg, &error)) {
-        error_report("%s", error_get_pretty(error));
-        error_free(error);
+        error_propagate(errp, error);
         return NULL;
     }
 
     on_write_error = BLOCKDEV_ON_ERROR_ENOSPC;
     if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
         if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
-            error_report("werror is not supported by this bus type");
+            error_setg(errp, "werror is not supported by this bus type");
             return NULL;
         }
 
-        on_write_error = parse_block_error_action(buf, 0);
-        if (on_write_error < 0) {
+        on_write_error = parse_block_error_action(buf, 0, &error);
+        if (error_is_set(&error)) {
+            error_propagate(errp, error);
             return NULL;
         }
     }
@@ -460,8 +459,9 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
             return NULL;
         }
 
-        on_read_error = parse_block_error_action(buf, 1);
-        if (on_read_error < 0) {
+        on_read_error = parse_block_error_action(buf, 1, &error);
+        if (error_is_set(&error)) {
+            error_propagate(errp, error);
             return NULL;
         }
     }
@@ -514,8 +514,9 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
     ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, drv, &error);
 
     if (ret < 0) {
-        error_report("could not open disk image %s: %s",
-                     file ?: dinfo->id, error_get_pretty(error));
+        error_setg(errp, "could not open disk image %s: %s",
+                   file ?: dinfo->id, error_get_pretty(error));
+        error_free(error);
         goto err;
     }
 
@@ -862,9 +863,15 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     }
 
     /* Actual block device init: Functionality shared with blockdev-add */
-    dinfo = blockdev_init(bs_opts, type);
+    dinfo = blockdev_init(bs_opts, type, &local_err);
     if (dinfo == NULL) {
+        if (error_is_set(&local_err)) {
+            qerror_report_err(local_err);
+            error_free(local_err);
+        }
         goto fail;
+    } else {
+        assert(!error_is_set(&local_err));
     }
 
     /* Set legacy DriveInfo fields */
@@ -2155,7 +2162,6 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
     QmpOutputVisitor *ov = qmp_output_visitor_new();
     QObject *obj;
     QDict *qdict;
-    DriveInfo *dinfo;
     Error *local_err = NULL;
 
     /* Require an ID in the top level */
@@ -2189,9 +2195,9 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
 
     qdict_flatten(qdict);
 
-    dinfo = blockdev_init(qdict, IF_NONE);
-    if (!dinfo) {
-        error_setg(errp, "Could not open image");
+    blockdev_init(qdict, IF_NONE, &local_err);
+    if (error_is_set(&local_err)) {
+        error_propagate(errp, local_err);
         goto fail;
     }
 
commit 0ebd24e0a203cf2852c310b59fbe050190dc6c8c
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Sep 19 15:12:18 2013 +0200

    blockdev: Don't disable COR automatically with blockdev-add
    
    If a read-only device is configured with copy-on-read=on, the old code
    only prints a warning and automatically disables copy on read. Make it
    a real error for blockdev-add.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/block.c b/block.c
index 84c0eac..fd05a80 100644
--- a/block.c
+++ b/block.c
@@ -778,8 +778,13 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
     }
 
     assert(bs->copy_on_read == 0); /* bdrv_new() and bdrv_close() make it so */
-    if (!bs->read_only && (flags & BDRV_O_COPY_ON_READ)) {
-        bdrv_enable_copy_on_read(bs);
+    if (flags & BDRV_O_COPY_ON_READ) {
+        if (!bs->read_only) {
+            bdrv_enable_copy_on_read(bs);
+        } else {
+            error_setg(errp, "Can't use copy-on-read on read-only device");
+            return -EINVAL;
+        }
     }
 
     if (filename != NULL) {
diff --git a/blockdev.c b/blockdev.c
index e1ad319..1f14514 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -510,10 +510,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
 
     bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
 
-    if (ro && copy_on_read) {
-        error_report("warning: disabling copy_on_read on read-only drive");
-    }
-
     QINCREF(bs_opts);
     ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, drv, &error);
 
@@ -601,6 +597,18 @@ QemuOptsList qemu_legacy_drive_opts = {
             .type = QEMU_OPT_STRING,
             .help = "pci address (virtio only)",
         },
+
+        /* Options that are passed on, but have special semantics with -drive */
+        {
+            .name = "read-only",
+            .type = QEMU_OPT_BOOL,
+            .help = "open drive file as read-only",
+        },{
+            .name = "copy-on-read",
+            .type = QEMU_OPT_BOOL,
+            .help = "copy read data from backing file into image file",
+        },
+
         { /* end of list */ }
     },
 };
@@ -616,6 +624,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     int cyls, heads, secs, translation;
     int max_devs, bus_id, unit_id, index;
     const char *devaddr;
+    bool read_only, copy_on_read;
     Error *local_err = NULL;
 
     /* Change legacy command line options into QMP ones */
@@ -698,6 +707,20 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
         }
     }
 
+    /* copy-on-read is disabled with a warning for read-only devices */
+    read_only = qemu_opt_get_bool(legacy_opts, "read-only", false);
+    copy_on_read = qemu_opt_get_bool(legacy_opts, "copy-on-read", false);
+
+    if (read_only && copy_on_read) {
+        error_report("warning: disabling copy-on-read on read-only drive");
+        copy_on_read = false;
+    }
+
+    qdict_put(bs_opts, "read-only",
+              qstring_from_str(read_only ? "on" : "off"));
+    qdict_put(bs_opts, "copy-on-read",
+              qstring_from_str(copy_on_read ? "on" :"off"));
+
     /* Controller type */
     value = qemu_opt_get(legacy_opts, "if");
     if (value) {
commit e34ef046412431acf5b4e30762390b4048187bb8
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Sep 19 14:24:10 2013 +0200

    blockdev: Remove 'media' parameter from blockdev_init()
    
    The remaining users shouldn't be there with blockdev-add and are easy to
    move to drive_init().
    
    Bonus bug fix: As a side effect, CD-ROM drives can now use block drivers
    on the read-only whitelist without explicitly specifying read-only=on,
    even if a format is explicitly specified.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 401ee25..e1ad319 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -309,8 +309,7 @@ typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType;
 
 /* Takes the ownership of bs_opts */
 static DriveInfo *blockdev_init(QDict *bs_opts,
-                                BlockInterfaceType type,
-                                DriveMediaType media)
+                                BlockInterfaceType type)
 {
     const char *buf;
     const char *file = NULL;
@@ -488,22 +487,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
         bdrv_set_io_limits(dinfo->bdrv, &cfg);
     }
 
-    switch(type) {
-    case IF_IDE:
-    case IF_SCSI:
-    case IF_XEN:
-    case IF_NONE:
-        dinfo->media_cd = media == MEDIA_CDROM;
-        break;
-    case IF_SD:
-    case IF_FLOPPY:
-    case IF_PFLASH:
-    case IF_MTD:
-    case IF_VIRTIO:
-        break;
-    default:
-        abort();
-    }
     if (!file || !*file) {
         if (has_driver_specific_opts) {
             file = NULL;
@@ -525,11 +508,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
         bdrv_flags |= BDRV_O_INCOMING;
     }
 
-    if (media == MEDIA_CDROM) {
-        /* CDROM is fine for any interface, don't check.  */
-        ro = 1;
-    }
-
     bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
 
     if (ro && copy_on_read) {
@@ -713,6 +691,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
             media = MEDIA_DISK;
         } else if (!strcmp(value, "cdrom")) {
             media = MEDIA_CDROM;
+            qdict_put(bs_opts, "read-only", qstring_from_str("on"));
         } else {
             error_report("'%s' invalid media", value);
             goto fail;
@@ -860,7 +839,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     }
 
     /* Actual block device init: Functionality shared with blockdev-add */
-    dinfo = blockdev_init(bs_opts, type, media);
+    dinfo = blockdev_init(bs_opts, type);
     if (dinfo == NULL) {
         goto fail;
     }
@@ -878,6 +857,17 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     dinfo->unit = unit_id;
     dinfo->devaddr = devaddr;
 
+    switch(type) {
+    case IF_IDE:
+    case IF_SCSI:
+    case IF_XEN:
+    case IF_NONE:
+        dinfo->media_cd = media == MEDIA_CDROM;
+        break;
+    default:
+        break;
+    }
+
 fail:
     qemu_opts_del(legacy_opts);
     return dinfo;
@@ -2176,7 +2166,7 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
 
     qdict_flatten(qdict);
 
-    dinfo = blockdev_init(qdict, IF_NONE, MEDIA_DISK);
+    dinfo = blockdev_init(qdict, IF_NONE);
     if (!dinfo) {
         error_setg(errp, "Could not open image");
         goto fail;
commit a9b43397a9782d028f45b63fb4affee164f85948
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Sep 18 16:47:41 2013 +0200

    qemu-iotests: Check autodel behaviour for device_del
    
    Block devices creates with -drive and drive_add should automatically
    disappear if the guest device is unplugged. blockdev-add ones shouldn't.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067
new file mode 100755
index 0000000..79dc38b
--- /dev/null
+++ b/tests/qemu-iotests/067
@@ -0,0 +1,133 @@
+#!/bin/bash
+#
+# Test automatic deletion of BDSes created by -drive/drive_add
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=kwolf at redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt qcow2
+_supported_proto file
+_supported_os Linux
+
+function do_run_qemu()
+{
+    echo Testing: "$@"
+    $QEMU -nographic -qmp stdio -serial none "$@"
+    echo
+}
+
+function run_qemu()
+{
+    do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp
+}
+
+size=128M
+
+_make_test_img $size
+
+echo
+echo === -drive/-device and device_del ===
+echo
+
+run_qemu -drive file=$TEST_IMG,format=$IMGFMT,if=none,id=disk -device virtio-blk-pci,drive=disk,id=virtio0 <<EOF
+{ "execute": "qmp_capabilities" }
+{ "execute": "query-block" }
+{ "execute": "device_del", "arguments": { "id": "virtio0" } }
+{ "execute": "system_reset" }
+{ "execute": "query-block" }
+{ "execute": "quit" }
+EOF
+
+echo
+echo === -drive/device_add and device_del ===
+echo
+
+run_qemu -drive file=$TEST_IMG,format=$IMGFMT,if=none,id=disk <<EOF
+{ "execute": "qmp_capabilities" }
+{ "execute": "query-block" }
+{ "execute": "device_add",
+   "arguments": { "driver": "virtio-blk-pci", "drive": "disk",
+                  "id": "virtio0" } }
+{ "execute": "device_del", "arguments": { "id": "virtio0" } }
+{ "execute": "system_reset" }
+{ "execute": "query-block" }
+{ "execute": "quit" }
+EOF
+
+echo
+echo === drive_add/device_add and device_del ===
+echo
+
+run_qemu <<EOF
+{ "execute": "qmp_capabilities" }
+{ "execute": "human-monitor-command",
+  "arguments": { "command-line": "drive_add 0 file=$TEST_IMG,format=$IMGFMT,if=none,id=disk" } }
+{ "execute": "query-block" }
+{ "execute": "device_add",
+   "arguments": { "driver": "virtio-blk-pci", "drive": "disk",
+                  "id": "virtio0" } }
+{ "execute": "device_del", "arguments": { "id": "virtio0" } }
+{ "execute": "system_reset" }
+{ "execute": "query-block" }
+{ "execute": "quit" }
+EOF
+
+echo
+echo === blockdev_add/device_add and device_del ===
+echo
+
+run_qemu <<EOF
+{ "execute": "qmp_capabilities" }
+{ "execute": "blockdev-add",
+  "arguments": {
+      "options": {
+        "driver": "$IMGFMT",
+        "id": "disk",
+        "file": {
+            "driver": "file",
+            "filename": "$TEST_IMG"
+        }
+      }
+    }
+  }
+{ "execute": "query-block" }
+{ "execute": "device_add",
+   "arguments": { "driver": "virtio-blk-pci", "drive": "disk",
+                  "id": "virtio0" } }
+{ "execute": "device_del", "arguments": { "id": "virtio0" } }
+{ "execute": "system_reset" }
+{ "execute": "query-block" }
+{ "execute": "quit" }
+EOF
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out
new file mode 100644
index 0000000..4bb9ff9
--- /dev/null
+++ b/tests/qemu-iotests/067.out
@@ -0,0 +1,80 @@
+QA output created by 067
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 
+
+=== -drive/-device and device_del ===
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virtio-blk-pci,drive=disk,id=virtio0
+QMP_VERSION
+{"return": {}}
+{"return": [{"io-status": "ok", "device": "disk", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": 139264, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "type": "unknown"}, {"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]}
+{"return": {}}
+{"return": {}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"path": "/machine/peripheral/virtio0/virtio-backend"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"device": "virtio0", "path": "/machine/peripheral/virtio0"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "RESET"}
+{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]}
+{"return": {}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
+
+
+=== -drive/device_add and device_del ===
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
+QMP_VERSION
+{"return": {}}
+{"return": [{"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": 139264, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}, {"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]}
+{"return": {}}
+{"return": {}}
+{"return": {}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"path": "/machine/peripheral/virtio0/virtio-backend"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"device": "virtio0", "path": "/machine/peripheral/virtio0"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "RESET"}
+{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]}
+{"return": {}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
+
+
+=== drive_add/device_add and device_del ===
+
+Testing:
+QMP_VERSION
+{"return": {}}
+{"return": "OK\r\n"}
+{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": 139264, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
+{"return": {}}
+{"return": {}}
+{"return": {}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"path": "/machine/peripheral/virtio0/virtio-backend"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"device": "virtio0", "path": "/machine/peripheral/virtio0"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "RESET"}
+{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]}
+{"return": {}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
+
+
+=== blockdev_add/device_add and device_del ===
+
+Testing:
+QMP_VERSION
+{"return": {}}
+{"return": {}}
+{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": 139264, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
+{"return": {}}
+{"return": {}}
+{"return": {}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"path": "/machine/peripheral/virtio0/virtio-backend"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"device": "virtio0", "path": "/machine/peripheral/virtio0"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "RESET"}
+{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"io-status": "ok", "device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": 139264, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
+{"return": {}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
+
+*** done
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
index 5dfda63..8e7b1a4 100644
--- a/tests/qemu-iotests/common.filter
+++ b/tests/qemu-iotests/common.filter
@@ -159,5 +159,13 @@ _filter_qemu()
         -e 's#^QEMU [0-9]\+\.[0-9]\+\.[0-9]\+ monitor#QEMU X.Y.Z monitor#'
 }
 
+# replace problematic QMP output like timestamps
+_filter_qmp()
+{
+    _filter_win32 | \
+    sed -e 's#\("\(micro\)\?seconds": \)[0-9]\+#\1 TIMESTAMP#g' \
+        -e 's#^{"QMP":.*}$#QMP_VERSION#'
+}
+
 # make sure this script returns success
 /bin/true
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 514bd87..13c5500 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -72,3 +72,4 @@
 064 rw auto
 065 rw auto
 066 rw auto
+067 rw auto
commit 4f8a066b5fc254eeaabbbde56ba4f5b29cc68fdf
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Sep 13 15:51:47 2013 +0200

    blockdev: Remove IF_* check for read-only blockdev_init
    
    IF_NONE allows read-only, which makes forbidding it in this place
    for other types pretty much pointless.
    
    Instead, make sure that all devices for which the check would have
    errored out check in their init function that they don't get a read-only
    BlockDriverState. This catches even cases where IF_NONE and -device is
    used.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index b11155c..401ee25 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -528,12 +528,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
     if (media == MEDIA_CDROM) {
         /* CDROM is fine for any interface, don't check.  */
         ro = 1;
-    } else if (ro == 1) {
-        if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY &&
-            type != IF_NONE && type != IF_PFLASH) {
-            error_report("read-only not supported by this bus type");
-            goto err;
-        }
     }
 
     bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 8c3b7f0..02a1544 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -624,6 +624,11 @@ static int m25p80_init(SSISlave *ss)
     if (dinfo && dinfo->bdrv) {
         DB_PRINT_L(0, "Binding to IF_MTD drive\n");
         s->bdrv = dinfo->bdrv;
+        if (bdrv_is_read_only(s->bdrv)) {
+            fprintf(stderr, "Can't use a read-only drive");
+            return 1;
+        }
+
         /* FIXME: Move to late init */
         if (bdrv_read(s->bdrv, 0, s->storage, DIV_ROUND_UP(s->size,
                                                     BDRV_SECTOR_SIZE))) {
diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
index 8742294..098f6c6 100644
--- a/hw/block/xen_disk.c
+++ b/hw/block/xen_disk.c
@@ -830,6 +830,11 @@ static int blk_connect(struct XenDevice *xendev)
         /* setup via qemu cmdline -> already setup for us */
         xen_be_printf(&blkdev->xendev, 2, "get configured bdrv (cmdline setup)\n");
         blkdev->bs = blkdev->dinfo->bdrv;
+        if (bdrv_is_read_only(blkdev->bs) && !readonly) {
+            xen_be_printf(&blkdev->xendev, 0, "Unexpected read-only drive");
+            blkdev->bs = NULL;
+            return -1;
+        }
         /* blkdev->bs is not create by us, we get a reference
          * so we can bdrv_unref() unconditionally */
         bdrv_ref(blkdev->bs);
diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
index 42613b3..d1168c9 100644
--- a/hw/sd/milkymist-memcard.c
+++ b/hw/sd/milkymist-memcard.c
@@ -255,6 +255,10 @@ static int milkymist_memcard_init(SysBusDevice *dev)
 
     dinfo = drive_get_next(IF_SD);
     s->card = sd_init(dinfo ? dinfo->bdrv : NULL, false);
+    if (s->card == NULL) {
+        return -1;
+    }
+
     s->enabled = dinfo ? bdrv_is_inserted(dinfo->bdrv) : 0;
 
     memory_region_init_io(&s->regs_region, OBJECT(s), &memcard_mmio_ops, s,
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
index bf5d1fb..937a478 100644
--- a/hw/sd/omap_mmc.c
+++ b/hw/sd/omap_mmc.c
@@ -593,6 +593,9 @@ struct omap_mmc_s *omap_mmc_init(hwaddr base,
 
     /* Instantiate the storage */
     s->card = sd_init(bd, false);
+    if (s->card == NULL) {
+        exit(1);
+    }
 
     return s;
 }
@@ -618,6 +621,9 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
 
     /* Instantiate the storage */
     s->card = sd_init(bd, false);
+    if (s->card == NULL) {
+        exit(1);
+    }
 
     s->cdet = qemu_allocate_irqs(omap_mmc_cover_cb, s, 1)[0];
     sd_set_cb(s->card, NULL, s->cdet);
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index 03875bf..c35896d 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -491,6 +491,10 @@ static int pl181_init(SysBusDevice *sbd)
     qdev_init_gpio_out(dev, s->cardstatus, 2);
     dinfo = drive_get_next(IF_SD);
     s->card = sd_init(dinfo ? dinfo->bdrv : NULL, false);
+    if (s->card == NULL) {
+        return -1;
+    }
+
     return 0;
 }
 
diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c
index 90c955f..b9d8b1a 100644
--- a/hw/sd/pxa2xx_mmci.c
+++ b/hw/sd/pxa2xx_mmci.c
@@ -539,6 +539,9 @@ PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
 
     /* Instantiate the actual storage */
     s->card = sd_init(bd, false);
+    if (s->card == NULL) {
+        exit(1);
+    }
 
     register_savevm(NULL, "pxa2xx_mmci", 0, 0,
                     pxa2xx_mmci_save, pxa2xx_mmci_load, s);
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 346d86f..7380f06 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -494,6 +494,11 @@ SDState *sd_init(BlockDriverState *bs, bool is_spi)
 {
     SDState *sd;
 
+    if (bdrv_is_read_only(bs)) {
+        fprintf(stderr, "sd_init: Cannot use read-only drive\n");
+        return NULL;
+    }
+
     sd = (SDState *) g_malloc0(sizeof(SDState));
     sd->buf = qemu_blockalign(bs, 512);
     sd->spi = is_spi;
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 1483e19..0906a1d 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1166,6 +1166,9 @@ static void sdhci_initfn(Object *obj)
 
     di = drive_get_next(IF_SD);
     s->card = sd_init(di ? di->bdrv : NULL, false);
+    if (s->card == NULL) {
+        exit(1);
+    }
     s->eject_cb = qemu_allocate_irqs(sdhci_insert_eject_cb, s, 1)[0];
     s->ro_cb = qemu_allocate_irqs(sdhci_card_readonly_cb, s, 1)[0];
     sd_set_cb(s->card, s->ro_cb, s->eject_cb);
diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index d47e237..1bb56c4 100644
--- a/hw/sd/ssi-sd.c
+++ b/hw/sd/ssi-sd.c
@@ -246,6 +246,9 @@ static int ssi_sd_init(SSISlave *dev)
     s->mode = SSI_SD_CMD;
     dinfo = drive_get_next(IF_SD);
     s->sd = sd_init(dinfo ? dinfo->bdrv : NULL, true);
+    if (s->sd == NULL) {
+        return -1;
+    }
     register_savevm(&dev->qdev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s);
     return 0;
 }
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index e58776a..2839e32 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -139,7 +139,10 @@ QEMU X.Y.Z monitor - type 'help' for more information
 (qemu) qququiquit
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on
-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on: read-only not supported by this bus type
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) QEMU_PROG: Can't use a read-only drive
+QEMU_PROG: Device initialization failed.
+QEMU_PROG: Initialization of device ide-hd failed
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on
 QEMU X.Y.Z monitor - type 'help' for more information
commit 394c7d4d6bd06386308e2fef0cf1c613a10e0d23
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Sep 13 14:09:17 2013 +0200

    blockdev: Move virtio-blk device creation to drive_init
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index b543f6d..b11155c 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -318,7 +318,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
     int ro = 0;
     int bdrv_flags = 0;
     int on_read_error, on_write_error;
-    const char *devaddr;
     DriveInfo *dinfo;
     ThrottleConfig cfg;
     int snapshot = 0;
@@ -468,20 +467,12 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
         }
     }
 
-    if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) {
-        if (type != IF_VIRTIO) {
-            error_report("addr is not supported by this bus type");
-            return NULL;
-        }
-    }
-
     /* init */
     dinfo = g_malloc0(sizeof(*dinfo));
     dinfo->id = g_strdup(qemu_opts_id(opts));
     dinfo->bdrv = bdrv_new(dinfo->id);
     dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
     dinfo->bdrv->read_only = ro;
-    dinfo->devaddr = devaddr;
     dinfo->type = type;
     dinfo->refcount = 1;
     if (serial != NULL) {
@@ -508,22 +499,8 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
     case IF_FLOPPY:
     case IF_PFLASH:
     case IF_MTD:
-        break;
     case IF_VIRTIO:
-    {
-        /* add virtio block device */
-        QemuOpts *devopts;
-        devopts = qemu_opts_create_nofail(qemu_find_opts("device"));
-        if (arch_type == QEMU_ARCH_S390X) {
-            qemu_opt_set(devopts, "driver", "virtio-blk-s390");
-        } else {
-            qemu_opt_set(devopts, "driver", "virtio-blk-pci");
-        }
-        qemu_opt_set(devopts, "drive", dinfo->id);
-        if (devaddr)
-            qemu_opt_set(devopts, "addr", devaddr);
         break;
-    }
     default:
         abort();
     }
@@ -647,6 +624,10 @@ QemuOptsList qemu_legacy_drive_opts = {
             .name = "boot",
             .type = QEMU_OPT_BOOL,
             .help = "(deprecated, ignored)",
+        },{
+            .name = "addr",
+            .type = QEMU_OPT_STRING,
+            .help = "pci address (virtio only)",
         },
         { /* end of list */ }
     },
@@ -662,6 +643,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     BlockInterfaceType type;
     int cyls, heads, secs, translation;
     int max_devs, bus_id, unit_id, index;
+    const char *devaddr;
     Error *local_err = NULL;
 
     /* Change legacy command line options into QMP ones */
@@ -862,6 +844,27 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
         g_free(new_id);
     }
 
+    /* Add virtio block device */
+    devaddr = qemu_opt_get(legacy_opts, "addr");
+    if (devaddr && type != IF_VIRTIO) {
+        error_report("addr is not supported by this bus type");
+        goto fail;
+    }
+
+    if (type == IF_VIRTIO) {
+        QemuOpts *devopts;
+        devopts = qemu_opts_create_nofail(qemu_find_opts("device"));
+        if (arch_type == QEMU_ARCH_S390X) {
+            qemu_opt_set(devopts, "driver", "virtio-blk-s390");
+        } else {
+            qemu_opt_set(devopts, "driver", "virtio-blk-pci");
+        }
+        qemu_opt_set(devopts, "drive", qdict_get_str(bs_opts, "id"));
+        if (devaddr) {
+            qemu_opt_set(devopts, "addr", devaddr);
+        }
+    }
+
     /* Actual block device init: Functionality shared with blockdev-add */
     dinfo = blockdev_init(bs_opts, type, media);
     if (dinfo == NULL) {
@@ -879,6 +882,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
 
     dinfo->bus = bus_id;
     dinfo->unit = unit_id;
+    dinfo->devaddr = devaddr;
 
 fail:
     qemu_opts_del(legacy_opts);
@@ -2259,10 +2263,6 @@ QemuOptsList qemu_common_drive_opts = {
             .type = QEMU_OPT_STRING,
             .help = "write error action",
         },{
-            .name = "addr",
-            .type = QEMU_OPT_STRING,
-            .help = "pci address (virtio only)",
-        },{
             .name = "read-only",
             .type = QEMU_OPT_BOOL,
             .help = "open drive file as read-only",
commit 87a899c5090c7864fc7dcff3ea0ac34153ea621b
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Sep 10 15:48:13 2013 +0200

    blockdev: Move bus/unit/index processing to drive_init
    
    This requires moving the automatic ID generation at the same time, so
    let's do that as well.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index d633f6e..b543f6d 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -315,10 +315,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
     const char *buf;
     const char *file = NULL;
     const char *serial;
-    const char *mediastr = "";
-    int bus_id, unit_id;
-    int max_devs;
-    int index;
     int ro = 0;
     int bdrv_flags = 0;
     int on_read_error, on_write_error;
@@ -358,10 +354,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
     has_driver_specific_opts = !!qdict_size(bs_opts);
 
     /* extract parameters */
-    bus_id  = qemu_opt_get_number(opts, "bus", 0);
-    unit_id = qemu_opt_get_number(opts, "unit", -1);
-    index   = qemu_opt_get_number(opts, "index", -1);
-
     snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
     ro = qemu_opt_get_bool(opts, "read-only", 0);
     copy_on_read = qemu_opt_get_bool(opts, "copy-on-read", false);
@@ -369,8 +361,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
     file = qemu_opt_get(opts, "file");
     serial = qemu_opt_get(opts, "serial");
 
-    max_devs = if_max_devs[type];
-
     if ((buf = qemu_opt_get(opts, "discard")) != NULL) {
         if (bdrv_parse_discard_flags(buf, &bdrv_flags) != 0) {
             error_report("invalid discard option");
@@ -485,66 +475,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
         }
     }
 
-    /* compute bus and unit according index */
-
-    if (index != -1) {
-        if (bus_id != 0 || unit_id != -1) {
-            error_report("index cannot be used with bus and unit");
-            return NULL;
-        }
-        bus_id = drive_index_to_bus_id(type, index);
-        unit_id = drive_index_to_unit_id(type, index);
-    }
-
-    /* if user doesn't specify a unit_id,
-     * try to find the first free
-     */
-
-    if (unit_id == -1) {
-       unit_id = 0;
-       while (drive_get(type, bus_id, unit_id) != NULL) {
-           unit_id++;
-           if (max_devs && unit_id >= max_devs) {
-               unit_id -= max_devs;
-               bus_id++;
-           }
-       }
-    }
-
-    /* check unit id */
-
-    if (max_devs && unit_id >= max_devs) {
-        error_report("unit %d too big (max is %d)",
-                     unit_id, max_devs - 1);
-        return NULL;
-    }
-
-    /*
-     * catch multiple definitions
-     */
-
-    if (drive_get(type, bus_id, unit_id) != NULL) {
-        error_report("drive with bus=%d, unit=%d (index=%d) exists",
-                     bus_id, unit_id, index);
-        return NULL;
-    }
-
-    /* no id supplied -> create one */
-    if (qemu_opts_id(opts) == NULL) {
-        char *new_id;
-        if (type == IF_IDE || type == IF_SCSI) {
-            mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
-        }
-        if (max_devs) {
-            new_id = g_strdup_printf("%s%i%s%i", if_name[type], bus_id,
-                                     mediastr, unit_id);
-        } else {
-            new_id = g_strdup_printf("%s%s%i", if_name[type],
-                                     mediastr, unit_id);
-        }
-        qemu_opts_set_id(opts, new_id);
-    }
-
     /* init */
     dinfo = g_malloc0(sizeof(*dinfo));
     dinfo->id = g_strdup(qemu_opts_id(opts));
@@ -553,8 +483,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
     dinfo->bdrv->read_only = ro;
     dinfo->devaddr = devaddr;
     dinfo->type = type;
-    dinfo->bus = bus_id;
-    dinfo->unit = unit_id;
     dinfo->refcount = 1;
     if (serial != NULL) {
         dinfo->serial = g_strdup(serial);
@@ -680,6 +608,18 @@ QemuOptsList qemu_legacy_drive_opts = {
     .head = QTAILQ_HEAD_INITIALIZER(qemu_legacy_drive_opts.head),
     .desc = {
         {
+            .name = "bus",
+            .type = QEMU_OPT_NUMBER,
+            .help = "bus number",
+        },{
+            .name = "unit",
+            .type = QEMU_OPT_NUMBER,
+            .help = "unit number (i.e. lun for scsi)",
+        },{
+            .name = "index",
+            .type = QEMU_OPT_NUMBER,
+            .help = "index number",
+        },{
             .name = "media",
             .type = QEMU_OPT_STRING,
             .help = "media type (disk, cdrom)",
@@ -721,6 +661,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     DriveMediaType media = MEDIA_DISK;
     BlockInterfaceType type;
     int cyls, heads, secs, translation;
+    int max_devs, bus_id, unit_id, index;
     Error *local_err = NULL;
 
     /* Change legacy command line options into QMP ones */
@@ -864,6 +805,63 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
         }
     }
 
+    /* Device address specified by bus/unit or index.
+     * If none was specified, try to find the first free one. */
+    bus_id  = qemu_opt_get_number(legacy_opts, "bus", 0);
+    unit_id = qemu_opt_get_number(legacy_opts, "unit", -1);
+    index   = qemu_opt_get_number(legacy_opts, "index", -1);
+
+    max_devs = if_max_devs[type];
+
+    if (index != -1) {
+        if (bus_id != 0 || unit_id != -1) {
+            error_report("index cannot be used with bus and unit");
+            goto fail;
+        }
+        bus_id = drive_index_to_bus_id(type, index);
+        unit_id = drive_index_to_unit_id(type, index);
+    }
+
+    if (unit_id == -1) {
+       unit_id = 0;
+       while (drive_get(type, bus_id, unit_id) != NULL) {
+           unit_id++;
+           if (max_devs && unit_id >= max_devs) {
+               unit_id -= max_devs;
+               bus_id++;
+           }
+       }
+    }
+
+    if (max_devs && unit_id >= max_devs) {
+        error_report("unit %d too big (max is %d)", unit_id, max_devs - 1);
+        goto fail;
+    }
+
+    if (drive_get(type, bus_id, unit_id) != NULL) {
+        error_report("drive with bus=%d, unit=%d (index=%d) exists",
+                     bus_id, unit_id, index);
+        goto fail;
+    }
+
+    /* no id supplied -> create one */
+    if (qemu_opts_id(all_opts) == NULL) {
+        char *new_id;
+        const char *mediastr = "";
+        if (type == IF_IDE || type == IF_SCSI) {
+            mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
+        }
+        if (max_devs) {
+            new_id = g_strdup_printf("%s%i%s%i", if_name[type], bus_id,
+                                     mediastr, unit_id);
+        } else {
+            new_id = g_strdup_printf("%s%s%i", if_name[type],
+                                     mediastr, unit_id);
+        }
+        qdict_put(bs_opts, "id", qstring_from_str(new_id));
+        g_free(new_id);
+    }
+
     /* Actual block device init: Functionality shared with blockdev-add */
     dinfo = blockdev_init(bs_opts, type, media);
     if (dinfo == NULL) {
@@ -879,6 +877,9 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     dinfo->secs = secs;
     dinfo->trans = translation;
 
+    dinfo->bus = bus_id;
+    dinfo->unit = unit_id;
+
 fail:
     qemu_opts_del(legacy_opts);
     return dinfo;
@@ -2214,18 +2215,6 @@ QemuOptsList qemu_common_drive_opts = {
     .head = QTAILQ_HEAD_INITIALIZER(qemu_common_drive_opts.head),
     .desc = {
         {
-            .name = "bus",
-            .type = QEMU_OPT_NUMBER,
-            .help = "bus number",
-        },{
-            .name = "unit",
-            .type = QEMU_OPT_NUMBER,
-            .help = "unit number (i.e. lun for scsi)",
-        },{
-            .name = "index",
-            .type = QEMU_OPT_NUMBER,
-            .help = "index number",
-        },{
             .name = "snapshot",
             .type = QEMU_OPT_BOOL,
             .help = "enable/disable snapshot mode",
commit 26929298023b0592dc6ac8bc15163b5a24341670
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Sep 9 17:01:03 2013 +0200

    blockdev: Move parsing of 'boot' option to drive_init
    
    It's already ignored and only prints a deprecation message. No use in
    making it available in new interfaces.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 8fa9510..d633f6e 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -452,12 +452,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
         return NULL;
     }
 
-    if (qemu_opt_get(opts, "boot") != NULL) {
-        fprintf(stderr, "qemu-kvm: boot=on|off is deprecated and will be "
-                "ignored. Future versions will reject this parameter. Please "
-                "update your scripts.\n");
-    }
-
     on_write_error = BLOCKDEV_ON_ERROR_ENOSPC;
     if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
         if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
@@ -709,6 +703,10 @@ QemuOptsList qemu_legacy_drive_opts = {
             .name = "trans",
             .type = QEMU_OPT_STRING,
             .help = "chs translation (auto, lba, none)",
+        },{
+            .name = "boot",
+            .type = QEMU_OPT_BOOL,
+            .help = "(deprecated, ignored)",
         },
         { /* end of list */ }
     },
@@ -784,6 +782,13 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
         goto fail;
     }
 
+    /* Deprecated option boot=[on|off] */
+    if (qemu_opt_get(legacy_opts, "boot") != NULL) {
+        fprintf(stderr, "qemu-kvm: boot=on|off is deprecated and will be "
+                "ignored. Future versions will reject this parameter. Please "
+                "update your scripts.\n");
+    }
+
     /* Media type */
     value = qemu_opt_get(legacy_opts, "media");
     if (value) {
@@ -2328,10 +2333,6 @@ QemuOptsList qemu_common_drive_opts = {
             .name = "copy-on-read",
             .type = QEMU_OPT_BOOL,
             .help = "copy read data from backing file into image file",
-        },{
-            .name = "boot",
-            .type = QEMU_OPT_BOOL,
-            .help = "(deprecated, ignored)",
         },
         { /* end of list */ }
     },
commit b41a7338cfdeeb913ee4846d79a3f7e221350aed
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Sep 9 16:49:49 2013 +0200

    blockdev: Moving parsing of geometry options to drive_init
    
    This moves all of the geometry options (cyls/heads/secs/trans) to
    drive_init so that they can only be accessed using legacy functions, but
    never with anything blockdev-add related.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index e25f0b8..8fa9510 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -317,7 +317,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
     const char *serial;
     const char *mediastr = "";
     int bus_id, unit_id;
-    int cyls, heads, secs, translation;
     int max_devs;
     int index;
     int ro = 0;
@@ -335,8 +334,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
     bool has_driver_specific_opts;
     BlockDriver *drv = NULL;
 
-    translation = BIOS_ATA_TRANSLATION_AUTO;
-
     /* Check common options by copying from bs_opts to opts, all other options
      * stay in bs_opts for processing by bdrv_open(). */
     id = qdict_get_try_str(bs_opts, "id");
@@ -365,10 +362,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
     unit_id = qemu_opt_get_number(opts, "unit", -1);
     index   = qemu_opt_get_number(opts, "index", -1);
 
-    cyls  = qemu_opt_get_number(opts, "cyls", 0);
-    heads = qemu_opt_get_number(opts, "heads", 0);
-    secs  = qemu_opt_get_number(opts, "secs", 0);
-
     snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
     ro = qemu_opt_get_bool(opts, "read-only", 0);
     copy_on_read = qemu_opt_get_bool(opts, "copy-on-read", false);
@@ -378,46 +371,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
 
     max_devs = if_max_devs[type];
 
-    if (cyls || heads || secs) {
-        if (cyls < 1) {
-            error_report("invalid physical cyls number");
-	    return NULL;
-	}
-        if (heads < 1) {
-            error_report("invalid physical heads number");
-	    return NULL;
-	}
-        if (secs < 1) {
-            error_report("invalid physical secs number");
-	    return NULL;
-	}
-    }
-
-    if ((buf = qemu_opt_get(opts, "trans")) != NULL) {
-        if (!cyls) {
-            error_report("'%s' trans must be used with cyls, heads and secs",
-                         buf);
-            return NULL;
-        }
-        if (!strcmp(buf, "none"))
-            translation = BIOS_ATA_TRANSLATION_NONE;
-        else if (!strcmp(buf, "lba"))
-            translation = BIOS_ATA_TRANSLATION_LBA;
-        else if (!strcmp(buf, "auto"))
-            translation = BIOS_ATA_TRANSLATION_AUTO;
-	else {
-            error_report("'%s' invalid translation type", buf);
-	    return NULL;
-	}
-    }
-
-    if (media == MEDIA_CDROM) {
-        if (cyls || secs || heads) {
-            error_report("CHS can't be set with media=cdrom");
-            return NULL;
-        }
-    }
-
     if ((buf = qemu_opt_get(opts, "discard")) != NULL) {
         if (bdrv_parse_discard_flags(buf, &bdrv_flags) != 0) {
             error_report("invalid discard option");
@@ -608,10 +561,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
     dinfo->type = type;
     dinfo->bus = bus_id;
     dinfo->unit = unit_id;
-    dinfo->cyls = cyls;
-    dinfo->heads = heads;
-    dinfo->secs = secs;
-    dinfo->trans = translation;
     dinfo->refcount = 1;
     if (serial != NULL) {
         dinfo->serial = g_strdup(serial);
@@ -744,6 +693,22 @@ QemuOptsList qemu_legacy_drive_opts = {
             .name = "if",
             .type = QEMU_OPT_STRING,
             .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
+        },{
+            .name = "cyls",
+            .type = QEMU_OPT_NUMBER,
+            .help = "number of cylinders (ide disk geometry)",
+        },{
+            .name = "heads",
+            .type = QEMU_OPT_NUMBER,
+            .help = "number of heads (ide disk geometry)",
+        },{
+            .name = "secs",
+            .type = QEMU_OPT_NUMBER,
+            .help = "number of sectors (ide disk geometry)",
+        },{
+            .name = "trans",
+            .type = QEMU_OPT_STRING,
+            .help = "chs translation (auto, lba, none)",
         },
         { /* end of list */ }
     },
@@ -757,6 +722,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     QemuOpts *legacy_opts;
     DriveMediaType media = MEDIA_DISK;
     BlockInterfaceType type;
+    int cyls, heads, secs, translation;
     Error *local_err = NULL;
 
     /* Change legacy command line options into QMP ones */
@@ -846,6 +812,53 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
         type = block_default_type;
     }
 
+    /* Geometry */
+    cyls  = qemu_opt_get_number(legacy_opts, "cyls", 0);
+    heads = qemu_opt_get_number(legacy_opts, "heads", 0);
+    secs  = qemu_opt_get_number(legacy_opts, "secs", 0);
+
+    if (cyls || heads || secs) {
+        if (cyls < 1) {
+            error_report("invalid physical cyls number");
+            goto fail;
+        }
+        if (heads < 1) {
+            error_report("invalid physical heads number");
+            goto fail;
+        }
+        if (secs < 1) {
+            error_report("invalid physical secs number");
+            goto fail;
+        }
+    }
+
+    translation = BIOS_ATA_TRANSLATION_AUTO;
+    value = qemu_opt_get(legacy_opts, "trans");
+    if (value != NULL) {
+        if (!cyls) {
+            error_report("'%s' trans must be used with cyls, heads and secs",
+                         value);
+            goto fail;
+        }
+        if (!strcmp(value, "none")) {
+            translation = BIOS_ATA_TRANSLATION_NONE;
+        } else if (!strcmp(value, "lba")) {
+            translation = BIOS_ATA_TRANSLATION_LBA;
+        } else if (!strcmp(value, "auto")) {
+            translation = BIOS_ATA_TRANSLATION_AUTO;
+        } else {
+            error_report("'%s' invalid translation type", value);
+            goto fail;
+        }
+    }
+
+    if (media == MEDIA_CDROM) {
+        if (cyls || secs || heads) {
+            error_report("CHS can't be set with media=cdrom");
+            goto fail;
+        }
+    }
+
     /* Actual block device init: Functionality shared with blockdev-add */
     dinfo = blockdev_init(bs_opts, type, media);
     if (dinfo == NULL) {
@@ -856,6 +869,11 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     dinfo->enable_auto_del = true;
     dinfo->opts = all_opts;
 
+    dinfo->cyls = cyls;
+    dinfo->heads = heads;
+    dinfo->secs = secs;
+    dinfo->trans = translation;
+
 fail:
     qemu_opts_del(legacy_opts);
     return dinfo;
@@ -2203,22 +2221,6 @@ QemuOptsList qemu_common_drive_opts = {
             .type = QEMU_OPT_NUMBER,
             .help = "index number",
         },{
-            .name = "cyls",
-            .type = QEMU_OPT_NUMBER,
-            .help = "number of cylinders (ide disk geometry)",
-        },{
-            .name = "heads",
-            .type = QEMU_OPT_NUMBER,
-            .help = "number of heads (ide disk geometry)",
-        },{
-            .name = "secs",
-            .type = QEMU_OPT_NUMBER,
-            .help = "number of sectors (ide disk geometry)",
-        },{
-            .name = "trans",
-            .type = QEMU_OPT_STRING,
-            .help = "chs translation (auto, lba. none)",
-        },{
             .name = "snapshot",
             .type = QEMU_OPT_BOOL,
             .help = "enable/disable snapshot mode",
commit 593d464bd43900c2a0c8800b76212f6a93e99a0d
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Aug 28 17:24:51 2013 +0200

    blockdev: Move parsing of 'if' option to drive_init
    
    It's always IF_NONE for blockdev-add.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Benoit Canet <benoit at irqsave.net>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 149ddc1..e25f0b8 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -309,14 +309,13 @@ typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType;
 
 /* Takes the ownership of bs_opts */
 static DriveInfo *blockdev_init(QDict *bs_opts,
-                                BlockInterfaceType block_default_type,
+                                BlockInterfaceType type,
                                 DriveMediaType media)
 {
     const char *buf;
     const char *file = NULL;
     const char *serial;
     const char *mediastr = "";
-    BlockInterfaceType type;
     int bus_id, unit_id;
     int cyls, heads, secs, translation;
     int max_devs;
@@ -377,17 +376,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
     file = qemu_opt_get(opts, "file");
     serial = qemu_opt_get(opts, "serial");
 
-    if ((buf = qemu_opt_get(opts, "if")) != NULL) {
-        for (type = 0; type < IF_COUNT && strcmp(buf, if_name[type]); type++)
-            ;
-        if (type == IF_COUNT) {
-            error_report("unsupported bus type '%s'", buf);
-            return NULL;
-	}
-    } else {
-        type = block_default_type;
-    }
-
     max_devs = if_max_devs[type];
 
     if (cyls || heads || secs) {
@@ -752,6 +740,10 @@ QemuOptsList qemu_legacy_drive_opts = {
             .name = "media",
             .type = QEMU_OPT_STRING,
             .help = "media type (disk, cdrom)",
+        },{
+            .name = "if",
+            .type = QEMU_OPT_STRING,
+            .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
         },
         { /* end of list */ }
     },
@@ -764,6 +756,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     QDict *bs_opts;
     QemuOpts *legacy_opts;
     DriveMediaType media = MEDIA_DISK;
+    BlockInterfaceType type;
     Error *local_err = NULL;
 
     /* Change legacy command line options into QMP ones */
@@ -838,8 +831,23 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
         }
     }
 
+    /* Controller type */
+    value = qemu_opt_get(legacy_opts, "if");
+    if (value) {
+        for (type = 0;
+             type < IF_COUNT && strcmp(value, if_name[type]);
+             type++) {
+        }
+        if (type == IF_COUNT) {
+            error_report("unsupported bus type '%s'", value);
+            goto fail;
+        }
+    } else {
+        type = block_default_type;
+    }
+
     /* Actual block device init: Functionality shared with blockdev-add */
-    dinfo = blockdev_init(bs_opts, block_default_type, media);
+    dinfo = blockdev_init(bs_opts, type, media);
     if (dinfo == NULL) {
         goto fail;
     }
@@ -2191,10 +2199,6 @@ QemuOptsList qemu_common_drive_opts = {
             .type = QEMU_OPT_NUMBER,
             .help = "unit number (i.e. lun for scsi)",
         },{
-            .name = "if",
-            .type = QEMU_OPT_STRING,
-            .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
-        },{
             .name = "index",
             .type = QEMU_OPT_NUMBER,
             .help = "index number",
commit 33cb7dc8b7a26ccdff2f054056d3f2e487cbb4cd
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Aug 28 17:00:13 2013 +0200

    blockdev: Move parsing of 'media' option to drive_init
    
    This moves as much as possible of the processing of the 'media' option
    to drive_init so that it can only be accessed using legacy functions,
    but never with anything blockdev-add related.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Benoit Canet <benoit at irqsave.net>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 617fad9..149ddc1 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -305,16 +305,18 @@ static bool check_throttle_config(ThrottleConfig *cfg, Error **errp)
     return true;
 }
 
+typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType;
+
 /* Takes the ownership of bs_opts */
 static DriveInfo *blockdev_init(QDict *bs_opts,
-                                BlockInterfaceType block_default_type)
+                                BlockInterfaceType block_default_type,
+                                DriveMediaType media)
 {
     const char *buf;
     const char *file = NULL;
     const char *serial;
     const char *mediastr = "";
     BlockInterfaceType type;
-    enum { MEDIA_DISK, MEDIA_CDROM } media;
     int bus_id, unit_id;
     int cyls, heads, secs, translation;
     int max_devs;
@@ -335,7 +337,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
     BlockDriver *drv = NULL;
 
     translation = BIOS_ATA_TRANSLATION_AUTO;
-    media = MEDIA_DISK;
 
     /* Check common options by copying from bs_opts to opts, all other options
      * stay in bs_opts for processing by bdrv_open(). */
@@ -422,19 +423,11 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
 	}
     }
 
-    if ((buf = qemu_opt_get(opts, "media")) != NULL) {
-        if (!strcmp(buf, "disk")) {
-	    media = MEDIA_DISK;
-	} else if (!strcmp(buf, "cdrom")) {
-            if (cyls || secs || heads) {
-                error_report("CHS can't be set with media=%s", buf);
-	        return NULL;
-            }
-	    media = MEDIA_CDROM;
-	} else {
-	    error_report("'%s' invalid media", buf);
-	    return NULL;
-	}
+    if (media == MEDIA_CDROM) {
+        if (cyls || secs || heads) {
+            error_report("CHS can't be set with media=cdrom");
+            return NULL;
+        }
     }
 
     if ((buf = qemu_opt_get(opts, "discard")) != NULL) {
@@ -751,11 +744,27 @@ static void qemu_opt_rename(QemuOpts *opts, const char *from, const char *to)
     }
 }
 
+QemuOptsList qemu_legacy_drive_opts = {
+    .name = "drive",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_legacy_drive_opts.head),
+    .desc = {
+        {
+            .name = "media",
+            .type = QEMU_OPT_STRING,
+            .help = "media type (disk, cdrom)",
+        },
+        { /* end of list */ }
+    },
+};
+
 DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
 {
     const char *value;
-    DriveInfo *dinfo;
+    DriveInfo *dinfo = NULL;
     QDict *bs_opts;
+    QemuOpts *legacy_opts;
+    DriveMediaType media = MEDIA_DISK;
+    Error *local_err = NULL;
 
     /* Change legacy command line options into QMP ones */
     qemu_opt_rename(all_opts, "iops", "throttling.iops-total");
@@ -808,8 +817,29 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     bs_opts = qdict_new();
     qemu_opts_to_qdict(all_opts, bs_opts);
 
+    legacy_opts = qemu_opts_create_nofail(&qemu_legacy_drive_opts);
+    qemu_opts_absorb_qdict(legacy_opts, bs_opts, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        goto fail;
+    }
+
+    /* Media type */
+    value = qemu_opt_get(legacy_opts, "media");
+    if (value) {
+        if (!strcmp(value, "disk")) {
+            media = MEDIA_DISK;
+        } else if (!strcmp(value, "cdrom")) {
+            media = MEDIA_CDROM;
+        } else {
+            error_report("'%s' invalid media", value);
+            goto fail;
+        }
+    }
+
     /* Actual block device init: Functionality shared with blockdev-add */
-    dinfo = blockdev_init(bs_opts, block_default_type);
+    dinfo = blockdev_init(bs_opts, block_default_type, media);
     if (dinfo == NULL) {
         goto fail;
     }
@@ -819,6 +849,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     dinfo->opts = all_opts;
 
 fail:
+    qemu_opts_del(legacy_opts);
     return dinfo;
 }
 
@@ -2115,7 +2146,7 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
 
     qdict_flatten(qdict);
 
-    dinfo = blockdev_init(qdict, IF_NONE);
+    dinfo = blockdev_init(qdict, IF_NONE, MEDIA_DISK);
     if (!dinfo) {
         error_setg(errp, "Could not open image");
         goto fail;
@@ -2184,10 +2215,6 @@ QemuOptsList qemu_common_drive_opts = {
             .type = QEMU_OPT_STRING,
             .help = "chs translation (auto, lba. none)",
         },{
-            .name = "media",
-            .type = QEMU_OPT_STRING,
-            .help = "media type (disk, cdrom)",
-        },{
             .name = "snapshot",
             .type = QEMU_OPT_BOOL,
             .help = "enable/disable snapshot mode",
commit f298d071662af6cf5dc221ee3e3bd0154035e570
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Sep 10 12:01:20 2013 +0200

    blockdev: Pass QDict to blockdev_init()
    
    Working on a QDict instead of a QemuOpts that accepts anything is more
    in line with bdrv_open(). A QDict is what qmp_blockdev_add() already has
    anyway, so this saves additional conversions. And last, but not least,
    it allows later patches to easily extract legacy options into a
    separate, typed QemuOpts for drive_init() (the untyped QemuOpts that
    drive_init already has doesn't allow access to numbers, only strings,
    and is therefore useless without conversion).
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Benoit Canet <benoit at irqsave.net>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index c1fcd3c..617fad9 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -217,7 +217,10 @@ static void bdrv_format_print(void *opaque, const char *name)
 
 static void drive_uninit(DriveInfo *dinfo)
 {
-    qemu_opts_del(dinfo->opts);
+    if (dinfo->opts) {
+        qemu_opts_del(dinfo->opts);
+    }
+
     bdrv_unref(dinfo->bdrv);
     g_free(dinfo->id);
     QTAILQ_REMOVE(&drives, dinfo, next);
@@ -302,7 +305,8 @@ static bool check_throttle_config(ThrottleConfig *cfg, Error **errp)
     return true;
 }
 
-static DriveInfo *blockdev_init(QemuOpts *all_opts,
+/* Takes the ownership of bs_opts */
+static DriveInfo *blockdev_init(QDict *bs_opts,
                                 BlockInterfaceType block_default_type)
 {
     const char *buf;
@@ -326,7 +330,6 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts,
     int ret;
     Error *error = NULL;
     QemuOpts *opts;
-    QDict *bs_opts;
     const char *id;
     bool has_driver_specific_opts;
     BlockDriver *drv = NULL;
@@ -334,9 +337,9 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts,
     translation = BIOS_ATA_TRANSLATION_AUTO;
     media = MEDIA_DISK;
 
-    /* Check common options by copying from all_opts to opts, all other options
-     * are stored in bs_opts. */
-    id = qemu_opts_id(all_opts);
+    /* Check common options by copying from bs_opts to opts, all other options
+     * stay in bs_opts for processing by bdrv_open(). */
+    id = qdict_get_try_str(bs_opts, "id");
     opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error);
     if (error_is_set(&error)) {
         qerror_report_err(error);
@@ -344,8 +347,6 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts,
         return NULL;
     }
 
-    bs_opts = qdict_new();
-    qemu_opts_to_qdict(all_opts, bs_opts);
     qemu_opts_absorb_qdict(opts, bs_opts, &error);
     if (error_is_set(&error)) {
         qerror_report_err(error);
@@ -630,7 +631,6 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts,
     dinfo->heads = heads;
     dinfo->secs = secs;
     dinfo->trans = translation;
-    dinfo->opts = all_opts;
     dinfo->refcount = 1;
     if (serial != NULL) {
         dinfo->serial = g_strdup(serial);
@@ -755,6 +755,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
 {
     const char *value;
     DriveInfo *dinfo;
+    QDict *bs_opts;
 
     /* Change legacy command line options into QMP ones */
     qemu_opt_rename(all_opts, "iops", "throttling.iops-total");
@@ -803,14 +804,19 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
         qemu_opt_unset(all_opts, "cache");
     }
 
+    /* Get a QDict for processing the options */
+    bs_opts = qdict_new();
+    qemu_opts_to_qdict(all_opts, bs_opts);
+
     /* Actual block device init: Functionality shared with blockdev-add */
-    dinfo = blockdev_init(all_opts, block_default_type);
+    dinfo = blockdev_init(bs_opts, block_default_type);
     if (dinfo == NULL) {
         goto fail;
     }
 
     /* Set legacy DriveInfo fields */
     dinfo->enable_auto_del = true;
+    dinfo->opts = all_opts;
 
 fail:
     return dinfo;
@@ -2109,13 +2115,7 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
 
     qdict_flatten(qdict);
 
-    QemuOpts *opts = qemu_opts_from_qdict(&qemu_drive_opts, qdict, &local_err);
-    if (error_is_set(&local_err)) {
-        error_propagate(errp, local_err);
-        goto fail;
-    }
-
-    dinfo = blockdev_init(opts, IF_NONE);
+    dinfo = blockdev_init(qdict, IF_NONE);
     if (!dinfo) {
         error_setg(errp, "Could not open image");
         goto fail;
commit 326642bc7f0ff95a0c08db527861a9a114a109da
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Jul 11 12:52:34 2013 +0200

    blockdev: Separate ID generation from DriveInfo creation
    
    blockdev-add shouldn't automatically generate IDs, but will keep most of
    the DriveInfo creation code.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Reviewed-by: Wenchao Xia <xiawenc at linux.vnet.ibm.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 9929d78..c1fcd3c 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -600,23 +600,25 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts,
         return NULL;
     }
 
-    /* init */
-
-    dinfo = g_malloc0(sizeof(*dinfo));
-    if ((buf = qemu_opts_id(opts)) != NULL) {
-        dinfo->id = g_strdup(buf);
-    } else {
-        /* no id supplied -> create one */
-        dinfo->id = g_malloc0(32);
-        if (type == IF_IDE || type == IF_SCSI)
+    /* no id supplied -> create one */
+    if (qemu_opts_id(opts) == NULL) {
+        char *new_id;
+        if (type == IF_IDE || type == IF_SCSI) {
             mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
-        if (max_devs)
-            snprintf(dinfo->id, 32, "%s%i%s%i",
-                     if_name[type], bus_id, mediastr, unit_id);
-        else
-            snprintf(dinfo->id, 32, "%s%s%i",
-                     if_name[type], mediastr, unit_id);
+        }
+        if (max_devs) {
+            new_id = g_strdup_printf("%s%i%s%i", if_name[type], bus_id,
+                                     mediastr, unit_id);
+        } else {
+            new_id = g_strdup_printf("%s%s%i", if_name[type],
+                                     mediastr, unit_id);
+        }
+        qemu_opts_set_id(opts, new_id);
     }
+
+    /* init */
+    dinfo = g_malloc0(sizeof(*dinfo));
+    dinfo->id = g_strdup(qemu_opts_id(opts));
     dinfo->bdrv = bdrv_new(dinfo->id);
     dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
     dinfo->bdrv->read_only = ro;
diff --git a/include/qemu/option.h b/include/qemu/option.h
index 63db4cc..5c0c6dd 100644
--- a/include/qemu/option.h
+++ b/include/qemu/option.h
@@ -142,6 +142,7 @@ void qemu_opts_loc_restore(QemuOpts *opts);
 int qemu_opts_set(QemuOptsList *list, const char *id,
                   const char *name, const char *value);
 const char *qemu_opts_id(QemuOpts *opts);
+void qemu_opts_set_id(QemuOpts *opts, char *id);
 void qemu_opts_del(QemuOpts *opts);
 void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp);
 int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname);
diff --git a/util/qemu-option.c b/util/qemu-option.c
index e0844a9..efcb5dc 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -834,6 +834,12 @@ const char *qemu_opts_id(QemuOpts *opts)
     return opts->id;
 }
 
+/* The id string will be g_free()d by qemu_opts_del */
+void qemu_opts_set_id(QemuOpts *opts, char *id)
+{
+    opts->id = id;
+}
+
 void qemu_opts_del(QemuOpts *opts)
 {
     QemuOpt *opt;
commit d26c9a15738147a8dccc451c6f6d1ddc2305713d
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Sep 23 15:26:03 2013 +0200

    blockdev: 'blockdev-add' QMP command
    
    For examples see the changes to qmp-commands.hx.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 52996ea..9929d78 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -38,6 +38,8 @@
 #include "qemu/option.h"
 #include "qemu/config-file.h"
 #include "qapi/qmp/types.h"
+#include "qapi-visit.h"
+#include "qapi/qmp-output-visitor.h"
 #include "sysemu/sysemu.h"
 #include "block/block_int.h"
 #include "qmp-commands.h"
@@ -2066,6 +2068,61 @@ void qmp_block_job_complete(const char *device, Error **errp)
     block_job_complete(job, errp);
 }
 
+void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
+{
+    QmpOutputVisitor *ov = qmp_output_visitor_new();
+    QObject *obj;
+    QDict *qdict;
+    DriveInfo *dinfo;
+    Error *local_err = NULL;
+
+    /* Require an ID in the top level */
+    if (!options->has_id) {
+        error_setg(errp, "Block device needs an ID");
+        goto fail;
+    }
+
+    /* TODO Sort it out in raw-posix and drive_init: Reject aio=native with
+     * cache.direct=false instead of silently switching to aio=threads, except
+     * if called from drive_init.
+     *
+     * For now, simply forbidding the combination for all drivers will do. */
+    if (options->has_aio && options->aio == BLOCKDEV_AIO_OPTIONS_NATIVE) {
+        bool direct = options->cache->has_direct && options->cache->direct;
+        if (!options->has_cache && !direct) {
+            error_setg(errp, "aio=native requires cache.direct=true");
+            goto fail;
+        }
+    }
+
+    visit_type_BlockdevOptions(qmp_output_get_visitor(ov),
+                               &options, NULL, &local_err);
+    if (error_is_set(&local_err)) {
+        error_propagate(errp, local_err);
+        goto fail;
+    }
+
+    obj = qmp_output_get_qobject(ov);
+    qdict = qobject_to_qdict(obj);
+
+    qdict_flatten(qdict);
+
+    QemuOpts *opts = qemu_opts_from_qdict(&qemu_drive_opts, qdict, &local_err);
+    if (error_is_set(&local_err)) {
+        error_propagate(errp, local_err);
+        goto fail;
+    }
+
+    dinfo = blockdev_init(opts, IF_NONE);
+    if (!dinfo) {
+        error_setg(errp, "Could not open image");
+        goto fail;
+    }
+
+fail:
+    qmp_output_visitor_cleanup(ov);
+}
+
 static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs)
 {
     BlockJobInfoList **prev = opaque;
diff --git a/qapi-schema.json b/qapi-schema.json
index a1a81a4..60f3fd1 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3952,3 +3952,239 @@
 ##
 { 'command': 'query-rx-filter', 'data': { '*name': 'str' },
   'returns': ['RxFilterInfo'] }
+
+
+##
+# @BlockdevDiscardOptions
+#
+# Determines how to handle discard requests.
+#
+# @ignore:      Ignore the request
+# @unmap:       Forward as an unmap request
+#
+# Since: 1.7
+##
+{ 'enum': 'BlockdevDiscardOptions',
+  'data': [ 'ignore', 'unmap' ] }
+
+##
+# @BlockdevAioOptions
+#
+# Selects the AIO backend to handle I/O requests
+#
+# @threads:     Use qemu's thread pool
+# @native:      Use native AIO backend (only Linux and Windows)
+#
+# Since: 1.7
+##
+{ 'enum': 'BlockdevAioOptions',
+  'data': [ 'threads', 'native' ] }
+
+##
+# @BlockdevCacheOptions
+#
+# Includes cache-related options for block devices
+#
+# @writeback:   #optional enables writeback mode for any caches (default: true)
+# @direct:      #optional enables use of O_DIRECT (bypass the host page cache;
+#               default: false)
+# @no-flush:    #optional ignore any flush requests for the device (default:
+#               false)
+#
+# Since: 1.7
+##
+{ 'type': 'BlockdevCacheOptions',
+  'data': { '*writeback': 'bool',
+            '*direct': 'bool',
+            '*no-flush': 'bool' } }
+
+##
+# @BlockdevOptionsBase
+#
+# Options that are available for all block devices, independent of the block
+# driver.
+#
+# @driver:      block driver name
+# @id:          #optional id by which the new block device can be referred to.
+#               This is a required option on the top level of blockdev-add, and
+#               currently not allowed on any other level.
+# @discard:     #optional discard-related options (default: ignore)
+# @cache:       #optional cache-related options
+# @aio:         #optional AIO backend (default: threads)
+# @rerror:      #optional how to handle read errors on the device
+#               (default: report)
+# @werror:      #optional how to handle write errors on the device
+#               (default: enospc)
+# @read-only:   #optional whether the block device should be read-only
+#               (default: false)
+#
+# Since: 1.7
+##
+{ 'type': 'BlockdevOptionsBase',
+  'data': { 'driver': 'str',
+            '*id': 'str',
+            '*discard': 'BlockdevDiscardOptions',
+            '*cache': 'BlockdevCacheOptions',
+            '*aio': 'BlockdevAioOptions',
+            '*rerror': 'BlockdevOnError',
+            '*werror': 'BlockdevOnError',
+            '*read-only': 'bool' } }
+
+##
+# @BlockdevOptionsFile
+#
+# Driver specific block device options for the file backend and similar
+# protocols.
+#
+# @filename:    path to the image file
+#
+# Since: 1.7
+##
+{ 'type': 'BlockdevOptionsFile',
+  'data': { 'filename': 'str' } }
+
+##
+# @BlockdevOptionsVVFAT
+#
+# Driver specific block device options for the vvfat protocol.
+#
+# @dir:         directory to be exported as FAT image
+# @fat-type:    #optional FAT type: 12, 16 or 32
+# @floppy:      #optional whether to export a floppy image (true) or
+#               partitioned hard disk (false; default)
+# @rw:          #optional whether to allow write operations (default: false)
+#
+# Since: 1.7
+##
+{ 'type': 'BlockdevOptionsVVFAT',
+  'data': { 'dir': 'str', '*fat-type': 'int', '*floppy': 'bool',
+            '*rw': 'bool' } }
+
+##
+# @BlockdevOptionsGenericFormat
+#
+# Driver specific block device options for image format that have no option
+# besides their data source.
+#
+# @file:        reference to or definition of the data source block device
+#
+# Since: 1.7
+##
+{ 'type': 'BlockdevOptionsGenericFormat',
+  'data': { 'file': 'BlockdevRef' } }
+
+##
+# @BlockdevOptionsGenericCOWFormat
+#
+# Driver specific block device options for image format that have no option
+# besides their data source and an optional backing file.
+#
+# @backing:     #optional reference to or definition of the backing file block
+#               device (if missing, taken from the image file content). It is
+#               allowed to pass an empty string here in order to disable the
+#               default backing file.
+#
+# Since: 1.7
+##
+{ 'type': 'BlockdevOptionsGenericCOWFormat',
+  'base': 'BlockdevOptionsGenericFormat',
+  'data': { '*backing': 'BlockdevRef' } }
+
+##
+# @BlockdevOptionsQcow2
+#
+# Driver specific block device options for qcow2.
+#
+# @lazy-refcounts:        #optional whether to enable the lazy refcounts
+#                         feature (default is taken from the image file)
+#
+# @pass-discard-request:  #optional whether discard requests to the qcow2
+#                         device should be forwarded to the data source
+#
+# @pass-discard-snapshot: #optional whether discard requests for the data source
+#                         should be issued when a snapshot operation (e.g.
+#                         deleting a snapshot) frees clusters in the qcow2 file
+#
+# @pass-discard-other:    #optional whether discard requests for the data source
+#                         should be issued on other occasions where a cluster
+#                         gets freed
+#
+# Since: 1.7
+##
+{ 'type': 'BlockdevOptionsQcow2',
+  'base': 'BlockdevOptionsGenericCOWFormat',
+  'data': { '*lazy-refcounts': 'bool',
+            '*pass-discard-request': 'bool',
+            '*pass-discard-snapshot': 'bool',
+            '*pass-discard-other': 'bool' } }
+
+##
+# @BlockdevOptions
+#
+# Options for creating a block device.
+#
+# Since: 1.7
+##
+{ 'union': 'BlockdevOptions',
+  'base': 'BlockdevOptionsBase',
+  'discriminator': 'driver',
+  'data': {
+      'file':       'BlockdevOptionsFile',
+      'http':       'BlockdevOptionsFile',
+      'https':      'BlockdevOptionsFile',
+      'ftp':        'BlockdevOptionsFile',
+      'ftps':       'BlockdevOptionsFile',
+      'tftp':       'BlockdevOptionsFile',
+# TODO gluster: Wait for structured options
+# TODO iscsi: Wait for structured options
+# TODO nbd: Should take InetSocketAddress for 'host'?
+# TODO rbd: Wait for structured options
+# TODO sheepdog: Wait for structured options
+# TODO ssh: Should take InetSocketAddress for 'host'?
+      'vvfat':      'BlockdevOptionsVVFAT',
+
+# TODO blkdebug: Wait for structured options
+# TODO blkverify: Wait for structured options
+
+      'bochs':      'BlockdevOptionsGenericFormat',
+      'cloop':      'BlockdevOptionsGenericFormat',
+      'cow':        'BlockdevOptionsGenericCOWFormat',
+      'dmg':        'BlockdevOptionsGenericFormat',
+      'parallels':  'BlockdevOptionsGenericFormat',
+      'qcow':       'BlockdevOptionsGenericCOWFormat',
+      'qcow2':      'BlockdevOptionsQcow2',
+      'qed':        'BlockdevOptionsGenericCOWFormat',
+      'raw':        'BlockdevOptionsGenericFormat',
+      'vdi':        'BlockdevOptionsGenericFormat',
+      'vhdx':       'BlockdevOptionsGenericFormat',
+      'vmdk':       'BlockdevOptionsGenericCOWFormat',
+      'vpc':        'BlockdevOptionsGenericFormat'
+  } }
+
+##
+# @BlockdevRef
+#
+# Reference to a block device.
+#
+# @definition:      defines a new block device inline
+# @reference:       references the ID of an existing block device. An
+#                   empty string means that no block device should be
+#                   referenced.
+#
+# Since: 1.7
+##
+{ 'union': 'BlockdevRef',
+  'discriminator': {},
+  'data': { 'definition': 'BlockdevOptions',
+            'reference': 'str' } }
+
+##
+# @blockdev-add:
+#
+# Creates a new block device.
+#
+# @options: block device options for the new device
+#
+# Since: 1.7
+##
+{ 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index b17c46e..fba15cd 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -3240,3 +3240,58 @@ Example:
    }
 
 EQMP
+
+    {
+        .name       = "blockdev-add",
+        .args_type  = "options:q",
+        .mhandler.cmd_new = qmp_marshal_input_blockdev_add,
+    },
+
+SQMP
+blockdev-add
+------------
+
+Add a block device.
+
+Arguments:
+
+- "options": block driver options
+
+Example (1):
+
+-> { "execute": "blockdev-add",
+    "arguments": { "options" : { "driver": "qcow2",
+                                 "file": { "driver": "file",
+                                           "filename": "test.qcow2" } } } }
+<- { "return": {} }
+
+Example (2):
+
+-> { "execute": "blockdev-add",
+     "arguments": {
+         "options": {
+           "driver": "qcow2",
+           "id": "my_disk",
+           "discard": "unmap",
+           "cache": {
+               "direct": true,
+               "writeback": true
+           },
+           "file": {
+               "driver": "file",
+               "filename": "/tmp/test.qcow2"
+           },
+           "backing": {
+               "driver": "raw",
+               "file": {
+                   "driver": "file",
+                   "filename": "/dev/fdset/4"
+               }
+           }
+         }
+       }
+     }
+
+<- { "return": {} }
+
+EQMP
commit 2d246f01d374c1a10c48c45aa931aa18f0a56634
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Sep 18 15:14:47 2013 +0200

    blockdev: Introduce DriveInfo.enable_auto_del
    
    BlockDriverStates shouldn't be affected by an unplugged guest device,
    except if created with the legacy -drive command line option or the
    drive_add HMP command.
    
    Make the automatic deletion as well as cancelling of jobs conditional on
    an enable_auto_del boolean that is only set in drive_init().
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Wenchao Xia <xiawenc at linux.vnet.ibm.com>

diff --git a/blockdev.c b/blockdev.c
index ab79df7..52996ea 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -89,6 +89,10 @@ void blockdev_mark_auto_del(BlockDriverState *bs)
 {
     DriveInfo *dinfo = drive_get_by_blockdev(bs);
 
+    if (dinfo && !dinfo->enable_auto_del) {
+        return;
+    }
+
     if (bs->job) {
         block_job_cancel(bs->job);
     }
@@ -746,6 +750,7 @@ static void qemu_opt_rename(QemuOpts *opts, const char *from, const char *to)
 DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
 {
     const char *value;
+    DriveInfo *dinfo;
 
     /* Change legacy command line options into QMP ones */
     qemu_opt_rename(all_opts, "iops", "throttling.iops-total");
@@ -794,7 +799,17 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
         qemu_opt_unset(all_opts, "cache");
     }
 
-    return blockdev_init(all_opts, block_default_type);
+    /* Actual block device init: Functionality shared with blockdev-add */
+    dinfo = blockdev_init(all_opts, block_default_type);
+    if (dinfo == NULL) {
+        goto fail;
+    }
+
+    /* Set legacy DriveInfo fields */
+    dinfo->enable_auto_del = true;
+
+fail:
+    return dinfo;
 }
 
 void do_commit(Monitor *mon, const QDict *qdict)
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
index 804ec88..1082091 100644
--- a/include/sysemu/blockdev.h
+++ b/include/sysemu/blockdev.h
@@ -37,6 +37,7 @@ struct DriveInfo {
     int bus;
     int unit;
     int auto_del;               /* see blockdev_mark_auto_del() */
+    bool enable_auto_del; /* Only for legacy drive_init() */
     int media_cd;
     int cyls, heads, secs, trans;
     QemuOpts *opts;
commit 622f557f5aaea1326c94ca4cddfa4eafeade3723
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Sep 19 11:56:36 2013 +0200

    qapi-types/visit.py: Inheritance for structs
    
    This introduces a new 'base' key for struct definitions that refers to
    another struct type. On the JSON level, the fields of the base type are
    included directly into the same namespace as the fields of the defined
    type, like with unions. On the C level, a pointer to a struct of the
    base type is included.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index 0ce045c..91f44d0 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -53,6 +53,23 @@ 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.
 
+
+A complex type definition can specify another complex type as its base.
+In this case, the fields of the base type are included as top-level fields
+of the new complex type's dictionary in the QMP wire format. An example
+definition is:
+
+ { 'type': 'BlockdevOptionsGenericFormat', 'data': { 'file': 'str' } }
+ { 'type': 'BlockdevOptionsGenericCOWFormat',
+   'base': 'BlockdevOptionsGenericFormat',
+   'data': { '*backing': 'str' } }
+
+An example BlockdevOptionsGenericCOWFormat object on the wire could use
+both fields like this:
+
+ { "file": "/some/place/my-image",
+   "backing": "/some/place/my-backing-file" }
+
 === Enumeration types ===
 
 An enumeration type is a dictionary containing a single key whose value is a
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 566fe5e..4a1652b 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -86,6 +86,7 @@ def generate_struct(expr):
     structname = expr.get('type', "")
     fieldname = expr.get('field', "")
     members = expr['data']
+    base = expr.get('base')
 
     ret = mcgen('''
 struct %(name)s
@@ -93,6 +94,9 @@ struct %(name)s
 ''',
           name=structname)
 
+    if base:
+        ret += generate_struct_fields({'base': base})
+
     ret += generate_struct_fields(members)
 
     if len(fieldname):
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 1e44004..c39e628 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -17,7 +17,7 @@ import os
 import getopt
 import errno
 
-def generate_visit_struct_fields(name, field_prefix, fn_prefix, members):
+def generate_visit_struct_fields(name, field_prefix, fn_prefix, members, base = None):
     substructs = []
     ret = ''
     full_name = name if not fn_prefix else "%s_%s" % (name, fn_prefix)
@@ -42,6 +42,19 @@ static void visit_type_%(full_name)s_fields(Visitor *m, %(name)s ** obj, Error *
         name=name, full_name=full_name)
     push_indent()
 
+    if base:
+        ret += mcgen('''
+visit_start_implicit_struct(m, obj ? (void**) &(*obj)->%(c_name)s : NULL, sizeof(%(type)s), &err);
+if (!err) {
+    visit_type_%(type)s_fields(m, obj ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, &err);
+    error_propagate(errp, err);
+    err = NULL;
+    visit_end_implicit_struct(m, &err);
+}
+''',
+                     c_prefix=c_var(field_prefix),
+                     type=type_name(base), c_name=c_var('base'))
+
     for argname, argentry, optional, structured in parse_args(members):
         if optional:
             ret += mcgen('''
@@ -124,8 +137,9 @@ def generate_visit_struct(expr):
 
     name = expr['type']
     members = expr['data']
+    base = expr.get('base')
 
-    ret = generate_visit_struct_fields(name, "", "", members)
+    ret = generate_visit_struct_fields(name, "", "", members, base)
 
     ret += mcgen('''
 
commit 14d36307ffdf949df9c1dd7f435e138b36f63bb0
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Sep 18 17:22:02 2013 +0200

    qapi-types/visit.py: Pass whole expr dict for structs
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 5222463..566fe5e 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -71,7 +71,7 @@ def generate_struct_fields(members):
                          c_name=c_var(argname))
         if structured:
             push_indent()
-            ret += generate_struct("", argname, argentry)
+            ret += generate_struct({ "field": argname, "data": argentry})
             pop_indent()
         else:
             ret += mcgen('''
@@ -81,7 +81,12 @@ def generate_struct_fields(members):
 
     return ret
 
-def generate_struct(structname, fieldname, members):
+def generate_struct(expr):
+
+    structname = expr.get('type', "")
+    fieldname = expr.get('field', "")
+    members = expr['data']
+
     ret = mcgen('''
 struct %(name)s
 {
@@ -417,7 +422,7 @@ if do_builtins:
 for expr in exprs:
     ret = "\n"
     if expr.has_key('type'):
-        ret += generate_struct(expr['type'], "", expr['data']) + "\n"
+        ret += generate_struct(expr) + "\n"
         ret += generate_type_cleanup_decl(expr['type'] + "List")
         fdef.write(generate_type_cleanup(expr['type'] + "List") + "\n")
         ret += generate_type_cleanup_decl(expr['type'])
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 597cca4..1e44004 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -120,7 +120,11 @@ if (!err) {
 ''')
     return ret
 
-def generate_visit_struct(name, members):
+def generate_visit_struct(expr):
+
+    name = expr['type']
+    members = expr['data']
+
     ret = generate_visit_struct_fields(name, "", "", members)
 
     ret += mcgen('''
@@ -472,7 +476,7 @@ if do_builtins:
 
 for expr in exprs:
     if expr.has_key('type'):
-        ret = generate_visit_struct(expr['type'], expr['data'])
+        ret = generate_visit_struct(expr)
         ret += generate_visit_list(expr['type'], expr['data'])
         fdef.write(ret)
 
commit 52c8d629cac27ad16dd51507b4733d46fa4efc55
Author: Fam Zheng <famz at redhat.com>
Date:   Fri Oct 11 15:43:23 2013 +0800

    vmdk: refuse enabling zeroed grain with flat images
    
    This is a header flag and we needs sparse for the header.
    
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index a1aaea7..709aa3d 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1664,6 +1664,10 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
         error_setg(errp, "Flat image can't have backing file");
         return -ENOTSUP;
     }
+    if (flat && zeroed_grain) {
+        error_setg(errp, "Flat image can't enable zeroed grain");
+        return -ENOTSUP;
+    }
     if (backing_file) {
         BlockDriverState *bs = bdrv_new("");
         ret = bdrv_open(bs, backing_file, NULL, 0, NULL, errp);
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
index 18cdad1..b81c575 100755
--- a/tests/qemu-iotests/059
+++ b/tests/qemu-iotests/059
@@ -71,6 +71,10 @@ echo "=== Testing monolithicFlat creation and opening ==="
 IMGOPTS="subformat=monolithicFlat" _make_test_img 2G
 $QEMU_IMG info $TEST_IMG | _filter_testdir
 
+echo
+echo "=== Testing monolithicFlat with zeroed_grain ==="
+IMGOPTS="subformat=monolithicFlat,zeroed_grain=on" _make_test_img 2G
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
index 265cd76..9b12efb 100644
--- a/tests/qemu-iotests/059.out
+++ b/tests/qemu-iotests/059.out
@@ -22,4 +22,8 @@ image: TEST_DIR/t.vmdk
 file format: vmdk
 virtual size: 2.0G (2147483648 bytes)
 disk size: 4.0K
+
+=== Testing monolithicFlat with zeroed_grain ===
+qemu-img: TEST_DIR/t.IMGFMT: Flat image can't enable zeroed grain
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648
 *** done
commit 4823970bcb882cd5b7e9c9a21fa6573190035050
Author: Fam Zheng <famz at redhat.com>
Date:   Fri Oct 11 15:43:22 2013 +0800

    vmdk: convert error code to use errp
    
    Convert "fprintf(stderr,..." and standardize error messages:
    
    Remove a few local_error's and use errp.
    
    Remove "VMDK:" or "Vmdk:" prefixes in error message and fix to upper
    case.
    
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index 5d56e31..a1aaea7 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -331,8 +331,7 @@ static int vmdk_reopen_prepare(BDRVReopenState *state,
     assert(state->bs != NULL);
 
     if (queue == NULL) {
-        error_set(errp, ERROR_CLASS_GENERIC_ERROR,
-                 "No reopen queue for VMDK extents");
+        error_setg(errp, "No reopen queue for VMDK extents");
         goto exit;
     }
 
@@ -391,22 +390,23 @@ static int vmdk_add_extent(BlockDriverState *bs,
                            int64_t l1_offset, int64_t l1_backup_offset,
                            uint32_t l1_size,
                            int l2_size, uint64_t cluster_sectors,
-                           VmdkExtent **new_extent)
+                           VmdkExtent **new_extent,
+                           Error **errp)
 {
     VmdkExtent *extent;
     BDRVVmdkState *s = bs->opaque;
 
     if (cluster_sectors > 0x200000) {
         /* 0x200000 * 512Bytes = 1GB for one cluster is unrealistic */
-        error_report("invalid granularity, image may be corrupt");
-        return -EINVAL;
+        error_setg(errp, "Invalid granularity, image may be corrupt");
+        return -EFBIG;
     }
     if (l1_size > 512 * 1024 * 1024) {
         /* Although with big capacity and small l1_entry_sectors, we can get a
          * big l1_size, we don't want unbounded value to allocate the table.
          * Limit it to 512M, which is 16PB for default cluster and L2 table
          * size */
-        error_report("L1 size too big");
+        error_setg(errp, "L1 size too big");
         return -EFBIG;
     }
 
@@ -438,7 +438,8 @@ static int vmdk_add_extent(BlockDriverState *bs,
     return 0;
 }
 
-static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent)
+static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
+                            Error **errp)
 {
     int ret;
     int l1_size, i;
@@ -447,10 +448,13 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent)
     l1_size = extent->l1_size * sizeof(uint32_t);
     extent->l1_table = g_malloc(l1_size);
     ret = bdrv_pread(extent->file,
-                    extent->l1_table_offset,
-                    extent->l1_table,
-                    l1_size);
+                     extent->l1_table_offset,
+                     extent->l1_table,
+                     l1_size);
     if (ret < 0) {
+        error_setg_errno(errp, -ret,
+                         "Could not read l1 table from extent '%s'",
+                         extent->file->filename);
         goto fail_l1;
     }
     for (i = 0; i < extent->l1_size; i++) {
@@ -460,10 +464,13 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent)
     if (extent->l1_backup_table_offset) {
         extent->l1_backup_table = g_malloc(l1_size);
         ret = bdrv_pread(extent->file,
-                        extent->l1_backup_table_offset,
-                        extent->l1_backup_table,
-                        l1_size);
+                         extent->l1_backup_table_offset,
+                         extent->l1_backup_table,
+                         l1_size);
         if (ret < 0) {
+            error_setg_errno(errp, -ret,
+                             "Could not read l1 backup table from extent '%s'",
+                             extent->file->filename);
             goto fail_l1b;
         }
         for (i = 0; i < extent->l1_size; i++) {
@@ -483,7 +490,7 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent)
 
 static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
                                  BlockDriverState *file,
-                                 int flags)
+                                 int flags, Error **errp)
 {
     int ret;
     uint32_t magic;
@@ -492,6 +499,9 @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
 
     ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
     if (ret < 0) {
+        error_setg_errno(errp, -ret,
+                         "Could not read header from file '%s'",
+                         file->filename);
         return ret;
     }
     ret = vmdk_add_extent(bs, file, false,
@@ -501,11 +511,12 @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
                           le32_to_cpu(header.l1dir_size),
                           4096,
                           le32_to_cpu(header.granularity),
-                          &extent);
+                          &extent,
+                          errp);
     if (ret < 0) {
         return ret;
     }
-    ret = vmdk_init_tables(bs, extent);
+    ret = vmdk_init_tables(bs, extent, errp);
     if (ret) {
         /* free extent allocated by vmdk_add_extent */
         vmdk_free_last_extent(bs);
@@ -514,11 +525,11 @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
 }
 
 static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
-                               uint64_t desc_offset);
+                               uint64_t desc_offset, Error **errp);
 
 static int vmdk_open_vmdk4(BlockDriverState *bs,
                            BlockDriverState *file,
-                           int flags)
+                           int flags, Error **errp)
 {
     int ret;
     uint32_t magic;
@@ -529,12 +540,14 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
 
     ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
     if (ret < 0) {
-        return ret;
+        error_setg_errno(errp, -ret,
+                         "Could not read header from file '%s'",
+                         file->filename);
     }
     if (header.capacity == 0) {
         uint64_t desc_offset = le64_to_cpu(header.desc_offset);
         if (desc_offset) {
-            return vmdk_open_desc_file(bs, flags, desc_offset << 9);
+            return vmdk_open_desc_file(bs, flags, desc_offset << 9, errp);
         }
     }
 
@@ -616,7 +629,8 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
                           l1_size,
                           le32_to_cpu(header.num_gtes_per_gt),
                           le64_to_cpu(header.granularity),
-                          &extent);
+                          &extent,
+                          errp);
     if (ret < 0) {
         return ret;
     }
@@ -625,7 +639,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
     extent->has_marker = le32_to_cpu(header.flags) & VMDK4_FLAG_MARKER;
     extent->version = le32_to_cpu(header.version);
     extent->has_zero_grain = le32_to_cpu(header.flags) & VMDK4_FLAG_ZERO_GRAIN;
-    ret = vmdk_init_tables(bs, extent);
+    ret = vmdk_init_tables(bs, extent, errp);
     if (ret) {
         /* free extent allocated by vmdk_add_extent */
         vmdk_free_last_extent(bs);
@@ -663,7 +677,7 @@ static int vmdk_parse_description(const char *desc, const char *opt_name,
 /* Open an extent file and append to bs array */
 static int vmdk_open_sparse(BlockDriverState *bs,
                             BlockDriverState *file,
-                            int flags)
+                            int flags, Error **errp)
 {
     uint32_t magic;
 
@@ -674,10 +688,10 @@ static int vmdk_open_sparse(BlockDriverState *bs,
     magic = be32_to_cpu(magic);
     switch (magic) {
         case VMDK3_MAGIC:
-            return vmdk_open_vmfs_sparse(bs, file, flags);
+            return vmdk_open_vmfs_sparse(bs, file, flags, errp);
             break;
         case VMDK4_MAGIC:
-            return vmdk_open_vmdk4(bs, file, flags);
+            return vmdk_open_vmdk4(bs, file, flags, errp);
             break;
         default:
             return -EMEDIUMTYPE;
@@ -686,7 +700,7 @@ static int vmdk_open_sparse(BlockDriverState *bs,
 }
 
 static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
-        const char *desc_file_path)
+                              const char *desc_file_path, Error **errp)
 {
     int ret;
     char access[11];
@@ -697,7 +711,6 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
     int64_t flat_offset;
     char extent_path[PATH_MAX];
     BlockDriverState *extent_file;
-    Error *local_err = NULL;
 
     while (*p) {
         /* parse extent line:
@@ -712,9 +725,11 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
             goto next_line;
         } else if (!strcmp(type, "FLAT")) {
             if (ret != 5 || flat_offset < 0) {
+                error_setg(errp, "Invalid extent lines: \n%s", p);
                 return -EINVAL;
             }
         } else if (ret != 4) {
+            error_setg(errp, "Invalid extent lines: \n%s", p);
             return -EINVAL;
         }
 
@@ -728,10 +743,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
         path_combine(extent_path, sizeof(extent_path),
                 desc_file_path, fname);
         ret = bdrv_file_open(&extent_file, extent_path, NULL, bs->open_flags,
-                             &local_err);
+                             errp);
         if (ret) {
-            qerror_report_err(local_err);
-            error_free(local_err);
             return ret;
         }
 
@@ -741,21 +754,20 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
             VmdkExtent *extent;
 
             ret = vmdk_add_extent(bs, extent_file, true, sectors,
-                            0, 0, 0, 0, 0, &extent);
+                            0, 0, 0, 0, 0, &extent, errp);
             if (ret < 0) {
                 return ret;
             }
             extent->flat_start_offset = flat_offset << 9;
         } else if (!strcmp(type, "SPARSE") || !strcmp(type, "VMFSSPARSE")) {
             /* SPARSE extent and VMFSSPARSE extent are both "COWD" sparse file*/
-            ret = vmdk_open_sparse(bs, extent_file, bs->open_flags);
+            ret = vmdk_open_sparse(bs, extent_file, bs->open_flags, errp);
             if (ret) {
                 bdrv_unref(extent_file);
                 return ret;
             }
         } else {
-            fprintf(stderr,
-                "VMDK: Not supported extent type \"%s\""".\n", type);
+            error_setg(errp, "Unsupported extent type '%s'", type);
             return -ENOTSUP;
         }
 next_line:
@@ -769,7 +781,7 @@ next_line:
 }
 
 static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
-                               uint64_t desc_offset)
+                               uint64_t desc_offset, Error **errp)
 {
     int ret;
     char *buf = NULL;
@@ -798,13 +810,12 @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
         strcmp(ct, "vmfsSparse") &&
         strcmp(ct, "twoGbMaxExtentSparse") &&
         strcmp(ct, "twoGbMaxExtentFlat")) {
-        fprintf(stderr,
-                "VMDK: Not supported image type \"%s\""".\n", ct);
+        error_setg(errp, "Unsupported image type '%s'", ct);
         ret = -ENOTSUP;
         goto exit;
     }
     s->desc_offset = 0;
-    ret = vmdk_parse_extents(buf, bs, bs->file->filename);
+    ret = vmdk_parse_extents(buf, bs, bs->file->filename, errp);
 exit:
     g_free(buf);
     return ret;
@@ -816,10 +827,10 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
     int ret;
     BDRVVmdkState *s = bs->opaque;
 
-    if (vmdk_open_sparse(bs, bs->file, flags) == 0) {
+    if (vmdk_open_sparse(bs, bs->file, flags, errp) == 0) {
         s->desc_offset = 0x200;
     } else {
-        ret = vmdk_open_desc_file(bs, flags, 0);
+        ret = vmdk_open_desc_file(bs, flags, 0, errp);
         if (ret) {
             goto fail;
         }
@@ -1286,8 +1297,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
     VmdkMetaData m_data;
 
     if (sector_num > bs->total_sectors) {
-        fprintf(stderr,
-                "(VMDK) Wrong offset: sector_num=0x%" PRIx64
+        error_report("Wrong offset: sector_num=0x%" PRIx64
                 " total_sectors=0x%" PRIx64 "\n",
                 sector_num, bs->total_sectors);
         return -EIO;
@@ -1307,9 +1317,8 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
         if (extent->compressed) {
             if (ret == VMDK_OK) {
                 /* Refuse write to allocated cluster for streamOptimized */
-                fprintf(stderr,
-                        "VMDK: can't write to allocated cluster"
-                        " for streamOptimized\n");
+                error_report("Could not write to allocated cluster"
+                              " for streamOptimized");
                 return -EIO;
             } else {
                 /* allocate */
@@ -1517,12 +1526,12 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
 }
 
 static int filename_decompose(const char *filename, char *path, char *prefix,
-        char *postfix, size_t buf_len)
+                              char *postfix, size_t buf_len, Error **errp)
 {
     const char *p, *q;
 
     if (filename == NULL || !strlen(filename)) {
-        fprintf(stderr, "Vmdk: no filename provided.\n");
+        error_setg(errp, "No filename provided");
         return VMDK_ERROR;
     }
     p = strrchr(filename, '/');
@@ -1595,9 +1604,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
         "ddb.geometry.heads = \"%d\"\n"
         "ddb.geometry.sectors = \"63\"\n"
         "ddb.adapterType = \"%s\"\n";
-    Error *local_err = NULL;
 
-    if (filename_decompose(filename, path, prefix, postfix, PATH_MAX)) {
+    if (filename_decompose(filename, path, prefix, postfix, PATH_MAX, errp)) {
         return -EINVAL;
     }
     /* Read out options */
@@ -1623,7 +1631,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
                strcmp(adapter_type, "buslogic") &&
                strcmp(adapter_type, "lsilogic") &&
                strcmp(adapter_type, "legacyESX")) {
-        fprintf(stderr, "VMDK: Unknown adapter type: '%s'.\n", adapter_type);
+        error_setg(errp, "Unknown adapter type: '%s'", adapter_type);
         return -EINVAL;
     }
     if (strcmp(adapter_type, "ide") != 0) {
@@ -1639,7 +1647,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
                strcmp(fmt, "twoGbMaxExtentSparse") &&
                strcmp(fmt, "twoGbMaxExtentFlat") &&
                strcmp(fmt, "streamOptimized")) {
-        fprintf(stderr, "VMDK: Unknown subformat: %s\n", fmt);
+        error_setg(errp, "Unknown subformat: '%s'", fmt);
         return -EINVAL;
     }
     split = !(strcmp(fmt, "twoGbMaxExtentFlat") &&
@@ -1653,15 +1661,13 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
         desc_extent_line = "RW %lld SPARSE \"%s\"\n";
     }
     if (flat && backing_file) {
-        /* not supporting backing file for flat image */
+        error_setg(errp, "Flat image can't have backing file");
         return -ENOTSUP;
     }
     if (backing_file) {
         BlockDriverState *bs = bdrv_new("");
-        ret = bdrv_open(bs, backing_file, NULL, 0, NULL, &local_err);
+        ret = bdrv_open(bs, backing_file, NULL, 0, NULL, errp);
         if (ret != 0) {
-            qerror_report_err(local_err);
-            error_free(local_err);
             bdrv_unref(bs);
             return ret;
         }
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
index 21de6e7..265cd76 100644
--- a/tests/qemu-iotests/059.out
+++ b/tests/qemu-iotests/059.out
@@ -2,8 +2,7 @@ QA output created by 059
 
 === Testing invalid granularity ===
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-invalid granularity, image may be corrupt
-qemu-io: can't open device TEST_DIR/t.vmdk: Could not open 'TEST_DIR/t.vmdk': Wrong medium type
+qemu-io: can't open device TEST_DIR/t.vmdk: Invalid granularity, image may be corrupt
 no file open, try 'help open'
 
 === Testing too big L2 table size ===
@@ -14,8 +13,7 @@ no file open, try 'help open'
 
 === Testing too big L1 table size ===
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-L1 size too big
-qemu-io: can't open device TEST_DIR/t.vmdk: Could not open 'TEST_DIR/t.vmdk': Wrong medium type
+qemu-io: can't open device TEST_DIR/t.vmdk: L1 size too big
 no file open, try 'help open'
 
 === Testing monolithicFlat creation and opening ===
commit 2cdfb12332e885c8ce36f520d2a2a9200101e183
Author: Wenchao Xia <xiawenc at linux.vnet.ibm.com>
Date:   Thu Sep 26 08:42:56 2013 +0800

    build: add command check-clean
    
    This command will package the clean operations in tests. Now root Makefile
    simply calls the command and do not care the details of it any more. Original
    the built binaries for test will not be removed, now they will be deleted
    in clean operation.
    
    Signed-off-by: Wenchao Xia <xiawenc at linux.vnet.ibm.com>
    Reviewed-by: Fam Zheng <famz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/Makefile b/Makefile
index 60fb87e..b15003f 100644
--- a/Makefile
+++ b/Makefile
@@ -246,7 +246,6 @@ clean:
 	rm -f $(foreach f,$(GENERATED_SOURCES),$(f) $(f)-timestamp)
 	rm -rf qapi-generated
 	rm -rf qga/qapi-generated
-	$(MAKE) -C tests/tcg clean
 	for d in $(ALL_SUBDIRS); do \
 	if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
 	rm -f $$d/qemu-options.def; \
diff --git a/tests/Makefile b/tests/Makefile
index 6d67fdf..fa4c9f0 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -196,6 +196,7 @@ check-help:
 	@echo " make check-qapi-schema    Run QAPI schema tests"
 	@echo " make check-block          Run block tests"
 	@echo " make check-report.html    Generates an HTML test report"
+	@echo " make check-clean          Clean the tests"
 	@echo
 	@echo "Please note that HTML reports do not regenerate if the unit tests"
 	@echo "has not changed."
@@ -270,12 +271,17 @@ $(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
 
 # Consolidated targets
 
-.PHONY: check-qapi-schema check-qtest check-unit check
+.PHONY: check-qapi-schema check-qtest check-unit check check-clean
 check-qapi-schema: $(patsubst %,check-%, $(check-qapi-schema-y))
 check-qtest: $(patsubst %,check-qtest-%, $(QTEST_TARGETS))
 check-unit: $(patsubst %,check-%, $(check-unit-y))
 check-block: $(patsubst %,check-%, $(check-block-y))
 check: check-qapi-schema check-unit check-qtest
+check-clean:
+	$(MAKE) -C tests/tcg clean
+	rm -rf $(check-unit-y) $(check-qtest-i386-y) $(check-qtest-x86_64-y) $(check-qtest-sparc64-y) $(check-qtest-sparc-y) tests/*.o $(QEMU_IOTESTS_HELPERS-y)
+
+clean: check-clean
 
 # Build the help program automatically
 
commit 22ee5a557acc820109a9948620a26f66e4fa3a8f
Author: Wenchao Xia <xiawenc at linux.vnet.ibm.com>
Date:   Thu Sep 26 08:42:55 2013 +0800

    tests: build the helper program by default
    
    Usually we may configure and make, then goto ./tests/qemu-iotest,
    check. In this case an error will happen since helper program
    was not built. This patch simply build it by default. A better way
    may be introducing Makefile in ./tests/qemu-iotest, but it is more
    complicate to handle out of tree case, and a bit overkill
    for a single file now, we can do that when more files come.
    
    Signed-off-by: Wenchao Xia <xiawenc at linux.vnet.ibm.com>
    Reviewed-by: Fam Zheng <famz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/Makefile b/tests/Makefile
index 915ae5e..6d67fdf 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -252,8 +252,10 @@ check-report.html: check-report.xml
 
 # Other tests
 
+QEMU_IOTESTS_HELPERS-$(CONFIG_LINUX) = tests/qemu-iotests/socket_scm_helper$(EXESUF)
+
 .PHONY: check-tests/qemu-iotests-quick.sh
-check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh qemu-img$(EXESUF) qemu-io$(EXESUF) tests/qemu-iotests/socket_scm_helper$(EXESUF)
+check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh qemu-img$(EXESUF) qemu-io$(EXESUF) $(QEMU_IOTESTS_HELPERS-y)
 	$<
 
 .PHONY: check-tests/test-qapi.py
@@ -275,5 +277,9 @@ check-unit: $(patsubst %,check-%, $(check-unit-y))
 check-block: $(patsubst %,check-%, $(check-block-y))
 check: check-qapi-schema check-unit check-qtest
 
+# Build the help program automatically
+
+all: $(QEMU_IOTESTS_HELPERS-y)
+
 -include $(wildcard tests/*.d)
 -include $(wildcard tests/libqos/*.d)
commit e428e439df4d92ac42cb913a1dd19b86155eae86
Author: Max Reitz <mreitz at redhat.com>
Date:   Fri Oct 11 11:37:01 2013 +0200

    block/raw-posix: Employ error parameter
    
    Make use of the error parameter in the opening and creating functions in
    block/raw-posix.c.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/raw-posix.c b/block/raw-posix.c
index f7f102d..6f03fbf 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -276,7 +276,7 @@ static QemuOptsList raw_runtime_opts = {
 };
 
 static int raw_open_common(BlockDriverState *bs, QDict *options,
-                           int bdrv_flags, int open_flags)
+                           int bdrv_flags, int open_flags, Error **errp)
 {
     BDRVRawState *s = bs->opaque;
     QemuOpts *opts;
@@ -287,8 +287,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
     opts = qemu_opts_create_nofail(&raw_runtime_opts);
     qemu_opts_absorb_qdict(opts, options, &local_err);
     if (error_is_set(&local_err)) {
-        qerror_report_err(local_err);
-        error_free(local_err);
+        error_propagate(errp, local_err);
         ret = -EINVAL;
         goto fail;
     }
@@ -297,6 +296,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
 
     ret = raw_normalize_devicepath(&filename);
     if (ret != 0) {
+        error_setg_errno(errp, -ret, "Could not normalize device path");
         goto fail;
     }
 
@@ -310,6 +310,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
         if (ret == -EROFS) {
             ret = -EACCES;
         }
+        error_setg_errno(errp, -ret, "Could not open file");
         goto fail;
     }
     s->fd = fd;
@@ -318,6 +319,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
     if (raw_set_aio(&s->aio_ctx, &s->use_aio, bdrv_flags)) {
         qemu_close(fd);
         ret = -errno;
+        error_setg_errno(errp, -ret, "Could not set AIO state");
         goto fail;
     }
 #endif
@@ -339,9 +341,15 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
                     Error **errp)
 {
     BDRVRawState *s = bs->opaque;
+    Error *local_err = NULL;
+    int ret;
 
     s->type = FTYPE_FILE;
-    return raw_open_common(bs, options, flags, 0);
+    ret = raw_open_common(bs, options, flags, 0, &local_err);
+    if (error_is_set(&local_err)) {
+        error_propagate(errp, local_err);
+    }
+    return ret;
 }
 
 static int raw_reopen_prepare(BDRVReopenState *state,
@@ -366,6 +374,7 @@ static int raw_reopen_prepare(BDRVReopenState *state,
      * valid in the 'false' condition even if aio_ctx is set, and raw_set_aio()
      * won't override aio_ctx if aio_ctx is non-NULL */
     if (raw_set_aio(&s->aio_ctx, &raw_s->use_aio, state->flags)) {
+        error_setg(errp, "Could not set AIO state");
         return -1;
     }
 #endif
@@ -417,6 +426,7 @@ static int raw_reopen_prepare(BDRVReopenState *state,
         assert(!(raw_s->open_flags & O_CREAT));
         raw_s->fd = qemu_open(state->bs->filename, raw_s->open_flags);
         if (raw_s->fd == -1) {
+            error_setg_errno(errp, errno, "Could not reopen file");
             ret = -1;
         }
     }
@@ -1060,12 +1070,15 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
                    0644);
     if (fd < 0) {
         result = -errno;
+        error_setg_errno(errp, -result, "Could not create file");
     } else {
         if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) {
             result = -errno;
+            error_setg_errno(errp, -result, "Could not resize file");
         }
         if (qemu_close(fd) != 0) {
             result = -errno;
+            error_setg_errno(errp, -result, "Could not close the new file");
         }
     }
     return result;
@@ -1338,6 +1351,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
                      Error **errp)
 {
     BDRVRawState *s = bs->opaque;
+    Error *local_err = NULL;
     int ret;
     const char *filename = qdict_get_str(options, "filename");
 
@@ -1381,8 +1395,11 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
     }
 #endif
 
-    ret = raw_open_common(bs, options, flags, 0);
+    ret = raw_open_common(bs, options, flags, 0, &local_err);
     if (ret < 0) {
+        if (error_is_set(&local_err)) {
+            error_propagate(errp, local_err);
+        }
         return ret;
     }
 
@@ -1390,6 +1407,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
         ret = check_hdev_writable(s);
         if (ret < 0) {
             raw_close(bs);
+            error_setg_errno(errp, -ret, "The device is not writable");
             return ret;
         }
     }
@@ -1525,15 +1543,23 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options,
     }
 
     fd = qemu_open(filename, O_WRONLY | O_BINARY);
-    if (fd < 0)
-        return -errno;
+    if (fd < 0) {
+        ret = -errno;
+        error_setg_errno(errp, -ret, "Could not open device");
+        return ret;
+    }
 
-    if (fstat(fd, &stat_buf) < 0)
+    if (fstat(fd, &stat_buf) < 0) {
         ret = -errno;
-    else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode))
+        error_setg_errno(errp, -ret, "Could not stat device");
+    } else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode)) {
+        error_setg(errp,
+                   "The given file is neither a block nor a character device");
         ret = -ENODEV;
-    else if (lseek(fd, 0, SEEK_END) < total_size * BDRV_SECTOR_SIZE)
+    } else if (lseek(fd, 0, SEEK_END) < total_size * BDRV_SECTOR_SIZE) {
+        error_setg(errp, "Device is too small");
         ret = -ENOSPC;
+    }
 
     qemu_close(fd);
     return ret;
@@ -1575,14 +1601,19 @@ static int floppy_open(BlockDriverState *bs, QDict *options, int flags,
                        Error **errp)
 {
     BDRVRawState *s = bs->opaque;
+    Error *local_err = NULL;
     int ret;
 
     s->type = FTYPE_FD;
 
     /* open will not fail even if no floppy is inserted, so add O_NONBLOCK */
-    ret = raw_open_common(bs, options, flags, O_NONBLOCK);
-    if (ret)
+    ret = raw_open_common(bs, options, flags, O_NONBLOCK, &local_err);
+    if (ret) {
+        if (error_is_set(&local_err)) {
+            error_propagate(errp, local_err);
+        }
         return ret;
+    }
 
     /* close fd so that we can reopen it as needed */
     qemu_close(s->fd);
@@ -1698,11 +1729,17 @@ static int cdrom_open(BlockDriverState *bs, QDict *options, int flags,
                       Error **errp)
 {
     BDRVRawState *s = bs->opaque;
+    Error *local_err = NULL;
+    int ret;
 
     s->type = FTYPE_CD;
 
     /* open will not fail even if no CD is inserted, so add O_NONBLOCK */
-    return raw_open_common(bs, options, flags, O_NONBLOCK);
+    ret = raw_open_common(bs, options, flags, O_NONBLOCK, &local_err);
+    if (error_is_set(&local_err)) {
+        error_propagate(errp, local_err);
+    }
+    return ret;
 }
 
 static int cdrom_probe_device(const char *filename)
@@ -1806,13 +1843,18 @@ static BlockDriver bdrv_host_cdrom = {
 static int cdrom_open(BlockDriverState *bs, QDict *options, int flags)
 {
     BDRVRawState *s = bs->opaque;
+    Error *local_err = NULL;
     int ret;
 
     s->type = FTYPE_CD;
 
-    ret = raw_open_common(bs, options, flags, 0);
-    if (ret)
+    ret = raw_open_common(bs, options, flags, 0, &local_err);
+    if (ret) {
+        if (error_is_set(&local_err)) {
+            error_propagate(errp, local_err);
+        }
         return ret;
+    }
 
     /* make sure the door isn't locked at this time */
     ioctl(s->fd, CDIOCALLOW);
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index 04bb236..e58776a 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -223,6 +223,6 @@ Testing: -drive file=foo:bar
 QEMU_PROG: -drive file=foo:bar: could not open disk image foo:bar: Unknown protocol
 
 Testing: -drive file.filename=foo:bar
-QEMU_PROG: -drive file.filename=foo:bar: could not open disk image ide0-hd0: Could not open 'foo:bar': No such file or directory
+QEMU_PROG: -drive file.filename=foo:bar: could not open disk image ide0-hd0: Could not open file: No such file or directory
 
 *** done
commit 5dd75f9afbea2e4e370c96676d34676e6f6b95b7
Author: Fam Zheng <famz at redhat.com>
Date:   Fri Oct 11 14:59:49 2013 +0800

    qemu-iotests: move blank lines of output in case 059
    
    Move the blank line to above the test step banner, so it looks clearer
    in blocks.
    
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
index dd6addf..18cdad1 100755
--- a/tests/qemu-iotests/059
+++ b/tests/qemu-iotests/059
@@ -47,27 +47,27 @@ capacity_offset=16
 granularity_offset=20
 grain_table_size_offset=44
 
-echo "=== Testing invalid granularity ==="
 echo
+echo "=== Testing invalid granularity ==="
 _make_test_img 64M
 poke_file "$TEST_IMG" "$granularity_offset" "\xff\xff\xff\xff\xff\xff\xff\xff"
 { $QEMU_IO -c "read 0 512" "$TEST_IMG"; } 2>&1 | _filter_qemu_io | _filter_testdir
 
-echo "=== Testing too big L2 table size ==="
 echo
+echo "=== Testing too big L2 table size ==="
 _make_test_img 64M
 poke_file "$TEST_IMG" "$grain_table_size_offset" "\xff\xff\xff\xff"
 { $QEMU_IO -c "read 0 512" "$TEST_IMG"; } 2>&1 | _filter_qemu_io | _filter_testdir
 
-echo "=== Testing too big L1 table size ==="
 echo
+echo "=== Testing too big L1 table size ==="
 _make_test_img 64M
 poke_file "$TEST_IMG" "$capacity_offset" "\xff\xff\xff\xff"
 poke_file "$TEST_IMG" "$grain_table_size_offset" "\x01\x00\x00\x00"
 { $QEMU_IO -c "read 0 512" "$TEST_IMG"; } 2>&1 | _filter_qemu_io | _filter_testdir
 
-echo "=== Testing monolithicFlat creation and opening ==="
 echo
+echo "=== Testing monolithicFlat creation and opening ==="
 IMGOPTS="subformat=monolithicFlat" _make_test_img 2G
 $QEMU_IMG info $TEST_IMG | _filter_testdir
 
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
index 9159dbe..21de6e7 100644
--- a/tests/qemu-iotests/059.out
+++ b/tests/qemu-iotests/059.out
@@ -1,24 +1,24 @@
 QA output created by 059
-=== Testing invalid granularity ===
 
+=== Testing invalid granularity ===
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
 invalid granularity, image may be corrupt
 qemu-io: can't open device TEST_DIR/t.vmdk: Could not open 'TEST_DIR/t.vmdk': Wrong medium type
 no file open, try 'help open'
-=== Testing too big L2 table size ===
 
+=== Testing too big L2 table size ===
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
 L2 table size too big
 qemu-io: can't open device TEST_DIR/t.vmdk: Could not open 'TEST_DIR/t.vmdk': Wrong medium type
 no file open, try 'help open'
-=== Testing too big L1 table size ===
 
+=== Testing too big L1 table size ===
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
 L1 size too big
 qemu-io: can't open device TEST_DIR/t.vmdk: Could not open 'TEST_DIR/t.vmdk': Wrong medium type
 no file open, try 'help open'
-=== Testing monolithicFlat creation and opening ===
 
+=== Testing monolithicFlat creation and opening ===
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648
 image: TEST_DIR/t.vmdk
 file format: vmdk
commit ca2884087a36c60d592aa0e8e327bf1579972077
Author: Max Reitz <mreitz at redhat.com>
Date:   Thu Oct 10 15:44:04 2013 +0200

    blkverify: Employ error parameter
    
    Make use of the error parameter in blkverify_open.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/blkverify.c b/block/blkverify.c
index 1e8e6d9..3c63528 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -128,8 +128,7 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
     opts = qemu_opts_create_nofail(&runtime_opts);
     qemu_opts_absorb_qdict(opts, options, &local_err);
     if (error_is_set(&local_err)) {
-        qerror_report_err(local_err);
-        error_free(local_err);
+        error_propagate(errp, local_err);
         ret = -EINVAL;
         goto fail;
     }
@@ -137,20 +136,21 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
     /* Parse the raw image filename */
     raw = qemu_opt_get(opts, "x-raw");
     if (raw == NULL) {
+        error_setg(errp, "Could not retrieve raw image filename");
         ret = -EINVAL;
         goto fail;
     }
 
     ret = bdrv_file_open(&bs->file, raw, NULL, flags, &local_err);
     if (ret < 0) {
-        qerror_report_err(local_err);
-        error_free(local_err);
+        error_propagate(errp, local_err);
         goto fail;
     }
 
     /* Open the test file */
     filename = qemu_opt_get(opts, "x-image");
     if (filename == NULL) {
+        error_setg(errp, "Could not retrieve test image filename");
         ret = -EINVAL;
         goto fail;
     }
@@ -158,8 +158,7 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
     s->test_file = bdrv_new("");
     ret = bdrv_open(s->test_file, filename, NULL, flags, NULL, &local_err);
     if (ret < 0) {
-        qerror_report_err(local_err);
-        error_free(local_err);
+        error_propagate(errp, local_err);
         bdrv_unref(s->test_file);
         s->test_file = NULL;
         goto fail;
commit 10ffa72faed7e02805d7911d58d429efe6f95f93
Author: Max Reitz <mreitz at redhat.com>
Date:   Thu Oct 10 15:44:03 2013 +0200

    blkdebug: Employ error parameter
    
    Make use of the error parameter in blkdebug_open.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/blkdebug.c b/block/blkdebug.c
index be948b2..16d2b91 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -362,8 +362,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
     opts = qemu_opts_create_nofail(&runtime_opts);
     qemu_opts_absorb_qdict(opts, options, &local_err);
     if (error_is_set(&local_err)) {
-        qerror_report_err(local_err);
-        error_free(local_err);
+        error_propagate(errp, local_err);
         ret = -EINVAL;
         goto fail;
     }
@@ -373,6 +372,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
     if (config) {
         ret = read_config(s, config);
         if (ret < 0) {
+            error_setg_errno(errp, -ret, "Could not read blkdebug config file");
             goto fail;
         }
     }
@@ -383,14 +383,14 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
     /* Open the backing file */
     filename = qemu_opt_get(opts, "x-image");
     if (filename == NULL) {
+        error_setg(errp, "Could not retrieve image file name");
         ret = -EINVAL;
         goto fail;
     }
 
     ret = bdrv_file_open(&bs->file, filename, NULL, flags, &local_err);
     if (ret < 0) {
-        qerror_report_err(local_err);
-        error_free(local_err);
+        error_propagate(errp, local_err);
         goto fail;
     }
 
commit c6252b7cea0dfa893cf1f49de3a58f222e910783
Author: Max Reitz <mreitz at redhat.com>
Date:   Thu Oct 10 15:44:02 2013 +0200

    block/raw-win32: Employ error parameter
    
    Make use of the error parameter in the opening and creating functions in
    block/raw-win32.c.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/raw-win32.c b/block/raw-win32.c
index 6ef320f..c3e4c62 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -251,8 +251,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
     opts = qemu_opts_create_nofail(&raw_runtime_opts);
     qemu_opts_absorb_qdict(opts, options, &local_err);
     if (error_is_set(&local_err)) {
-        qerror_report_err(local_err);
-        error_free(local_err);
+        error_propagate(errp, local_err);
         ret = -EINVAL;
         goto fail;
     }
@@ -264,6 +263,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
     if ((flags & BDRV_O_NATIVE_AIO) && aio == NULL) {
         aio = win32_aio_init();
         if (aio == NULL) {
+            error_setg(errp, "Could not initialize AIO");
             ret = -EINVAL;
             goto fail;
         }
@@ -280,6 +280,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
         } else {
             ret = -EINVAL;
         }
+        error_setg_errno(errp, -ret, "Could not open file");
         goto fail;
     }
 
@@ -287,6 +288,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
         ret = win32_aio_attach(aio, s->hfile);
         if (ret < 0) {
             CloseHandle(s->hfile);
+            error_setg_errno(errp, -ret, "Could not enable AIO");
             goto fail;
         }
         s->aio = aio;
@@ -438,8 +440,10 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
 
     fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
                    0644);
-    if (fd < 0)
+    if (fd < 0) {
+        error_setg_errno(errp, errno, "Could not create file");
         return -EIO;
+    }
     set_sparse(fd);
     ftruncate(fd, total_size * 512);
     qemu_close(fd);
@@ -550,8 +554,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
     QemuOpts *opts = qemu_opts_create_nofail(&raw_runtime_opts);
     qemu_opts_absorb_qdict(opts, options, &local_err);
     if (error_is_set(&local_err)) {
-        qerror_report_err(local_err);
-        error_free(local_err);
+        error_propagate(errp, local_err);
         ret = -EINVAL;
         goto done;
     }
@@ -560,6 +563,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
 
     if (strstart(filename, "/dev/cdrom", NULL)) {
         if (find_cdrom(device_name, sizeof(device_name)) < 0) {
+            error_setg(errp, "Could not open CD-ROM drive");
             ret = -ENOENT;
             goto done;
         }
@@ -586,8 +590,10 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
         int err = GetLastError();
 
         if (err == ERROR_ACCESS_DENIED) {
+            error_setg_errno(errp, EACCES, "Could not open device");
             ret = -EACCES;
         } else {
+            error_setg(errp, "Could not open device");
             ret = -1;
         }
         goto done;
commit 92f1deec317230575726a8e0ab5c110781d30ec0
Author: Max Reitz <mreitz at redhat.com>
Date:   Thu Oct 10 15:44:00 2013 +0200

    block/raw_bsd: Employ error parameter
    
    Propagate errors in raw_create rather than directly reporting and
    afterwards discarding them.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/raw_bsd.c b/block/raw_bsd.c
index d61906b..0078c1b 100644
--- a/block/raw_bsd.c
+++ b/block/raw_bsd.c
@@ -140,8 +140,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
 
     ret = bdrv_create_file(filename, options, &local_err);
     if (error_is_set(&local_err)) {
-        qerror_report_err(local_err);
-        error_free(local_err);
+        error_propagate(errp, local_err);
     }
     return ret;
 }
commit 1fa5cc839aa6068c9182ad8d611f844c58f95f42
Author: Max Reitz <mreitz at redhat.com>
Date:   Thu Oct 10 11:09:28 2013 +0200

    qcow2: Evaluate overlap check options
    
    Evaluate the runtime overlap check options and set
    BDRVQcowState.overlap_check appropriately.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index eee7eaf..c1abaff 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -425,6 +425,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
     Error *local_err = NULL;
     uint64_t ext_end;
     uint64_t l1_vm_state_index;
+    const char *opt_overlap_check;
+    int overlap_check_template = 0;
 
     ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
     if (ret < 0) {
@@ -688,7 +690,32 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
     s->discard_passthrough[QCOW2_DISCARD_OTHER] =
         qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false);
 
-    s->overlap_check = QCOW2_OL_CACHED;
+    opt_overlap_check = qemu_opt_get(opts, "overlap-check") ?: "cached";
+    if (!strcmp(opt_overlap_check, "none")) {
+        overlap_check_template = 0;
+    } else if (!strcmp(opt_overlap_check, "constant")) {
+        overlap_check_template = QCOW2_OL_CONSTANT;
+    } else if (!strcmp(opt_overlap_check, "cached")) {
+        overlap_check_template = QCOW2_OL_CACHED;
+    } else if (!strcmp(opt_overlap_check, "all")) {
+        overlap_check_template = QCOW2_OL_ALL;
+    } else {
+        error_setg(errp, "Unsupported value '%s' for qcow2 option "
+                   "'overlap-check'. Allowed are either of the following: "
+                   "none, constant, cached, all", opt_overlap_check);
+        qemu_opts_del(opts);
+        ret = -EINVAL;
+        goto fail;
+    }
+
+    s->overlap_check = 0;
+    for (i = 0; i < QCOW2_OL_MAX_BITNR; i++) {
+        /* overlap-check defines a template bitmask, but every flag may be
+         * overwritten through the associated boolean option */
+        s->overlap_check |=
+            qemu_opt_get_bool(opts, overlap_bool_option_names[i],
+                              overlap_check_template & (1 << i)) << i;
+    }
 
     qemu_opts_del(opts);
 
commit 4a273c398b0c96985d56fed8156e19876b2e3c9e
Author: Max Reitz <mreitz at redhat.com>
Date:   Thu Oct 10 11:09:27 2013 +0200

    qcow2: Add more overlap check bitmask macros
    
    Introduces the macros QCOW2_OL_CONSTANT and QCOW2_OL_ALL in addition to
    the already existing QCOW2_OL_CACHED, signifying all metadata overlap
    checks that can be performed in constant time (regardless of image size
    etc.) and truly all available overlap checks, respectively.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2.h b/block/qcow2.h
index 28ccc4a..922e190 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -326,11 +326,19 @@ typedef enum QCow2MetadataOverlap {
     QCOW2_OL_INACTIVE_L2    = (1 << QCOW2_OL_INACTIVE_L2_BITNR),
 } QCow2MetadataOverlap;
 
+/* Perform all overlap checks which can be done in constant time */
+#define QCOW2_OL_CONSTANT \
+    (QCOW2_OL_MAIN_HEADER | QCOW2_OL_ACTIVE_L1 | QCOW2_OL_REFCOUNT_TABLE | \
+     QCOW2_OL_SNAPSHOT_TABLE)
+
 /* Perform all overlap checks which don't require disk access */
 #define QCOW2_OL_CACHED \
-    (QCOW2_OL_MAIN_HEADER | QCOW2_OL_ACTIVE_L1 | QCOW2_OL_ACTIVE_L2 | \
-     QCOW2_OL_REFCOUNT_TABLE | QCOW2_OL_REFCOUNT_BLOCK | \
-     QCOW2_OL_SNAPSHOT_TABLE | QCOW2_OL_INACTIVE_L1)
+    (QCOW2_OL_CONSTANT | QCOW2_OL_ACTIVE_L2 | QCOW2_OL_REFCOUNT_BLOCK | \
+     QCOW2_OL_INACTIVE_L1)
+
+/* Perform all overlap checks */
+#define QCOW2_OL_ALL \
+    (QCOW2_OL_CACHED | QCOW2_OL_INACTIVE_L2)
 
 #define L1E_OFFSET_MASK 0x00ffffffffffff00ULL
 #define L2E_OFFSET_MASK 0x00ffffffffffff00ULL
commit 4092e99d935fe26fd53631cc9e170f9a19e3ee4a
Author: Max Reitz <mreitz at redhat.com>
Date:   Thu Oct 10 11:09:26 2013 +0200

    qcow2: Array assigning options to OL check bits
    
    Add an array which assigns the option string to its corresponding
    overlap check bit.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index a517e3d..eee7eaf 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -404,6 +404,17 @@ static QemuOptsList qcow2_runtime_opts = {
     },
 };
 
+static const char *overlap_bool_option_names[QCOW2_OL_MAX_BITNR] = {
+    [QCOW2_OL_MAIN_HEADER_BITNR]    = QCOW2_OPT_OVERLAP_MAIN_HEADER,
+    [QCOW2_OL_ACTIVE_L1_BITNR]      = QCOW2_OPT_OVERLAP_ACTIVE_L1,
+    [QCOW2_OL_ACTIVE_L2_BITNR]      = QCOW2_OPT_OVERLAP_ACTIVE_L2,
+    [QCOW2_OL_REFCOUNT_TABLE_BITNR] = QCOW2_OPT_OVERLAP_REFCOUNT_TABLE,
+    [QCOW2_OL_REFCOUNT_BLOCK_BITNR] = QCOW2_OPT_OVERLAP_REFCOUNT_BLOCK,
+    [QCOW2_OL_SNAPSHOT_TABLE_BITNR] = QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE,
+    [QCOW2_OL_INACTIVE_L1_BITNR]    = QCOW2_OPT_OVERLAP_INACTIVE_L1,
+    [QCOW2_OL_INACTIVE_L2_BITNR]    = QCOW2_OPT_OVERLAP_INACTIVE_L2,
+};
+
 static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
                       Error **errp)
 {
commit 05de7e86cab3ed3830de38b38b39bbc711bc1158
Author: Max Reitz <mreitz at redhat.com>
Date:   Thu Oct 10 11:09:25 2013 +0200

    qcow2: Add overlap-check options
    
    Add runtime options to tune the overlap checks to be performed before
    write accesses.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 46acca7..a517e3d 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -354,6 +354,52 @@ static QemuOptsList qcow2_runtime_opts = {
             .type = QEMU_OPT_BOOL,
             .help = "Generate discard requests when other clusters are freed",
         },
+        {
+            .name = QCOW2_OPT_OVERLAP,
+            .type = QEMU_OPT_STRING,
+            .help = "Selects which overlap checks to perform from a range of "
+                    "templates (none, constant, cached, all)",
+        },
+        {
+            .name = QCOW2_OPT_OVERLAP_MAIN_HEADER,
+            .type = QEMU_OPT_BOOL,
+            .help = "Check for unintended writes into the main qcow2 header",
+        },
+        {
+            .name = QCOW2_OPT_OVERLAP_ACTIVE_L1,
+            .type = QEMU_OPT_BOOL,
+            .help = "Check for unintended writes into the active L1 table",
+        },
+        {
+            .name = QCOW2_OPT_OVERLAP_ACTIVE_L2,
+            .type = QEMU_OPT_BOOL,
+            .help = "Check for unintended writes into an active L2 table",
+        },
+        {
+            .name = QCOW2_OPT_OVERLAP_REFCOUNT_TABLE,
+            .type = QEMU_OPT_BOOL,
+            .help = "Check for unintended writes into the refcount table",
+        },
+        {
+            .name = QCOW2_OPT_OVERLAP_REFCOUNT_BLOCK,
+            .type = QEMU_OPT_BOOL,
+            .help = "Check for unintended writes into a refcount block",
+        },
+        {
+            .name = QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE,
+            .type = QEMU_OPT_BOOL,
+            .help = "Check for unintended writes into the snapshot table",
+        },
+        {
+            .name = QCOW2_OPT_OVERLAP_INACTIVE_L1,
+            .type = QEMU_OPT_BOOL,
+            .help = "Check for unintended writes into an inactive L1 table",
+        },
+        {
+            .name = QCOW2_OPT_OVERLAP_INACTIVE_L2,
+            .type = QEMU_OPT_BOOL,
+            .help = "Check for unintended writes into an inactive L2 table",
+        },
         { /* end of list */ }
     },
 };
diff --git a/block/qcow2.h b/block/qcow2.h
index 6c85bb9..28ccc4a 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -63,6 +63,15 @@
 #define QCOW2_OPT_DISCARD_REQUEST "pass-discard-request"
 #define QCOW2_OPT_DISCARD_SNAPSHOT "pass-discard-snapshot"
 #define QCOW2_OPT_DISCARD_OTHER "pass-discard-other"
+#define QCOW2_OPT_OVERLAP "overlap-check"
+#define QCOW2_OPT_OVERLAP_MAIN_HEADER "overlap-check.main-header"
+#define QCOW2_OPT_OVERLAP_ACTIVE_L1 "overlap-check.active-l1"
+#define QCOW2_OPT_OVERLAP_ACTIVE_L2 "overlap-check.active-l2"
+#define QCOW2_OPT_OVERLAP_REFCOUNT_TABLE "overlap-check.refcount-table"
+#define QCOW2_OPT_OVERLAP_REFCOUNT_BLOCK "overlap-check.refcount-block"
+#define QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE "overlap-check.snapshot-table"
+#define QCOW2_OPT_OVERLAP_INACTIVE_L1 "overlap-check.inactive-l1"
+#define QCOW2_OPT_OVERLAP_INACTIVE_L2 "overlap-check.inactive-l2"
 
 typedef struct QCowHeader {
     uint32_t magic;
commit 3e3553905cfc814d59de6d1a634c3a991b2a9257
Author: Max Reitz <mreitz at redhat.com>
Date:   Thu Oct 10 11:09:24 2013 +0200

    qcow2: Make overlap check mask variable
    
    Replace the QCOW2_OL_DEFAULT macro by a variable overlap_check in
    BDRVQcowState.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 988644a..1ff43d0 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1649,7 +1649,7 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
                                  int64_t size)
 {
     BDRVQcowState *s = bs->opaque;
-    int chk = QCOW2_OL_DEFAULT & ~ign;
+    int chk = s->overlap_check & ~ign;
     int i, j;
 
     if (!size) {
diff --git a/block/qcow2.c b/block/qcow2.c
index c461471..46acca7 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -631,6 +631,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
     s->discard_passthrough[QCOW2_DISCARD_OTHER] =
         qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false);
 
+    s->overlap_check = QCOW2_OL_CACHED;
+
     qemu_opts_del(opts);
 
     if (s->use_lazy_refcounts && s->qcow_version < 3) {
diff --git a/block/qcow2.h b/block/qcow2.h
index 8692011..6c85bb9 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -203,6 +203,8 @@ typedef struct BDRVQcowState {
 
     bool discard_passthrough[QCOW2_DISCARD_MAX];
 
+    int overlap_check; /* bitmask of Qcow2MetadataOverlap values */
+
     uint64_t incompatible_features;
     uint64_t compatible_features;
     uint64_t autoclear_features;
@@ -321,9 +323,6 @@ typedef enum QCow2MetadataOverlap {
      QCOW2_OL_REFCOUNT_TABLE | QCOW2_OL_REFCOUNT_BLOCK | \
      QCOW2_OL_SNAPSHOT_TABLE | QCOW2_OL_INACTIVE_L1)
 
-/* The default checks to perform */
-#define QCOW2_OL_DEFAULT QCOW2_OL_CACHED
-
 #define L1E_OFFSET_MASK 0x00ffffffffffff00ULL
 #define L2E_OFFSET_MASK 0x00ffffffffffff00ULL
 #define L2E_COMPRESSED_OFFSET_SIZE_MASK 0x3fffffffffffffffULL
commit 231bb267644ee3a9ebfd9c7f42d5d41610194b45
Author: Max Reitz <mreitz at redhat.com>
Date:   Thu Oct 10 11:09:23 2013 +0200

    qcow2: Use negated overflow check mask
    
    In qcow2_check_metadata_overlap and qcow2_pre_write_overlap_check,
    change the parameter signifying the checks to perform from its current
    positive form to a negative one, i.e., it will no longer explicitly
    specify every check to perform but rather a mask of checks not to
    perform.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
index 40a5a3f..8ecbb5b 100644
--- a/block/qcow2-cache.c
+++ b/block/qcow2-cache.c
@@ -115,15 +115,13 @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
     }
 
     if (c == s->refcount_block_cache) {
-        ret = qcow2_pre_write_overlap_check(bs,
-                QCOW2_OL_DEFAULT & ~QCOW2_OL_REFCOUNT_BLOCK,
+        ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_REFCOUNT_BLOCK,
                 c->entries[i].offset, s->cluster_size);
     } else if (c == s->l2_table_cache) {
-        ret = qcow2_pre_write_overlap_check(bs,
-                QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L2,
+        ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L2,
                 c->entries[i].offset, s->cluster_size);
     } else {
-        ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
+        ret = qcow2_pre_write_overlap_check(bs, 0,
                 c->entries[i].offset, s->cluster_size);
     }
 
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 0fd26bb..0348b97 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -83,8 +83,8 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
 
     /* the L1 position has not yet been updated, so these clusters must
      * indeed be completely free */
-    ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
-                                        new_l1_table_offset, new_l1_size2);
+    ret = qcow2_pre_write_overlap_check(bs, 0, new_l1_table_offset,
+                                        new_l1_size2);
     if (ret < 0) {
         goto fail;
     }
@@ -160,8 +160,7 @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
         buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]);
     }
 
-    ret = qcow2_pre_write_overlap_check(bs,
-            QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L1,
+    ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L1,
             s->l1_table_offset + 8 * l1_start_index, sizeof(buf));
     if (ret < 0) {
         return ret;
@@ -396,7 +395,7 @@ static int coroutine_fn copy_sectors(BlockDriverState *bs,
                         &s->aes_encrypt_key);
     }
 
-    ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
+    ret = qcow2_pre_write_overlap_check(bs, 0,
             cluster_offset + n_start * BDRV_SECTOR_SIZE, n * BDRV_SECTOR_SIZE);
     if (ret < 0) {
         goto out;
@@ -1604,8 +1603,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
                 }
             }
 
-            ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
-                                                offset, s->cluster_size);
+            ret = qcow2_pre_write_overlap_check(bs, 0, offset, s->cluster_size);
             if (ret < 0) {
                 if (!preallocated) {
                     qcow2_free_clusters(bs, offset, s->cluster_size,
@@ -1661,8 +1659,8 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
             }
         } else {
             if (l2_dirty) {
-                ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT &
-                        ~(QCOW2_OL_INACTIVE_L2 | QCOW2_OL_ACTIVE_L2), l2_offset,
+                ret = qcow2_pre_write_overlap_check(bs,
+                        QCOW2_OL_INACTIVE_L2 | QCOW2_OL_ACTIVE_L2, l2_offset,
                         s->cluster_size);
                 if (ret < 0) {
                     goto fail;
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 4ef6899..988644a 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1311,9 +1311,8 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
         }
 
         if (l2_dirty) {
-            ret = qcow2_pre_write_overlap_check(bs,
-                    QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L2, l2_offset,
-                    s->cluster_size);
+            ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L2,
+                                                l2_offset, s->cluster_size);
             if (ret < 0) {
                 fprintf(stderr, "ERROR: Could not write L2 table; metadata "
                         "overlap check failed: %s\n", strerror(-ret));
@@ -1354,8 +1353,7 @@ static int write_reftable_entry(BlockDriverState *bs, int rt_index)
         buf[i] = cpu_to_be64(s->refcount_table[rt_start_index + i]);
     }
 
-    ret = qcow2_pre_write_overlap_check(bs,
-            QCOW2_OL_DEFAULT & ~QCOW2_OL_REFCOUNT_TABLE,
+    ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_REFCOUNT_TABLE,
             s->refcount_table_offset + rt_start_index * sizeof(uint64_t),
             sizeof(buf));
     if (ret < 0) {
@@ -1406,8 +1404,7 @@ static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index,
 
     /* new block has not yet been entered into refcount table, therefore it is
      * no refcount block yet (regarding this check) */
-    ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, new_offset,
-            s->cluster_size);
+    ret = qcow2_pre_write_overlap_check(bs, 0, new_offset, s->cluster_size);
     if (ret < 0) {
         fprintf(stderr, "Could not write refcount block; metadata overlap "
                 "check failed: %s\n", strerror(-ret));
@@ -1639,8 +1636,8 @@ fail:
  * looking for overlaps with important metadata sections (L1/L2 tables etc.),
  * i.e. a sanity check without relying on the refcount tables.
  *
- * The chk parameter specifies exactly what checks to perform (being a bitmask
- * of QCow2MetadataOverlap values).
+ * The ign parameter specifies what checks not to perform (being a bitmask of
+ * QCow2MetadataOverlap values), i.e., what sections to ignore.
  *
  * Returns:
  * - 0 if writing to this offset will not affect the mentioned metadata
@@ -1648,10 +1645,11 @@ fail:
  * - a negative value (-errno) indicating an error while performing a check,
  *   e.g. when bdrv_read failed on QCOW2_OL_INACTIVE_L2
  */
-int qcow2_check_metadata_overlap(BlockDriverState *bs, int chk, int64_t offset,
+int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
                                  int64_t size)
 {
     BDRVQcowState *s = bs->opaque;
+    int chk = QCOW2_OL_DEFAULT & ~ign;
     int i, j;
 
     if (!size) {
@@ -1767,10 +1765,10 @@ static const char *metadata_ol_names[] = {
  * Returns 0 if there were neither overlaps nor errors while checking for
  * overlaps; or a negative value (-errno) on error.
  */
-int qcow2_pre_write_overlap_check(BlockDriverState *bs, int chk, int64_t offset,
+int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
                                   int64_t size)
 {
-    int ret = qcow2_check_metadata_overlap(bs, chk, offset, size);
+    int ret = qcow2_check_metadata_overlap(bs, ign, offset, size);
 
     if (ret < 0) {
         return ret;
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 884b06d..3529c68 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -192,8 +192,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
 
     /* The snapshot list position has not yet been updated, so these clusters
      * must indeed be completely free */
-    ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, offset,
-                                        snapshots_size);
+    ret = qcow2_pre_write_overlap_check(bs, 0, offset, snapshots_size);
     if (ret < 0) {
         goto fail;
     }
@@ -395,8 +394,8 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
         l1_table[i] = cpu_to_be64(s->l1_table[i]);
     }
 
-    ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
-            sn->l1_table_offset, s->l1_size * sizeof(uint64_t));
+    ret = qcow2_pre_write_overlap_check(bs, 0, sn->l1_table_offset,
+                                        s->l1_size * sizeof(uint64_t));
     if (ret < 0) {
         goto fail;
     }
@@ -521,9 +520,8 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
         goto fail;
     }
 
-    ret = qcow2_pre_write_overlap_check(bs,
-            QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L1,
-            s->l1_table_offset, cur_l1_bytes);
+    ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L1,
+                                        s->l1_table_offset, cur_l1_bytes);
     if (ret < 0) {
         goto fail;
     }
diff --git a/block/qcow2.c b/block/qcow2.c
index 3d1e74d..c461471 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -965,7 +965,7 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
                 cur_nr_sectors * 512);
         }
 
-        ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
+        ret = qcow2_pre_write_overlap_check(bs, 0,
                 cluster_offset + index_in_cluster * BDRV_SECTOR_SIZE,
                 cur_nr_sectors * BDRV_SECTOR_SIZE);
         if (ret < 0) {
@@ -1751,8 +1751,7 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num,
         }
         cluster_offset &= s->cluster_offset_mask;
 
-        ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
-                cluster_offset, out_len);
+        ret = qcow2_pre_write_overlap_check(bs, 0, cluster_offset, out_len);
         if (ret < 0) {
             goto fail;
         }
diff --git a/block/qcow2.h b/block/qcow2.h
index 455e38d..8692011 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -433,9 +433,9 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
 
 void qcow2_process_discards(BlockDriverState *bs, int ret);
 
-int qcow2_check_metadata_overlap(BlockDriverState *bs, int chk, int64_t offset,
+int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
                                  int64_t size);
-int qcow2_pre_write_overlap_check(BlockDriverState *bs, int chk, int64_t offset,
+int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
                                   int64_t size);
 
 /* qcow2-cluster.c functions */
commit 8f94a6e40e46cbc8e8014da825d25824b1803b34
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Oct 10 11:45:55 2013 +0200

    block: Improve driver whitelist checks
    
    The main intent of this patch is to consolidate the whitelist checks to
    a single point in the code instead of spreading it everywhere. This adds
    a nicer error message for read-only whitelisting, too, in places where
    it was still missing.
    
    The patch also contains a bonus bug fix: By finding the format first in
    bdrv_open() and then independently checking against the whitelist only
    later, we avoid the case that use of a non-whitelisted format results in
    probing rather than an error message. Previously, this could happen when
    using the driver=... option.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Fam Zheng <famz at redhat.com>

diff --git a/block.c b/block.c
index beea027..84c0eac 100644
--- a/block.c
+++ b/block.c
@@ -769,7 +769,11 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
     bs->read_only = !(open_flags & BDRV_O_RDWR);
 
     if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, bs->read_only)) {
-        error_setg(errp, "Driver '%s' is not whitelisted", drv->format_name);
+        error_setg(errp,
+                   !bs->read_only && bdrv_is_whitelisted(drv, true)
+                        ? "Driver '%s' can only be used for read-only devices"
+                        : "Driver '%s' is not whitelisted",
+                   drv->format_name);
         return -ENOTSUP;
     }
 
@@ -881,7 +885,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
     /* Find the right block driver */
     drvname = qdict_get_try_str(options, "driver");
     if (drvname) {
-        drv = bdrv_find_whitelisted_format(drvname, !(flags & BDRV_O_RDWR));
+        drv = bdrv_find_format(drvname);
         if (!drv) {
             error_setg(errp, "Unknown driver '%s'", drvname);
         }
@@ -1123,7 +1127,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
     /* Find the right image format driver */
     drvname = qdict_get_try_str(options, "driver");
     if (drvname) {
-        drv = bdrv_find_whitelisted_format(drvname, !(flags & BDRV_O_RDWR));
+        drv = bdrv_find_format(drvname);
         qdict_del(options, "driver");
     }
 
diff --git a/blockdev.c b/blockdev.c
index a91d5a8..ab79df7 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -468,13 +468,9 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts,
             return NULL;
         }
 
-        drv = bdrv_find_whitelisted_format(buf, ro);
+        drv = bdrv_find_format(buf);
         if (!drv) {
-            if (!ro && bdrv_find_whitelisted_format(buf, !ro)) {
-                error_report("'%s' can be only used as read-only device.", buf);
-            } else {
-                error_report("'%s' invalid format", buf);
-            }
+            error_report("'%s' invalid format", buf);
             return NULL;
         }
     }
commit 00c49b21e7af1dd8d2167c1b019619ac186dad14
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 9 14:42:47 2013 +0200

    qcow2: Use better type for numerical snapshot ID
    
    When trying to find a new snapshot ID, the existing ones are converted
    to integers using strtoul. This function returns an unsigned long,
    therefore its result should be saved in an unsigned long as well.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index fe7e14c..884b06d 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -292,7 +292,8 @@ static void find_new_snapshot_id(BlockDriverState *bs,
 {
     BDRVQcowState *s = bs->opaque;
     QCowSnapshot *sn;
-    int i, id, id_max = 0;
+    int i;
+    unsigned long id, id_max = 0;
 
     for(i = 0; i < s->nb_snapshots; i++) {
         sn = s->snapshots + i;
@@ -300,7 +301,7 @@ static void find_new_snapshot_id(BlockDriverState *bs,
         if (id > id_max)
             id_max = id;
     }
-    snprintf(id_str, id_str_size, "%d", id_max + 1);
+    snprintf(id_str, id_str_size, "%lu", id_max + 1);
 }
 
 static int find_snapshot_by_id_and_name(BlockDriverState *bs,
commit 84757f7e67cda3df8b04e06fbdeecc266415d2f3
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 9 14:42:00 2013 +0200

    qcow2: Fix snapshot restoration in snapshot_create
    
    If the new snapshot table could not be written in qcow2_snapshot_create,
    the old snapshot table has to be restored in memory and the new one
    released. This should include restoration of the old snapshot count as
    well, which is added by this patch.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 812dab2..fe7e14c 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -433,6 +433,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     if (ret < 0) {
         g_free(s->snapshots);
         s->snapshots = old_snapshot_list;
+        s->nb_snapshots--;
         goto fail;
     }
 
commit f9bff971436b5924ca3c3203c6a3dcd6437bd430
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 9 14:41:28 2013 +0200

    qcow2: Remove wrong metadata overlap check
    
    In qcow2_write_compressed, if the compression fails, a normal cluster is
    written to disk. This is done through bdrv_write on the qcow2 BDS
    itself (using the guest offset), thus it is wrong to do a metadata
    overlap check before.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 9095f7c..3d1e74d 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1738,14 +1738,6 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num,
 
     if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
         /* could not compress: write normal cluster */
-
-        ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
-                sector_num * BDRV_SECTOR_SIZE,
-                s->cluster_sectors * BDRV_SECTOR_SIZE);
-        if (ret < 0) {
-            goto fail;
-        }
-
         ret = bdrv_write(bs, sector_num, buf, s->cluster_sectors);
         if (ret < 0) {
             goto fail;
commit 9e3f08923a14ba0655c6797edd9ffef44bb8cbf2
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 9 14:40:48 2013 +0200

    qcow2: Add missing space in error message
    
    The error message in qcow2_downgrade about an unsupported refcount
    order is missing a space. This patch adds it.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index e8d2735..9095f7c 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1915,7 +1915,7 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version)
          * support anything different than 4 anyway, there is no point in doing
          * so right now; however, we should error out (if qemu supports this in
          * the future and this code has not been adapted) */
-        error_report("qcow2_downgrade: Image refcount orders other than 4 are"
+        error_report("qcow2_downgrade: Image refcount orders other than 4 are "
                      "currently not supported.");
         return -ENOTSUP;
     }
commit 89e911816a1d5cdbc9480d5464c571d216cf5ea8
Author: Jeff Cody <jcody at redhat.com>
Date:   Fri Sep 27 08:48:15 2013 -0400

    block: qemu-iotests for vhdx, read sample dynamic image
    
    This adds the VHDX format to the qemu-iotests format, and adds
    a read test.  The test reads from an existing sample image, that
    was created with Hyper-V under Windwos Server 2012.
    
    The image file is a 1GB dynamic image, with 32MB blocks.
    
    The pattern 0xa5 exists from 0MB-33MB (past a block size boundary)
    
    The pattern 0x96 exists from 33MB-66MB (past another block boundary,
    and leaving a partial blank block)
    
    From 66MB-1024MB, all reads should return 0.
    
    Although 1GB dynamic image with 66MB of data, the bzip2'ed image
    file size is only 874 bytes.
    
    This also adds in the IMGFMT_GENERIC flag, so r/o images can be
    tested (e.g. ./check -vhdx) without failing tests that assume
    r/w support.
    
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/064 b/tests/qemu-iotests/064
new file mode 100755
index 0000000..6789aa6
--- /dev/null
+++ b/tests/qemu-iotests/064
@@ -0,0 +1,62 @@
+#!/bin/bash
+#
+# Test VHDX read/write from a sample image created with Hyper-V
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=jcody at redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+_cleanup()
+{
+    _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt vhdx
+_supported_proto generic
+_supported_os Linux
+
+_use_sample_img iotest-dynamic-1G.vhdx.bz2
+
+echo
+echo "=== Verify pattern 0xa5, 0 - 33MB ==="
+$QEMU_IO -r -c "read -pP 0xa5 0 33M" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "=== Verify pattern 0x96, 33M - 66M ==="
+$QEMU_IO -r -c "read -pP 0x96 33M 33M" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "=== Verify pattern 0x00, 66M - 1024M ==="
+$QEMU_IO -r -c "read -pP 0x00 66M 958M" "$TEST_IMG" | _filter_qemu_io
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/064.out b/tests/qemu-iotests/064.out
new file mode 100644
index 0000000..b9e8e4a
--- /dev/null
+++ b/tests/qemu-iotests/064.out
@@ -0,0 +1,14 @@
+QA output created by 064
+
+=== Verify pattern 0xa5, 0 - 33MB ===
+read 34603008/34603008 bytes at offset 0
+33 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+=== Verify pattern 0x96, 33M - 66M ===
+read 34603008/34603008 bytes at offset 34603008
+33 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+=== Verify pattern 0x00, 66M - 1024M ===
+read 1004535808/1004535808 bytes at offset 69206016
+958 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+*** done
diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
index fecaf85..2932e14 100644
--- a/tests/qemu-iotests/common
+++ b/tests/qemu-iotests/common
@@ -45,6 +45,7 @@ valgrind=false
 rm -f $tmp.list $tmp.tmp $tmp.sed
 
 export IMGFMT=raw
+export IMGFMT_GENERIC=true
 export IMGPROTO=file
 export IMGOPTS=""
 export QEMU_IO_OPTIONS=""
@@ -133,6 +134,7 @@ check options
     -qed                test qed
     -vdi                test vdi
     -vpc                test vpc
+    -vhdx               test vhdx
     -vmdk               test vmdk
     -rbd                test rbd
     -sheepdog           test sheepdog
@@ -195,6 +197,12 @@ testlist options
             xpand=false
             ;;
 
+        -vhdx)
+            IMGFMT=vhdx
+            xpand=false
+            IMGFMT_GENERIC=false
+            ;;
+
         -rbd)
             IMGPROTO=rbd
             xpand=false
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 227c003..4e82604 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -339,7 +339,7 @@ _fail()
 _supported_fmt()
 {
     for f; do
-        if [ "$f" = "$IMGFMT" -o "$f" = "generic" ]; then
+        if [ "$f" = "$IMGFMT" -o "$f" = "generic" -a "$IMGFMT_GENERIC" = "true" ]; then
             return
         fi
     done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 9c94d14..514bd87 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -69,5 +69,6 @@
 061 rw auto
 062 rw auto
 063 rw auto
+064 rw auto
 065 rw auto
 066 rw auto
diff --git a/tests/qemu-iotests/sample_images/iotest-dynamic-1G.vhdx.bz2 b/tests/qemu-iotests/sample_images/iotest-dynamic-1G.vhdx.bz2
new file mode 100644
index 0000000..77d97a0
Binary files /dev/null and b/tests/qemu-iotests/sample_images/iotest-dynamic-1G.vhdx.bz2 differ
commit 13164591f30ad95ae24f9892cf2caf779271a29b
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun Sep 29 00:09:35 2013 +0300

    ahci: set ahci mode on reset
    
    ATM we set AHCI mode on 1st GHC write.
    Spec says we should set it on reset.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index a71a4ca..a8be62c 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -1198,7 +1198,15 @@ void ahci_reset(AHCIState *s)
     int i;
 
     s->control_regs.irqstatus = 0;
-    s->control_regs.ghc = 0;
+    /* AHCI Enable (AE)
+     * The implementation of this bit is dependent upon the value of the
+     * CAP.SAM bit. If CAP.SAM is '0', then GHC.AE shall be read-write and
+     * shall have a reset value of '0'. If CAP.SAM is '1', then AE shall be
+     * read-only and shall have a reset value of '1'.
+     *
+     * We set HOST_CAP_AHCI so we must enable AHCI at reset.
+     */
+    s->control_regs.ghc = HOST_CTL_AHCI_EN;
 
     for (i = 0; i < s->ports; i++) {
         pr = &s->dev[i].port_regs;
commit 975a93c082452db9aa1397a797ca8f13ba367393
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 9 12:07:33 2013 +0200

    qemu-iotests: Discard preallocated zero clusters
    
    Add a new test case for discarding preallocated zero clusters; doing
    this should not result in any leaks.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/066 b/tests/qemu-iotests/066
new file mode 100755
index 0000000..1c2452b
--- /dev/null
+++ b/tests/qemu-iotests/066
@@ -0,0 +1,63 @@
+#!/bin/bash
+#
+# Test case for discarding preallocated zero clusters in qcow2
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=mreitz at redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+_cleanup()
+{
+	_cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# This tests qocw2-specific low-level functionality
+_supported_fmt qcow2
+_supported_proto generic
+_supported_os Linux
+
+IMGOPTS="compat=1.1"
+IMG_SIZE=64M
+
+echo
+echo "=== Testing snapshotting an image with zero clusters ==="
+echo
+_make_test_img $IMG_SIZE
+# Write some normal clusters, zero them (creating preallocated zero clusters)
+# and discard those
+$QEMU_IO -c "write 0 256k" -c "write -z 0 256k" -c "discard 0 256k" "$TEST_IMG" \
+         | _filter_qemu_io
+# Check the image (there shouldn't be any leaks)
+_check_test_img
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/066.out b/tests/qemu-iotests/066.out
new file mode 100644
index 0000000..9139780
--- /dev/null
+++ b/tests/qemu-iotests/066.out
@@ -0,0 +1,13 @@
+QA output created by 066
+
+=== Testing snapshotting an image with zero clusters ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+wrote 262144/262144 bytes at offset 0
+256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 262144/262144 bytes at offset 0
+256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+discard 262144/262144 bytes at offset 0
+256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+No errors were found on the image.
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index f1a68b0..9c94d14 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -70,3 +70,4 @@
 062 rw auto
 063 rw auto
 065 rw auto
+066 rw auto
commit f6186f49e2c98d91f22027d8c62996df4fcf3f92
Author: Benoît Canet <benoit at irqsave.net>
Date:   Wed Oct 2 14:33:48 2013 +0200

    block: Add BlockDriver.bdrv_check_ext_snapshot.
    
    This field is used by blkverify to disable external snapshots creation.
    It will also be used by block filters like quorum to disable external
    snapshot creation.
    
    Signed-off-by: Benoit Canet <benoit at irqsave.net>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index d86efad..beea027 100644
--- a/block.c
+++ b/block.c
@@ -4647,3 +4647,22 @@ int bdrv_amend_options(BlockDriverState *bs, QEMUOptionParameter *options)
     }
     return bs->drv->bdrv_amend_options(bs, options);
 }
+
+ExtSnapshotPerm bdrv_check_ext_snapshot(BlockDriverState *bs)
+{
+    if (bs->drv->bdrv_check_ext_snapshot) {
+        return bs->drv->bdrv_check_ext_snapshot(bs);
+    }
+
+    if (bs->file && bs->file->drv && bs->file->drv->bdrv_check_ext_snapshot) {
+        return bs->file->drv->bdrv_check_ext_snapshot(bs);
+    }
+
+    /* external snapshots are allowed by default */
+    return EXT_SNAPSHOT_ALLOWED;
+}
+
+ExtSnapshotPerm bdrv_check_ext_snapshot_forbidden(BlockDriverState *bs)
+{
+    return EXT_SNAPSHOT_FORBIDDEN;
+}
diff --git a/block/blkverify.c b/block/blkverify.c
index bff95d2..1e8e6d9 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -417,6 +417,8 @@ static BlockDriver bdrv_blkverify = {
     .bdrv_aio_readv         = blkverify_aio_readv,
     .bdrv_aio_writev        = blkverify_aio_writev,
     .bdrv_aio_flush         = blkverify_aio_flush,
+
+    .bdrv_check_ext_snapshot = bdrv_check_ext_snapshot_forbidden,
 };
 
 static void bdrv_blkverify_init(void)
diff --git a/blockdev.c b/blockdev.c
index 8c83f6f..a91d5a8 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1131,6 +1131,11 @@ static void external_snapshot_prepare(BlkTransactionState *common,
         }
     }
 
+    if (bdrv_check_ext_snapshot(state->old_bs) != EXT_SNAPSHOT_ALLOWED) {
+        error_set(errp, QERR_FEATURE_DISABLED, "snapshot");
+        return;
+    }
+
     flags = state->old_bs->open_flags;
 
     /* create new image w/backing file */
diff --git a/include/block/block.h b/include/block/block.h
index 0d4d5c3..3560deb 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -248,6 +248,20 @@ int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix);
 
 int bdrv_amend_options(BlockDriverState *bs_new, QEMUOptionParameter *options);
 
+/* external snapshots */
+
+typedef enum {
+    EXT_SNAPSHOT_ALLOWED,
+    EXT_SNAPSHOT_FORBIDDEN,
+} ExtSnapshotPerm;
+
+/* return EXT_SNAPSHOT_ALLOWED if external snapshot is allowed
+ * return EXT_SNAPSHOT_FORBIDDEN if external snapshot is forbidden
+ */
+ExtSnapshotPerm bdrv_check_ext_snapshot(BlockDriverState *bs);
+/* helper used to forbid external snapshots like in blkverify */
+ExtSnapshotPerm bdrv_check_ext_snapshot_forbidden(BlockDriverState *bs);
+
 /* async block I/O */
 typedef void BlockDriverDirtyHandler(BlockDriverState *bs, int64_t sector,
                                      int sector_num);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 17b26b2..a48731d 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -67,6 +67,12 @@ typedef struct BdrvTrackedRequest {
 struct BlockDriver {
     const char *format_name;
     int instance_size;
+
+    /* if not defined external snapshots are allowed
+     * future block filters will query their children to build the response
+     */
+    ExtSnapshotPerm (*bdrv_check_ext_snapshot)(BlockDriverState *bs);
+
     int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
     int (*bdrv_probe_device)(const char *filename);
 
commit 92bc50a5ad7fbc9a0bd17240eaea5027a100ca79
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Oct 8 14:43:14 2013 +0200

    block/get_block_status: avoid redundant callouts on raw devices
    
    if a raw device like an iscsi target or host device is used
    the current implementation makes a second call out to get
    the block status of bs->file.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 43acaad..d86efad 100644
--- a/block.c
+++ b/block.c
@@ -3147,6 +3147,12 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
         return ret;
     }
 
+    if (ret & BDRV_BLOCK_RAW) {
+        assert(ret & BDRV_BLOCK_OFFSET_VALID);
+        return bdrv_get_block_status(bs->file, ret >> BDRV_SECTOR_BITS,
+                                     *pnum, pnum);
+    }
+
     if (!(ret & BDRV_BLOCK_DATA)) {
         if (bdrv_has_zero_init(bs)) {
             ret |= BDRV_BLOCK_ZERO;
diff --git a/block/raw_bsd.c b/block/raw_bsd.c
index d4ace60..d61906b 100644
--- a/block/raw_bsd.c
+++ b/block/raw_bsd.c
@@ -62,7 +62,9 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
                                             int64_t sector_num,
                                             int nb_sectors, int *pnum)
 {
-    return bdrv_get_block_status(bs->file, sector_num, nb_sectors, pnum);
+    *pnum = nb_sectors;
+    return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID | BDRV_BLOCK_DATA |
+           (sector_num << BDRV_SECTOR_BITS);
 }
 
 static int coroutine_fn raw_co_write_zeroes(BlockDriverState *bs,
diff --git a/include/block/block.h b/include/block/block.h
index e265124..0d4d5c3 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -84,6 +84,9 @@ typedef struct BlockDevOps {
 /* BDRV_BLOCK_DATA: data is read from bs->file or another file
  * BDRV_BLOCK_ZERO: sectors read as zero
  * BDRV_BLOCK_OFFSET_VALID: sector stored in bs->file as raw data
+ * BDRV_BLOCK_RAW: used internally to indicate that the request
+ *                 was answered by the raw driver and that one
+ *                 should look in bs->file directly.
  *
  * If BDRV_BLOCK_OFFSET_VALID is set, bits 9-62 represent the offset in
  * bs->file where sector data can be read from as raw data.
@@ -105,6 +108,7 @@ typedef struct BlockDevOps {
 #define BDRV_BLOCK_DATA         1
 #define BDRV_BLOCK_ZERO         2
 #define BDRV_BLOCK_OFFSET_VALID 4
+#define BDRV_BLOCK_RAW          8
 #define BDRV_BLOCK_OFFSET_MASK  BDRV_SECTOR_MASK
 
 typedef enum {
commit 88fb15351284868b70fa1d5b101e809057fcc5aa
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 9 10:51:06 2013 +0200

    qcow2: Assert against snapshot name/ID overflow
    
    qcow2_write_snapshots relies on the length of every snapshot ID and name
    fitting into an unsigned 16 bit integer. This is currently ensured by
    QEMU through generally only allowing 128 byte IDs and 256 byte names.
    However, if this should change in the future, the length written to the
    image file should not be silently truncated (though the name itself
    would be written completely).
    
    Since this is currently not an issue but might require attention due to
    internal QEMU changes in the future, an assert ensuring sanity is enough
    for now.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index f6f3e64..812dab2 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -221,6 +221,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
 
         id_str_size = strlen(sn->id_str);
         name_size = strlen(sn->name);
+        assert(id_str_size <= UINT16_MAX && name_size <= UINT16_MAX);
         h.id_str_size = cpu_to_be16(id_str_size);
         h.name_size = cpu_to_be16(name_size);
         offset = align_offset(offset, 8);
commit 9186ad9658cc597937fbc03ad66bceb3a0515d99
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 9 10:51:05 2013 +0200

    qcow2: Free allocated snapshot table on error
    
    If an error occurs during qcow2_write_snapshots, the newly allocated
    snapshot table clusters are leaked and should thus be freed.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 3337974..f6f3e64 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -279,6 +279,10 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
     return 0;
 
 fail:
+    if (snapshots_offset > 0) {
+        qcow2_free_clusters(bs, snapshots_offset, snapshots_size,
+                            QCOW2_DISCARD_ALWAYS);
+    }
     return ret;
 }
 
commit 37d41f0a04e5017d37906728a806d7944e867a2a
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 9 10:51:04 2013 +0200

    qcow2: Always use error path on writing snapshots
    
    qcow2_write_snapshots does contain a fail label and there is no reason
    not to use it on some errors; therefore, we should always jump there on
    error.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 5e8a779..3337974 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -182,11 +182,12 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
     snapshots_offset = qcow2_alloc_clusters(bs, snapshots_size);
     offset = snapshots_offset;
     if (offset < 0) {
-        return offset;
+        ret = offset;
+        goto fail;
     }
     ret = bdrv_flush(bs);
     if (ret < 0) {
-        return ret;
+        goto fail;
     }
 
     /* The snapshot list position has not yet been updated, so these clusters
@@ -194,7 +195,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
     ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, offset,
                                         snapshots_size);
     if (ret < 0) {
-        return ret;
+        goto fail;
     }
 
 
commit 8f730dd24edd2576ecbd596de7ea4361296b129c
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 9 10:44:28 2013 +0200

    qcow2: Free preallocated zero clusters
    
    In qcow2_free_any_clusters, preallocated zero clusters should be freed
    just as normal clusters are.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 4cb9c23..4ef6899 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -796,11 +796,13 @@ void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry,
         }
         break;
     case QCOW2_CLUSTER_NORMAL:
-        qcow2_free_clusters(bs, l2_entry & L2E_OFFSET_MASK,
-                            nb_clusters << s->cluster_bits, type);
+    case QCOW2_CLUSTER_ZERO:
+        if (l2_entry & L2E_OFFSET_MASK) {
+            qcow2_free_clusters(bs, l2_entry & L2E_OFFSET_MASK,
+                                nb_clusters << s->cluster_bits, type);
+        }
         break;
     case QCOW2_CLUSTER_UNALLOCATED:
-    case QCOW2_CLUSTER_ZERO:
         break;
     default:
         abort();
commit 998b959c1e59044f5d5f64c482f4ce8facc8e0bc
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 9 10:42:56 2013 +0200

    qcow2: Use pread for inactive L1 in overlap check
    
    Currently, qcow2_check_metadata_overlap uses bdrv_read to read inactive
    L1 tables from disk. The number of sectors to read is calculated through
    a truncating integer division, therefore, if the L1 table size is not a
    multiple of the sector size, the final entries will not be read and
    their entries in memory remain undefined (from the g_malloc).
    Using bdrv_pread fixes this.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 2d67885..4cb9c23 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1719,12 +1719,11 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int chk, int64_t offset,
         for (i = 0; i < s->nb_snapshots; i++) {
             uint64_t l1_ofs = s->snapshots[i].l1_table_offset;
             uint32_t l1_sz  = s->snapshots[i].l1_size;
-            uint64_t *l1 = g_malloc(l1_sz * sizeof(uint64_t));
+            uint64_t l1_sz2 = l1_sz * sizeof(uint64_t);
+            uint64_t *l1 = g_malloc(l1_sz2);
             int ret;
 
-            ret = bdrv_read(bs->file, l1_ofs / BDRV_SECTOR_SIZE, (uint8_t *)l1,
-                            l1_sz * sizeof(uint64_t) / BDRV_SECTOR_SIZE);
-
+            ret = bdrv_pread(bs->file, l1_ofs, l1, l1_sz2);
             if (ret < 0) {
                 g_free(l1);
                 return ret;
commit f252080453ec081ba653bba4e0c1ca86c52cf19f
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 9 10:34:10 2013 +0200

    qcow2: Alignment of snapshot table entries
    
    The qcow2 specification does not explicitly state so far that every
    snapshot table entry is aligned to 8 bytes. QEMU, in contrast, does this
    alignment, thus it should be properly documented (which this patch
    does).
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/docs/specs/qcow2.txt b/docs/specs/qcow2.txt
index 33eca36..f19536a 100644
--- a/docs/specs/qcow2.txt
+++ b/docs/specs/qcow2.txt
@@ -355,3 +355,6 @@ Snapshot table entry:
         variable:   Unique ID string for the snapshot (not null terminated)
 
         variable:   Name of the snapshot (not null terminated)
+
+        variable:   Padding to round up the snapshot table entry size to the
+                    next multiple of 8.
commit 3677e6f6252542cbab85674d97d051d95e91693b
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 9 10:46:20 2013 +0200

    qemu-iotests: Additional info from qemu-img info
    
    Add a test for the additional information now provided by qemu-img info
    when used on qcow2 images. It also tests the qemu QMP output from the
    query-block command when running qemu with different runtime options
    than specified in the image (ImageInfoSpecific should always refer to
    the image).
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/065 b/tests/qemu-iotests/065
new file mode 100755
index 0000000..ab5445f
--- /dev/null
+++ b/tests/qemu-iotests/065
@@ -0,0 +1,125 @@
+#!/usr/bin/env python2
+#
+# Test for additional information emitted by qemu-img info on qcow2
+# images
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import re
+import json
+import iotests
+from iotests import qemu_img, qemu_img_pipe
+import unittest
+
+test_img = os.path.join(iotests.test_dir, 'test.img')
+
+class TestImageInfoSpecific(iotests.QMPTestCase):
+    '''Abstract base class for ImageInfoSpecific tests'''
+
+    def setUp(self):
+        if self.img_options is None:
+            self.skipTest('Skipping abstract test class')
+        qemu_img('create', '-f', iotests.imgfmt, '-o', self.img_options,
+                 test_img, '128K')
+
+    def tearDown(self):
+        os.remove(test_img)
+
+class TestQemuImgInfo(TestImageInfoSpecific):
+    '''Abstract base class for qemu-img info tests'''
+
+    img_options = None
+    json_compare = None
+    human_compare = None
+
+    def test_json(self):
+        data = json.loads(qemu_img_pipe('info', '--output=json', test_img))
+        data = data['format-specific']
+        self.assertEqual(data['type'], iotests.imgfmt)
+        self.assertEqual(data['data'], self.json_compare)
+
+    def test_human(self):
+        data = qemu_img_pipe('info', '--output=human', test_img).split('\n')
+        data = data[(data.index('Format specific information:') + 1)
+                    :data.index('')]
+        for field in data:
+            self.assertTrue(re.match('^ {4}[^ ]', field) is not None)
+        data = map(lambda line: line.strip(), data)
+        self.assertEqual(data, self.human_compare)
+
+class TestQMP(TestImageInfoSpecific):
+    '''Abstract base class for qemu QMP tests'''
+
+    img_options = None
+    qemu_options = ''
+    TestImageInfoSpecific = TestImageInfoSpecific
+
+    def setUp(self):
+        self.TestImageInfoSpecific.setUp(self)
+        self.vm = iotests.VM().add_drive(test_img, self.qemu_options)
+        self.vm.launch()
+
+    def tearDown(self):
+        self.vm.shutdown()
+        self.TestImageInfoSpecific.tearDown(self)
+
+    def test_qmp(self):
+        result = self.vm.qmp('query-block')['return']
+        drive = filter(lambda drive: drive['device'] == 'drive0', result)[0]
+        data = drive['inserted']['image']['format-specific']
+        self.assertEqual(data['type'], iotests.imgfmt)
+        self.assertEqual(data['data'], self.compare)
+
+class TestQCow2(TestQemuImgInfo):
+    '''Testing a qcow2 version 2 image'''
+    img_options = 'compat=0.10'
+    json_compare = { 'compat': '0.10' }
+    human_compare = [ 'compat: 0.10' ]
+
+class TestQCow3NotLazy(TestQemuImgInfo):
+    '''Testing a qcow2 version 3 image with lazy refcounts disabled'''
+    img_options = 'compat=1.1,lazy_refcounts=off'
+    json_compare = { 'compat': '1.1', 'lazy-refcounts': False }
+    human_compare = [ 'compat: 1.1', 'lazy refcounts: false' ]
+
+class TestQCow3Lazy(TestQemuImgInfo):
+    '''Testing a qcow2 version 3 image with lazy refcounts enabled'''
+    img_options = 'compat=1.1,lazy_refcounts=on'
+    json_compare = { 'compat': '1.1', 'lazy-refcounts': True }
+    human_compare = [ 'compat: 1.1', 'lazy refcounts: true' ]
+
+class TestQCow3NotLazyQMP(TestQMP):
+    '''Testing a qcow2 version 3 image with lazy refcounts disabled, opening
+       with lazy refcounts enabled'''
+    img_options = 'compat=1.1,lazy_refcounts=off'
+    qemu_options = 'lazy-refcounts=on'
+    compare = { 'compat': '1.1', 'lazy-refcounts': False }
+
+class TestQCow3LazyQMP(TestQMP):
+    '''Testing a qcow2 version 3 image with lazy refcounts enabled, opening
+       with lazy refcounts disabled'''
+    img_options = 'compat=1.1,lazy_refcounts=on'
+    qemu_options = 'lazy-refcounts=off'
+    compare = { 'compat': '1.1', 'lazy-refcounts': True }
+
+TestImageInfoSpecific = None
+TestQemuImgInfo = None
+TestQMP = None
+
+if __name__ == '__main__':
+    iotests.main(supported_fmts=['qcow2'])
diff --git a/tests/qemu-iotests/065.out b/tests/qemu-iotests/065.out
new file mode 100644
index 0000000..594c16f
--- /dev/null
+++ b/tests/qemu-iotests/065.out
@@ -0,0 +1,5 @@
+........
+----------------------------------------------------------------------
+Ran 8 tests
+
+OK
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 1ad02e5..f1a68b0 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -69,3 +69,4 @@
 061 rw auto
 062 rw auto
 063 rw auto
+065 rw auto
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 376d6e8..fb10ff4 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -49,6 +49,10 @@ def qemu_img_verbose(*args):
     '''Run qemu-img without suppressing its output and return the exit code'''
     return subprocess.call(qemu_img_args + list(args))
 
+def qemu_img_pipe(*args):
+    '''Run qemu-img and return its output'''
+    return subprocess.Popen(qemu_img_args + list(args), stdout=subprocess.PIPE).communicate()[0]
+
 def qemu_io(*args):
     '''Run qemu-io and return the stdout data'''
     args = qemu_io_args + list(args)
commit 4c2e946500c45685fdec61b3d929311dc26a2ad5
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 9 10:46:19 2013 +0200

    qemu-iotests: Discard specific info in _img_info
    
    In _img_info, filter out additional information specific to the image
    format provided by qemu-img info, since tests designed for multiple
    image formats would produce different outputs for every image format
    otherwise.
    
    In a human-readable dump, that new information will always be last for
    each "image information block" (multiple blocks are emitted when
    inspecting the backing file chain). Every block is separated by an empty
    line. Therefore, in this case, everything starting with the line "Format
    specific information:" up to that empty line (or EOF, if it is the last
    block) has to be stripped.
    
    The JSON dump will always emit pretty JSON data. Therefore, the opening
    and closing braces of every object will be on lines which are indented
    by exactly the same amount, and all lines in between will have more
    indentation. Thus, in this case, everything starting with a line
    matching the regular expression /^ *"format-specific": {/ until /^ *},?/
    has to be stripped, where the number of spaces at the beginning of the
    respective lines is equal.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 1b22db0..227c003 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -197,12 +197,30 @@ _check_test_img()
 
 _img_info()
 {
+    discard=0
+    regex_json_spec_start='^ *"format-specific": \{'
     $QEMU_IMG info "$@" "$TEST_IMG" 2>&1 | \
         sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
             -e "s#$TEST_DIR#TEST_DIR#g" \
             -e "s#$IMGFMT#IMGFMT#g" \
             -e "/^disk size:/ D" \
-            -e "/actual-size/ D"
+            -e "/actual-size/ D" | \
+        while IFS='' read line; do
+            if [[ $line == "Format specific information:" ]]; then
+                discard=1
+            elif [[ $line =~ $regex_json_spec_start ]]; then
+                discard=2
+                regex_json_spec_end="^${line%%[^ ]*}\\},? *$"
+            fi
+            if [[ $discard == 0 ]]; then
+                echo "$line"
+            elif [[ $discard == 1 && ! $line ]]; then
+                echo
+                discard=0
+            elif [[ $discard == 2 && $line =~ $regex_json_spec_end ]]; then
+                discard=0
+            fi
+        done
 }
 
 _get_pids_by_name()
commit 37764dfb71c4d0d058b71ba33340c6beab7d5a66
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 9 10:46:18 2013 +0200

    qcow2: Add support for ImageInfoSpecific
    
    Add a new ImageInfoSpecificQCow2 type as a subtype of ImageInfoSpecific.
    This contains the compatibility level as a string and an optional
    lazy_refcounts boolean (optional means mandatory for compat >= 1.1 and
    not available for compat == 0.10).
    
    Also, add qcow2_get_specific_info, which returns this information.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 4a9888c..e8d2735 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1810,6 +1810,33 @@ static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
     return 0;
 }
 
+static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+    ImageInfoSpecific *spec_info = g_new(ImageInfoSpecific, 1);
+
+    *spec_info = (ImageInfoSpecific){
+        .kind  = IMAGE_INFO_SPECIFIC_KIND_QCOW2,
+        {
+            .qcow2 = g_new(ImageInfoSpecificQCow2, 1),
+        },
+    };
+    if (s->qcow_version == 2) {
+        *spec_info->qcow2 = (ImageInfoSpecificQCow2){
+            .compat = g_strdup("0.10"),
+        };
+    } else if (s->qcow_version == 3) {
+        *spec_info->qcow2 = (ImageInfoSpecificQCow2){
+            .compat             = g_strdup("1.1"),
+            .lazy_refcounts     = s->compatible_features &
+                                  QCOW2_COMPAT_LAZY_REFCOUNTS,
+            .has_lazy_refcounts = true,
+        };
+    }
+
+    return spec_info;
+}
+
 #if 0
 static void dump_refcounts(BlockDriverState *bs)
 {
@@ -2130,6 +2157,7 @@ static BlockDriver bdrv_qcow2 = {
     .bdrv_snapshot_list     = qcow2_snapshot_list,
     .bdrv_snapshot_load_tmp     = qcow2_snapshot_load_tmp,
     .bdrv_get_info      = qcow2_get_info,
+    .bdrv_get_specific_info = qcow2_get_specific_info,
 
     .bdrv_save_vmstate    = qcow2_save_vmstate,
     .bdrv_load_vmstate    = qcow2_load_vmstate,
diff --git a/qapi-schema.json b/qapi-schema.json
index 246789b..a1a81a4 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -210,6 +210,21 @@
             'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } }
 
 ##
+# @ImageInfoSpecificQCow2:
+#
+# @compat: compatibility level
+#
+# @lazy-refcounts: #optional on or off; only valid for compat >= 1.1
+#
+# Since: 1.7
+##
+{ 'type': 'ImageInfoSpecificQCow2',
+  'data': {
+      'compat': 'str',
+      '*lazy-refcounts': 'bool'
+  } }
+
+##
 # @ImageInfoSpecific:
 #
 # A discriminated record of image format specific information structures.
@@ -219,6 +234,7 @@
 
 { 'union': 'ImageInfoSpecific',
   'data': {
+      'qcow2': 'ImageInfoSpecificQCow2'
   } }
 
 ##
commit a8d8ecb77fc16da49ea2c1edae267dc9d0c01dfd
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 9 10:46:17 2013 +0200

    block/qapi: Human-readable ImageInfoSpecific dump
    
    Add a function for generically dumping the ImageInfoSpecific information
    in a human-readable format to block/qapi.c.
    
    Use this function in bdrv_image_info_dump and qemu-io-cmds.c:info_f to
    allow qemu-img info resp. qemu-io -c info to print that format specific
    information.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qapi.c b/block/qapi.c
index ab1dd24..5880b3e 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -25,6 +25,9 @@
 #include "block/qapi.h"
 #include "block/block_int.h"
 #include "qmp-commands.h"
+#include "qapi-visit.h"
+#include "qapi/qmp-output-visitor.h"
+#include "qapi/qmp/types.h"
 
 /*
  * Returns 0 on success, with *p_list either set to describe snapshot
@@ -426,6 +429,119 @@ void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f,
     }
 }
 
+static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation,
+                       QDict *dict);
+static void dump_qlist(fprintf_function func_fprintf, void *f, int indentation,
+                       QList *list);
+
+static void dump_qobject(fprintf_function func_fprintf, void *f,
+                         int comp_indent, QObject *obj)
+{
+    switch (qobject_type(obj)) {
+        case QTYPE_QINT: {
+            QInt *value = qobject_to_qint(obj);
+            func_fprintf(f, "%" PRId64, qint_get_int(value));
+            break;
+        }
+        case QTYPE_QSTRING: {
+            QString *value = qobject_to_qstring(obj);
+            func_fprintf(f, "%s", qstring_get_str(value));
+            break;
+        }
+        case QTYPE_QDICT: {
+            QDict *value = qobject_to_qdict(obj);
+            dump_qdict(func_fprintf, f, comp_indent, value);
+            break;
+        }
+        case QTYPE_QLIST: {
+            QList *value = qobject_to_qlist(obj);
+            dump_qlist(func_fprintf, f, comp_indent, value);
+            break;
+        }
+        case QTYPE_QFLOAT: {
+            QFloat *value = qobject_to_qfloat(obj);
+            func_fprintf(f, "%g", qfloat_get_double(value));
+            break;
+        }
+        case QTYPE_QBOOL: {
+            QBool *value = qobject_to_qbool(obj);
+            func_fprintf(f, "%s", qbool_get_int(value) ? "true" : "false");
+            break;
+        }
+        case QTYPE_QERROR: {
+            QString *value = qerror_human((QError *)obj);
+            func_fprintf(f, "%s", qstring_get_str(value));
+            break;
+        }
+        case QTYPE_NONE:
+            break;
+        case QTYPE_MAX:
+        default:
+            abort();
+    }
+}
+
+static void dump_qlist(fprintf_function func_fprintf, void *f, int indentation,
+                       QList *list)
+{
+    const QListEntry *entry;
+    int i = 0;
+
+    for (entry = qlist_first(list); entry; entry = qlist_next(entry), i++) {
+        qtype_code type = qobject_type(entry->value);
+        bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST);
+        const char *format = composite ? "%*s[%i]:\n" : "%*s[%i]: ";
+
+        func_fprintf(f, format, indentation * 4, "", i);
+        dump_qobject(func_fprintf, f, indentation + 1, entry->value);
+        if (!composite) {
+            func_fprintf(f, "\n");
+        }
+    }
+}
+
+static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation,
+                       QDict *dict)
+{
+    const QDictEntry *entry;
+
+    for (entry = qdict_first(dict); entry; entry = qdict_next(dict, entry)) {
+        qtype_code type = qobject_type(entry->value);
+        bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST);
+        const char *format = composite ? "%*s%s:\n" : "%*s%s: ";
+        char key[strlen(entry->key) + 1];
+        int i;
+
+        /* replace dashes with spaces in key (variable) names */
+        for (i = 0; entry->key[i]; i++) {
+            key[i] = entry->key[i] == '-' ? ' ' : entry->key[i];
+        }
+        key[i] = 0;
+
+        func_fprintf(f, format, indentation * 4, "", key);
+        dump_qobject(func_fprintf, f, indentation + 1, entry->value);
+        if (!composite) {
+            func_fprintf(f, "\n");
+        }
+    }
+}
+
+void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f,
+                                   ImageInfoSpecific *info_spec)
+{
+    Error *local_err = NULL;
+    QmpOutputVisitor *ov = qmp_output_visitor_new();
+    QObject *obj, *data;
+
+    visit_type_ImageInfoSpecific(qmp_output_get_visitor(ov), &info_spec, NULL,
+                                 &local_err);
+    obj = qmp_output_get_qobject(ov);
+    assert(qobject_type(obj) == QTYPE_QDICT);
+    data = qdict_get(qobject_to_qdict(obj), "data");
+    dump_qobject(func_fprintf, f, 1, data);
+    qmp_output_visitor_cleanup(ov);
+}
+
 void bdrv_image_info_dump(fprintf_function func_fprintf, void *f,
                           ImageInfo *info)
 {
@@ -496,4 +612,9 @@ void bdrv_image_info_dump(fprintf_function func_fprintf, void *f,
             func_fprintf(f, "\n");
         }
     }
+
+    if (info->has_format_specific) {
+        func_fprintf(f, "Format specific information:\n");
+        bdrv_image_info_specific_dump(func_fprintf, f, info->format_specific);
+    }
 }
diff --git a/include/block/qapi.h b/include/block/qapi.h
index 0496cc9..9518ee4 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -42,6 +42,8 @@ BlockStats *bdrv_query_stats(const BlockDriverState *bs);
 
 void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f,
                         QEMUSnapshotInfo *sn);
+void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f,
+                                   ImageInfoSpecific *info_spec);
 void bdrv_image_info_dump(fprintf_function func_fprintf, void *f,
                           ImageInfo *info);
 #endif
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 8565d49..667f4e4 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -10,6 +10,7 @@
 
 #include "qemu-io.h"
 #include "block/block_int.h"
+#include "block/qapi.h"
 #include "qemu/main-loop.h"
 
 #define CMD_NOFILE_OK   0x01
@@ -1678,6 +1679,7 @@ static const cmdinfo_t length_cmd = {
 static int info_f(BlockDriverState *bs, int argc, char **argv)
 {
     BlockDriverInfo bdi;
+    ImageInfoSpecific *spec_info;
     char s1[64], s2[64];
     int ret;
 
@@ -1699,6 +1701,13 @@ static int info_f(BlockDriverState *bs, int argc, char **argv)
     printf("cluster size: %s\n", s1);
     printf("vm state offset: %s\n", s2);
 
+    spec_info = bdrv_get_specific_info(bs);
+    if (spec_info) {
+        printf("Format specific information:\n");
+        bdrv_image_info_specific_dump(fprintf, stdout, spec_info);
+        qapi_free_ImageInfoSpecific(spec_info);
+    }
+
     return 0;
 }
 
commit eae041fe6f4314962e873615134eefb32cf8ba61
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 9 10:46:16 2013 +0200

    block: Add bdrv_get_specific_info
    
    Add a function for retrieving an ImageInfoSpecific object from a block
    driver.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index d7ca37e..43acaad 100644
--- a/block.c
+++ b/block.c
@@ -3322,6 +3322,15 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
     return drv->bdrv_get_info(bs, bdi);
 }
 
+ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs)
+{
+    BlockDriver *drv = bs->drv;
+    if (drv && drv->bdrv_get_specific_info) {
+        return drv->bdrv_get_specific_info(bs);
+    }
+    return NULL;
+}
+
 int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
                       int64_t pos, int size)
 {
diff --git a/block/qapi.c b/block/qapi.c
index 782051c..ab1dd24 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -134,6 +134,9 @@ void bdrv_query_image_info(BlockDriverState *bs,
         info->dirty_flag = bdi.is_dirty;
         info->has_dirty_flag = true;
     }
+    info->format_specific     = bdrv_get_specific_info(bs);
+    info->has_format_specific = info->format_specific != NULL;
+
     backing_filename = bs->backing_file;
     if (backing_filename[0] != '\0') {
         info->backing_filename = g_strdup(backing_filename);
diff --git a/include/block/block.h b/include/block/block.h
index f808550..e265124 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -335,6 +335,7 @@ int bdrv_get_flags(BlockDriverState *bs);
 int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
                           const uint8_t *buf, int nb_sectors);
 int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
+ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs);
 void bdrv_round_to_clusters(BlockDriverState *bs,
                             int64_t sector_num, int nb_sectors,
                             int64_t *cluster_sector_num,
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 211087a..17b26b2 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -168,6 +168,7 @@ struct BlockDriver {
     int (*bdrv_snapshot_load_tmp)(BlockDriverState *bs,
                                   const char *snapshot_name);
     int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
+    ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs);
 
     int (*bdrv_save_vmstate)(BlockDriverState *bs, QEMUIOVector *qiov,
                              int64_t pos);
commit f2bb8a8a47597634b74c161c44b9980c7f4e50ac
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 9 10:46:15 2013 +0200

    qapi: Add ImageInfoSpecific type
    
    Add a new type ImageInfoSpecific as a union for image format specific
    information in ImageInfo.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qapi-schema.json b/qapi-schema.json
index 381ffbf..246789b 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -210,6 +210,18 @@
             'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } }
 
 ##
+# @ImageInfoSpecific:
+#
+# A discriminated record of image format specific information structures.
+#
+# Since: 1.7
+##
+
+{ 'union': 'ImageInfoSpecific',
+  'data': {
+  } }
+
+##
 # @ImageInfo:
 #
 # Information about a QEMU image file
@@ -238,6 +250,9 @@
 #
 # @backing-image: #optional info of the backing image (since 1.6)
 #
+# @format-specific: #optional structure supplying additional format-specific
+# information (since 1.7)
+#
 # Since: 1.3
 #
 ##
@@ -248,7 +263,8 @@
            '*cluster-size': 'int', '*encrypted': 'bool',
            '*backing-filename': 'str', '*full-backing-filename': 'str',
            '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'],
-           '*backing-image': 'ImageInfo' } }
+           '*backing-image': 'ImageInfo',
+           '*format-specific': 'ImageInfoSpecific' } }
 
 ##
 # @ImageCheck:
commit 79e14bf7782d861d3d773a67680de07a8f354f4e
Author: Fam Zheng <famz at redhat.com>
Date:   Tue Oct 8 17:29:40 2013 +0800

    qapi: make use of new BlockJobType
    
    Switch the string to enum type BlockJobType in BlockJobDriver.
    
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/backup.c b/block/backup.c
index d374472..cad14c9 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -204,7 +204,7 @@ static void backup_iostatus_reset(BlockJob *job)
 
 static const BlockJobDriver backup_job_driver = {
     .instance_size  = sizeof(BackupBlockJob),
-    .job_type       = "backup",
+    .job_type       = BLOCK_JOB_TYPE_BACKUP,
     .set_speed      = backup_set_speed,
     .iostatus_reset = backup_iostatus_reset,
 };
diff --git a/block/commit.c b/block/commit.c
index 5146138..d4090cb 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -175,7 +175,7 @@ static void commit_set_speed(BlockJob *job, int64_t speed, Error **errp)
 
 static const BlockJobDriver commit_job_driver = {
     .instance_size = sizeof(CommitBlockJob),
-    .job_type      = "commit",
+    .job_type      = BLOCK_JOB_TYPE_COMMIT,
     .set_speed     = commit_set_speed,
 };
 
diff --git a/block/mirror.c b/block/mirror.c
index 991cc24..7b95acf 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -527,7 +527,7 @@ static void mirror_complete(BlockJob *job, Error **errp)
 
 static const BlockJobDriver mirror_job_driver = {
     .instance_size = sizeof(MirrorBlockJob),
-    .job_type      = "mirror",
+    .job_type      = BLOCK_JOB_TYPE_MIRROR,
     .set_speed     = mirror_set_speed,
     .iostatus_reset= mirror_iostatus_reset,
     .complete      = mirror_complete,
diff --git a/block/stream.c b/block/stream.c
index 7f412bd..694fd42 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -205,7 +205,7 @@ static void stream_set_speed(BlockJob *job, int64_t speed, Error **errp)
 
 static const BlockJobDriver stream_job_driver = {
     .instance_size = sizeof(StreamBlockJob),
-    .job_type      = "stream",
+    .job_type      = BLOCK_JOB_TYPE_STREAM,
     .set_speed     = stream_set_speed,
 };
 
diff --git a/blockjob.c b/blockjob.c
index 6814e69..9e5fd5c 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -209,7 +209,7 @@ void block_job_sleep_ns(BlockJob *job, QEMUClockType type, int64_t ns)
 BlockJobInfo *block_job_query(BlockJob *job)
 {
     BlockJobInfo *info = g_new0(BlockJobInfo, 1);
-    info->type      = g_strdup(job->driver->job_type);
+    info->type      = g_strdup(BlockJobType_lookup[job->driver->job_type]);
     info->device    = g_strdup(bdrv_get_device_name(job->bs));
     info->len       = job->len;
     info->busy      = job->busy;
@@ -236,7 +236,7 @@ QObject *qobject_from_block_job(BlockJob *job)
                               "'len': %" PRId64 ","
                               "'offset': %" PRId64 ","
                               "'speed': %" PRId64 " }",
-                              job->driver->job_type,
+                              BlockJobType_lookup[job->driver->job_type],
                               bdrv_get_device_name(job->bs),
                               job->len,
                               job->offset,
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
index 99359b5..d76de62 100644
--- a/include/block/blockjob.h
+++ b/include/block/blockjob.h
@@ -37,7 +37,7 @@ typedef struct BlockJobDriver {
     size_t instance_size;
 
     /** String describing the operation, part of query-block-jobs QMP API */
-    const char *job_type;
+    BlockJobType job_type;
 
     /** Optional callback for job types that support setting a speed limit */
     void (*set_speed)(BlockJob *job, int64_t speed, Error **errp);
commit 2cb5b22286a7546226d9e9363aaee543fcba6b61
Author: Fam Zheng <famz at redhat.com>
Date:   Tue Oct 8 17:29:39 2013 +0800

    qapi: Introduce enum BlockJobType
    
    This will replace the open coded block job type string for mirror,
    commit and backup.
    
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qapi-schema.json b/qapi-schema.json
index 145eca8..381ffbf 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1366,6 +1366,24 @@
   'data': ['top', 'full', 'none'] }
 
 ##
+# @BlockJobType:
+#
+# Type of a block job.
+#
+# @commit: block commit job type, see "block-commit"
+#
+# @stream: block stream job type, see "block-stream"
+#
+# @mirror: drive mirror job type, see "drive-mirror"
+#
+# @backup: drive backup job type, see "drive-backup"
+#
+# Since: 1.7
+##
+{ 'enum': 'BlockJobType',
+  'data': ['commit', 'stream', 'mirror', 'backup'] }
+
+##
 # @BlockJobInfo:
 #
 # Information about a long-running block device operation.
commit 3fc4b10af09b75a1cb811b61abc9d8c90771dfb2
Author: Fam Zheng <famz at redhat.com>
Date:   Tue Oct 8 17:29:38 2013 +0800

    blockjob: rename BlockJobType to BlockJobDriver
    
    We will use BlockJobType as the enum type name of block jobs in QAPI,
    rename current BlockJobType to BlockJobDriver, which will eventually
    become a set of operations, similar to block drivers.
    
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/backup.c b/block/backup.c
index 04c4b5c..d374472 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -202,7 +202,7 @@ static void backup_iostatus_reset(BlockJob *job)
     bdrv_iostatus_reset(s->target);
 }
 
-static const BlockJobType backup_job_type = {
+static const BlockJobDriver backup_job_driver = {
     .instance_size  = sizeof(BackupBlockJob),
     .job_type       = "backup",
     .set_speed      = backup_set_speed,
@@ -370,7 +370,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target,
         return;
     }
 
-    BackupBlockJob *job = block_job_create(&backup_job_type, bs, speed,
+    BackupBlockJob *job = block_job_create(&backup_job_driver, bs, speed,
                                            cb, opaque, errp);
     if (!job) {
         return;
diff --git a/block/commit.c b/block/commit.c
index ac4b7cc..5146138 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -173,7 +173,7 @@ static void commit_set_speed(BlockJob *job, int64_t speed, Error **errp)
     ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE, SLICE_TIME);
 }
 
-static const BlockJobType commit_job_type = {
+static const BlockJobDriver commit_job_driver = {
     .instance_size = sizeof(CommitBlockJob),
     .job_type      = "commit",
     .set_speed     = commit_set_speed,
@@ -238,7 +238,7 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
     }
 
 
-    s = block_job_create(&commit_job_type, bs, speed, cb, opaque, errp);
+    s = block_job_create(&commit_job_driver, bs, speed, cb, opaque, errp);
     if (!s) {
         return;
     }
diff --git a/block/mirror.c b/block/mirror.c
index 6e7a274..991cc24 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -525,7 +525,7 @@ static void mirror_complete(BlockJob *job, Error **errp)
     block_job_resume(job);
 }
 
-static const BlockJobType mirror_job_type = {
+static const BlockJobDriver mirror_job_driver = {
     .instance_size = sizeof(MirrorBlockJob),
     .job_type      = "mirror",
     .set_speed     = mirror_set_speed,
@@ -563,7 +563,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
         return;
     }
 
-    s = block_job_create(&mirror_job_type, bs, speed, cb, opaque, errp);
+    s = block_job_create(&mirror_job_driver, bs, speed, cb, opaque, errp);
     if (!s) {
         return;
     }
diff --git a/block/stream.c b/block/stream.c
index 45837f4..7f412bd 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -203,7 +203,7 @@ static void stream_set_speed(BlockJob *job, int64_t speed, Error **errp)
     ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE, SLICE_TIME);
 }
 
-static const BlockJobType stream_job_type = {
+static const BlockJobDriver stream_job_driver = {
     .instance_size = sizeof(StreamBlockJob),
     .job_type      = "stream",
     .set_speed     = stream_set_speed,
@@ -224,7 +224,7 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base,
         return;
     }
 
-    s = block_job_create(&stream_job_type, bs, speed, cb, opaque, errp);
+    s = block_job_create(&stream_job_driver, bs, speed, cb, opaque, errp);
     if (!s) {
         return;
     }
diff --git a/blockjob.c b/blockjob.c
index e7d49b7..6814e69 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -35,7 +35,7 @@
 #include "qmp-commands.h"
 #include "qemu/timer.h"
 
-void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs,
+void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
                        int64_t speed, BlockDriverCompletionFunc *cb,
                        void *opaque, Error **errp)
 {
@@ -48,8 +48,8 @@ void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs,
     bdrv_ref(bs);
     bdrv_set_in_use(bs, 1);
 
-    job = g_malloc0(job_type->instance_size);
-    job->job_type      = job_type;
+    job = g_malloc0(driver->instance_size);
+    job->driver        = driver;
     job->bs            = bs;
     job->cb            = cb;
     job->opaque        = opaque;
@@ -87,11 +87,11 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
 {
     Error *local_err = NULL;
 
-    if (!job->job_type->set_speed) {
+    if (!job->driver->set_speed) {
         error_set(errp, QERR_NOT_SUPPORTED);
         return;
     }
-    job->job_type->set_speed(job, speed, &local_err);
+    job->driver->set_speed(job, speed, &local_err);
     if (error_is_set(&local_err)) {
         error_propagate(errp, local_err);
         return;
@@ -102,12 +102,12 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
 
 void block_job_complete(BlockJob *job, Error **errp)
 {
-    if (job->paused || job->cancelled || !job->job_type->complete) {
+    if (job->paused || job->cancelled || !job->driver->complete) {
         error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name);
         return;
     }
 
-    job->job_type->complete(job, errp);
+    job->driver->complete(job, errp);
 }
 
 void block_job_pause(BlockJob *job)
@@ -143,8 +143,8 @@ bool block_job_is_cancelled(BlockJob *job)
 void block_job_iostatus_reset(BlockJob *job)
 {
     job->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
-    if (job->job_type->iostatus_reset) {
-        job->job_type->iostatus_reset(job);
+    if (job->driver->iostatus_reset) {
+        job->driver->iostatus_reset(job);
     }
 }
 
@@ -209,7 +209,7 @@ void block_job_sleep_ns(BlockJob *job, QEMUClockType type, int64_t ns)
 BlockJobInfo *block_job_query(BlockJob *job)
 {
     BlockJobInfo *info = g_new0(BlockJobInfo, 1);
-    info->type      = g_strdup(job->job_type->job_type);
+    info->type      = g_strdup(job->driver->job_type);
     info->device    = g_strdup(bdrv_get_device_name(job->bs));
     info->len       = job->len;
     info->busy      = job->busy;
@@ -236,7 +236,7 @@ QObject *qobject_from_block_job(BlockJob *job)
                               "'len': %" PRId64 ","
                               "'offset': %" PRId64 ","
                               "'speed': %" PRId64 " }",
-                              job->job_type->job_type,
+                              job->driver->job_type,
                               bdrv_get_device_name(job->bs),
                               job->len,
                               job->offset,
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
index d530409..99359b5 100644
--- a/include/block/blockjob.h
+++ b/include/block/blockjob.h
@@ -28,11 +28,11 @@
 #include "block/block.h"
 
 /**
- * BlockJobType:
+ * BlockJobDriver:
  *
- * A class type for block job objects.
+ * A class type for block job driver.
  */
-typedef struct BlockJobType {
+typedef struct BlockJobDriver {
     /** Derived BlockJob struct size */
     size_t instance_size;
 
@@ -50,7 +50,7 @@ typedef struct BlockJobType {
      * manually.
      */
     void (*complete)(BlockJob *job, Error **errp);
-} BlockJobType;
+} BlockJobDriver;
 
 /**
  * BlockJob:
@@ -59,7 +59,7 @@ typedef struct BlockJobType {
  */
 struct BlockJob {
     /** The job type, including the job vtable.  */
-    const BlockJobType *job_type;
+    const BlockJobDriver *driver;
 
     /** The block device on which the job is operating.  */
     BlockDriverState *bs;
@@ -128,7 +128,7 @@ struct BlockJob {
  * This function is not part of the public job interface; it should be
  * called from a wrapper that is specific to the job type.
  */
-void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs,
+void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
                        int64_t speed, BlockDriverCompletionFunc *cb,
                        void *opaque, Error **errp);
 
commit 867b3201a333e35a91bea9febc66cce689a765c4
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 4 11:45:20 2013 -0700

    exec: Add both big- and little-endian memory helpers
    
    Step three in the transition: helpers not tied to the target
    "default" endianness.  To be used when the guest uses a memory
    operation with non-default endianness.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/include/exec/softmmu_template.h b/include/exec/softmmu_template.h
index 5edac51..c6a5440 100644
--- a/include/exec/softmmu_template.h
+++ b/include/exec/softmmu_template.h
@@ -70,6 +70,48 @@
 #define ADDR_READ addr_read
 #endif
 
+#if DATA_SIZE == 8
+# define BSWAP(X)  bswap64(X)
+#elif DATA_SIZE == 4
+# define BSWAP(X)  bswap32(X)
+#elif DATA_SIZE == 2
+# define BSWAP(X)  bswap16(X)
+#else
+# define BSWAP(X)  (X)
+#endif
+
+#ifdef TARGET_WORDS_BIGENDIAN
+# define TGT_BE(X)  (X)
+# define TGT_LE(X)  BSWAP(X)
+#else
+# define TGT_BE(X)  BSWAP(X)
+# define TGT_LE(X)  (X)
+#endif
+
+#if DATA_SIZE == 1
+# define helper_le_ld_name  glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)
+# define helper_be_ld_name  helper_le_ld_name
+# define helper_le_lds_name glue(glue(helper_ret_ld, SSUFFIX), MMUSUFFIX)
+# define helper_be_lds_name helper_le_lds_name
+# define helper_le_st_name  glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)
+# define helper_be_st_name  helper_le_st_name
+#else
+# define helper_le_ld_name  glue(glue(helper_le_ld, USUFFIX), MMUSUFFIX)
+# define helper_be_ld_name  glue(glue(helper_be_ld, USUFFIX), MMUSUFFIX)
+# define helper_le_lds_name glue(glue(helper_le_ld, SSUFFIX), MMUSUFFIX)
+# define helper_be_lds_name glue(glue(helper_be_ld, SSUFFIX), MMUSUFFIX)
+# define helper_le_st_name  glue(glue(helper_le_st, SUFFIX), MMUSUFFIX)
+# define helper_be_st_name  glue(glue(helper_be_st, SUFFIX), MMUSUFFIX)
+#endif
+
+#ifdef TARGET_WORDS_BIGENDIAN
+# define helper_te_ld_name  helper_be_ld_name
+# define helper_te_st_name  helper_be_st_name
+#else
+# define helper_te_ld_name  helper_le_ld_name
+# define helper_te_st_name  helper_le_st_name
+#endif
+
 static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
                                               hwaddr physaddr,
                                               target_ulong addr,
@@ -89,18 +131,16 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
     return val;
 }
 
-/* handle all cases except unaligned access which span two pages */
 #ifdef SOFTMMU_CODE_ACCESS
-static
+static __attribute__((unused))
 #endif
-WORD_TYPE
-glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)(CPUArchState *env,
-                                              target_ulong addr, int mmu_idx,
-                                              uintptr_t retaddr)
+WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
+                            uintptr_t retaddr)
 {
     int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
     target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
     uintptr_t haddr;
+    DATA_TYPE res;
 
     /* Adjust the given return address.  */
     retaddr -= GETPC_ADJ;
@@ -124,7 +164,12 @@ glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)(CPUArchState *env,
             goto do_unaligned_access;
         }
         ioaddr = env->iotlb[mmu_idx][index];
-        return glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr);
+
+        /* ??? Note that the io helpers always read data in the target
+           byte ordering.  We should push the LE/BE request down into io.  */
+        res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr);
+        res = TGT_LE(res);
+        return res;
     }
 
     /* Handle slow unaligned access (it spans two pages or IO).  */
@@ -132,7 +177,7 @@ glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)(CPUArchState *env,
         && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
                     >= TARGET_PAGE_SIZE)) {
         target_ulong addr1, addr2;
-        DATA_TYPE res1, res2, res;
+        DATA_TYPE res1, res2;
         unsigned shift;
     do_unaligned_access:
 #ifdef ALIGNED_ONLY
@@ -142,16 +187,94 @@ glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)(CPUArchState *env,
         addr2 = addr1 + DATA_SIZE;
         /* Note the adjustment at the beginning of the function.
            Undo that for the recursion.  */
-        res1 = glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)
-            (env, addr1, mmu_idx, retaddr + GETPC_ADJ);
-        res2 = glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)
-            (env, addr2, mmu_idx, retaddr + GETPC_ADJ);
+        res1 = helper_le_ld_name(env, addr1, mmu_idx, retaddr + GETPC_ADJ);
+        res2 = helper_le_ld_name(env, addr2, mmu_idx, retaddr + GETPC_ADJ);
         shift = (addr & (DATA_SIZE - 1)) * 8;
-#ifdef TARGET_WORDS_BIGENDIAN
-        res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
-#else
+
+        /* Little-endian combine.  */
         res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift));
+        return res;
+    }
+
+    /* Handle aligned access or unaligned access in the same page.  */
+#ifdef ALIGNED_ONLY
+    if ((addr & (DATA_SIZE - 1)) != 0) {
+        do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
+    }
+#endif
+
+    haddr = addr + env->tlb_table[mmu_idx][index].addend;
+#if DATA_SIZE == 1
+    res = glue(glue(ld, LSUFFIX), _p)((uint8_t *)haddr);
+#else
+    res = glue(glue(ld, LSUFFIX), _le_p)((uint8_t *)haddr);
+#endif
+    return res;
+}
+
+#if DATA_SIZE > 1
+#ifdef SOFTMMU_CODE_ACCESS
+static __attribute__((unused))
+#endif
+WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
+                            uintptr_t retaddr)
+{
+    int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+    target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
+    uintptr_t haddr;
+    DATA_TYPE res;
+
+    /* Adjust the given return address.  */
+    retaddr -= GETPC_ADJ;
+
+    /* If the TLB entry is for a different page, reload and try again.  */
+    if ((addr & TARGET_PAGE_MASK)
+         != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
+#ifdef ALIGNED_ONLY
+        if ((addr & (DATA_SIZE - 1)) != 0) {
+            do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
+        }
+#endif
+        tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
+        tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
+    }
+
+    /* Handle an IO access.  */
+    if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
+        hwaddr ioaddr;
+        if ((addr & (DATA_SIZE - 1)) != 0) {
+            goto do_unaligned_access;
+        }
+        ioaddr = env->iotlb[mmu_idx][index];
+
+        /* ??? Note that the io helpers always read data in the target
+           byte ordering.  We should push the LE/BE request down into io.  */
+        res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr);
+        res = TGT_BE(res);
+        return res;
+    }
+
+    /* Handle slow unaligned access (it spans two pages or IO).  */
+    if (DATA_SIZE > 1
+        && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
+                    >= TARGET_PAGE_SIZE)) {
+        target_ulong addr1, addr2;
+        DATA_TYPE res1, res2;
+        unsigned shift;
+    do_unaligned_access:
+#ifdef ALIGNED_ONLY
+        do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
 #endif
+        addr1 = addr & ~(DATA_SIZE - 1);
+        addr2 = addr1 + DATA_SIZE;
+        /* Note the adjustment at the beginning of the function.
+           Undo that for the recursion.  */
+        res1 = helper_be_ld_name(env, addr1, mmu_idx, retaddr + GETPC_ADJ);
+        res2 = helper_be_ld_name(env, addr2, mmu_idx, retaddr + GETPC_ADJ);
+        shift = (addr & (DATA_SIZE - 1)) * 8;
+
+        /* Big-endian combine.  */
+        res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
         return res;
     }
 
@@ -163,16 +286,16 @@ glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)(CPUArchState *env,
 #endif
 
     haddr = addr + env->tlb_table[mmu_idx][index].addend;
-    /* Note that ldl_raw is defined with type "int".  */
-    return (DATA_TYPE) glue(glue(ld, LSUFFIX), _raw)((uint8_t *)haddr);
+    res = glue(glue(ld, LSUFFIX), _be_p)((uint8_t *)haddr);
+    return res;
 }
+#endif /* DATA_SIZE > 1 */
 
 DATA_TYPE
 glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr,
                                          int mmu_idx)
 {
-    return glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)(env, addr, mmu_idx,
-                                                         GETRA());
+    return helper_te_ld_name (env, addr, mmu_idx, GETRA());
 }
 
 #ifndef SOFTMMU_CODE_ACCESS
@@ -180,14 +303,19 @@ glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr,
 /* Provide signed versions of the load routines as well.  We can of course
    avoid this for 64-bit data, or for 32-bit data on 32-bit host.  */
 #if DATA_SIZE * 8 < TCG_TARGET_REG_BITS
-WORD_TYPE
-glue(glue(helper_ret_ld, SSUFFIX), MMUSUFFIX)(CPUArchState *env,
-                                              target_ulong addr, int mmu_idx,
-                                              uintptr_t retaddr)
+WORD_TYPE helper_le_lds_name(CPUArchState *env, target_ulong addr,
+                             int mmu_idx, uintptr_t retaddr)
+{
+    return (SDATA_TYPE)helper_le_ld_name(env, addr, mmu_idx, retaddr);
+}
+
+# if DATA_SIZE > 1
+WORD_TYPE helper_be_lds_name(CPUArchState *env, target_ulong addr,
+                             int mmu_idx, uintptr_t retaddr)
 {
-    return (SDATA_TYPE) glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)
-        (env, addr, mmu_idx, retaddr);
+    return (SDATA_TYPE)helper_be_ld_name(env, addr, mmu_idx, retaddr);
 }
+# endif
 #endif
 
 static inline void glue(io_write, SUFFIX)(CPUArchState *env,
@@ -208,10 +336,8 @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env,
     io_mem_write(mr, physaddr, val, 1 << SHIFT);
 }
 
-void
-glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)(CPUArchState *env,
-                                             target_ulong addr, DATA_TYPE val,
-                                             int mmu_idx, uintptr_t retaddr)
+void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
+                       int mmu_idx, uintptr_t retaddr)
 {
     int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
     target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
@@ -239,6 +365,10 @@ glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)(CPUArchState *env,
             goto do_unaligned_access;
         }
         ioaddr = env->iotlb[mmu_idx][index];
+
+        /* ??? Note that the io helpers always read data in the target
+           byte ordering.  We should push the LE/BE request down into io.  */
+        val = TGT_LE(val);
         glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr);
         return;
     }
@@ -256,11 +386,84 @@ glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)(CPUArchState *env,
         /* Note: relies on the fact that tlb_fill() does not remove the
          * previous page from the TLB cache.  */
         for (i = DATA_SIZE - 1; i >= 0; i--) {
-#ifdef TARGET_WORDS_BIGENDIAN
-            uint8_t val8 = val >> (((DATA_SIZE - 1) * 8) - (i * 8));
-#else
+            /* Little-endian extract.  */
             uint8_t val8 = val >> (i * 8);
+            /* Note the adjustment at the beginning of the function.
+               Undo that for the recursion.  */
+            glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
+                                            mmu_idx, retaddr + GETPC_ADJ);
+        }
+        return;
+    }
+
+    /* Handle aligned access or unaligned access in the same page.  */
+#ifdef ALIGNED_ONLY
+    if ((addr & (DATA_SIZE - 1)) != 0) {
+        do_unaligned_access(env, addr, 1, mmu_idx, retaddr);
+    }
+#endif
+
+    haddr = addr + env->tlb_table[mmu_idx][index].addend;
+#if DATA_SIZE == 1
+    glue(glue(st, SUFFIX), _p)((uint8_t *)haddr, val);
+#else
+    glue(glue(st, SUFFIX), _le_p)((uint8_t *)haddr, val);
 #endif
+}
+
+#if DATA_SIZE > 1
+void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
+                       int mmu_idx, uintptr_t retaddr)
+{
+    int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+    target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
+    uintptr_t haddr;
+
+    /* Adjust the given return address.  */
+    retaddr -= GETPC_ADJ;
+
+    /* If the TLB entry is for a different page, reload and try again.  */
+    if ((addr & TARGET_PAGE_MASK)
+        != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
+#ifdef ALIGNED_ONLY
+        if ((addr & (DATA_SIZE - 1)) != 0) {
+            do_unaligned_access(env, addr, 1, mmu_idx, retaddr);
+        }
+#endif
+        tlb_fill(env, addr, 1, mmu_idx, retaddr);
+        tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
+    }
+
+    /* Handle an IO access.  */
+    if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
+        hwaddr ioaddr;
+        if ((addr & (DATA_SIZE - 1)) != 0) {
+            goto do_unaligned_access;
+        }
+        ioaddr = env->iotlb[mmu_idx][index];
+
+        /* ??? Note that the io helpers always read data in the target
+           byte ordering.  We should push the LE/BE request down into io.  */
+        val = TGT_BE(val);
+        glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr);
+        return;
+    }
+
+    /* Handle slow unaligned access (it spans two pages or IO).  */
+    if (DATA_SIZE > 1
+        && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
+                     >= TARGET_PAGE_SIZE)) {
+        int i;
+    do_unaligned_access:
+#ifdef ALIGNED_ONLY
+        do_unaligned_access(env, addr, 1, mmu_idx, retaddr);
+#endif
+        /* XXX: not efficient, but simple */
+        /* Note: relies on the fact that tlb_fill() does not remove the
+         * previous page from the TLB cache.  */
+        for (i = DATA_SIZE - 1; i >= 0; i--) {
+            /* Big-endian extract.  */
+            uint8_t val8 = val >> (((DATA_SIZE - 1) * 8) - (i * 8));
             /* Note the adjustment at the beginning of the function.
                Undo that for the recursion.  */
             glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
@@ -277,15 +480,15 @@ glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)(CPUArchState *env,
 #endif
 
     haddr = addr + env->tlb_table[mmu_idx][index].addend;
-    glue(glue(st, SUFFIX), _raw)((uint8_t *)haddr, val);
+    glue(glue(st, SUFFIX), _be_p)((uint8_t *)haddr, val);
 }
+#endif /* DATA_SIZE > 1 */
 
 void
 glue(glue(helper_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr,
                                          DATA_TYPE val, int mmu_idx)
 {
-    glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)(env, addr, val, mmu_idx,
-                                                 GETRA());
+    helper_te_st_name(env, addr, val, mmu_idx, GETRA());
 }
 
 #endif /* !defined(SOFTMMU_CODE_ACCESS) */
@@ -301,3 +504,16 @@ glue(glue(helper_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr,
 #undef SDATA_TYPE
 #undef USUFFIX
 #undef SSUFFIX
+#undef BSWAP
+#undef TGT_BE
+#undef TGT_LE
+#undef CPU_BE
+#undef CPU_LE
+#undef helper_le_ld_name
+#undef helper_be_ld_name
+#undef helper_le_lds_name
+#undef helper_be_lds_name
+#undef helper_le_st_name
+#undef helper_be_st_name
+#undef helper_te_ld_name
+#undef helper_te_st_name
diff --git a/tcg/tcg.h b/tcg/tcg.h
index db0abc3..0d9bd29 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -774,29 +774,66 @@ void tcg_register_jit(void *buf, size_t buf_size);
 /* Value zero-extended to tcg register size.  */
 tcg_target_ulong helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr,
                                      int mmu_idx, uintptr_t retaddr);
-tcg_target_ulong helper_ret_lduw_mmu(CPUArchState *env, target_ulong addr,
-                                     int mmu_idx, uintptr_t retaddr);
-tcg_target_ulong helper_ret_ldul_mmu(CPUArchState *env, target_ulong addr,
-                                     int mmu_idx, uintptr_t retaddr);
-uint64_t helper_ret_ldq_mmu(CPUArchState *env, target_ulong addr,
-                            int mmu_idx, uintptr_t retaddr);
+tcg_target_ulong helper_le_lduw_mmu(CPUArchState *env, target_ulong addr,
+                                    int mmu_idx, uintptr_t retaddr);
+tcg_target_ulong helper_le_ldul_mmu(CPUArchState *env, target_ulong addr,
+                                    int mmu_idx, uintptr_t retaddr);
+uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr,
+                           int mmu_idx, uintptr_t retaddr);
+tcg_target_ulong helper_be_lduw_mmu(CPUArchState *env, target_ulong addr,
+                                    int mmu_idx, uintptr_t retaddr);
+tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr,
+                                    int mmu_idx, uintptr_t retaddr);
+uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr,
+                           int mmu_idx, uintptr_t retaddr);
 
 /* Value sign-extended to tcg register size.  */
 tcg_target_ulong helper_ret_ldsb_mmu(CPUArchState *env, target_ulong addr,
                                      int mmu_idx, uintptr_t retaddr);
-tcg_target_ulong helper_ret_ldsw_mmu(CPUArchState *env, target_ulong addr,
-                                     int mmu_idx, uintptr_t retaddr);
-tcg_target_ulong helper_ret_ldsl_mmu(CPUArchState *env, target_ulong addr,
-                                     int mmu_idx, uintptr_t retaddr);
+tcg_target_ulong helper_le_ldsw_mmu(CPUArchState *env, target_ulong addr,
+                                    int mmu_idx, uintptr_t retaddr);
+tcg_target_ulong helper_le_ldsl_mmu(CPUArchState *env, target_ulong addr,
+                                    int mmu_idx, uintptr_t retaddr);
+tcg_target_ulong helper_be_ldsw_mmu(CPUArchState *env, target_ulong addr,
+                                    int mmu_idx, uintptr_t retaddr);
+tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
+                                    int mmu_idx, uintptr_t retaddr);
 
 void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
                         int mmu_idx, uintptr_t retaddr);
-void helper_ret_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
-                        int mmu_idx, uintptr_t retaddr);
-void helper_ret_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
-                        int mmu_idx, uintptr_t retaddr);
-void helper_ret_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
-                        int mmu_idx, uintptr_t retaddr);
+void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+                       int mmu_idx, uintptr_t retaddr);
+void helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
+                       int mmu_idx, uintptr_t retaddr);
+void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
+                       int mmu_idx, uintptr_t retaddr);
+void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+                       int mmu_idx, uintptr_t retaddr);
+void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
+                       int mmu_idx, uintptr_t retaddr);
+void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
+                       int mmu_idx, uintptr_t retaddr);
+
+/* Temporary aliases until backends are converted.  */
+#ifdef TARGET_WORDS_BIGENDIAN
+# define helper_ret_ldsw_mmu  helper_be_ldsw_mmu
+# define helper_ret_lduw_mmu  helper_be_lduw_mmu
+# define helper_ret_ldsl_mmu  helper_be_ldsl_mmu
+# define helper_ret_ldul_mmu  helper_be_ldul_mmu
+# define helper_ret_ldq_mmu   helper_be_ldq_mmu
+# define helper_ret_stw_mmu   helper_be_stw_mmu
+# define helper_ret_stl_mmu   helper_be_stl_mmu
+# define helper_ret_stq_mmu   helper_be_stq_mmu
+#else
+# define helper_ret_ldsw_mmu  helper_le_ldsw_mmu
+# define helper_ret_lduw_mmu  helper_le_lduw_mmu
+# define helper_ret_ldsl_mmu  helper_le_ldsl_mmu
+# define helper_ret_ldul_mmu  helper_le_ldul_mmu
+# define helper_ret_ldq_mmu   helper_le_ldq_mmu
+# define helper_ret_stw_mmu   helper_le_stw_mmu
+# define helper_ret_stl_mmu   helper_le_stl_mmu
+# define helper_ret_stq_mmu   helper_le_stq_mmu
+#endif
 
 uint8_t helper_ldb_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
 uint16_t helper_ldw_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
commit f713d6ad7b9f52129695d5e3e63541abcd0375c0
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 4 08:11:05 2013 -0700

    tcg: Add qemu_ld_st_i32/64
    
    Step two in the transition, adding the new ldst opcodes.  Keep the old
    opcodes around until all backends support the new opcodes.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/README b/tcg/README
index 063aeb9..f178212 100644
--- a/tcg/README
+++ b/tcg/README
@@ -412,30 +412,25 @@ current TB was linked to this TB. Otherwise execute the next
 instructions. Only indices 0 and 1 are valid and tcg_gen_goto_tb may be issued
 at most once with each slot index per TB.
 
-* qemu_ld8u t0, t1, flags
-qemu_ld8s t0, t1, flags
-qemu_ld16u t0, t1, flags
-qemu_ld16s t0, t1, flags
-qemu_ld32 t0, t1, flags
-qemu_ld32u t0, t1, flags
-qemu_ld32s t0, t1, flags
-qemu_ld64 t0, t1, flags
-
-Load data at the QEMU CPU address t1 into t0. t1 has the QEMU CPU address
-type. 'flags' contains the QEMU memory index (selects user or kernel access)
-for example.
-
-Note that "qemu_ld32" implies a 32-bit result, while "qemu_ld32u" and
-"qemu_ld32s" imply a 64-bit result appropriately extended from 32 bits.
-
-* qemu_st8 t0, t1, flags
-qemu_st16 t0, t1, flags
-qemu_st32 t0, t1, flags
-qemu_st64 t0, t1, flags
-
-Store the data t0 at the QEMU CPU Address t1. t1 has the QEMU CPU
-address type. 'flags' contains the QEMU memory index (selects user or
-kernel access) for example.
+* qemu_ld_i32/i64 t0, t1, flags, memidx
+* qemu_st_i32/i64 t0, t1, flags, memidx
+
+Load data at the guest address t1 into t0, or store data in t0 at guest
+address t1.  The _i32/_i64 size applies to the size of the input/output
+register t0 only.  The address t1 is always sized according to the guest,
+and the width of the memory operation is controlled by flags.
+
+Both t0 and t1 may be split into little-endian ordered pairs of registers
+if dealing with 64-bit quantities on a 32-bit host.
+
+The memidx selects the qemu tlb index to use (e.g. user or kernel access).
+The flags are the TCGMemOp bits, selecting the sign, width, and endianness
+of the memory access.
+
+For a 32-bit host, qemu_ld/st_i64 is guaranteed to only be used with a
+64-bit memory access specified in flags.
+
+*********
 
 Note 1: Some shortcuts are defined when the last operand is known to be
 a constant (e.g. addi for add, movi for mov).
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
index d3a1bc2..82ad919 100644
--- a/tcg/aarch64/tcg-target.h
+++ b/tcg/aarch64/tcg-target.h
@@ -96,6 +96,8 @@ enum {
     TCG_AREG0 = TCG_REG_X19,
 };
 
+#define TCG_TARGET_HAS_new_ldst         0
+
 static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
 {
     __builtin___clear_cache((char *)start, (char *)stop);
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 9482bfa..25e1e28 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -85,6 +85,8 @@ extern bool use_idiv_instructions;
 #define TCG_TARGET_HAS_div_i32          use_idiv_instructions
 #define TCG_TARGET_HAS_rem_i32          0
 
+#define TCG_TARGET_HAS_new_ldst         0
+
 extern bool tcg_target_deposit_valid(int ofs, int len);
 #define TCG_TARGET_deposit_i32_valid  tcg_target_deposit_valid
 
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index d32d7ef..fa7d966 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -130,6 +130,8 @@ typedef enum {
 #define TCG_TARGET_HAS_mulsh_i64        0
 #endif
 
+#define TCG_TARGET_HAS_new_ldst         0
+
 #define TCG_TARGET_deposit_i32_valid(ofs, len) \
     (((ofs) == 0 && (len) == 8) || ((ofs) == 8 && (len) == 8) || \
      ((ofs) == 0 && (len) == 16))
diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h
index 4330c9c..c90038a 100644
--- a/tcg/ia64/tcg-target.h
+++ b/tcg/ia64/tcg-target.h
@@ -151,6 +151,8 @@ typedef enum {
 #define TCG_TARGET_HAS_mulsh_i32        0
 #define TCG_TARGET_HAS_mulsh_i64        0
 
+#define TCG_TARGET_HAS_new_ldst         0
+
 #define TCG_TARGET_deposit_i32_valid(ofs, len) ((len) <= 16)
 #define TCG_TARGET_deposit_i64_valid(ofs, len) ((len) <= 16)
 
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index c372522..683c6af 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -122,6 +122,8 @@ extern bool use_mips32r2_instructions;
 #define TCG_TARGET_HAS_ext16s_i32       use_mips32r2_instructions
 #define TCG_TARGET_HAS_rot_i32          use_mips32r2_instructions
 
+#define TCG_TARGET_HAS_new_ldst         0
+
 /* optional instructions automatically implemented */
 #define TCG_TARGET_HAS_neg_i32          0 /* sub  rd, zero, rt   */
 #define TCG_TARGET_HAS_ext8u_i32        0 /* andi rt, rs, 0xff   */
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index c9f8ff5..e3ac629 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -99,6 +99,8 @@ typedef enum {
 #define TCG_TARGET_HAS_muluh_i32        0
 #define TCG_TARGET_HAS_mulsh_i32        0
 
+#define TCG_TARGET_HAS_new_ldst         0
+
 #define TCG_AREG0 TCG_REG_R27
 
 #define tcg_qemu_tb_exec(env, tb_ptr) \
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
index fa4b9da..457ea69 100644
--- a/tcg/ppc64/tcg-target.h
+++ b/tcg/ppc64/tcg-target.h
@@ -123,6 +123,8 @@ typedef enum {
 #define TCG_TARGET_HAS_muluh_i64        1
 #define TCG_TARGET_HAS_mulsh_i64        1
 
+#define TCG_TARGET_HAS_new_ldst         0
+
 #define TCG_AREG0 TCG_REG_R27
 
 #define TCG_TARGET_EXTEND_ARGS 1
diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h
index 6142fb2..10adb77 100644
--- a/tcg/s390/tcg-target.h
+++ b/tcg/s390/tcg-target.h
@@ -99,6 +99,8 @@ typedef enum TCGReg {
 #define TCG_TARGET_HAS_muluh_i64        0
 #define TCG_TARGET_HAS_mulsh_i64        0
 
+#define TCG_TARGET_HAS_new_ldst         0
+
 extern bool tcg_target_deposit_valid(int ofs, int len);
 #define TCG_TARGET_deposit_i32_valid  tcg_target_deposit_valid
 #define TCG_TARGET_deposit_i64_valid  tcg_target_deposit_valid
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
index 1ff2922..00f3a18 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -148,6 +148,8 @@ typedef enum {
 #define TCG_TARGET_HAS_mulsh_i64        0
 #endif
 
+#define TCG_TARGET_HAS_new_ldst         0
+
 #define TCG_AREG0 TCG_REG_I0
 
 static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index bb30a7c..7eabf22 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -137,24 +137,6 @@ static inline void tcg_gen_ldst_op_i64(TCGOpcode opc, TCGv_i64 val,
     *tcg_ctx.gen_opparam_ptr++ = offset;
 }
 
-static inline void tcg_gen_qemu_ldst_op_i64_i32(TCGOpcode opc, TCGv_i64 val,
-                                                TCGv_i32 addr, TCGArg mem_index)
-{
-    *tcg_ctx.gen_opc_ptr++ = opc;
-    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(val);
-    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(addr);
-    *tcg_ctx.gen_opparam_ptr++ = mem_index;
-}
-
-static inline void tcg_gen_qemu_ldst_op_i64_i64(TCGOpcode opc, TCGv_i64 val,
-                                                TCGv_i64 addr, TCGArg mem_index)
-{
-    *tcg_ctx.gen_opc_ptr++ = opc;
-    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(val);
-    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(addr);
-    *tcg_ctx.gen_opparam_ptr++ = mem_index;
-}
-
 static inline void tcg_gen_op4_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
                                    TCGv_i32 arg3, TCGv_i32 arg4)
 {
@@ -361,6 +343,21 @@ static inline void tcg_gen_op6ii_i64(TCGOpcode opc, TCGv_i64 arg1,
     *tcg_ctx.gen_opparam_ptr++ = arg6;
 }
 
+static inline void tcg_add_param_i32(TCGv_i32 val)
+{
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(val);
+}
+
+static inline void tcg_add_param_i64(TCGv_i64 val)
+{
+#if TCG_TARGET_REG_BITS == 32
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(TCGV_LOW(val));
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(TCGV_HIGH(val));
+#else
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(val);
+#endif
+}
+
 static inline void gen_set_label(int n)
 {
     tcg_gen_op1i(INDEX_op_set_label, n);
@@ -2600,11 +2597,12 @@ static inline void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh,
 #define tcg_global_mem_new tcg_global_mem_new_i32
 #define tcg_temp_local_new() tcg_temp_local_new_i32()
 #define tcg_temp_free tcg_temp_free_i32
-#define tcg_gen_qemu_ldst_op tcg_gen_op3i_i32
-#define tcg_gen_qemu_ldst_op_i64 tcg_gen_qemu_ldst_op_i64_i32
 #define TCGV_UNUSED(x) TCGV_UNUSED_I32(x)
 #define TCGV_IS_UNUSED(x) TCGV_IS_UNUSED_I32(x)
 #define TCGV_EQUAL(a, b) TCGV_EQUAL_I32(a, b)
+#define tcg_add_param_tl tcg_add_param_i32
+#define tcg_gen_qemu_ld_tl tcg_gen_qemu_ld_i32
+#define tcg_gen_qemu_st_tl tcg_gen_qemu_st_i32
 #else
 #define TCGv TCGv_i64
 #define tcg_temp_new() tcg_temp_new_i64()
@@ -2612,11 +2610,12 @@ static inline void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh,
 #define tcg_global_mem_new tcg_global_mem_new_i64
 #define tcg_temp_local_new() tcg_temp_local_new_i64()
 #define tcg_temp_free tcg_temp_free_i64
-#define tcg_gen_qemu_ldst_op tcg_gen_op3i_i64
-#define tcg_gen_qemu_ldst_op_i64 tcg_gen_qemu_ldst_op_i64_i64
 #define TCGV_UNUSED(x) TCGV_UNUSED_I64(x)
 #define TCGV_IS_UNUSED(x) TCGV_IS_UNUSED_I64(x)
 #define TCGV_EQUAL(a, b) TCGV_EQUAL_I64(a, b)
+#define tcg_add_param_tl tcg_add_param_i64
+#define tcg_gen_qemu_ld_tl tcg_gen_qemu_ld_i64
+#define tcg_gen_qemu_st_tl tcg_gen_qemu_st_i64
 #endif
 
 /* debug info: write the PC of the corresponding QEMU CPU instruction */
@@ -2648,197 +2647,67 @@ static inline void tcg_gen_goto_tb(unsigned idx)
     tcg_gen_op1i(INDEX_op_goto_tb, idx);
 }
 
-#if TCG_TARGET_REG_BITS == 32
-static inline void tcg_gen_qemu_ld8u(TCGv ret, TCGv addr, int mem_index)
-{
-#if TARGET_LONG_BITS == 32
-    tcg_gen_op3i_i32(INDEX_op_qemu_ld8u, ret, addr, mem_index);
-#else
-    tcg_gen_op4i_i32(INDEX_op_qemu_ld8u, TCGV_LOW(ret), TCGV_LOW(addr),
-                     TCGV_HIGH(addr), mem_index);
-    tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
-#endif
-}
-
-static inline void tcg_gen_qemu_ld8s(TCGv ret, TCGv addr, int mem_index)
-{
-#if TARGET_LONG_BITS == 32
-    tcg_gen_op3i_i32(INDEX_op_qemu_ld8s, ret, addr, mem_index);
-#else
-    tcg_gen_op4i_i32(INDEX_op_qemu_ld8s, TCGV_LOW(ret), TCGV_LOW(addr),
-                     TCGV_HIGH(addr), mem_index);
-    tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
-#endif
-}
 
-static inline void tcg_gen_qemu_ld16u(TCGv ret, TCGv addr, int mem_index)
-{
-#if TARGET_LONG_BITS == 32
-    tcg_gen_op3i_i32(INDEX_op_qemu_ld16u, ret, addr, mem_index);
-#else
-    tcg_gen_op4i_i32(INDEX_op_qemu_ld16u, TCGV_LOW(ret), TCGV_LOW(addr),
-                     TCGV_HIGH(addr), mem_index);
-    tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
-#endif
-}
-
-static inline void tcg_gen_qemu_ld16s(TCGv ret, TCGv addr, int mem_index)
-{
-#if TARGET_LONG_BITS == 32
-    tcg_gen_op3i_i32(INDEX_op_qemu_ld16s, ret, addr, mem_index);
-#else
-    tcg_gen_op4i_i32(INDEX_op_qemu_ld16s, TCGV_LOW(ret), TCGV_LOW(addr),
-                     TCGV_HIGH(addr), mem_index);
-    tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
-#endif
-}
-
-static inline void tcg_gen_qemu_ld32u(TCGv ret, TCGv addr, int mem_index)
-{
-#if TARGET_LONG_BITS == 32
-    tcg_gen_op3i_i32(INDEX_op_qemu_ld32, ret, addr, mem_index);
-#else
-    tcg_gen_op4i_i32(INDEX_op_qemu_ld32, TCGV_LOW(ret), TCGV_LOW(addr),
-                     TCGV_HIGH(addr), mem_index);
-    tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
-#endif
-}
-
-static inline void tcg_gen_qemu_ld32s(TCGv ret, TCGv addr, int mem_index)
-{
-#if TARGET_LONG_BITS == 32
-    tcg_gen_op3i_i32(INDEX_op_qemu_ld32, ret, addr, mem_index);
-#else
-    tcg_gen_op4i_i32(INDEX_op_qemu_ld32, TCGV_LOW(ret), TCGV_LOW(addr),
-                     TCGV_HIGH(addr), mem_index);
-    tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
-#endif
-}
-
-static inline void tcg_gen_qemu_ld64(TCGv_i64 ret, TCGv addr, int mem_index)
-{
-#if TARGET_LONG_BITS == 32
-    tcg_gen_op4i_i32(INDEX_op_qemu_ld64, TCGV_LOW(ret), TCGV_HIGH(ret), addr, mem_index);
-#else
-    tcg_gen_op5i_i32(INDEX_op_qemu_ld64, TCGV_LOW(ret), TCGV_HIGH(ret),
-                     TCGV_LOW(addr), TCGV_HIGH(addr), mem_index);
-#endif
-}
-
-static inline void tcg_gen_qemu_st8(TCGv arg, TCGv addr, int mem_index)
-{
-#if TARGET_LONG_BITS == 32
-    tcg_gen_op3i_i32(INDEX_op_qemu_st8, arg, addr, mem_index);
-#else
-    tcg_gen_op4i_i32(INDEX_op_qemu_st8, TCGV_LOW(arg), TCGV_LOW(addr),
-                     TCGV_HIGH(addr), mem_index);
-#endif
-}
-
-static inline void tcg_gen_qemu_st16(TCGv arg, TCGv addr, int mem_index)
-{
-#if TARGET_LONG_BITS == 32
-    tcg_gen_op3i_i32(INDEX_op_qemu_st16, arg, addr, mem_index);
-#else
-    tcg_gen_op4i_i32(INDEX_op_qemu_st16, TCGV_LOW(arg), TCGV_LOW(addr),
-                     TCGV_HIGH(addr), mem_index);
-#endif
-}
-
-static inline void tcg_gen_qemu_st32(TCGv arg, TCGv addr, int mem_index)
-{
-#if TARGET_LONG_BITS == 32
-    tcg_gen_op3i_i32(INDEX_op_qemu_st32, arg, addr, mem_index);
-#else
-    tcg_gen_op4i_i32(INDEX_op_qemu_st32, TCGV_LOW(arg), TCGV_LOW(addr),
-                     TCGV_HIGH(addr), mem_index);
-#endif
-}
-
-static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
-{
-#if TARGET_LONG_BITS == 32
-    tcg_gen_op4i_i32(INDEX_op_qemu_st64, TCGV_LOW(arg), TCGV_HIGH(arg), addr,
-                     mem_index);
-#else
-    tcg_gen_op5i_i32(INDEX_op_qemu_st64, TCGV_LOW(arg), TCGV_HIGH(arg),
-                     TCGV_LOW(addr), TCGV_HIGH(addr), mem_index);
-#endif
-}
-
-#define tcg_gen_ld_ptr(R, A, O) tcg_gen_ld_i32(TCGV_PTR_TO_NAT(R), (A), (O))
-#define tcg_gen_discard_ptr(A) tcg_gen_discard_i32(TCGV_PTR_TO_NAT(A))
-
-#else /* TCG_TARGET_REG_BITS == 32 */
+void tcg_gen_qemu_ld_i32(TCGv_i32, TCGv, TCGArg, TCGMemOp);
+void tcg_gen_qemu_st_i32(TCGv_i32, TCGv, TCGArg, TCGMemOp);
+void tcg_gen_qemu_ld_i64(TCGv_i64, TCGv, TCGArg, TCGMemOp);
+void tcg_gen_qemu_st_i64(TCGv_i64, TCGv, TCGArg, TCGMemOp);
 
 static inline void tcg_gen_qemu_ld8u(TCGv ret, TCGv addr, int mem_index)
 {
-    tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld8u, ret, addr, mem_index);
+    tcg_gen_qemu_ld_tl(ret, addr, mem_index, MO_UB);
 }
 
 static inline void tcg_gen_qemu_ld8s(TCGv ret, TCGv addr, int mem_index)
 {
-    tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld8s, ret, addr, mem_index);
+    tcg_gen_qemu_ld_tl(ret, addr, mem_index, MO_SB);
 }
 
 static inline void tcg_gen_qemu_ld16u(TCGv ret, TCGv addr, int mem_index)
 {
-    tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld16u, ret, addr, mem_index);
+    tcg_gen_qemu_ld_tl(ret, addr, mem_index, MO_TEUW);
 }
 
 static inline void tcg_gen_qemu_ld16s(TCGv ret, TCGv addr, int mem_index)
 {
-    tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld16s, ret, addr, mem_index);
+    tcg_gen_qemu_ld_tl(ret, addr, mem_index, MO_TESW);
 }
 
 static inline void tcg_gen_qemu_ld32u(TCGv ret, TCGv addr, int mem_index)
 {
-#if TARGET_LONG_BITS == 32
-    tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld32, ret, addr, mem_index);
-#else
-    tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld32u, ret, addr, mem_index);
-#endif
+    tcg_gen_qemu_ld_tl(ret, addr, mem_index, MO_TEUL);
 }
 
 static inline void tcg_gen_qemu_ld32s(TCGv ret, TCGv addr, int mem_index)
 {
-#if TARGET_LONG_BITS == 32
-    tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld32, ret, addr, mem_index);
-#else
-    tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld32s, ret, addr, mem_index);
-#endif
+    tcg_gen_qemu_ld_tl(ret, addr, mem_index, MO_TESL);
 }
 
 static inline void tcg_gen_qemu_ld64(TCGv_i64 ret, TCGv addr, int mem_index)
 {
-    tcg_gen_qemu_ldst_op_i64(INDEX_op_qemu_ld64, ret, addr, mem_index);
+    tcg_gen_qemu_ld_i64(ret, addr, mem_index, MO_TEQ);
 }
 
 static inline void tcg_gen_qemu_st8(TCGv arg, TCGv addr, int mem_index)
 {
-    tcg_gen_qemu_ldst_op(INDEX_op_qemu_st8, arg, addr, mem_index);
+    tcg_gen_qemu_st_tl(arg, addr, mem_index, MO_UB);
 }
 
 static inline void tcg_gen_qemu_st16(TCGv arg, TCGv addr, int mem_index)
 {
-    tcg_gen_qemu_ldst_op(INDEX_op_qemu_st16, arg, addr, mem_index);
+    tcg_gen_qemu_st_tl(arg, addr, mem_index, MO_TEUW);
 }
 
 static inline void tcg_gen_qemu_st32(TCGv arg, TCGv addr, int mem_index)
 {
-    tcg_gen_qemu_ldst_op(INDEX_op_qemu_st32, arg, addr, mem_index);
+    tcg_gen_qemu_st_tl(arg, addr, mem_index, MO_TEUL);
 }
 
 static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
 {
-    tcg_gen_qemu_ldst_op_i64(INDEX_op_qemu_st64, arg, addr, mem_index);
+    tcg_gen_qemu_st_i64(arg, addr, mem_index, MO_TEQ);
 }
 
-#define tcg_gen_ld_ptr(R, A, O) tcg_gen_ld_i64(TCGV_PTR_TO_NAT(R), (A), (O))
-#define tcg_gen_discard_ptr(A) tcg_gen_discard_i64(TCGV_PTR_TO_NAT(A))
-
-#endif /* TCG_TARGET_REG_BITS != 32 */
-
 #if TARGET_LONG_BITS == 64
 #define tcg_gen_movi_tl tcg_gen_movi_i64
 #define tcg_gen_mov_tl tcg_gen_mov_i64
@@ -2997,17 +2866,25 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
 #endif
 
 #if TCG_TARGET_REG_BITS == 32
-#define tcg_gen_add_ptr(R, A, B) tcg_gen_add_i32(TCGV_PTR_TO_NAT(R), \
-                                               TCGV_PTR_TO_NAT(A), \
-                                               TCGV_PTR_TO_NAT(B))
-#define tcg_gen_addi_ptr(R, A, B) tcg_gen_addi_i32(TCGV_PTR_TO_NAT(R), \
-                                                 TCGV_PTR_TO_NAT(A), (B))
-#define tcg_gen_ext_i32_ptr(R, A) tcg_gen_mov_i32(TCGV_PTR_TO_NAT(R), (A))
-#else /* TCG_TARGET_REG_BITS == 32 */
-#define tcg_gen_add_ptr(R, A, B) tcg_gen_add_i64(TCGV_PTR_TO_NAT(R), \
-                                               TCGV_PTR_TO_NAT(A), \
-                                               TCGV_PTR_TO_NAT(B))
-#define tcg_gen_addi_ptr(R, A, B) tcg_gen_addi_i64(TCGV_PTR_TO_NAT(R),   \
-                                                 TCGV_PTR_TO_NAT(A), (B))
-#define tcg_gen_ext_i32_ptr(R, A) tcg_gen_ext_i32_i64(TCGV_PTR_TO_NAT(R), (A))
-#endif /* TCG_TARGET_REG_BITS != 32 */
+# define tcg_gen_ld_ptr(R, A, O) \
+    tcg_gen_ld_i32(TCGV_PTR_TO_NAT(R), (A), (O))
+# define tcg_gen_discard_ptr(A) \
+    tcg_gen_discard_i32(TCGV_PTR_TO_NAT(A))
+# define tcg_gen_add_ptr(R, A, B) \
+    tcg_gen_add_i32(TCGV_PTR_TO_NAT(R), TCGV_PTR_TO_NAT(A), TCGV_PTR_TO_NAT(B))
+# define tcg_gen_addi_ptr(R, A, B) \
+    tcg_gen_addi_i32(TCGV_PTR_TO_NAT(R), TCGV_PTR_TO_NAT(A), (B))
+# define tcg_gen_ext_i32_ptr(R, A) \
+    tcg_gen_mov_i32(TCGV_PTR_TO_NAT(R), (A))
+#else
+# define tcg_gen_ld_ptr(R, A, O) \
+    tcg_gen_ld_i64(TCGV_PTR_TO_NAT(R), (A), (O))
+# define tcg_gen_discard_ptr(A) \
+    tcg_gen_discard_i64(TCGV_PTR_TO_NAT(A))
+# define tcg_gen_add_ptr(R, A, B) \
+    tcg_gen_add_i64(TCGV_PTR_TO_NAT(R), TCGV_PTR_TO_NAT(A), TCGV_PTR_TO_NAT(B))
+# define tcg_gen_addi_ptr(R, A, B) \
+    tcg_gen_addi_i64(TCGV_PTR_TO_NAT(R), TCGV_PTR_TO_NAT(A), (B))
+# define tcg_gen_ext_i32_ptr(R, A) \
+    tcg_gen_ext_i32_i64(TCGV_PTR_TO_NAT(R), (A))
+#endif /* TCG_TARGET_REG_BITS == 32 */
diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index a75c29d..d71707d 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -180,79 +180,107 @@ DEF(debug_insn_start, 0, 0, 1, TCG_OPF_NOT_PRESENT)
 #endif
 DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_END)
 DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_END)
-/* Note: even if TARGET_LONG_BITS is not defined, the INDEX_op
-   constants must be defined */
+
+#define IMPL_NEW_LDST \
+    (TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS \
+     | IMPL(TCG_TARGET_HAS_new_ldst))
+
+#if TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
+DEF(qemu_ld_i32, 1, 1, 2, IMPL_NEW_LDST)
+DEF(qemu_st_i32, 0, 2, 2, IMPL_NEW_LDST)
+# if TCG_TARGET_REG_BITS == 64
+DEF(qemu_ld_i64, 1, 1, 2, IMPL_NEW_LDST | TCG_OPF_64BIT)
+DEF(qemu_st_i64, 0, 2, 2, IMPL_NEW_LDST | TCG_OPF_64BIT)
+# else
+DEF(qemu_ld_i64, 2, 1, 2, IMPL_NEW_LDST | TCG_OPF_64BIT)
+DEF(qemu_st_i64, 0, 3, 2, IMPL_NEW_LDST | TCG_OPF_64BIT)
+# endif
+#else
+DEF(qemu_ld_i32, 1, 2, 2, IMPL_NEW_LDST)
+DEF(qemu_st_i32, 0, 3, 2, IMPL_NEW_LDST)
+DEF(qemu_ld_i64, 2, 2, 2, IMPL_NEW_LDST | TCG_OPF_64BIT)
+DEF(qemu_st_i64, 0, 4, 2, IMPL_NEW_LDST | TCG_OPF_64BIT)
+#endif
+
+#undef IMPL_NEW_LDST
+
+#define IMPL_OLD_LDST \
+    (TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS \
+     | IMPL(!TCG_TARGET_HAS_new_ldst))
+
 #if TCG_TARGET_REG_BITS == 32
 #if TARGET_LONG_BITS == 32
-DEF(qemu_ld8u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld8u, 1, 1, 1, IMPL_OLD_LDST)
 #else
-DEF(qemu_ld8u, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld8u, 1, 2, 1, IMPL_OLD_LDST)
 #endif
 #if TARGET_LONG_BITS == 32
-DEF(qemu_ld8s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld8s, 1, 1, 1, IMPL_OLD_LDST)
 #else
-DEF(qemu_ld8s, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld8s, 1, 2, 1, IMPL_OLD_LDST)
 #endif
 #if TARGET_LONG_BITS == 32
-DEF(qemu_ld16u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld16u, 1, 1, 1, IMPL_OLD_LDST)
 #else
-DEF(qemu_ld16u, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld16u, 1, 2, 1, IMPL_OLD_LDST)
 #endif
 #if TARGET_LONG_BITS == 32
-DEF(qemu_ld16s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld16s, 1, 1, 1, IMPL_OLD_LDST)
 #else
-DEF(qemu_ld16s, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld16s, 1, 2, 1, IMPL_OLD_LDST)
 #endif
 #if TARGET_LONG_BITS == 32
-DEF(qemu_ld32, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld32, 1, 1, 1, IMPL_OLD_LDST)
 #else
-DEF(qemu_ld32, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld32, 1, 2, 1, IMPL_OLD_LDST)
 #endif
 #if TARGET_LONG_BITS == 32
-DEF(qemu_ld64, 2, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld64, 2, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
 #else
-DEF(qemu_ld64, 2, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld64, 2, 2, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
 #endif
 
 #if TARGET_LONG_BITS == 32
-DEF(qemu_st8, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st8, 0, 2, 1, IMPL_OLD_LDST)
 #else
-DEF(qemu_st8, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st8, 0, 3, 1, IMPL_OLD_LDST)
 #endif
 #if TARGET_LONG_BITS == 32
-DEF(qemu_st16, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st16, 0, 2, 1, IMPL_OLD_LDST)
 #else
-DEF(qemu_st16, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st16, 0, 3, 1, IMPL_OLD_LDST)
 #endif
 #if TARGET_LONG_BITS == 32
-DEF(qemu_st32, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st32, 0, 2, 1, IMPL_OLD_LDST)
 #else
-DEF(qemu_st32, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st32, 0, 3, 1, IMPL_OLD_LDST)
 #endif
 #if TARGET_LONG_BITS == 32
-DEF(qemu_st64, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st64, 0, 3, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
 #else
-DEF(qemu_st64, 0, 4, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st64, 0, 4, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
 #endif
 
 #else /* TCG_TARGET_REG_BITS == 32 */
 
-DEF(qemu_ld8u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF(qemu_ld8s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF(qemu_ld16u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF(qemu_ld16s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF(qemu_ld32, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF(qemu_ld32u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF(qemu_ld32s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF(qemu_ld64, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld8u, 1, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
+DEF(qemu_ld8s, 1, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
+DEF(qemu_ld16u, 1, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
+DEF(qemu_ld16s, 1, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
+DEF(qemu_ld32, 1, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
+DEF(qemu_ld32u, 1, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
+DEF(qemu_ld32s, 1, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
+DEF(qemu_ld64, 1, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
 
-DEF(qemu_st8, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF(qemu_st16, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF(qemu_st32, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF(qemu_st64, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st8, 0, 2, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
+DEF(qemu_st16, 0, 2, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
+DEF(qemu_st32, 0, 2, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
+DEF(qemu_st64, 0, 2, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
 
 #endif /* TCG_TARGET_REG_BITS != 32 */
 
+#undef IMPL_OLD_LDST
+
 #undef IMPL
 #undef IMPL64
 #undef DEF
diff --git a/tcg/tcg.c b/tcg/tcg.c
index eba080a..66d3f3d 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -811,6 +811,188 @@ void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
 }
 #endif
 
+static inline TCGMemOp tcg_canonicalize_memop(TCGMemOp op, bool is64, bool st)
+{
+    switch (op & MO_SIZE) {
+    case MO_8:
+        op &= ~MO_BSWAP;
+        break;
+    case MO_16:
+        break;
+    case MO_32:
+        if (!is64) {
+            op &= ~MO_SIGN;
+        }
+        break;
+    case MO_64:
+        if (!is64) {
+            tcg_abort();
+        }
+        break;
+    }
+    if (st) {
+        op &= ~MO_SIGN;
+    }
+    return op;
+}
+
+static const TCGOpcode old_ld_opc[8] = {
+    [MO_UB] = INDEX_op_qemu_ld8u,
+    [MO_SB] = INDEX_op_qemu_ld8s,
+    [MO_UW] = INDEX_op_qemu_ld16u,
+    [MO_SW] = INDEX_op_qemu_ld16s,
+#if TCG_TARGET_REG_BITS == 32
+    [MO_UL] = INDEX_op_qemu_ld32,
+    [MO_SL] = INDEX_op_qemu_ld32,
+#else
+    [MO_UL] = INDEX_op_qemu_ld32u,
+    [MO_SL] = INDEX_op_qemu_ld32s,
+#endif
+    [MO_Q]  = INDEX_op_qemu_ld64,
+};
+
+static const TCGOpcode old_st_opc[4] = {
+    [MO_UB] = INDEX_op_qemu_st8,
+    [MO_UW] = INDEX_op_qemu_st16,
+    [MO_UL] = INDEX_op_qemu_st32,
+    [MO_Q]  = INDEX_op_qemu_st64,
+};
+
+void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
+{
+    memop = tcg_canonicalize_memop(memop, 0, 0);
+
+    if (TCG_TARGET_HAS_new_ldst) {
+        *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_ld_i32;
+        tcg_add_param_i32(val);
+        tcg_add_param_tl(addr);
+        *tcg_ctx.gen_opparam_ptr++ = memop;
+        *tcg_ctx.gen_opparam_ptr++ = idx;
+        return;
+    }
+
+    /* The old opcodes only support target-endian memory operations.  */
+    assert((memop & MO_BSWAP) == MO_TE || (memop & MO_SIZE) == MO_8);
+    assert(old_ld_opc[memop & MO_SSIZE] != 0);
+
+    if (TCG_TARGET_REG_BITS == 32) {
+        *tcg_ctx.gen_opc_ptr++ = old_ld_opc[memop & MO_SSIZE];
+        tcg_add_param_i32(val);
+        tcg_add_param_tl(addr);
+        *tcg_ctx.gen_opparam_ptr++ = idx;
+    } else {
+        TCGv_i64 val64 = tcg_temp_new_i64();
+
+        *tcg_ctx.gen_opc_ptr++ = old_ld_opc[memop & MO_SSIZE];
+        tcg_add_param_i64(val64);
+        tcg_add_param_tl(addr);
+        *tcg_ctx.gen_opparam_ptr++ = idx;
+
+        tcg_gen_trunc_i64_i32(val, val64);
+        tcg_temp_free_i64(val64);
+    }
+}
+
+void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
+{
+    memop = tcg_canonicalize_memop(memop, 0, 1);
+
+    if (TCG_TARGET_HAS_new_ldst) {
+        *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_st_i32;
+        tcg_add_param_i32(val);
+        tcg_add_param_tl(addr);
+        *tcg_ctx.gen_opparam_ptr++ = memop;
+        *tcg_ctx.gen_opparam_ptr++ = idx;
+        return;
+    }
+
+    /* The old opcodes only support target-endian memory operations.  */
+    assert((memop & MO_BSWAP) == MO_TE || (memop & MO_SIZE) == MO_8);
+    assert(old_st_opc[memop & MO_SIZE] != 0);
+
+    if (TCG_TARGET_REG_BITS == 32) {
+        *tcg_ctx.gen_opc_ptr++ = old_st_opc[memop & MO_SIZE];
+        tcg_add_param_i32(val);
+        tcg_add_param_tl(addr);
+        *tcg_ctx.gen_opparam_ptr++ = idx;
+    } else {
+        TCGv_i64 val64 = tcg_temp_new_i64();
+
+        tcg_gen_extu_i32_i64(val64, val);
+
+        *tcg_ctx.gen_opc_ptr++ = old_st_opc[memop & MO_SIZE];
+        tcg_add_param_i64(val64);
+        tcg_add_param_tl(addr);
+        *tcg_ctx.gen_opparam_ptr++ = idx;
+
+        tcg_temp_free_i64(val64);
+    }
+}
+
+void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
+{
+    memop = tcg_canonicalize_memop(memop, 1, 0);
+
+#if TCG_TARGET_REG_BITS == 32
+    if ((memop & MO_SIZE) < MO_64) {
+        tcg_gen_qemu_ld_i32(TCGV_LOW(val), addr, idx, memop);
+        if (memop & MO_SIGN) {
+            tcg_gen_sari_i32(TCGV_HIGH(val), TCGV_LOW(val), 31);
+        } else {
+            tcg_gen_movi_i32(TCGV_HIGH(val), 0);
+        }
+        return;
+    }
+#endif
+
+    if (TCG_TARGET_HAS_new_ldst) {
+        *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_ld_i64;
+        tcg_add_param_i64(val);
+        tcg_add_param_tl(addr);
+        *tcg_ctx.gen_opparam_ptr++ = memop;
+        *tcg_ctx.gen_opparam_ptr++ = idx;
+        return;
+    }
+
+    /* The old opcodes only support target-endian memory operations.  */
+    assert((memop & MO_BSWAP) == MO_TE || (memop & MO_SIZE) == MO_8);
+    assert(old_ld_opc[memop & MO_SSIZE] != 0);
+
+    *tcg_ctx.gen_opc_ptr++ = old_ld_opc[memop & MO_SSIZE];
+    tcg_add_param_i64(val);
+    tcg_add_param_tl(addr);
+    *tcg_ctx.gen_opparam_ptr++ = idx;
+}
+
+void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
+{
+    memop = tcg_canonicalize_memop(memop, 1, 1);
+
+#if TCG_TARGET_REG_BITS == 32
+    if ((memop & MO_SIZE) < MO_64) {
+        tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop);
+        return;
+    }
+#endif
+
+    if (TCG_TARGET_HAS_new_ldst) {
+        *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_st_i64;
+        tcg_add_param_i64(val);
+        tcg_add_param_tl(addr);
+        *tcg_ctx.gen_opparam_ptr++ = memop;
+        *tcg_ctx.gen_opparam_ptr++ = idx;
+        return;
+    }
+
+    /* The old opcodes only support target-endian memory operations.  */
+    assert((memop & MO_BSWAP) == MO_TE || (memop & MO_SIZE) == MO_8);
+    assert(old_st_opc[memop & MO_SIZE] != 0);
+
+    *tcg_ctx.gen_opc_ptr++ = old_st_opc[memop & MO_SIZE];
+    tcg_add_param_i64(val);
+    tcg_add_param_tl(addr);
+    *tcg_ctx.gen_opparam_ptr++ = idx;
+}
 
 static void tcg_reg_alloc_start(TCGContext *s)
 {
@@ -893,6 +1075,22 @@ static const char * const cond_name[] =
     [TCG_COND_GTU] = "gtu"
 };
 
+static const char * const ldst_name[] =
+{
+    [MO_UB]   = "ub",
+    [MO_SB]   = "sb",
+    [MO_LEUW] = "leuw",
+    [MO_LESW] = "lesw",
+    [MO_LEUL] = "leul",
+    [MO_LESL] = "lesl",
+    [MO_LEQ]  = "leq",
+    [MO_BEUW] = "beuw",
+    [MO_BESW] = "besw",
+    [MO_BEUL] = "beul",
+    [MO_BESL] = "besl",
+    [MO_BEQ]  = "beq",
+};
+
 void tcg_dump_ops(TCGContext *s)
 {
     const uint16_t *opc_ptr;
@@ -1021,6 +1219,17 @@ void tcg_dump_ops(TCGContext *s)
                 }
                 i = 1;
                 break;
+            case INDEX_op_qemu_ld_i32:
+            case INDEX_op_qemu_st_i32:
+            case INDEX_op_qemu_ld_i64:
+            case INDEX_op_qemu_st_i64:
+                if (args[k] < ARRAY_SIZE(ldst_name) && ldst_name[args[k]]) {
+                    qemu_log(",%s", ldst_name[args[k++]]);
+                } else {
+                    qemu_log(",$0x%" TCG_PRIlx, args[k++]);
+                }
+                i = 1;
+                break;
             default:
                 i = 0;
                 break;
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
index c2ecfbe..6e1da8c 100644
--- a/tcg/tci/tcg-target.h
+++ b/tcg/tci/tcg-target.h
@@ -120,6 +120,8 @@
 #define TCG_TARGET_HAS_mulsh_i64        0
 #endif /* TCG_TARGET_REG_BITS == 64 */
 
+#define TCG_TARGET_HAS_new_ldst         0
+
 /* Number of registers available.
    For 32 bit hosts, we need more than 8 registers (call arguments). */
 /* #define TCG_TARGET_NB_REGS 8 */
commit 39c153b80f890dc5f02465dc59992e195abd5f40
Merge: e8f2f59 51fb256
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Thu Oct 10 13:16:25 2013 -0700

    Merge remote-tracking branch 'afaerber/tags/qom-cpu-for-anthony' into staging
    
    QOM CPUState refactorings / X86CPU
    
    * Fix for X86CPU model field of qemu32/qemu64 CPU models
    * Bug fix for longjmp on FreeBSD
    * Removal of unused function
    * Confinement of clone syscall infrastructure to linux-user
    
    # gpg: Signature made Wed 09 Oct 2013 03:40:51 AM PDT using RSA key ID 3E7E013F
    # gpg: Can't check signature: public key not found
    
    # By Andreas Färber (2) and others
    # Via Andreas Färber
    * afaerber/tags/qom-cpu-for-anthony:
      cpu: Drop cpu_model_str from CPU_COMMON
      cpu: Move cpu_copy() into linux-user
      cputlb: Remove dead function tlb_update_dirty()
      cpu-exec: Also reload CPUClass *cc after longjmp return in cpu_exec()
      target-i386: Set model=6 on qemu64 & qemu32 CPU models

commit e8f2f59aaf2978641b7e073ba623bd4b4a9e864d
Merge: 88b70e5 386a5a1
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Thu Oct 10 13:16:02 2013 -0700

    Merge remote-tracking branch 'amit/char-remove-watch-on-unplug' into staging
    
    # By Amit Shah
    # Via Amit Shah
    * amit/char-remove-watch-on-unplug:
      char: remove watch callback on chardev detach from frontend
      char: use common function to disable callbacks on chardev close
      char: move backends' io watch tag to CharDriverState
    
    Message-id: 20131004154802.GA25646 at grmbl.mre
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit 88b70e56b969142c88f240434f392b9348600ef5
Merge: e572398 c236f45
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Thu Oct 10 13:15:46 2013 -0700

    Merge remote-tracking branch 'otubo/seccomp' into staging
    
    # By Eduardo Otubo
    # Via Eduardo Otubo
    * otubo/seccomp:
      seccomp: fine tuning whitelist by adding times()
    
    Message-id: 1380047458-21673-1-git-send-email-otubo at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit e572398de14c2173d5701d1f7771689764356b68
Merge: f2c6bcf ad98acb
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Thu Oct 10 13:00:03 2013 -0700

    Merge remote-tracking branch 'mcayland/qemu-openbios' into staging
    
    * mcayland/qemu-openbios:
      Update OpenBIOS images
    
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit 0106dc4f05231b44f54fae5d0ee42031298588bd
Author: Mark Wu <wudxw at linux.vnet.ibm.com>
Date:   Wed Oct 9 10:37:26 2013 +0800

    qemu-ga: Extend 'guest-info' command to expose flag 'success-response'
    
    Now we have several qemu-ga commands not returning response on success.
    It has been documented in qga/qapi-schema.json already. This patch exposes
    the 'success-response' flag by extending 'guest-info' command. With this
    change, the clients can handle the command response more flexibly.
    
    Signed-off-by: Mark Wu <wudxw at linux.vnet.ibm.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    *fixed up commit subject
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>

diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h
index 7d759ef..cea3818 100644
--- a/include/qapi/qmp/dispatch.h
+++ b/include/qapi/qmp/dispatch.h
@@ -49,6 +49,7 @@ void qmp_disable_command(const char *name);
 void qmp_enable_command(const char *name);
 bool qmp_command_is_enabled(const QmpCommand *cmd);
 const char *qmp_command_name(const QmpCommand *cmd);
+bool qmp_has_success_response(const QmpCommand *cmd);
 QObject *qmp_build_error_object(Error *errp);
 typedef void (*qmp_cmd_callback_fn)(QmpCommand *cmd, void *opaque);
 void qmp_for_each_command(qmp_cmd_callback_fn fn, void *opaque);
diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c
index 5e26710..3e4498a 100644
--- a/qapi/qmp-registry.c
+++ b/qapi/qmp-registry.c
@@ -76,6 +76,11 @@ const char *qmp_command_name(const QmpCommand *cmd)
     return cmd->name;
 }
 
+bool qmp_has_success_response(const QmpCommand *cmd)
+{
+    return !(cmd->options & QCO_NO_SUCCESS_RESP);
+}
+
 void qmp_for_each_command(qmp_cmd_callback_fn fn, void *opaque)
 {
     QmpCommand *cmd;
diff --git a/qga/commands.c b/qga/commands.c
index e87cbf8..a0c2de0 100644
--- a/qga/commands.c
+++ b/qga/commands.c
@@ -54,6 +54,7 @@ static void qmp_command_info(QmpCommand *cmd, void *opaque)
     cmd_info = g_malloc0(sizeof(GuestAgentCommandInfo));
     cmd_info->name = g_strdup(qmp_command_name(cmd));
     cmd_info->enabled = qmp_command_is_enabled(cmd);
+    cmd_info->success_response = qmp_has_success_response(cmd);
 
     cmd_info_list = g_malloc0(sizeof(GuestAgentCommandInfoList));
     cmd_info_list->value = cmd_info;
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index 7155b7a..245f968 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -141,10 +141,13 @@
 #
 # @enabled: whether command is currently enabled by guest admin
 #
+# @success-response: whether command returns a response on success
+#                    (since 1.7)
+#
 # Since 1.1.0
 ##
 { 'type': 'GuestAgentCommandInfo',
-  'data': { 'name': 'str', 'enabled': 'bool' } }
+  'data': { 'name': 'str', 'enabled': 'bool', 'success-response': 'bool' } }
 
 ##
 # @GuestAgentInfo
commit 8dc4d915dd6ea347a47557f5aa75a648555fe253
Author: Mark Wu <wudxw at linux.vnet.ibm.com>
Date:   Wed Oct 9 11:25:07 2013 +0800

    qemu-ga: Add interface to traverse the qmp command list by QmpCommand
    
    In the original code, qmp_get_command_list is used to construct
    a list of all commands' name. To get the information of all qga
    commands, it traverses the name list and search the command info
    with its name.  So it can cause O(n^2) in the number of commands.
    
    This patch adds an interface to traverse the qmp command list by
    QmpCommand to replace qmp_get_command_list. It can decrease the
    complexity from O(n^2) to O(n).
    
    Signed-off-by: Mark Wu <wudxw at linux.vnet.ibm.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    *fix up commit subject
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>

diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h
index 1ce11f5..7d759ef 100644
--- a/include/qapi/qmp/dispatch.h
+++ b/include/qapi/qmp/dispatch.h
@@ -47,9 +47,11 @@ QmpCommand *qmp_find_command(const char *name);
 QObject *qmp_dispatch(QObject *request);
 void qmp_disable_command(const char *name);
 void qmp_enable_command(const char *name);
-bool qmp_command_is_enabled(const char *name);
-char **qmp_get_command_list(void);
+bool qmp_command_is_enabled(const QmpCommand *cmd);
+const char *qmp_command_name(const QmpCommand *cmd);
 QObject *qmp_build_error_object(Error *errp);
+typedef void (*qmp_cmd_callback_fn)(QmpCommand *cmd, void *opaque);
+void qmp_for_each_command(qmp_cmd_callback_fn fn, void *opaque);
 
 #endif
 
diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c
index 28bbbe8..5e26710 100644
--- a/qapi/qmp-registry.c
+++ b/qapi/qmp-registry.c
@@ -66,35 +66,21 @@ void qmp_enable_command(const char *name)
     qmp_toggle_command(name, true);
 }
 
-bool qmp_command_is_enabled(const char *name)
+bool qmp_command_is_enabled(const QmpCommand *cmd)
 {
-    QmpCommand *cmd;
-
-    QTAILQ_FOREACH(cmd, &qmp_commands, node) {
-        if (strcmp(cmd->name, name) == 0) {
-            return cmd->enabled;
-        }
-    }
+    return cmd->enabled;
+}
 
-    return false;
+const char *qmp_command_name(const QmpCommand *cmd)
+{
+    return cmd->name;
 }
 
-char **qmp_get_command_list(void)
+void qmp_for_each_command(qmp_cmd_callback_fn fn, void *opaque)
 {
     QmpCommand *cmd;
-    int count = 1;
-    char **list_head, **list;
-
-    QTAILQ_FOREACH(cmd, &qmp_commands, node) {
-        count++;
-    }
-
-    list_head = list = g_malloc0(count * sizeof(char *));
 
     QTAILQ_FOREACH(cmd, &qmp_commands, node) {
-        *list = g_strdup(cmd->name);
-        list++;
+        fn(cmd, opaque);
     }
-
-    return list_head;
 }
diff --git a/qga/commands.c b/qga/commands.c
index 528b082..e87cbf8 100644
--- a/qga/commands.c
+++ b/qga/commands.c
@@ -45,35 +45,27 @@ void qmp_guest_ping(Error **err)
     slog("guest-ping called");
 }
 
-struct GuestAgentInfo *qmp_guest_info(Error **err)
+static void qmp_command_info(QmpCommand *cmd, void *opaque)
 {
-    GuestAgentInfo *info = g_malloc0(sizeof(GuestAgentInfo));
+    GuestAgentInfo *info = opaque;
     GuestAgentCommandInfo *cmd_info;
     GuestAgentCommandInfoList *cmd_info_list;
-    char **cmd_list_head, **cmd_list;
-
-    info->version = g_strdup(QEMU_VERSION);
-
-    cmd_list_head = cmd_list = qmp_get_command_list();
-    if (*cmd_list_head == NULL) {
-        goto out;
-    }
 
-    while (*cmd_list) {
-        cmd_info = g_malloc0(sizeof(GuestAgentCommandInfo));
-        cmd_info->name = g_strdup(*cmd_list);
-        cmd_info->enabled = qmp_command_is_enabled(cmd_info->name);
+    cmd_info = g_malloc0(sizeof(GuestAgentCommandInfo));
+    cmd_info->name = g_strdup(qmp_command_name(cmd));
+    cmd_info->enabled = qmp_command_is_enabled(cmd);
 
-        cmd_info_list = g_malloc0(sizeof(GuestAgentCommandInfoList));
-        cmd_info_list->value = cmd_info;
-        cmd_info_list->next = info->supported_commands;
-        info->supported_commands = cmd_info_list;
+    cmd_info_list = g_malloc0(sizeof(GuestAgentCommandInfoList));
+    cmd_info_list->value = cmd_info;
+    cmd_info_list->next = info->supported_commands;
+    info->supported_commands = cmd_info_list;
+}
 
-        g_free(*cmd_list);
-        cmd_list++;
-    }
+struct GuestAgentInfo *qmp_guest_info(Error **err)
+{
+    GuestAgentInfo *info = g_malloc0(sizeof(GuestAgentInfo));
 
-out:
-    g_free(cmd_list_head);
+    info->version = g_strdup(QEMU_VERSION);
+    qmp_for_each_command(qmp_command_info, info);
     return info;
 }
diff --git a/qga/main.c b/qga/main.c
index 6c746c8..c58b26a 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -347,48 +347,35 @@ static gint ga_strcmp(gconstpointer str1, gconstpointer str2)
 }
 
 /* disable commands that aren't safe for fsfreeze */
-static void ga_disable_non_whitelisted(void)
+static void ga_disable_non_whitelisted(QmpCommand *cmd, void *opaque)
 {
-    char **list_head, **list;
-    bool whitelisted;
-    int i;
-
-    list_head = list = qmp_get_command_list();
-    while (*list != NULL) {
-        whitelisted = false;
-        i = 0;
-        while (ga_freeze_whitelist[i] != NULL) {
-            if (strcmp(*list, ga_freeze_whitelist[i]) == 0) {
-                whitelisted = true;
-            }
-            i++;
-        }
-        if (!whitelisted) {
-            g_debug("disabling command: %s", *list);
-            qmp_disable_command(*list);
+    bool whitelisted = false;
+    int i = 0;
+    const char *name = qmp_command_name(cmd);
+
+    while (ga_freeze_whitelist[i] != NULL) {
+        if (strcmp(name, ga_freeze_whitelist[i]) == 0) {
+            whitelisted = true;
         }
-        g_free(*list);
-        list++;
+        i++;
+    }
+    if (!whitelisted) {
+        g_debug("disabling command: %s", name);
+        qmp_disable_command(name);
     }
-    g_free(list_head);
 }
 
 /* [re-]enable all commands, except those explicitly blacklisted by user */
-static void ga_enable_non_blacklisted(GList *blacklist)
+static void ga_enable_non_blacklisted(QmpCommand *cmd, void *opaque)
 {
-    char **list_head, **list;
-
-    list_head = list = qmp_get_command_list();
-    while (*list != NULL) {
-        if (g_list_find_custom(blacklist, *list, ga_strcmp) == NULL &&
-            !qmp_command_is_enabled(*list)) {
-            g_debug("enabling command: %s", *list);
-            qmp_enable_command(*list);
-        }
-        g_free(*list);
-        list++;
+    GList *blacklist = opaque;
+    const char *name = qmp_command_name(cmd);
+
+    if (g_list_find_custom(blacklist, name, ga_strcmp) == NULL &&
+        !qmp_command_is_enabled(cmd)) {
+        g_debug("enabling command: %s", name);
+        qmp_enable_command(name);
     }
-    g_free(list_head);
 }
 
 static bool ga_create_file(const char *path)
@@ -424,7 +411,7 @@ void ga_set_frozen(GAState *s)
         return;
     }
     /* disable all non-whitelisted (for frozen state) commands */
-    ga_disable_non_whitelisted();
+    qmp_for_each_command(ga_disable_non_whitelisted, NULL);
     g_warning("disabling logging due to filesystem freeze");
     ga_disable_logging(s);
     s->frozen = true;
@@ -460,7 +447,7 @@ void ga_unset_frozen(GAState *s)
     }
 
     /* enable all disabled, non-blacklisted commands */
-    ga_enable_non_blacklisted(s->blacklist);
+    qmp_for_each_command(ga_enable_non_blacklisted, s->blacklist);
     s->frozen = false;
     if (!ga_delete_file(s->state_filepath_isfrozen)) {
         g_warning("unable to delete %s, fsfreeze may not function properly",
@@ -920,6 +907,11 @@ int64_t ga_get_fd_handle(GAState *s, Error **errp)
     return handle;
 }
 
+static void ga_print_cmd(QmpCommand *cmd, void *opaque)
+{
+    printf("%s\n", qmp_command_name(cmd));
+}
+
 int main(int argc, char **argv)
 {
     const char *sopt = "hVvdm:p:l:f:F::b:s:t:";
@@ -996,15 +988,8 @@ int main(int argc, char **argv)
             daemonize = 1;
             break;
         case 'b': {
-            char **list_head, **list;
             if (is_help_option(optarg)) {
-                list_head = list = qmp_get_command_list();
-                while (*list != NULL) {
-                    printf("%s\n", *list);
-                    g_free(*list);
-                    list++;
-                }
-                g_free(list_head);
+                qmp_for_each_command(ga_print_cmd, NULL);
                 return 0;
             }
             for (j = 0, i = 0, len = strlen(optarg); i < len; i++) {
@@ -1126,7 +1111,7 @@ int main(int argc, char **argv)
             s->deferred_options.log_filepath = log_filepath;
         }
         ga_disable_logging(s);
-        ga_disable_non_whitelisted();
+        qmp_for_each_command(ga_disable_non_whitelisted, NULL);
     } else {
         if (daemonize) {
             become_daemon(pid_filepath);
commit e5d9adbdab972a2172815c1174aed3fabcc448f1
Author: Tomoki Sekiyama <tomoki.sekiyama at hds.com>
Date:   Tue Oct 1 17:09:53 2013 -0400

    qemu-ga: execute fsfreeze-freeze in reverse order of mounts
    
    Currently, fsfreeze-freeze may cause deadlock if a guest has loopback mounts
    of image files in its disk; e.g.:
    
        # mount | grep ^/
        /dev/vda1 / type ext4 (rw,noatime,seclabel,data=ordered)
        /tmp/disk.img on /mnt type ext4 (rw,relatime,seclabel)
    
    To avoid the deadlock, this freezes filesystems in reverse order of mounts.
    
    Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama at hds.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    *fix up commit msg
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index e199738..f453132 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -566,7 +566,7 @@ typedef struct FsMount {
     QTAILQ_ENTRY(FsMount) next;
 } FsMount;
 
-typedef QTAILQ_HEAD(, FsMount) FsMountList;
+typedef QTAILQ_HEAD(FsMountList, FsMount) FsMountList;
 
 static void free_fs_mount_list(FsMountList *mounts)
 {
@@ -728,7 +728,7 @@ int64_t qmp_guest_fsfreeze_freeze(Error **err)
     /* cannot risk guest agent blocking itself on a write in this state */
     ga_set_frozen(ga_state);
 
-    QTAILQ_FOREACH(mount, &mounts, next) {
+    QTAILQ_FOREACH_REVERSE(mount, &mounts, FsMountList, next) {
         fd = qemu_open(mount->dirname, O_RDONLY);
         if (fd == -1) {
             error_setg_errno(err, errno, "failed to open %s", mount->dirname);
commit 6c5f4ead649dd876c5762c468b205563288d5ecd
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Sep 3 13:52:19 2013 -0700

    tcg: Add TCGMemOp
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/tcg.h b/tcg/tcg.h
index 7d0c652..db0abc3 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -197,6 +197,60 @@ typedef enum TCGType {
 #endif
 } TCGType;
 
+/* Constants for qemu_ld and qemu_st for the Memory Operation field.  */
+typedef enum TCGMemOp {
+    MO_8     = 0,
+    MO_16    = 1,
+    MO_32    = 2,
+    MO_64    = 3,
+    MO_SIZE  = 3,   /* Mask for the above.  */
+
+    MO_SIGN  = 4,   /* Sign-extended, otherwise zero-extended.  */
+
+    MO_BSWAP = 8,   /* Host reverse endian.  */
+#ifdef HOST_WORDS_BIGENDIAN
+    MO_LE    = MO_BSWAP,
+    MO_BE    = 0,
+#else
+    MO_LE    = 0,
+    MO_BE    = MO_BSWAP,
+#endif
+#ifdef TARGET_WORDS_BIGENDIAN
+    MO_TE    = MO_BE,
+#else
+    MO_TE    = MO_LE,
+#endif
+
+    /* Combinations of the above, for ease of use.  */
+    MO_UB    = MO_8,
+    MO_UW    = MO_16,
+    MO_UL    = MO_32,
+    MO_SB    = MO_SIGN | MO_8,
+    MO_SW    = MO_SIGN | MO_16,
+    MO_SL    = MO_SIGN | MO_32,
+    MO_Q     = MO_64,
+
+    MO_LEUW  = MO_LE | MO_UW,
+    MO_LEUL  = MO_LE | MO_UL,
+    MO_LESW  = MO_LE | MO_SW,
+    MO_LESL  = MO_LE | MO_SL,
+    MO_LEQ   = MO_LE | MO_Q,
+
+    MO_BEUW  = MO_BE | MO_UW,
+    MO_BEUL  = MO_BE | MO_UL,
+    MO_BESW  = MO_BE | MO_SW,
+    MO_BESL  = MO_BE | MO_SL,
+    MO_BEQ   = MO_BE | MO_Q,
+
+    MO_TEUW  = MO_TE | MO_UW,
+    MO_TEUL  = MO_TE | MO_UL,
+    MO_TESW  = MO_TE | MO_SW,
+    MO_TESL  = MO_TE | MO_SL,
+    MO_TEQ   = MO_TE | MO_Q,
+
+    MO_SSIZE = MO_SIZE | MO_SIGN,
+} TCGMemOp;
+
 typedef tcg_target_ulong TCGArg;
 
 /* Define a type and accessor macros for variables.  Using a struct is
commit ec9135cd6e5e448a3a5c1d75cac611c655ebb3d5
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Oct 3 14:58:00 2013 -0500

    configure: Remove CONFIG_QEMU_LDST_OPTIMIZATION
    
    No longer used.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/configure b/configure
index aeb6bbf..57ee62a 100755
--- a/configure
+++ b/configure
@@ -3791,14 +3791,6 @@ echo "libs_softmmu=$libs_softmmu" >> $config_host_mak
 
 echo "ARCH=$ARCH" >> $config_host_mak
 
-case "$cpu" in
-  aarch64 | arm | i386 | x86_64 | x32 | ppc*)
-    # The TCG interpreter currently does not support ld/st optimization.
-    if test "$tcg_interpreter" = "no" ; then
-        echo "CONFIG_QEMU_LDST_OPTIMIZATION=y" >> $config_host_mak
-    fi
-  ;;
-esac
 if test "$debug_tcg" = "yes" ; then
   echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
 fi
commit 9ecefc84dd12af07394575a75f0689dc748eea78
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Oct 3 14:51:24 2013 -0500

    tcg: Add tcg-be-ldst.h
    
    Move TCGLabelQemuLdst and related stuff out of tcg.h.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/aarch64/tcg-target.c b/tcg/aarch64/tcg-target.c
index 78e1443..04d7ae3 100644
--- a/tcg/aarch64/tcg-target.c
+++ b/tcg/aarch64/tcg-target.c
@@ -10,6 +10,7 @@
  * See the COPYING file in the top-level directory for details.
  */
 
+#include "tcg-be-ldst.h"
 #include "qemu/bitops.h"
 
 #ifndef NDEBUG
@@ -834,33 +835,13 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
     tcg_out_goto(s, (tcg_target_long)lb->raddr);
 }
 
-void tcg_out_tb_finalize(TCGContext *s)
-{
-    int i;
-    for (i = 0; i < s->nb_qemu_ldst_labels; i++) {
-        TCGLabelQemuLdst *label = &s->qemu_ldst_labels[i];
-        if (label->is_ld) {
-            tcg_out_qemu_ld_slow_path(s, label);
-        } else {
-            tcg_out_qemu_st_slow_path(s, label);
-        }
-    }
-}
-
 static void add_qemu_ldst_label(TCGContext *s, int is_ld, int opc,
                                 TCGReg data_reg, TCGReg addr_reg,
                                 int mem_index,
                                 uint8_t *raddr, uint8_t *label_ptr)
 {
-    int idx;
-    TCGLabelQemuLdst *label;
-
-    if (s->nb_qemu_ldst_labels >= TCG_MAX_QEMU_LDST) {
-        tcg_abort();
-    }
+    TCGLabelQemuLdst *label = new_ldst_label(s);
 
-    idx = s->nb_qemu_ldst_labels++;
-    label = &s->qemu_ldst_labels[idx];
     label->is_ld = is_ld;
     label->opc = opc;
     label->datalo_reg = data_reg;
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 622cc49..c0e1466 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -22,6 +22,8 @@
  * THE SOFTWARE.
  */
 
+#include "tcg-be-ldst.h"
+
 /* The __ARM_ARCH define is provided by gcc 4.8.  Construct it otherwise.  */
 #ifndef __ARM_ARCH
 # if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
@@ -1243,15 +1245,8 @@ static void add_qemu_ldst_label(TCGContext *s, int is_ld, int opc,
                                 int addrhi_reg, int mem_index,
                                 uint8_t *raddr, uint8_t *label_ptr)
 {
-    int idx;
-    TCGLabelQemuLdst *label;
-
-    if (s->nb_qemu_ldst_labels >= TCG_MAX_QEMU_LDST) {
-        tcg_abort();
-    }
+    TCGLabelQemuLdst *label = new_ldst_label(s);
 
-    idx = s->nb_qemu_ldst_labels++;
-    label = (TCGLabelQemuLdst *)&s->qemu_ldst_labels[idx];
     label->is_ld = is_ld;
     label->opc = opc;
     label->datalo_reg = data_reg;
@@ -1968,22 +1963,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
     }
 }
 
-#ifdef CONFIG_SOFTMMU
-/* Generate TB finalization at the end of block.  */
-void tcg_out_tb_finalize(TCGContext *s)
-{
-    int i;
-    for (i = 0; i < s->nb_qemu_ldst_labels; i++) {
-        TCGLabelQemuLdst *label = &s->qemu_ldst_labels[i];
-        if (label->is_ld) {
-            tcg_out_qemu_ld_slow_path(s, label);
-        } else {
-            tcg_out_qemu_st_slow_path(s, label);
-        }
-    }
-}
-#endif /* SOFTMMU */
-
 static const TCGTargetOpDef arm_op_defs[] = {
     { INDEX_op_exit_tb, { } },
     { INDEX_op_goto_tb, { } },
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index c1f0741..b865b4b 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -22,6 +22,8 @@
  * THE SOFTWARE.
  */
 
+#include "tcg-be-ldst.h"
+
 #ifndef NDEBUG
 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
 #if TCG_TARGET_REG_BITS == 64
@@ -1455,15 +1457,8 @@ static void add_qemu_ldst_label(TCGContext *s,
                                 uint8_t *raddr,
                                 uint8_t **label_ptr)
 {
-    int idx;
-    TCGLabelQemuLdst *label;
-
-    if (s->nb_qemu_ldst_labels >= TCG_MAX_QEMU_LDST) {
-        tcg_abort();
-    }
+    TCGLabelQemuLdst *label = new_ldst_label(s);
 
-    idx = s->nb_qemu_ldst_labels++;
-    label = (TCGLabelQemuLdst *)&s->qemu_ldst_labels[idx];
     label->is_ld = is_ld;
     label->opc = opc;
     label->datalo_reg = data_reg;
@@ -1628,25 +1623,6 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
     tcg_out_push(s, retaddr);
     tcg_out_jmp(s, (uintptr_t)qemu_st_helpers[s_bits]);
 }
-
-/*
- * Generate TB finalization at the end of block
- */
-void tcg_out_tb_finalize(TCGContext *s)
-{
-    int i;
-    TCGLabelQemuLdst *label;
-
-    /* qemu_ld/st slow paths */
-    for (i = 0; i < s->nb_qemu_ldst_labels; i++) {
-        label = (TCGLabelQemuLdst *)&s->qemu_ldst_labels[i];
-        if (label->is_ld) {
-            tcg_out_qemu_ld_slow_path(s, label);
-        } else {
-            tcg_out_qemu_st_slow_path(s, label);
-        }
-    }
-}
 #endif  /* CONFIG_SOFTMMU */
 
 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 97e33ed..68778c2 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -22,6 +22,8 @@
  * THE SOFTWARE.
  */
 
+#include "tcg-be-ldst.h"
+
 static uint8_t *tb_ret_addr;
 
 #if defined _CALL_DARWIN || defined __APPLE__
@@ -532,15 +534,8 @@ static void add_qemu_ldst_label (TCGContext *s,
                                  uint8_t *raddr,
                                  uint8_t *label_ptr)
 {
-    int idx;
-    TCGLabelQemuLdst *label;
-
-    if (s->nb_qemu_ldst_labels >= TCG_MAX_QEMU_LDST) {
-        tcg_abort();
-    }
+    TCGLabelQemuLdst *label = new_ldst_label(s);
 
-    idx = s->nb_qemu_ldst_labels++;
-    label = (TCGLabelQemuLdst *)&s->qemu_ldst_labels[idx];
     label->is_ld = is_ld;
     label->opc = opc;
     label->datalo_reg = data_reg;
@@ -889,23 +884,6 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
     tcg_out_b(s, LK, (uintptr_t)st_trampolines[l->opc]);
     tcg_out_b(s, 0, (uintptr_t)l->raddr);
 }
-
-void tcg_out_tb_finalize(TCGContext *s)
-{
-    int i;
-    TCGLabelQemuLdst *label;
-
-    /* qemu_ld/st slow paths */
-    for (i = 0; i < s->nb_qemu_ldst_labels; i++) {
-        label = (TCGLabelQemuLdst *) &s->qemu_ldst_labels[i];
-        if (label->is_ld) {
-            tcg_out_qemu_ld_slow_path (s, label);
-        }
-        else {
-            tcg_out_qemu_st_slow_path (s, label);
-        }
-    }
-}
 #endif
 
 #ifdef CONFIG_SOFTMMU
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 332f4d8..12c1f61 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -22,6 +22,8 @@
  * THE SOFTWARE.
  */
 
+#include "tcg-be-ldst.h"
+
 #define TCG_CT_CONST_S16  0x100
 #define TCG_CT_CONST_U16  0x200
 #define TCG_CT_CONST_S32  0x400
@@ -931,15 +933,8 @@ static void add_qemu_ldst_label(TCGContext *s, bool is_ld, int opc,
                                 int data_reg, int addr_reg, int mem_index,
                                 uint8_t *raddr, uint8_t *label_ptr)
 {
-    int idx;
-    TCGLabelQemuLdst *label;
-
-    if (s->nb_qemu_ldst_labels >= TCG_MAX_QEMU_LDST) {
-        tcg_abort();
-    }
+    TCGLabelQemuLdst *label = new_ldst_label(s);
 
-    idx = s->nb_qemu_ldst_labels++;
-    label = (TCGLabelQemuLdst *)&s->qemu_ldst_labels[idx];
     label->is_ld = is_ld;
     label->opc = opc;
     label->datalo_reg = data_reg;
@@ -998,21 +993,6 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 
     tcg_out_b(s, 0, (uintptr_t)lb->raddr);
 }
-
-void tcg_out_tb_finalize(TCGContext *s)
-{
-    int i, n = s->nb_qemu_ldst_labels;
-
-    /* qemu_ld/st slow paths */
-    for (i = 0; i < n; i++) {
-        TCGLabelQemuLdst *label = &s->qemu_ldst_labels[i];
-        if (label->is_ld) {
-            tcg_out_qemu_ld_slow_path(s, label);
-        } else {
-            tcg_out_qemu_st_slow_path(s, label);
-        }
-    }
-}
 #endif /* SOFTMMU */
 
 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
diff --git a/tcg/tcg-be-ldst.h b/tcg/tcg-be-ldst.h
new file mode 100644
index 0000000..2826d29
--- /dev/null
+++ b/tcg/tcg-be-ldst.h
@@ -0,0 +1,90 @@
+/*
+ * TCG Backend Data: load-store optimization only.
+ *
+ * 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.
+ */
+
+#ifdef CONFIG_SOFTMMU
+#define TCG_MAX_QEMU_LDST       640
+
+typedef struct TCGLabelQemuLdst {
+    int is_ld:1;            /* qemu_ld: 1, qemu_st: 0 */
+    int opc:4;
+    TCGReg addrlo_reg;      /* reg index for low word of guest virtual addr */
+    TCGReg addrhi_reg;      /* reg index for high word of guest virtual addr */
+    TCGReg datalo_reg;      /* reg index for low word to be loaded or stored */
+    TCGReg datahi_reg;      /* reg index for high word to be loaded or stored */
+    int mem_index;          /* soft MMU memory index */
+    uint8_t *raddr;         /* gen code addr of the next IR of qemu_ld/st IR */
+    uint8_t *label_ptr[2];  /* label pointers to be updated */
+} TCGLabelQemuLdst;
+
+typedef struct TCGBackendData {
+    int nb_ldst_labels;
+    TCGLabelQemuLdst ldst_labels[TCG_MAX_QEMU_LDST];
+} TCGBackendData;
+
+
+/*
+ * Initialize TB backend data at the beginning of the TB.
+ */
+
+static inline void tcg_out_tb_init(TCGContext *s)
+{
+    s->be->nb_ldst_labels = 0;
+}
+
+/*
+ * Generate TB finalization at the end of block
+ */
+
+static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l);
+static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l);
+
+static void tcg_out_tb_finalize(TCGContext *s)
+{
+    TCGLabelQemuLdst *lb = s->be->ldst_labels;
+    int i, n = s->be->nb_ldst_labels;
+
+    /* qemu_ld/st slow paths */
+    for (i = 0; i < n; i++) {
+        if (lb[i].is_ld) {
+            tcg_out_qemu_ld_slow_path(s, lb + i);
+        } else {
+            tcg_out_qemu_st_slow_path(s, lb + i);
+        }
+    }
+}
+
+/*
+ * Allocate a new TCGLabelQemuLdst entry.
+ */
+
+static inline TCGLabelQemuLdst *new_ldst_label(TCGContext *s)
+{
+    TCGBackendData *be = s->be;
+    int n = be->nb_ldst_labels;
+
+    assert(n < TCG_MAX_QEMU_LDST);
+    be->nb_ldst_labels = n + 1;
+    return &be->ldst_labels[n];
+}
+#else
+#include "tcg-be-null.h"
+#endif /* CONFIG_SOFTMMU */
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 3b88c56..eba080a 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -103,6 +103,9 @@ static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
                        intptr_t arg2);
 static int tcg_target_const_match(tcg_target_long val,
                                   const TCGArgConstraint *arg_ct);
+static void tcg_out_tb_init(TCGContext *s);
+static void tcg_out_tb_finalize(TCGContext *s);
+
 
 TCGOpDef tcg_op_defs[] = {
 #define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
@@ -370,13 +373,7 @@ void tcg_func_start(TCGContext *s)
     s->gen_opc_ptr = s->gen_opc_buf;
     s->gen_opparam_ptr = s->gen_opparam_buf;
 
-#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
-    /* Initialize qemu_ld/st labels to assist code generation at the end of TB
-       for TLB miss cases at the end of TB */
-    s->qemu_ldst_labels = tcg_malloc(sizeof(TCGLabelQemuLdst) *
-                                     TCG_MAX_QEMU_LDST);
-    s->nb_qemu_ldst_labels = 0;
-#endif
+    s->be = tcg_malloc(sizeof(TCGBackendData));
 }
 
 static inline void tcg_temp_alloc(TCGContext *s, int n)
@@ -2297,6 +2294,8 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
     s->code_buf = gen_code_buf;
     s->code_ptr = gen_code_buf;
 
+    tcg_out_tb_init(s);
+
     args = s->gen_opparam_buf;
     op_index = 0;
 
@@ -2370,10 +2369,8 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
 #endif
     }
  the_end:
-#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
     /* Generate TB finalization at the end of block */
     tcg_out_tb_finalize(s);
-#endif
     return -1;
 }
 
diff --git a/tcg/tcg.h b/tcg/tcg.h
index f67fdb6..7d0c652 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -211,24 +211,6 @@ typedef tcg_target_ulong TCGArg;
    are aliases for target_ulong and host pointer sized values respectively.
  */
 
-#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
-/* Macros/structures for qemu_ld/st IR code optimization:
-   TCG_MAX_HELPER_LABELS is defined as same as OPC_BUF_SIZE in exec-all.h. */
-#define TCG_MAX_QEMU_LDST       640
-
-typedef struct TCGLabelQemuLdst {
-    int is_ld:1;            /* qemu_ld: 1, qemu_st: 0 */
-    int opc:4;
-    int addrlo_reg;         /* reg index for low word of guest virtual addr */
-    int addrhi_reg;         /* reg index for high word of guest virtual addr */
-    int datalo_reg;         /* reg index for low word to be loaded or stored */
-    int datahi_reg;         /* reg index for high word to be loaded or stored */
-    int mem_index;          /* soft MMU memory index */
-    uint8_t *raddr;         /* gen code addr of the next IR of qemu_ld/st IR */
-    uint8_t *label_ptr[2];  /* label pointers to be updated */
-} TCGLabelQemuLdst;
-#endif
-
 #ifdef CONFIG_DEBUG_TCG
 #define DEBUG_TCGV 1
 #endif
@@ -488,12 +470,8 @@ struct TCGContext {
 
     TBContext tb_ctx;
 
-#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
-    /* labels info for qemu_ld/st IRs
-       The labels help to generate TLB miss case codes at the end of TB */
-    TCGLabelQemuLdst *qemu_ldst_labels;
-    int nb_qemu_ldst_labels;
-#endif
+    /* The TCGBackendData structure is private to tcg-target.c.  */
+    struct TCGBackendData *be;
 };
 
 extern TCGContext tcg_ctx;
@@ -735,11 +713,6 @@ TCGv_i64 tcg_const_local_i64(int64_t val);
 
 void tcg_register_jit(void *buf, size_t buf_size);
 
-#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
-/* Generate TB finalization at the end of block */
-void tcg_out_tb_finalize(TCGContext *s);
-#endif
-
 /*
  * Memory helpers that will be used by TCG generated code.
  */
commit 3cf246f0d402fdb80bfa2b3c0a20131f394c349d
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Oct 3 14:04:46 2013 -0500

    tcg: Add tcg-be-null.h
    
    This is a no-op backend data implementation, for those targets that
    are not currently using the load/store optimization path.
    
    This is prepatory to always requiring these functions in all backends.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index cd4f1ae..0656d39 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -23,6 +23,8 @@
  * THE SOFTWARE.
  */
 
+#include "tcg-be-null.h"
+
 /*
  * Register definitions
  */
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 5f0a65b..40551cd 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -24,6 +24,8 @@
  * THE SOFTWARE.
  */
 
+#include "tcg-be-null.h"
+
 #if defined(TCG_TARGET_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
 # define TCG_NEED_BSWAP 0
 #else
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 1b44aee..0a4f3be 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -24,6 +24,8 @@
  * THE SOFTWARE.
  */
 
+#include "tcg-be-null.h"
+
 /* We only support generating code for 64-bit mode.  */
 #if TCG_TARGET_REG_BITS != 64
 #error "unsupported code generation mode"
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 9574954..cbd1c91 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -22,6 +22,8 @@
  * THE SOFTWARE.
  */
 
+#include "tcg-be-null.h"
+
 #ifndef NDEBUG
 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
     "%g0",
diff --git a/tcg/tcg-be-null.h b/tcg/tcg-be-null.h
new file mode 100644
index 0000000..74c57d5
--- /dev/null
+++ b/tcg/tcg-be-null.h
@@ -0,0 +1,43 @@
+/*
+ * TCG Backend Data: No backend data
+ *
+ * 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.
+ */
+
+typedef struct TCGBackendData {
+    /* Empty */
+    char dummy;
+} TCGBackendData;
+
+
+/*
+ * Initialize TB backend data at the beginning of the TB.
+ */
+
+static inline void tcg_out_tb_init(TCGContext *s)
+{
+}
+
+/*
+ * Generate TB finalization at the end of block
+ */
+
+static inline void tcg_out_tb_finalize(TCGContext *s)
+{
+}
diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c
index 4976bec..fc80704 100644
--- a/tcg/tci/tcg-target.c
+++ b/tcg/tci/tcg-target.c
@@ -22,6 +22,8 @@
  * THE SOFTWARE.
  */
 
+#include "tcg-be-null.h"
+
 /* TODO list:
  * - See TODO comments in code.
  */
commit dbdbe0cd3124a3e9afa2d1c11da7c6476097bb9d
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Sep 3 14:24:58 2013 -0700

    exec: Delete is_tcg_gen_code and GETRA_EXT
    
    All implementations now boil down to GETRA.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 3ce80d1..6ad05ca 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -320,18 +320,6 @@ extern uintptr_t tci_tb_ptr;
 
 #define GETPC()  (GETRA() - GETPC_ADJ)
 
-/* ??? Delete these once they are no longer used.  */
-bool is_tcg_gen_code(uintptr_t pc_ptr);
-#ifdef GETRA_LDST
-# define GETRA_EXT()  tcg_getra_ext(GETRA())
-static inline uintptr_t tcg_getra_ext(uintptr_t ra)
-{
-    return is_tcg_gen_code(ra) ? GETRA_LDST(ra) : ra;
-}
-#else
-# define GETRA_EXT()  GETRA()
-#endif
-
 #if !defined(CONFIG_USER_ONLY)
 
 void phys_mem_set_alloc(void *(*alloc)(ram_addr_t));
diff --git a/include/exec/softmmu_template.h b/include/exec/softmmu_template.h
index 5bbc56a..5edac51 100644
--- a/include/exec/softmmu_template.h
+++ b/include/exec/softmmu_template.h
@@ -172,7 +172,7 @@ glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr,
                                          int mmu_idx)
 {
     return glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)(env, addr, mmu_idx,
-                                                        GETRA_EXT());
+                                                         GETRA());
 }
 
 #ifndef SOFTMMU_CODE_ACCESS
@@ -285,7 +285,7 @@ glue(glue(helper_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr,
                                          DATA_TYPE val, int mmu_idx)
 {
     glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)(env, addr, val, mmu_idx,
-                                                 GETRA_EXT());
+                                                 GETRA());
 }
 
 #endif /* !defined(SOFTMMU_CODE_ACCESS) */
diff --git a/translate-all.c b/translate-all.c
index e7aff92..aeda54d 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1318,18 +1318,6 @@ static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
     mmap_unlock();
 }
 
-#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
-/* check whether the given addr is in TCG generated code buffer or not */
-bool is_tcg_gen_code(uintptr_t tc_ptr)
-{
-    /* This can be called during code generation, code_gen_buffer_size
-       is used instead of code_gen_ptr for upper boundary checking */
-    return (tc_ptr >= (uintptr_t)tcg_ctx.code_gen_buffer &&
-            tc_ptr < (uintptr_t)(tcg_ctx.code_gen_buffer +
-                    tcg_ctx.code_gen_buffer_size));
-}
-#endif
-
 /* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
    tb[1].tc_ptr. Return NULL if not found */
 static TranslationBlock *tb_find_pc(uintptr_t tc_ptr)
commit 023261ef851b22a04f6c5d76da870051031757a6
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Oct 1 13:47:38 2013 -0700

    tcg-aarch64: Update to helper_ret_*_mmu routines
    
    A minimal update to use the new helpers with the return address argument.
    
    Tested-by: Claudio Fontana <claudio.fontana at linaro.org>
    Reviewed-by: Claudio Fontana <claudio.fontana at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 8dd1594..3ce80d1 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -320,24 +320,6 @@ extern uintptr_t tci_tb_ptr;
 
 #define GETPC()  (GETRA() - GETPC_ADJ)
 
-/* The LDST optimizations splits code generation into fast and slow path.
-   In some implementations, we pass the "logical" return address manually;
-   in others, we must infer the logical return from the true return.  */
-#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
-# if defined(__aarch64__)
-#  define GETRA_LDST(RA)  tcg_getra_ldst(RA)
-static inline uintptr_t tcg_getra_ldst(uintptr_t ra)
-{
-    int32_t b;
-    ra += 4;                    /* skip one instruction */
-    b = *(int32_t *)ra;         /* load the branch insn */
-    b = (b << 6) >> (6 - 2);    /* extract the displacement */
-    ra += b;                    /* apply the displacement  */
-    return ra;
-}
-# endif
-#endif /* CONFIG_QEMU_LDST_OPTIMIZATION */
-
 /* ??? Delete these once they are no longer used.  */
 bool is_tcg_gen_code(uintptr_t pc_ptr);
 #ifdef GETRA_LDST
diff --git a/tcg/aarch64/tcg-target.c b/tcg/aarch64/tcg-target.c
index 6379df1..78e1443 100644
--- a/tcg/aarch64/tcg-target.c
+++ b/tcg/aarch64/tcg-target.c
@@ -778,22 +778,24 @@ static inline void tcg_out_nop(TCGContext *s)
 }
 
 #ifdef CONFIG_SOFTMMU
-/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
-   int mmu_idx) */
+/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
+ *                                     int mmu_idx, uintptr_t ra)
+ */
 static const void * const qemu_ld_helpers[4] = {
-    helper_ldb_mmu,
-    helper_ldw_mmu,
-    helper_ldl_mmu,
-    helper_ldq_mmu,
+    helper_ret_ldub_mmu,
+    helper_ret_lduw_mmu,
+    helper_ret_ldul_mmu,
+    helper_ret_ldq_mmu,
 };
 
-/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
-   uintxx_t val, int mmu_idx) */
+/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
+ *                                     uintxx_t val, int mmu_idx, uintptr_t ra)
+ */
 static const void * const qemu_st_helpers[4] = {
-    helper_stb_mmu,
-    helper_stw_mmu,
-    helper_stl_mmu,
-    helper_stq_mmu,
+    helper_ret_stb_mmu,
+    helper_ret_stw_mmu,
+    helper_ret_stl_mmu,
+    helper_ret_stq_mmu,
 };
 
 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
@@ -802,6 +804,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
     tcg_out_movr(s, 1, TCG_REG_X0, TCG_AREG0);
     tcg_out_movr(s, (TARGET_LONG_BITS == 64), TCG_REG_X1, lb->addrlo_reg);
     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X2, lb->mem_index);
+    tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_X3, (tcg_target_long)lb->raddr);
     tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP,
                  (tcg_target_long)qemu_ld_helpers[lb->opc & 3]);
     tcg_out_callr(s, TCG_REG_TMP);
@@ -822,6 +825,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
     tcg_out_movr(s, (TARGET_LONG_BITS == 64), TCG_REG_X1, lb->addrlo_reg);
     tcg_out_movr(s, 1, TCG_REG_X2, lb->datalo_reg);
     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X3, lb->mem_index);
+    tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_X4, (tcg_target_long)lb->raddr);
     tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP,
                  (tcg_target_long)qemu_st_helpers[lb->opc & 3]);
     tcg_out_callr(s, TCG_REG_TMP);
commit 84fd9dd3f78ced9d41e1160d43862bb620cb462a
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 14 16:44:31 2013 -0700

    tcg: Merge tcg_register_helper into tcg_context_init
    
    Eliminates the repeated checks for having created
    the s->helpers hash table.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 154ae5b..3b88c56 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -288,6 +288,7 @@ void tcg_context_init(TCGContext *s)
     TCGOpDef *def;
     TCGArgConstraint *args_ct;
     int *sorted_args;
+    GHashTable *helper_table;
 
     memset(s, 0, sizeof(*s));
     s->nb_globals = 0;
@@ -314,8 +315,12 @@ void tcg_context_init(TCGContext *s)
     }
 
     /* Register helpers.  */
+    /* Use g_direct_hash/equal for direct pointer comparisons on func.  */
+    s->helpers = helper_table = g_hash_table_new(NULL, NULL);
+
     for (i = 0; i < ARRAY_SIZE(all_helpers); ++i) {
-        tcg_register_helper(all_helpers[i].func, all_helpers[i].name);
+        g_hash_table_insert(helper_table, (gpointer)all_helpers[i].func,
+                            (gpointer)all_helpers[i].name);
     }
 
     tcg_target_init(s);
@@ -653,20 +658,6 @@ int tcg_check_temp_count(void)
 }
 #endif
 
-void tcg_register_helper(void *func, const char *name)
-{
-    TCGContext *s = &tcg_ctx;
-    GHashTable *table = s->helpers;
-
-    if (table == NULL) {
-        /* Use g_direct_hash/equal for direct pointer comparisons on func.  */
-        table = g_hash_table_new(NULL, NULL);
-        s->helpers = table;
-    }
-
-    g_hash_table_insert(table, (gpointer)func, (gpointer)name);
-}
-
 /* Note: we convert the 64 bit args to 32 bit and do some alignment
    and endian swap. Maybe it would be better to do the alignment
    and endian swap in tcg_reg_alloc_call(). */
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 8c5eb42..f67fdb6 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -672,7 +672,6 @@ 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);
 void tcg_dump_ops(TCGContext *s);
 
 void dump_ops(const uint16_t *opc_buf, const TCGArg *opparam_buf);
commit 4953ee62711bd11a55e58b26c8c71b302198363c
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 14 16:06:50 2013 -0700

    tcg: Add tcg-runtime.c helpers to all_helpers
    
    For the few targets that actually use these, we'd not report
    them symbolicly in the tcg opcode logs.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 81218dc..154ae5b 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -264,6 +264,22 @@ typedef struct TCGHelperInfo {
 static const TCGHelperInfo all_helpers[] = {
 #define GEN_HELPER 2
 #include "helper.h"
+
+    /* Include tcg-runtime.c functions.  */
+    { tcg_helper_div_i32, "div_i32" },
+    { tcg_helper_rem_i32, "rem_i32" },
+    { tcg_helper_divu_i32, "divu_i32" },
+    { tcg_helper_remu_i32, "remu_i32" },
+
+    { tcg_helper_shl_i64, "shl_i64" },
+    { tcg_helper_shr_i64, "shr_i64" },
+    { tcg_helper_sar_i64, "sar_i64" },
+    { tcg_helper_div_i64, "div_i64" },
+    { tcg_helper_rem_i64, "rem_i64" },
+    { tcg_helper_divu_i64, "divu_i64" },
+    { tcg_helper_remu_i64, "remu_i64" },
+    { tcg_helper_mulsh_i64, "mulsh_i64" },
+    { tcg_helper_muluh_i64, "muluh_i64" },
 };
 
 void tcg_context_init(TCGContext *s)
commit 100b5e0170e86661aaf830869be930a1a201ed08
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 14 15:57:22 2013 -0700

    tcg: Put target helper data into an array.
    
    One call inside of a loop to tcg_register_helper instead of hundreds
    of sequential calls.
    
    Presumably more icache and branch prediction friendly; resulting binary
    size mostly unchanged on x86_64, as we're trading 32-bit rip-relative
    references in .text for full 64-bit pointers in .rodata.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/include/exec/def-helper.h b/include/exec/def-helper.h
index 022a9ce..73d51f9 100644
--- a/include/exec/def-helper.h
+++ b/include/exec/def-helper.h
@@ -240,8 +240,7 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
 #elif GEN_HELPER == 2
 /* Register helpers.  */
 
-#define DEF_HELPER_FLAGS_0(name, flags, ret) \
-tcg_register_helper(HELPER(name), #name);
+#define DEF_HELPER_FLAGS_0(name, flags, ret)  { HELPER(name), #name },
 
 #define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
 DEF_HELPER_FLAGS_0(name, flags, ret)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index d3ac5fd..81218dc 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -256,9 +256,19 @@ void tcg_pool_reset(TCGContext *s)
 
 #include "helper.h"
 
+typedef struct TCGHelperInfo {
+    void *func;
+    const char *name;
+} TCGHelperInfo;
+
+static const TCGHelperInfo all_helpers[] = {
+#define GEN_HELPER 2
+#include "helper.h"
+};
+
 void tcg_context_init(TCGContext *s)
 {
-    int op, total_args, n;
+    int op, total_args, n, i;
     TCGOpDef *def;
     TCGArgConstraint *args_ct;
     int *sorted_args;
@@ -288,8 +298,9 @@ void tcg_context_init(TCGContext *s)
     }
 
     /* Register helpers.  */
-#define GEN_HELPER 2
-#include "helper.h"
+    for (i = 0; i < ARRAY_SIZE(all_helpers); ++i) {
+        tcg_register_helper(all_helpers[i].func, all_helpers[i].name);
+    }
 
     tcg_target_init(s);
 }
commit f5daeec412b9624ba902bdba26edff88a1694ea6
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 14 15:38:30 2013 -0700

    tcg: Remove stray semi-colons from target-*/helper.h
    
    During GEN_HELPER=1, these are actually stray top-level semi-colons
    which are technically invalid ISO C, but GCC accepts as an extension.
    If we added enough __extension__ markers that we could dare use
    -Wpedantic, we'd see
    
      warning: ISO C does not allow extra ‘;’ outside of a function
    
    This will become a hard error in the next patch, wherein those ; will
    appear in the middle of a data structure.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 732b701..5a0e78c 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -114,7 +114,7 @@ DEF_HELPER_FLAGS_1(tbia, TCG_CALL_NO_RWG, void, env)
 DEF_HELPER_FLAGS_2(tbis, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_FLAGS_1(tb_flush, TCG_CALL_NO_RWG, void, env)
 
-DEF_HELPER_1(halt, void, i64);
+DEF_HELPER_1(halt, void, i64)
 
 DEF_HELPER_FLAGS_0(get_vmtime, TCG_CALL_NO_RWG, i64)
 DEF_HELPER_FLAGS_0(get_walltime, TCG_CALL_NO_RWG, i64)
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 63ae13a..cac9564 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -247,10 +247,10 @@ 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_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)
diff --git a/target-cris/helper.h b/target-cris/helper.h
index 8e8365c..0ac31f5 100644
--- a/target-cris/helper.h
+++ b/target-cris/helper.h
@@ -4,14 +4,14 @@ DEF_HELPER_2(raise_exception, void, env, i32)
 DEF_HELPER_2(tlb_flush_pid, void, env, i32)
 DEF_HELPER_2(spc_write, void, env, i32)
 DEF_HELPER_3(dump, void, i32, i32, i32)
-DEF_HELPER_1(rfe, void, env);
-DEF_HELPER_1(rfn, void, env);
+DEF_HELPER_1(rfe, void, env)
+DEF_HELPER_1(rfn, void, env)
 
 DEF_HELPER_3(movl_sreg_reg, void, env, i32, i32)
 DEF_HELPER_3(movl_reg_sreg, void, env, i32, i32)
 
-DEF_HELPER_FLAGS_1(lz, TCG_CALL_NO_SE, i32, i32);
-DEF_HELPER_FLAGS_4(btst, TCG_CALL_NO_SE, i32, env, i32, i32, i32);
+DEF_HELPER_FLAGS_1(lz, TCG_CALL_NO_SE, i32, i32)
+DEF_HELPER_FLAGS_4(btst, TCG_CALL_NO_SE, i32, env, i32, i32, i32)
 
 DEF_HELPER_FLAGS_4(evaluate_flags_muls, TCG_CALL_NO_SE, i32, env, i32, i32, i32)
 DEF_HELPER_FLAGS_4(evaluate_flags_mulu, TCG_CALL_NO_SE, i32, env, i32, i32, i32)
diff --git a/target-mips/helper.h b/target-mips/helper.h
index ed75e2c..1a8b86d 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -148,7 +148,7 @@ DEF_HELPER_2(mtc0_taghi, void, env, tl)
 DEF_HELPER_2(mtc0_datahi, void, env, tl)
 
 /* MIPS MT functions */
-DEF_HELPER_2(mftgpr, tl, env, i32);
+DEF_HELPER_2(mftgpr, tl, env, i32)
 DEF_HELPER_2(mftlo, tl, env, i32)
 DEF_HELPER_2(mfthi, tl, env, i32)
 DEF_HELPER_2(mftacx, tl, env, i32)
@@ -165,11 +165,11 @@ DEF_HELPER_1(evpe, tl, env)
 #endif /* !CONFIG_USER_ONLY */
 
 /* microMIPS functions */
-DEF_HELPER_4(lwm, void, env, tl, tl, i32);
-DEF_HELPER_4(swm, void, env, tl, tl, i32);
+DEF_HELPER_4(lwm, void, env, tl, tl, i32)
+DEF_HELPER_4(swm, void, env, tl, tl, i32)
 #ifdef TARGET_MIPS64
-DEF_HELPER_4(ldm, void, env, tl, tl, i32);
-DEF_HELPER_4(sdm, void, env, tl, tl, i32);
+DEF_HELPER_4(ldm, void, env, tl, tl, i32)
+DEF_HELPER_4(sdm, void, env, tl, tl, i32)
 #endif
 
 DEF_HELPER_2(fork, void, tl, tl)
@@ -615,7 +615,7 @@ DEF_HELPER_FLAGS_4(dmsubu, 0, void, tl, tl, i32, env)
 DEF_HELPER_FLAGS_1(bitrev, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_FLAGS_3(insv, 0, tl, env, tl, tl)
 #if defined(TARGET_MIPS64)
-DEF_HELPER_FLAGS_3(dinsv, 0, tl, env, tl, tl);
+DEF_HELPER_FLAGS_3(dinsv, 0, tl, env, tl, tl)
 #endif
 
 /* DSP Compare-Pick Sub-class insns */
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 56814b5..6d282bb 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -168,8 +168,8 @@ DEF_HELPER_3(vslo, void, avr, avr, avr)
 DEF_HELPER_3(vsro, void, avr, avr, avr)
 DEF_HELPER_3(vaddcuw, void, avr, avr, avr)
 DEF_HELPER_3(vsubcuw, void, avr, avr, avr)
-DEF_HELPER_2(lvsl, void, avr, tl);
-DEF_HELPER_2(lvsr, void, avr, tl);
+DEF_HELPER_2(lvsl, void, avr, tl)
+DEF_HELPER_2(lvsr, void, avr, tl)
 DEF_HELPER_4(vaddsbs, void, env, avr, avr, avr)
 DEF_HELPER_4(vaddshs, void, env, avr, avr, avr)
 DEF_HELPER_4(vaddsws, void, env, avr, avr, avr)
@@ -220,7 +220,7 @@ DEF_HELPER_5(vmsumuhs, void, env, avr, avr, avr, avr)
 DEF_HELPER_5(vmsumshm, void, env, avr, avr, avr, avr)
 DEF_HELPER_5(vmsumshs, void, env, avr, avr, avr, avr)
 DEF_HELPER_4(vmladduhm, void, avr, avr, avr, avr)
-DEF_HELPER_2(mtvscr, void, env, avr);
+DEF_HELPER_2(mtvscr, void, env, avr)
 DEF_HELPER_3(lvebx, void, env, avr, tl)
 DEF_HELPER_3(lvehx, void, env, avr, tl)
 DEF_HELPER_3(lvewx, void, env, avr, tl)
@@ -349,7 +349,7 @@ DEF_HELPER_2(load_slb_vsid, tl, env, tl)
 DEF_HELPER_FLAGS_1(slbia, TCG_CALL_NO_RWG, void, env)
 DEF_HELPER_FLAGS_2(slbie, TCG_CALL_NO_RWG, void, env, tl)
 #endif
-DEF_HELPER_FLAGS_2(load_sr, TCG_CALL_NO_RWG, tl, env, tl);
+DEF_HELPER_FLAGS_2(load_sr, TCG_CALL_NO_RWG, tl, env, tl)
 DEF_HELPER_FLAGS_3(store_sr, TCG_CALL_NO_RWG, void, env, tl, tl)
 
 DEF_HELPER_FLAGS_1(602_mfrom, TCG_CALL_NO_RWG_SE, tl, tl)
@@ -367,7 +367,7 @@ DEF_HELPER_3(divo, tl, env, tl, tl)
 DEF_HELPER_3(divs, tl, env, tl, tl)
 DEF_HELPER_3(divso, tl, env, tl, tl)
 
-DEF_HELPER_2(load_dcr, tl, env, tl);
+DEF_HELPER_2(load_dcr, tl, env, tl)
 DEF_HELPER_3(store_dcr, void, env, tl, tl)
 
 DEF_HELPER_2(load_dump_spr, void, env, i32)
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 15f7328..2a771b2 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -103,7 +103,7 @@ DEF_HELPER_3(fmuls, f32, env, f32, f32)
 DEF_HELPER_3(fdivs, f32, env, f32, f32)
 
 DEF_HELPER_3(fsmuld, f64, env, f32, f32)
-DEF_HELPER_3(fdmulq, void, env, f64, f64);
+DEF_HELPER_3(fdmulq, void, env, f64, f64)
 
 DEF_HELPER_FLAGS_1(fnegs, TCG_CALL_NO_RWG_SE, f32, f32)
 DEF_HELPER_2(fitod, f64, env, s32)
@@ -156,22 +156,22 @@ DEF_HELPER_FLAGS_3(bshuffle, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
     DEF_HELPER_FLAGS_2(f ## name ## 32s, TCG_CALL_NO_RWG_SE, \
                        i32, i32, i32)
 
-VIS_HELPER(padd);
-VIS_HELPER(psub);
+VIS_HELPER(padd)
+VIS_HELPER(psub)
 #define VIS_CMPHELPER(name)                                              \
     DEF_HELPER_FLAGS_2(f##name##16, TCG_CALL_NO_RWG_SE,      \
                        i64, i64, i64)                                    \
     DEF_HELPER_FLAGS_2(f##name##32, TCG_CALL_NO_RWG_SE,      \
                        i64, i64, i64)
-VIS_CMPHELPER(cmpgt);
-VIS_CMPHELPER(cmpeq);
-VIS_CMPHELPER(cmple);
-VIS_CMPHELPER(cmpne);
+VIS_CMPHELPER(cmpgt)
+VIS_CMPHELPER(cmpeq)
+VIS_CMPHELPER(cmple)
+VIS_CMPHELPER(cmpne)
 #endif
 #undef F_HELPER_0_1
 #undef VIS_HELPER
 #undef VIS_CMPHELPER
-DEF_HELPER_1(compute_psr, void, env);
-DEF_HELPER_1(compute_C_icc, i32, env);
+DEF_HELPER_1(compute_psr, void, env)
+DEF_HELPER_1(compute_C_icc, i32, env)
 
 #include "exec/def-helper.h"
commit 5cd8f6210f83db15702e81b91e40e7079608e6f3
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 14 15:09:39 2013 -0700

    tcg: Move helper registration into tcg_context_init
    
    No longer needs to be done on a per-target basis.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 28ce436..9cb8084 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -140,10 +140,6 @@ void alpha_translate_init(void)
                                      offsetof(CPUAlphaState, usp), "usp");
 #endif
 
-    /* register helpers */
-#define GEN_HELPER 2
-#include "helper.h"
-
     done_init = 1;
 }
 
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 998bde2..5f003e7 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -115,9 +115,6 @@ void arm_translate_init(void)
 #endif
 
     a64_translate_init();
-
-#define GEN_HELPER 2
-#include "helper.h"
 }
 
 static inline TCGv_i32 load_cpu_offset(int offset)
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 617e1b4..5faa44c 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3480,9 +3480,6 @@ void cris_initialize_tcg(void)
 {
     int i;
 
-#define GEN_HELPER 2
-#include "helper.h"
-
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
     cc_x = tcg_global_mem_new(TCG_AREG0,
                               offsetof(CPUCRISState, cc_x), "cc_x");
diff --git a/target-i386/translate.c b/target-i386/translate.c
index be74ebc..eb0ea93 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -8261,10 +8261,6 @@ void optimize_flags_init(void)
     cpu_regs[R_EDI] = tcg_global_mem_new_i32(TCG_AREG0,
                                              offsetof(CPUX86State, regs[R_EDI]), "edi");
 #endif
-
-    /* register helpers */
-#define GEN_HELPER 2
-#include "helper.h"
 }
 
 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index f31e48d..f54b94a 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -108,9 +108,6 @@ void m68k_tcg_init(void)
 
     NULL_QREG = tcg_global_mem_new(TCG_AREG0, -4, "NULL");
     store_dummy = tcg_global_mem_new(TCG_AREG0, -8, "NULL");
-
-#define GEN_HELPER 2
-#include "helper.h"
 }
 
 static inline void qemu_assert(int cond, const char *msg)
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 0673176..1b937b3 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -2024,8 +2024,6 @@ void mb_tcg_init(void)
                           offsetof(CPUMBState, sregs[i]),
                           special_regnames[i]);
     }
-#define GEN_HELPER 2
-#include "helper.h"
 }
 
 void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb, int pc_pos)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index ad43d59..0d8db66 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15886,10 +15886,6 @@ void mips_tcg_init(void)
                                        offsetof(CPUMIPSState, active_fpu.fcr31),
                                        "fcr31");
 
-    /* register helpers */
-#define GEN_HELPER 2
-#include "helper.h"
-
     inited = 1;
 }
 
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 723b77d..8908a2e 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -110,8 +110,6 @@ void openrisc_translate_init(void)
                                       offsetof(CPUOpenRISCState, gpr[i]),
                                       regnames[i]);
     }
-#define GEN_HELPER 2
-#include "helper.h"
 }
 
 /* Writeback SR_F transaltion-space to execution-space.  */
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 9c59f69..66c7771 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -175,10 +175,6 @@ void ppc_translate_init(void)
     cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
                                              offsetof(CPUPPCState, access_type), "access_type");
 
-    /* register helpers */
-#define GEN_HELPER 2
-#include "helper.h"
-
     done_init = 1;
 }
 
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index afe90eb..bc99a37 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -188,10 +188,6 @@ void s390x_translate_init(void)
                                       offsetof(CPUS390XState, fregs[i].d),
                                       cpu_reg_names[i + 16]);
     }
-
-    /* register helpers */
-#define GEN_HELPER 2
-#include "helper.h"
 }
 
 static TCGv_i64 load_reg(int reg)
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index c06b29f..2272eb0 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -143,10 +143,6 @@ void sh4_translate_init(void)
                                               offsetof(CPUSH4State, fregs[i]),
                                               fregnames[i]);
 
-    /* register helpers */
-#define GEN_HELPER 2
-#include "helper.h"
-
     done_init = 1;
 }
 
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 36615f1..dce64c3 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5456,11 +5456,6 @@ void gen_intermediate_code_init(CPUSPARCState *env)
                                                 offsetof(CPUSPARCState, fpr[i]),
                                                 fregnames[i]);
         }
-
-        /* register helpers */
-
-#define GEN_HELPER 2
-#include "helper.h"
     }
 }
 
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index 1246895..4572890 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -74,9 +74,6 @@ void uc32_translate_init(void)
         cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
                                 offsetof(CPUUniCore32State, regs[i]), regnames[i]);
     }
-
-#define GEN_HELPER 2
-#include "helper.h"
 }
 
 static int num_temps;
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 24343bd..06641bb 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -238,8 +238,6 @@ void xtensa_translate_init(void)
                     uregnames[i].name);
         }
     }
-#define GEN_HELPER 2
-#include "helper.h"
 }
 
 static inline bool option_bits_enabled(DisasContext *dc, uint64_t opt)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 9cd5c38..d3ac5fd 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -254,6 +254,8 @@ void tcg_pool_reset(TCGContext *s)
     s->pool_current = NULL;
 }
 
+#include "helper.h"
+
 void tcg_context_init(TCGContext *s)
 {
     int op, total_args, n;
@@ -284,7 +286,11 @@ void tcg_context_init(TCGContext *s)
         sorted_args += n;
         args_ct += n;
     }
-    
+
+    /* Register helpers.  */
+#define GEN_HELPER 2
+#include "helper.h"
+
     tcg_target_init(s);
 }
 
commit e5e84d22a3c31a674f9bb1d9ffcb92c111e13421
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 14 14:41:34 2013 -0700

    target-m68k: Rename helpers.h to helper.h
    
    This brings the m68k target in line with all other targets.
    
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 00a7a08..a508896 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -21,7 +21,7 @@
 #include "cpu.h"
 #include "exec/gdbstub.h"
 
-#include "helpers.h"
+#include "helper.h"
 
 #define SIGNBIT (1u << 31)
 
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
new file mode 100644
index 0000000..2b02450
--- /dev/null
+++ b/target-m68k/helper.h
@@ -0,0 +1,54 @@
+#include "exec/def-helper.h"
+
+DEF_HELPER_1(bitrev, i32, i32)
+DEF_HELPER_1(ff1, i32, i32)
+DEF_HELPER_2(sats, i32, i32, i32)
+DEF_HELPER_2(divu, void, env, i32)
+DEF_HELPER_2(divs, void, env, i32)
+DEF_HELPER_3(addx_cc, i32, env, i32, i32)
+DEF_HELPER_3(subx_cc, i32, env, i32, i32)
+DEF_HELPER_3(shl_cc, i32, env, i32, i32)
+DEF_HELPER_3(shr_cc, i32, env, i32, i32)
+DEF_HELPER_3(sar_cc, i32, env, i32, i32)
+DEF_HELPER_2(xflag_lt, i32, i32, i32)
+DEF_HELPER_2(set_sr, void, env, i32)
+DEF_HELPER_3(movec, void, env, i32, i32)
+
+DEF_HELPER_2(f64_to_i32, f32, env, f64)
+DEF_HELPER_2(f64_to_f32, f32, env, f64)
+DEF_HELPER_2(i32_to_f64, f64, env, i32)
+DEF_HELPER_2(f32_to_f64, f64, env, f32)
+DEF_HELPER_2(iround_f64, f64, env, f64)
+DEF_HELPER_2(itrunc_f64, f64, env, f64)
+DEF_HELPER_2(sqrt_f64, f64, env, f64)
+DEF_HELPER_1(abs_f64, f64, f64)
+DEF_HELPER_1(chs_f64, f64, f64)
+DEF_HELPER_3(add_f64, f64, env, f64, f64)
+DEF_HELPER_3(sub_f64, f64, env, f64, f64)
+DEF_HELPER_3(mul_f64, f64, env, f64, f64)
+DEF_HELPER_3(div_f64, f64, env, f64, f64)
+DEF_HELPER_3(sub_cmp_f64, f64, env, f64, f64)
+DEF_HELPER_2(compare_f64, i32, env, f64)
+
+DEF_HELPER_3(mac_move, void, env, i32, i32)
+DEF_HELPER_3(macmulf, i64, env, i32, i32)
+DEF_HELPER_3(macmuls, i64, env, i32, i32)
+DEF_HELPER_3(macmulu, i64, env, i32, i32)
+DEF_HELPER_2(macsats, void, env, i32)
+DEF_HELPER_2(macsatu, void, env, i32)
+DEF_HELPER_2(macsatf, void, env, i32)
+DEF_HELPER_2(mac_set_flags, void, env, i32)
+DEF_HELPER_2(set_macsr, void, env, i32)
+DEF_HELPER_2(get_macf, i32, env, i64)
+DEF_HELPER_1(get_macs, i32, i64)
+DEF_HELPER_1(get_macu, i32, i64)
+DEF_HELPER_2(get_mac_extf, i32, env, i32)
+DEF_HELPER_2(get_mac_exti, i32, env, i32)
+DEF_HELPER_3(set_mac_extf, void, env, i32, i32)
+DEF_HELPER_3(set_mac_exts, void, env, i32, i32)
+DEF_HELPER_3(set_mac_extu, void, env, i32, i32)
+
+DEF_HELPER_2(flush_flags, void, env, i32)
+DEF_HELPER_2(raise_exception, void, env, i32)
+
+#include "exec/def-helper.h"
diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h
deleted file mode 100644
index 2b02450..0000000
--- a/target-m68k/helpers.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#include "exec/def-helper.h"
-
-DEF_HELPER_1(bitrev, i32, i32)
-DEF_HELPER_1(ff1, i32, i32)
-DEF_HELPER_2(sats, i32, i32, i32)
-DEF_HELPER_2(divu, void, env, i32)
-DEF_HELPER_2(divs, void, env, i32)
-DEF_HELPER_3(addx_cc, i32, env, i32, i32)
-DEF_HELPER_3(subx_cc, i32, env, i32, i32)
-DEF_HELPER_3(shl_cc, i32, env, i32, i32)
-DEF_HELPER_3(shr_cc, i32, env, i32, i32)
-DEF_HELPER_3(sar_cc, i32, env, i32, i32)
-DEF_HELPER_2(xflag_lt, i32, i32, i32)
-DEF_HELPER_2(set_sr, void, env, i32)
-DEF_HELPER_3(movec, void, env, i32, i32)
-
-DEF_HELPER_2(f64_to_i32, f32, env, f64)
-DEF_HELPER_2(f64_to_f32, f32, env, f64)
-DEF_HELPER_2(i32_to_f64, f64, env, i32)
-DEF_HELPER_2(f32_to_f64, f64, env, f32)
-DEF_HELPER_2(iround_f64, f64, env, f64)
-DEF_HELPER_2(itrunc_f64, f64, env, f64)
-DEF_HELPER_2(sqrt_f64, f64, env, f64)
-DEF_HELPER_1(abs_f64, f64, f64)
-DEF_HELPER_1(chs_f64, f64, f64)
-DEF_HELPER_3(add_f64, f64, env, f64, f64)
-DEF_HELPER_3(sub_f64, f64, env, f64, f64)
-DEF_HELPER_3(mul_f64, f64, env, f64, f64)
-DEF_HELPER_3(div_f64, f64, env, f64, f64)
-DEF_HELPER_3(sub_cmp_f64, f64, env, f64, f64)
-DEF_HELPER_2(compare_f64, i32, env, f64)
-
-DEF_HELPER_3(mac_move, void, env, i32, i32)
-DEF_HELPER_3(macmulf, i64, env, i32, i32)
-DEF_HELPER_3(macmuls, i64, env, i32, i32)
-DEF_HELPER_3(macmulu, i64, env, i32, i32)
-DEF_HELPER_2(macsats, void, env, i32)
-DEF_HELPER_2(macsatu, void, env, i32)
-DEF_HELPER_2(macsatf, void, env, i32)
-DEF_HELPER_2(mac_set_flags, void, env, i32)
-DEF_HELPER_2(set_macsr, void, env, i32)
-DEF_HELPER_2(get_macf, i32, env, i64)
-DEF_HELPER_1(get_macs, i32, i64)
-DEF_HELPER_1(get_macu, i32, i64)
-DEF_HELPER_2(get_mac_extf, i32, env, i32)
-DEF_HELPER_2(get_mac_exti, i32, env, i32)
-DEF_HELPER_3(set_mac_extf, void, env, i32, i32)
-DEF_HELPER_3(set_mac_exts, void, env, i32, i32)
-DEF_HELPER_3(set_mac_extu, void, env, i32, i32)
-
-DEF_HELPER_2(flush_flags, void, env, i32)
-DEF_HELPER_2(raise_exception, void, env, i32)
-
-#include "exec/def-helper.h"
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 30f7d8b..bbbfd7f 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -17,7 +17,7 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "cpu.h"
-#include "helpers.h"
+#include "helper.h"
 
 #if defined(CONFIG_USER_ONLY)
 
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 0be0a96..f31e48d 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -23,9 +23,9 @@
 #include "tcg-op.h"
 #include "qemu/log.h"
 
-#include "helpers.h"
+#include "helper.h"
 #define GEN_HELPER 1
-#include "helpers.h"
+#include "helper.h"
 
 //#define DEBUG_DISPATCH 1
 
@@ -110,7 +110,7 @@ void m68k_tcg_init(void)
     store_dummy = tcg_global_mem_new(TCG_AREG0, -8, "NULL");
 
 #define GEN_HELPER 2
-#include "helpers.h"
+#include "helper.h"
 }
 
 static inline void qemu_assert(int cond, const char *msg)
commit 6e085f72c6d331fb0e9fc69e3061cd1e5893d9e4
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 14 14:37:06 2013 -0700

    tcg: Use a GHashTable for tcg_find_helper
    
    Slightly changes the interface, in that we now return name
    instead of a TCGHelperInfo structure, which goes away.
    
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/tcg.c b/tcg/tcg.c
index fd7fb6b..9cd5c38 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -623,20 +623,15 @@ int tcg_check_temp_count(void)
 void tcg_register_helper(void *func, const char *name)
 {
     TCGContext *s = &tcg_ctx;
-    int n;
-    if ((s->nb_helpers + 1) > s->allocated_helpers) {
-        n = s->allocated_helpers;
-        if (n == 0) {
-            n = 4;
-        } else {
-            n *= 2;
-        }
-        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
-        s->allocated_helpers = n;
+    GHashTable *table = s->helpers;
+
+    if (table == NULL) {
+        /* Use g_direct_hash/equal for direct pointer comparisons on func.  */
+        table = g_hash_table_new(NULL, NULL);
+        s->helpers = table;
     }
-    s->helpers[s->nb_helpers].func = (uintptr_t)func;
-    s->helpers[s->nb_helpers].name = name;
-    s->nb_helpers++;
+
+    g_hash_table_insert(table, (gpointer)func, (gpointer)name);
 }
 
 /* Note: we convert the 64 bit args to 32 bit and do some alignment
@@ -851,47 +846,14 @@ char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
     return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
 }
 
-static int helper_cmp(const void *p1, const void *p2)
+/* Find helper name.  */
+static inline const char *tcg_find_helper(TCGContext *s, uintptr_t val)
 {
-    const TCGHelperInfo *th1 = p1;
-    const TCGHelperInfo *th2 = p2;
-    if (th1->func < th2->func)
-        return -1;
-    else if (th1->func == th2->func)
-        return 0;
-    else
-        return 1;
-}
-
-/* find helper definition (Note: A hash table would be better) */
-static TCGHelperInfo *tcg_find_helper(TCGContext *s, uintptr_t val)
-{
-    int m, m_min, m_max;
-    TCGHelperInfo *th;
-    uintptr_t v;
-
-    if (unlikely(!s->helpers_sorted)) {
-        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
-              helper_cmp);
-        s->helpers_sorted = 1;
-    }
-
-    /* binary search */
-    m_min = 0;
-    m_max = s->nb_helpers - 1;
-    while (m_min <= m_max) {
-        m = (m_min + m_max) >> 1;
-        th = &s->helpers[m];
-        v = th->func;
-        if (v == val)
-            return th;
-        else if (val < v) {
-            m_max = m - 1;
-        } else {
-            m_min = m + 1;
-        }
+    const char *ret = NULL;
+    if (s->helpers) {
+        ret = g_hash_table_lookup(s->helpers, (gpointer)val);
     }
-    return NULL;
+    return ret;
 }
 
 static const char * const cond_name[] =
@@ -976,7 +938,7 @@ void tcg_dump_ops(TCGContext *s)
             }
         } else if (c == INDEX_op_movi_i32 || c == INDEX_op_movi_i64) {
             tcg_target_ulong val;
-            TCGHelperInfo *th;
+            const char *name;
 
             nb_oargs = def->nb_oargs;
             nb_iargs = def->nb_iargs;
@@ -984,9 +946,9 @@ void tcg_dump_ops(TCGContext *s)
             qemu_log(" %s %s,$", def->name,
                      tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
             val = args[1];
-            th = tcg_find_helper(s, val);
-            if (th) {
-                qemu_log("%s", th->name);
+            name = tcg_find_helper(s, val);
+            if (name) {
+                qemu_log("%s", name);
             } else {
                 if (c == INDEX_op_movi_i32) {
                     qemu_log("0x%x", (uint32_t)val);
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 20543f6..8c5eb42 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -405,11 +405,6 @@ typedef struct TCGTemp {
     const char *name;
 } TCGTemp;
 
-typedef struct TCGHelperInfo {
-    uintptr_t func;
-    const char *name;
-} TCGHelperInfo;
-
 typedef struct TCGContext TCGContext;
 
 struct TCGContext {
@@ -447,10 +442,7 @@ struct TCGContext {
     uint8_t *code_ptr;
     TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */
 
-    TCGHelperInfo *helpers;
-    int nb_helpers;
-    int allocated_helpers;
-    int helpers_sorted;
+    GHashTable *helpers;
 
 #ifdef CONFIG_PROFILER
     /* profiling info */
commit 7c57df0d852a9a9faf9068ff235886c8b28b113e
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 14 14:29:35 2013 -0700

    tcg: Delete tcg_helper_get_name declaration
    
    The function was deleted in 4dc81f2822187f4503d4bdb76785cafa5b28db0b.
    
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/tcg.h b/tcg/tcg.h
index 902c751..20543f6 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -681,7 +681,6 @@ TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr, TCGArg *args,
 
 /* only used for debugging purposes */
 void tcg_register_helper(void *func, const char *name);
-const char *tcg_helper_get_name(TCGContext *s, void *func);
 void tcg_dump_ops(TCGContext *s);
 
 void dump_ops(const uint16_t *opc_buf, const TCGArg *opparam_buf);
commit 802b5081233a6b643a8b135a5facaf14bafaa77d
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 25 12:11:31 2013 -0700

    tcg-hppa: Remove tcg backend
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/MAINTAINERS b/MAINTAINERS
index ab8166a..d59651e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -793,11 +793,6 @@ M: Andrzej Zaborowski <balrogg at gmail.com>
 S: Maintained
 F: tcg/arm/
 
-HPPA target
-M: Richard Henderson <rth at twiddle.net>
-S: Maintained
-F: tcg/hppa/
-
 i386 target
 M: qemu-devel at nongnu.org
 S: Maintained
diff --git a/configure b/configure
index 23dbaaf..aeb6bbf 100755
--- a/configure
+++ b/configure
@@ -429,9 +429,6 @@ case "$cpu" in
   aarch64)
     cpu="aarch64"
   ;;
-  hppa|parisc|parisc64)
-    cpu="hppa"
-  ;;
   mips*)
     cpu="mips"
   ;;
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
deleted file mode 100644
index 236b39c..0000000
--- a/tcg/hppa/tcg-target.c
+++ /dev/null
@@ -1,1831 +0,0 @@
-/*
- * Tiny Code Generator for QEMU
- *
- * Copyright (c) 2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#if TCG_TARGET_REG_BITS != 32
-#error unsupported
-#endif
-
-#ifndef NDEBUG
-static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
-    "%r0", "%r1", "%rp", "%r3", "%r4", "%r5", "%r6", "%r7",
-    "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
-    "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23",
-    "%r24", "%r25", "%r26", "%dp", "%ret0", "%ret1", "%sp", "%r31",
-};
-#endif
-
-/* This is an 8 byte temp slot in the stack frame.  */
-#define STACK_TEMP_OFS -16
-
-#ifdef CONFIG_USE_GUEST_BASE
-#define TCG_GUEST_BASE_REG TCG_REG_R16
-#else
-#define TCG_GUEST_BASE_REG TCG_REG_R0
-#endif
-
-static const int tcg_target_reg_alloc_order[] = {
-    TCG_REG_R4,
-    TCG_REG_R5,
-    TCG_REG_R6,
-    TCG_REG_R7,
-    TCG_REG_R8,
-    TCG_REG_R9,
-    TCG_REG_R10,
-    TCG_REG_R11,
-    TCG_REG_R12,
-    TCG_REG_R13,
-
-    TCG_REG_R17,
-    TCG_REG_R14,
-    TCG_REG_R15,
-    TCG_REG_R16,
-
-    TCG_REG_R26,
-    TCG_REG_R25,
-    TCG_REG_R24,
-    TCG_REG_R23,
-
-    TCG_REG_RET0,
-    TCG_REG_RET1,
-};
-
-static const int tcg_target_call_iarg_regs[4] = {
-    TCG_REG_R26,
-    TCG_REG_R25,
-    TCG_REG_R24,
-    TCG_REG_R23,
-};
-
-static const int tcg_target_call_oarg_regs[2] = {
-    TCG_REG_RET0,
-    TCG_REG_RET1,
-};
-
-/* True iff val fits a signed field of width BITS.  */
-static inline int check_fit_tl(tcg_target_long val, unsigned int bits)
-{
-    return (val << ((sizeof(tcg_target_long) * 8 - bits))
-            >> (sizeof(tcg_target_long) * 8 - bits)) == val;
-}
-
-/* True iff depi can be used to compute (reg | MASK).
-   Accept a bit pattern like:
-      0....01....1
-      1....10....0
-      0..01..10..0
-   Copied from gcc sources.  */
-static inline int or_mask_p(tcg_target_ulong mask)
-{
-    if (mask == 0 || mask == -1) {
-        return 0;
-    }
-    mask += mask & -mask;
-    return (mask & (mask - 1)) == 0;
-}
-
-/* True iff depi or extru can be used to compute (reg & mask).
-   Accept a bit pattern like these:
-      0....01....1
-      1....10....0
-      1..10..01..1
-   Copied from gcc sources.  */
-static inline int and_mask_p(tcg_target_ulong mask)
-{
-    return or_mask_p(~mask);
-}
-
-static int low_sign_ext(int val, int len)
-{
-    return (((val << 1) & ~(-1u << len)) | ((val >> (len - 1)) & 1));
-}
-
-static int reassemble_12(int as12)
-{
-    return (((as12 & 0x800) >> 11) |
-            ((as12 & 0x400) >> 8) |
-            ((as12 & 0x3ff) << 3));
-}
-
-static int reassemble_17(int as17)
-{
-    return (((as17 & 0x10000) >> 16) |
-            ((as17 & 0x0f800) << 5) |
-            ((as17 & 0x00400) >> 8) |
-            ((as17 & 0x003ff) << 3));
-}
-
-static int reassemble_21(int as21)
-{
-    return (((as21 & 0x100000) >> 20) |
-            ((as21 & 0x0ffe00) >> 8) |
-            ((as21 & 0x000180) << 7) |
-            ((as21 & 0x00007c) << 14) |
-            ((as21 & 0x000003) << 12));
-}
-
-/* ??? Bizzarely, there is no PCREL12F relocation type.  I guess all
-   such relocations are simply fully handled by the assembler.  */
-#define R_PARISC_PCREL12F  R_PARISC_NONE
-
-static void patch_reloc(uint8_t *code_ptr, int type,
-                        intptr_t value, intptr_t addend)
-{
-    uint32_t *insn_ptr = (uint32_t *)code_ptr;
-    uint32_t insn = *insn_ptr;
-    intptr_t pcrel;
-
-    value += addend;
-    pcrel = (value - ((intptr_t)code_ptr + 8)) >> 2;
-
-    switch (type) {
-    case R_PARISC_PCREL12F:
-        assert(check_fit_tl(pcrel, 12));
-        /* ??? We assume all patches are forward.  See tcg_out_brcond
-           re setting the NUL bit on the branch and eliding the nop.  */
-        assert(pcrel >= 0);
-        insn &= ~0x1ffdu;
-        insn |= reassemble_12(pcrel);
-        break;
-    case R_PARISC_PCREL17F:
-        assert(check_fit_tl(pcrel, 17));
-        insn &= ~0x1f1ffdu;
-        insn |= reassemble_17(pcrel);
-        break;
-    default:
-        tcg_abort();
-    }
-
-    *insn_ptr = insn;
-}
-
-/* parse target specific constraints */
-static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
-{
-    const char *ct_str;
-
-    ct_str = *pct_str;
-    switch (ct_str[0]) {
-    case 'r':
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
-        break;
-    case 'L': /* qemu_ld/st constraint */
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R26);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R25);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R24);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R23);
-        break;
-    case 'Z':
-        ct->ct |= TCG_CT_CONST_0;
-        break;
-    case 'I':
-        ct->ct |= TCG_CT_CONST_S11;
-        break;
-    case 'J':
-        ct->ct |= TCG_CT_CONST_S5;
-	break;
-    case 'K':
-        ct->ct |= TCG_CT_CONST_MS11;
-        break;
-    case 'M':
-        ct->ct |= TCG_CT_CONST_AND;
-        break;
-    case 'O':
-        ct->ct |= TCG_CT_CONST_OR;
-        break;
-    default:
-        return -1;
-    }
-    ct_str++;
-    *pct_str = ct_str;
-    return 0;
-}
-
-/* test if a constant matches the constraint */
-static int tcg_target_const_match(tcg_target_long val,
-                                  const TCGArgConstraint *arg_ct)
-{
-    int ct = arg_ct->ct;
-    if (ct & TCG_CT_CONST) {
-        return 1;
-    } else if (ct & TCG_CT_CONST_0) {
-        return val == 0;
-    } else if (ct & TCG_CT_CONST_S5) {
-        return check_fit_tl(val, 5);
-    } else if (ct & TCG_CT_CONST_S11) {
-        return check_fit_tl(val, 11);
-    } else if (ct & TCG_CT_CONST_MS11) {
-        return check_fit_tl(-val, 11);
-    } else if (ct & TCG_CT_CONST_AND) {
-        return and_mask_p(val);
-    } else if (ct & TCG_CT_CONST_OR) {
-        return or_mask_p(val);
-    }
-    return 0;
-}
-
-#define INSN_OP(x)       ((x) << 26)
-#define INSN_EXT3BR(x)   ((x) << 13)
-#define INSN_EXT3SH(x)   ((x) << 10)
-#define INSN_EXT4(x)     ((x) << 6)
-#define INSN_EXT5(x)     (x)
-#define INSN_EXT6(x)     ((x) << 6)
-#define INSN_EXT7(x)     ((x) << 6)
-#define INSN_EXT8A(x)    ((x) << 6)
-#define INSN_EXT8B(x)    ((x) << 5)
-#define INSN_T(x)        (x)
-#define INSN_R1(x)       ((x) << 16)
-#define INSN_R2(x)       ((x) << 21)
-#define INSN_DEP_LEN(x)  (32 - (x))
-#define INSN_SHDEP_CP(x) ((31 - (x)) << 5)
-#define INSN_SHDEP_P(x)  ((x) << 5)
-#define INSN_COND(x)     ((x) << 13)
-#define INSN_IM11(x)     low_sign_ext(x, 11)
-#define INSN_IM14(x)     low_sign_ext(x, 14)
-#define INSN_IM5(x)      (low_sign_ext(x, 5) << 16)
-
-#define COND_NEVER   0
-#define COND_EQ      1
-#define COND_LT      2
-#define COND_LE      3
-#define COND_LTU     4
-#define COND_LEU     5
-#define COND_SV      6
-#define COND_OD      7
-#define COND_FALSE   8
-
-#define INSN_ADD	(INSN_OP(0x02) | INSN_EXT6(0x18))
-#define INSN_ADDC	(INSN_OP(0x02) | INSN_EXT6(0x1c))
-#define INSN_ADDI	(INSN_OP(0x2d))
-#define INSN_ADDIL	(INSN_OP(0x0a))
-#define INSN_ADDL	(INSN_OP(0x02) | INSN_EXT6(0x28))
-#define INSN_AND	(INSN_OP(0x02) | INSN_EXT6(0x08))
-#define INSN_ANDCM	(INSN_OP(0x02) | INSN_EXT6(0x00))
-#define INSN_COMCLR	(INSN_OP(0x02) | INSN_EXT6(0x22))
-#define INSN_COMICLR	(INSN_OP(0x24))
-#define INSN_DEP	(INSN_OP(0x35) | INSN_EXT3SH(3))
-#define INSN_DEPI	(INSN_OP(0x35) | INSN_EXT3SH(7))
-#define INSN_EXTRS	(INSN_OP(0x34) | INSN_EXT3SH(7))
-#define INSN_EXTRU	(INSN_OP(0x34) | INSN_EXT3SH(6))
-#define INSN_LDIL	(INSN_OP(0x08))
-#define INSN_LDO	(INSN_OP(0x0d))
-#define INSN_MTCTL	(INSN_OP(0x00) | INSN_EXT8B(0xc2))
-#define INSN_OR		(INSN_OP(0x02) | INSN_EXT6(0x09))
-#define INSN_SHD	(INSN_OP(0x34) | INSN_EXT3SH(2))
-#define INSN_SUB	(INSN_OP(0x02) | INSN_EXT6(0x10))
-#define INSN_SUBB	(INSN_OP(0x02) | INSN_EXT6(0x14))
-#define INSN_SUBI	(INSN_OP(0x25))
-#define INSN_VEXTRS	(INSN_OP(0x34) | INSN_EXT3SH(5))
-#define INSN_VEXTRU	(INSN_OP(0x34) | INSN_EXT3SH(4))
-#define INSN_VSHD	(INSN_OP(0x34) | INSN_EXT3SH(0))
-#define INSN_XOR	(INSN_OP(0x02) | INSN_EXT6(0x0a))
-#define INSN_ZDEP	(INSN_OP(0x35) | INSN_EXT3SH(2))
-#define INSN_ZVDEP	(INSN_OP(0x35) | INSN_EXT3SH(0))
-
-#define INSN_BL         (INSN_OP(0x3a) | INSN_EXT3BR(0))
-#define INSN_BL_N       (INSN_OP(0x3a) | INSN_EXT3BR(0) | 2)
-#define INSN_BLR        (INSN_OP(0x3a) | INSN_EXT3BR(2))
-#define INSN_BV         (INSN_OP(0x3a) | INSN_EXT3BR(6))
-#define INSN_BV_N       (INSN_OP(0x3a) | INSN_EXT3BR(6) | 2)
-#define INSN_BLE_SR4    (INSN_OP(0x39) | (1 << 13))
-
-#define INSN_LDB        (INSN_OP(0x10))
-#define INSN_LDH        (INSN_OP(0x11))
-#define INSN_LDW        (INSN_OP(0x12))
-#define INSN_LDWM       (INSN_OP(0x13))
-#define INSN_FLDDS      (INSN_OP(0x0b) | INSN_EXT4(0) | (1 << 12))
-
-#define INSN_LDBX	(INSN_OP(0x03) | INSN_EXT4(0))
-#define INSN_LDHX	(INSN_OP(0x03) | INSN_EXT4(1))
-#define INSN_LDWX       (INSN_OP(0x03) | INSN_EXT4(2))
-
-#define INSN_STB        (INSN_OP(0x18))
-#define INSN_STH        (INSN_OP(0x19))
-#define INSN_STW        (INSN_OP(0x1a))
-#define INSN_STWM       (INSN_OP(0x1b))
-#define INSN_FSTDS      (INSN_OP(0x0b) | INSN_EXT4(8) | (1 << 12))
-
-#define INSN_COMBT      (INSN_OP(0x20))
-#define INSN_COMBF      (INSN_OP(0x22))
-#define INSN_COMIBT     (INSN_OP(0x21))
-#define INSN_COMIBF     (INSN_OP(0x23))
-
-/* supplied by libgcc */
-extern void *__canonicalize_funcptr_for_compare(const void *);
-
-static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
-{
-    /* PA1.1 defines COPY as OR r,0,t; PA2.0 defines COPY as LDO 0(r),t
-       but hppa-dis.c is unaware of this definition */
-    if (ret != arg) {
-        tcg_out32(s, INSN_OR | INSN_T(ret) | INSN_R1(arg)
-                  | INSN_R2(TCG_REG_R0));
-    }
-}
-
-static void tcg_out_movi(TCGContext *s, TCGType type,
-                         TCGReg ret, tcg_target_long arg)
-{
-    if (check_fit_tl(arg, 14)) {
-        tcg_out32(s, INSN_LDO | INSN_R1(ret)
-                  | INSN_R2(TCG_REG_R0) | INSN_IM14(arg));
-    } else {
-        uint32_t hi, lo;
-        hi = arg >> 11;
-        lo = arg & 0x7ff;
-
-        tcg_out32(s, INSN_LDIL | INSN_R2(ret) | reassemble_21(hi));
-        if (lo) {
-            tcg_out32(s, INSN_LDO | INSN_R1(ret)
-                      | INSN_R2(ret) | INSN_IM14(lo));
-        }
-    }
-}
-
-static void tcg_out_ldst(TCGContext *s, int ret, int addr,
-                         tcg_target_long offset, int op)
-{
-    if (!check_fit_tl(offset, 14)) {
-        uint32_t hi, lo, op;
-
-        hi = offset >> 11;
-        lo = offset & 0x7ff;
-
-        if (addr == TCG_REG_R0) {
-            op = INSN_LDIL | INSN_R2(TCG_REG_R1);
-        } else {
-            op = INSN_ADDIL | INSN_R2(addr);
-        }
-        tcg_out32(s, op | reassemble_21(hi));
-
-        addr = TCG_REG_R1;
-	offset = lo;
-    }
-
-    if (ret != addr || offset != 0 || op != INSN_LDO) {
-        tcg_out32(s, op | INSN_R1(ret) | INSN_R2(addr) | INSN_IM14(offset));
-    }
-}
-
-/* This function is required by tcg.c.  */
-static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
-                              TCGReg arg1, intptr_t arg2)
-{
-    tcg_out_ldst(s, ret, arg1, arg2, INSN_LDW);
-}
-
-/* This function is required by tcg.c.  */
-static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg ret,
-                              TCGReg arg1, intptr_t arg2)
-{
-    tcg_out_ldst(s, ret, arg1, arg2, INSN_STW);
-}
-
-static void tcg_out_ldst_index(TCGContext *s, int data,
-                               int base, int index, int op)
-{
-    tcg_out32(s, op | INSN_T(data) | INSN_R1(index) | INSN_R2(base));
-}
-
-static inline void tcg_out_addi2(TCGContext *s, int ret, int arg1,
-                                 tcg_target_long val)
-{
-    tcg_out_ldst(s, ret, arg1, val, INSN_LDO);
-}
-
-/* This function is required by tcg.c.  */
-static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
-{
-    tcg_out_addi2(s, reg, reg, val);
-}
-
-static inline void tcg_out_arith(TCGContext *s, int t, int r1, int r2, int op)
-{
-    tcg_out32(s, op | INSN_T(t) | INSN_R1(r1) | INSN_R2(r2));
-}
-
-static inline void tcg_out_arithi(TCGContext *s, int t, int r1,
-                                  tcg_target_long val, int op)
-{
-    assert(check_fit_tl(val, 11));
-    tcg_out32(s, op | INSN_R1(t) | INSN_R2(r1) | INSN_IM11(val));
-}
-
-static inline void tcg_out_nop(TCGContext *s)
-{
-    tcg_out_arith(s, TCG_REG_R0, TCG_REG_R0, TCG_REG_R0, INSN_OR);
-}
-
-static inline void tcg_out_mtctl_sar(TCGContext *s, int arg)
-{
-    tcg_out32(s, INSN_MTCTL | INSN_R2(11) | INSN_R1(arg));
-}
-
-/* Extract LEN bits at position OFS from ARG and place in RET.
-   Note that here the bit ordering is reversed from the PA-RISC
-   standard, such that the right-most bit is 0.  */
-static inline void tcg_out_extr(TCGContext *s, int ret, int arg,
-                                unsigned ofs, unsigned len, int sign)
-{
-    assert(ofs < 32 && len <= 32 - ofs);
-    tcg_out32(s, (sign ? INSN_EXTRS : INSN_EXTRU)
-              | INSN_R1(ret) | INSN_R2(arg)
-              | INSN_SHDEP_P(31 - ofs) | INSN_DEP_LEN(len));
-}
-
-/* Likewise with OFS interpreted little-endian.  */
-static inline void tcg_out_dep(TCGContext *s, int ret, int arg,
-                               unsigned ofs, unsigned len)
-{
-    assert(ofs < 32 && len <= 32 - ofs);
-    tcg_out32(s, INSN_DEP | INSN_R2(ret) | INSN_R1(arg)
-              | INSN_SHDEP_CP(31 - ofs) | INSN_DEP_LEN(len));
-}
-
-static inline void tcg_out_depi(TCGContext *s, int ret, int arg,
-                                unsigned ofs, unsigned len)
-{
-    assert(ofs < 32 && len <= 32 - ofs);
-    tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(arg)
-              | INSN_SHDEP_CP(31 - ofs) | INSN_DEP_LEN(len));
-}
-
-static inline void tcg_out_shd(TCGContext *s, int ret, int hi, int lo,
-                               unsigned count)
-{
-    assert(count < 32);
-    tcg_out32(s, INSN_SHD | INSN_R1(hi) | INSN_R2(lo) | INSN_T(ret)
-              | INSN_SHDEP_CP(count));
-}
-
-static void tcg_out_vshd(TCGContext *s, int ret, int hi, int lo, int creg)
-{
-    tcg_out_mtctl_sar(s, creg);
-    tcg_out32(s, INSN_VSHD | INSN_T(ret) | INSN_R1(hi) | INSN_R2(lo));
-}
-
-static void tcg_out_ori(TCGContext *s, int ret, int arg, tcg_target_ulong m)
-{
-    int bs0, bs1;
-
-    /* Note that the argument is constrained to match or_mask_p.  */
-    for (bs0 = 0; bs0 < 32; bs0++) {
-        if ((m & (1u << bs0)) != 0) {
-            break;
-        }
-    }
-    for (bs1 = bs0; bs1 < 32; bs1++) {
-        if ((m & (1u << bs1)) == 0) {
-            break;
-        }
-    }
-    assert(bs1 == 32 || (1ul << bs1) > m);
-
-    tcg_out_mov(s, TCG_TYPE_I32, ret, arg);
-    tcg_out_depi(s, ret, -1, bs0, bs1 - bs0);
-}
-
-static void tcg_out_andi(TCGContext *s, int ret, int arg, tcg_target_ulong m)
-{
-    int ls0, ls1, ms0;
-
-    /* Note that the argument is constrained to match and_mask_p.  */
-    for (ls0 = 0; ls0 < 32; ls0++) {
-        if ((m & (1u << ls0)) == 0) {
-            break;
-        }
-    }
-    for (ls1 = ls0; ls1 < 32; ls1++) {
-        if ((m & (1u << ls1)) != 0) {
-            break;
-        }
-    }
-    for (ms0 = ls1; ms0 < 32; ms0++) {
-        if ((m & (1u << ms0)) == 0) {
-            break;
-        }
-    }
-    assert (ms0 == 32);
-
-    if (ls1 == 32) {
-        tcg_out_extr(s, ret, arg, 0, ls0, 0);
-    } else {
-        tcg_out_mov(s, TCG_TYPE_I32, ret, arg);
-        tcg_out_depi(s, ret, 0, ls0, ls1 - ls0);
-    }
-}
-
-static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg)
-{
-    tcg_out_extr(s, ret, arg, 0, 8, 1);
-}
-
-static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg)
-{
-    tcg_out_extr(s, ret, arg, 0, 16, 1);
-}
-
-static void tcg_out_shli(TCGContext *s, int ret, int arg, int count)
-{
-    count &= 31;
-    tcg_out32(s, INSN_ZDEP | INSN_R2(ret) | INSN_R1(arg)
-              | INSN_SHDEP_CP(31 - count) | INSN_DEP_LEN(32 - count));
-}
-
-static void tcg_out_shl(TCGContext *s, int ret, int arg, int creg)
-{
-    tcg_out_arithi(s, TCG_REG_R20, creg, 31, INSN_SUBI);
-    tcg_out_mtctl_sar(s, TCG_REG_R20);
-    tcg_out32(s, INSN_ZVDEP | INSN_R2(ret) | INSN_R1(arg) | INSN_DEP_LEN(32));
-}
-
-static void tcg_out_shri(TCGContext *s, int ret, int arg, int count)
-{
-    count &= 31;
-    tcg_out_extr(s, ret, arg, count, 32 - count, 0);
-}
-
-static void tcg_out_shr(TCGContext *s, int ret, int arg, int creg)
-{
-    tcg_out_vshd(s, ret, TCG_REG_R0, arg, creg);
-}
-
-static void tcg_out_sari(TCGContext *s, int ret, int arg, int count)
-{
-    count &= 31;
-    tcg_out_extr(s, ret, arg, count, 32 - count, 1);
-}
-
-static void tcg_out_sar(TCGContext *s, int ret, int arg, int creg)
-{
-    tcg_out_arithi(s, TCG_REG_R20, creg, 31, INSN_SUBI);
-    tcg_out_mtctl_sar(s, TCG_REG_R20);
-    tcg_out32(s, INSN_VEXTRS | INSN_R1(ret) | INSN_R2(arg) | INSN_DEP_LEN(32));
-}
-
-static void tcg_out_rotli(TCGContext *s, int ret, int arg, int count)
-{
-    count &= 31;
-    tcg_out_shd(s, ret, arg, arg, 32 - count);
-}
-
-static void tcg_out_rotl(TCGContext *s, int ret, int arg, int creg)
-{
-    tcg_out_arithi(s, TCG_REG_R20, creg, 32, INSN_SUBI);
-    tcg_out_vshd(s, ret, arg, arg, TCG_REG_R20);
-}
-
-static void tcg_out_rotri(TCGContext *s, int ret, int arg, int count)
-{
-    count &= 31;
-    tcg_out_shd(s, ret, arg, arg, count);
-}
-
-static void tcg_out_rotr(TCGContext *s, int ret, int arg, int creg)
-{
-    tcg_out_vshd(s, ret, arg, arg, creg);
-}
-
-static void tcg_out_bswap16(TCGContext *s, int ret, int arg, int sign)
-{
-    if (ret != arg) {
-        tcg_out_mov(s, TCG_TYPE_I32, ret, arg); /* arg =  xxAB */
-    }
-    tcg_out_dep(s, ret, ret, 16, 8);          /* ret =  xBAB */
-    tcg_out_extr(s, ret, ret, 8, 16, sign);   /* ret =  ..BA */
-}
-
-static void tcg_out_bswap32(TCGContext *s, int ret, int arg, int temp)
-{
-                                          /* arg =  ABCD */
-    tcg_out_rotri(s, temp, arg, 16);      /* temp = CDAB */
-    tcg_out_dep(s, temp, temp, 16, 8);    /* temp = CBAB */
-    tcg_out_shd(s, ret, arg, temp, 8);    /* ret =  DCBA */
-}
-
-static void tcg_out_call(TCGContext *s, const void *func)
-{
-    tcg_target_long val, hi, lo, disp;
-
-    val = (uint32_t)__canonicalize_funcptr_for_compare(func);
-    disp = (val - ((tcg_target_long)s->code_ptr + 8)) >> 2;
-
-    if (check_fit_tl(disp, 17)) {
-        tcg_out32(s, INSN_BL_N | INSN_R2(TCG_REG_RP) | reassemble_17(disp));
-    } else {
-        hi = val >> 11;
-        lo = val & 0x7ff;
-
-        tcg_out32(s, INSN_LDIL | INSN_R2(TCG_REG_R20) | reassemble_21(hi));
-        tcg_out32(s, INSN_BLE_SR4 | INSN_R2(TCG_REG_R20)
-                  | reassemble_17(lo >> 2));
-        tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_RP, TCG_REG_R31);
-    }
-}
-
-static void tcg_out_xmpyu(TCGContext *s, int retl, int reth,
-                          int arg1, int arg2)
-{
-    /* Store both words into the stack for copy to the FPU.  */
-    tcg_out_ldst(s, arg1, TCG_REG_CALL_STACK, STACK_TEMP_OFS, INSN_STW);
-    tcg_out_ldst(s, arg2, TCG_REG_CALL_STACK, STACK_TEMP_OFS + 4, INSN_STW);
-
-    /* Load both words into the FPU at the same time.  We get away
-       with this because we can address the left and right half of the
-       FPU registers individually once loaded.  */
-    /* fldds stack_temp(sp),fr22 */
-    tcg_out32(s, INSN_FLDDS | INSN_R2(TCG_REG_CALL_STACK)
-              | INSN_IM5(STACK_TEMP_OFS) | INSN_T(22));
-
-    /* xmpyu fr22r,fr22,fr22 */
-    tcg_out32(s, 0x3ad64796);
-
-    /* Store the 64-bit result back into the stack.  */
-    /* fstds stack_temp(sp),fr22 */
-    tcg_out32(s, INSN_FSTDS | INSN_R2(TCG_REG_CALL_STACK)
-              | INSN_IM5(STACK_TEMP_OFS) | INSN_T(22));
-
-    /* Load the pieces of the result that the caller requested.  */
-    if (reth) {
-        tcg_out_ldst(s, reth, TCG_REG_CALL_STACK, STACK_TEMP_OFS, INSN_LDW);
-    }
-    if (retl) {
-        tcg_out_ldst(s, retl, TCG_REG_CALL_STACK, STACK_TEMP_OFS + 4,
-                     INSN_LDW);
-    }
-}
-
-static void tcg_out_add2(TCGContext *s, int destl, int desth,
-                         int al, int ah, int bl, int bh, int blconst)
-{
-    int tmp = (destl == ah || destl == bh ? TCG_REG_R20 : destl);
-
-    if (blconst) {
-        tcg_out_arithi(s, tmp, al, bl, INSN_ADDI);
-    } else {
-        tcg_out_arith(s, tmp, al, bl, INSN_ADD);
-    }
-    tcg_out_arith(s, desth, ah, bh, INSN_ADDC);
-
-    tcg_out_mov(s, TCG_TYPE_I32, destl, tmp);
-}
-
-static void tcg_out_sub2(TCGContext *s, int destl, int desth, int al, int ah,
-                         int bl, int bh, int alconst, int blconst)
-{
-    int tmp = (destl == ah || destl == bh ? TCG_REG_R20 : destl);
-
-    if (alconst) {
-        if (blconst) {
-            tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R20, bl);
-            bl = TCG_REG_R20;
-        }
-        tcg_out_arithi(s, tmp, bl, al, INSN_SUBI);
-    } else if (blconst) {
-        tcg_out_arithi(s, tmp, al, -bl, INSN_ADDI);
-    } else {
-        tcg_out_arith(s, tmp, al, bl, INSN_SUB);
-    }
-    tcg_out_arith(s, desth, ah, bh, INSN_SUBB);
-
-    tcg_out_mov(s, TCG_TYPE_I32, destl, tmp);
-}
-
-static void tcg_out_branch(TCGContext *s, int label_index, int nul)
-{
-    TCGLabel *l = &s->labels[label_index];
-    uint32_t op = nul ? INSN_BL_N : INSN_BL;
-
-    if (l->has_value) {
-        tcg_target_long val = l->u.value;
-
-        val -= (tcg_target_long)s->code_ptr + 8;
-        val >>= 2;
-        assert(check_fit_tl(val, 17));
-
-        tcg_out32(s, op | reassemble_17(val));
-    } else {
-        /* We need to keep the offset unchanged for retranslation.  */
-        uint32_t old_insn = *(uint32_t *)s->code_ptr;
-
-        tcg_out_reloc(s, s->code_ptr, R_PARISC_PCREL17F, label_index, 0);
-        tcg_out32(s, op | (old_insn & 0x1f1ffdu));
-    }
-}
-
-static const uint8_t tcg_cond_to_cmp_cond[] =
-{
-    [TCG_COND_EQ] = COND_EQ,
-    [TCG_COND_NE] = COND_EQ | COND_FALSE,
-    [TCG_COND_LT] = COND_LT,
-    [TCG_COND_GE] = COND_LT | COND_FALSE,
-    [TCG_COND_LE] = COND_LE,
-    [TCG_COND_GT] = COND_LE | COND_FALSE,
-    [TCG_COND_LTU] = COND_LTU,
-    [TCG_COND_GEU] = COND_LTU | COND_FALSE,
-    [TCG_COND_LEU] = COND_LEU,
-    [TCG_COND_GTU] = COND_LEU | COND_FALSE,
-};
-
-static void tcg_out_brcond(TCGContext *s, int cond, TCGArg c1,
-                           TCGArg c2, int c2const, int label_index)
-{
-    TCGLabel *l = &s->labels[label_index];
-    int op, pacond;
-
-    /* Note that COMIB operates as if the immediate is the first
-       operand.  We model brcond with the immediate in the second
-       to better match what targets are likely to give us.  For
-       consistency, model COMB with reversed operands as well.  */
-    pacond = tcg_cond_to_cmp_cond[tcg_swap_cond(cond)];
-
-    if (c2const) {
-        op = (pacond & COND_FALSE ? INSN_COMIBF : INSN_COMIBT);
-        op |= INSN_IM5(c2);
-    } else {
-        op = (pacond & COND_FALSE ? INSN_COMBF : INSN_COMBT);
-        op |= INSN_R1(c2);
-    }
-    op |= INSN_R2(c1);
-    op |= INSN_COND(pacond & 7);
-
-    if (l->has_value) {
-        tcg_target_long val = l->u.value;
-
-        val -= (tcg_target_long)s->code_ptr + 8;
-        val >>= 2;
-        assert(check_fit_tl(val, 12));
-
-        /* ??? Assume that all branches to defined labels are backward.
-           Which means that if the nul bit is set, the delay slot is
-           executed if the branch is taken, and not executed in fallthru.  */
-        tcg_out32(s, op | reassemble_12(val));
-        tcg_out_nop(s);
-    } else {
-        /* We need to keep the offset unchanged for retranslation.  */
-        uint32_t old_insn = *(uint32_t *)s->code_ptr;
-
-        tcg_out_reloc(s, s->code_ptr, R_PARISC_PCREL12F, label_index, 0);
-        /* ??? Assume that all branches to undefined labels are forward.
-           Which means that if the nul bit is set, the delay slot is
-           not executed if the branch is taken, which is what we want.  */
-        tcg_out32(s, op | 2 | (old_insn & 0x1ffdu));
-    }
-}
-
-static void tcg_out_comclr(TCGContext *s, int cond, TCGArg ret,
-                           TCGArg c1, TCGArg c2, int c2const)
-{
-    int op, pacond;
-
-    /* Note that COMICLR operates as if the immediate is the first
-       operand.  We model setcond with the immediate in the second
-       to better match what targets are likely to give us.  For
-       consistency, model COMCLR with reversed operands as well.  */
-    pacond = tcg_cond_to_cmp_cond[tcg_swap_cond(cond)];
-
-    if (c2const) {
-        op = INSN_COMICLR | INSN_R2(c1) | INSN_R1(ret) | INSN_IM11(c2);
-    } else {
-        op = INSN_COMCLR | INSN_R2(c1) | INSN_R1(c2) | INSN_T(ret);
-    }
-    op |= INSN_COND(pacond & 7);
-    op |= pacond & COND_FALSE ? 1 << 12 : 0;
-
-    tcg_out32(s, op);
-}
-
-static void tcg_out_brcond2(TCGContext *s, int cond, TCGArg al, TCGArg ah,
-                            TCGArg bl, int blconst, TCGArg bh, int bhconst,
-                            int label_index)
-{
-    switch (cond) {
-    case TCG_COND_EQ:
-        tcg_out_comclr(s, TCG_COND_NE, TCG_REG_R0, al, bl, blconst);
-        tcg_out_brcond(s, TCG_COND_EQ, ah, bh, bhconst, label_index);
-        break;
-    case TCG_COND_NE:
-        tcg_out_brcond(s, TCG_COND_NE, al, bl, blconst, label_index);
-        tcg_out_brcond(s, TCG_COND_NE, ah, bh, bhconst, label_index);
-        break;
-    default:
-        tcg_out_brcond(s, tcg_high_cond(cond), ah, bh, bhconst, label_index);
-        tcg_out_comclr(s, TCG_COND_NE, TCG_REG_R0, ah, bh, bhconst);
-        tcg_out_brcond(s, tcg_unsigned_cond(cond),
-                       al, bl, blconst, label_index);
-        break;
-    }
-}
-
-static void tcg_out_setcond(TCGContext *s, int cond, TCGArg ret,
-                            TCGArg c1, TCGArg c2, int c2const)
-{
-    tcg_out_comclr(s, tcg_invert_cond(cond), ret, c1, c2, c2const);
-    tcg_out_movi(s, TCG_TYPE_I32, ret, 1);
-}
-
-static void tcg_out_setcond2(TCGContext *s, int cond, TCGArg ret,
-                             TCGArg al, TCGArg ah, TCGArg bl, int blconst,
-                             TCGArg bh, int bhconst)
-{
-    int scratch = TCG_REG_R20;
-
-    /* Note that the low parts are fully consumed before scratch is set.  */
-    if (ret != ah && (bhconst || ret != bh)) {
-        scratch = ret;
-    }
-
-    switch (cond) {
-    case TCG_COND_EQ:
-    case TCG_COND_NE:
-        tcg_out_setcond(s, cond, scratch, al, bl, blconst);
-        tcg_out_comclr(s, TCG_COND_EQ, TCG_REG_R0, ah, bh, bhconst);
-        tcg_out_movi(s, TCG_TYPE_I32, scratch, cond == TCG_COND_NE);
-        break;
-
-    case TCG_COND_GE:
-    case TCG_COND_GEU:
-    case TCG_COND_LT:
-    case TCG_COND_LTU:
-        /* Optimize compares with low part zero.  */
-        if (bl == 0) {
-            tcg_out_setcond(s, cond, ret, ah, bh, bhconst);
-            return;
-        }
-        /* FALLTHRU */
-
-    case TCG_COND_LE:
-    case TCG_COND_LEU:
-    case TCG_COND_GT:
-    case TCG_COND_GTU:
-        /* <= : ah < bh | (ah == bh && al <= bl) */
-        tcg_out_setcond(s, tcg_unsigned_cond(cond), scratch, al, bl, blconst);
-        tcg_out_comclr(s, TCG_COND_EQ, TCG_REG_R0, ah, bh, bhconst);
-        tcg_out_movi(s, TCG_TYPE_I32, scratch, 0);
-        tcg_out_comclr(s, tcg_invert_cond(tcg_high_cond(cond)),
-                       TCG_REG_R0, ah, bh, bhconst);
-        tcg_out_movi(s, TCG_TYPE_I32, scratch, 1);
-        break;
-
-    default:
-        tcg_abort();
-    }
-
-    tcg_out_mov(s, TCG_TYPE_I32, ret, scratch);
-}
-
-static void tcg_out_movcond(TCGContext *s, int cond, TCGArg ret,
-                            TCGArg c1, TCGArg c2, int c2const,
-                            TCGArg v1, int v1const)
-{
-    tcg_out_comclr(s, tcg_invert_cond(cond), TCG_REG_R0, c1, c2, c2const);
-    if (v1const) {
-        tcg_out_movi(s, TCG_TYPE_I32, ret, v1);
-    } else {
-        tcg_out_mov(s, TCG_TYPE_I32, ret, v1);
-    }
-}
-
-#if defined(CONFIG_SOFTMMU)
-/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
-   int mmu_idx) */
-static const void * const qemu_ld_helpers[4] = {
-    helper_ldb_mmu,
-    helper_ldw_mmu,
-    helper_ldl_mmu,
-    helper_ldq_mmu,
-};
-
-/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
-   uintxx_t val, int mmu_idx) */
-static const void * const qemu_st_helpers[4] = {
-    helper_stb_mmu,
-    helper_stw_mmu,
-    helper_stl_mmu,
-    helper_stq_mmu,
-};
-
-/* Load and compare a TLB entry, and branch if TLB miss.  OFFSET is set to
-   the offset of the first ADDR_READ or ADDR_WRITE member of the appropriate
-   TLB for the memory index.  The return value is the offset from ENV
-   contained in R1 afterward (to be used when loading ADDEND); if the
-   return value is 0, R1 is not used.  */
-
-static int tcg_out_tlb_read(TCGContext *s, int r0, int r1, int addrlo,
-                            int addrhi, int s_bits, int lab_miss, int offset)
-{
-    int ret;
-
-    /* Extracting the index into the TLB.  The "normal C operation" is
-          r1 = addr_reg >> TARGET_PAGE_BITS;
-          r1 &= CPU_TLB_SIZE - 1;
-          r1 <<= CPU_TLB_ENTRY_BITS;
-       What this does is extract CPU_TLB_BITS beginning at TARGET_PAGE_BITS
-       and place them at CPU_TLB_ENTRY_BITS.  We can combine the first two
-       operations with an EXTRU.  Unfortunately, the current value of
-       CPU_TLB_ENTRY_BITS is > 3, so we can't merge that shift with the
-       add that follows.  */
-    tcg_out_extr(s, r1, addrlo, TARGET_PAGE_BITS, CPU_TLB_BITS, 0);
-    tcg_out_shli(s, r1, r1, CPU_TLB_ENTRY_BITS);
-    tcg_out_arith(s, r1, r1, TCG_AREG0, INSN_ADDL);
-
-    /* Make sure that both the addr_{read,write} and addend can be
-       read with a 14-bit offset from the same base register.  */
-    if (check_fit_tl(offset + CPU_TLB_SIZE, 14)) {
-        ret = 0;
-    } else {
-        ret = (offset + 0x400) & ~0x7ff;
-        offset = ret - offset;
-        tcg_out_addi2(s, TCG_REG_R1, r1, ret);
-        r1 = TCG_REG_R1;
-    }
-
-    /* Load the entry from the computed slot.  */
-    if (TARGET_LONG_BITS == 64) {
-        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R23, r1, offset);
-        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, r1, offset + 4);
-    } else {
-        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, r1, offset);
-    }
-
-    /* Compute the value that ought to appear in the TLB for a hit, namely,
-       the page of the address.  We include the low N bits of the address
-       to catch unaligned accesses and force them onto the slow path.  Do
-       this computation after having issued the load from the TLB slot to
-       give the load time to complete.  */
-    tcg_out_andi(s, r0, addrlo, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
-
-    /* If not equal, jump to lab_miss. */
-    if (TARGET_LONG_BITS == 64) {
-        tcg_out_brcond2(s, TCG_COND_NE, TCG_REG_R20, TCG_REG_R23,
-                        r0, 0, addrhi, 0, lab_miss);
-    } else {
-        tcg_out_brcond(s, TCG_COND_NE, TCG_REG_R20, r0, 0, lab_miss);
-    }
-
-    return ret;
-}
-
-static int tcg_out_arg_reg32(TCGContext *s, int argno, TCGArg v, bool vconst)
-{
-    if (argno < 4) {
-        if (vconst) {
-            tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[argno], v);
-        } else {
-            tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[argno], v);
-        }
-    } else {
-        if (vconst && v != 0) {
-            tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R20, v);
-            v = TCG_REG_R20;
-        }
-        tcg_out_st(s, TCG_TYPE_I32, v, TCG_REG_CALL_STACK,
-                   TCG_TARGET_CALL_STACK_OFFSET - ((argno - 3) * 4));
-    }
-    return argno + 1;
-}
-
-static int tcg_out_arg_reg64(TCGContext *s, int argno, TCGArg vl, TCGArg vh)
-{
-    /* 64-bit arguments must go in even reg pairs and stack slots.  */
-    if (argno & 1) {
-        argno++;
-    }
-    argno = tcg_out_arg_reg32(s, argno, vl, false);
-    argno = tcg_out_arg_reg32(s, argno, vh, false);
-    return argno;
-}
-#endif
-
-static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo_reg, int datahi_reg,
-                                   int addr_reg, int addend_reg, int opc)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
-    const int bswap = 0;
-#else
-    const int bswap = 1;
-#endif
-
-    switch (opc) {
-    case 0:
-        tcg_out_ldst_index(s, datalo_reg, addr_reg, addend_reg, INSN_LDBX);
-        break;
-    case 0 | 4:
-        tcg_out_ldst_index(s, datalo_reg, addr_reg, addend_reg, INSN_LDBX);
-        tcg_out_ext8s(s, datalo_reg, datalo_reg);
-        break;
-    case 1:
-        tcg_out_ldst_index(s, datalo_reg, addr_reg, addend_reg, INSN_LDHX);
-        if (bswap) {
-            tcg_out_bswap16(s, datalo_reg, datalo_reg, 0);
-        }
-        break;
-    case 1 | 4:
-        tcg_out_ldst_index(s, datalo_reg, addr_reg, addend_reg, INSN_LDHX);
-        if (bswap) {
-            tcg_out_bswap16(s, datalo_reg, datalo_reg, 1);
-        } else {
-            tcg_out_ext16s(s, datalo_reg, datalo_reg);
-        }
-        break;
-    case 2:
-        tcg_out_ldst_index(s, datalo_reg, addr_reg, addend_reg, INSN_LDWX);
-        if (bswap) {
-            tcg_out_bswap32(s, datalo_reg, datalo_reg, TCG_REG_R20);
-        }
-        break;
-    case 3:
-        if (bswap) {
-            int t = datahi_reg;
-            datahi_reg = datalo_reg;
-            datalo_reg = t;
-        }
-        /* We can't access the low-part with a reg+reg addressing mode,
-           so perform the addition now and use reg_ofs addressing mode.  */
-        if (addend_reg != TCG_REG_R0) {
-            tcg_out_arith(s, TCG_REG_R20, addr_reg, addend_reg, INSN_ADD);
-            addr_reg = TCG_REG_R20;
-	}
-        /* Make sure not to clobber the base register.  */
-        if (datahi_reg == addr_reg) {
-            tcg_out_ldst(s, datalo_reg, addr_reg, 4, INSN_LDW);
-            tcg_out_ldst(s, datahi_reg, addr_reg, 0, INSN_LDW);
-        } else {
-            tcg_out_ldst(s, datahi_reg, addr_reg, 0, INSN_LDW);
-            tcg_out_ldst(s, datalo_reg, addr_reg, 4, INSN_LDW);
-        }
-        if (bswap) {
-            tcg_out_bswap32(s, datalo_reg, datalo_reg, TCG_REG_R20);
-            tcg_out_bswap32(s, datahi_reg, datahi_reg, TCG_REG_R20);
-        }
-        break;
-    default:
-        tcg_abort();
-    }
-}
-
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
-{
-    int datalo_reg = *args++;
-    /* Note that datahi_reg is only used for 64-bit loads.  */
-    int datahi_reg = (opc == 3 ? *args++ : TCG_REG_R0);
-    int addrlo_reg = *args++;
-
-#if defined(CONFIG_SOFTMMU)
-    /* Note that addrhi_reg is only used for 64-bit guests.  */
-    int addrhi_reg = (TARGET_LONG_BITS == 64 ? *args++ : TCG_REG_R0);
-    int mem_index = *args;
-    int lab1, lab2, argno, offset;
-
-    lab1 = gen_new_label();
-    lab2 = gen_new_label();
-
-    offset = offsetof(CPUArchState, tlb_table[mem_index][0].addr_read);
-    offset = tcg_out_tlb_read(s, TCG_REG_R26, TCG_REG_R25, addrlo_reg,
-                              addrhi_reg, opc & 3, lab1, offset);
-
-    /* TLB Hit.  */
-    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20,
-               (offset ? TCG_REG_R1 : TCG_REG_R25),
-               offsetof(CPUArchState, tlb_table[mem_index][0].addend) - offset);
-    tcg_out_qemu_ld_direct(s, datalo_reg, datahi_reg, addrlo_reg,
-                           TCG_REG_R20, opc);
-    tcg_out_branch(s, lab2, 1);
-
-    /* TLB Miss.  */
-    /* label1: */
-    tcg_out_label(s, lab1, s->code_ptr);
-
-    argno = 0;
-    argno = tcg_out_arg_reg32(s, argno, TCG_AREG0, false);
-    if (TARGET_LONG_BITS == 64) {
-        argno = tcg_out_arg_reg64(s, argno, addrlo_reg, addrhi_reg);
-    } else {
-        argno = tcg_out_arg_reg32(s, argno, addrlo_reg, false);
-    }
-    argno = tcg_out_arg_reg32(s, argno, mem_index, true);
-
-    tcg_out_call(s, qemu_ld_helpers[opc & 3]);
-
-    switch (opc) {
-    case 0:
-        tcg_out_andi(s, datalo_reg, TCG_REG_RET0, 0xff);
-        break;
-    case 0 | 4:
-        tcg_out_ext8s(s, datalo_reg, TCG_REG_RET0);
-        break;
-    case 1:
-        tcg_out_andi(s, datalo_reg, TCG_REG_RET0, 0xffff);
-        break;
-    case 1 | 4:
-        tcg_out_ext16s(s, datalo_reg, TCG_REG_RET0);
-        break;
-    case 2:
-    case 2 | 4:
-        tcg_out_mov(s, TCG_TYPE_I32, datalo_reg, TCG_REG_RET0);
-        break;
-    case 3:
-        tcg_out_mov(s, TCG_TYPE_I32, datahi_reg, TCG_REG_RET0);
-        tcg_out_mov(s, TCG_TYPE_I32, datalo_reg, TCG_REG_RET1);
-        break;
-    default:
-        tcg_abort();
-    }
-
-    /* label2: */
-    tcg_out_label(s, lab2, s->code_ptr);
-#else
-    tcg_out_qemu_ld_direct(s, datalo_reg, datahi_reg, addrlo_reg,
-                           (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_R0), opc);
-#endif
-}
-
-static void tcg_out_qemu_st_direct(TCGContext *s, int datalo_reg,
-                                   int datahi_reg, int addr_reg, int opc)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
-    const int bswap = 0;
-#else
-    const int bswap = 1;
-#endif
-
-    switch (opc) {
-    case 0:
-        tcg_out_ldst(s, datalo_reg, addr_reg, 0, INSN_STB);
-        break;
-    case 1:
-        if (bswap) {
-            tcg_out_bswap16(s, TCG_REG_R20, datalo_reg, 0);
-            datalo_reg = TCG_REG_R20;
-        }
-        tcg_out_ldst(s, datalo_reg, addr_reg, 0, INSN_STH);
-        break;
-    case 2:
-        if (bswap) {
-            tcg_out_bswap32(s, TCG_REG_R20, datalo_reg, TCG_REG_R20);
-            datalo_reg = TCG_REG_R20;
-        }
-        tcg_out_ldst(s, datalo_reg, addr_reg, 0, INSN_STW);
-        break;
-    case 3:
-        if (bswap) {
-            tcg_out_bswap32(s, TCG_REG_R20, datalo_reg, TCG_REG_R20);
-            tcg_out_bswap32(s, TCG_REG_R23, datahi_reg, TCG_REG_R23);
-            datahi_reg = TCG_REG_R20;
-            datalo_reg = TCG_REG_R23;
-        }
-        tcg_out_ldst(s, datahi_reg, addr_reg, 0, INSN_STW);
-        tcg_out_ldst(s, datalo_reg, addr_reg, 4, INSN_STW);
-        break;
-    default:
-        tcg_abort();
-    }
-
-}
-
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
-{
-    int datalo_reg = *args++;
-    /* Note that datahi_reg is only used for 64-bit loads.  */
-    int datahi_reg = (opc == 3 ? *args++ : TCG_REG_R0);
-    int addrlo_reg = *args++;
-
-#if defined(CONFIG_SOFTMMU)
-    /* Note that addrhi_reg is only used for 64-bit guests.  */
-    int addrhi_reg = (TARGET_LONG_BITS == 64 ? *args++ : TCG_REG_R0);
-    int mem_index = *args;
-    int lab1, lab2, argno, next, offset;
-
-    lab1 = gen_new_label();
-    lab2 = gen_new_label();
-
-    offset = offsetof(CPUArchState, tlb_table[mem_index][0].addr_write);
-    offset = tcg_out_tlb_read(s, TCG_REG_R26, TCG_REG_R25, addrlo_reg,
-                              addrhi_reg, opc, lab1, offset);
-
-    /* TLB Hit.  */
-    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20,
-               (offset ? TCG_REG_R1 : TCG_REG_R25),
-               offsetof(CPUArchState, tlb_table[mem_index][0].addend) - offset);
-
-    /* There are no indexed stores, so we must do this addition explitly.
-       Careful to avoid R20, which is used for the bswaps to follow.  */
-    tcg_out_arith(s, TCG_REG_R31, addrlo_reg, TCG_REG_R20, INSN_ADDL);
-    tcg_out_qemu_st_direct(s, datalo_reg, datahi_reg, TCG_REG_R31, opc);
-    tcg_out_branch(s, lab2, 1);
-
-    /* TLB Miss.  */
-    /* label1: */
-    tcg_out_label(s, lab1, s->code_ptr);
-
-    argno = 0;
-    argno = tcg_out_arg_reg32(s, argno, TCG_AREG0, false);
-    if (TARGET_LONG_BITS == 64) {
-        argno = tcg_out_arg_reg64(s, argno, addrlo_reg, addrhi_reg);
-    } else {
-        argno = tcg_out_arg_reg32(s, argno, addrlo_reg, false);
-    }
-
-    next = (argno < 4 ? tcg_target_call_iarg_regs[argno] : TCG_REG_R20);
-    switch(opc) {
-    case 0:
-        tcg_out_andi(s, next, datalo_reg, 0xff);
-        argno = tcg_out_arg_reg32(s, argno, next, false);
-        break;
-    case 1:
-        tcg_out_andi(s, next, datalo_reg, 0xffff);
-        argno = tcg_out_arg_reg32(s, argno, next, false);
-        break;
-    case 2:
-        argno = tcg_out_arg_reg32(s, argno, datalo_reg, false);
-        break;
-    case 3:
-        argno = tcg_out_arg_reg64(s, argno, datalo_reg, datahi_reg);
-        break;
-    default:
-        tcg_abort();
-    }
-    argno = tcg_out_arg_reg32(s, argno, mem_index, true);
-
-    tcg_out_call(s, qemu_st_helpers[opc]);
-
-    /* label2: */
-    tcg_out_label(s, lab2, s->code_ptr);
-#else
-    /* There are no indexed stores, so if GUEST_BASE is set we must do
-       the add explicitly.  Careful to avoid R20, which is used for the
-       bswaps to follow.  */
-    if (GUEST_BASE != 0) {
-        tcg_out_arith(s, TCG_REG_R31, addrlo_reg,
-                      TCG_GUEST_BASE_REG, INSN_ADDL);
-        addrlo_reg = TCG_REG_R31;
-    }
-    tcg_out_qemu_st_direct(s, datalo_reg, datahi_reg, addrlo_reg, opc);
-#endif
-}
-
-static void tcg_out_exit_tb(TCGContext *s, TCGArg arg)
-{
-    if (!check_fit_tl(arg, 14)) {
-        uint32_t hi, lo;
-        hi = arg & ~0x7ff;
-        lo = arg & 0x7ff;
-        if (lo) {
-            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RET0, hi);
-            tcg_out32(s, INSN_BV | INSN_R2(TCG_REG_R18));
-            tcg_out_addi(s, TCG_REG_RET0, lo);
-            return;
-        }
-        arg = hi;
-    }
-    tcg_out32(s, INSN_BV | INSN_R2(TCG_REG_R18));
-    tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RET0, arg);
-}
-
-static void tcg_out_goto_tb(TCGContext *s, TCGArg arg)
-{
-    if (s->tb_jmp_offset) {
-        /* direct jump method */
-        fprintf(stderr, "goto_tb direct\n");
-        tcg_abort();
-    } else {
-        /* indirect jump method */
-        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, TCG_REG_R0,
-                   (tcg_target_long)(s->tb_next + arg));
-        tcg_out32(s, INSN_BV_N | INSN_R2(TCG_REG_R20));
-    }
-    s->tb_next_offset[arg] = s->code_ptr - s->code_buf;
-}
-
-static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
-                              const int *const_args)
-{
-    switch (opc) {
-    case INDEX_op_exit_tb:
-        tcg_out_exit_tb(s, args[0]);
-        break;
-    case INDEX_op_goto_tb:
-        tcg_out_goto_tb(s, args[0]);
-        break;
-
-    case INDEX_op_call:
-        if (const_args[0]) {
-            tcg_out_call(s, (void *)args[0]);
-        } else {
-            /* ??? FIXME: the value in the register in args[0] is almost
-               certainly a procedure descriptor, not a code address.  We
-               probably need to use the millicode $$dyncall routine.  */
-            tcg_abort();
-        }
-        break;
-
-    case INDEX_op_br:
-        tcg_out_branch(s, args[0], 1);
-        break;
-
-    case INDEX_op_movi_i32:
-        tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]);
-        break;
-
-    case INDEX_op_ld8u_i32:
-        tcg_out_ldst(s, args[0], args[1], args[2], INSN_LDB);
-        break;
-    case INDEX_op_ld8s_i32:
-        tcg_out_ldst(s, args[0], args[1], args[2], INSN_LDB);
-        tcg_out_ext8s(s, args[0], args[0]);
-        break;
-    case INDEX_op_ld16u_i32:
-        tcg_out_ldst(s, args[0], args[1], args[2], INSN_LDH);
-        break;
-    case INDEX_op_ld16s_i32:
-        tcg_out_ldst(s, args[0], args[1], args[2], INSN_LDH);
-        tcg_out_ext16s(s, args[0], args[0]);
-        break;
-    case INDEX_op_ld_i32:
-        tcg_out_ldst(s, args[0], args[1], args[2], INSN_LDW);
-        break;
-
-    case INDEX_op_st8_i32:
-        tcg_out_ldst(s, args[0], args[1], args[2], INSN_STB);
-        break;
-    case INDEX_op_st16_i32:
-        tcg_out_ldst(s, args[0], args[1], args[2], INSN_STH);
-        break;
-    case INDEX_op_st_i32:
-        tcg_out_ldst(s, args[0], args[1], args[2], INSN_STW);
-        break;
-
-    case INDEX_op_add_i32:
-        if (const_args[2]) {
-            tcg_out_addi2(s, args[0], args[1], args[2]);
-        } else {
-            tcg_out_arith(s, args[0], args[1], args[2], INSN_ADDL);
-        }
-        break;
-
-    case INDEX_op_sub_i32:
-        if (const_args[1]) {
-            if (const_args[2]) {
-                tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1] - args[2]);
-            } else {
-                /* Recall that SUBI is a reversed subtract.  */
-                tcg_out_arithi(s, args[0], args[2], args[1], INSN_SUBI);
-            }
-        } else if (const_args[2]) {
-            tcg_out_addi2(s, args[0], args[1], -args[2]);
-        } else {
-            tcg_out_arith(s, args[0], args[1], args[2], INSN_SUB);
-        }
-        break;
-
-    case INDEX_op_and_i32:
-        if (const_args[2]) {
-            tcg_out_andi(s, args[0], args[1], args[2]);
-        } else {
-            tcg_out_arith(s, args[0], args[1], args[2], INSN_AND);
-        }
-        break;
-
-    case INDEX_op_or_i32:
-        if (const_args[2]) {
-            tcg_out_ori(s, args[0], args[1], args[2]);
-        } else {
-            tcg_out_arith(s, args[0], args[1], args[2], INSN_OR);
-        }
-        break;
-
-    case INDEX_op_xor_i32:
-        tcg_out_arith(s, args[0], args[1], args[2], INSN_XOR);
-        break;
-
-    case INDEX_op_andc_i32:
-        if (const_args[2]) {
-            tcg_out_andi(s, args[0], args[1], ~args[2]);
-        } else {
-            tcg_out_arith(s, args[0], args[1], args[2], INSN_ANDCM);
-        }
-        break;
-
-    case INDEX_op_shl_i32:
-        if (const_args[2]) {
-            tcg_out_shli(s, args[0], args[1], args[2]);
-        } else {
-            tcg_out_shl(s, args[0], args[1], args[2]);
-        }
-        break;
-
-    case INDEX_op_shr_i32:
-        if (const_args[2]) {
-            tcg_out_shri(s, args[0], args[1], args[2]);
-        } else {
-            tcg_out_shr(s, args[0], args[1], args[2]);
-        }
-        break;
-
-    case INDEX_op_sar_i32:
-        if (const_args[2]) {
-            tcg_out_sari(s, args[0], args[1], args[2]);
-        } else {
-            tcg_out_sar(s, args[0], args[1], args[2]);
-        }
-        break;
-
-    case INDEX_op_rotl_i32:
-        if (const_args[2]) {
-            tcg_out_rotli(s, args[0], args[1], args[2]);
-        } else {
-            tcg_out_rotl(s, args[0], args[1], args[2]);
-        }
-        break;
-
-    case INDEX_op_rotr_i32:
-        if (const_args[2]) {
-            tcg_out_rotri(s, args[0], args[1], args[2]);
-        } else {
-            tcg_out_rotr(s, args[0], args[1], args[2]);
-        }
-        break;
-
-    case INDEX_op_mul_i32:
-        tcg_out_xmpyu(s, args[0], TCG_REG_R0, args[1], args[2]);
-        break;
-    case INDEX_op_mulu2_i32:
-        tcg_out_xmpyu(s, args[0], args[1], args[2], args[3]);
-        break;
-
-    case INDEX_op_bswap16_i32:
-        tcg_out_bswap16(s, args[0], args[1], 0);
-        break;
-    case INDEX_op_bswap32_i32:
-        tcg_out_bswap32(s, args[0], args[1], TCG_REG_R20);
-        break;
-
-    case INDEX_op_not_i32:
-        tcg_out_arithi(s, args[0], args[1], -1, INSN_SUBI);
-        break;
-    case INDEX_op_ext8s_i32:
-        tcg_out_ext8s(s, args[0], args[1]);
-        break;
-    case INDEX_op_ext16s_i32:
-        tcg_out_ext16s(s, args[0], args[1]);
-        break;
-
-    case INDEX_op_brcond_i32:
-        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], args[3]);
-        break;
-    case INDEX_op_brcond2_i32:
-        tcg_out_brcond2(s, args[4], args[0], args[1],
-                        args[2], const_args[2],
-                        args[3], const_args[3], args[5]);
-        break;
-
-    case INDEX_op_setcond_i32:
-        tcg_out_setcond(s, args[3], args[0], args[1], args[2], const_args[2]);
-        break;
-    case INDEX_op_setcond2_i32:
-        tcg_out_setcond2(s, args[5], args[0], args[1], args[2],
-                         args[3], const_args[3], args[4], const_args[4]);
-        break;
-
-    case INDEX_op_movcond_i32:
-        tcg_out_movcond(s, args[5], args[0], args[1], args[2], const_args[2],
-                        args[3], const_args[3]);
-        break;
-
-    case INDEX_op_add2_i32:
-        tcg_out_add2(s, args[0], args[1], args[2], args[3],
-                     args[4], args[5], const_args[4]);
-        break;
-
-    case INDEX_op_sub2_i32:
-        tcg_out_sub2(s, args[0], args[1], args[2], args[3],
-                     args[4], args[5], const_args[2], const_args[4]);
-        break;
-
-    case INDEX_op_deposit_i32:
-        if (const_args[2]) {
-            tcg_out_depi(s, args[0], args[2], args[3], args[4]);
-        } else {
-            tcg_out_dep(s, args[0], args[2], args[3], args[4]);
-        }
-        break;
-
-    case INDEX_op_qemu_ld8u:
-        tcg_out_qemu_ld(s, args, 0);
-        break;
-    case INDEX_op_qemu_ld8s:
-        tcg_out_qemu_ld(s, args, 0 | 4);
-        break;
-    case INDEX_op_qemu_ld16u:
-        tcg_out_qemu_ld(s, args, 1);
-        break;
-    case INDEX_op_qemu_ld16s:
-        tcg_out_qemu_ld(s, args, 1 | 4);
-        break;
-    case INDEX_op_qemu_ld32:
-        tcg_out_qemu_ld(s, args, 2);
-        break;
-    case INDEX_op_qemu_ld64:
-        tcg_out_qemu_ld(s, args, 3);
-        break;
-
-    case INDEX_op_qemu_st8:
-        tcg_out_qemu_st(s, args, 0);
-        break;
-    case INDEX_op_qemu_st16:
-        tcg_out_qemu_st(s, args, 1);
-        break;
-    case INDEX_op_qemu_st32:
-        tcg_out_qemu_st(s, args, 2);
-        break;
-    case INDEX_op_qemu_st64:
-        tcg_out_qemu_st(s, args, 3);
-        break;
-
-    default:
-        fprintf(stderr, "unknown opcode 0x%x\n", opc);
-        tcg_abort();
-    }
-}
-
-static const TCGTargetOpDef hppa_op_defs[] = {
-    { INDEX_op_exit_tb, { } },
-    { INDEX_op_goto_tb, { } },
-
-    { INDEX_op_call, { "ri" } },
-    { INDEX_op_br, { } },
-
-    { INDEX_op_mov_i32, { "r", "r" } },
-    { INDEX_op_movi_i32, { "r" } },
-
-    { INDEX_op_ld8u_i32, { "r", "r" } },
-    { INDEX_op_ld8s_i32, { "r", "r" } },
-    { INDEX_op_ld16u_i32, { "r", "r" } },
-    { INDEX_op_ld16s_i32, { "r", "r" } },
-    { INDEX_op_ld_i32, { "r", "r" } },
-    { INDEX_op_st8_i32, { "rZ", "r" } },
-    { INDEX_op_st16_i32, { "rZ", "r" } },
-    { INDEX_op_st_i32, { "rZ", "r" } },
-
-    { INDEX_op_add_i32, { "r", "rZ", "ri" } },
-    { INDEX_op_sub_i32, { "r", "rI", "ri" } },
-    { INDEX_op_and_i32, { "r", "rZ", "rM" } },
-    { INDEX_op_or_i32, { "r", "rZ", "rO" } },
-    { INDEX_op_xor_i32, { "r", "rZ", "rZ" } },
-    /* Note that the second argument will be inverted, which means
-       we want a constant whose inversion matches M, and that O = ~M.
-       See the implementation of and_mask_p.  */
-    { INDEX_op_andc_i32, { "r", "rZ", "rO" } },
-
-    { INDEX_op_mul_i32, { "r", "r", "r" } },
-    { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
-
-    { INDEX_op_shl_i32, { "r", "r", "ri" } },
-    { INDEX_op_shr_i32, { "r", "r", "ri" } },
-    { INDEX_op_sar_i32, { "r", "r", "ri" } },
-    { INDEX_op_rotl_i32, { "r", "r", "ri" } },
-    { INDEX_op_rotr_i32, { "r", "r", "ri" } },
-
-    { INDEX_op_bswap16_i32, { "r", "r" } },
-    { INDEX_op_bswap32_i32, { "r", "r" } },
-    { INDEX_op_not_i32, { "r", "r" } },
-
-    { INDEX_op_ext8s_i32, { "r", "r" } },
-    { INDEX_op_ext16s_i32, { "r", "r" } },
-
-    { INDEX_op_brcond_i32, { "rZ", "rJ" } },
-    { INDEX_op_brcond2_i32,  { "rZ", "rZ", "rJ", "rJ" } },
-
-    { INDEX_op_setcond_i32, { "r", "rZ", "rI" } },
-    { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rI", "rI" } },
-
-    /* ??? We can actually support a signed 14-bit arg3, but we
-       only have existing constraints for a signed 11-bit.  */
-    { INDEX_op_movcond_i32, { "r", "rZ", "rI", "rI", "0" } },
-
-    { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rI", "rZ" } },
-    { INDEX_op_sub2_i32, { "r", "r", "rI", "rZ", "rK", "rZ" } },
-
-    { INDEX_op_deposit_i32, { "r", "0", "rJ" } },
-
-#if TARGET_LONG_BITS == 32
-    { INDEX_op_qemu_ld8u, { "r", "L" } },
-    { INDEX_op_qemu_ld8s, { "r", "L" } },
-    { INDEX_op_qemu_ld16u, { "r", "L" } },
-    { INDEX_op_qemu_ld16s, { "r", "L" } },
-    { INDEX_op_qemu_ld32, { "r", "L" } },
-    { INDEX_op_qemu_ld64, { "r", "r", "L" } },
-
-    { INDEX_op_qemu_st8, { "LZ", "L" } },
-    { INDEX_op_qemu_st16, { "LZ", "L" } },
-    { INDEX_op_qemu_st32, { "LZ", "L" } },
-    { INDEX_op_qemu_st64, { "LZ", "LZ", "L" } },
-#else
-    { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
-    { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
-    { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
-    { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
-    { INDEX_op_qemu_ld32, { "r", "L", "L" } },
-    { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
-
-    { INDEX_op_qemu_st8, { "LZ", "L", "L" } },
-    { INDEX_op_qemu_st16, { "LZ", "L", "L" } },
-    { INDEX_op_qemu_st32, { "LZ", "L", "L" } },
-    { INDEX_op_qemu_st64, { "LZ", "LZ", "L", "L" } },
-#endif
-    { -1 },
-};
-
-static int tcg_target_callee_save_regs[] = {
-    /* R2, the return address register, is saved specially
-       in the caller's frame.  */
-    /* R3, the frame pointer, is not currently modified.  */
-    TCG_REG_R4,
-    TCG_REG_R5,
-    TCG_REG_R6,
-    TCG_REG_R7,
-    TCG_REG_R8,
-    TCG_REG_R9,
-    TCG_REG_R10,
-    TCG_REG_R11,
-    TCG_REG_R12,
-    TCG_REG_R13,
-    TCG_REG_R14,
-    TCG_REG_R15,
-    TCG_REG_R16,
-    TCG_REG_R17, /* R17 is the global env.  */
-    TCG_REG_R18
-};
-
-#define FRAME_SIZE ((-TCG_TARGET_CALL_STACK_OFFSET \
-                     + TCG_TARGET_STATIC_CALL_ARGS_SIZE \
-                     + ARRAY_SIZE(tcg_target_callee_save_regs) * 4 \
-                     + CPU_TEMP_BUF_NLONGS * sizeof(long) \
-                     + TCG_TARGET_STACK_ALIGN - 1) \
-                    & -TCG_TARGET_STACK_ALIGN)
-
-static void tcg_target_qemu_prologue(TCGContext *s)
-{
-    int frame_size, i;
-
-    frame_size = FRAME_SIZE;
-
-    /* The return address is stored in the caller's frame.  */
-    tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_CALL_STACK, -20);
-
-    /* Allocate stack frame, saving the first register at the same time.  */
-    tcg_out_ldst(s, tcg_target_callee_save_regs[0],
-                 TCG_REG_CALL_STACK, frame_size, INSN_STWM);
-
-    /* Save all callee saved registers.  */
-    for (i = 1; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
-        tcg_out_st(s, TCG_TYPE_PTR, tcg_target_callee_save_regs[i],
-                   TCG_REG_CALL_STACK, -frame_size + i * 4);
-    }
-
-    /* Record the location of the TCG temps.  */
-    tcg_set_frame(s, TCG_REG_CALL_STACK, -frame_size + i * 4,
-                  CPU_TEMP_BUF_NLONGS * sizeof(long));
-
-#ifdef CONFIG_USE_GUEST_BASE
-    if (GUEST_BASE != 0) {
-        tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE);
-        tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
-    }
-#endif
-
-    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
-
-    /* Jump to TB, and adjust R18 to be the return address.  */
-    tcg_out32(s, INSN_BLE_SR4 | INSN_R2(tcg_target_call_iarg_regs[1]));
-    tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R18, TCG_REG_R31);
-
-    /* Restore callee saved registers.  */
-    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_CALL_STACK,
-               -frame_size - 20);
-    for (i = 1; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
-        tcg_out_ld(s, TCG_TYPE_PTR, tcg_target_callee_save_regs[i],
-                   TCG_REG_CALL_STACK, -frame_size + i * 4);
-    }
-
-    /* Deallocate stack frame and return.  */
-    tcg_out32(s, INSN_BV | INSN_R2(TCG_REG_RP));
-    tcg_out_ldst(s, tcg_target_callee_save_regs[0],
-                 TCG_REG_CALL_STACK, -frame_size, INSN_LDWM);
-}
-
-static void tcg_target_init(TCGContext *s)
-{
-    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
-
-    tcg_regset_clear(tcg_target_call_clobber_regs);
-    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R20);
-    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R21);
-    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R22);
-    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R23);
-    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R24);
-    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R25);
-    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R26);
-    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RET0);
-    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RET1);
-
-    tcg_regset_clear(s->reserved_regs);
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);  /* hardwired to zero */
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1);  /* addil target */
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_RP);  /* link register */
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R3);  /* frame pointer */
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R18); /* return pointer */
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R19); /* clobbered w/o pic */
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R20); /* reserved */
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_DP);  /* data pointer */
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);  /* stack pointer */
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R31); /* ble link reg */
-
-    tcg_add_target_add_op_defs(hppa_op_defs);
-}
-
-typedef struct {
-    DebugFrameCIE cie;
-    DebugFrameFDEHeader fde;
-    uint8_t fde_def_cfa[4];
-    uint8_t fde_ret_ofs[3];
-    uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
-} DebugFrame;
-
-#define ELF_HOST_MACHINE  EM_PARISC
-#define ELF_HOST_FLAGS    EFA_PARISC_1_1
-
-/* ??? BFD (and thus GDB) wants very much to distinguish between HPUX
-   and other extensions.  We don't really care, but if we don't set this
-   to *something* then the object file won't be properly matched.  */
-#define ELF_OSABI         ELFOSABI_LINUX
-
-static DebugFrame debug_frame = {
-    .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
-    .cie.id = -1,
-    .cie.version = 1,
-    .cie.code_align = 1,
-    .cie.data_align = 1,
-    .cie.return_column = 2,
-
-    /* Total FDE size does not include the "len" member.  */
-    .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
-
-    .fde_def_cfa = {
-        0x12, 30,                       /* DW_CFA_def_cfa_sf sp, ... */
-        (-FRAME_SIZE & 0x7f) | 0x80,     /* ... sleb128 -FRAME_SIZE */
-        (-FRAME_SIZE >> 7) & 0x7f
-    },
-    .fde_ret_ofs = {
-        0x11, 2, (-20 / 4) & 0x7f       /* DW_CFA_offset_extended_sf r2, 20 */
-    },
-    .fde_reg_ofs = {
-        /* This must match the ordering in tcg_target_callee_save_regs.  */
-        0x80 + 4, 0,                    /* DW_CFA_offset r4, 0 */
-        0x80 + 5, 4,                    /* DW_CFA_offset r5, 4 */
-        0x80 + 6, 8,                    /* DW_CFA_offset r6, 8 */
-        0x80 + 7, 12,                    /* ... */
-        0x80 + 8, 16,
-        0x80 + 9, 20,
-        0x80 + 10, 24,
-        0x80 + 11, 28,
-        0x80 + 12, 32,
-        0x80 + 13, 36,
-        0x80 + 14, 40,
-        0x80 + 15, 44,
-        0x80 + 16, 48,
-        0x80 + 17, 52,
-        0x80 + 18, 56,
-    }
-};
-
-void tcg_register_jit(void *buf, size_t buf_size)
-{
-    debug_frame.fde.func_start = (tcg_target_long) buf;
-    debug_frame.fde.func_len = buf_size;
-
-    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
-}
diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h
deleted file mode 100644
index 122edce..0000000
--- a/tcg/hppa/tcg-target.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Tiny Code Generator for QEMU
- *
- * Copyright (c) 2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#ifndef TCG_TARGET_HPPA
-#define TCG_TARGET_HPPA 1
-
-#define TCG_TARGET_WORDS_BIGENDIAN
-
-#define TCG_TARGET_NB_REGS 32
-
-typedef enum {
-    TCG_REG_R0 = 0,
-    TCG_REG_R1,
-    TCG_REG_RP,
-    TCG_REG_R3,
-    TCG_REG_R4,
-    TCG_REG_R5,
-    TCG_REG_R6,
-    TCG_REG_R7,
-    TCG_REG_R8,
-    TCG_REG_R9,
-    TCG_REG_R10,
-    TCG_REG_R11,
-    TCG_REG_R12,
-    TCG_REG_R13,
-    TCG_REG_R14,
-    TCG_REG_R15,
-    TCG_REG_R16,
-    TCG_REG_R17,
-    TCG_REG_R18,
-    TCG_REG_R19,
-    TCG_REG_R20,
-    TCG_REG_R21,
-    TCG_REG_R22,
-    TCG_REG_R23,
-    TCG_REG_R24,
-    TCG_REG_R25,
-    TCG_REG_R26,
-    TCG_REG_DP,
-    TCG_REG_RET0,
-    TCG_REG_RET1,
-    TCG_REG_SP,
-    TCG_REG_R31,
-} TCGReg;
-
-#define TCG_CT_CONST_0    0x0100
-#define TCG_CT_CONST_S5   0x0200
-#define TCG_CT_CONST_S11  0x0400
-#define TCG_CT_CONST_MS11 0x0800
-#define TCG_CT_CONST_AND  0x1000
-#define TCG_CT_CONST_OR   0x2000
-
-/* used for function call generation */
-#define TCG_REG_CALL_STACK TCG_REG_SP
-#define TCG_TARGET_STACK_ALIGN 64
-#define TCG_TARGET_CALL_STACK_OFFSET -48
-#define TCG_TARGET_STATIC_CALL_ARGS_SIZE 8*4
-#define TCG_TARGET_CALL_ALIGN_ARGS 1
-#define TCG_TARGET_STACK_GROWSUP
-
-/* optional instructions */
-#define TCG_TARGET_HAS_div_i32          0
-#define TCG_TARGET_HAS_rem_i32          0
-#define TCG_TARGET_HAS_rot_i32          1
-#define TCG_TARGET_HAS_ext8s_i32        1
-#define TCG_TARGET_HAS_ext16s_i32       1
-#define TCG_TARGET_HAS_bswap16_i32      1
-#define TCG_TARGET_HAS_bswap32_i32      1
-#define TCG_TARGET_HAS_not_i32          1
-#define TCG_TARGET_HAS_andc_i32         1
-#define TCG_TARGET_HAS_orc_i32          0
-#define TCG_TARGET_HAS_eqv_i32          0
-#define TCG_TARGET_HAS_nand_i32         0
-#define TCG_TARGET_HAS_nor_i32          0
-#define TCG_TARGET_HAS_deposit_i32      1
-#define TCG_TARGET_HAS_movcond_i32      1
-#define TCG_TARGET_HAS_muls2_i32        0
-#define TCG_TARGET_HAS_muluh_i32        0
-#define TCG_TARGET_HAS_mulsh_i32        0
-
-/* optional instructions automatically implemented */
-#define TCG_TARGET_HAS_neg_i32          0 /* sub rd, 0, rs */
-#define TCG_TARGET_HAS_ext8u_i32        0 /* and rd, rs, 0xff */
-#define TCG_TARGET_HAS_ext16u_i32       0 /* and rd, rs, 0xffff */
-
-#define TCG_AREG0 TCG_REG_R17
-
-
-static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
-{
-    start &= ~31;
-    while (start <= stop) {
-        asm volatile ("fdc 0(%0)\n\t"
-                      "sync\n\t"
-                      "fic 0(%%sr4, %0)\n\t"
-                      "sync"
-                      : : "r"(start) : "memory");
-        start += 32;
-    }
-}
-
-#endif
commit f2c6bcfc2e15e1dc5c69c3e579ff2063068ecb85
Merge: 634ebf4 33876df
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Thu Oct 10 10:03:38 2013 -0700

    Merge remote-tracking branch 'sstabellini/xen-2013-10-10' into staging
    
    # By Matthew Daley (1) and Roger Pau Monné (1)
    # Via Stefano Stabellini
    * sstabellini/xen-2013-10-10:
      qemu/xen: make use of xenstore relative paths
      xen_disk: mark ioreq as mapped before unmapping in error case

commit 634ebf4b177723f2cf329a719f31913cf9ce5de6
Merge: c4ca690 8464243
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Thu Oct 10 10:03:00 2013 -0700

    Merge remote-tracking branch 'bonzini/scsi-next' into staging
    
    # By Asias He (1) and Peter Lieven (1)
    # Via Paolo Bonzini
    * bonzini/scsi-next:
      scsi: Allocate SCSITargetReq r->buf dynamically [CVE-2013-4344]
      block/iscsi: reenable iscsi_co_get_block_status
    
    Message-id: 1381332391-8781-1-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit c4ca6901582c00a2d13368520779e4948b184071
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Thu Oct 10 09:56:25 2013 -0700

    Update email address
    
    Amazon is now funding my work as QEMU maintainer so update addresses
    accordingly.
    
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

diff --git a/MAINTAINERS b/MAINTAINERS
index ab8166a..fbe1fd9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -50,7 +50,7 @@ Descriptions of section entries:
 
 General Project Administration
 ------------------------------
-M: Anthony Liguori <anthony at codemonkey.ws>
+M: Anthony Liguori <aliguori at amazon.com>
 
 Guest CPU cores (TCG):
 ----------------------
@@ -499,7 +499,7 @@ F: hw/unicore32/
 X86 Machines
 ------------
 PC
-M: Anthony Liguori <anthony at codemonkey.ws>
+M: Anthony Liguori <aliguori at amazon.com>
 S: Supported
 F: hw/i386/pc.[ch]
 F: hw/i386/pc_piix.c
@@ -582,7 +582,7 @@ S: Supported
 F: hw/*/*vhost*
 
 virtio
-M: Anthony Liguori <anthony at codemonkey.ws>
+M: Anthony Liguori <aliguori at amazon.com>
 S: Supported
 F: hw/*/virtio*
 
@@ -641,7 +641,7 @@ F: block/
 F: hw/block/
 
 Character Devices
-M: Anthony Liguori <anthony at codemonkey.ws>
+M: Anthony Liguori <aliguori at amazon.com>
 S: Maintained
 F: qemu-char.c
 
@@ -679,7 +679,7 @@ F: audio/spiceaudio.c
 F: hw/display/qxl*
 
 Graphics
-M: Anthony Liguori <anthony at codemonkey.ws>
+M: Anthony Liguori <aliguori at amazon.com>
 S: Maintained
 F: ui/
 
@@ -689,7 +689,7 @@ S: Odd Fixes
 F: ui/cocoa.m
 
 Main loop
-M: Anthony Liguori <anthony at codemonkey.ws>
+M: Anthony Liguori <aliguori at amazon.com>
 S: Supported
 F: vl.c
 
@@ -701,7 +701,7 @@ F: hmp.c
 F: hmp-commands.hx
 
 Network device layer
-M: Anthony Liguori <anthony at codemonkey.ws>
+M: Anthony Liguori <aliguori at amazon.com>
 M: Stefan Hajnoczi <stefanha at redhat.com>
 S: Maintained
 F: net/
commit 33876dfad64bc481f59c5e9ccf60db78624c4b93
Author: Roger Pau Monné <roger.pau at citrix.com>
Date:   Thu Oct 10 14:25:52 2013 +0000

    qemu/xen: make use of xenstore relative paths
    
    Qemu has several hardcoded xenstore paths that are only valid on Dom0.
    Attempts to launch a Qemu instance (to act as a userspace backend for
    PV disks) will fail because Qemu is not able to access those paths
    when running on a domain different than Dom0.
    
    Instead make the xenstore paths relative to the domain where Qemu is
    actually running.
    
    Signed-off-by: Roger Pau Monné <roger.pau at citrix.com>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Reviewed-by: Anthony PERARD <anthony.perard at citrix.com>
    Cc: xen-devel at lists.xenproject.org
    Cc: Anthony PERARD <anthony.perard at citrix.com>

diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
index d82ce5d..197795f 100644
--- a/hw/xen/xen_backend.c
+++ b/hw/xen/xen_backend.c
@@ -205,7 +205,6 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
                                            struct XenDevOps *ops)
 {
     struct XenDevice *xendev;
-    char *dom0;
 
     xendev = xen_be_find_xendev(type, dom, dev);
     if (xendev) {
@@ -219,12 +218,10 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
     xendev->dev   = dev;
     xendev->ops   = ops;
 
-    dom0 = xs_get_domain_path(xenstore, 0);
-    snprintf(xendev->be, sizeof(xendev->be), "%s/backend/%s/%d/%d",
-             dom0, xendev->type, xendev->dom, xendev->dev);
+    snprintf(xendev->be, sizeof(xendev->be), "backend/%s/%d/%d",
+             xendev->type, xendev->dom, xendev->dev);
     snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
              xendev->type, xendev->dev);
-    free(dom0);
 
     xendev->debug      = debug;
     xendev->local_port = -1;
@@ -570,14 +567,12 @@ static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
 {
     struct XenDevice *xendev;
     char path[XEN_BUFSIZE], token[XEN_BUFSIZE];
-    char **dev = NULL, *dom0;
+    char **dev = NULL;
     unsigned int cdev, j;
 
     /* setup watch */
-    dom0 = xs_get_domain_path(xenstore, 0);
     snprintf(token, sizeof(token), "be:%p:%d:%p", type, dom, ops);
-    snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
-    free(dom0);
+    snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
     if (!xs_watch(xenstore, path, token)) {
         xen_be_printf(NULL, 0, "xen be: watching backend path (%s) failed\n", path);
         return -1;
@@ -603,12 +598,10 @@ static void xenstore_update_be(char *watch, char *type, int dom,
                                struct XenDevOps *ops)
 {
     struct XenDevice *xendev;
-    char path[XEN_BUFSIZE], *dom0, *bepath;
+    char path[XEN_BUFSIZE], *bepath;
     unsigned int len, dev;
 
-    dom0 = xs_get_domain_path(xenstore, 0);
-    len = snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
-    free(dom0);
+    len = snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
     if (strncmp(path, watch, len) != 0) {
         return;
     }
diff --git a/xen-all.c b/xen-all.c
index 48e881b..9a27899 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -949,7 +949,7 @@ static void xenstore_record_dm_state(struct xs_handle *xs, const char *state)
         exit(1);
     }
 
-    snprintf(path, sizeof (path), "/local/domain/0/device-model/%u/state", xen_domid);
+    snprintf(path, sizeof (path), "device-model/%u/state", xen_domid);
     if (!xs_write(xs, XBT_NULL, path, state, strlen(state))) {
         fprintf(stderr, "error recording dm state\n");
         exit(1);
commit a76f48e53382e6f039db6278443e3ce437653302
Author: Matthew Daley <mattjd at gmail.com>
Date:   Thu Oct 10 14:10:48 2013 +0000

    xen_disk: mark ioreq as mapped before unmapping in error case
    
    Commit 4472beae modified the semantics of ioreq_{un,}map so that they are
    idempotent if called when they're not needed (ie., twice in a row). However,
    it neglected to handle the case where batch mapping is not being used (the
    default), and one of the grants fails to map. In this case, ioreq_unmap will
    be called to unwind and unmap any mappings already performed, but ioreq_unmap
    simply returns due to the aforementioned change (the ioreq has not already
    been marked as mapped).
    
    The frontend user can therefore force xen_disk to leak grant mappings, a
    per-domain limited resource.
    
    Fix by marking the ioreq as mapped before calling ioreq_unmap in this
    situation.
    
    Signed-off-by: Matthew Daley <mattjd at gmail.com>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
index f35fc59..8742294 100644
--- a/hw/block/xen_disk.c
+++ b/hw/block/xen_disk.c
@@ -405,6 +405,7 @@ static int ioreq_map(struct ioreq *ioreq)
                 xen_be_printf(&ioreq->blkdev->xendev, 0,
                               "can't map grant ref %d (%s, %d maps)\n",
                               refs[i], strerror(errno), ioreq->blkdev->cnt_map);
+                ioreq->mapped = 1;
                 ioreq_unmap(ioreq);
                 return -1;
             }
commit 846424350b292f16b732b573273a5c1f195cd7a3
Author: Asias He <asias at redhat.com>
Date:   Wed Oct 9 15:41:03 2013 +0800

    scsi: Allocate SCSITargetReq r->buf dynamically [CVE-2013-4344]
    
    r->buf is hardcoded to 2056 which is (256 + 1) * 8, allowing 256 luns at
    most. If more than 256 luns are specified by user, we have buffer
    overflow in scsi_target_emulate_report_luns.
    
    To fix, we allocate the buffer dynamically.
    
    Signed-off-by: Asias He <asias at redhat.com>
    Tested-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 4d36841..24ec52f 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -11,6 +11,8 @@ static char *scsibus_get_dev_path(DeviceState *dev);
 static char *scsibus_get_fw_dev_path(DeviceState *dev);
 static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
 static void scsi_req_dequeue(SCSIRequest *req);
+static uint8_t *scsi_target_alloc_buf(SCSIRequest *req, size_t len);
+static void scsi_target_free_buf(SCSIRequest *req);
 
 static Property scsi_props[] = {
     DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0),
@@ -317,7 +319,8 @@ typedef struct SCSITargetReq SCSITargetReq;
 struct SCSITargetReq {
     SCSIRequest req;
     int len;
-    uint8_t buf[2056];
+    uint8_t *buf;
+    int buf_len;
 };
 
 static void store_lun(uint8_t *outbuf, int lun)
@@ -361,14 +364,12 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
     if (!found_lun0) {
         n += 8;
     }
-    len = MIN(n + 8, r->req.cmd.xfer & ~7);
-    if (len > sizeof(r->buf)) {
-        /* TODO: > 256 LUNs? */
-        return false;
-    }
 
+    scsi_target_alloc_buf(&r->req, n + 8);
+
+    len = MIN(n + 8, r->req.cmd.xfer & ~7);
     memset(r->buf, 0, len);
-    stl_be_p(&r->buf, n);
+    stl_be_p(&r->buf[0], n);
     i = found_lun0 ? 8 : 16;
     QTAILQ_FOREACH(kid, &r->req.bus->qbus.children, sibling) {
         DeviceState *qdev = kid->child;
@@ -387,6 +388,9 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
 static bool scsi_target_emulate_inquiry(SCSITargetReq *r)
 {
     assert(r->req.dev->lun != r->req.lun);
+
+    scsi_target_alloc_buf(&r->req, SCSI_INQUIRY_LEN);
+
     if (r->req.cmd.buf[1] & 0x2) {
         /* Command support data - optional, not implemented */
         return false;
@@ -411,7 +415,7 @@ static bool scsi_target_emulate_inquiry(SCSITargetReq *r)
             return false;
         }
         /* done with EVPD */
-        assert(r->len < sizeof(r->buf));
+        assert(r->len < r->buf_len);
         r->len = MIN(r->req.cmd.xfer, r->len);
         return true;
     }
@@ -422,7 +426,7 @@ static bool scsi_target_emulate_inquiry(SCSITargetReq *r)
     }
 
     /* PAGE CODE == 0 */
-    r->len = MIN(r->req.cmd.xfer, 36);
+    r->len = MIN(r->req.cmd.xfer, SCSI_INQUIRY_LEN);
     memset(r->buf, 0, r->len);
     if (r->req.lun != 0) {
         r->buf[0] = TYPE_NO_LUN;
@@ -455,8 +459,9 @@ static int32_t scsi_target_send_command(SCSIRequest *req, uint8_t *buf)
         }
         break;
     case REQUEST_SENSE:
+        scsi_target_alloc_buf(&r->req, SCSI_SENSE_LEN);
         r->len = scsi_device_get_sense(r->req.dev, r->buf,
-                                       MIN(req->cmd.xfer, sizeof r->buf),
+                                       MIN(req->cmd.xfer, r->buf_len),
                                        (req->cmd.buf[1] & 1) == 0);
         if (r->req.dev->sense_is_ua) {
             scsi_device_unit_attention_reported(req->dev);
@@ -501,11 +506,29 @@ static uint8_t *scsi_target_get_buf(SCSIRequest *req)
     return r->buf;
 }
 
+static uint8_t *scsi_target_alloc_buf(SCSIRequest *req, size_t len)
+{
+    SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req);
+
+    r->buf = g_malloc(len);
+    r->buf_len = len;
+
+    return r->buf;
+}
+
+static void scsi_target_free_buf(SCSIRequest *req)
+{
+    SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req);
+
+    g_free(r->buf);
+}
+
 static const struct SCSIReqOps reqops_target_command = {
     .size         = sizeof(SCSITargetReq),
     .send_command = scsi_target_send_command,
     .read_data    = scsi_target_read_data,
     .get_buf      = scsi_target_get_buf,
+    .free_req     = scsi_target_free_buf,
 };
 
 
@@ -1365,7 +1388,7 @@ int scsi_build_sense(uint8_t *in_buf, int in_len,
         buf[7] = 10;
         buf[12] = sense.asc;
         buf[13] = sense.ascq;
-        return MIN(len, 18);
+        return MIN(len, SCSI_SENSE_LEN);
     } else {
         /* Return descriptor format sense buffer */
         buf[0] = 0x72;
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
index 1b66510..76f6ac2 100644
--- a/include/hw/scsi/scsi.h
+++ b/include/hw/scsi/scsi.h
@@ -9,6 +9,8 @@
 #define MAX_SCSI_DEVS	255
 
 #define SCSI_CMD_BUF_SIZE     16
+#define SCSI_SENSE_LEN      18
+#define SCSI_INQUIRY_LEN    36
 
 typedef struct SCSIBus SCSIBus;
 typedef struct SCSIBusInfo SCSIBusInfo;
commit a107170537abdfec7221c1e0d424c82f5faf2ebe
Merge: 80dfc87 d4cea8d
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Wed Oct 9 07:54:42 2013 -0700

    Merge remote-tracking branch 'stefanha/block' into staging
    
    # By Max Reitz (5) and others
    # Via Stefan Hajnoczi
    * stefanha/block:
      block: use correct filename
      qemu-iotests: Correct 026 output
      qcow2: Free allocated L2 cluster on error
      qcow2: Switch L1 table in a single sequence
      block: vhdx - add migration blocker
      block: use correct filename for error report
      qcow2: CHECK_OFLAG_COPIED is obsolete
      qcow2: Correct endianness in overlap check
    
    Message-id: 1381145289-6591-1-git-send-email-stefanha at redhat.com
    Signed-off-by: Anthony Liguori <anthony at codemonkey.ws>

commit 80dfc87394ed10f47918299a5192f337a85333d8
Merge: 576e81b 387eede
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Wed Oct 9 07:54:20 2013 -0700

    Merge remote-tracking branch 'mjt/trivial-patches' into staging
    
    # By Stefan Weil (5) and others
    # Via Michael Tokarev
    * mjt/trivial-patches:
      migration: Fix compiler warning ('caps' may be used uninitialized)
      util/path: Fix type which is longer than 8 bit for MinGW
      hw/9pfs: Fix errno value for xattr functions
      vl: Clean up unnecessary boot_order complications
      qemu-char: Fix potential out of bounds access to local arrays
      pci-ohci: Add missing 'break' in ohci_service_td
      sh4: Fix serial line access for Linux kernels later than 3.2
      hw/alpha: Fix compiler warning (integer constant is too large)
      target-i386: Fix compiler warning (integer constant is too large)
      block: Remove unused assignment (fixes warning from clang)
      exec: cleanup DEBUG_SUBPAGE
      tests: Fix schema parser test for in-tree build
      tests: Update .gitignore for test-int128 and test-bitops
      .gitignore: ignore tests/qemu-iotests/socket_scm_helper
    
    Message-id: 1381051979-25742-1-git-send-email-mjt at msgid.tls.msk.ru
    Signed-off-by: Anthony Liguori <anthony at codemonkey.ws>

commit 576e81be39ee195b9fd7c948fed16ed6846cef3a
Merge: 9e8f8b1 ee06e23
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Wed Oct 9 07:52:57 2013 -0700

    Merge remote-tracking branch 'rth/tcg-arm-pull' into staging
    
    # By Richard Henderson
    # Via Richard Henderson
    * rth/tcg-arm-pull:
      tcg-arm: Move the tlb addend load earlier
      tcg-arm: Remove restriction on qemu_ld output register
      tcg-arm: Return register containing tlb addend
      tcg-arm: Move load of tlb addend into tcg_out_tlb_read
      tcg-arm: Use QEMU_BUILD_BUG_ON to verify constraints on tlb
      tcg-arm: Use strd for tcg_out_arg_reg64
      tcg-arm: Rearrange slow-path qemu_ld/st
      tcg-arm: Use ldrd/strd for appropriate qemu_ld/st64
    
    Message-id: 1380663109-14434-1-git-send-email-rth at twiddle.net
    Signed-off-by: Anthony Liguori <anthony at codemonkey.ws>

commit 9e8f8b1cd8e1b85dc93c367c4745f9944079a37b
Merge: dfe2279 04fd1c7
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Wed Oct 9 07:52:21 2013 -0700

    Merge remote-tracking branch 'sweil/mingw' into staging
    
    # By Sebastian Ottlik
    # Via Stefan Weil
    * sweil/mingw:
      util: call socket_set_fast_reuse instead of setting SO_REUSEADDR
      slirp: call socket_set_fast_reuse instead of setting SO_REUSEADDR
      net: call socket_set_fast_reuse instead of setting SO_REUSEADDR
      gdbstub: call socket_set_fast_reuse instead of setting SO_REUSEADDR
      util: add socket_set_fast_reuse function which will replace setting SO_REUSEADDR
    
    Message-id: 1380735690-24009-1-git-send-email-sw at weilnetz.de
    Signed-off-by: Anthony Liguori <anthony at codemonkey.ws>

commit dfe22799751818115ed6d36bedc8a55b2026de3a
Merge: ce079ab ee6ee83
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Wed Oct 9 07:52:11 2013 -0700

    Merge remote-tracking branch 'kraxel/chardev.8' into staging
    
    # By Gerd Hoffmann
    # Via Gerd Hoffmann
    * kraxel/chardev.8:
      chardev: handle qmp_chardev_add(KIND_MUX) failure
    
    Message-id: 1380708925-6721-1-git-send-email-kraxel at redhat.com
    Signed-off-by: Anthony Liguori <anthony at codemonkey.ws>

commit ce079abb410d685d48c1285bc6749d9b23c78c5c
Merge: 0e19885 3df2b8f
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Wed Oct 9 07:50:37 2013 -0700

    Merge remote-tracking branch 'sweil/tci' into staging
    
    # By Stefan Weil
    # Via Stefan Weil
    * sweil/tci:
      misc: Use new rotate functions
      bitops: Add rotate functions (rol8, ror8, ...)
      tci: Add implementation of rotl_i64, rotr_i64
    
    Message-id: 1380137693-3729-1-git-send-email-sw at weilnetz.de
    Signed-off-by: Anthony Liguori <anthony at codemonkey.ws>

commit 24c7608a5d973e5d562715998e9887f74deac794
Author: Peter Lieven <pl at kamp.de>
Date:   Wed Oct 2 13:52:08 2013 +0200

    block/iscsi: reenable iscsi_co_get_block_status
    
    Commit f35c934a accidently disabled iscsi_co_get_block_status for all
    libiscsi versions. Its not possible to check for enumeration constants
    in the C preprocessor. This patch changes the check to the preprocessor
    constant LIBISCSI_FEATURE_IOVECTOR which was introduced shortly after
    get_lba_status support was added to libiscsi.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/iscsi.c b/block/iscsi.c
index 6152ef1..a2a961e 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -811,7 +811,7 @@ iscsi_getlength(BlockDriverState *bs)
     return len;
 }
 
-#if defined(SCSI_PROVISIONING_TYPE_DEALLOCATED)
+#if defined(LIBISCSI_FEATURE_IOVECTOR)
 
 static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,
                                                   int64_t sector_num,
@@ -903,7 +903,7 @@ out:
     return ret;
 }
 
-#endif /* SCSI_PROVISIONING_TYPE_DEALLOCATED */
+#endif /* LIBISCSI_FEATURE_IOVECTOR */
 
 static int
 coroutine_fn iscsi_co_discard(BlockDriverState *bs, int64_t sector_num,
@@ -1529,7 +1529,7 @@ static BlockDriver bdrv_iscsi = {
     .bdrv_getlength  = iscsi_getlength,
     .bdrv_truncate   = iscsi_truncate,
 
-#if defined(SCSI_PROVISIONING_TYPE_DEALLOCATED)
+#if defined(LIBISCSI_FEATURE_IOVECTOR)
     .bdrv_co_get_block_status = iscsi_co_get_block_status,
 #endif
     .bdrv_co_discard      = iscsi_co_discard,
commit d4cea8dfb99153803164915c7a1109549ad3da9c
Author: Dunrong Huang <riegamaths at gmail.com>
Date:   Thu Oct 3 01:31:27 2013 +0800

    block: use correct filename
    
    The content filename point to may be erased by qemu_opts_absorb_qdict()
    in raw_open_common() in drv->bdrv_file_open()
    
    So it's better to use bs->filename.
    
    Signed-off-by: Dunrong Huang <riegamaths at gmail.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block.c b/block.c
index e2d9936..d7ca37e 100644
--- a/block.c
+++ b/block.c
@@ -824,8 +824,8 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
 
 #ifndef _WIN32
     if (bs->is_temporary) {
-        assert(filename != NULL);
-        unlink(filename);
+        assert(bs->filename[0] != '\0');
+        unlink(bs->filename);
     }
 #endif
     return 0;
commit 5c1fa87708d5f226bfd96e8eef8c905fb6895ae3
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Oct 2 16:45:31 2013 +0200

    qemu-iotests: Correct 026 output
    
    Because l2_allocate now frees the unused L2 cluster on error, the
    according test cases in 026 don't result in one leaked cluster anymore.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out
index 0764389..1504579 100644
--- a/tests/qemu-iotests/026.out
+++ b/tests/qemu-iotests/026.out
@@ -5,16 +5,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
 
 Event: l1_update; errno: 5; imm: off; once: on; write 
 write failed: Input/output error
-
-1 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
+No errors were found on the image.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
 Event: l1_update; errno: 5; imm: off; once: on; write -b
 write failed: Input/output error
-
-1 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
+No errors were found on the image.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
 Event: l1_update; errno: 5; imm: off; once: off; write 
@@ -33,16 +29,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
 
 Event: l1_update; errno: 28; imm: off; once: on; write 
 write failed: No space left on device
-
-1 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
+No errors were found on the image.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
 Event: l1_update; errno: 28; imm: off; once: on; write -b
 write failed: No space left on device
-
-1 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
+No errors were found on the image.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
 Event: l1_update; errno: 28; imm: off; once: off; write 
@@ -181,16 +173,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
 
 Event: l2_alloc.write; errno: 5; imm: off; once: on; write 
 write failed: Input/output error
-
-1 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
+No errors were found on the image.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
 Event: l2_alloc.write; errno: 5; imm: off; once: on; write -b
 write failed: Input/output error
-
-1 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
+No errors were found on the image.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
 Event: l2_alloc.write; errno: 5; imm: off; once: off; write 
@@ -207,16 +195,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
 
 Event: l2_alloc.write; errno: 28; imm: off; once: on; write 
 write failed: No space left on device
-
-1 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
+No errors were found on the image.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
 Event: l2_alloc.write; errno: 28; imm: off; once: on; write -b
 write failed: No space left on device
-
-1 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
+No errors were found on the image.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
 Event: l2_alloc.write; errno: 28; imm: off; once: off; write 
diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache
index 33bad0d..c9d242e 100644
--- a/tests/qemu-iotests/026.out.nocache
+++ b/tests/qemu-iotests/026.out.nocache
@@ -5,16 +5,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
 
 Event: l1_update; errno: 5; imm: off; once: on; write 
 write failed: Input/output error
-
-1 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
+No errors were found on the image.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
 Event: l1_update; errno: 5; imm: off; once: on; write -b
 write failed: Input/output error
-
-1 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
+No errors were found on the image.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
 Event: l1_update; errno: 5; imm: off; once: off; write 
@@ -33,16 +29,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
 
 Event: l1_update; errno: 28; imm: off; once: on; write 
 write failed: No space left on device
-
-1 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
+No errors were found on the image.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
 Event: l1_update; errno: 28; imm: off; once: on; write -b
 write failed: No space left on device
-
-1 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
+No errors were found on the image.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
 Event: l1_update; errno: 28; imm: off; once: off; write 
@@ -189,16 +181,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
 
 Event: l2_alloc.write; errno: 5; imm: off; once: on; write 
 write failed: Input/output error
-
-1 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
+No errors were found on the image.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
 Event: l2_alloc.write; errno: 5; imm: off; once: on; write -b
 write failed: Input/output error
-
-1 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
+No errors were found on the image.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
 Event: l2_alloc.write; errno: 5; imm: off; once: off; write 
@@ -215,16 +203,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
 
 Event: l2_alloc.write; errno: 28; imm: off; once: on; write 
 write failed: No space left on device
-
-1 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
+No errors were found on the image.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
 Event: l2_alloc.write; errno: 28; imm: off; once: on; write -b
 write failed: No space left on device
-
-1 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
+No errors were found on the image.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
 Event: l2_alloc.write; errno: 28; imm: off; once: off; write 
commit e3b21ef9e016e6d91fd71e44af5e23fb359e18f9
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Sep 25 16:37:19 2013 +0200

    qcow2: Free allocated L2 cluster on error
    
    If an error occurs in l2_allocate, the allocated (but unused) L2 cluster
    should be freed.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Reviewed-by: Benoit Canet <benoit at irqsave.net>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 2ed45f0..0fd26bb 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -273,6 +273,10 @@ fail:
         qcow2_cache_put(bs, s->l2_table_cache, (void**) table);
     }
     s->l1_table[l1_index] = old_l2_offset;
+    if (l2_offset > 0) {
+        qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t),
+                            QCOW2_DISCARD_ALWAYS);
+    }
     return ret;
 }
 
commit 51fb256ab5ebc3e1879eb1df9c828866a2ef8141
Author: Andreas Färber <afaerber at suse.de>
Date:   Tue Jul 2 18:26:11 2013 +0200

    cpu: Drop cpu_model_str from CPU_COMMON
    
    Since this is only read in cpu_copy() and linux-user has a global
    cpu_model, drop the field from generic code.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index a5c028c..01cd8c7 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -178,7 +178,5 @@ typedef struct CPUWatchpoint {
                                                                         \
     /* user data */                                                     \
     void *opaque;                                                       \
-                                                                        \
-    const char *cpu_model_str;
 
 #endif
diff --git a/linux-user/main.c b/linux-user/main.c
index 5fe587b..6b4ab09 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -42,7 +42,7 @@ const char *filename;
 const char *argv0;
 int gdbstub_port;
 envlist_t *envlist;
-const char *cpu_model;
+static const char *cpu_model;
 unsigned long mmap_min_addr;
 #if defined(CONFIG_USE_GUEST_BASE)
 unsigned long guest_base;
@@ -3287,7 +3287,7 @@ void init_task_state(TaskState *ts)
 
 CPUArchState *cpu_copy(CPUArchState *env)
 {
-    CPUArchState *new_env = cpu_init(env->cpu_model_str);
+    CPUArchState *new_env = cpu_init(cpu_model);
 #if defined(TARGET_HAS_ICE)
     CPUBreakpoint *bp;
     CPUWatchpoint *wp;
diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c
index cfad2ea..a0d5d5b 100644
--- a/target-alpha/cpu.c
+++ b/target-alpha/cpu.c
@@ -131,7 +131,6 @@ static ObjectClass *alpha_cpu_class_by_name(const char *cpu_model)
 AlphaCPU *cpu_alpha_init(const char *cpu_model)
 {
     AlphaCPU *cpu;
-    CPUAlphaState *env;
     ObjectClass *cpu_class;
 
     cpu_class = alpha_cpu_class_by_name(cpu_model);
@@ -140,9 +139,6 @@ AlphaCPU *cpu_alpha_init(const char *cpu_model)
         cpu_class = object_class_by_name(TYPE("ev67"));
     }
     cpu = ALPHA_CPU(object_new(object_class_get_name(cpu_class)));
-    env = &cpu->env;
-
-    env->cpu_model_str = cpu_model;
 
     object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
 
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 2a98be7..c63bbd7 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1749,7 +1749,6 @@ void register_cp_regs_for_features(ARMCPU *cpu)
 ARMCPU *cpu_arm_init(const char *cpu_model)
 {
     ARMCPU *cpu;
-    CPUARMState *env;
     ObjectClass *oc;
 
     oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model);
@@ -1757,8 +1756,6 @@ ARMCPU *cpu_arm_init(const char *cpu_model)
         return NULL;
     }
     cpu = ARM_CPU(object_new(object_class_get_name(oc)));
-    env = &cpu->env;
-    env->cpu_model_str = cpu_model;
 
     /* TODO this should be set centrally, once possible */
     object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index c1c994f..d0c9bdb 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1899,7 +1899,6 @@ X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge,
                        Error **errp)
 {
     X86CPU *cpu = NULL;
-    CPUX86State *env;
     gchar **model_pieces;
     char *name, *features;
     char *typename;
@@ -1922,8 +1921,6 @@ X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge,
     qdev_set_parent_bus(DEVICE(cpu), qdev_get_child_bus(icc_bridge, "icc"));
     object_unref(OBJECT(cpu));
 #endif
-    env = &cpu->env;
-    env->cpu_model_str = cpu_model;
 
     cpu_x86_register(cpu, name, &error);
     if (error) {
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 00a7a08..a8f32fc 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -110,7 +110,6 @@ M68kCPU *cpu_m68k_init(const char *cpu_model)
     }
     cpu = M68K_CPU(object_new(object_class_get_name(oc)));
     env = &cpu->env;
-    env->cpu_model_str = cpu_model;
 
     register_m68k_insns(env);
 
diff --git a/target-mips/translate.c b/target-mips/translate.c
index ad43d59..dea3956 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15907,7 +15907,6 @@ MIPSCPU *cpu_mips_init(const char *cpu_model)
     cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
     env = &cpu->env;
     env->cpu_model = def;
-    env->cpu_model_str = cpu_model;
 
 #ifndef CONFIG_USER_ONLY
     mmu_init(env, def);
diff --git a/target-moxie/cpu.c b/target-moxie/cpu.c
index d97a091..484ecc2 100644
--- a/target-moxie/cpu.c
+++ b/target-moxie/cpu.c
@@ -138,7 +138,6 @@ MoxieCPU *cpu_moxie_init(const char *cpu_model)
         return NULL;
     }
     cpu = MOXIE_CPU(object_new(object_class_get_name(oc)));
-    cpu->env.cpu_model_str = cpu_model;
 
     object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
 
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
index 075f00a..8137943 100644
--- a/target-openrisc/cpu.c
+++ b/target-openrisc/cpu.c
@@ -209,7 +209,6 @@ OpenRISCCPU *cpu_openrisc_init(const char *cpu_model)
         return NULL;
     }
     cpu = OPENRISC_CPU(object_new(object_class_get_name(oc)));
-    cpu->env.cpu_model_str = cpu_model;
 
     object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
 
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index d2645ba..651da6b 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8267,7 +8267,6 @@ static ObjectClass *ppc_cpu_class_by_name(const char *name)
 PowerPCCPU *cpu_ppc_init(const char *cpu_model)
 {
     PowerPCCPU *cpu;
-    CPUPPCState *env;
     ObjectClass *oc;
     Error *err = NULL;
 
@@ -8277,8 +8276,6 @@ PowerPCCPU *cpu_ppc_init(const char *cpu_model)
     }
 
     cpu = POWERPC_CPU(object_new(object_class_get_name(oc)));
-    env = &cpu->env;
-    env->cpu_model_str = cpu_model;
 
     object_property_set_bool(OBJECT(cpu), true, "realized", &err);
     if (err != NULL) {
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 61abfd7..da33b38 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -73,11 +73,8 @@ void s390x_cpu_timer(void *opaque)
 S390CPU *cpu_s390x_init(const char *cpu_model)
 {
     S390CPU *cpu;
-    CPUS390XState *env;
 
     cpu = S390_CPU(object_new(TYPE_S390_CPU));
-    env = &cpu->env;
-    env->cpu_model_str = cpu_model;
 
     object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
 
diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c
index 34b2b57..c23294d 100644
--- a/target-sh4/cpu.c
+++ b/target-sh4/cpu.c
@@ -144,7 +144,6 @@ static ObjectClass *superh_cpu_class_by_name(const char *cpu_model)
 SuperHCPU *cpu_sh4_init(const char *cpu_model)
 {
     SuperHCPU *cpu;
-    CPUSH4State *env;
     ObjectClass *oc;
 
     oc = superh_cpu_class_by_name(cpu_model);
@@ -152,8 +151,6 @@ SuperHCPU *cpu_sh4_init(const char *cpu_model)
         return NULL;
     }
     cpu = SUPERH_CPU(object_new(object_class_get_name(oc)));
-    env = &cpu->env;
-    env->cpu_model_str = cpu_model;
 
     object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
 
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index 47ce60d..e7f878e 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -84,7 +84,6 @@ static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
         env->def->features |= CPU_FEATURE_FLOAT128;
     }
 #endif
-    env->cpu_model_str = cpu_model;
     env->version = def->iu_version;
     env->fsr = def->fpu_version;
     env->nwindows = def->nwindows;
diff --git a/target-unicore32/helper.c b/target-unicore32/helper.c
index 61eb2c3..9bf4fea 100644
--- a/target-unicore32/helper.c
+++ b/target-unicore32/helper.c
@@ -37,7 +37,6 @@ CPUUniCore32State *uc32_cpu_init(const char *cpu_model)
     }
     cpu = UNICORE32_CPU(object_new(object_class_get_name(oc)));
     env = &cpu->env;
-    env->cpu_model_str = cpu_model;
 
     object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
 
commit 30ba0ee52d1519b717089782ef1caf0480a01dc3
Author: Andreas Färber <afaerber at suse.de>
Date:   Tue Jul 2 17:43:21 2013 +0200

    cpu: Move cpu_copy() into linux-user
    
    It is only used there and is deemed very fragile if not incorrect in its
    current memcpy() form. Moving it into linux-user will allow to move
    parts into target_cpu.h headers and only copy what the ABI mandates.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/exec.c b/exec.c
index 26681ce..bccd891 100644
--- a/exec.c
+++ b/exec.c
@@ -625,38 +625,6 @@ void cpu_abort(CPUArchState *env, const char *fmt, ...)
     abort();
 }
 
-CPUArchState *cpu_copy(CPUArchState *env)
-{
-    CPUArchState *new_env = cpu_init(env->cpu_model_str);
-#if defined(TARGET_HAS_ICE)
-    CPUBreakpoint *bp;
-    CPUWatchpoint *wp;
-#endif
-
-    /* Reset non arch specific state */
-    cpu_reset(ENV_GET_CPU(new_env));
-
-    /* Copy arch specific state into the new CPU */
-    memcpy(new_env, env, sizeof(CPUArchState));
-
-    /* Clone all break/watchpoints.
-       Note: Once we support ptrace with hw-debug register access, make sure
-       BP_CPU break/watchpoints are handled correctly on clone. */
-    QTAILQ_INIT(&env->breakpoints);
-    QTAILQ_INIT(&env->watchpoints);
-#if defined(TARGET_HAS_ICE)
-    QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
-        cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
-    }
-    QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
-        cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
-                              wp->flags, NULL);
-    }
-#endif
-
-    return new_env;
-}
-
 #if !defined(CONFIG_USER_ONLY)
 static void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t end,
                                       uintptr_t length)
diff --git a/linux-user/main.c b/linux-user/main.c
index 1561950..5fe587b 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3285,6 +3285,37 @@ void init_task_state(TaskState *ts)
     ts->sigqueue_table[i].next = NULL;
 }
 
+CPUArchState *cpu_copy(CPUArchState *env)
+{
+    CPUArchState *new_env = cpu_init(env->cpu_model_str);
+#if defined(TARGET_HAS_ICE)
+    CPUBreakpoint *bp;
+    CPUWatchpoint *wp;
+#endif
+
+    /* Reset non arch specific state */
+    cpu_reset(ENV_GET_CPU(new_env));
+
+    memcpy(new_env, env, sizeof(CPUArchState));
+
+    /* Clone all break/watchpoints.
+       Note: Once we support ptrace with hw-debug register access, make sure
+       BP_CPU break/watchpoints are handled correctly on clone. */
+    QTAILQ_INIT(&env->breakpoints);
+    QTAILQ_INIT(&env->watchpoints);
+#if defined(TARGET_HAS_ICE)
+    QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+        cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
+    }
+    QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
+        cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
+                              wp->flags, NULL);
+    }
+#endif
+
+    return new_env;
+}
+
 static void handle_arg_help(const char *arg)
 {
     usage();
commit 812586405c5d165aae791d3806a9bbb8312ec2ac
Author: liguang <lig.fnst at cn.fujitsu.com>
Date:   Tue Sep 3 15:05:17 2013 +0800

    cputlb: Remove dead function tlb_update_dirty()
    
    Signed-off-by: liguang <lig.fnst at cn.fujitsu.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/cputlb.c b/cputlb.c
index 19ecf60..fff0afb 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -169,21 +169,6 @@ static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
     return ram_addr;
 }
 
-static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
-{
-    ram_addr_t ram_addr;
-    void *p;
-
-    if (tlb_is_dirty_ram(tlb_entry)) {
-        p = (void *)(uintptr_t)((tlb_entry->addr_write & TARGET_PAGE_MASK)
-            + tlb_entry->addend);
-        ram_addr = qemu_ram_addr_from_host_nofail(p);
-        if (!cpu_physical_memory_is_dirty(ram_addr)) {
-            tlb_entry->addr_write |= TLB_NOTDIRTY;
-        }
-    }
-}
-
 void cpu_tlb_reset_dirty_all(ram_addr_t start1, ram_addr_t length)
 {
     CPUState *cpu;
commit 6c78f29a2424622bfc9c30dfbbc13404481eacb6
Author: Juergen Lock <qemu-l at jelal.kn-bremen.de>
Date:   Thu Oct 3 16:09:37 2013 +0200

    cpu-exec: Also reload CPUClass *cc after longjmp return in cpu_exec()
    
    Local variable CPUClass *cc needs to be reloaded after return from longjmp,
    too.  (This fixes a mips-softmmu crash observed on FreeBSD when QEMU is
    built with clang.)
    
    Reported-by: Dimitry Andric <dim at FreeBSD.org>
    Signed-off-by: Juergen Lock <nox at jelal.kn-bremen.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/cpu-exec.c b/cpu-exec.c
index 5a43995..30cfa2a 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -681,6 +681,10 @@ int cpu_exec(CPUArchState *env)
              * local variables as longjmp is marked 'noreturn'. */
             cpu = current_cpu;
             env = cpu->env_ptr;
+#if !(defined(CONFIG_USER_ONLY) && \
+      (defined(TARGET_M68K) || defined(TARGET_PPC) || defined(TARGET_S390X)))
+            cc = CPU_GET_CLASS(cpu);
+#endif
         }
     } /* for(;;) */
 
commit 387eedebf60a463ba30833588f10123da296ba4d
Author: Michael Tokarev <mjt at tls.msk.ru>
Date:   Sat Oct 5 13:18:28 2013 +0400

    migration: Fix compiler warning ('caps' may be used uninitialized)
    
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>
    Reviewed-by: Stefan Weil <sw at weilnetz.de>

diff --git a/migration.c b/migration.c
index b4f8462..2b1ab20 100644
--- a/migration.c
+++ b/migration.c
@@ -150,6 +150,7 @@ MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp)
     MigrationState *s = migrate_get_current();
     int i;
 
+    caps = NULL; /* silence compiler warning */
     for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
         if (head == NULL) {
             head = g_malloc0(sizeof(*caps));
commit ddd23638d7eebd7419148ba8db65f0d53a1920ab
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Oct 2 22:40:29 2013 +0200

    util/path: Fix type which is longer than 8 bit for MinGW
    
    While dirent->d_type is 8 bit for most systems, it is 32 bit for MinGW.
    Reducing it to 8 bit results in a compiler warning because the macro
    is_dir_maybe compares that 8 bit value with 32 bit constants.
    
    Using 'unsigned' instead of 'unsigned char' matches the declaration for
    MinGW and does not harm the other systems.
    
    MinGW-w64 is not affected: it does not declare d_type.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/util/path.c b/util/path.c
index f0c6962..623219e 100644
--- a/util/path.c
+++ b/util/path.c
@@ -39,7 +39,7 @@ static int strneq(const char *s1, unsigned int n, const char *s2)
 }
 
 static struct pathelem *add_entry(struct pathelem *root, const char *name,
-                                  unsigned char type);
+                                  unsigned type);
 
 static struct pathelem *new_entry(const char *root,
                                   struct pathelem *parent,
@@ -82,7 +82,7 @@ static struct pathelem *add_dir_maybe(struct pathelem *path)
 }
 
 static struct pathelem *add_entry(struct pathelem *root, const char *name,
-                                  unsigned char type)
+                                  unsigned type)
 {
     struct pathelem **e;
 
commit 8af00205445eb901f17ca5b632d976065187538e
Author: Daniel P. Berrange <berrange at redhat.com>
Date:   Tue Oct 1 12:28:17 2013 +0100

    hw/9pfs: Fix errno value for xattr functions
    
    If there is no operation driver for the xattr type the
    functions return '-1' and set errno to '-EOPNOTSUPP'.
    When the calling code sets 'ret = -errno' this turns
    into a large positive number.
    
    In Linux 3.11, the kernel has switched to using 9p
    version 9p2000.L, instead of 9p2000.u, which enables
    support for xattr operations. This on its own is harmless,
    but for another change which makes it request the xattr
    with a name 'security.capability'.
    
    The result is that the guest sees a succesful return
    of 95 bytes of data, instead of a failure with errno
    set to 95. Since the kernel expects a maximum of 20
    bytes for an xattr return this gets translated to the
    unexpected errno ERANGE.
    
    This all means that when running a binary off a 9p fs
    in 3.11 kernels you get a fun result of:
    
      # ./date
      sh: ./date: Numerical result out of range
    
    The only workaround is to pass 'version=9p2000.u' when
    mounting the 9p fs in the guest, to disable all use of
    xattrs.
    
    Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
    Reviewed-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/hw/9pfs/virtio-9p-xattr.c b/hw/9pfs/virtio-9p-xattr.c
index 90ae565..3fae557 100644
--- a/hw/9pfs/virtio-9p-xattr.c
+++ b/hw/9pfs/virtio-9p-xattr.c
@@ -36,7 +36,7 @@ ssize_t v9fs_get_xattr(FsContext *ctx, const char *path,
     if (xops) {
         return xops->getxattr(ctx, path, name, value, size);
     }
-    errno = -EOPNOTSUPP;
+    errno = EOPNOTSUPP;
     return -1;
 }
 
@@ -123,7 +123,7 @@ int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
     if (xops) {
         return xops->setxattr(ctx, path, name, value, size, flags);
     }
-    errno = -EOPNOTSUPP;
+    errno = EOPNOTSUPP;
     return -1;
 
 }
@@ -135,7 +135,7 @@ int v9fs_remove_xattr(FsContext *ctx,
     if (xops) {
         return xops->removexattr(ctx, path, name);
     }
-    errno = -EOPNOTSUPP;
+    errno = EOPNOTSUPP;
     return -1;
 
 }
commit e3fdc535f25b471e55ac3c8b9f0b504957015bbe
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Oct 1 13:47:22 2013 +0200

    vl: Clean up unnecessary boot_order complications
    
    Messed up in commit 8281abd.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/vl.c b/vl.c
index 983cdc6..7e1f408 100644
--- a/vl.c
+++ b/vl.c
@@ -2825,7 +2825,7 @@ int main(int argc, char **argv, char **envp)
     const char *icount_option = NULL;
     const char *initrd_filename;
     const char *kernel_filename, *kernel_cmdline;
-    const char *boot_order = NULL;
+    const char *boot_order;
     DisplayState *ds;
     int cyls, heads, secs, translation;
     QemuOpts *hda_opts = NULL, *opts, *machine_opts;
@@ -4050,9 +4050,7 @@ int main(int argc, char **argv, char **envp)
     initrd_filename = qemu_opt_get(machine_opts, "initrd");
     kernel_cmdline = qemu_opt_get(machine_opts, "append");
 
-    if (!boot_order) {
-        boot_order = machine->default_boot_order;
-    }
+    boot_order = machine->default_boot_order;
     opts = qemu_opts_find(qemu_find_opts("boot-opts"), NULL);
     if (opts) {
         char *normal_boot_order;
commit 49aa4058ac6dd0081aaa45776f07c98df397ca5e
Author: Stefan Weil <sw at weilnetz.de>
Date:   Mon Sep 30 23:04:49 2013 +0200

    qemu-char: Fix potential out of bounds access to local arrays
    
    Latest gcc-4.8 supports a new option -fsanitize=address which activates
    an AddressSanitizer. This AddressSanitizer stops the QEMU system emulation
    very early because two character arrays of size 8 are potentially written
    with 9 bytes.
    
    Commit 6ea314d91439741e95772dfbab98b4135e04bebb added the code.
    
    There is no obvious reason why width or height could need 8 characters,
    so reduce it to 7 characters which together with the terminating '\0'
    fit into the arrays.
    
    Cc: qemu-stable <qemu-stable at nongnu.org>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Reviewed-by: Alex Bennée <alex at bennee.com>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/qemu-char.c b/qemu-char.c
index f7f5464..6d393e6 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2989,11 +2989,11 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
     if (strstart(filename, "vc", &p)) {
         qemu_opt_set(opts, "backend", "vc");
         if (*p == ':') {
-            if (sscanf(p+1, "%8[0-9]x%8[0-9]", width, height) == 2) {
+            if (sscanf(p+1, "%7[0-9]x%7[0-9]", width, height) == 2) {
                 /* pixels */
                 qemu_opt_set(opts, "width", width);
                 qemu_opt_set(opts, "height", height);
-            } else if (sscanf(p+1, "%8[0-9]Cx%8[0-9]C", width, height) == 2) {
+            } else if (sscanf(p+1, "%7[0-9]Cx%7[0-9]C", width, height) == 2) {
                 /* chars */
                 qemu_opt_set(opts, "cols", width);
                 qemu_opt_set(opts, "rows", height);
commit b1c50c5f248805be747e96e89efbe784ee99f764
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Fri Oct 4 12:50:51 2013 -0600

    vfio-pci: Fix endian issues in vfio_pci_size_rom()
    
    VFIO is always little endian so do byte swapping of our mask on the
    way in and byte swapping of the size on the way out.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Reported-by: Alexey Kardashevskiy <aik at ozlabs.ru>

diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index 1fbc40b..a2d5283 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -1141,7 +1141,7 @@ static const MemoryRegionOps vfio_rom_ops = {
 
 static void vfio_pci_size_rom(VFIODevice *vdev)
 {
-    uint32_t orig, size = (uint32_t)PCI_ROM_ADDRESS_MASK;
+    uint32_t orig, size = cpu_to_le32((uint32_t)PCI_ROM_ADDRESS_MASK);
     off_t offset = vdev->config_offset + PCI_ROM_ADDRESS;
     char name[32];
 
@@ -1163,7 +1163,7 @@ static void vfio_pci_size_rom(VFIODevice *vdev)
         return;
     }
 
-    size = ~(size & PCI_ROM_ADDRESS_MASK) + 1;
+    size = ~(le32_to_cpu(size) & PCI_ROM_ADDRESS_MASK) + 1;
 
     if (!size) {
         return;
commit 64fa25a0efcadda6e8197e8ea578f6117d01bb4b
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Fri Oct 4 08:51:36 2013 -0600

    vfio-pci: Add dummy PCI ROM write accessor
    
    Just to be sure we don't jump off any NULL pointer cliffs.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Reported-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index 68e25bd..1fbc40b 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -1128,8 +1128,14 @@ static uint64_t vfio_rom_read(void *opaque, hwaddr addr, unsigned size)
     return val;
 }
 
+static void vfio_rom_write(void *opaque, hwaddr addr,
+                           uint64_t data, unsigned size)
+{
+}
+
 static const MemoryRegionOps vfio_rom_ops = {
     .read = vfio_rom_read,
+    .write = vfio_rom_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
commit 1d5bf692e55ae22b59083741d521e27db704846d
Author: Alexey Kardashevskiy <aik at ozlabs.ru>
Date:   Thu Oct 3 09:10:09 2013 -0600

    vfio: Fix debug output for int128 values
    
    Memory regions can easily be 2^64 byte long and therefore overflow
    for just a bit but that is enough for int128_get64() to assert.
    
    This takes care of debug printing of huge section sizes.
    
    Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index 0c9bb95..68e25bd 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -2084,7 +2084,8 @@ static void vfio_listener_region_add(MemoryListener *listener,
     if (vfio_listener_skipped_section(section)) {
         DPRINTF("SKIPPING region_add %"HWADDR_PRIx" - %"PRIx64"\n",
                 section->offset_within_address_space,
-                section->offset_within_address_space + section->size - 1);
+                section->offset_within_address_space +
+                int128_get64(int128_sub(section->size, int128_one())));
         return;
     }
 
@@ -2129,7 +2130,8 @@ static void vfio_listener_region_del(MemoryListener *listener,
     if (vfio_listener_skipped_section(section)) {
         DPRINTF("SKIPPING region_del %"HWADDR_PRIx" - %"PRIx64"\n",
                 section->offset_within_address_space,
-                section->offset_within_address_space + section->size - 1);
+                section->offset_within_address_space +
+                int128_get64(int128_sub(section->size, int128_one())));
         return;
     }
 
commit 6ef8263ead779e1eecfaf1e0388f4c3941ea7ec3
Author: Sebastian Macke <sebastian at macke.de>
Date:   Thu Oct 3 16:16:14 2013 +0800

    target-openrisc: Removes a non-conforming behavior for the first page of the memory
    
    Where *software* leaves 0x0000 - 0x2000 unmapped, the hardware should
    still allow for this area to be mapped.
    
    Signed-off-by: Sebastian Macke <sebastian at macke.de>
    Signed-off-by: Stefan Kristiansson <stefan.kristiansson at saunalahti.fi>
    Reviewed-by: Jia Liu <proljc at gmail.com>

diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c
index 323a173..22d7cbe 100644
--- a/target-openrisc/mmu.c
+++ b/target-openrisc/mmu.c
@@ -122,13 +122,6 @@ static int cpu_openrisc_get_phys_addr(OpenRISCCPU *cpu,
 {
     int ret = TLBRET_MATCH;
 
-    /* [0x0000--0x2000]: unmapped */
-    if (address < 0x2000 && (cpu->env.sr & SR_SM)) {
-        *physical = address;
-        *prot = PAGE_READ | PAGE_WRITE;
-        return ret;
-    }
-
     if (rw == 2) {    /* ITLB */
        *physical = 0;
         ret = cpu->env.tlb->cpu_openrisc_map_address_code(cpu, physical,
commit bf961b52785061e1802214c9e03a1c65b261f7c1
Author: Sebastian Macke <sebastian at macke.de>
Date:   Thu Oct 3 16:04:46 2013 +0800

    target-openrisc: Correct handling of page faults.
    
    The result of (rw & 0) is always zero and therefore a logic false.
    The whole comparison will therefore never be executed, it is a obvious bug,
    we should use !(rw & 1) here.
    
    Signed-off-by: Sebastian Macke <sebastian at macke.de>
    Reviewed-by: Jia Liu <proljc at gmail.com>

diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c
index 57f5616..323a173 100644
--- a/target-openrisc/mmu.c
+++ b/target-openrisc/mmu.c
@@ -102,7 +102,7 @@ int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu,
         }
     }
 
-    if ((rw & 0) && ((right & PAGE_READ) == 0)) {
+    if (!(rw & 1) && ((right & PAGE_READ) == 0)) {
         return TLBRET_BADADDR;
     }
     if ((rw & 1) && ((right & PAGE_WRITE) == 0)) {
commit ad98acb9b1d610c4d243f53d9fb380e500d4abbe
Author: Mark Cave-Ayland <mark.cave-ayland at ilande.co.uk>
Date:   Thu Oct 3 00:04:20 2013 +0100

    Update OpenBIOS images
    
    Update OpenBIOS images to SVN r1229 built from submodule.
    
    Signed-off-by: Mark Cave-Ayland <mark.cave-ayland at ilande.co.uk>

diff --git a/pc-bios/README b/pc-bios/README
index e404a22..d70be16 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -12,7 +12,7 @@
   1275-1994 (referred to as Open Firmware) compliant firmware.
   The included images for PowerPC (for 32 and 64 bit PPC CPUs),
   Sparc32 and Sparc64 are built from OpenBIOS SVN revision
-  1198.
+  1229.
 
 - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
   implementation for certain IBM POWER hardware.  The sources are at
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
index c6b3319..550273a 100644
Binary files a/pc-bios/openbios-ppc and b/pc-bios/openbios-ppc differ
diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
index 2aa400c..01105fc 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 f6ee286..62c9e77 100644
Binary files a/pc-bios/openbios-sparc64 and b/pc-bios/openbios-sparc64 differ
diff --git a/roms/openbios b/roms/openbios
index 0f3d51e..d363cf5 160000
--- a/roms/openbios
+++ b/roms/openbios
@@ -1 +1 @@
-Subproject commit 0f3d51ef22ec9166beb3ed434d253029ed7cfe84
+Subproject commit d363cf50c50c268da7e6d0bf707adde1893d1ab9
commit f16f39c3fc973c5d7cbc2224eefb4ef5eb1e64ff
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Wed Oct 2 13:51:00 2013 -0600

    vfio-pci: Implement PCI hot reset
    
    Now that VFIO has a PCI hot reset interface, take advantage of it.
    There are two modes that we need to consider.  The first is when only
    one device within the set of devices affected is actually assigned to
    the guest.  In this case the other devices are are just held by VFIO
    for isolation and we can pretend they're not there, doing an entire
    bus reset whenever the device reset callback is triggered.  Supporting
    this case separately allows us to do the best reset we can do of the
    device even if the device is hotplugged.
    
    The second mode is when multiple affected devices are all exposed to
    the guest.  In this case we can only do a hot reset when the entire
    system is being reset.  However, this also allows us to track which
    individual devices are affected by a reset and only do them once.
    
    We split our reset function into pre- and post-reset helper functions
    prioritize the types of device resets available to us, and create
    separate _one vs _multi reset interfaces to handle the distinct cases
    above.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index a73e7f5..0c9bb95 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -188,6 +188,7 @@ typedef struct VFIODevice {
     bool pci_aer;
     bool has_flr;
     bool has_pm_reset;
+    bool needs_reset;
 } VFIODevice;
 
 typedef struct VFIOGroup {
@@ -2758,6 +2759,279 @@ static int vfio_add_capabilities(VFIODevice *vdev)
     return vfio_add_std_cap(vdev, pdev->config[PCI_CAPABILITY_LIST]);
 }
 
+static void vfio_pci_pre_reset(VFIODevice *vdev)
+{
+    PCIDevice *pdev = &vdev->pdev;
+    uint16_t cmd;
+
+    vfio_disable_interrupts(vdev);
+
+    /* Make sure the device is in D0 */
+    if (vdev->pm_cap) {
+        uint16_t pmcsr;
+        uint8_t state;
+
+        pmcsr = vfio_pci_read_config(pdev, vdev->pm_cap + PCI_PM_CTRL, 2);
+        state = pmcsr & PCI_PM_CTRL_STATE_MASK;
+        if (state) {
+            pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+            vfio_pci_write_config(pdev, vdev->pm_cap + PCI_PM_CTRL, pmcsr, 2);
+            /* vfio handles the necessary delay here */
+            pmcsr = vfio_pci_read_config(pdev, vdev->pm_cap + PCI_PM_CTRL, 2);
+            state = pmcsr & PCI_PM_CTRL_STATE_MASK;
+            if (state) {
+                error_report("vfio: Unable to power on device, stuck in D%d\n",
+                             state);
+            }
+        }
+    }
+
+    /*
+     * Stop any ongoing DMA by disconecting I/O, MMIO, and bus master.
+     * Also put INTx Disable in known state.
+     */
+    cmd = vfio_pci_read_config(pdev, PCI_COMMAND, 2);
+    cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+             PCI_COMMAND_INTX_DISABLE);
+    vfio_pci_write_config(pdev, PCI_COMMAND, cmd, 2);
+}
+
+static void vfio_pci_post_reset(VFIODevice *vdev)
+{
+    vfio_enable_intx(vdev);
+}
+
+static bool vfio_pci_host_match(PCIHostDeviceAddress *host1,
+                                PCIHostDeviceAddress *host2)
+{
+    return (host1->domain == host2->domain && host1->bus == host2->bus &&
+            host1->slot == host2->slot && host1->function == host2->function);
+}
+
+static int vfio_pci_hot_reset(VFIODevice *vdev, bool single)
+{
+    VFIOGroup *group;
+    struct vfio_pci_hot_reset_info *info;
+    struct vfio_pci_dependent_device *devices;
+    struct vfio_pci_hot_reset *reset;
+    int32_t *fds;
+    int ret, i, count;
+    bool multi = false;
+
+    DPRINTF("%s(%04x:%02x:%02x.%x) %s\n", __func__, vdev->host.domain,
+            vdev->host.bus, vdev->host.slot, vdev->host.function,
+            single ? "one" : "multi");
+
+    vfio_pci_pre_reset(vdev);
+    vdev->needs_reset = false;
+
+    info = g_malloc0(sizeof(*info));
+    info->argsz = sizeof(*info);
+
+    ret = ioctl(vdev->fd, VFIO_DEVICE_GET_PCI_HOT_RESET_INFO, info);
+    if (ret && errno != ENOSPC) {
+        ret = -errno;
+        if (!vdev->has_pm_reset) {
+            error_report("vfio: Cannot reset device %04x:%02x:%02x.%x, "
+                         "no available reset mechanism.", vdev->host.domain,
+                         vdev->host.bus, vdev->host.slot, vdev->host.function);
+        }
+        goto out_single;
+    }
+
+    count = info->count;
+    info = g_realloc(info, sizeof(*info) + (count * sizeof(*devices)));
+    info->argsz = sizeof(*info) + (count * sizeof(*devices));
+    devices = &info->devices[0];
+
+    ret = ioctl(vdev->fd, VFIO_DEVICE_GET_PCI_HOT_RESET_INFO, info);
+    if (ret) {
+        ret = -errno;
+        error_report("vfio: hot reset info failed: %m");
+        goto out_single;
+    }
+
+    DPRINTF("%04x:%02x:%02x.%x: hot reset dependent devices:\n",
+            vdev->host.domain, vdev->host.bus, vdev->host.slot,
+            vdev->host.function);
+
+    /* Verify that we have all the groups required */
+    for (i = 0; i < info->count; i++) {
+        PCIHostDeviceAddress host;
+        VFIODevice *tmp;
+
+        host.domain = devices[i].segment;
+        host.bus = devices[i].bus;
+        host.slot = PCI_SLOT(devices[i].devfn);
+        host.function = PCI_FUNC(devices[i].devfn);
+
+        DPRINTF("\t%04x:%02x:%02x.%x group %d\n", host.domain,
+                host.bus, host.slot, host.function, devices[i].group_id);
+
+        if (vfio_pci_host_match(&host, &vdev->host)) {
+            continue;
+        }
+
+        QLIST_FOREACH(group, &group_list, next) {
+            if (group->groupid == devices[i].group_id) {
+                break;
+            }
+        }
+
+        if (!group) {
+            if (!vdev->has_pm_reset) {
+                error_report("vfio: Cannot reset device %04x:%02x:%02x.%x, "
+                             "depends on group %d which is not owned.",
+                             vdev->host.domain, vdev->host.bus, vdev->host.slot,
+                             vdev->host.function, devices[i].group_id);
+            }
+            ret = -EPERM;
+            goto out;
+        }
+
+        /* Prep dependent devices for reset and clear our marker. */
+        QLIST_FOREACH(tmp, &group->device_list, next) {
+            if (vfio_pci_host_match(&host, &tmp->host)) {
+                if (single) {
+                    DPRINTF("vfio: found another in-use device "
+                            "%04x:%02x:%02x.%x\n", host.domain, host.bus,
+                            host.slot, host.function);
+                    ret = -EINVAL;
+                    goto out_single;
+                }
+                vfio_pci_pre_reset(tmp);
+                tmp->needs_reset = false;
+                multi = true;
+                break;
+            }
+        }
+    }
+
+    if (!single && !multi) {
+        DPRINTF("vfio: No other in-use devices for multi hot reset\n");
+        ret = -EINVAL;
+        goto out_single;
+    }
+
+    /* Determine how many group fds need to be passed */
+    count = 0;
+    QLIST_FOREACH(group, &group_list, next) {
+        for (i = 0; i < info->count; i++) {
+            if (group->groupid == devices[i].group_id) {
+                count++;
+                break;
+            }
+        }
+    }
+
+    reset = g_malloc0(sizeof(*reset) + (count * sizeof(*fds)));
+    reset->argsz = sizeof(*reset) + (count * sizeof(*fds));
+    fds = &reset->group_fds[0];
+
+    /* Fill in group fds */
+    QLIST_FOREACH(group, &group_list, next) {
+        for (i = 0; i < info->count; i++) {
+            if (group->groupid == devices[i].group_id) {
+                fds[reset->count++] = group->fd;
+                break;
+            }
+        }
+    }
+
+    /* Bus reset! */
+    ret = ioctl(vdev->fd, VFIO_DEVICE_PCI_HOT_RESET, reset);
+    g_free(reset);
+
+    DPRINTF("%04x:%02x:%02x.%x hot reset: %s\n", vdev->host.domain,
+            vdev->host.bus, vdev->host.slot, vdev->host.function,
+            ret ? "%m" : "Success");
+
+out:
+    /* Re-enable INTx on affected devices */
+    for (i = 0; i < info->count; i++) {
+        PCIHostDeviceAddress host;
+        VFIODevice *tmp;
+
+        host.domain = devices[i].segment;
+        host.bus = devices[i].bus;
+        host.slot = PCI_SLOT(devices[i].devfn);
+        host.function = PCI_FUNC(devices[i].devfn);
+
+        if (vfio_pci_host_match(&host, &vdev->host)) {
+            continue;
+        }
+
+        QLIST_FOREACH(group, &group_list, next) {
+            if (group->groupid == devices[i].group_id) {
+                break;
+            }
+        }
+
+        if (!group) {
+            break;
+        }
+
+        QLIST_FOREACH(tmp, &group->device_list, next) {
+            if (vfio_pci_host_match(&host, &tmp->host)) {
+                vfio_pci_post_reset(tmp);
+                break;
+            }
+        }
+    }
+out_single:
+    vfio_pci_post_reset(vdev);
+    g_free(info);
+
+    return ret;
+}
+
+/*
+ * We want to differentiate hot reset of mulitple in-use devices vs hot reset
+ * of a single in-use device.  VFIO_DEVICE_RESET will already handle the case
+ * of doing hot resets when there is only a single device per bus.  The in-use
+ * here refers to how many VFIODevices are affected.  A hot reset that affects
+ * multiple devices, but only a single in-use device, means that we can call
+ * it from our bus ->reset() callback since the extent is effectively a single
+ * device.  This allows us to make use of it in the hotplug path.  When there
+ * are multiple in-use devices, we can only trigger the hot reset during a
+ * system reset and thus from our reset handler.  We separate _one vs _multi
+ * here so that we don't overlap and do a double reset on the system reset
+ * path where both our reset handler and ->reset() callback are used.  Calling
+ * _one() will only do a hot reset for the one in-use devices case, calling
+ * _multi() will do nothing if a _one() would have been sufficient.
+ */
+static int vfio_pci_hot_reset_one(VFIODevice *vdev)
+{
+    return vfio_pci_hot_reset(vdev, true);
+}
+
+static int vfio_pci_hot_reset_multi(VFIODevice *vdev)
+{
+    return vfio_pci_hot_reset(vdev, false);
+}
+
+static void vfio_pci_reset_handler(void *opaque)
+{
+    VFIOGroup *group;
+    VFIODevice *vdev;
+
+    QLIST_FOREACH(group, &group_list, next) {
+        QLIST_FOREACH(vdev, &group->device_list, next) {
+            if (!vdev->reset_works || (!vdev->has_flr && vdev->has_pm_reset)) {
+                vdev->needs_reset = true;
+            }
+        }
+    }
+
+    QLIST_FOREACH(group, &group_list, next) {
+        QLIST_FOREACH(vdev, &group->device_list, next) {
+            if (vdev->needs_reset) {
+                vfio_pci_hot_reset_multi(vdev);
+            }
+        }
+    }
+}
+
 static int vfio_connect_container(VFIOGroup *group)
 {
     VFIOContainer *container;
@@ -2900,6 +3174,10 @@ static VFIOGroup *vfio_get_group(int groupid)
         return NULL;
     }
 
+    if (QLIST_EMPTY(&group_list)) {
+        qemu_register_reset(vfio_pci_reset_handler, NULL);
+    }
+
     QLIST_INSERT_HEAD(&group_list, group, next);
 
     return group;
@@ -2916,6 +3194,10 @@ static void vfio_put_group(VFIOGroup *group)
     DPRINTF("vfio_put_group: close group->fd\n");
     close(group->fd);
     g_free(group);
+
+    if (QLIST_EMPTY(&group_list)) {
+        qemu_unregister_reset(vfio_pci_reset_handler, NULL);
+    }
 }
 
 static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev)
@@ -2954,9 +3236,6 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev)
     }
 
     vdev->reset_works = !!(dev_info.flags & VFIO_DEVICE_FLAGS_RESET);
-    if (!vdev->reset_works) {
-        error_report("Warning, device %s does not support reset", name);
-    }
 
     if (dev_info.num_regions < VFIO_PCI_CONFIG_REGION_INDEX + 1) {
         error_report("vfio: unexpected number of io regions %u",
@@ -3362,51 +3641,34 @@ static void vfio_pci_reset(DeviceState *dev)
 {
     PCIDevice *pdev = DO_UPCAST(PCIDevice, qdev, dev);
     VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev);
-    uint16_t cmd;
 
     DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain,
             vdev->host.bus, vdev->host.slot, vdev->host.function);
 
-    vfio_disable_interrupts(vdev);
-
-    /* Make sure the device is in D0 */
-    if (vdev->pm_cap) {
-        uint16_t pmcsr;
-        uint8_t state;
+    vfio_pci_pre_reset(vdev);
 
-        pmcsr = vfio_pci_read_config(pdev, vdev->pm_cap + PCI_PM_CTRL, 2);
-        state = pmcsr & PCI_PM_CTRL_STATE_MASK;
-        if (state) {
-            pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
-            vfio_pci_write_config(pdev, vdev->pm_cap + PCI_PM_CTRL, pmcsr, 2);
-            /* vfio handles the necessary delay here */
-            pmcsr = vfio_pci_read_config(pdev, vdev->pm_cap + PCI_PM_CTRL, 2);
-            state = pmcsr & PCI_PM_CTRL_STATE_MASK;
-            if (state) {
-                error_report("vfio: Unable to power on device, stuck in D%d\n",
-                             state);
-            }
-        }
+    if (vdev->reset_works && (vdev->has_flr || !vdev->has_pm_reset) &&
+        !ioctl(vdev->fd, VFIO_DEVICE_RESET)) {
+        DPRINTF("%04x:%02x:%02x.%x FLR/VFIO_DEVICE_RESET\n", vdev->host.domain,
+            vdev->host.bus, vdev->host.slot, vdev->host.function);
+        goto post_reset;
     }
 
-    /*
-     * Stop any ongoing DMA by disconecting I/O, MMIO, and bus master.
-     * Also put INTx Disable in known state.
-     */
-    cmd = vfio_pci_read_config(pdev, PCI_COMMAND, 2);
-    cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
-             PCI_COMMAND_INTX_DISABLE);
-    vfio_pci_write_config(pdev, PCI_COMMAND, cmd, 2);
+    /* See if we can do our own bus reset */
+    if (!vfio_pci_hot_reset_one(vdev)) {
+        goto post_reset;
+    }
 
-    if (vdev->reset_works) {
-        if (ioctl(vdev->fd, VFIO_DEVICE_RESET)) {
-            error_report("vfio: Error unable to reset physical device "
-                         "(%04x:%02x:%02x.%x): %m", vdev->host.domain,
-                         vdev->host.bus, vdev->host.slot, vdev->host.function);
-        }
+    /* If nothing else works and the device supports PM reset, use it */
+    if (vdev->reset_works && vdev->has_pm_reset &&
+        !ioctl(vdev->fd, VFIO_DEVICE_RESET)) {
+        DPRINTF("%04x:%02x:%02x.%x PCI PM Reset\n", vdev->host.domain,
+            vdev->host.bus, vdev->host.slot, vdev->host.function);
+        goto post_reset;
     }
 
-    vfio_enable_intx(vdev);
+post_reset:
+    vfio_pci_post_reset(vdev);
 }
 
 static Property vfio_pci_dev_properties[] = {
commit 4b351a0f212769deda960da44e299f44d5da0737
Author: Ján Veselý <jano.vesely at gmail.com>
Date:   Sat Sep 21 16:26:41 2013 -0400

    pci-ohci: Add missing 'break' in ohci_service_td
    
    Device communication errors need to be reported to driver.
    Add a debug message while at it.
    
    Signed-off-by: Jan Vesely <jano.vesely at gmail.com>
    Acked-by: Gerd Hoffmann <kraxel at gmail.com>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 35f0878..0396e33 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -1143,7 +1143,9 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
             switch (ret) {
             case USB_RET_IOERROR:
             case USB_RET_NODEV:
+                DPRINTF("usb-ohci: got DEV ERROR\n");
                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING);
+                break;
             case USB_RET_NAK:
                 DPRINTF("usb-ohci: got NAK\n");
                 return 1;
commit 84faf7c3927ca7f3013362e38c58c02a7e733c0c
Author: Guenter Roeck <linux at roeck-us.net>
Date:   Sun Sep 8 00:39:05 2013 -0700

    sh4: Fix serial line access for Linux kernels later than 3.2
    
    With Linux kernel version 3.3 or later, qemu fails with the following message:
    
    sh_serial: unsupported read from 0x18
      Aborted
    
    Reported-and-analyzed-by: Rob Landley <rob at landley.net>
    Signed-off-by: Guenter Roeck <linux at roeck-us.net>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c
index 6223a55..9328dd1 100644
--- a/hw/char/sh_serial.c
+++ b/hw/char/sh_serial.c
@@ -248,11 +248,9 @@ static uint64_t sh_serial_read(void *opaque, hwaddr offs,
                     s->flags &= ~SH_SERIAL_FLAG_RDF;
             }
             break;
-#if 0
         case 0x18:
             ret = s->fcr;
             break;
-#endif
         case 0x1c:
             ret = s->rx_cnt;
             break;
commit 9b2caaf40bd667492b4e6228dd3d1f5e44083456
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Sep 29 17:51:20 2013 +0200

    hw/alpha: Fix compiler warning (integer constant is too large)
    
    From buildbot default_i386_rhel61:
    
      CC    alpha-softmmu/hw/alpha/typhoon.o
    hw/alpha/typhoon.c: In function 'typhoon_translate_iommu':
    hw/alpha/typhoon.c:703: warning: integer constant is too large for 'long' type
    hw/alpha/typhoon.c:703: warning: integer constant is too large for 'long' type
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Acked-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
index aac9a32..59e1bb8 100644
--- a/hw/alpha/typhoon.c
+++ b/hw/alpha/typhoon.c
@@ -700,7 +700,7 @@ static IOMMUTLBEntry typhoon_translate_iommu(MemoryRegion *iommu, hwaddr addr)
             }
         }
 
-        if (addr >= 0x80000000000 && addr <= 0xfffffffffff) {
+        if (addr >= 0x80000000000ull && addr <= 0xfffffffffffull) {
             /* Check the fourth window for DAC enable and window enable.  */
             if ((pchip->win[3].wba & 0x80000000001ull) == 0x80000000001ull) {
                 uint64_t pte_addr;
commit 00fdef658675ac2d019005769c426c275bceec6f
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Sep 29 17:55:56 2013 +0200

    target-i386: Fix compiler warning (integer constant is too large)
    
    From buildbot default_i386_rhel61:
    
      CC    i386-softmmu/target-i386/arch_memory_mapping.o
    target-i386/arch_memory_mapping.c: In function 'walk_pde':
    target-i386/arch_memory_mapping.c:110: warning:
     integer constant is too large for 'long' type
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c
index 2566a04..462f984 100644
--- a/target-i386/arch_memory_mapping.c
+++ b/target-i386/arch_memory_mapping.c
@@ -75,7 +75,7 @@ static void walk_pte2(MemoryMappingList *list,
 }
 
 /* PAE Paging or IA-32e Paging */
-#define PLM4_ADDR_MASK 0xffffffffff000 /* selects bits 51:12 */
+#define PLM4_ADDR_MASK 0xffffffffff000ULL /* selects bits 51:12 */
 
 static void walk_pde(MemoryMappingList *list, hwaddr pde_start_addr,
                      int32_t a20_mask, target_ulong start_line_addr)
commit 3a6f2703268c99f2f2f0a93f2fbacec7b039fd36
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Sep 28 11:55:14 2013 +0200

    block: Remove unused assignment (fixes warning from clang)
    
    blockdev.c:1929:13: warning: Value stored to 'ret' is never read
                ret = 0;
                ^     ~
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/blockdev.c b/blockdev.c
index 8aa66a9..8c83f6f 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1926,7 +1926,6 @@ void qmp_drive_mirror(const char *device, const char *target,
     } else {
         switch (mode) {
         case NEW_IMAGE_MODE_EXISTING:
-            ret = 0;
             break;
         case NEW_IMAGE_MODE_ABSOLUTE_PATHS:
             /* create new image with backing file */
commit 016e9d62fe66d40eff09d069714f3ccfd2066d79
Author: Amos Kong <akong at redhat.com>
Date:   Fri Sep 27 09:25:38 2013 +0800

    exec: cleanup DEBUG_SUBPAGE
    
    Touched some error after enabling DEBUG_SUBPAGE.
    
    Signed-off-by: Amos Kong <akong at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/exec.c b/exec.c
index 26681ce..51c2369 100644
--- a/exec.c
+++ b/exec.c
@@ -1573,7 +1573,7 @@ static uint64_t subpage_read(void *opaque, hwaddr addr,
     uint8_t buf[4];
 
 #if defined(DEBUG_SUBPAGE)
-    printf("%s: subpage %p len %d addr " TARGET_FMT_plx "\n", __func__,
+    printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__,
            subpage, len, addr);
 #endif
     address_space_read(subpage->as, addr + subpage->base, buf, len);
@@ -1596,7 +1596,7 @@ static void subpage_write(void *opaque, hwaddr addr,
     uint8_t buf[4];
 
 #if defined(DEBUG_SUBPAGE)
-    printf("%s: subpage %p len %d addr " TARGET_FMT_plx
+    printf("%s: subpage %p len %u addr " TARGET_FMT_plx
            " value %"PRIx64"\n",
            __func__, subpage, len, addr, value);
 #endif
@@ -1617,16 +1617,16 @@ static void subpage_write(void *opaque, hwaddr addr,
 }
 
 static bool subpage_accepts(void *opaque, hwaddr addr,
-                            unsigned size, bool is_write)
+                            unsigned len, bool is_write)
 {
     subpage_t *subpage = opaque;
 #if defined(DEBUG_SUBPAGE)
-    printf("%s: subpage %p %c len %d addr " TARGET_FMT_plx "\n",
+    printf("%s: subpage %p %c len %u addr " TARGET_FMT_plx "\n",
            __func__, subpage, is_write ? 'w' : 'r', len, addr);
 #endif
 
     return address_space_access_valid(subpage->as, addr + subpage->base,
-                                      size, is_write);
+                                      len, is_write);
 }
 
 static const MemoryRegionOps subpage_ops = {
@@ -1646,8 +1646,8 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
     idx = SUBPAGE_IDX(start);
     eidx = SUBPAGE_IDX(end);
 #if defined(DEBUG_SUBPAGE)
-    printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
-           mmio, start, end, idx, eidx, memory);
+    printf("%s: %p start %08x end %08x idx %08x eidx %08x section %d\n",
+           __func__, mmio, start, end, idx, eidx, section);
 #endif
     for (; idx <= eidx; idx++) {
         mmio->sub_section[idx] = section;
@@ -1668,8 +1668,8 @@ static subpage_t *subpage_init(AddressSpace *as, hwaddr base)
                           "subpage", TARGET_PAGE_SIZE);
     mmio->iomem.subpage = true;
 #if defined(DEBUG_SUBPAGE)
-    printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
-           mmio, base, TARGET_PAGE_SIZE, subpage_memory);
+    printf("%s: %p base " TARGET_FMT_plx " len %08x\n", __func__,
+           mmio, base, TARGET_PAGE_SIZE);
 #endif
     subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, PHYS_SECTION_UNASSIGNED);
 
commit d8039e58b1ecfdc9af171502c83e3949f6dafb95
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Sep 24 09:43:39 2013 +0200

    tests: Fix schema parser test for in-tree build
    
    Commit 4f193e3 added the test, but screwed up in-tree builds
    (SRCDIR=.): the tests's output overwrites the expected output, and is
    thus compared to itself.
    
    Cc: qemu-stable at nongnu.org
    Reported-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Laszlo Ersek <lersek at redhat.com>
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/tests/.gitignore b/tests/.gitignore
index f94ce04..425757c 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -23,3 +23,4 @@ test-thread-pool
 test-x86-cpuid
 test-xbzrle
 *-test
+qapi-schema/*.test.*
diff --git a/tests/Makefile b/tests/Makefile
index 994fef1..915ae5e 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -261,10 +261,10 @@ check-tests/test-qapi.py: tests/test-qapi.py
 
 .PHONY: $(patsubst %, check-%, $(check-qapi-schema-y))
 $(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
-	$(call quiet-command, PYTHONPATH=$(SRC_PATH)/scripts $(PYTHON) $(SRC_PATH)/tests/qapi-schema/test-qapi.py <$^ >$*.out 2>$*.err; echo $$? >$*.exit, "  TEST  $*.out")
-	@diff -q $(SRC_PATH)/$*.out $*.out
-	@diff -q $(SRC_PATH)/$*.err $*.err
-	@diff -q $(SRC_PATH)/$*.exit $*.exit
+	$(call quiet-command, PYTHONPATH=$(SRC_PATH)/scripts $(PYTHON) $(SRC_PATH)/tests/qapi-schema/test-qapi.py <$^ >$*.test.out 2>$*.test.err; echo $$? >$*.test.exit, "  TEST  $*.out")
+	@diff -q $(SRC_PATH)/$*.out $*.test.out
+	@diff -q $(SRC_PATH)/$*.err $*.test.err
+	@diff -q $(SRC_PATH)/$*.exit $*.test.exit
 
 # Consolidated targets
 
commit 8fbf47c3a8a7f37a11268a07290d20a325ba4cb6
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Wed Oct 2 12:52:38 2013 -0600

    vfio-pci: Cleanup error_reports
    
    Remove carriage returns and tweak formatting for error_reports.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index 730dec5..a73e7f5 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -3055,13 +3055,15 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev)
     ret = ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info);
     if (ret) {
         /* This can fail for an old kernel or legacy PCI dev */
-        DPRINTF("VFIO_DEVICE_GET_IRQ_INFO failure ret=%d\n", ret);
+        DPRINTF("VFIO_DEVICE_GET_IRQ_INFO failure: %m\n");
         ret = 0;
     } else if (irq_info.count == 1) {
         vdev->pci_aer = true;
     } else {
-        error_report("vfio: Warning: "
-                     "Could not enable error recovery for the device\n");
+        error_report("vfio: %04x:%02x:%02x.%x "
+                     "Could not enable error recovery for the device",
+                     vdev->host.domain, vdev->host.bus, vdev->host.slot,
+                     vdev->host.function);
     }
 
 error:
@@ -3102,11 +3104,10 @@ static void vfio_err_notifier_handler(void *opaque)
      * guest to contain the error.
      */
 
-    error_report("%s (%04x:%02x:%02x.%x)"
-        "Unrecoverable error detected...\n"
-        "Please collect any data possible and then kill the guest",
-        __func__, vdev->host.domain, vdev->host.bus,
-        vdev->host.slot, vdev->host.function);
+    error_report("%s(%04x:%02x:%02x.%x) Unrecoverable error detected.  "
+                 "Please collect any data possible and then kill the guest",
+                 __func__, vdev->host.domain, vdev->host.bus,
+                 vdev->host.slot, vdev->host.function);
 
     vm_stop(RUN_STATE_IO_ERROR);
 }
@@ -3129,8 +3130,7 @@ static void vfio_register_err_notifier(VFIODevice *vdev)
     }
 
     if (event_notifier_init(&vdev->err_notifier, 0)) {
-        error_report("vfio: Warning: "
-                     "Unable to init event notifier for error detection\n");
+        error_report("vfio: Unable to init event notifier for error detection");
         vdev->pci_aer = false;
         return;
     }
@@ -3151,7 +3151,7 @@ static void vfio_register_err_notifier(VFIODevice *vdev)
 
     ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
     if (ret) {
-        error_report("vfio: Failed to set up error notification\n");
+        error_report("vfio: Failed to set up error notification");
         qemu_set_fd_handler(*pfd, NULL, NULL, vdev);
         event_notifier_cleanup(&vdev->err_notifier);
         vdev->pci_aer = false;
@@ -3184,7 +3184,7 @@ static void vfio_unregister_err_notifier(VFIODevice *vdev)
 
     ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
     if (ret) {
-        error_report("vfio: Failed to de-assign error fd: %d\n", ret);
+        error_report("vfio: Failed to de-assign error fd: %m");
     }
     g_free(irq_set);
     qemu_set_fd_handler(event_notifier_get_fd(&vdev->err_notifier),
commit 6f864e6ec8812d5a5525a7861ca599c6bcabdebe
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Wed Oct 2 12:52:38 2013 -0600

    vfio-pci: Lazy PCI option ROM loading
    
    During vfio-pci initfn, the device is not always in a state where the
    option ROM can be read.  In the case of graphics cards, there's often
    no per function reset, which means we have host driver state affecting
    whether the option ROM is usable.  Ideally we want to move reading the
    option ROM past any co-assigned device resets to the point where the
    guest first tries to read the ROM itself.
    
    To accomplish this, we switch the memory region for the option rom to
    an I/O region rather than a memory mapped region.  This has the side
    benefit that we don't waste KVM memory slots for a BAR where we don't
    care about performance.  This also allows us to delay loading the ROM
    from the device until the first read by the guest.  We then use the
    PCI config space size of the ROM BAR when setting up the BAR through
    QEMU PCI.
    
    Another benefit of this approach is that previously when a user set
    the ROM to a file using the romfile= option, we still probed VFIO for
    the parameters of the ROM, which can result in dmesg errors about an
    invalid ROM.  We now only probe VFIO to get the ROM contents if the
    guest actually tries to read the ROM.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index ede026d..730dec5 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -166,6 +166,7 @@ typedef struct VFIODevice {
     off_t config_offset; /* Offset of config space region within device fd */
     unsigned int rom_size;
     off_t rom_offset; /* Offset of ROM region within device fd */
+    void *rom;
     int msi_cap_size;
     VFIOMSIVector *msi_vectors;
     VFIOMSIXInfo *msix;
@@ -1058,6 +1059,125 @@ static const MemoryRegionOps vfio_bar_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
+static void vfio_pci_load_rom(VFIODevice *vdev)
+{
+    struct vfio_region_info reg_info = {
+        .argsz = sizeof(reg_info),
+        .index = VFIO_PCI_ROM_REGION_INDEX
+    };
+    uint64_t size;
+    off_t off = 0;
+    size_t bytes;
+
+    if (ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, &reg_info)) {
+        error_report("vfio: Error getting ROM info: %m");
+        return;
+    }
+
+    DPRINTF("Device %04x:%02x:%02x.%x ROM:\n", vdev->host.domain,
+            vdev->host.bus, vdev->host.slot, vdev->host.function);
+    DPRINTF("  size: 0x%lx, offset: 0x%lx, flags: 0x%lx\n",
+            (unsigned long)reg_info.size, (unsigned long)reg_info.offset,
+            (unsigned long)reg_info.flags);
+
+    vdev->rom_size = size = reg_info.size;
+    vdev->rom_offset = reg_info.offset;
+
+    if (!vdev->rom_size) {
+        return;
+    }
+
+    vdev->rom = g_malloc(size);
+    memset(vdev->rom, 0xff, size);
+
+    while (size) {
+        bytes = pread(vdev->fd, vdev->rom + off, size, vdev->rom_offset + off);
+        if (bytes == 0) {
+            break;
+        } else if (bytes > 0) {
+            off += bytes;
+            size -= bytes;
+        } else {
+            if (errno == EINTR || errno == EAGAIN) {
+                continue;
+            }
+            error_report("vfio: Error reading device ROM: %m");
+            break;
+        }
+    }
+}
+
+static uint64_t vfio_rom_read(void *opaque, hwaddr addr, unsigned size)
+{
+    VFIODevice *vdev = opaque;
+    uint64_t val = ((uint64_t)1 << (size * 8)) - 1;
+
+    /* Load the ROM lazily when the guest tries to read it */
+    if (unlikely(!vdev->rom)) {
+        vfio_pci_load_rom(vdev);
+    }
+
+    memcpy(&val, vdev->rom + addr,
+           (addr < vdev->rom_size) ? MIN(size, vdev->rom_size - addr) : 0);
+
+    DPRINTF("%s(%04x:%02x:%02x.%x, 0x%"HWADDR_PRIx", 0x%x) = 0x%"PRIx64"\n",
+            __func__, vdev->host.domain, vdev->host.bus, vdev->host.slot,
+            vdev->host.function, addr, size, val);
+
+    return val;
+}
+
+static const MemoryRegionOps vfio_rom_ops = {
+    .read = vfio_rom_read,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void vfio_pci_size_rom(VFIODevice *vdev)
+{
+    uint32_t orig, size = (uint32_t)PCI_ROM_ADDRESS_MASK;
+    off_t offset = vdev->config_offset + PCI_ROM_ADDRESS;
+    char name[32];
+
+    if (vdev->pdev.romfile || !vdev->pdev.rom_bar) {
+        return;
+    }
+
+    /*
+     * Use the same size ROM BAR as the physical device.  The contents
+     * will get filled in later when the guest tries to read it.
+     */
+    if (pread(vdev->fd, &orig, 4, offset) != 4 ||
+        pwrite(vdev->fd, &size, 4, offset) != 4 ||
+        pread(vdev->fd, &size, 4, offset) != 4 ||
+        pwrite(vdev->fd, &orig, 4, offset) != 4) {
+        error_report("%s(%04x:%02x:%02x.%x) failed: %m",
+                     __func__, vdev->host.domain, vdev->host.bus,
+                     vdev->host.slot, vdev->host.function);
+        return;
+    }
+
+    size = ~(size & PCI_ROM_ADDRESS_MASK) + 1;
+
+    if (!size) {
+        return;
+    }
+
+    DPRINTF("%04x:%02x:%02x.%x ROM size 0x%x\n", vdev->host.domain,
+            vdev->host.bus, vdev->host.slot, vdev->host.function, size);
+
+    snprintf(name, sizeof(name), "vfio[%04x:%02x:%02x.%x].rom",
+             vdev->host.domain, vdev->host.bus, vdev->host.slot,
+             vdev->host.function);
+
+    memory_region_init_io(&vdev->pdev.rom, OBJECT(vdev),
+                          &vfio_rom_ops, vdev, name, size);
+
+    pci_register_bar(&vdev->pdev, PCI_ROM_SLOT,
+                     PCI_BASE_ADDRESS_SPACE_MEMORY, &vdev->pdev.rom);
+
+    vdev->pdev.has_rom = true;
+}
+
 static void vfio_vga_write(void *opaque, hwaddr addr,
                            uint64_t data, unsigned size)
 {
@@ -2638,51 +2758,6 @@ static int vfio_add_capabilities(VFIODevice *vdev)
     return vfio_add_std_cap(vdev, pdev->config[PCI_CAPABILITY_LIST]);
 }
 
-static int vfio_load_rom(VFIODevice *vdev)
-{
-    uint64_t size = vdev->rom_size;
-    char name[32];
-    off_t off = 0, voff = vdev->rom_offset;
-    ssize_t bytes;
-    void *ptr;
-
-    /* If loading ROM from file, pci handles it */
-    if (vdev->pdev.romfile || !vdev->pdev.rom_bar || !size) {
-        return 0;
-    }
-
-    DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain,
-            vdev->host.bus, vdev->host.slot, vdev->host.function);
-
-    snprintf(name, sizeof(name), "vfio[%04x:%02x:%02x.%x].rom",
-             vdev->host.domain, vdev->host.bus, vdev->host.slot,
-             vdev->host.function);
-    memory_region_init_ram(&vdev->pdev.rom, OBJECT(vdev), name, size);
-    ptr = memory_region_get_ram_ptr(&vdev->pdev.rom);
-    memset(ptr, 0xff, size);
-
-    while (size) {
-        bytes = pread(vdev->fd, ptr + off, size, voff + off);
-        if (bytes == 0) {
-            break; /* expect that we could get back less than the ROM BAR */
-        } else if (bytes > 0) {
-            off += bytes;
-            size -= bytes;
-        } else {
-            if (errno == EINTR || errno == EAGAIN) {
-                continue;
-            }
-            error_report("vfio: Error reading device ROM: %m");
-            memory_region_destroy(&vdev->pdev.rom);
-            return -errno;
-        }
-    }
-
-    pci_register_bar(&vdev->pdev, PCI_ROM_SLOT, 0, &vdev->pdev.rom);
-    vdev->pdev.has_rom = true;
-    return 0;
-}
-
 static int vfio_connect_container(VFIOGroup *group)
 {
     VFIOContainer *container;
@@ -2916,22 +2991,6 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev)
         QLIST_INIT(&vdev->bars[i].quirks);
     }
 
-    reg_info.index = VFIO_PCI_ROM_REGION_INDEX;
-
-    ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, &reg_info);
-    if (ret) {
-        error_report("vfio: Error getting ROM info: %m");
-        goto error;
-    }
-
-    DPRINTF("Device %s ROM:\n", name);
-    DPRINTF("  size: 0x%lx, offset: 0x%lx, flags: 0x%lx\n",
-            (unsigned long)reg_info.size, (unsigned long)reg_info.offset,
-            (unsigned long)reg_info.flags);
-
-    vdev->rom_size = reg_info.size;
-    vdev->rom_offset = reg_info.offset;
-
     reg_info.index = VFIO_PCI_CONFIG_REGION_INDEX;
 
     ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, &reg_info);
@@ -3229,7 +3288,7 @@ static int vfio_initfn(PCIDevice *pdev)
     memset(&vdev->pdev.config[PCI_BASE_ADDRESS_0], 0, 24);
     memset(&vdev->pdev.config[PCI_ROM_ADDRESS], 0, 4);
 
-    vfio_load_rom(vdev);
+    vfio_pci_size_rom(vdev);
 
     ret = vfio_early_setup_msix(vdev);
     if (ret) {
@@ -3294,6 +3353,7 @@ static void vfio_exitfn(PCIDevice *pdev)
     vfio_teardown_msi(vdev);
     vfio_unmap_bars(vdev);
     g_free(vdev->emulated_config_bits);
+    g_free(vdev->rom);
     vfio_put_device(vdev);
     vfio_put_group(group);
 }
commit befe5176ef7a0004ba23517c97c804e292273635
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Wed Oct 2 12:52:38 2013 -0600

    vfio-pci: Test device reset capabilities
    
    Not all resets are created equal.  PM reset is not very reliable,
    especially for GPUs, so we might want to opt for a bus reset if a
    standard reset will only do a D3hot->D0 transition.  We can also
    use this to tell if the standard reset will do a bus reset (if
    neither has_pm_reset or has_flr is probed, but the device still
    supports reset).
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index 75a53e2..ede026d 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -185,6 +185,8 @@ typedef struct VFIODevice {
     bool reset_works;
     bool has_vga;
     bool pci_aer;
+    bool has_flr;
+    bool has_pm_reset;
 } VFIODevice;
 
 typedef struct VFIOGroup {
@@ -2513,6 +2515,42 @@ static int vfio_setup_pcie_cap(VFIODevice *vdev, int pos, uint8_t size)
     return pos;
 }
 
+static void vfio_check_pcie_flr(VFIODevice *vdev, uint8_t pos)
+{
+    uint32_t cap = pci_get_long(vdev->pdev.config + pos + PCI_EXP_DEVCAP);
+
+    if (cap & PCI_EXP_DEVCAP_FLR) {
+        DPRINTF("%04x:%02x:%02x.%x Supports FLR via PCIe cap\n",
+                vdev->host.domain, vdev->host.bus, vdev->host.slot,
+                vdev->host.function);
+        vdev->has_flr = true;
+    }
+}
+
+static void vfio_check_pm_reset(VFIODevice *vdev, uint8_t pos)
+{
+    uint16_t csr = pci_get_word(vdev->pdev.config + pos + PCI_PM_CTRL);
+
+    if (!(csr & PCI_PM_CTRL_NO_SOFT_RESET)) {
+        DPRINTF("%04x:%02x:%02x.%x Supports PM reset\n",
+                vdev->host.domain, vdev->host.bus, vdev->host.slot,
+                vdev->host.function);
+        vdev->has_pm_reset = true;
+    }
+}
+
+static void vfio_check_af_flr(VFIODevice *vdev, uint8_t pos)
+{
+    uint8_t cap = pci_get_byte(vdev->pdev.config + pos + PCI_AF_CAP);
+
+    if ((cap & PCI_AF_CAP_TP) && (cap & PCI_AF_CAP_FLR)) {
+        DPRINTF("%04x:%02x:%02x.%x Supports FLR via AF cap\n",
+                vdev->host.domain, vdev->host.bus, vdev->host.slot,
+                vdev->host.function);
+        vdev->has_flr = true;
+    }
+}
+
 static int vfio_add_std_cap(VFIODevice *vdev, uint8_t pos)
 {
     PCIDevice *pdev = &vdev->pdev;
@@ -2557,13 +2595,21 @@ static int vfio_add_std_cap(VFIODevice *vdev, uint8_t pos)
         ret = vfio_setup_msi(vdev, pos);
         break;
     case PCI_CAP_ID_EXP:
+        vfio_check_pcie_flr(vdev, pos);
         ret = vfio_setup_pcie_cap(vdev, pos, size);
         break;
     case PCI_CAP_ID_MSIX:
         ret = vfio_setup_msix(vdev, pos);
         break;
     case PCI_CAP_ID_PM:
+        vfio_check_pm_reset(vdev, pos);
         vdev->pm_cap = pos;
+        ret = pci_add_capability(pdev, cap_id, pos, size);
+        break;
+    case PCI_CAP_ID_AF:
+        vfio_check_af_flr(vdev, pos);
+        ret = pci_add_capability(pdev, cap_id, pos, size);
+        break;
     default:
         ret = pci_add_capability(pdev, cap_id, pos, size);
         break;
commit c7679d450ee021eb0826be65e4e018884443643a
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Wed Oct 2 12:52:38 2013 -0600

    vfio-pci: Add support for MSI affinity
    
    When MSI is accelerated through KVM the vectors are only programmed
    when the guest first enables MSI support.  Subsequent writes to the
    vector address or data fields are ignored.  Unfortunately that means
    we're ignore updates done to adjust SMP affinity of the vectors.
    MSI SMP affinity already works in non-KVM mode because the address
    and data fields are read from their backing store on each interrupt.
    
    This patch stores the MSIMessage programmed into KVM so that we can
    determine when changes are made and update the routes.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index a1c08fb..75a53e2 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -119,6 +119,7 @@ typedef struct VFIOINTx {
 typedef struct VFIOMSIVector {
     EventNotifier interrupt; /* eventfd triggered on interrupt */
     struct VFIODevice *vdev; /* back pointer to device */
+    MSIMessage msg; /* cache the MSI message so we know when it changes */
     int virq; /* KVM irqchip route for QEMU bypass */
     bool use;
 } VFIOMSIVector;
@@ -795,7 +796,6 @@ retry:
     vdev->msi_vectors = g_malloc0(vdev->nr_vectors * sizeof(VFIOMSIVector));
 
     for (i = 0; i < vdev->nr_vectors; i++) {
-        MSIMessage msg;
         VFIOMSIVector *vector = &vdev->msi_vectors[i];
 
         vector->vdev = vdev;
@@ -805,13 +805,13 @@ retry:
             error_report("vfio: Error: event_notifier_init failed");
         }
 
-        msg = msi_get_message(&vdev->pdev, i);
+        vector->msg = msi_get_message(&vdev->pdev, i);
 
         /*
          * Attempt to enable route through KVM irqchip,
          * default to userspace handling if unavailable.
          */
-        vector->virq = kvm_irqchip_add_msi_route(kvm_state, msg);
+        vector->virq = kvm_irqchip_add_msi_route(kvm_state, vector->msg);
         if (vector->virq < 0 ||
             kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interrupt,
                                            NULL, vector->virq) < 0) {
@@ -917,6 +917,33 @@ static void vfio_disable_msi(VFIODevice *vdev)
             vdev->host.bus, vdev->host.slot, vdev->host.function);
 }
 
+static void vfio_update_msi(VFIODevice *vdev)
+{
+    int i;
+
+    for (i = 0; i < vdev->nr_vectors; i++) {
+        VFIOMSIVector *vector = &vdev->msi_vectors[i];
+        MSIMessage msg;
+
+        if (!vector->use || vector->virq < 0) {
+            continue;
+        }
+
+        msg = msi_get_message(&vdev->pdev, i);
+
+        if (msg.address != vector->msg.address ||
+            msg.data != vector->msg.data) {
+
+            DPRINTF("%s(%04x:%02x:%02x.%x) MSI vector %d changed\n",
+                    __func__, vdev->host.domain, vdev->host.bus,
+                    vdev->host.slot, vdev->host.function, i);
+
+            kvm_irqchip_update_msi_route(kvm_state, vector->virq, msg);
+            vector->msg = msg;
+        }
+    }
+}
+
 /*
  * IO Port/MMIO - Beware of the endians, VFIO is always little endian
  */
@@ -1834,10 +1861,16 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
 
         is_enabled = msi_enabled(pdev);
 
-        if (!was_enabled && is_enabled) {
-            vfio_enable_msi(vdev);
-        } else if (was_enabled && !is_enabled) {
-            vfio_disable_msi(vdev);
+        if (!was_enabled) {
+            if (is_enabled) {
+                vfio_enable_msi(vdev);
+            }
+        } else {
+            if (!is_enabled) {
+                vfio_disable_msi(vdev);
+            } else {
+                vfio_update_msi(vdev);
+            }
         }
     } else if (pdev->cap_present & QEMU_PCI_CAP_MSIX &&
         ranges_overlap(addr, len, pdev->msix_cap, MSIX_CAP_LENGTH)) {
commit 04fd1c789677fe121cb9546c652d088c994477fb
Author: Sebastian Ottlik <ottlik at fzi.de>
Date:   Wed Oct 2 12:23:16 2013 +0200

    util: call socket_set_fast_reuse instead of setting SO_REUSEADDR
    
    SO_REUSEADDR should be avoided on Windows but is desired on other operating
    systems. So instead of setting it we call socket_set_fast_reuse that will result
    in the appropriate behaviour on all operating systems.
    
    Signed-off-by: Sebastian Ottlik <ottlik at fzi.de>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 095716e..6b97dc1 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -155,7 +155,7 @@ int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp)
             continue;
         }
 
-        qemu_setsockopt(slisten, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+        socket_set_fast_reuse(slisten);
 #ifdef IPV6_V6ONLY
         if (e->ai_family == PF_INET6) {
             /* listen on both ipv4 and ipv6 */
@@ -274,7 +274,7 @@ static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
         error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED);
         return -1;
     }
-    qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+    socket_set_fast_reuse(sock);
     if (connect_state != NULL) {
         qemu_set_nonblock(sock);
     }
@@ -455,7 +455,7 @@ int inet_dgram_opts(QemuOpts *opts, Error **errp)
         error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED);
         goto err;
     }
-    qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+    socket_set_fast_reuse(sock);
 
     /* bind socket */
     if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) {
commit aad1239a7e15f42c0b8a802433582c48417a4541
Author: Sebastian Ottlik <ottlik at fzi.de>
Date:   Wed Oct 2 12:23:15 2013 +0200

    slirp: call socket_set_fast_reuse instead of setting SO_REUSEADDR
    
    SO_REUSEADDR should be avoided on Windows but is desired on other operating
    systems. So instead of setting it we call socket_set_fast_reuse that will result
    in the appropriate behaviour on all operating systems.
    
    Signed-off-by: Sebastian Ottlik <ottlik at fzi.de>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/slirp/misc.c b/slirp/misc.c
index c0d4899..6c1636f 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -212,8 +212,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
                     so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
                 } while (so->s < 0 && errno == EINTR);
                 closesocket(s);
-                opt = 1;
-                qemu_setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
+                socket_set_fast_reuse(so->s);
                 opt = 1;
                 qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
 		qemu_set_nonblock(so->s);
diff --git a/slirp/socket.c b/slirp/socket.c
index 25d60e7..37ac5cf 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -627,9 +627,7 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
 	addr.sin_port = hport;
 
 	if (((s = qemu_socket(AF_INET,SOCK_STREAM,0)) < 0) ||
-#ifndef _WIN32
-	    (qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)) < 0) ||
-#endif
+	    (socket_set_fast_reuse(s) < 0) ||
 	    (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
 	    (listen(s,1) < 0)) {
 		int tmperrno = errno; /* Don't clobber the real reason we failed */
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 043f28f..7571c5a 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -337,8 +337,7 @@ int tcp_fconnect(struct socket *so)
     struct sockaddr_in addr;
 
     qemu_set_nonblock(s);
-    opt = 1;
-    qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+    socket_set_fast_reuse(s);
     opt = 1;
     qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
 
@@ -426,8 +425,7 @@ void tcp_connect(struct socket *inso)
         return;
     }
     qemu_set_nonblock(s);
-    opt = 1;
-    qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
+    socket_set_fast_reuse(s);
     opt = 1;
     qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
     socket_set_nodelay(s);
diff --git a/slirp/udp.c b/slirp/udp.c
index b105f87..8cc6cb6 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -354,7 +354,7 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
 {
 	struct sockaddr_in addr;
 	struct socket *so;
-	socklen_t addrlen = sizeof(struct sockaddr_in), opt = 1;
+	socklen_t addrlen = sizeof(struct sockaddr_in);
 
 	so = socreate(slirp);
 	if (!so) {
@@ -372,7 +372,7 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
 		udp_detach(so);
 		return NULL;
 	}
-	qemu_setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
+	socket_set_fast_reuse(so->s);
 
 	getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
 	so->so_fport = addr.sin_port;
commit bcbe92fb080420551125994f3b15c139019da694
Author: Sebastian Ottlik <ottlik at fzi.de>
Date:   Wed Oct 2 12:23:14 2013 +0200

    net: call socket_set_fast_reuse instead of setting SO_REUSEADDR
    
    SO_REUSEADDR should be avoided on Windows but is desired on other operating
    systems. So instead of setting it we call socket_set_fast_reuse that will result
    in the appropriate behaviour on all operating systems.
    
    An exception to this rule are multicast sockets where it is sensible to have
    multiple sockets listen on the same ip and port and we should set SO_REUSEADDR
    on windows.
    
    Signed-off-by: Sebastian Ottlik <ottlik at fzi.de>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/net/socket.c b/net/socket.c
index e61309d..fb21e20 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -262,6 +262,11 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
         return -1;
     }
 
+    /* Allow multiple sockets to bind the same multicast ip and port by setting
+     * SO_REUSEADDR. This is the only situation where SO_REUSEADDR should be set
+     * on windows. Use socket_set_fast_reuse otherwise as it sets SO_REUSEADDR
+     * only on posix systems.
+     */
     val = 1;
     ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
     if (ret < 0) {
@@ -510,7 +515,7 @@ static int net_socket_listen_init(NetClientState *peer,
     NetClientState *nc;
     NetSocketState *s;
     struct sockaddr_in saddr;
-    int fd, val, ret;
+    int fd, ret;
 
     if (parse_host_port(&saddr, host_str) < 0)
         return -1;
@@ -522,9 +527,7 @@ static int net_socket_listen_init(NetClientState *peer,
     }
     qemu_set_nonblock(fd);
 
-    /* allow fast reuse */
-    val = 1;
-    qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
+    socket_set_fast_reuse(fd);
 
     ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
     if (ret < 0) {
@@ -645,7 +648,7 @@ static int net_socket_udp_init(NetClientState *peer,
                                  const char *lhost)
 {
     NetSocketState *s;
-    int fd, val, ret;
+    int fd, ret;
     struct sockaddr_in laddr, raddr;
 
     if (parse_host_port(&laddr, lhost) < 0) {
@@ -661,11 +664,9 @@ static int net_socket_udp_init(NetClientState *peer,
         perror("socket(PF_INET, SOCK_DGRAM)");
         return -1;
     }
-    val = 1;
-    ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
-                          &val, sizeof(val));
+
+    ret = socket_set_fast_reuse(fd);
     if (ret < 0) {
-        perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
         closesocket(fd);
         return -1;
     }
commit 6669ca13c39a8515cc634695698d3dea5f39be1c
Author: Sebastian Ottlik <ottlik at fzi.de>
Date:   Wed Oct 2 12:23:13 2013 +0200

    gdbstub: call socket_set_fast_reuse instead of setting SO_REUSEADDR
    
    SO_REUSEADDR should be avoided on Windows but is desired on other operating
    systems. So instead of setting it we call socket_set_fast_reuse that will result
    in the appropriate behaviour on all operating systems.
    
    Signed-off-by: Sebastian Ottlik <ottlik at fzi.de>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/gdbstub.c b/gdbstub.c
index 2b7f22b..0e5a3f5 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1553,7 +1553,7 @@ static void gdb_accept(void)
 static int gdbserver_open(int port)
 {
     struct sockaddr_in sockaddr;
-    int fd, val, ret;
+    int fd, ret;
 
     fd = socket(PF_INET, SOCK_STREAM, 0);
     if (fd < 0) {
@@ -1564,9 +1564,7 @@ static int gdbserver_open(int port)
     fcntl(fd, F_SETFD, FD_CLOEXEC);
 #endif
 
-    /* allow fast reuse */
-    val = 1;
-    qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
+    socket_set_fast_reuse(fd);
 
     sockaddr.sin_family = AF_INET;
     sockaddr.sin_port = htons(port);
commit 606600a176c981addcfedb0698f13fd0f2f4446e
Author: Sebastian Ottlik <ottlik at fzi.de>
Date:   Wed Oct 2 12:23:12 2013 +0200

    util: add socket_set_fast_reuse function which will replace setting SO_REUSEADDR
    
    If a socket is closed it remains in TIME_WAIT state for some time. On operating
    systems using BSD sockets the endpoint of the socket may not be reused while in
    this state unless SO_REUSEADDR was set on the socket. On windows on the other
    hand the default behaviour is to allow reuse (i.e. identical to SO_REUSEADDR on
    other operating systems) and setting SO_REUSEADDR on a socket allows it to be
    bound to a endpoint even if the endpoint is already used by another socket
    independently of the other sockets state. This can even result in undefined
    behaviour.
    
    Many sockets used by QEMU should not block the use of their endpoint after being
    closed while they are still in TIME_WAIT state. Currently QEMU sets SO_REUSEADDR
    for such sockets, which can lead to problems on Windows. This patch introduces
    the function socket_set_fast_reuse that should be used instead of setting
    SO_REUSEADDR when fast socket reuse is desired and behaves correctly on all
    operating systems.
    
    As a failure of this function can only be caused by bad QEMU internal errors, an
    assertion handles these situations. The return value is still passed on, to
    minimize changes in client code and prevent unused variable warnings if NDEBUG
    is defined.
    
    Signed-off-by: Sebastian Ottlik <ottlik at fzi.de>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index c5174d7..45588d7 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -39,6 +39,7 @@ int socket_set_cork(int fd, int v);
 int socket_set_nodelay(int fd);
 void qemu_set_block(int fd);
 void qemu_set_nonblock(int fd);
+int socket_set_fast_reuse(int fd);
 int send_all(int fd, const void *buf, int len1);
 int recv_all(int fd, void *buf, int len1, bool single_read);
 
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 253bc3d..e00a44c 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -157,6 +157,18 @@ void qemu_set_nonblock(int fd)
     fcntl(fd, F_SETFL, f | O_NONBLOCK);
 }
 
+int socket_set_fast_reuse(int fd)
+{
+    int val = 1, ret;
+
+    ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+                     (const char *)&val, sizeof(val));
+
+    assert(ret == 0);
+
+    return ret;
+}
+
 void qemu_set_cloexec(int fd)
 {
     int f;
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index 983b7a2..776ccfa 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -124,6 +124,16 @@ void qemu_set_nonblock(int fd)
     qemu_fd_register(fd);
 }
 
+int socket_set_fast_reuse(int fd)
+{
+    /* Enabling the reuse of an endpoint that was used by a socket still in
+     * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows
+     * fast reuse is the default and SO_REUSEADDR does strange things. So we
+     * don't have to do anything here. More info can be found at:
+     * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */
+    return 0;
+}
+
 int inet_aton(const char *cp, struct in_addr *ia)
 {
     uint32_t addr = inet_addr(cp);
commit 0e19885e736938c3f6bd8c139eca00728bb24384
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Wed Oct 2 12:09:12 2013 -0500

    Update MAINTAINERS
    
    All of Paul's emails are bouncing and he hasn't been active for
    some time.
    
    Signed-off-by: Anthony Liguori <anthony at codemonkey.ws>

diff --git a/MAINTAINERS b/MAINTAINERS
index 5c3c70c..ab8166a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -51,7 +51,6 @@ Descriptions of section entries:
 General Project Administration
 ------------------------------
 M: Anthony Liguori <anthony at codemonkey.ws>
-M: Paul Brook <paul at codesourcery.com>
 
 Guest CPU cores (TCG):
 ----------------------
@@ -62,7 +61,6 @@ F: target-alpha/
 F: hw/alpha/
 
 ARM
-M: Paul Brook <paul at codesourcery.com>
 M: Peter Maydell <peter.maydell at linaro.org>
 S: Maintained
 F: target-arm/
@@ -83,8 +81,7 @@ F: hw/lm32/
 F: hw/char/lm32_*
 
 M68K
-M: Paul Brook <paul at codesourcery.com>
-S: Odd Fixes
+S: Orphan
 F: target-m68k/
 F: hw/m68k/
 
@@ -248,7 +245,6 @@ F: hw/*/imx*
 F: hw/arm/kzm.c
 
 Integrator CP
-M: Paul Brook <paul at codesourcery.com>
 M: Peter Maydell <peter.maydell at linaro.org>
 S: Maintained
 F: hw/arm/integratorcp.c
@@ -274,7 +270,6 @@ S: Maintained
 F: hw/arm/palm.c
 
 Real View
-M: Paul Brook <paul at codesourcery.com>
 M: Peter Maydell <peter.maydell at linaro.org>
 S: Maintained
 F: hw/arm/realview*
@@ -285,13 +280,11 @@ S: Maintained
 F: hw/arm/spitz.c
 
 Stellaris
-M: Paul Brook <paul at codesourcery.com>
 M: Peter Maydell <peter.maydell at linaro.org>
 S: Maintained
 F: hw/*/stellaris*
 
 Versatile PB
-M: Paul Brook <paul at codesourcery.com>
 M: Peter Maydell <peter.maydell at linaro.org>
 S: Maintained
 F: hw/*/versatile*
@@ -327,18 +320,15 @@ F: hw/lm32/milkymist.c
 M68K Machines
 -------------
 an5206
-M: Paul Brook <paul at codesourcery.com>
-S: Maintained
+S: Orphan
 F: hw/m68k/an5206.c
 
 dummy_m68k
-M: Paul Brook <paul at codesourcery.com>
-S: Maintained
+S: Orphan
 F: hw/m68k/dummy_m68k.c
 
 mcf5208
-M: Paul Brook <paul at codesourcery.com>
-S: Maintained
+S: Orphan
 F: hw/m68k/mcf5208.c
 
 MicroBlaze Machines
@@ -567,8 +557,7 @@ F: hw/scsi/*
 T: git git://github.com/bonzini/qemu.git scsi-next
 
 LSI53C895A
-M: Paul Brook <paul at codesourcery.com>
-S: Odd Fixes
+S: Orphan
 F: hw/scsi/lsi53c895a.c
 
 SSI
commit f8e6a11aecc96e9d8a84f17d7c07019471714e20
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Tue Sep 10 17:48:59 2013 -0300

    target-i386: Set model=6 on qemu64 & qemu32 CPU models
    
    There's no Intel CPU with family=6,model=2, and Linux and Windows guests
    disable SEP when seeing that combination due to Pentium Pro erratum #82.
    
    In addition to just having SEP ignored by guests, Skype (and maybe other
    applications) runs sysenter directly without passing through ntdll on
    Windows, and crashes because Windows ignored the SEP CPUID bit.
    
    So, having model > 2 is a better default on qemu64 and qemu32 for two
    reasons: making SEP really available for guests, and avoiding crashing
    applications that work on bare metal.
    
    model=3 would fix the problem, but it causes CPU enumeration problems
    for Windows guests[1]. So let's set model=6, that matches "Athlon
    (PM core)" on AMD and "P2 with on-die L2 cache" on Intel and it allows
    Windows to use all CPUs as well as fixing sysenter.
    
    [1] https://bugzilla.redhat.com/show_bug.cgi?id=508623
    
    Cc: Andrea Arcangeli <aarcange at redhat.com>
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 9b2ddc4..6083839 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -230,6 +230,14 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
             .driver   = "e1000",\
             .property = "mitigation",\
             .value    = "off",\
+        },{\
+            .driver   = "qemu64-" TYPE_X86_CPU,\
+            .property = "model",\
+            .value    = stringify(2),\
+        },{\
+            .driver   = "qemu32-" TYPE_X86_CPU,\
+            .property = "model",\
+            .value    = stringify(3),\
         }
 
 #define PC_COMPAT_1_5 \
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index b682802..c1c994f 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -545,7 +545,7 @@ static x86_def_t builtin_x86_defs[] = {
         .level = 4,
         .vendor = CPUID_VENDOR_AMD,
         .family = 6,
-        .model = 2,
+        .model = 6,
         .stepping = 3,
         .features[FEAT_1_EDX] =
             PPRO_FEATURES |
@@ -648,7 +648,7 @@ static x86_def_t builtin_x86_defs[] = {
         .level = 4,
         .vendor = CPUID_VENDOR_INTEL,
         .family = 6,
-        .model = 3,
+        .model = 6,
         .stepping = 3,
         .features[FEAT_1_EDX] =
             PPRO_FEATURES,
commit fda74f826baec78d685e5a87fd8a95bfb7bb2243
Author: Max Reitz <mreitz at redhat.com>
Date:   Mon Sep 30 17:57:21 2013 +0200

    qcow2: Switch L1 table in a single sequence
    
    Switching the L1 table in memory should be an atomic operation, as far
    as possible. Calling qcow2_free_clusters on the old L1 table on disk is
    not a good idea when the old L1 table is no longer valid and the address
    to the new one hasn't yet been written into the corresponding
    BDRVQcowState field. To be more specific, this can lead to segfaults due
    to qcow2_check_metadata_overlap trying to access the L1 table during the
    free operation.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 39323ac..2ed45f0 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -35,6 +35,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
     BDRVQcowState *s = bs->opaque;
     int new_l1_size2, ret, i;
     uint64_t *new_l1_table;
+    int64_t old_l1_table_offset, old_l1_size;
     int64_t new_l1_table_offset, new_l1_size;
     uint8_t data[12];
 
@@ -106,11 +107,13 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
         goto fail;
     }
     g_free(s->l1_table);
-    qcow2_free_clusters(bs, s->l1_table_offset, s->l1_size * sizeof(uint64_t),
-                        QCOW2_DISCARD_OTHER);
+    old_l1_table_offset = s->l1_table_offset;
     s->l1_table_offset = new_l1_table_offset;
     s->l1_table = new_l1_table;
+    old_l1_size = s->l1_size;
     s->l1_size = new_l1_size;
+    qcow2_free_clusters(bs, old_l1_table_offset, old_l1_size * sizeof(uint64_t),
+                        QCOW2_DISCARD_OTHER);
     return 0;
  fail:
     g_free(new_l1_table);
commit 5641bf405608cc89578fafed8ec689a19046285a
Author: Jeff Cody <jcody at redhat.com>
Date:   Tue Oct 1 11:59:20 2013 -0400

    block: vhdx - add migration blocker
    
    This blocks migration for VHDX image files, until the
    functionality can be supported.
    
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/vhdx.c b/block/vhdx.c
index b8aa49c..6cb0412 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -20,6 +20,7 @@
 #include "qemu/module.h"
 #include "qemu/crc32c.h"
 #include "block/vhdx.h"
+#include "migration/migration.h"
 
 
 /* Several metadata and region table data entries are identified by
@@ -159,6 +160,7 @@ typedef struct BDRVVHDXState {
     VHDXParentLocatorHeader parent_header;
     VHDXParentLocatorEntry *parent_entries;
 
+    Error *migration_blocker;
 } BDRVVHDXState;
 
 uint32_t vhdx_checksum_calc(uint32_t crc, uint8_t *buf, size_t size,
@@ -806,6 +808,12 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
 
     /* TODO: differencing files, write */
 
+    /* Disable migration when VHDX images are used */
+    error_set(&s->migration_blocker,
+            QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+            "vhdx", bs->device_name, "live migration");
+    migrate_add_blocker(s->migration_blocker);
+
     return 0;
 fail:
     qemu_vfree(s->headers[0]);
@@ -952,6 +960,8 @@ static void vhdx_close(BlockDriverState *bs)
     qemu_vfree(s->headers[1]);
     qemu_vfree(s->bat);
     qemu_vfree(s->parent_entries);
+    migrate_del_blocker(s->migration_blocker);
+    error_free(s->migration_blocker);
 }
 
 static BlockDriver bdrv_vhdx = {
commit 2fa9aa59cfc472c16309c4e84547aa873423b2f5
Author: Dunrong Huang <riegamaths at gmail.com>
Date:   Tue Sep 24 18:14:01 2013 +0800

    block: use correct filename for error report
    
    The content filename point to will be erased by qemu_opts_absorb_qdict()
    in raw_open_common() in drv->bdrv_file_open()
    
    So it's better to use bs->filename.
    
    Signed-off-by: Dunrong Huang <riegamaths at gmail.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block.c b/block.c
index 93e113a..e2d9936 100644
--- a/block.c
+++ b/block.c
@@ -808,8 +808,8 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
     if (ret < 0) {
         if (error_is_set(&local_err)) {
             error_propagate(errp, local_err);
-        } else if (filename) {
-            error_setg_errno(errp, -ret, "Could not open '%s'", filename);
+        } else if (bs->filename[0]) {
+            error_setg_errno(errp, -ret, "Could not open '%s'", bs->filename);
         } else {
             error_setg_errno(errp, -ret, "Could not open image");
         }
commit db0749012b3d1cf655bddb3cc79052a0fd4dc97b
Author: Max Reitz <mreitz at redhat.com>
Date:   Mon Sep 30 09:21:07 2013 +0200

    qcow2: CHECK_OFLAG_COPIED is obsolete
    
    CHECK_OFLAG_COPIED as a parameter to check_refcounts_l1 and
    check_refcounts_l2 is obselete now, since the OFLAG_COPIED consistency
    check is actually no longer performed by these functions (but by
    check_oflag_copied).
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Reviewed-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 364eeba..2d67885 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1034,7 +1034,6 @@ static void inc_refcounts(BlockDriverState *bs,
 
 /* Flags for check_refcounts_l1() and check_refcounts_l2() */
 enum {
-    CHECK_OFLAG_COPIED = 0x1,   /* check QCOW_OFLAG_COPIED matches refcount */
     CHECK_FRAG_INFO = 0x2,      /* update BlockFragInfo counters */
 };
 
@@ -1481,8 +1480,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
 
     /* current L1 table */
     ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters,
-                             s->l1_table_offset, s->l1_size,
-                             CHECK_OFLAG_COPIED | CHECK_FRAG_INFO);
+                             s->l1_table_offset, s->l1_size, CHECK_FRAG_INFO);
     if (ret < 0) {
         goto fail;
     }
commit 1e242b5544a48bc43eca9c637dc91ec06bcf3a31
Author: Max Reitz <mreitz at redhat.com>
Date:   Mon Sep 30 08:59:28 2013 +0200

    qcow2: Correct endianness in overlap check
    
    If an inactive L1 table is loaded from disk, its entries are in big
    endian and have to be converted to host byte order before using them.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Reviewed-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index d2b7064..364eeba 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1733,8 +1733,8 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int chk, int64_t offset,
             }
 
             for (j = 0; j < l1_sz; j++) {
-                if ((l1[j] & L1E_OFFSET_MASK) &&
-                    overlaps_with(l1[j] & L1E_OFFSET_MASK, s->cluster_size)) {
+                uint64_t l2_ofs = be64_to_cpu(l1[j]) & L1E_OFFSET_MASK;
+                if (l2_ofs && overlaps_with(l2_ofs, s->cluster_size)) {
                     g_free(l1);
                     return QCOW2_OL_INACTIVE_L2;
                 }
commit ee06e23051251c00778edf54fb930198df0e873a
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 30 09:48:56 2013 -0700

    tcg-arm: Move the tlb addend load earlier
    
    There are free scheduling slots between the sequence of
    comparison instructions.  This requires changing the
    register in use to avoid conflict with those compares.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 0b09672..622cc49 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1183,8 +1183,8 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
      *   add    r2, r2, r0, lsl #CPU_TLB_ENTRY_BITS               (3)
      *   ldr    r0, [r2, #cmp]                                    (4)
      *   tst    addr_reg, #s_mask
-     *   cmpeq  r0, tmp, lsl #TARGET_PAGE_BITS                    (5)
-     *   ldr    r1, [r2, #add]
+     *   ldr    r1, [r2, #add]                                    (5)
+     *   cmpeq  r0, tmp, lsl #TARGET_PAGE_BITS
      */
     tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP,
                     0, addrlo, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
@@ -1221,6 +1221,9 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
                         0, addrlo, (1 << s_bits) - 1);
     }
 
+    /* Load the tlb addend.  */
+    tcg_out_ld32_12(s, COND_AL, TCG_REG_R2, TCG_REG_R2, add_off);
+
     tcg_out_dat_reg(s, (s_bits ? COND_EQ : COND_AL), ARITH_CMP, 0,
                     TCG_REG_R0, TCG_REG_TMP, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
 
@@ -1229,9 +1232,7 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
                         TCG_REG_R1, addrhi, SHIFT_IMM_LSL(0));
     }
 
-    /* Load the tlb addend.  */
-    tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2, add_off);
-    return TCG_REG_R1;
+    return TCG_REG_R2;
 }
 
 /* Record the context of a call to the out of line helper code for the slow
commit 66c2056fb83b873df0a3a4bda3a679bf53d082a2
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 30 09:12:32 2013 -0700

    tcg-arm: Remove restriction on qemu_ld output register
    
    The main intent of the patch is to allow the tlb addend register
    to be changed, without tying that change to the constraint.  But
    the most common side-effect seems to be to enable usage of ldrd
    with the r0,r1 pair.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 86e02c4..0b09672 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -183,15 +183,6 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14);
 #endif
         break;
-    case 'L':
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
-#ifdef CONFIG_SOFTMMU
-        /* r1 is still needed to load data_reg or data_reg2,
-           so don't use it. */
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
-#endif
-        break;
 
     /* qemu_st address & data_reg */
     case 's':
@@ -1314,8 +1305,17 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
         tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
         break;
     case 3:
-        tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
-        tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1);
+        if (data_reg != TCG_REG_R1) {
+            tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
+            tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1);
+        } else if (data_reg2 != TCG_REG_R0) {
+            tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1);
+            tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
+        } else {
+            tcg_out_mov_reg(s, COND_AL, TCG_REG_TMP, TCG_REG_R0);
+            tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1);
+            tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_TMP);
+        }
         break;
     }
 
@@ -1420,17 +1420,27 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
         }
         break;
     case 3:
-        if (bswap) {
-            tcg_out_ld32_rwb(s, COND_AL, data_reg2, addend, addr_reg);
-            tcg_out_ld32_12(s, COND_AL, data_reg, addend, 4);
-            tcg_out_bswap32(s, COND_AL, data_reg2, data_reg2);
-            tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
-        } else if (use_armv6_instructions
-                   && (data_reg & 1) == 0 && data_reg2 == data_reg + 1) {
-            tcg_out_ldrd_r(s, COND_AL, data_reg, addr_reg, addend);
-        } else {
-            tcg_out_ld32_rwb(s, COND_AL, data_reg, addend, addr_reg);
-            tcg_out_ld32_12(s, COND_AL, data_reg2, addend, 4);
+        {
+            /* Be careful not to modify data_reg and data_reg2
+               for the slow path below.  */
+            TCGReg dl = (bswap ? data_reg2 : data_reg);
+            TCGReg dh = (bswap ? data_reg : data_reg2);
+
+            if (use_armv6_instructions && (dl & 1) == 0 && dh == dl + 1) {
+                tcg_out_ldrd_r(s, COND_AL, dl, addr_reg, addend);
+            } else if (dl != addend) {
+                tcg_out_ld32_rwb(s, COND_AL, dl, addend, addr_reg);
+                tcg_out_ld32_12(s, COND_AL, dh, addend, 4);
+            } else {
+                tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_TMP,
+                                addend, addr_reg, SHIFT_IMM_LSL(0));
+                tcg_out_ld32_12(s, COND_AL, dl, TCG_REG_TMP, 0);
+                tcg_out_ld32_12(s, COND_AL, dh, TCG_REG_TMP, 4);
+            }
+            if (bswap) {
+                tcg_out_bswap32(s, COND_AL, dh, dh);
+                tcg_out_bswap32(s, COND_AL, dl, dl);
+            }
         }
         break;
     }
@@ -2025,7 +2035,7 @@ static const TCGTargetOpDef arm_op_defs[] = {
     { INDEX_op_qemu_ld16u, { "r", "l" } },
     { INDEX_op_qemu_ld16s, { "r", "l" } },
     { INDEX_op_qemu_ld32, { "r", "l" } },
-    { INDEX_op_qemu_ld64, { "L", "L", "l" } },
+    { INDEX_op_qemu_ld64, { "r", "r", "l" } },
 
     { INDEX_op_qemu_st8, { "s", "s" } },
     { INDEX_op_qemu_st16, { "s", "s" } },
@@ -2037,7 +2047,7 @@ static const TCGTargetOpDef arm_op_defs[] = {
     { INDEX_op_qemu_ld16u, { "r", "l", "l" } },
     { INDEX_op_qemu_ld16s, { "r", "l", "l" } },
     { INDEX_op_qemu_ld32, { "r", "l", "l" } },
-    { INDEX_op_qemu_ld64, { "L", "L", "l", "l" } },
+    { INDEX_op_qemu_ld64, { "r", "r", "l", "l" } },
 
     { INDEX_op_qemu_st8, { "s", "s", "s" } },
     { INDEX_op_qemu_st16, { "s", "s", "s" } },
commit d3e440bef2783b7b2ebc210a0717c36351506b8c
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 30 08:45:53 2013 -0700

    tcg-arm: Return register containing tlb addend
    
    Preparatory to rescheduling the tlb load, and changing said register.
    Continues to use R1 for now.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index b9ec4f6..86e02c4 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1172,11 +1172,11 @@ QEMU_BUILD_BUG_ON(CPU_TLB_BITS > 8);
 QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1])
                   > 0xffff);
 
-/* Load and compare a TLB entry, leaving the flags set.  Leaves R1 containing
-   the addend of the tlb entry.  Clobbers R0, R2, TMP.  */
+/* Load and compare a TLB entry, leaving the flags set.  Returns the register
+   containing the addend of the tlb entry.  Clobbers R0, R1, R2, TMP.  */
 
-static void tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
-                             int s_bits, int mem_index, bool is_load)
+static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
+                               int s_bits, int mem_index, bool is_load)
 {
     TCGReg base = TCG_AREG0;
     int cmp_off =
@@ -1240,6 +1240,7 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
 
     /* Load the tlb addend.  */
     tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2, add_off);
+    return TCG_REG_R1;
 }
 
 /* Record the context of a call to the out of line helper code for the slow
@@ -1366,7 +1367,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     bool bswap;
 #ifdef CONFIG_SOFTMMU
     int mem_index, s_bits;
-    TCGReg addr_reg2;
+    TCGReg addr_reg2, addend;
     uint8_t *label_ptr;
 #endif
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -1383,7 +1384,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     mem_index = *args;
     s_bits = opc & 3;
 
-    tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits, mem_index, 1);
+    addend = tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits, mem_index, 1);
 
     /* This a conditional BL only to load a pointer within this opcode into LR
        for the slow path.  We will not be using the value for a tail call.  */
@@ -1392,44 +1393,44 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 
     switch (opc) {
     case 0:
-        tcg_out_ld8_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
+        tcg_out_ld8_r(s, COND_AL, data_reg, addr_reg, addend);
         break;
     case 0 | 4:
-        tcg_out_ld8s_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
+        tcg_out_ld8s_r(s, COND_AL, data_reg, addr_reg, addend);
         break;
     case 1:
-        tcg_out_ld16u_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
+        tcg_out_ld16u_r(s, COND_AL, data_reg, addr_reg, addend);
         if (bswap) {
             tcg_out_bswap16(s, COND_AL, data_reg, data_reg);
         }
         break;
     case 1 | 4:
         if (bswap) {
-            tcg_out_ld16u_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
+            tcg_out_ld16u_r(s, COND_AL, data_reg, addr_reg, addend);
             tcg_out_bswap16s(s, COND_AL, data_reg, data_reg);
         } else {
-            tcg_out_ld16s_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
+            tcg_out_ld16s_r(s, COND_AL, data_reg, addr_reg, addend);
         }
         break;
     case 2:
     default:
-        tcg_out_ld32_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
+        tcg_out_ld32_r(s, COND_AL, data_reg, addr_reg, addend);
         if (bswap) {
             tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
         }
         break;
     case 3:
         if (bswap) {
-            tcg_out_ld32_rwb(s, COND_AL, data_reg2, TCG_REG_R1, addr_reg);
-            tcg_out_ld32_12(s, COND_AL, data_reg, TCG_REG_R1, 4);
+            tcg_out_ld32_rwb(s, COND_AL, data_reg2, addend, addr_reg);
+            tcg_out_ld32_12(s, COND_AL, data_reg, addend, 4);
             tcg_out_bswap32(s, COND_AL, data_reg2, data_reg2);
             tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
         } else if (use_armv6_instructions
                    && (data_reg & 1) == 0 && data_reg2 == data_reg + 1) {
-            tcg_out_ldrd_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
+            tcg_out_ldrd_r(s, COND_AL, data_reg, addr_reg, addend);
         } else {
-            tcg_out_ld32_rwb(s, COND_AL, data_reg, TCG_REG_R1, addr_reg);
-            tcg_out_ld32_12(s, COND_AL, data_reg2, TCG_REG_R1, 4);
+            tcg_out_ld32_rwb(s, COND_AL, data_reg, addend, addr_reg);
+            tcg_out_ld32_12(s, COND_AL, data_reg2, addend, 4);
         }
         break;
     }
@@ -1508,7 +1509,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
     bool bswap;
 #ifdef CONFIG_SOFTMMU
     int mem_index, s_bits;
-    TCGReg addr_reg2;
+    TCGReg addr_reg2, addend;
     uint8_t *label_ptr;
 #endif
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -1525,41 +1526,41 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
     mem_index = *args;
     s_bits = opc & 3;
 
-    tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits, mem_index, 0);
+    addend = tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits, mem_index, 0);
 
     switch (opc) {
     case 0:
-        tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+        tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, addend);
         break;
     case 1:
         if (bswap) {
             tcg_out_bswap16st(s, COND_EQ, TCG_REG_R0, data_reg);
-            tcg_out_st16_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
+            tcg_out_st16_r(s, COND_EQ, TCG_REG_R0, addr_reg, addend);
         } else {
-            tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+            tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, addend);
         }
         break;
     case 2:
     default:
         if (bswap) {
             tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
-            tcg_out_st32_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
+            tcg_out_st32_r(s, COND_EQ, TCG_REG_R0, addr_reg, addend);
         } else {
-            tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+            tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, addend);
         }
         break;
     case 3:
         if (bswap) {
             tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg2);
-            tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, addr_reg);
+            tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, addend, addr_reg);
             tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
-            tcg_out_st32_12(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, 4);
+            tcg_out_st32_12(s, COND_EQ, TCG_REG_R0, addend, 4);
         } else if (use_armv6_instructions
                    && (data_reg & 1) == 0 && data_reg2 == data_reg + 1) {
-            tcg_out_strd_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+            tcg_out_strd_r(s, COND_EQ, data_reg, addr_reg, addend);
         } else {
-            tcg_out_st32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
-            tcg_out_st32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
+            tcg_out_st32_rwb(s, COND_EQ, data_reg, addend, addr_reg);
+            tcg_out_st32_12(s, COND_EQ, data_reg2, addend, 4);
         }
         break;
     }
commit d0ebde228415c6d89ad61270a461717fbb04915c
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 30 08:16:00 2013 -0700

    tcg-arm: Move load of tlb addend into tcg_out_tlb_read
    
    This allows us to make more intelligent decisions about the relative
    offsets of the tlb comparator and the addend, avoiding any need of
    writeback addressing.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 1f7bbe1..b9ec4f6 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1172,42 +1172,39 @@ QEMU_BUILD_BUG_ON(CPU_TLB_BITS > 8);
 QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1])
                   > 0xffff);
 
-/* Load and compare a TLB entry, leaving the flags set.  Leaves R2 pointing
-   to the tlb entry.  Clobbers R1 and TMP.  */
+/* Load and compare a TLB entry, leaving the flags set.  Leaves R1 containing
+   the addend of the tlb entry.  Clobbers R0, R2, TMP.  */
 
 static void tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
-                             int s_bits, int tlb_offset)
+                             int s_bits, int mem_index, bool is_load)
 {
     TCGReg base = TCG_AREG0;
+    int cmp_off =
+        (is_load
+         ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
+         : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
+    int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
 
     /* Should generate something like the following:
-     * pre-v7:
      *   shr    tmp, addr_reg, #TARGET_PAGE_BITS                  (1)
-     *   add    r2, env, #off & 0xff00
+     *   add    r2, env, #high
      *   and    r0, tmp, #(CPU_TLB_SIZE - 1)                      (2)
      *   add    r2, r2, r0, lsl #CPU_TLB_ENTRY_BITS               (3)
-     *   ldr    r0, [r2, #off & 0xff]!                            (4)
+     *   ldr    r0, [r2, #cmp]                                    (4)
      *   tst    addr_reg, #s_mask
      *   cmpeq  r0, tmp, lsl #TARGET_PAGE_BITS                    (5)
-     *
-     * v7 (not implemented yet):
-     *   ubfx   r2, addr_reg, #TARGET_PAGE_BITS, #CPU_TLB_BITS    (1)
-     *   movw   tmp, #~TARGET_PAGE_MASK & ~s_mask
-     *   movw   r0, #off
-     *   add    r2, env, r2, lsl #CPU_TLB_ENTRY_BITS              (2)
-     *   bic    tmp, addr_reg, tmp
-     *   ldr    r0, [r2, r0]!                                     (3)
-     *   cmp    r0, tmp                                           (4)
+     *   ldr    r1, [r2, #add]
      */
     tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP,
                     0, addrlo, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
 
     /* We checked that the offset is contained within 16 bits above.  */
-    if (tlb_offset > 0xff) {
+    if (add_off > 0xfff || (use_armv6_instructions && cmp_off > 0xff)) {
         tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R2, base,
-                        (24 << 7) | (tlb_offset >> 8));
-        tlb_offset &= 0xff;
+                        (24 << 7) | (cmp_off >> 8));
         base = TCG_REG_R2;
+        add_off -= cmp_off & 0xff00;
+        cmp_off &= 0xff;
     }
 
     tcg_out_dat_imm(s, COND_AL, ARITH_AND,
@@ -1219,14 +1216,11 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
        but due to how the pointer needs setting up, ldm isn't useful.
        Base arm5 doesn't have ldrd, but armv5te does.  */
     if (use_armv6_instructions && TARGET_LONG_BITS == 64) {
-        tcg_out_memop_8(s, COND_AL, INSN_LDRD_IMM, TCG_REG_R0,
-                        TCG_REG_R2, tlb_offset, 1, 1);
+        tcg_out_ldrd_8(s, COND_AL, TCG_REG_R0, TCG_REG_R2, cmp_off);
     } else {
-        tcg_out_memop_12(s, COND_AL, INSN_LDR_IMM, TCG_REG_R0,
-                         TCG_REG_R2, tlb_offset, 1, 1);
+        tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_R2, cmp_off);
         if (TARGET_LONG_BITS == 64) {
-            tcg_out_memop_12(s, COND_AL, INSN_LDR_IMM, TCG_REG_R1,
-                             TCG_REG_R2, 4, 1, 0);
+            tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2, cmp_off + 4);
         }
     }
 
@@ -1243,6 +1237,9 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
         tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
                         TCG_REG_R1, addrhi, SHIFT_IMM_LSL(0));
     }
+
+    /* Load the tlb addend.  */
+    tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2, add_off);
 }
 
 /* Record the context of a call to the out of line helper code for the slow
@@ -1386,18 +1383,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     mem_index = *args;
     s_bits = opc & 3;
 
-    tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits,
-                     offsetof(CPUArchState, tlb_table[mem_index][0].addr_read));
+    tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits, mem_index, 1);
 
     /* This a conditional BL only to load a pointer within this opcode into LR
        for the slow path.  We will not be using the value for a tail call.  */
     label_ptr = s->code_ptr;
     tcg_out_bl_noaddr(s, COND_NE);
 
-    tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2,
-                    offsetof(CPUTLBEntry, addend)
-                    - offsetof(CPUTLBEntry, addr_read));
-
     switch (opc) {
     case 0:
         tcg_out_ld8_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
@@ -1533,13 +1525,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
     mem_index = *args;
     s_bits = opc & 3;
 
-    tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits,
-                     offsetof(CPUArchState,
-                              tlb_table[mem_index][0].addr_write));
-
-    tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2,
-                    offsetof(CPUTLBEntry, addend)
-                    - offsetof(CPUTLBEntry, addr_write));
+    tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits, mem_index, 0);
 
     switch (opc) {
     case 0:
commit f2488736371ae902f345cf9270d141f0a6797731
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 28 14:40:52 2013 -0700

    tcg-arm: Use QEMU_BUILD_BUG_ON to verify constraints on tlb
    
    One of the two constraints we already checked via #if, but
    the tlb offset distance was only checked at runtime.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index f953f4e..1f7bbe1 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1163,6 +1163,15 @@ static TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
 
 #define TLB_SHIFT	(CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
 
+/* We're expecting to use an 8-bit immediate and to mask.  */
+QEMU_BUILD_BUG_ON(CPU_TLB_BITS > 8);
+
+/* We're expecting to use an 8-bit immediate add + 8-bit ldrd offset.
+   Using the offset of the second entry in the last tlb table ensures
+   that we can index all of the elements of the first entry.  */
+QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1])
+                  > 0xffff);
+
 /* Load and compare a TLB entry, leaving the flags set.  Leaves R2 pointing
    to the tlb entry.  Clobbers R1 and TMP.  */
 
@@ -1190,14 +1199,10 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
      *   ldr    r0, [r2, r0]!                                     (3)
      *   cmp    r0, tmp                                           (4)
      */
-#  if CPU_TLB_BITS > 8
-#   error
-#  endif
     tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP,
                     0, addrlo, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
 
-    /* We assume that the offset is contained within 16 bits.  */
-    assert((tlb_offset & ~0xffff) == 0);
+    /* We checked that the offset is contained within 16 bits above.  */
     if (tlb_offset > 0xff) {
         tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R2, base,
                         (24 << 7) | (tlb_offset >> 8));
commit e5e2e4a74b75b41f72e1e3b3bac8c2a6b02896c2
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 28 11:16:16 2013 -0700

    tcg-arm: Use strd for tcg_out_arg_reg64
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 9d2fe8a..f953f4e 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1149,9 +1149,16 @@ static TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
     if (argreg & 1) {
         argreg++;
     }
-    argreg = tcg_out_arg_reg32(s, argreg, arglo);
-    argreg = tcg_out_arg_reg32(s, argreg, arghi);
-    return argreg;
+    if (use_armv6_instructions && argreg >= 4
+        && (arglo & 1) == 0 && arghi == arglo + 1) {
+        tcg_out_strd_8(s, COND_AL, arglo,
+                       TCG_REG_CALL_STACK, (argreg - 4) * 4);
+        return argreg + 2;
+    } else {
+        argreg = tcg_out_arg_reg32(s, argreg, arglo);
+        argreg = tcg_out_arg_reg32(s, argreg, arghi);
+        return argreg;
+    }
 }
 
 #define TLB_SHIFT	(CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
commit d9f4dde4a6d34f14509664edc262016f21be5aac
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Jul 27 14:09:47 2013 -1000

    tcg-arm: Rearrange slow-path qemu_ld/st
    
    Use the new helper_ret_*_mmu routines.  Use a conditional call
    to arrange for a tail-call from the store path, and to load the
    return address for the helper for the load path.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index dc27f33..8dd1594 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -324,21 +324,7 @@ extern uintptr_t tci_tb_ptr;
    In some implementations, we pass the "logical" return address manually;
    in others, we must infer the logical return from the true return.  */
 #if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
-# if defined(__arm__)
-/* We define two insns between the return address and the branch back to
-   straight-line.  Find and decode that branch insn.  */
-#  define GETRA_LDST(RA)   tcg_getra_ldst(RA)
-static inline uintptr_t tcg_getra_ldst(uintptr_t ra)
-{
-    int32_t b;
-    ra += 8;                    /* skip the two insns */
-    b = *(int32_t *)ra;         /* load the branch insn */
-    b = (b << 8) >> (8 - 2);    /* extract the displacement */
-    ra += 8;                    /* branches are relative to pc+8 */
-    ra += b;                    /* apply the displacement */
-    return ra;
-}
-# elif defined(__aarch64__)
+# if defined(__aarch64__)
 #  define GETRA_LDST(RA)  tcg_getra_ldst(RA)
 static inline uintptr_t tcg_getra_ldst(uintptr_t ra)
 {
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index ea0d9b4..9d2fe8a 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -175,11 +175,12 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
         ct->ct |= TCG_CT_REG;
         tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
 #ifdef CONFIG_SOFTMMU
-        /* r0-r2 will be overwritten when reading the tlb entry,
+        /* r0-r2,lr will be overwritten when reading the tlb entry,
            so don't use these. */
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14);
 #endif
         break;
     case 'L':
@@ -207,6 +208,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
         /* Avoid clashes with registers being used for helper args */
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
 #endif
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14);
 #endif
         break;
 
@@ -382,13 +384,17 @@ static inline void tcg_out_b_noaddr(TCGContext *s, int cond)
     /* We pay attention here to not modify the branch target by skipping
        the corresponding bytes. This ensure that caches and memory are
        kept coherent during retranslation. */
-#ifdef HOST_WORDS_BIGENDIAN
-    tcg_out8(s, (cond << 4) | 0x0a);
-    s->code_ptr += 3;
-#else
     s->code_ptr += 3;
     tcg_out8(s, (cond << 4) | 0x0a);
-#endif
+}
+
+static inline void tcg_out_bl_noaddr(TCGContext *s, int cond)
+{
+    /* We pay attention here to not modify the branch target by skipping
+       the corresponding bytes. This ensure that caches and memory are
+       kept coherent during retranslation. */
+    s->code_ptr += 3;
+    tcg_out8(s, (cond << 4) | 0x0b);
 }
 
 static inline void tcg_out_bl(TCGContext *s, int cond, int32_t offset)
@@ -1002,34 +1008,27 @@ static inline void tcg_out_st8(TCGContext *s, int cond,
         tcg_out_st8_12(s, cond, rd, rn, offset);
 }
 
-/* The _goto case is normally between TBs within the same code buffer,
- * and with the code buffer limited to 16MB we shouldn't need the long
- * case.
- *
- * .... except to the prologue that is in its own buffer.
+/* The _goto case is normally between TBs within the same code buffer, and
+ * with the code buffer limited to 16MB we wouldn't need the long case.
+ * But we also use it for the tail-call to the qemu_ld/st helpers, which does.
  */
 static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
 {
-    int32_t val;
+    int32_t disp = addr - (tcg_target_long) s->code_ptr;
 
-    if (addr & 1) {
-        /* goto to a Thumb destination isn't supported */
-        tcg_abort();
+    if ((addr & 1) == 0 && disp - 8 < 0x01fffffd && disp - 8 > -0x01fffffd) {
+        tcg_out_b(s, cond, disp);
+        return;
     }
 
-    val = addr - (tcg_target_long) s->code_ptr;
-    if (val - 8 < 0x01fffffd && val - 8 > -0x01fffffd)
-        tcg_out_b(s, cond, val);
-    else {
-        if (cond == COND_AL) {
-            tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
-            tcg_out32(s, addr);
-        } else {
-            tcg_out_movi32(s, cond, TCG_REG_TMP, val - 8);
-            tcg_out_dat_reg(s, cond, ARITH_ADD,
-                            TCG_REG_PC, TCG_REG_PC,
-                            TCG_REG_TMP, SHIFT_IMM_LSL(0));
+    tcg_out_movi32(s, cond, TCG_REG_TMP, addr);
+    if (use_armv5t_instructions) {
+        tcg_out_bx(s, cond, TCG_REG_TMP);
+    } else {
+        if (addr & 1) {
+            tcg_abort();
         }
+        tcg_out_mov_reg(s, cond, TCG_REG_PC, TCG_REG_TMP);
     }
 }
 
@@ -1084,23 +1083,29 @@ static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
 }
 
 #ifdef CONFIG_SOFTMMU
-
-/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
-   int mmu_idx) */
-static const void * const qemu_ld_helpers[4] = {
-    helper_ldb_mmu,
-    helper_ldw_mmu,
-    helper_ldl_mmu,
-    helper_ldq_mmu,
+/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
+ *                                     int mmu_idx, uintptr_t ra)
+ */
+static const void * const qemu_ld_helpers[8] = {
+    helper_ret_ldub_mmu,
+    helper_ret_lduw_mmu,
+    helper_ret_ldul_mmu,
+    helper_ret_ldq_mmu,
+
+    helper_ret_ldsb_mmu,
+    helper_ret_ldsw_mmu,
+    helper_ret_ldul_mmu,
+    helper_ret_ldq_mmu,
 };
 
-/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
-   uintxx_t val, int mmu_idx) */
+/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
+ *                                     uintxx_t val, int mmu_idx, uintptr_t ra)
+ */
 static const void * const qemu_st_helpers[4] = {
-    helper_stb_mmu,
-    helper_stw_mmu,
-    helper_stl_mmu,
-    helper_stq_mmu,
+    helper_ret_stb_mmu,
+    helper_ret_stw_mmu,
+    helper_ret_stl_mmu,
+    helper_ret_stq_mmu,
 };
 
 /* Helper routines for marshalling helper function arguments into
@@ -1259,7 +1264,8 @@ static void add_qemu_ldst_label(TCGContext *s, int is_ld, int opc,
 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
 {
     TCGReg argreg, data_reg, data_reg2;
-    uint8_t *start;
+    int opc = lb->opc;
+    uintptr_t func;
 
     reloc_pc24(lb->label_ptr[0], (tcg_target_long)s->code_ptr);
 
@@ -1270,22 +1276,30 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
         argreg = tcg_out_arg_reg32(s, argreg, lb->addrlo_reg);
     }
     argreg = tcg_out_arg_imm32(s, argreg, lb->mem_index);
-    tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[lb->opc & 3]);
+    argreg = tcg_out_arg_reg32(s, argreg, TCG_REG_R14);
+
+    /* For armv6 we can use the canonical unsigned helpers and minimize
+       icache usage.  For pre-armv6, use the signed helpers since we do
+       not have a single insn sign-extend.  */
+    if (use_armv6_instructions) {
+        func = (uintptr_t)qemu_ld_helpers[opc & 3];
+    } else {
+        func = (uintptr_t)qemu_ld_helpers[opc];
+        if (opc & 4) {
+            opc = 2;
+        }
+    }
+    tcg_out_call(s, func);
 
     data_reg = lb->datalo_reg;
     data_reg2 = lb->datahi_reg;
-
-    start = s->code_ptr;
-    switch (lb->opc) {
+    switch (opc) {
     case 0 | 4:
         tcg_out_ext8s(s, COND_AL, data_reg, TCG_REG_R0);
         break;
     case 1 | 4:
         tcg_out_ext16s(s, COND_AL, data_reg, TCG_REG_R0);
         break;
-    case 0:
-    case 1:
-    case 2:
     default:
         tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
         break;
@@ -1295,23 +1309,6 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
         break;
     }
 
-    /* For GETPC_LDST in exec-all.h, we architect exactly 2 insns between
-       the call and the branch back to straight-line code.  Note that the
-       moves above could be elided by register allocation, nor do we know
-       which code alternative we chose for extension.  */
-    switch (s->code_ptr - start) {
-    case 0:
-        tcg_out_nop(s);
-        /* FALLTHRU */
-    case 4:
-        tcg_out_nop(s);
-        /* FALLTHRU */
-    case 8:
-        break;
-    default:
-        abort();
-    }
-
     tcg_out_goto(s, COND_AL, (tcg_target_long)lb->raddr);
 }
 
@@ -1347,13 +1344,10 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
     }
 
     argreg = tcg_out_arg_imm32(s, argreg, lb->mem_index);
-    tcg_out_call(s, (tcg_target_long) qemu_st_helpers[lb->opc & 3]);
+    argreg = tcg_out_arg_reg32(s, argreg, TCG_REG_R14);
 
-    /* For GETPC_LDST in exec-all.h, we architect exactly 2 insns between
-       the call and the branch back to straight-line code.  */
-    tcg_out_nop(s);
-    tcg_out_nop(s);
-    tcg_out_goto(s, COND_AL, (tcg_target_long)lb->raddr);
+    /* Tail-call to the helper, which will return to the fast path.  */
+    tcg_out_goto(s, COND_AL, (tcg_target_long) qemu_st_helpers[lb->opc & 3]);
 }
 #endif /* SOFTMMU */
 
@@ -1383,8 +1377,10 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits,
                      offsetof(CPUArchState, tlb_table[mem_index][0].addr_read));
 
+    /* This a conditional BL only to load a pointer within this opcode into LR
+       for the slow path.  We will not be using the value for a tail call.  */
     label_ptr = s->code_ptr;
-    tcg_out_b_noaddr(s, COND_NE);
+    tcg_out_bl_noaddr(s, COND_NE);
 
     tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2,
                     offsetof(CPUTLBEntry, addend)
@@ -1529,50 +1525,51 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
                      offsetof(CPUArchState,
                               tlb_table[mem_index][0].addr_write));
 
-    label_ptr = s->code_ptr;
-    tcg_out_b_noaddr(s, COND_NE);
-
     tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2,
                     offsetof(CPUTLBEntry, addend)
                     - offsetof(CPUTLBEntry, addr_write));
 
     switch (opc) {
     case 0:
-        tcg_out_st8_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
+        tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
         break;
     case 1:
         if (bswap) {
-            tcg_out_bswap16st(s, COND_AL, TCG_REG_R0, data_reg);
-            tcg_out_st16_r(s, COND_AL, TCG_REG_R0, addr_reg, TCG_REG_R1);
+            tcg_out_bswap16st(s, COND_EQ, TCG_REG_R0, data_reg);
+            tcg_out_st16_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
         } else {
-            tcg_out_st16_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
+            tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
         }
         break;
     case 2:
     default:
         if (bswap) {
-            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
-            tcg_out_st32_r(s, COND_AL, TCG_REG_R0, addr_reg, TCG_REG_R1);
+            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
+            tcg_out_st32_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
         } else {
-            tcg_out_st32_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
+            tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
         }
         break;
     case 3:
         if (bswap) {
-            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg2);
-            tcg_out_st32_rwb(s, COND_AL, TCG_REG_R0, TCG_REG_R1, addr_reg);
-            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
-            tcg_out_st32_12(s, COND_AL, TCG_REG_R0, TCG_REG_R1, 4);
+            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg2);
+            tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, addr_reg);
+            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
+            tcg_out_st32_12(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, 4);
         } else if (use_armv6_instructions
                    && (data_reg & 1) == 0 && data_reg2 == data_reg + 1) {
-            tcg_out_strd_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
+            tcg_out_strd_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
         } else {
-            tcg_out_st32_rwb(s, COND_AL, data_reg, TCG_REG_R1, addr_reg);
-            tcg_out_st32_12(s, COND_AL, data_reg2, TCG_REG_R1, 4);
+            tcg_out_st32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
+            tcg_out_st32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
         }
         break;
     }
 
+    /* The conditional call must come last, as we're going to return here.  */
+    label_ptr = s->code_ptr;
+    tcg_out_bl_noaddr(s, COND_NE);
+
     add_qemu_ldst_label(s, 0, opc, data_reg, data_reg2, addr_reg, addr_reg2,
                         mem_index, s->code_ptr, label_ptr);
 #else /* !CONFIG_SOFTMMU */
commit 23bbc25085ceac827e1da9bebead058f436f66a6
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Jul 27 08:42:51 2013 -1000

    tcg-arm: Use ldrd/strd for appropriate qemu_ld/st64
    
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index eb0e84c..ea0d9b4 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -320,6 +320,9 @@ typedef enum {
     INSN_STRB_REG  = 0x06400000,
 
     INSN_LDRD_IMM  = 0x004000d0,
+    INSN_LDRD_REG  = 0x000000d0,
+    INSN_STRD_IMM  = 0x004000f0,
+    INSN_STRD_REG  = 0x000000f0,
 } ARMInsn;
 
 #define SHIFT_IMM_LSL(im)	(((im) << 7) | 0x00)
@@ -810,6 +813,30 @@ static inline void tcg_out_st32_r(TCGContext *s, int cond, TCGReg rt,
     tcg_out_memop_r(s, cond, INSN_STR_REG, rt, rn, rm, 1, 1, 0);
 }
 
+static inline void tcg_out_ldrd_8(TCGContext *s, int cond, TCGReg rt,
+                                   TCGReg rn, int imm8)
+{
+    tcg_out_memop_8(s, cond, INSN_LDRD_IMM, rt, rn, imm8, 1, 0);
+}
+
+static inline void tcg_out_ldrd_r(TCGContext *s, int cond, TCGReg rt,
+                                  TCGReg rn, TCGReg rm)
+{
+    tcg_out_memop_r(s, cond, INSN_LDRD_REG, rt, rn, rm, 1, 1, 0);
+}
+
+static inline void tcg_out_strd_8(TCGContext *s, int cond, TCGReg rt,
+                                   TCGReg rn, int imm8)
+{
+    tcg_out_memop_8(s, cond, INSN_STRD_IMM, rt, rn, imm8, 1, 0);
+}
+
+static inline void tcg_out_strd_r(TCGContext *s, int cond, TCGReg rt,
+                                  TCGReg rn, TCGReg rm)
+{
+    tcg_out_memop_r(s, cond, INSN_STRD_REG, rt, rn, rm, 1, 1, 0);
+}
+
 /* Register pre-increment with base writeback.  */
 static inline void tcg_out_ld32_rwb(TCGContext *s, int cond, TCGReg rt,
                                     TCGReg rn, TCGReg rm)
@@ -1397,6 +1424,9 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
             tcg_out_ld32_12(s, COND_AL, data_reg, TCG_REG_R1, 4);
             tcg_out_bswap32(s, COND_AL, data_reg2, data_reg2);
             tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
+        } else if (use_armv6_instructions
+                   && (data_reg & 1) == 0 && data_reg2 == data_reg + 1) {
+            tcg_out_ldrd_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
         } else {
             tcg_out_ld32_rwb(s, COND_AL, data_reg, TCG_REG_R1, addr_reg);
             tcg_out_ld32_12(s, COND_AL, data_reg2, TCG_REG_R1, 4);
@@ -1450,9 +1480,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
         }
         break;
     case 3:
-        /* TODO: use block load -
-         * check that data_reg2 > data_reg or the other way */
-        if (data_reg == addr_reg) {
+        if (use_armv6_instructions && !bswap
+            && (data_reg & 1) == 0 && data_reg2 == data_reg + 1) {
+            tcg_out_ldrd_8(s, COND_AL, data_reg, addr_reg, 0);
+        } else if (use_armv6_instructions && bswap
+                   && (data_reg2 & 1) == 0 && data_reg == data_reg2 + 1) {
+            tcg_out_ldrd_8(s, COND_AL, data_reg2, addr_reg, 0);
+        } else if (data_reg == addr_reg) {
             tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
             tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
         } else {
@@ -1529,6 +1563,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
             tcg_out_st32_rwb(s, COND_AL, TCG_REG_R0, TCG_REG_R1, addr_reg);
             tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
             tcg_out_st32_12(s, COND_AL, TCG_REG_R0, TCG_REG_R1, 4);
+        } else if (use_armv6_instructions
+                   && (data_reg & 1) == 0 && data_reg2 == data_reg + 1) {
+            tcg_out_strd_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
         } else {
             tcg_out_st32_rwb(s, COND_AL, data_reg, TCG_REG_R1, addr_reg);
             tcg_out_st32_12(s, COND_AL, data_reg2, TCG_REG_R1, 4);
@@ -1576,13 +1613,14 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
         }
         break;
     case 3:
-        /* TODO: use block store -
-         * check that data_reg2 > data_reg or the other way */
         if (bswap) {
             tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg2);
             tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
             tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
             tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 4);
+        } else if (use_armv6_instructions
+                   && (data_reg & 1) == 0 && data_reg2 == data_reg + 1) {
+            tcg_out_strd_8(s, COND_AL, data_reg, addr_reg, 0);
         } else {
             tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
             tcg_out_st32_12(s, COND_AL, data_reg2, addr_reg, 4);
commit 9dbb52e862458935c250bac9e71d5a87da4e33e9
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Sep 24 09:43:40 2013 +0200

    tests: Update .gitignore for test-int128 and test-bitops
    
    Forgotten in commit 6046c62 and 3464700.
    
    Cc: qemu-stable at nongnu.org
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Laszlo Ersek <lersek at redhat.com>
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/tests/.gitignore b/tests/.gitignore
index ae5280e..f94ce04 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -5,9 +5,11 @@ check-qjson
 check-qlist
 check-qstring
 test-aio
+test-bitops
 test-throttle
 test-cutils
 test-hbitmap
+test-int128
 test-iov
 test-mul64
 test-qapi-types.[ch]
commit d1c295f5721f206d55315405baa2c299acec7d76
Author: Fam Zheng <famz at redhat.com>
Date:   Sun Sep 22 20:49:19 2013 +0800

    .gitignore: ignore tests/qemu-iotests/socket_scm_helper
    
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Reviewed-by: Wenchao Xia<xiawenc at linux.vnet.ibm.com>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/tests/qemu-iotests/.gitignore b/tests/qemu-iotests/.gitignore
index 62b4002..0541f80 100644
--- a/tests/qemu-iotests/.gitignore
+++ b/tests/qemu-iotests/.gitignore
@@ -2,6 +2,7 @@ check.log
 check.time
 *.out.bad
 *.notrun
+socket_scm_helper
 
 # ignore everything in the scratch directory
 scratch/
commit ee6ee83de29923483b4905b35f18abf5333f6ea9
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Sep 13 12:48:47 2013 +0200

    chardev: handle qmp_chardev_add(KIND_MUX) failure
    
    Cc: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/qemu-char.c b/qemu-char.c
index f7f5464..2ca34cd 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3271,7 +3271,12 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
             backend->kind = CHARDEV_BACKEND_KIND_MUX;
             backend->mux->chardev = g_strdup(bid);
             ret = qmp_chardev_add(id, backend, errp);
-            assert(!error_is_set(errp));
+            if (error_is_set(errp)) {
+                chr = qemu_chr_find(bid);
+                qemu_chr_delete(chr);
+                chr = NULL;
+                goto qapi_out;
+            }
         }
 
         chr = qemu_chr_find(id);
commit a684f3cf9b9b9c3cb82be87aafc463de8974610c
Merge: 349cd52 1cf9412
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Mon Sep 30 17:15:27 2013 -0500

    Merge remote-tracking branch 'kraxel/seabios-1.7.3.2' into staging
    
    # By Gerd Hoffmann
    # Via Gerd Hoffmann
    * kraxel/seabios-1.7.3.2:
      update seabios from 1.7.2.2 to 1.7.3.2
    
    Message-id: 1380533055-24960-1-git-send-email-kraxel at redhat.com

commit 349cd52c708eb7974d4517f40151685e09a069f6
Merge: eb322b8 774e80e
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Mon Sep 30 17:15:18 2013 -0500

    Merge remote-tracking branch 'kraxel/roms.1' into staging
    
    # By Gerd Hoffmann
    # Via Gerd Hoffmann
    * kraxel/roms.1:
      roms: add support for building sgabios
      roms: enable parallel seabios / seavgabios builds
      roms: enable ipxe cross builds
      roms: add rules to build slof
      roms: rewrite scripts/refresh-pxe-roms.sh
      roms: parallel ipxe builds
      roms: build lgplvgabios isavga variant
      roms: enable parallel builds for 'make lgplvgabios'
      roms: add 'make clean'
    
    Message-id: 1380532378-22138-1-git-send-email-kraxel at redhat.com

commit eb322b8155120166fa259a8e96040f76ba4fde64
Merge: 4235d77 e26d3e7
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Mon Sep 30 17:15:01 2013 -0500

    Merge remote-tracking branch 'mst/tags/for_anthony' into staging
    
    pc,pci,virtio fixes and cleanups
    
    This includes pc and pci cleanups and enhancements,
    and a virtio-net bugfix related to softmac programming.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    
    # gpg: Signature made Sun 29 Sep 2013 01:51:16 AM CDT using RSA key ID D28D5469
    # gpg: Can't check signature: public key not found
    
    # By Michael S. Tsirkin (8) and others
    # Via Michael S. Tsirkin
    * mst/tags/for_anthony:
      smbios: Factor out smbios_maybe_add_str()
      smbios: Make multiple -smbios type= accumulate sanely
      smbios: Improve diagnostics for conflicting entries
      smbios: Convert to QemuOpts
      smbios: Normalize smbios_entry_add()'s error handling to exit(1)
      virtio-net: fix up HMP NIC info string on reset
      pci: remove explicit check to 64K ioport size
      piix4: disable io on reset
      piix: use 64 bit window programmed by guest
      q35: use 64 bit window programmed by guest
      pci: add helper to retrieve the 64-bit range
      range: add min/max operations on ranges
      range: add Range to typedefs
      q35: make pci window address/size match guest cfg
    
    Message-id: 1380437951-21788-1-git-send-email-mst at redhat.com

diff --cc include/sysemu/sysemu.h
index ffc53aa,4257736..cd5791e
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@@ -16,10 -16,9 +16,11 @@@ extern const char *bios_name
  
  extern const char *qemu_name;
  extern uint8_t qemu_uuid[];
+ extern bool qemu_uuid_set;
  int qemu_uuid_parse(const char *str, uint8_t *uuid);
 +
  #define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
 +#define UUID_NONE "00000000-0000-0000-0000-000000000000"
  
  bool runstate_check(RunState state);
  void runstate_set(RunState new_state);
commit 4235d77349e93e7157555f20f1892088f55edff4
Merge: 3469a60 6165300
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Mon Sep 30 17:14:49 2013 -0500

    Merge remote-tracking branch 'kwolf/for-anthony' into staging
    
    # By Max Reitz (10) and others
    # Via Kevin Wolf
    * kwolf/for-anthony: (30 commits)
      qcow2: Remove useless count_contiguous_clusters() parameter
      qcow2: COMPRESSED on count_contiguous_clusters
      qcow2: count_contiguous_clusters and compression
      qcow2: Free only newly allocated clusters on error
      qcow2: Always use error path in l2_allocate
      qcow2: Don't put invalid L2 table into cache
      qemu-iotests: Preallocated zero clusters in 061
      qcow2: Correct bitmap size in zero expansion
      qemu-iotests: Quote $TEST_IMG* and $TEST_DIR usage
      qemu-iotests: Add basic ability to use binary sample images
      qemu-iotests: fix qmp.py search path
      block: use DIV_ROUND_UP in bdrv_co_do_readv
      qcow2: Assert against currently impossible overflow
      block: qed - use QEMU_PACKED for on-disk structures
      block: qcow2 - used QEMU_PACKED for on-disk structures
      block: vpc - use QEMU_PACKED for on-disk structures
      block: vdi - use QEMU_PACKED for on-disk structures
      rbd: avoid qemu_rbd_snap_list() memory leaks
      qdict: Extract qdict_extract_subqdict
      block: Fix compiler warning (-Werror=uninitialized)
      ...
    
    Message-id: 1380296370-14523-1-git-send-email-kwolf at redhat.com

commit 3469a60d9f6f7ba6fca3fe0788391f7285ead631
Merge: 28b9d47 594278d
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Mon Sep 30 17:14:10 2013 -0500

    Merge remote-tracking branch 'sstabellini/xen-2013-09-25' into staging
    
    # By Anthony PERARD (2) and Liu, Jinsong (2)
    # Via Stefano Stabellini
    * sstabellini/xen-2013-09-25:
      xen: Enable cpu-hotplug on xenfv machine.
      xen: Fix vcpu initialization.
      qemu: Add qemu xen logic for Xen HVM S3 resume
      qemu: Adjust qemu wakeup
    
    Message-id: alpine.DEB.2.02.1309251749180.5498 at kaball.uk.xensource.com

commit 28b9d47db61a96d2630c7ffa6cbfdcdd1536f7cb
Merge: 8429d63 7f12d64
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Mon Sep 30 17:14:01 2013 -0500

    Merge remote-tracking branch 'rth/tcg-ppc-pull' into staging
    
    # By Richard Henderson (19) and Paolo Bonzini (2)
    # Via Richard Henderson
    * rth/tcg-ppc-pull: (21 commits)
      tcg-ppc64: Implement CONFIG_QEMU_LDST_OPTIMIZATION
      tcg-ppc64: Add _noaddr functions for emitting forward branches
      tcg-ppc64: Streamline tcg_out_tlb_read
      tcg-ppc64: Implement tcg_register_jit
      tcg-ppc64: Handle long offsets better
      tcg-ppc64: Tidy register allocation order
      tcg-ppc64: Look through a constant function descriptor
      tcg-ppc64: Fold constant call address into descriptor load
      tcg-ppc64: Don't load the static chain from TCG
      tcg-ppc64: Avoid code for nop move
      tcg-ppc64: Use tcg_out64
      tcg-ppc64: Use TCG_REG_Rn constants
      tcg-ppc64: More use of TAI and SAI helper macros
      tcg-ppc64: Reformat tcg-target.c
      tcg-ppc: Fix and cleanup tcg_out_tlb_check
      tcg-ppc: Use conditional branch and link to slow path
      tcg-ppc: Cleanup tcg_out_qemu_ld/st_slow_path
      tcg-ppc: Avoid code for nop move
      tcg-ppc: use new return-argument ld/st helpers
      tcg-ppc: fix qemu_ld/qemu_st for AIX ABI
      ...
    
    Message-id: 1380126458-3247-1-git-send-email-rth at twiddle.net

commit 8429d63b0e5671f112cb4cbf8ab6d697a676ccc4
Merge: d7f0efc d613a56
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Mon Sep 30 17:13:43 2013 -0500

    Merge remote-tracking branch 'quintela/migration.next' into staging
    
    # By Isaku Yamahata (4) and others
    # Via Juan Quintela
    * quintela/migration.next:
      migration: ram_handle_compressed
      arch_init: make is_zero_page accept size
      migration: Fix debug print type
      migration: add version supporting macros for struct pointer
      rdma: constify ram_chunk_{index, start, end}
      rdma: clean up of qemu_rdma_cleanup()
      arch_init: right return for ram_save_iterate
      savevm: fix wrong initialization by ram_control_load_hook
      savevm: add comments for qemu_file_get_error()
    
    Message-id: 1380024203-25897-1-git-send-email-quintela at redhat.com

commit d7f0efcb229bc1c3e458c6968efe4a6644f24740
Merge: 1b365b2 19b0dfc
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Mon Sep 30 17:13:32 2013 -0500

    Merge remote-tracking branch 'kraxel/audio.1' into staging
    
    # By Bandan Das (3) and Gerd Hoffmann (1)
    # Via Gerd Hoffmann
    * kraxel/audio.1:
      audio: remove CONFIG_MIXEMU configure option
      hda-codec: make mixemu selectable at runtime
      hda-codec: refactor common definitions into a header file
      audio maintainers update
    
    Message-id: 1380011943-15083-1-git-send-email-kraxel at redhat.com

commit 1b365b2eb629d033b3650acc9f46fc132ef0981c
Merge: 53d09b7 6a444f8
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Mon Sep 30 17:13:18 2013 -0500

    Merge remote-tracking branch 'borntraeger/tags/s390-next-20130924' into staging
    
    This is a bunch of fixes/changes for the s390 architecture. It also
    contains the fixes from the previous pull request, which did not make
    it yet.
    Overall it contains
    - a fix for kexec without kdump (which uses diag308 subcode 0 instead of 1)
    - several sclp related fixes
    - some initial sclp migration code
    - the sclp line mode console
    - A fix for a boot problem with the virtio ccw ipl bios
    - zeroed out padding bytes for the notes section of dump-guest-memory
    - some cleanups
    
    # gpg: Signature made Tue 24 Sep 2013 02:18:44 AM CDT using RSA key ID B5A61C7C
    # gpg: Can't check signature: public key not found
    
    # By Christian Borntraeger (6) and others
    # Via Christian Borntraeger
    * borntraeger/tags/s390-next-20130924:
      s390/sclplmconsole: Add support for SCLP line-mode console
      s390/ebcdic: Move conversion tables to header file
      s390/eventfacility: allow childs to handle more than 1 event type
      s390/eventfacility: remove unused event_type variable
      s390/eventfacility: Fix receive/send masks
      s390/eventfacility: fix multiple Read Event Data sources
      s390/sclp: add reset() functions
      s390/sclpquiesce: Add code to support live migration
      s390/sclpconsole: Add code to support live migration for sclpconsole
      s390/sclpconsole: modify definition of input buffer
      s390/kexec: Implement diag308 subcode 0
      s390/ioinst: Moved the CC setting to the IO instruction handlers
      s390/cpu: Make setcc() function available to other files
      s390/ipl: Update the s390-ccw.img rom
      s390/ipl: Fix waiting for virtio processing
      s390/dump: zero out padding bytes in notes sections
      s390/kvm: Add check for priviledged SCLP handler
    
    Message-id: 1380007671-18976-1-git-send-email-borntraeger at de.ibm.com

commit 1cf9412b3b583b59a1ac131609cbf673662ee7eb
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Sep 30 11:17:57 2013 +0200

    update seabios from 1.7.2.2 to 1.7.3.2
    
    'git shortlog d4f7d90f..ece025f5' says:
    
    Alex Williamson (4):
          seabios q35: Enable all PIRQn IRQs at startup
          seabios q35: Add new PCI slot to irq routing function
          seabios: Add a dummy PCI slot to irq mapping function
          pciinit: Enable default VGA device
    
    Asias He (2):
          virtio-scsi: Set _DRIVER_OK flag before scsi target scanning
          virtio-scsi: Pack struct virtio_scsi_{req_cmd,resp_cmd}
    
    Avik Sil (1):
          USB-EHCI: Fix null pointer assignment
    
    Christian Gmeiner (5):
          geodevga: fix errors in geode_fp_* functions
          geodevga: move framebuffer setup
          geodevga: move output setup to own function
          geodevga: add debug to msr functions
          geodevga: fix wrong define name
    
    David Woodhouse (26):
          Add macros for pushing and popping struct bregs
          Clean up #if in pirtable.c. CONFIG_PIRTABLE can't be set if CONFIG_COREBOOT is
          post: Export functions which will be used individually by CSM
          Export callrom() for CSM to use
          Export copy_smbios() from biostables.c
          Import LegacyBios.h from OVMF
          Complete and checksum EFI_COMPATIBILITY16_TABLE at build time
          Add pic_save_mask() and pic_restore_mask() functions
          Add CSM support
          Add README.CSM
          Add find_pmtimer() function
          Enable PMTIMER for CSM build
          Fix rom_reserve()/rom_confirm() for CSM oprom dispatch
          Don't calibrate TSC if PMTIMER is already set up
          Move find_pmtimer() to ACPI table setup where it logically belongs
          Use find_pmtimer() after copying Xen ACPI tables
          Use find_pmtimer() after copying coreboot ACPI tables
          Unify return path for CSM to go via csm_return()
          Make CONFIG_OPTIONROMS_DEPLOYED depend on CONFIG_QEMU
          Implement !CONFIG_OPTIONROMS support for CSM
          Implement !CONFIG_BOOT for CSM
          Enable VGA output when settings bochs-specific mode
          Disable CONFIG_THREAD_OPTIONROMS for CSM build
          Fix return type of le64_to_cpu() and be64_to_cpu()
          Rename find_pmtimer() to find_acpi_features()
          Add acpi_reboot() reset method using RESET_REG
    
    Gerd Hoffmann (6):
          config: allow DEBUG_IO for !QEMU
          coreboot: add qemu detection
          tweak coreboot qemu detection
          apm: fix shutdown
          ahci: add missing check for allocation failure
          fix buildversion.sh
    
    Hu Tao (1):
          Add pvpanic device driver
    
    Kevin O'Connor (101):
          pmm: Use 'struct segoff_s' in pmm header.
          Minor: Update README - variable changes are now reset on soft-reboots.
          Normalize POST initialization function name suffixes.
          POST: Reorganize post init functions for better grouping and reusability.
          Fix rebase error in commit 8a0a972f that broke LOWMEM variables.
          Support calling a function other than maininit() from reloc_preinit().
          Ensure exported symbols are visible in the final link
          POST: Move QEMU specific ramsize and BIOS table setup to paravirt.c.
          POST: Reorganize post entry and "preinit" functions.
          POST: Move cpu caching and dma setup to platform_hardware_setup().
          Undo incorrect assumptions about Xen in commit 6ca0460f.
          Determine century during init and store in VARLOW mem during runtime.
          No need to check both CONFIG_THREADS and CONFIG_THREAD_OPTIONROMS.
          Add runningOnQEMU() and runningOnXen() for runtime platform detection.
          Consistently use CONFIG_COREBOOT, CONFIG_QEMU, and runningOnXen().
          Convert kvm_para_available() to runningOnKVM().
          Minor - move definitions to paravirt.c from paravirt.h.
          Only perform SMP setup on QEMU.
          Start device_hardware_setup in mainint even with CONFIG_THREAD_OPTIONROMS.
          The mathcp setup touches the PIC and thus move to the "setup" phase.
          Update tools/acpi_extract.py to handle iasl 20130117 release.
          Support skipping content when reading from QEMU fw_cfg romfile entries.
          Convert fw_cfg ACPI entries into romfile entries.
          Convert fw_cfg SMBIOS entries into romfile entries.
          Convert basic integer fw_cfg entries into romfile entries.
          Convert fw_cfg NUMA entries into a romfile entry.
          Process fw_cfg e820 entries during the fw_cfg setup stage.
          Integrate qemu_cfg_preinit() into qemu_romfile_init().
          Group QEMU platform setup together and move to paravirt.c.
          vgabios: Bochs/QEMU vgabios support should depend on CONFIG_QEMU.
          Warn on unaligned PCI ROM structure in option roms.
          Fix Makefile - don't reference "out/" directly, instead use "$(OUT)".
          build: Don't require $(OUT) to be a sub-directory of the main directory.
          Rename rom_get_top() to rom_get_max().
          Report on f-segment UMB ram also.
          Clarify build generated "zone low" values.
          Verify CC is valid during build tests.
          Disable handle_post() on CSM builds.
          Remove unnecessary "export" declarations from assembler functions.
          Minor assembler enhancements to __csm_return.
          Introduce VARFSEG for variables that will reside in the f-segment.
          Convert VAR16VISIBLE, VAR16EXPORT, and VAR32VISIBLE to VARFSEG.
          Don't relocate "varlow" variable references at runtime.
          Move malloc's ZoneFSeg and ZoneLow setup to malloc_init.
          Calculate "RamSize" needed by 16bit interface dynamically.
          Eliminate separate BiosTableSpace[] space for f-segment allocations.
          Use CONFIG_ prefix for Kconfig variables; use BUILD_ for others.
          Try to detect an unsuccessful hard-reboot to prevent soft-reboot loops.
          Minor - fix confusing final_sec32low_start name in layoutrom.py.
          Minor - introduce numeric defines for the IVT offset of hw irqs.
          Separate out 16bit PCI-BIOS entry point from regular int 0x1a entry point.
          Support using the "extra stack" for all 16bit irq entry points.
          Minor - improve comments and grouping of handle_08().
          floppy: Introduce 'struct floppy_pio_s' for floppy PIO ops.
          floppy: Cleanup floppy irq wait handling.
          floppy: Clean up Check Interrupt Status code.
          floppy: Move recalibration and results parsing to floppy_cmd().
          floppy: Improve floppy_pio() error checking.
          floppy: Implement media format sensing.
          floppy: Actually do controller reset in floppy_reset().
          Minor - note that passing QEMU config via cmos is deprecated.
          Cache boot-fail-wait to avoid romfile access after POST.
          Rename src/ssdt-susp.dsl to src/ssdt-misc.dsl.
          acpi: Eliminate BDAT parameter passing to DSDT code.
          Add additional dependency checks to Makefile.
          Don't use __FILE__ in virtio-ring.c.
          shadow: Don't use PCIDevices list in make_bios_readonly().
          smm: Don't use PCIDevices list in smm_setup().
          Add VARVERIFY32INIT attribute for variables only available during "init".
          Use VARVERIFY32INIT on global variables that point to "tmp" memory.
          vgabios: Fix stdvga_perform_gray_scale_summing().
          vgabios: Fix cirrus memory clear on mode switch.
          Minor - add missing newline to floppy debug statement.
          Fix bug in NUMA node setup - don't create SRAT if NUMA not present.
          Update README - copy *.aml files for QEMU.
          Add dependencies to vgafixup.py and buildversion.sh scripts.
          Set ZF prior to keyboard read call in check_for_keystroke().
          mptable: Don't describe pci-to-pci bridges.
          mptable: Use same PCI irqs as ACPI code.
          Cleanup QEMU_CFG_NUMA fw_cfg processing - split into two romfile entries.
          Use container_of on romfile entries.
          acpi: Move ACPI table definitions from acpi.c to acpi.h.
          acpi: Remove dead code with descriptions of bit flags.
          acpi: Use cpu_to_leXX() consistently.
          Minor - explicitly close files in buildrom.py.
          Minor - move "tracked memory alloc" code in pmm.c.
          Introduce and convert pmm code to use standard list helpers.
          Minor - relocate code in stacks.c to keep low-level thread code together.
          Introduce helper function have_threads() in stacks.c.
          Convert stacks.c to use standard list manipulation code.
          Convert boot.c to use standard list manipulation code.
          Convert pciinit.c to use standard list manipulation code.
          Convert PCIDevices list to use standard list manipultion code.
          Revert "Convert pciinit.c to use standard list manipulation code."
          Fix error in hlist_for_each_entry_safe macro.
          Convert pciinit.c to use standard list manipulation code.
          make qemu_cfg_init depend on QEMU_HARDWARE instead of QEMU
          Another fix for hlist_for_each_entry_safe.
          Minor - remove debugging dprintf added to pciinit.c.
          Fix USB EHCI detection that was broken in hlist conversion of PCIDevices.
          Fix bug in CBFS file walking with compressed files.
    
    Laszlo Ersek (1):
          Enable VGA output when setting Cirrus-specific mode
    
    Michael S. Tsirkin (2):
          acpi: make default DSDT optional
          acpi: sync FADT flags from PIIX4 to Q35
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/pc-bios/acpi-dsdt.aml b/pc-bios/acpi-dsdt.aml
index 48dbe32..528372b 100644
Binary files a/pc-bios/acpi-dsdt.aml and b/pc-bios/acpi-dsdt.aml differ
diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index cccc487..697440c 100644
Binary files a/pc-bios/bios.bin and b/pc-bios/bios.bin differ
diff --git a/pc-bios/q35-acpi-dsdt.aml b/pc-bios/q35-acpi-dsdt.aml
index 91ab67c..4d23746 100644
Binary files a/pc-bios/q35-acpi-dsdt.aml and b/pc-bios/q35-acpi-dsdt.aml differ
diff --git a/roms/seabios b/roms/seabios
index d4f7d90..ece025f 160000
--- a/roms/seabios
+++ b/roms/seabios
@@ -1 +1 @@
-Subproject commit d4f7d90f47462b4e8836899adc5060fbde5253e9
+Subproject commit ece025f5980bae88fa677bc9c0d24d2e580e205d
commit 774e80ea1d080c608ab06a3b68d9f583644b8d85
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Sep 24 15:46:52 2013 +0200

    roms: add support for building sgabios
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/roms/Makefile b/roms/Makefile
index 6994873..10d5a65 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -50,6 +50,7 @@ default:
 	@echo "  bios           -- update bios.bin (seabios)"
 	@echo "  seavgabios     -- update vgabios binaries (seabios)"
 	@echo "  lgplvgabios    -- update vgabios binaries (lgpl)"
+	@echo "  sgabios        -- update sgabios binaries"
 	@echo "  pxerom         -- update nic roms (bios only)"
 	@echo "  efirom         -- update nic roms (bios+efi, this needs"
 	@echo "                    the EfiRom utility from edk2 / tianocore)"
@@ -89,6 +90,12 @@ build-lgplvgabios:
 	$(MAKE) $(MAKEFLAGS) -C vgabios $(vgabios_targets)
 
 
+.PHONY: sgabios
+sgabios:
+	$(MAKE) $(MAKEFLAGS) -C sgabios
+	cp sgabios/sgabios.bin ../pc-bios
+
+
 pxerom: $(patsubst %,pxe-rom-%,$(pxerom_variants))
 
 pxe-rom-%: build-pxe-roms
@@ -127,5 +134,7 @@ clean:
 	rm -rf seabios/.config seabios/out seabios/builds
 	$(MAKE) $(MAKEFLAGS) -C vgabios clean
 	rm -f vgabios/VGABIOS-lgpl-latest*
+	$(MAKE) $(MAKEFLAGS) -C sgabios clean
+	rm -f sgabios/.depend
 	$(MAKE) $(MAKEFLAGS) -C ipxe/src veryclean
 	$(MAKE) $(MAKEFLAGS) -C SLOF clean
commit 95f7c6803c71ca6f74e8d59da3fd189230d1c466
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Sep 24 15:38:28 2013 +0200

    roms: enable parallel seabios / seavgabios builds
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/roms/Makefile b/roms/Makefile
index 1966f04..6994873 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -55,18 +55,27 @@ default:
 	@echo "                    the EfiRom utility from edk2 / tianocore)"
 	@echo "  slof           -- update slof.bin"
 
-bios: config.seabios
-	sh configure-seabios.sh $<
-	make -C seabios out/bios.bin
-	cp seabios/out/bios.bin ../pc-bios/bios.bin
-	cp seabios/out/*dsdt.aml ../pc-bios/
+bios: build-seabios-config-seabios
+	cp seabios/builds/seabios/bios.bin ../pc-bios/bios.bin
+	cp seabios/builds/seabios/*dsdt.aml ../pc-bios/
 
 seavgabios: $(patsubst %,seavgabios-%,$(vgabios_variants))
 
-seavgabios-%: config.vga.%
-	sh configure-seabios.sh $<
-	make -C seabios out/vgabios.bin
-	cp seabios/out/vgabios.bin ../pc-bios/vgabios-$*.bin
+seavgabios-isavga: build-seabios-config-vga-isavga
+	cp seabios/builds/vga-isavga/vgabios.bin ../pc-bios/vgabios.bin
+
+seavgabios-%: build-seabios-config-vga-%
+	cp seabios/builds/vga-$*/vgabios.bin ../pc-bios/vgabios-$*.bin
+
+build-seabios-config-%: config.%
+	mkdir -p seabios/builds/$*
+	cp $< seabios/builds/$*/.config
+	$(MAKE) $(MAKEFLAGS) -C seabios \
+		KCONFIG_CONFIG=$(CURDIR)/seabios/builds/$*/.config \
+		OUT=$(CURDIR)/seabios/builds/$*/ oldnoconfig
+	$(MAKE) $(MAKEFLAGS) -C seabios \
+		KCONFIG_CONFIG=$(CURDIR)/seabios/builds/$*/.config \
+		OUT=$(CURDIR)/seabios/builds/$*/ all
 
 
 lgplvgabios: $(patsubst %,lgplvgabios-%,$(vgabios_variants))
@@ -115,7 +124,7 @@ slof:
 
 
 clean:
-	rm -rf seabios/.config seabios/out
+	rm -rf seabios/.config seabios/out seabios/builds
 	$(MAKE) $(MAKEFLAGS) -C vgabios clean
 	rm -f vgabios/VGABIOS-lgpl-latest*
 	$(MAKE) $(MAKEFLAGS) -C ipxe/src veryclean
diff --git a/roms/config.vga-cirrus b/roms/config.vga-cirrus
new file mode 100644
index 0000000..c8fe582
--- /dev/null
+++ b/roms/config.vga-cirrus
@@ -0,0 +1,3 @@
+CONFIG_BUILD_VGABIOS=y
+CONFIG_VGA_CIRRUS=y
+CONFIG_VGA_PCI=y
diff --git a/roms/config.vga-isavga b/roms/config.vga-isavga
new file mode 100644
index 0000000..e55e294
--- /dev/null
+++ b/roms/config.vga-isavga
@@ -0,0 +1,3 @@
+CONFIG_BUILD_VGABIOS=y
+CONFIG_VGA_BOCHS=y
+CONFIG_VGA_PCI=n
diff --git a/roms/config.vga-qxl b/roms/config.vga-qxl
new file mode 100644
index 0000000..d393f0c
--- /dev/null
+++ b/roms/config.vga-qxl
@@ -0,0 +1,6 @@
+CONFIG_BUILD_VGABIOS=y
+CONFIG_VGA_BOCHS=y
+CONFIG_VGA_PCI=y
+CONFIG_OVERRIDE_PCI_ID=y
+CONFIG_VGA_VID=0x1b36
+CONFIG_VGA_DID=0x0100
diff --git a/roms/config.vga-stdvga b/roms/config.vga-stdvga
new file mode 100644
index 0000000..7d063b7
--- /dev/null
+++ b/roms/config.vga-stdvga
@@ -0,0 +1,3 @@
+CONFIG_BUILD_VGABIOS=y
+CONFIG_VGA_BOCHS=y
+CONFIG_VGA_PCI=y
diff --git a/roms/config.vga-vmware b/roms/config.vga-vmware
new file mode 100644
index 0000000..eb10427
--- /dev/null
+++ b/roms/config.vga-vmware
@@ -0,0 +1,6 @@
+CONFIG_BUILD_VGABIOS=y
+CONFIG_VGA_BOCHS=y
+CONFIG_VGA_PCI=y
+CONFIG_OVERRIDE_PCI_ID=y
+CONFIG_VGA_VID=0x15ad
+CONFIG_VGA_DID=0x0405
diff --git a/roms/config.vga.cirrus b/roms/config.vga.cirrus
deleted file mode 100644
index c8fe582..0000000
--- a/roms/config.vga.cirrus
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG_BUILD_VGABIOS=y
-CONFIG_VGA_CIRRUS=y
-CONFIG_VGA_PCI=y
diff --git a/roms/config.vga.isavga b/roms/config.vga.isavga
deleted file mode 100644
index e55e294..0000000
--- a/roms/config.vga.isavga
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG_BUILD_VGABIOS=y
-CONFIG_VGA_BOCHS=y
-CONFIG_VGA_PCI=n
diff --git a/roms/config.vga.qxl b/roms/config.vga.qxl
deleted file mode 100644
index d393f0c..0000000
--- a/roms/config.vga.qxl
+++ /dev/null
@@ -1,6 +0,0 @@
-CONFIG_BUILD_VGABIOS=y
-CONFIG_VGA_BOCHS=y
-CONFIG_VGA_PCI=y
-CONFIG_OVERRIDE_PCI_ID=y
-CONFIG_VGA_VID=0x1b36
-CONFIG_VGA_DID=0x0100
diff --git a/roms/config.vga.stdvga b/roms/config.vga.stdvga
deleted file mode 100644
index 7d063b7..0000000
--- a/roms/config.vga.stdvga
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG_BUILD_VGABIOS=y
-CONFIG_VGA_BOCHS=y
-CONFIG_VGA_PCI=y
diff --git a/roms/config.vga.vmware b/roms/config.vga.vmware
deleted file mode 100644
index eb10427..0000000
--- a/roms/config.vga.vmware
+++ /dev/null
@@ -1,6 +0,0 @@
-CONFIG_BUILD_VGABIOS=y
-CONFIG_VGA_BOCHS=y
-CONFIG_VGA_PCI=y
-CONFIG_OVERRIDE_PCI_ID=y
-CONFIG_VGA_VID=0x15ad
-CONFIG_VGA_DID=0x0405
commit 779fa9d7060c547059ff1993dd38bea565d7f2e7
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Sep 23 11:05:48 2013 +0200

    roms: enable ipxe cross builds

diff --git a/roms/Makefile b/roms/Makefile
index 5fcc77d..1966f04 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -31,6 +31,7 @@ find-cross-gcc = $(firstword $(wildcard $(patsubst %ld,%gcc,$(call find-cross-ld
 find-cross-prefix = $(subst gcc,,$(notdir $(call find-cross-gcc,$(1))))
 
 powerpc64_cross_prefix := $(call find-cross-prefix,powerpc64)
+x86_64_cross_prefix := $(call find-cross-prefix,x86_64)
 
 #
 # EfiRom utility is shipped with edk2 / tianocore, in BaseTools/
@@ -95,10 +96,12 @@ efi-rom-%: build-pxe-roms build-efi-roms
 
 build-pxe-roms: ipxe/src/config/local/general.h
 	$(MAKE) $(MAKEFLAGS) -C ipxe/src GITVERSION="" \
+		CROSS_COMPILE=$(x86_64_cross_prefix) \
 		$(patsubst %,bin/%.rom,$(pxerom_targets))
 
 build-efi-roms: build-pxe-roms ipxe/src/config/local/general.h
 	$(MAKE) $(MAKEFLAGS) -C ipxe/src GITVERSION="" \
+		CROSS_COMPILE=$(x86_64_cross_prefix) \
 		$(patsubst %,bin-i386-efi/%.efidrv,$(pxerom_targets)) \
 		$(patsubst %,bin-x86_64-efi/%.efidrv,$(pxerom_targets))
 
commit bcf06c15e7beb31a9839951ee24a809b6919a85e
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Sep 20 14:51:10 2013 +0200

    roms: add rules to build slof
    
    Add some logic to detect cross compilers.  Add support for "make slof",
    which should JustWork[tm] if you are on a ppx64 machine or have a ppc64
    cross compiler installed somewhere in your path.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/roms/Makefile b/roms/Makefile
index 9672625..5fcc77d 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -18,6 +18,21 @@ pxe-rom-virtio   efi-rom-virtio   : VID := 1af4
 pxe-rom-virtio   efi-rom-virtio   : DID := 1000
 
 #
+# cross compiler auto detection
+#
+path := $(subst :, ,$(PATH))
+system := $(shell uname -s | tr "A-Z" "a-z")
+
+# first find cross binutils in path
+find-cross-ld = $(firstword $(wildcard $(patsubst %,%/$(1)-*$(system)*-ld,$(path))))
+# then check we have cross gcc too
+find-cross-gcc = $(firstword $(wildcard $(patsubst %ld,%gcc,$(call find-cross-ld,$(1)))))
+# finally strip off path + toolname so we get the prefix
+find-cross-prefix = $(subst gcc,,$(notdir $(call find-cross-gcc,$(1))))
+
+powerpc64_cross_prefix := $(call find-cross-prefix,powerpc64)
+
+#
 # EfiRom utility is shipped with edk2 / tianocore, in BaseTools/
 #
 # We need that to combine multiple images (legacy bios,
@@ -37,6 +52,7 @@ default:
 	@echo "  pxerom         -- update nic roms (bios only)"
 	@echo "  efirom         -- update nic roms (bios+efi, this needs"
 	@echo "                    the EfiRom utility from edk2 / tianocore)"
+	@echo "  slof           -- update slof.bin"
 
 bios: config.seabios
 	sh configure-seabios.sh $<
@@ -90,8 +106,14 @@ ipxe/src/config/local/%: config.ipxe.%
 	cp $< $@
 
 
+slof:
+	$(MAKE) $(MAKEFLAGS) -C SLOF CROSS=$(powerpc64_cross_prefix) qemu
+	cp SLOF/boot_rom.bin ../pc-bios/slof.bin
+
+
 clean:
 	rm -rf seabios/.config seabios/out
 	$(MAKE) $(MAKEFLAGS) -C vgabios clean
 	rm -f vgabios/VGABIOS-lgpl-latest*
 	$(MAKE) $(MAKEFLAGS) -C ipxe/src veryclean
+	$(MAKE) $(MAKEFLAGS) -C SLOF clean
commit 93a2b3c470cbf1523478e8272816e3a22400775d
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Sep 23 10:24:10 2013 +0200

    roms: rewrite scripts/refresh-pxe-roms.sh
    
    Just use the Makefile in roms/
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/scripts/refresh-pxe-roms.sh b/scripts/refresh-pxe-roms.sh
index 14d5860..90fc0b3 100755
--- a/scripts/refresh-pxe-roms.sh
+++ b/scripts/refresh-pxe-roms.sh
@@ -21,79 +21,11 @@
 # Usage: Run from root of qemu tree
 # ./scripts/refresh-pxe-roms.sh
 
-QEMU_DIR=$PWD
-ROM_DIR="pc-bios"
-BUILD_DIR="roms/ipxe"
-LOCAL_CONFIG="src/config/local/general.h"
-
-function cleanup ()
-{
-    if [ -n "$SAVED_CONFIG" ]; then
-        cp "$SAVED_CONFIG" "$BUILD_DIR"/"$LOCAL_CONFIG"
-        rm "$SAVED_CONFIG"
-    fi
-    cd "$QEMU_DIR"
-}
-
-function make_rom ()
-{
-    cd "$BUILD_DIR"/src
-
-    BUILD_LOG=$(mktemp)
-
-    echo Building "$2"...
-    make bin/"$1".rom > "$BUILD_LOG" 2>&1
-    if [ $? -ne 0 ]; then
-        echo Build failed
-        tail --lines=100 "$BUILD_LOG"
-        rm "$BUILD_LOG"
-        cleanup
-        exit 1
-    fi
-    rm "$BUILD_LOG"
-
-    cp bin/"$1".rom "$QEMU_DIR"/"$ROM_DIR"/"$2"
-
-    cd "$QEMU_DIR"
-}
-
-if [ ! -d "$QEMU_DIR"/"$ROM_DIR" ]; then
-    echo "error: can't find $ROM_DIR directory," \
-         "run me from the root of the qemu tree"
-    exit 1
-fi
-
-if [ ! -d "$BUILD_DIR"/src ]; then
-    echo "error: $BUILD_DIR not populated, try:"
-    echo "  git submodule init $BUILD_DIR"
-    echo "  git submodule update $BUILD_DIR"
-    exit 1
-fi
-
-if [ -e "$BUILD_DIR"/"$LOCAL_CONFIG" ]; then
-    SAVED_CONFIG=$(mktemp)
-    cp "$BUILD_DIR"/"$LOCAL_CONFIG" "$SAVED_CONFIG"
-fi
-
-echo "#undef BANNER_TIMEOUT" > "$BUILD_DIR"/"$LOCAL_CONFIG"
-echo "#define BANNER_TIMEOUT 0" >> "$BUILD_DIR"/"$LOCAL_CONFIG"
-
-IPXE_VERSION=$(cd "$BUILD_DIR" && git describe --tags)
-if [ -z "$IPXE_VERSION" ]; then
-    echo "error: unable to retrieve git version"
-    cleanup
-    exit 1
+targets="pxerom"
+if test -x "$(which EfiRom 2>/dev/null)"; then
+    targets="$targets efirom"
 fi
 
-echo "#undef PRODUCT_NAME" >> "$BUILD_DIR"/"$LOCAL_CONFIG"
-echo "#define PRODUCT_NAME \"iPXE $IPXE_VERSION\"" >> "$BUILD_DIR"/"$LOCAL_CONFIG"
-
-make_rom 8086100e pxe-e1000.rom
-make_rom 80861209 pxe-eepro100.rom
-make_rom 10500940 pxe-ne2k_pci.rom
-make_rom 10222000 pxe-pcnet.rom
-make_rom 10ec8139 pxe-rtl8139.rom
-make_rom 1af41000 pxe-virtio.rom
-
-echo done
-cleanup
+cd roms
+make -j4 $targets || exit 1
+make clean
commit 46ef7f33a200a903dfcf7174ef5db4a09dc84f06
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Sep 20 15:26:26 2013 +0200

    roms: parallel ipxe builds
    
    Enable parallel ipxe builds.  Reduce the recursive make calls.  Call
    recursive make properly using $(MAKE) $(MAKEFLAGS).
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/roms/Makefile b/roms/Makefile
index 11d7837..9672625 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -2,6 +2,7 @@
 vgabios_variants := stdvga cirrus vmware qxl isavga
 vgabios_targets  := $(subst -isavga,,$(patsubst %,vgabios-%.bin,$(vgabios_variants)))
 pxerom_variants  := e1000 eepro100 ne2k_pci pcnet rtl8139 virtio
+pxerom_targets   := 8086100e 80861209 10500940 10222000 10ec8139 1af41000
 
 pxe-rom-e1000    efi-rom-e1000    : VID := 8086
 pxe-rom-e1000    efi-rom-e1000    : DID := 100e
@@ -64,22 +65,27 @@ build-lgplvgabios:
 
 pxerom: $(patsubst %,pxe-rom-%,$(pxerom_variants))
 
-pxe-rom-%: ipxe/src/config/local/general.h
-	make -C ipxe/src bin/$(VID)$(DID).rom
+pxe-rom-%: build-pxe-roms
 	cp ipxe/src/bin/$(VID)$(DID).rom ../pc-bios/pxe-$*.rom
 
 efirom: $(patsubst %,efi-rom-%,$(pxerom_variants))
 
-efi-rom-%: ipxe/src/config/local/general.h
-	make -C ipxe/src bin/$(VID)$(DID).rom
-	make -C ipxe/src bin-i386-efi/$(VID)$(DID).efidrv
-	make -C ipxe/src bin-x86_64-efi/$(VID)$(DID).efidrv
+efi-rom-%: build-pxe-roms build-efi-roms
 	$(EFIROM) -f "0x$(VID)" -i "0x$(DID)" -l 0x02 \
 		-b ipxe/src/bin/$(VID)$(DID).rom \
 		-ec ipxe/src/bin-i386-efi/$(VID)$(DID).efidrv \
 		-ec ipxe/src/bin-x86_64-efi/$(VID)$(DID).efidrv \
 		-o ../pc-bios/efi-$*.rom
 
+build-pxe-roms: ipxe/src/config/local/general.h
+	$(MAKE) $(MAKEFLAGS) -C ipxe/src GITVERSION="" \
+		$(patsubst %,bin/%.rom,$(pxerom_targets))
+
+build-efi-roms: build-pxe-roms ipxe/src/config/local/general.h
+	$(MAKE) $(MAKEFLAGS) -C ipxe/src GITVERSION="" \
+		$(patsubst %,bin-i386-efi/%.efidrv,$(pxerom_targets)) \
+		$(patsubst %,bin-x86_64-efi/%.efidrv,$(pxerom_targets))
+
 ipxe/src/config/local/%: config.ipxe.%
 	cp $< $@
 
commit 5a7bd33385f25ccd09725899b380e0c62f6d5733
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Sep 20 14:35:31 2013 +0200

    roms: build lgplvgabios isavga variant
    
    Add logic to also build+install the isavga vgabios variant.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/roms/Makefile b/roms/Makefile
index 6d4330f..11d7837 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -1,6 +1,6 @@
 
-vgabios_variants := stdvga cirrus vmware qxl
-vgabios_targets  := $(patsubst %,vgabios-%.bin,$(vgabios_variants))
+vgabios_variants := stdvga cirrus vmware qxl isavga
+vgabios_targets  := $(subst -isavga,,$(patsubst %,vgabios-%.bin,$(vgabios_variants)))
 pxerom_variants  := e1000 eepro100 ne2k_pci pcnet rtl8139 virtio
 
 pxe-rom-e1000    efi-rom-e1000    : VID := 8086
@@ -53,6 +53,8 @@ seavgabios-%: config.vga.%
 
 lgplvgabios: $(patsubst %,lgplvgabios-%,$(vgabios_variants))
 
+lgplvgabios-isavga: build-lgplvgabios
+	cp vgabios/VGABIOS-lgpl-latest.bin ../pc-bios/vgabios.bin
 lgplvgabios-%: build-lgplvgabios
 	cp vgabios/VGABIOS-lgpl-latest.$*.bin ../pc-bios/vgabios-$*.bin
 
commit 1ede4dd04b4f16a281a92d6a44905c63fb1635cf
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Sep 20 14:29:29 2013 +0200

    roms: enable parallel builds for 'make lgplvgabios'
    
    Recurse into vgabios once, adjust dependencies, call make using
    $(MAKE) $(MAKEFLAGS) so jobserver mode works.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/roms/Makefile b/roms/Makefile
index b646060..6d4330f 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -1,5 +1,6 @@
 
 vgabios_variants := stdvga cirrus vmware qxl
+vgabios_targets  := $(patsubst %,vgabios-%.bin,$(vgabios_variants))
 pxerom_variants  := e1000 eepro100 ne2k_pci pcnet rtl8139 virtio
 
 pxe-rom-e1000    efi-rom-e1000    : VID := 8086
@@ -49,12 +50,16 @@ seavgabios-%: config.vga.%
 	make -C seabios out/vgabios.bin
 	cp seabios/out/vgabios.bin ../pc-bios/vgabios-$*.bin
 
+
 lgplvgabios: $(patsubst %,lgplvgabios-%,$(vgabios_variants))
 
-lgplvgabios-%:
-	make -C vgabios vgabios-$*.bin
+lgplvgabios-%: build-lgplvgabios
 	cp vgabios/VGABIOS-lgpl-latest.$*.bin ../pc-bios/vgabios-$*.bin
 
+build-lgplvgabios:
+	$(MAKE) $(MAKEFLAGS) -C vgabios $(vgabios_targets)
+
+
 pxerom: $(patsubst %,pxe-rom-%,$(pxerom_variants))
 
 pxe-rom-%: ipxe/src/config/local/general.h
commit 6887581728c9eddf858e7458b6eacbfe3ac68302
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Sep 20 15:34:27 2013 +0200

    roms: add 'make clean'
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/roms/Makefile b/roms/Makefile
index 7a228ae..b646060 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -75,3 +75,10 @@ efi-rom-%: ipxe/src/config/local/general.h
 
 ipxe/src/config/local/%: config.ipxe.%
 	cp $< $@
+
+
+clean:
+	rm -rf seabios/.config seabios/out
+	$(MAKE) $(MAKEFLAGS) -C vgabios clean
+	rm -f vgabios/VGABIOS-lgpl-latest*
+	$(MAKE) $(MAKEFLAGS) -C ipxe/src veryclean
commit e26d3e734650640fabd7d95ace4f3a6f88725e0b
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Aug 16 15:18:32 2013 +0200

    smbios: Factor out smbios_maybe_add_str()
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c
index d2dba6c..d3f1ee6 100644
--- a/hw/i386/smbios.c
+++ b/hw/i386/smbios.c
@@ -210,21 +210,22 @@ static void smbios_add_field(int type, int offset, const void *data, size_t len)
             cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
 }
 
-static void smbios_build_type_0_fields(void)
+static void smbios_maybe_add_str(int type, int offset, const char *data)
 {
-    if (type0.vendor) {
-        smbios_add_field(0, offsetof(struct smbios_type_0, vendor_str),
-                         type0.vendor, strlen(type0.vendor) + 1);
-    }
-    if (type0.version) {
-        smbios_add_field(0, offsetof(struct smbios_type_0, bios_version_str),
-                         type0.version, strlen(type0.version) + 1);
+    if (data) {
+        smbios_add_field(type, offset, data, strlen(data) + 1);
     }
-    if (type0.date) {
-        smbios_add_field(0, offsetof(struct smbios_type_0,
+}
+
+static void smbios_build_type_0_fields(void)
+{
+    smbios_maybe_add_str(0, offsetof(struct smbios_type_0, vendor_str),
+                         type0.vendor);
+    smbios_maybe_add_str(0, offsetof(struct smbios_type_0, bios_version_str),
+                         type0.version);
+    smbios_maybe_add_str(0, offsetof(struct smbios_type_0,
                                      bios_release_date_str),
-                         type0.date, strlen(type0.date) + 1);
-    }
+                         type0.date);
     if (type0.have_major_minor) {
         smbios_add_field(0, offsetof(struct smbios_type_0,
                                      system_bios_major_release),
@@ -237,30 +238,18 @@ static void smbios_build_type_0_fields(void)
 
 static void smbios_build_type_1_fields(void)
 {
-    if (type1.manufacturer) {
-        smbios_add_field(1, offsetof(struct smbios_type_1, manufacturer_str),
-                         type1.manufacturer, strlen(type1.manufacturer) + 1);
-    }
-    if (type1.product) {
-        smbios_add_field(1, offsetof(struct smbios_type_1, product_name_str),
-                         type1.product, strlen(type1.product) + 1);
-    }
-    if (type1.version) {
-        smbios_add_field(1, offsetof(struct smbios_type_1, version_str),
-                         type1.version, strlen(type1.version) + 1);
-    }
-    if (type1.serial) {
-        smbios_add_field(1, offsetof(struct smbios_type_1, serial_number_str),
-                         type1.serial, strlen(type1.serial) + 1);
-    }
-    if (type1.sku) {
-        smbios_add_field(1, offsetof(struct smbios_type_1, sku_number_str),
-                         type1.sku, strlen(type1.sku) + 1);
-    }
-    if (type1.family) {
-        smbios_add_field(1, offsetof(struct smbios_type_1, family_str),
-                         type1.family, strlen(type1.family) + 1);
-    }
+    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, manufacturer_str),
+                         type1.manufacturer);
+    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, product_name_str),
+                         type1.product);
+    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, version_str),
+                         type1.version);
+    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, serial_number_str),
+                         type1.serial);
+    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, sku_number_str),
+                         type1.sku);
+    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, family_str),
+                         type1.family);
     if (qemu_uuid_set) {
         smbios_add_field(1, offsetof(struct smbios_type_1, uuid),
                          qemu_uuid, 16);
commit fc3b32958a80bca13309e2695de07b43dd788421
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Aug 16 15:18:31 2013 +0200

    smbios: Make multiple -smbios type= accumulate sanely
    
    Currently, -smbios type=T,NAME=VAL,... adds one field (T,NAME) with
    value VAL to fw_cfg for each unique NAME.  If NAME occurs multiple
    times, the last one's VAL is used (before the QemuOpts conversion, the
    first one was used).
    
    Multiple -smbios can add multiple fields with the same (T, NAME).
    SeaBIOS reads all of them from fw_cfg, but uses only the first field
    (T, NAME).  The others are ignored.
    
    "First one wins, subsequent ones get ignored silently" isn't nice.  We
    commonly let the last option win.  Useful, because it lets you
    -readconfig first, then selectively override with command line
    options.
    
    Clean up -smbios to work the common way.  Accumulate the settings,
    with later ones overwriting earlier ones.  Put the result into fw_cfg
    (no more useless duplicates).
    
    Bonus cleanup: qemu_uuid_parse() no longer sets SMBIOS system uuid by
    side effect.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 62f1118..150647b 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -1113,9 +1113,6 @@ int qemu_uuid_parse(const char *str, uint8_t *uuid)
     if (ret != 16) {
         return -1;
     }
-#ifdef TARGET_I386
-    smbios_add_field(1, offsetof(struct smbios_type_1, uuid), uuid, 16);
-#endif
     return 0;
 }
 
diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c
index 4263551..d2dba6c 100644
--- a/hw/i386/smbios.c
+++ b/hw/i386/smbios.c
@@ -47,6 +47,7 @@ struct smbios_table {
 static uint8_t *smbios_entries;
 static size_t smbios_entries_len;
 static int smbios_type4_count = 0;
+static bool smbios_immutable;
 
 static struct {
     bool seen;
@@ -54,6 +55,17 @@ static struct {
     Location loc;
 } first_opt[2];
 
+static struct {
+    const char *vendor, *version, *date;
+    bool have_major_minor;
+    uint8_t major, minor;
+} type0;
+
+static struct {
+    const char *manufacturer, *product, *version, *serial, *sku, *family;
+    /* uuid is in qemu_uuid[] */
+} type1;
+
 static QemuOptsList qemu_smbios_opts = {
     .name = "smbios",
     .head = QTAILQ_HEAD_INITIALIZER(qemu_smbios_opts.head),
@@ -152,13 +164,6 @@ static void smbios_validate_table(void)
     }
 }
 
-uint8_t *smbios_get_table(size_t *length)
-{
-    smbios_validate_table();
-    *length = smbios_entries_len;
-    return smbios_entries;
-}
-
 /*
  * To avoid unresolvable overlaps in data, don't allow both
  * tables and fields for the same smbios type.
@@ -182,12 +187,10 @@ static void smbios_check_collision(int type, int entry)
     }
 }
 
-void smbios_add_field(int type, int offset, const void *data, size_t len)
+static void smbios_add_field(int type, int offset, const void *data, size_t len)
 {
     struct smbios_field *field;
 
-    smbios_check_collision(type, SMBIOS_FIELD_ENTRY);
-
     if (!smbios_entries) {
         smbios_entries_len = sizeof(uint16_t);
         smbios_entries = g_malloc0(smbios_entries_len);
@@ -207,82 +210,81 @@ void smbios_add_field(int type, int offset, const void *data, size_t len)
             cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
 }
 
-static void smbios_build_type_0_fields(QemuOpts *opts)
+static void smbios_build_type_0_fields(void)
 {
-    const char *val;
-    unsigned char major, minor;
-
-    val = qemu_opt_get(opts, "vendor");
-    if (val) {
+    if (type0.vendor) {
         smbios_add_field(0, offsetof(struct smbios_type_0, vendor_str),
-                         val, strlen(val) + 1);
+                         type0.vendor, strlen(type0.vendor) + 1);
     }
-    val = qemu_opt_get(opts, "version");
-    if (val) {
+    if (type0.version) {
         smbios_add_field(0, offsetof(struct smbios_type_0, bios_version_str),
-                         val, strlen(val) + 1);
+                         type0.version, strlen(type0.version) + 1);
     }
-    val = qemu_opt_get(opts, "date");
-    if (val) {
+    if (type0.date) {
         smbios_add_field(0, offsetof(struct smbios_type_0,
                                      bios_release_date_str),
-                         val, strlen(val) + 1);
+                         type0.date, strlen(type0.date) + 1);
     }
-    val = qemu_opt_get(opts, "release");
-    if (val) {
-        if (sscanf(val, "%hhu.%hhu", &major, &minor) != 2) {
-            error_report("Invalid release");
-            exit(1);
-        }
+    if (type0.have_major_minor) {
         smbios_add_field(0, offsetof(struct smbios_type_0,
                                      system_bios_major_release),
-                         &major, 1);
+                         &type0.major, 1);
         smbios_add_field(0, offsetof(struct smbios_type_0,
                                      system_bios_minor_release),
-                         &minor, 1);
+                         &type0.minor, 1);
     }
 }
 
-static void smbios_build_type_1_fields(QemuOpts *opts)
+static void smbios_build_type_1_fields(void)
 {
-    const char *val;
-
-    val = qemu_opt_get(opts, "manufacturer");
-    if (val) {
+    if (type1.manufacturer) {
         smbios_add_field(1, offsetof(struct smbios_type_1, manufacturer_str),
-                         val, strlen(val) + 1);
+                         type1.manufacturer, strlen(type1.manufacturer) + 1);
     }
-    val = qemu_opt_get(opts, "product");
-    if (val) {
+    if (type1.product) {
         smbios_add_field(1, offsetof(struct smbios_type_1, product_name_str),
-                         val, strlen(val) + 1);
+                         type1.product, strlen(type1.product) + 1);
     }
-    val = qemu_opt_get(opts, "version");
-    if (val) {
+    if (type1.version) {
         smbios_add_field(1, offsetof(struct smbios_type_1, version_str),
-                         val, strlen(val) + 1);
+                         type1.version, strlen(type1.version) + 1);
     }
-    val = qemu_opt_get(opts, "serial");
-    if (val) {
+    if (type1.serial) {
         smbios_add_field(1, offsetof(struct smbios_type_1, serial_number_str),
-                         val, strlen(val) + 1);
-    }
-    val = qemu_opt_get(opts, "uuid");
-    if (val) {
-        if (qemu_uuid_parse(val, qemu_uuid) != 0) {
-            error_report("Invalid UUID");
-            exit(1);
-        }
+                         type1.serial, strlen(type1.serial) + 1);
     }
-    val = qemu_opt_get(opts, "sku");
-    if (val) {
+    if (type1.sku) {
         smbios_add_field(1, offsetof(struct smbios_type_1, sku_number_str),
-                         val, strlen(val) + 1);
+                         type1.sku, strlen(type1.sku) + 1);
     }
-    val = qemu_opt_get(opts, "family");
-    if (val) {
+    if (type1.family) {
         smbios_add_field(1, offsetof(struct smbios_type_1, family_str),
-                         val, strlen(val) + 1);
+                         type1.family, strlen(type1.family) + 1);
+    }
+    if (qemu_uuid_set) {
+        smbios_add_field(1, offsetof(struct smbios_type_1, uuid),
+                         qemu_uuid, 16);
+    }
+}
+
+uint8_t *smbios_get_table(size_t *length)
+{
+    if (!smbios_immutable) {
+        smbios_build_type_0_fields();
+        smbios_build_type_1_fields();
+        smbios_validate_table();
+        smbios_immutable = true;
+    }
+    *length = smbios_entries_len;
+    return smbios_entries;
+}
+
+static void save_opt(const char **dest, QemuOpts *opts, const char *name)
+{
+    const char *val = qemu_opt_get(opts, name);
+
+    if (val) {
+        *dest = val;
     }
 }
 
@@ -291,6 +293,7 @@ void smbios_entry_add(QemuOpts *opts)
     Error *local_err = NULL;
     const char *val;
 
+    assert(!smbios_immutable);
     val = qemu_opt_get(opts, "file");
     if (val) {
         struct smbios_structure_header *header;
@@ -341,6 +344,8 @@ void smbios_entry_add(QemuOpts *opts)
     if (val) {
         unsigned long type = strtoul(val, NULL, 0);
 
+        smbios_check_collision(type, SMBIOS_FIELD_ENTRY);
+
         switch (type) {
         case 0:
             qemu_opts_validate(opts, qemu_smbios_type0_opts, &local_err);
@@ -348,7 +353,18 @@ void smbios_entry_add(QemuOpts *opts)
                 error_report("%s", error_get_pretty(local_err));
                 exit(1);
             }
-            smbios_build_type_0_fields(opts);
+            save_opt(&type0.vendor, opts, "vendor");
+            save_opt(&type0.version, opts, "version");
+            save_opt(&type0.date, opts, "date");
+
+            val = qemu_opt_get(opts, "release");
+            if (val) {
+                if (sscanf(val, "%hhu.%hhu", &type0.major, &type0.minor) != 2) {
+                    error_report("Invalid release");
+                    exit(1);
+                }
+                type0.have_major_minor = true;
+            }
             return;
         case 1:
             qemu_opts_validate(opts, qemu_smbios_type1_opts, &local_err);
@@ -356,7 +372,21 @@ void smbios_entry_add(QemuOpts *opts)
                 error_report("%s", error_get_pretty(local_err));
                 exit(1);
             }
-            smbios_build_type_1_fields(opts);
+            save_opt(&type1.manufacturer, opts, "manufacturer");
+            save_opt(&type1.product, opts, "product");
+            save_opt(&type1.version, opts, "version");
+            save_opt(&type1.serial, opts, "serial");
+            save_opt(&type1.sku, opts, "sku");
+            save_opt(&type1.family, opts, "family");
+
+            val = qemu_opt_get(opts, "uuid");
+            if (val) {
+                if (qemu_uuid_parse(val, qemu_uuid) != 0) {
+                    error_report("Invalid UUID");
+                    exit(1);
+                }
+                qemu_uuid_set = true;
+            }
             return;
         default:
             error_report("Don't know how to build fields for SMBIOS type %ld",
diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h
index d9f43b7..b08ec71 100644
--- a/include/hw/i386/smbios.h
+++ b/include/hw/i386/smbios.h
@@ -16,7 +16,6 @@
 #include "qemu/option.h"
 
 void smbios_entry_add(QemuOpts *opts);
-void smbios_add_field(int type, int offset, const void *data, size_t len);
 uint8_t *smbios_get_table(size_t *length);
 
 /*
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index b1aa059..4257736 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -16,6 +16,7 @@ extern const char *bios_name;
 
 extern const char *qemu_name;
 extern uint8_t qemu_uuid[];
+extern bool qemu_uuid_set;
 int qemu_uuid_parse(const char *str, uint8_t *uuid);
 #define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
 
diff --git a/vl.c b/vl.c
index 503f903..fb8006e 100644
--- a/vl.c
+++ b/vl.c
@@ -254,6 +254,7 @@ uint64_t node_mem[MAX_NODES];
 unsigned long *node_cpumask[MAX_NODES];
 
 uint8_t qemu_uuid[16];
+bool qemu_uuid_set;
 
 static QEMUBootSetHandler *boot_set_handler;
 static void *boot_set_opaque;
@@ -3588,6 +3589,7 @@ int main(int argc, char **argv, char **envp)
                             " Wrong format.\n");
                     exit(1);
                 }
+                qemu_uuid_set = true;
                 break;
 	    case QEMU_OPTION_option_rom:
 		if (nb_option_roms >= MAX_OPTION_ROMS) {
commit ec2df8c10a4585ba4641ae482cf2f5f13daa810e
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Aug 16 15:18:30 2013 +0200

    smbios: Improve diagnostics for conflicting entries
    
    We allow either tables or fields for the same type.  Makes sense,
    because SeaBIOS uses fields only when no tables are present.
    
    We do this by searching the SMBIOS blob for a previously added table
    or field.  Error messages look like this:
    
        qemu-system-x86_64: -smbios type=1,serial=42: SMBIOS type 1 table already defined, cannot add field
    
    User needs to know that "table" is defined by -smbios file=..., and
    "field" by -smbios type=...
    
    Instead of searching the blob, record additions of interest, and check
    that.  Simpler, and makes better error messages possible:
    
        qemu-system-x86_64: -smbios file=smbios_type_1.bin: Can't mix file= and type= for same type
        qemu-system-x86_64: -smbios type=1,serial=42,serial=99: This is the conflicting setting
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c
index abfd6f7..4263551 100644
--- a/hw/i386/smbios.c
+++ b/hw/i386/smbios.c
@@ -48,6 +48,12 @@ static uint8_t *smbios_entries;
 static size_t smbios_entries_len;
 static int smbios_type4_count = 0;
 
+static struct {
+    bool seen;
+    int headertype;
+    Location loc;
+} first_opt[2];
+
 static QemuOptsList qemu_smbios_opts = {
     .name = "smbios",
     .head = QTAILQ_HEAD_INITIALIZER(qemu_smbios_opts.head),
@@ -159,35 +165,20 @@ uint8_t *smbios_get_table(size_t *length)
  */
 static void smbios_check_collision(int type, int entry)
 {
-    uint16_t *num_entries = (uint16_t *)smbios_entries;
-    struct smbios_header *header;
-    char *p;
-    int i;
-
-    if (!num_entries)
-        return;
-
-    p = (char *)(num_entries + 1);
-
-    for (i = 0; i < *num_entries; i++) {
-        header = (struct smbios_header *)p;
-        if (entry == SMBIOS_TABLE_ENTRY && header->type == SMBIOS_FIELD_ENTRY) {
-            struct smbios_field *field = (void *)header;
-            if (type == field->type) {
-                error_report("SMBIOS type %d field already defined, "
-                             "cannot add table", type);
-                exit(1);
-            }
-        } else if (entry == SMBIOS_FIELD_ENTRY &&
-                   header->type == SMBIOS_TABLE_ENTRY) {
-            struct smbios_structure_header *table = (void *)(header + 1);
-            if (type == table->type) {
-                error_report("SMBIOS type %d table already defined, "
-                             "cannot add field", type);
+    if (type < ARRAY_SIZE(first_opt)) {
+        if (first_opt[type].seen) {
+            if (first_opt[type].headertype != entry) {
+                error_report("Can't mix file= and type= for same type");
+                loc_push_restore(&first_opt[type].loc);
+                error_report("This is the conflicting setting");
+                loc_pop(&first_opt[type].loc);
                 exit(1);
             }
+        } else {
+            first_opt[type].seen = true;
+            first_opt[type].headertype = entry;
+            loc_save(&first_opt[type].loc);
         }
-        p += le16_to_cpu(header->length);
     }
 }
 
commit 4f953d2fc806f1ba6fa76f01dfd121fe7d0dc4a7
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Aug 16 15:18:29 2013 +0200

    smbios: Convert to QemuOpts
    
    So that it can be set in config file for -readconfig.
    
    This tightens parsing of -smbios, and makes it more consistent with
    other options: unknown parameters are rejected, numbers with trailing
    junk are rejected, when a parameter is given multiple times, last
    rather than first wins, ...
    
    MST: drop one chunk to fix build errors
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 6ae8eb6..62f1118 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -1134,10 +1134,10 @@ void do_acpitable_option(const QemuOpts *opts)
 #endif
 }
 
-void do_smbios_option(const char *optarg)
+void do_smbios_option(QemuOpts *opts)
 {
 #ifdef TARGET_I386
-    smbios_entry_add(optarg);
+    smbios_entry_add(opts);
 #endif
 }
 
diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c
index 0608aee..abfd6f7 100644
--- a/hw/i386/smbios.c
+++ b/hw/i386/smbios.c
@@ -2,9 +2,11 @@
  * SMBIOS Support
  *
  * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2013 Red Hat, Inc.
  *
  * Authors:
  *  Alex Williamson <alex.williamson at hp.com>
+ *  Markus Armbruster <armbru 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.
@@ -13,6 +15,7 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
+#include "qemu/config-file.h"
 #include "qemu/error-report.h"
 #include "sysemu/sysemu.h"
 #include "hw/i386/smbios.h"
@@ -41,11 +44,100 @@ struct smbios_table {
 #define SMBIOS_FIELD_ENTRY 0
 #define SMBIOS_TABLE_ENTRY 1
 
-
 static uint8_t *smbios_entries;
 static size_t smbios_entries_len;
 static int smbios_type4_count = 0;
 
+static QemuOptsList qemu_smbios_opts = {
+    .name = "smbios",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_smbios_opts.head),
+    .desc = {
+        /*
+         * no elements => accept any params
+         * validation will happen later
+         */
+        { /* end of list */ }
+    }
+};
+
+static const QemuOptDesc qemu_smbios_file_opts[] = {
+    {
+        .name = "file",
+        .type = QEMU_OPT_STRING,
+        .help = "binary file containing an SMBIOS element",
+    },
+    { /* end of list */ }
+};
+
+static const QemuOptDesc qemu_smbios_type0_opts[] = {
+    {
+        .name = "type",
+        .type = QEMU_OPT_NUMBER,
+        .help = "SMBIOS element type",
+    },{
+        .name = "vendor",
+        .type = QEMU_OPT_STRING,
+        .help = "vendor name",
+    },{
+        .name = "version",
+        .type = QEMU_OPT_STRING,
+        .help = "version number",
+    },{
+        .name = "date",
+        .type = QEMU_OPT_STRING,
+        .help = "release date",
+    },{
+        .name = "release",
+        .type = QEMU_OPT_STRING,
+        .help = "revision number",
+    },
+    { /* end of list */ }
+};
+
+static const QemuOptDesc qemu_smbios_type1_opts[] = {
+    {
+        .name = "type",
+        .type = QEMU_OPT_NUMBER,
+        .help = "SMBIOS element type",
+    },{
+        .name = "manufacturer",
+        .type = QEMU_OPT_STRING,
+        .help = "manufacturer name",
+    },{
+        .name = "product",
+        .type = QEMU_OPT_STRING,
+        .help = "product name",
+    },{
+        .name = "version",
+        .type = QEMU_OPT_STRING,
+        .help = "version number",
+    },{
+        .name = "serial",
+        .type = QEMU_OPT_STRING,
+        .help = "serial number",
+    },{
+        .name = "uuid",
+        .type = QEMU_OPT_STRING,
+        .help = "UUID",
+    },{
+        .name = "sku",
+        .type = QEMU_OPT_STRING,
+        .help = "SKU number",
+    },{
+        .name = "family",
+        .type = QEMU_OPT_STRING,
+        .help = "family name",
+    },
+    { /* end of list */ }
+};
+
+static void smbios_register_config(void)
+{
+    qemu_add_opts(&qemu_smbios_opts);
+}
+
+machine_init(smbios_register_config);
+
 static void smbios_validate_table(void)
 {
     if (smbios_type4_count && smbios_type4_count != smp_cpus) {
@@ -124,23 +216,30 @@ void smbios_add_field(int type, int offset, const void *data, size_t len)
             cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
 }
 
-static void smbios_build_type_0_fields(const char *t)
+static void smbios_build_type_0_fields(QemuOpts *opts)
 {
-    char buf[1024];
+    const char *val;
     unsigned char major, minor;
 
-    if (get_param_value(buf, sizeof(buf), "vendor", t))
+    val = qemu_opt_get(opts, "vendor");
+    if (val) {
         smbios_add_field(0, offsetof(struct smbios_type_0, vendor_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "version", t))
+                         val, strlen(val) + 1);
+    }
+    val = qemu_opt_get(opts, "version");
+    if (val) {
         smbios_add_field(0, offsetof(struct smbios_type_0, bios_version_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "date", t))
+                         val, strlen(val) + 1);
+    }
+    val = qemu_opt_get(opts, "date");
+    if (val) {
         smbios_add_field(0, offsetof(struct smbios_type_0,
                                      bios_release_date_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "release", t)) {
-        if (sscanf(buf, "%hhu.%hhu", &major, &minor) != 2) {
+                         val, strlen(val) + 1);
+    }
+    val = qemu_opt_get(opts, "release");
+    if (val) {
+        if (sscanf(val, "%hhu.%hhu", &major, &minor) != 2) {
             error_report("Invalid release");
             exit(1);
         }
@@ -153,47 +252,69 @@ static void smbios_build_type_0_fields(const char *t)
     }
 }
 
-static void smbios_build_type_1_fields(const char *t)
+static void smbios_build_type_1_fields(QemuOpts *opts)
 {
-    char buf[1024];
+    const char *val;
 
-    if (get_param_value(buf, sizeof(buf), "manufacturer", t))
+    val = qemu_opt_get(opts, "manufacturer");
+    if (val) {
         smbios_add_field(1, offsetof(struct smbios_type_1, manufacturer_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "product", t))
+                         val, strlen(val) + 1);
+    }
+    val = qemu_opt_get(opts, "product");
+    if (val) {
         smbios_add_field(1, offsetof(struct smbios_type_1, product_name_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "version", t))
+                         val, strlen(val) + 1);
+    }
+    val = qemu_opt_get(opts, "version");
+    if (val) {
         smbios_add_field(1, offsetof(struct smbios_type_1, version_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "serial", t))
+                         val, strlen(val) + 1);
+    }
+    val = qemu_opt_get(opts, "serial");
+    if (val) {
         smbios_add_field(1, offsetof(struct smbios_type_1, serial_number_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "uuid", t)) {
-        if (qemu_uuid_parse(buf, qemu_uuid) != 0) {
+                         val, strlen(val) + 1);
+    }
+    val = qemu_opt_get(opts, "uuid");
+    if (val) {
+        if (qemu_uuid_parse(val, qemu_uuid) != 0) {
             error_report("Invalid UUID");
             exit(1);
         }
     }
-    if (get_param_value(buf, sizeof(buf), "sku", t))
+    val = qemu_opt_get(opts, "sku");
+    if (val) {
         smbios_add_field(1, offsetof(struct smbios_type_1, sku_number_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "family", t))
+                         val, strlen(val) + 1);
+    }
+    val = qemu_opt_get(opts, "family");
+    if (val) {
         smbios_add_field(1, offsetof(struct smbios_type_1, family_str),
-                         buf, strlen(buf) + 1);
+                         val, strlen(val) + 1);
+    }
 }
 
-void smbios_entry_add(const char *t)
+void smbios_entry_add(QemuOpts *opts)
 {
-    char buf[1024];
+    Error *local_err = NULL;
+    const char *val;
 
-    if (get_param_value(buf, sizeof(buf), "file", t)) {
+    val = qemu_opt_get(opts, "file");
+    if (val) {
         struct smbios_structure_header *header;
         struct smbios_table *table;
-        int size = get_image_size(buf);
+        int size;
+
+        qemu_opts_validate(opts, qemu_smbios_file_opts, &local_err);
+        if (local_err) {
+            error_report("%s", error_get_pretty(local_err));
+            exit(1);
+        }
 
+        size = get_image_size(val);
         if (size == -1 || size < sizeof(struct smbios_structure_header)) {
-            error_report("Cannot read SMBIOS file %s", buf);
+            error_report("Cannot read SMBIOS file %s", val);
             exit(1);
         }
 
@@ -208,8 +329,8 @@ void smbios_entry_add(const char *t)
         table->header.type = SMBIOS_TABLE_ENTRY;
         table->header.length = cpu_to_le16(sizeof(*table) + size);
 
-        if (load_image(buf, table->data) != size) {
-            error_report("Failed to load SMBIOS file %s", buf);
+        if (load_image(val, table->data) != size) {
+            error_report("Failed to load SMBIOS file %s", val);
             exit(1);
         }
 
@@ -225,14 +346,26 @@ void smbios_entry_add(const char *t)
         return;
     }
 
-    if (get_param_value(buf, sizeof(buf), "type", t)) {
-        unsigned long type = strtoul(buf, NULL, 0);
+    val = qemu_opt_get(opts, "type");
+    if (val) {
+        unsigned long type = strtoul(val, NULL, 0);
+
         switch (type) {
         case 0:
-            smbios_build_type_0_fields(t);
+            qemu_opts_validate(opts, qemu_smbios_type0_opts, &local_err);
+            if (local_err) {
+                error_report("%s", error_get_pretty(local_err));
+                exit(1);
+            }
+            smbios_build_type_0_fields(opts);
             return;
         case 1:
-            smbios_build_type_1_fields(t);
+            qemu_opts_validate(opts, qemu_smbios_type1_opts, &local_err);
+            if (local_err) {
+                error_report("%s", error_get_pretty(local_err));
+                exit(1);
+            }
+            smbios_build_type_1_fields(opts);
             return;
         default:
             error_report("Don't know how to build fields for SMBIOS type %ld",
diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h
index 56c6108..d9f43b7 100644
--- a/include/hw/i386/smbios.h
+++ b/include/hw/i386/smbios.h
@@ -13,7 +13,9 @@
  *
  */
 
-void smbios_entry_add(const char *t);
+#include "qemu/option.h"
+
+void smbios_entry_add(QemuOpts *opts);
 void smbios_add_field(int type, int offset, const void *data, size_t len);
 uint8_t *smbios_get_table(size_t *length);
 
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index dece913..be71bca 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -28,7 +28,7 @@ extern const uint32_t arch_type;
 
 void select_soundhw(const char *optarg);
 void do_acpitable_option(const QemuOpts *opts);
-void do_smbios_option(const char *optarg);
+void do_smbios_option(QemuOpts *opts);
 void cpudef_init(void);
 void audio_init(void);
 int tcg_available(void);
diff --git a/vl.c b/vl.c
index 4e709d5..503f903 100644
--- a/vl.c
+++ b/vl.c
@@ -3491,7 +3491,8 @@ int main(int argc, char **argv, char **envp)
                 do_acpitable_option(opts);
                 break;
             case QEMU_OPTION_smbios:
-                do_smbios_option(optarg);
+                opts = qemu_opts_parse(qemu_find_opts("smbios"), optarg, 0);
+                do_smbios_option(opts);
                 break;
             case QEMU_OPTION_enable_kvm:
                 olist = qemu_find_opts("machine");
commit 351a6a73ca7a9123f0dfd6c6f85fd01e82fe3741
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Aug 16 15:18:28 2013 +0200

    smbios: Normalize smbios_entry_add()'s error handling to exit(1)
    
    It exits on all error conditions but one, where it returns -1.
    Normalize, and return void.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index e47e139..6ae8eb6 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -1137,9 +1137,7 @@ void do_acpitable_option(const QemuOpts *opts)
 void do_smbios_option(const char *optarg)
 {
 #ifdef TARGET_I386
-    if (smbios_entry_add(optarg) < 0) {
-        exit(1);
-    }
+    smbios_entry_add(optarg);
 #endif
 }
 
diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c
index e708cb8..0608aee 100644
--- a/hw/i386/smbios.c
+++ b/hw/i386/smbios.c
@@ -183,7 +183,7 @@ static void smbios_build_type_1_fields(const char *t)
                          buf, strlen(buf) + 1);
 }
 
-int smbios_entry_add(const char *t)
+void smbios_entry_add(const char *t)
 {
     char buf[1024];
 
@@ -222,7 +222,7 @@ int smbios_entry_add(const char *t)
         smbios_entries_len += sizeof(*table) + size;
         (*(uint16_t *)smbios_entries) =
                 cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
-        return 0;
+        return;
     }
 
     if (get_param_value(buf, sizeof(buf), "type", t)) {
@@ -230,10 +230,10 @@ int smbios_entry_add(const char *t)
         switch (type) {
         case 0:
             smbios_build_type_0_fields(t);
-            return 0;
+            return;
         case 1:
             smbios_build_type_1_fields(t);
-            return 0;
+            return;
         default:
             error_report("Don't know how to build fields for SMBIOS type %ld",
                          type);
@@ -242,5 +242,5 @@ int smbios_entry_add(const char *t)
     }
 
     error_report("Must specify type= or file=");
-    return -1;
+    exit(1);
 }
diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h
index 9babeaf..56c6108 100644
--- a/include/hw/i386/smbios.h
+++ b/include/hw/i386/smbios.h
@@ -13,7 +13,7 @@
  *
  */
 
-int smbios_entry_add(const char *t);
+void smbios_entry_add(const char *t);
 void smbios_add_field(int type, int offset, const void *data, size_t len);
 uint8_t *smbios_get_table(size_t *length);
 
commit 61653008adad45026464f962759112995802fe01
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Sep 27 13:36:11 2013 +0200

    qcow2: Remove useless count_contiguous_clusters() parameter
    
    All callers pass start = 0, and it's doubtful if any other value would
    actually do what you expect. Remove the parameter.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Jeff Cody <jcody at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index f93960f..39323ac 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -281,7 +281,7 @@ fail:
  * cluster which may require a different handling)
  */
 static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size,
-        uint64_t *l2_table, uint64_t start, uint64_t stop_flags)
+        uint64_t *l2_table, uint64_t stop_flags)
 {
     int i;
     uint64_t mask = stop_flags | L2E_OFFSET_MASK | QCOW2_CLUSTER_COMPRESSED;
@@ -293,14 +293,14 @@ static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size,
 
     assert(qcow2_get_cluster_type(first_entry) != QCOW2_CLUSTER_COMPRESSED);
 
-    for (i = start; i < start + nb_clusters; i++) {
+    for (i = 0; i < nb_clusters; i++) {
         uint64_t l2_entry = be64_to_cpu(l2_table[i]) & mask;
         if (offset + (uint64_t) i * cluster_size != l2_entry) {
             break;
         }
     }
 
-	return (i - start);
+	return i;
 }
 
 static int count_contiguous_free_clusters(uint64_t nb_clusters, uint64_t *l2_table)
@@ -493,7 +493,7 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
             return -EIO;
         }
         c = count_contiguous_clusters(nb_clusters, s->cluster_size,
-                &l2_table[l2_index], 0, QCOW_OFLAG_ZERO);
+                &l2_table[l2_index], QCOW_OFLAG_ZERO);
         *cluster_offset = 0;
         break;
     case QCOW2_CLUSTER_UNALLOCATED:
@@ -504,7 +504,7 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
     case QCOW2_CLUSTER_NORMAL:
         /* how many allocated clusters ? */
         c = count_contiguous_clusters(nb_clusters, s->cluster_size,
-                &l2_table[l2_index], 0, QCOW_OFLAG_ZERO);
+                &l2_table[l2_index], QCOW_OFLAG_ZERO);
         *cluster_offset &= L2E_OFFSET_MASK;
         break;
     default:
@@ -934,7 +934,7 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
         /* We keep all QCOW_OFLAG_COPIED clusters */
         keep_clusters =
             count_contiguous_clusters(nb_clusters, s->cluster_size,
-                                      &l2_table[l2_index], 0,
+                                      &l2_table[l2_index],
                                       QCOW_OFLAG_COPIED | QCOW_OFLAG_ZERO);
         assert(keep_clusters <= nb_clusters);
 
commit 22f0dd29afd6011b2b7a94bf860502eafce4ddd5
Author: Max Reitz <mreitz at redhat.com>
Date:   Fri Sep 27 12:14:16 2013 +0200

    qcow2: COMPRESSED on count_contiguous_clusters
    
    Compressed clusters can never be contiguous, therefore the corresponding
    flag does not need to be given explicitly to count_contiguous_clusters.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 8b2361a..f93960f 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -493,8 +493,7 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
             return -EIO;
         }
         c = count_contiguous_clusters(nb_clusters, s->cluster_size,
-                &l2_table[l2_index], 0,
-                QCOW_OFLAG_COMPRESSED | QCOW_OFLAG_ZERO);
+                &l2_table[l2_index], 0, QCOW_OFLAG_ZERO);
         *cluster_offset = 0;
         break;
     case QCOW2_CLUSTER_UNALLOCATED:
@@ -505,8 +504,7 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
     case QCOW2_CLUSTER_NORMAL:
         /* how many allocated clusters ? */
         c = count_contiguous_clusters(nb_clusters, s->cluster_size,
-                &l2_table[l2_index], 0,
-                QCOW_OFLAG_COMPRESSED | QCOW_OFLAG_ZERO);
+                &l2_table[l2_index], 0, QCOW_OFLAG_ZERO);
         *cluster_offset &= L2E_OFFSET_MASK;
         break;
     default:
commit 15684a474286cc2c6106c756ddd095a21d058970
Author: Max Reitz <mreitz at redhat.com>
Date:   Fri Sep 27 12:14:15 2013 +0200

    qcow2: count_contiguous_clusters and compression
    
    The function is not intended to be used on compressed clusters and will
    not work correctly, if used anyway, since L2E_OFFSET_MASK is not the
    right mask for determining the offset of compressed clusters. Therefore,
    assert that the first cluster is not compressed and always include the
    compression flag in the mask of significant flags, i.e., stop the search
    as soon as a compressed cluster occurs.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 91d07f2..8b2361a 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -284,12 +284,15 @@ static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size,
         uint64_t *l2_table, uint64_t start, uint64_t stop_flags)
 {
     int i;
-    uint64_t mask = stop_flags | L2E_OFFSET_MASK;
-    uint64_t offset = be64_to_cpu(l2_table[0]) & mask;
+    uint64_t mask = stop_flags | L2E_OFFSET_MASK | QCOW2_CLUSTER_COMPRESSED;
+    uint64_t first_entry = be64_to_cpu(l2_table[0]);
+    uint64_t offset = first_entry & mask;
 
     if (!offset)
         return 0;
 
+    assert(qcow2_get_cluster_type(first_entry) != QCOW2_CLUSTER_COMPRESSED);
+
     for (i = start; i < start + nb_clusters; i++) {
         uint64_t l2_entry = be64_to_cpu(l2_table[i]) & mask;
         if (offset + (uint64_t) i * cluster_size != l2_entry) {
commit 320c70666687db4dd4df8165f9fe6960de782ca9
Author: Max Reitz <mreitz at redhat.com>
Date:   Fri Sep 27 10:21:48 2013 +0200

    qcow2: Free only newly allocated clusters on error
    
    In expand_zero_clusters_in_l1, a new cluster is only allocated if it was
    not already preallocated. On error, such preallocated clusters should
    not be freed, but only the newly allocated ones.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index c743db1..91d07f2 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1554,6 +1554,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
             uint64_t l2_entry = be64_to_cpu(l2_table[j]);
             int64_t offset = l2_entry & L2E_OFFSET_MASK, cluster_index;
             int cluster_type = qcow2_get_cluster_type(l2_entry);
+            bool preallocated = offset != 0;
 
             if (cluster_type == QCOW2_CLUSTER_NORMAL) {
                 cluster_index = offset >> s->cluster_bits;
@@ -1579,8 +1580,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
                 continue;
             }
 
-            if (!offset) {
-                /* not preallocated */
+            if (!preallocated) {
                 if (!bs->backing_hd) {
                     /* not backed; therefore we can simply deallocate the
                      * cluster */
@@ -1599,16 +1599,20 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
             ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
                                                 offset, s->cluster_size);
             if (ret < 0) {
-                qcow2_free_clusters(bs, offset, s->cluster_size,
-                        QCOW2_DISCARD_ALWAYS);
+                if (!preallocated) {
+                    qcow2_free_clusters(bs, offset, s->cluster_size,
+                                        QCOW2_DISCARD_ALWAYS);
+                }
                 goto fail;
             }
 
             ret = bdrv_write_zeroes(bs->file, offset / BDRV_SECTOR_SIZE,
                                     s->cluster_sectors);
             if (ret < 0) {
-                qcow2_free_clusters(bs, offset, s->cluster_size,
-                        QCOW2_DISCARD_ALWAYS);
+                if (!preallocated) {
+                    qcow2_free_clusters(bs, offset, s->cluster_size,
+                                        QCOW2_DISCARD_ALWAYS);
+                }
                 goto fail;
             }
 
commit be0b742ee320d1139d57062fa18490e7aa485f2a
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Sep 25 16:37:20 2013 +0200

    qcow2: Always use error path in l2_allocate
    
    Just returning -errno in some cases prevents
    trace_qcow2_l2_allocate_done from being executed (and, in one case, also
    the unused allocated L2 table from being freed). Always going down the
    error path fixes this.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 153ea50..c743db1 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -200,7 +200,8 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
 
     l2_offset = qcow2_alloc_clusters(bs, s->l2_size * sizeof(uint64_t));
     if (l2_offset < 0) {
-        return l2_offset;
+        ret = l2_offset;
+        goto fail;
     }
 
     ret = qcow2_cache_flush(bs, s->refcount_block_cache);
@@ -213,7 +214,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
     trace_qcow2_l2_allocate_get_empty(bs, l1_index);
     ret = qcow2_cache_get_empty(bs, s->l2_table_cache, l2_offset, (void**) table);
     if (ret < 0) {
-        return ret;
+        goto fail;
     }
 
     l2_table = *table;
commit 8585afd8133eed037dde9c14106e7eb8d7c46968
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Sep 25 16:37:18 2013 +0200

    qcow2: Don't put invalid L2 table into cache
    
    In l2_allocate, the fail path is executed if qcow2_cache_flush fails.
    However, the L2 table has not yet been fetched from the L2 table cache.
    The qcow2_cache_put in the fail path therefore basically gives an
    undefined argument as the L2 table address (in this case).
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index ffa8941..153ea50 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -188,7 +188,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
 {
     BDRVQcowState *s = bs->opaque;
     uint64_t old_l2_offset;
-    uint64_t *l2_table;
+    uint64_t *l2_table = NULL;
     int64_t l2_offset;
     int ret;
 
@@ -265,7 +265,9 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
 
 fail:
     trace_qcow2_l2_allocate_done(bs, l1_index, ret);
-    qcow2_cache_put(bs, s->l2_table_cache, (void**) table);
+    if (l2_table != NULL) {
+        qcow2_cache_put(bs, s->l2_table_cache, (void**) table);
+    }
     s->l1_table[l1_index] = old_l2_offset;
     return ret;
 }
commit fd9e03e6060b3a64099d17e4a886421b21dd7341
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Sep 25 12:07:23 2013 +0200

    qemu-iotests: Preallocated zero clusters in 061
    
    Add a test case for zero cluster expansion on an image completely filled
    with preallocated zero clusters to test 061.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
index 5f04bfa..fa9319d 100755
--- a/tests/qemu-iotests/061
+++ b/tests/qemu-iotests/061
@@ -200,6 +200,15 @@ $QEMU_IMG snapshot -a foo "$TEST_IMG"
 _check_test_img
 $QEMU_IO -c "read -P 0 0 128k" "$TEST_IMG" | _filter_qemu_io
 
+echo
+echo "=== Testing preallocated zero expansion on full image ==="
+echo
+IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG" _make_test_img 64M
+$QEMU_IO -c "write -P 0x2a 0 64M" "$TEST_IMG" -c "write -z 0 64M" | _filter_qemu_io
+$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
+_check_test_img
+$QEMU_IO -c "read -P 0 0 64M" "$TEST_IMG" | _filter_qemu_io
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
index d42127f..4027e00 100644
--- a/tests/qemu-iotests/061.out
+++ b/tests/qemu-iotests/061.out
@@ -373,4 +373,15 @@ read 131072/131072 bytes at offset 0
 No errors were found on the image.
 read 131072/131072 bytes at offset 0
 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+=== Testing preallocated zero expansion on full image ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+wrote 67108864/67108864 bytes at offset 0
+64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 67108864/67108864 bytes at offset 0
+64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+No errors were found on the image.
+read 67108864/67108864 bytes at offset 0
+64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 *** done
commit e390cf5a9722d3f3cc54efb505f6ff37fa554b11
Author: Max Reitz <mreitz at redhat.com>
Date:   Wed Sep 25 12:07:22 2013 +0200

    qcow2: Correct bitmap size in zero expansion
    
    Since the expanded_clusters bitmap is addressed using host offsets in
    the underlying image file, the correct size to use for allocating the
    bitmap is not determined by the guest disk image but by the underlying
    host image file.
    
    Furthermore, this size may change during the expansion due to cluster
    allocations on growable image files. In this case, the bitmap needs to
    be resized as well to reflect the growth.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index cab5f2e..ffa8941 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1510,8 +1510,8 @@ fail:
  * i.e., the number of bits in expanded_clusters.
  */
 static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
-                                      int l1_size, uint8_t *expanded_clusters,
-                                      uint64_t nb_clusters)
+                                      int l1_size, uint8_t **expanded_clusters,
+                                      uint64_t *nb_clusters)
 {
     BDRVQcowState *s = bs->opaque;
     bool is_active_l1 = (l1_table == s->l1_table);
@@ -1554,8 +1554,8 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
 
             if (cluster_type == QCOW2_CLUSTER_NORMAL) {
                 cluster_index = offset >> s->cluster_bits;
-                assert((cluster_index >= 0) && (cluster_index < nb_clusters));
-                if (expanded_clusters[cluster_index / 8] &
+                assert((cluster_index >= 0) && (cluster_index < *nb_clusters));
+                if ((*expanded_clusters)[cluster_index / 8] &
                     (1 << (cluster_index % 8))) {
                     /* Probably a shared L2 table; this cluster was a zero
                      * cluster which has been expanded, its refcount
@@ -1613,8 +1613,25 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
             l2_dirty = true;
 
             cluster_index = offset >> s->cluster_bits;
-            assert((cluster_index >= 0) && (cluster_index < nb_clusters));
-            expanded_clusters[cluster_index / 8] |= 1 << (cluster_index % 8);
+
+            if (cluster_index >= *nb_clusters) {
+                uint64_t old_bitmap_size = (*nb_clusters + 7) / 8;
+                uint64_t new_bitmap_size;
+                /* The offset may lie beyond the old end of the underlying image
+                 * file for growable files only */
+                assert(bs->file->growable);
+                *nb_clusters = size_to_clusters(s, bs->file->total_sectors *
+                                                BDRV_SECTOR_SIZE);
+                new_bitmap_size = (*nb_clusters + 7) / 8;
+                *expanded_clusters = g_realloc(*expanded_clusters,
+                                               new_bitmap_size);
+                /* clear the newly allocated space */
+                memset(&(*expanded_clusters)[old_bitmap_size], 0,
+                       new_bitmap_size - old_bitmap_size);
+            }
+
+            assert((cluster_index >= 0) && (cluster_index < *nb_clusters));
+            (*expanded_clusters)[cluster_index / 8] |= 1 << (cluster_index % 8);
         }
 
         if (is_active_l1) {
@@ -1673,18 +1690,17 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs)
 {
     BDRVQcowState *s = bs->opaque;
     uint64_t *l1_table = NULL;
-    int cluster_to_sector_bits = s->cluster_bits - BDRV_SECTOR_BITS;
     uint64_t nb_clusters;
     uint8_t *expanded_clusters;
     int ret;
     int i, j;
 
-    nb_clusters = (bs->total_sectors + (1 << cluster_to_sector_bits) - 1)
-            >> cluster_to_sector_bits;
+    nb_clusters = size_to_clusters(s, bs->file->total_sectors *
+                                   BDRV_SECTOR_SIZE);
     expanded_clusters = g_malloc0((nb_clusters + 7) / 8);
 
     ret = expand_zero_clusters_in_l1(bs, s->l1_table, s->l1_size,
-                                     expanded_clusters, nb_clusters);
+                                     &expanded_clusters, &nb_clusters);
     if (ret < 0) {
         goto fail;
     }
@@ -1718,7 +1734,7 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs)
         }
 
         ret = expand_zero_clusters_in_l1(bs, l1_table, s->snapshots[i].l1_size,
-                                         expanded_clusters, nb_clusters);
+                                         &expanded_clusters, &nb_clusters);
         if (ret < 0) {
             goto fail;
         }
commit fef9c19139f4d69a080d99b8cbade163d0bbf0fc
Author: Jeff Cody <jcody at redhat.com>
Date:   Wed Sep 25 08:12:22 2013 -0400

    qemu-iotests: Quote $TEST_IMG* and $TEST_DIR usage
    
    A lot of image filename and paths are used unquoted.  Quote these to
    make sure that directories / filenames with spaces are not problematic.
    
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/001 b/tests/qemu-iotests/001
index bd88dde..4e16469 100755
--- a/tests/qemu-iotests/001
+++ b/tests/qemu-iotests/001
@@ -48,15 +48,15 @@ _make_test_img $size
 
 echo
 echo "== reading whole image =="
-$QEMU_IO -c "read 0 $size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read 0 $size" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== rewriting whole image =="
-$QEMU_IO -c "write -P 0xa 0 $size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== verify pattern =="
-$QEMU_IO -c "read -P 0xa 0 $size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
 
 
 # success, all done
diff --git a/tests/qemu-iotests/002 b/tests/qemu-iotests/002
index 51d0a8f..6a865aa 100755
--- a/tests/qemu-iotests/002
+++ b/tests/qemu-iotests/002
@@ -48,36 +48,36 @@ _make_test_img $size
 
 echo
 echo "== reading whole image =="
-$QEMU_IO -c "read -p 0 $size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read -p 0 $size" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== rewriting whole image =="
-$QEMU_IO -c "write -pP 0xa 0 $size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write -pP 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== verify pattern =="
-$QEMU_IO -c "read -pP 0xa 0 $size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read -pP 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "unaligned pwrite"
-$QEMU_IO -c 'write -pP 0xab 66 42' $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c 'write -pP 0xac 512 288' $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c 'write -pP 0xad 800 224' $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c 'write -pP 0xae 66000 128k' $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c 'write -pP 0xaf 256k 42' $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c 'write -pP 0xab 66 42' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'write -pP 0xac 512 288' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'write -pP 0xad 800 224' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'write -pP 0xae 66000 128k' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'write -pP 0xaf 256k 42' "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "verify pattern"
-$QEMU_IO -c 'read -pP 0xa 0 66' $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c 'read -pP 0xab 66 42' $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c 'read -pP 0xa 108 404' $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c 'read -pP 0xac 512 288' $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c 'read -pP 0xad 800 224' $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c 'read -pP 0xa 1k 64976' $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c 'read -pP 0xae 66000 128k' $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c 'read -pP 0xa 197072 65072' $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c 'read -pP 0xaf 256k 42' $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c 'read -pP 0xa 262186 470' $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c 'read -pP 0xa 0 66' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'read -pP 0xab 66 42' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'read -pP 0xa 108 404' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'read -pP 0xac 512 288' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'read -pP 0xad 800 224' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'read -pP 0xa 1k 64976' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'read -pP 0xae 66000 128k' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'read -pP 0xa 197072 65072' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'read -pP 0xaf 256k 42' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'read -pP 0xa 262186 470' "$TEST_IMG" | _filter_qemu_io
 
 # success, all done
 echo "*** done"
diff --git a/tests/qemu-iotests/003 b/tests/qemu-iotests/003
index ee25fb8..98638d4 100755
--- a/tests/qemu-iotests/003
+++ b/tests/qemu-iotests/003
@@ -50,27 +50,27 @@ _make_test_img $size
 
 echo
 echo "== reading whole image =="
-$QEMU_IO -c "readv 0 $size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "readv 0 $size" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== rewriting whole image =="
-$QEMU_IO -c "writev -P 0xa 0 $size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "writev -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== verify pattern =="
-$QEMU_IO -c "readv -P 0xa 0 $size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "readv -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== vectored write =="
 $QEMU_IO -c "writev -P 0xb $offset $chunksize $chunksize \
 	$chunksize $chunksize $chunksize $chunksize $chunksize" \
-	$TEST_IMG | _filter_qemu_io
+	"$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== verify pattern =="
 $QEMU_IO -c "readv -P 0xb $offset $chunksize $chunksize \
 	$chunksize $chunksize $chunksize $chunksize $chunksize" \
-	$TEST_IMG | _filter_qemu_io
+	"$TEST_IMG" | _filter_qemu_io
 
 # success, all done
 echo "*** done"
diff --git a/tests/qemu-iotests/004 b/tests/qemu-iotests/004
index c76451c..651072e 100755
--- a/tests/qemu-iotests/004
+++ b/tests/qemu-iotests/004
@@ -51,51 +51,51 @@ _make_test_img $size
 
 echo
 echo "write before image boundary"
-$QEMU_IO -c "write $pre_offset 1M" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write $pre_offset 1M" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "write into image boundary"
-$QEMU_IO -c "write $pre_offset 4M" $TEST_IMG
+$QEMU_IO -c "write $pre_offset 4M" "$TEST_IMG"
 
 echo
 echo "write at image boundary"
-$QEMU_IO -c "write $size 4096" $TEST_IMG
+$QEMU_IO -c "write $size 4096" "$TEST_IMG"
 
 echo
 echo "write past image boundary"
-$QEMU_IO -c "write $past_offset 4096" $TEST_IMG
+$QEMU_IO -c "write $past_offset 4096" "$TEST_IMG"
 
 echo
 echo "pwrite past image boundary"
-$QEMU_IO -c "write -p $past_offset 4096" $TEST_IMG
+$QEMU_IO -c "write -p $past_offset 4096" "$TEST_IMG"
 
 echo
 echo "writev past image boundary"
-$QEMU_IO -c "writev $past_offset 4096" $TEST_IMG
+$QEMU_IO -c "writev $past_offset 4096" "$TEST_IMG"
 
 echo
 echo "read before image boundary"
-$QEMU_IO -c "read $pre_offset 1M" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read $pre_offset 1M" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "read into image boundary"
-$QEMU_IO -c "read $pre_offset 4M" $TEST_IMG
+$QEMU_IO -c "read $pre_offset 4M" "$TEST_IMG"
 
 echo
 echo "read at image boundary"
-$QEMU_IO -c "read $size 4096" $TEST_IMG
+$QEMU_IO -c "read $size 4096" "$TEST_IMG"
 
 echo
 echo "read past image boundary"
-$QEMU_IO -c "read $past_offset 4096" $TEST_IMG
+$QEMU_IO -c "read $past_offset 4096" "$TEST_IMG"
 
 echo
 echo "pread past image boundary"
-$QEMU_IO -c "read -p $past_offset 4096" $TEST_IMG
+$QEMU_IO -c "read -p $past_offset 4096" "$TEST_IMG"
 
 echo
 echo "readv past image boundary"
-$QEMU_IO -c "readv $past_offset 4096" $TEST_IMG
+$QEMU_IO -c "readv $past_offset 4096" "$TEST_IMG"
 
 
 # success, all done
diff --git a/tests/qemu-iotests/005 b/tests/qemu-iotests/005
index b7970e3..9abcb84 100755
--- a/tests/qemu-iotests/005
+++ b/tests/qemu-iotests/005
@@ -61,11 +61,11 @@ _make_test_img 5000G
 
 echo
 echo "small read"
-$QEMU_IO -c "read 1024 4096" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read 1024 4096" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "small write"
-$QEMU_IO -c "write 8192 4096" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write 8192 4096" "$TEST_IMG" | _filter_qemu_io
 
 # success, all done
 echo "*** done"
diff --git a/tests/qemu-iotests/007 b/tests/qemu-iotests/007
index 6fa7603..fe1a743 100755
--- a/tests/qemu-iotests/007
+++ b/tests/qemu-iotests/007
@@ -50,7 +50,7 @@ _make_test_img 1M
 
 for i in `seq 1 10`; do
     echo "savevm $i"
-    $QEMU -nographic -hda $TEST_IMG -serial none -monitor stdio >/dev/null 2>&1 <<EOF
+    $QEMU -nographic -hda "$TEST_IMG" -serial none -monitor stdio >/dev/null 2>&1 <<EOF
 savevm test-$i
 quit
 EOF
diff --git a/tests/qemu-iotests/008 b/tests/qemu-iotests/008
index 2c53bac..2d28efd 100755
--- a/tests/qemu-iotests/008
+++ b/tests/qemu-iotests/008
@@ -48,15 +48,15 @@ _make_test_img $size
 
 echo
 echo "== reading whole image =="
-$QEMU_IO -c "aio_read 0 $size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "aio_read 0 $size" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== rewriting whole image =="
-$QEMU_IO -c "aio_write -P 0xa 0 $size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "aio_write -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== verify pattern =="
-$QEMU_IO -c "aio_read -P 0xa 0 $size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "aio_read -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
 
 
 # success, all done
diff --git a/tests/qemu-iotests/009 b/tests/qemu-iotests/009
index 25368c8..57a43f5 100755
--- a/tests/qemu-iotests/009
+++ b/tests/qemu-iotests/009
@@ -57,7 +57,7 @@ $QEMU_IO \
 	-c "write 4k 4k" \
 	-c "write 9M 4k" \
 	-c "read -P 65 -s 4k -l 4k 2044k 8k" \
-$TEST_IMG | _filter_qemu_io
+"$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "checking image for errors"
diff --git a/tests/qemu-iotests/010 b/tests/qemu-iotests/010
index 7b57929..896a005 100755
--- a/tests/qemu-iotests/010
+++ b/tests/qemu-iotests/010
@@ -59,7 +59,7 @@ $QEMU_IO \
 	-c "write -P 165 2044k 4k" \
 	-c "write -P 99 8M 4k" \
 	-c "read -P 165 2044k 8k" \
-$TEST_IMG | _filter_qemu_io
+"$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "checking image for errors"
diff --git a/tests/qemu-iotests/011 b/tests/qemu-iotests/011
index b03df68..1c5158a 100755
--- a/tests/qemu-iotests/011
+++ b/tests/qemu-iotests/011
@@ -60,7 +60,7 @@ for i in `seq 1 10`; do
     # Note that we filter away the actual offset.  That's because qemu
     # may re-order the two aio requests.  We only want to make sure the
     # filesystem isn't corrupted afterwards anyway.
-    $QEMU_IO -c "aio_write $off1 1M" -c "aio_write $off2 1M" $TEST_IMG | \
+    $QEMU_IO -c "aio_write $off1 1M" -c "aio_write $off2 1M" "$TEST_IMG" | \
     	_filter_qemu_io | \
 	sed -e 's/bytes at offset [0-9]*/bytes at offset XXX/g'
 done
diff --git a/tests/qemu-iotests/012 b/tests/qemu-iotests/012
index 4052956..7c5b689 100755
--- a/tests/qemu-iotests/012
+++ b/tests/qemu-iotests/012
@@ -50,11 +50,11 @@ _make_test_img $size
 
 echo
 echo "== mark image read-only"
-chmod a-w $TEST_IMG
+chmod a-w "$TEST_IMG"
 
 echo
 echo "== read from read-only image"
-$QEMU_IO -r -c "read 0 512" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -r -c "read 0 512" "$TEST_IMG" | _filter_qemu_io
 
 # success, all done
 echo "*** done"
diff --git a/tests/qemu-iotests/013 b/tests/qemu-iotests/013
index ce40d5c..389f4b8 100755
--- a/tests/qemu-iotests/013
+++ b/tests/qemu-iotests/013
@@ -65,8 +65,8 @@ done
 echo "Compressing image"
 echo
 
-mv $TEST_IMG $TEST_IMG.orig
-$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -c $TEST_IMG.orig $TEST_IMG
+mv "$TEST_IMG" "$TEST_IMG.orig"
+$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -c "$TEST_IMG.orig" "$TEST_IMG"
 
 echo "Testing compressed image"
 echo
diff --git a/tests/qemu-iotests/014 b/tests/qemu-iotests/014
index a6d0aea..0edeb4b 100755
--- a/tests/qemu-iotests/014
+++ b/tests/qemu-iotests/014
@@ -61,7 +61,7 @@ done
 
 # With snapshots
 for i in `seq 1 3`; do
-    $QEMU_IMG snapshot -c test$i $TEST_IMG
+    $QEMU_IMG snapshot -c test$i "$TEST_IMG"
     for offset in $TEST_OFFSETS; do
         echo With snapshot test$i, offset $offset
         for op in $TEST_OPS; do
diff --git a/tests/qemu-iotests/015 b/tests/qemu-iotests/015
index 44c134f..099d757 100755
--- a/tests/qemu-iotests/015
+++ b/tests/qemu-iotests/015
@@ -61,19 +61,19 @@ _make_test_img $size
 
 # Create two snapshots which fill the image with two different patterns
 echo "creating first snapshot"
-$QEMU_IO -c "aio_write -P 123 0 $size" $TEST_IMG | _filter_qemu_io
-$QEMU_IMG snapshot -c snap1 $TEST_IMG
+$QEMU_IO -c "aio_write -P 123 0 $size" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG snapshot -c snap1 "$TEST_IMG"
 echo "creating second snapshot"
-$QEMU_IO -c "aio_write -P 165 0 $size" $TEST_IMG | _filter_qemu_io
-$QEMU_IMG snapshot -c snap2 $TEST_IMG
+$QEMU_IO -c "aio_write -P 165 0 $size" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG snapshot -c snap2 "$TEST_IMG"
 
 # Now check the pattern
 echo "checking first snapshot"
-$QEMU_IMG snapshot -a snap1 $TEST_IMG
-$QEMU_IO -c "aio_read -P 123 0 $size" $TEST_IMG | _filter_qemu_io
+$QEMU_IMG snapshot -a snap1 "$TEST_IMG"
+$QEMU_IO -c "aio_read -P 123 0 $size" "$TEST_IMG" | _filter_qemu_io
 echo "checking second snapshot"
-$QEMU_IMG snapshot -a snap2 $TEST_IMG
-$QEMU_IO -c "aio_read -P 165 0 $size" $TEST_IMG | _filter_qemu_io
+$QEMU_IMG snapshot -a snap2 "$TEST_IMG"
+$QEMU_IO -c "aio_read -P 165 0 $size" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "checking image for errors"
diff --git a/tests/qemu-iotests/016 b/tests/qemu-iotests/016
index a1467b8..b87a32b 100755
--- a/tests/qemu-iotests/016
+++ b/tests/qemu-iotests/016
@@ -48,21 +48,21 @@ _make_test_img $size
 
 echo
 echo "== reading at EOF =="
-$QEMU_IO -g -c "read -P 0 $size 512" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -g -c "read -P 0 $size 512" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== reading far past EOF =="
-$QEMU_IO -g -c "read -P 0 256M 512" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -g -c "read -P 0 256M 512" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== writing at EOF =="
-$QEMU_IO -g -c "write -P 66 $size 512" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 66 $size 512" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -g -c "write -P 66 $size 512" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 66 $size 512" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== writing far past EOF =="
-$QEMU_IO -g -c "write -P 66 256M 512" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 66 256M 512" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -g -c "write -P 66 256M 512" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 66 256M 512" "$TEST_IMG" | _filter_qemu_io
 
 # success, all done
 echo "*** done"
diff --git a/tests/qemu-iotests/018 b/tests/qemu-iotests/018
index 453ce61..15fcfe5 100755
--- a/tests/qemu-iotests/018
+++ b/tests/qemu-iotests/018
@@ -66,7 +66,7 @@ echo "Creating test image with backing file"
 echo
 
 TEST_IMG=$TEST_IMG_SAVE
-_make_test_img -b $TEST_IMG.base 6G
+_make_test_img -b "$TEST_IMG.base" 6G
 
 echo "Filling test image"
 echo
@@ -80,8 +80,8 @@ for offset in $TEST_OFFSETS; do
 done
 _check_test_img
 
-mv $TEST_IMG $TEST_IMG.orig
-$QEMU_IMG convert -O $IMGFMT $TEST_IMG.orig $TEST_IMG
+mv "$TEST_IMG" "$TEST_IMG.orig"
+$QEMU_IMG convert -O $IMGFMT "$TEST_IMG.orig" "$TEST_IMG"
 
 echo "Reading"
 echo
diff --git a/tests/qemu-iotests/019 b/tests/qemu-iotests/019
index 8872b30..cd3582c 100755
--- a/tests/qemu-iotests/019
+++ b/tests/qemu-iotests/019
@@ -33,8 +33,8 @@ status=1	# failure is the default!
 _cleanup()
 {
 	_cleanup_test_img
-    rm -f $TEST_IMG.base
-    rm -f $TEST_IMG.orig
+    rm -f "$TEST_IMG.base"
+    rm -f "$TEST_IMG.orig"
 }
 trap "_cleanup; exit \$status" 0 1 2 3 15
 
@@ -68,8 +68,8 @@ _check_test_img
 echo "Creating test image with backing file"
 echo
 
-mv $TEST_IMG $TEST_IMG.base
-_make_test_img -b $TEST_IMG.base 6G
+mv "$TEST_IMG" "$TEST_IMG.base"
+_make_test_img -b "$TEST_IMG.base" 6G
 
 echo "Filling test image"
 echo
@@ -83,7 +83,7 @@ for offset in $TEST_OFFSETS; do
 done
 _check_test_img
 
-mv $TEST_IMG $TEST_IMG.orig
+mv "$TEST_IMG" "$TEST_IMG.orig"
 
 
 
@@ -95,7 +95,7 @@ for backing_option in "-B $TEST_IMG.base" "-o backing_file=$TEST_IMG.base"; do
     echo
     echo Testing conversion with $backing_option | _filter_testdir | _filter_imgfmt
     echo
-    $QEMU_IMG convert -O $IMGFMT $backing_option $TEST_IMG.orig $TEST_IMG
+    $QEMU_IMG convert -O $IMGFMT $backing_option "$TEST_IMG.orig" "$TEST_IMG"
 
     echo "Checking if backing clusters are allocated when they shouldn't"
     echo
diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020
index 2fb0ff8..b3c86d8 100755
--- a/tests/qemu-iotests/020
+++ b/tests/qemu-iotests/020
@@ -31,8 +31,8 @@ status=1	# failure is the default!
 _cleanup()
 {
 	_cleanup_test_img
-    rm -f $TEST_IMG.base
-    rm -f $TEST_IMG.orig
+    rm -f "$TEST_IMG.base"
+    rm -f "$TEST_IMG.orig"
 }
 trap "_cleanup; exit \$status" 0 1 2 3 15
 
@@ -65,8 +65,8 @@ _check_test_img
 echo "Creating test image with backing file"
 echo
 
-mv $TEST_IMG $TEST_IMG.base
-_make_test_img -b $TEST_IMG.base 6G
+mv "$TEST_IMG" "$TEST_IMG.base"
+_make_test_img -b "$TEST_IMG.base" 6G
 
 echo "Filling test image"
 echo
@@ -80,8 +80,8 @@ for offset in $TEST_OFFSETS; do
 done
 _check_test_img
 
-$QEMU_IMG commit $TEST_IMG
-mv $TEST_IMG.base $TEST_IMG
+$QEMU_IMG commit "$TEST_IMG"
+mv "$TEST_IMG.base" "$TEST_IMG"
 
 echo "Reading from the backing file"
 echo
diff --git a/tests/qemu-iotests/021 b/tests/qemu-iotests/021
index 6da79eb..1c69024 100755
--- a/tests/qemu-iotests/021
+++ b/tests/qemu-iotests/021
@@ -53,7 +53,7 @@ for pattern in $INVALID_PATTERNS; do
     for op in $TEST_OPS; do
         echo
 	echo "== testing $op -P $pattern =="
-	$QEMU_IO -c "$op -P $pattern 0 4096" $TEST_IMG | _filter_qemu_io
+	$QEMU_IO -c "$op -P $pattern 0 4096" "$TEST_IMG" | _filter_qemu_io
     done
 done
 
diff --git a/tests/qemu-iotests/023 b/tests/qemu-iotests/023
index 4f31b56..090ed23 100755
--- a/tests/qemu-iotests/023
+++ b/tests/qemu-iotests/023
@@ -71,8 +71,8 @@ for CLUSTER_SIZE in $CLUSTER_SIZES; do
     echo "Compressing image"
     echo
 
-    mv $TEST_IMG $TEST_IMG.orig
-    $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -c $TEST_IMG.orig $TEST_IMG
+    mv "$TEST_IMG" "$TEST_IMG.orig"
+    $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -c "$TEST_IMG.orig" "$TEST_IMG"
 
     echo "Testing compressed image"
     echo
diff --git a/tests/qemu-iotests/024 b/tests/qemu-iotests/024
index 554b74b..be974f0 100755
--- a/tests/qemu-iotests/024
+++ b/tests/qemu-iotests/024
@@ -31,8 +31,8 @@ status=1	# failure is the default!
 _cleanup()
 {
 	_cleanup_test_img
-	rm -f $TEST_DIR/t.$IMGFMT.base_old
-	rm -f $TEST_DIR/t.$IMGFMT.base_new
+	rm -f "$TEST_DIR/t.$IMGFMT.base_old"
+	rm -f "$TEST_DIR/t.$IMGFMT.base_new"
 }
 trap "_cleanup; exit \$status" 0 1 2 3 15
 
@@ -62,19 +62,19 @@ echo
 
 _make_test_img 1G
 io_pattern writev 0 $CLUSTER_SIZE $((2 * CLUSTER_SIZE)) 8 0x11
-mv $TEST_IMG $TEST_IMG.base_old
+mv "$TEST_IMG" "$TEST_IMG.base_old"
 
 echo "Creating new backing file"
 echo
 
 _make_test_img 1G
 io_pattern writev 0 $((2 * CLUSTER_SIZE)) $((4 * CLUSTER_SIZE)) 4 0x22
-mv $TEST_IMG $TEST_IMG.base_new
+mv "$TEST_IMG" "$TEST_IMG.base_new"
 
 echo "Creating COW image"
 echo
 
-_make_test_img -b $TEST_IMG.base_old 1G
+_make_test_img -b "$TEST_IMG.base_old" 1G
 io_pattern writev 0 $((4 * CLUSTER_SIZE)) 0 1 0x33
 io_pattern writev $((8 * CLUSTER_SIZE)) $((4 * CLUSTER_SIZE)) 0 1 0x33
 
@@ -100,7 +100,7 @@ io_pattern readv $((15 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x00
 echo
 echo Rebase and test again
 echo
-$QEMU_IMG rebase -b $TEST_IMG.base_new $TEST_IMG
+$QEMU_IMG rebase -b "$TEST_IMG.base_new" "$TEST_IMG"
 io_pattern readv $((0 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
 io_pattern readv $((1 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
 io_pattern readv $((2 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
diff --git a/tests/qemu-iotests/025 b/tests/qemu-iotests/025
index 7062aa6..a7241cc 100755
--- a/tests/qemu-iotests/025
+++ b/tests/qemu-iotests/025
@@ -56,7 +56,7 @@ _check_test_img
 
 echo
 echo "=== Resizing image"
-$QEMU_IO $TEST_IMG <<EOF
+$QEMU_IO "$TEST_IMG" <<EOF
 length
 truncate $big_size
 length
@@ -65,7 +65,7 @@ _check_test_img
 
 echo
 echo "=== Verifying image size after reopen"
-$QEMU_IO -c "length" $TEST_IMG
+$QEMU_IO -c "length" "$TEST_IMG"
 
 echo
 echo "=== Verifying resized image"
diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026
index 107a3ff..ebe29d0 100755
--- a/tests/qemu-iotests/026
+++ b/tests/qemu-iotests/026
@@ -31,7 +31,7 @@ status=1	# failure is the default!
 _cleanup()
 {
 	_cleanup_test_img
-    rm $TEST_DIR/blkdebug.conf
+    rm "$TEST_DIR/blkdebug.conf"
 }
 trap "_cleanup; exit \$status" 0 1 2 3 15
 
@@ -75,7 +75,7 @@ for imm in off; do
 for once in on off; do
 for vmstate in "" "-b"; do
 
-cat > $TEST_DIR/blkdebug.conf <<EOF
+cat > "$TEST_DIR/blkdebug.conf" <<EOF
 [inject-error]
 event = "$event"
 errno = "$errno"
@@ -90,16 +90,16 @@ echo "Event: $event; errno: $errno; imm: $imm; once: $once; write $vmstate"
 
 # We want to catch a simple L2 update, not the allocation of the first L2 table
 if [ "$event" == "l2_update" ]; then
-    $QEMU_IO -c "write $vmstate 0 512" $TEST_IMG > /dev/null 2>&1
+    $QEMU_IO -c "write $vmstate 0 512" "$TEST_IMG" > /dev/null 2>&1
 fi
 
-$QEMU_IO -c "write $vmstate 0 128k " $BLKDBG_TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write $vmstate 0 128k " "$BLKDBG_TEST_IMG" | _filter_qemu_io
 
 # l2_load is not called on allocation, so issue a second write
 # Reads are another path to trigger l2_load, so do a read, too
 if [ "$event" == "l2_load" ]; then
-    $QEMU_IO -c "write $vmstate 0 128k " $BLKDBG_TEST_IMG | _filter_qemu_io
-    $QEMU_IO -c "read $vmstate 0 128k " $BLKDBG_TEST_IMG | _filter_qemu_io
+    $QEMU_IO -c "write $vmstate 0 128k " "$BLKDBG_TEST_IMG" | _filter_qemu_io
+    $QEMU_IO -c "read $vmstate 0 128k " "$BLKDBG_TEST_IMG" | _filter_qemu_io
 fi
 
 _check_test_img 2>&1 | grep -v "refcount=1 reference=0"
@@ -133,7 +133,7 @@ for imm in off; do
 for once in on off; do
 for vmstate in "" "-b"; do
 
-cat > $TEST_DIR/blkdebug.conf <<EOF
+cat > "$TEST_DIR/blkdebug.conf" <<EOF
 [inject-error]
 event = "$event"
 errno = "$errno"
@@ -145,7 +145,7 @@ _make_test_img 1G
 
 echo
 echo "Event: $event; errno: $errno; imm: $imm; once: $once; write $vmstate"
-$QEMU_IO -c "write $vmstate 0 64M" $BLKDBG_TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write $vmstate 0 64M" "$BLKDBG_TEST_IMG" | _filter_qemu_io
 
 _check_test_img 2>&1 | grep -v "refcount=1 reference=0"
 
@@ -172,7 +172,7 @@ for errno in 5 28; do
 for imm in off; do
 for once in on off; do
 
-cat > $TEST_DIR/blkdebug.conf <<EOF
+cat > "$TEST_DIR/blkdebug.conf" <<EOF
 [inject-error]
 event = "$event"
 errno = "$errno"
@@ -184,7 +184,7 @@ _make_test_img 1G
 
 echo
 echo "Event: $event; errno: $errno; imm: $imm; once: $once"
-$QEMU_IO -c "write -b 0 64k" $BLKDBG_TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write -b 0 64k" "$BLKDBG_TEST_IMG" | _filter_qemu_io
 
 _check_test_img 2>&1 | grep -v "refcount=1 reference=0"
 
diff --git a/tests/qemu-iotests/027 b/tests/qemu-iotests/027
index 7d90481..3fa81b8 100755
--- a/tests/qemu-iotests/027
+++ b/tests/qemu-iotests/027
@@ -54,23 +54,23 @@ _make_test_img $size
 # Otherwise an L2 table could get in the way after the data cluster.
 echo
 echo "== writing first cluster to populate metadata =="
-$QEMU_IO -c "write -pP 0xde $cluster_size $cluster_size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write -pP 0xde $cluster_size $cluster_size" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== writing at sub-cluster granularity =="
-$QEMU_IO -c "write -pP 0xa $subcluster_offset $subcluster_size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write -pP 0xa $subcluster_offset $subcluster_size" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== verify pattern =="
-$QEMU_IO -c "read -pP 0xa $subcluster_offset $subcluster_size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read -pP 0xa $subcluster_offset $subcluster_size" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== verify zeroes before sub-cluster pattern =="
-$QEMU_IO -c "read -pP 0 -l $subcluster_offset 0 $subcluster_size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read -pP 0 -l $subcluster_offset 0 $subcluster_size" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== verify zeroes after sub-cluster pattern =="
-$QEMU_IO -c "read -pP 0 -l 512 -s $subcluster_size $subcluster_offset $(( subcluster_size + 512 ))" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read -pP 0 -l 512 -s $subcluster_size $subcluster_offset $(( subcluster_size + 512 ))" "$TEST_IMG" | _filter_qemu_io
 
 # success, all done
 echo "*** done"
diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028
index b091ba9..93a9fa6 100755
--- a/tests/qemu-iotests/028
+++ b/tests/qemu-iotests/028
@@ -71,8 +71,8 @@ _check_test_img
 echo "Creating test image with backing file"
 echo
 
-mv $TEST_IMG $TEST_IMG.base
-_make_test_img -b $TEST_IMG.base $image_size
+mv "$TEST_IMG" "$TEST_IMG.base"
+_make_test_img -b "$TEST_IMG.base" $image_size
 
 echo "Filling test image"
 echo
@@ -97,7 +97,7 @@ io_zero readv $(( offset + 32 * 1024 )) 512 1024 32
 _check_test_img
 
 # Rebase it on top of its base image
-$QEMU_IMG rebase -b $TEST_IMG.base $TEST_IMG
+$QEMU_IMG rebase -b "$TEST_IMG.base" "$TEST_IMG"
 
 _check_test_img
 
diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029
index 0ad5e45..b424726 100755
--- a/tests/qemu-iotests/029
+++ b/tests/qemu-iotests/029
@@ -47,16 +47,16 @@ _supported_os Linux
 
 CLUSTER_SIZE=65536
 _make_test_img 64M
-$QEMU_IMG snapshot -c foo $TEST_IMG
-$QEMU_IO -c 'write -b 0 4k' $TEST_IMG | _filter_qemu_io
-$QEMU_IMG snapshot -a foo $TEST_IMG
+$QEMU_IMG snapshot -c foo "$TEST_IMG"
+$QEMU_IO -c 'write -b 0 4k' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG snapshot -a foo "$TEST_IMG"
 _check_test_img
 
 CLUSTER_SIZE=1024
 _make_test_img 16M
-$QEMU_IMG snapshot -c foo $TEST_IMG
-$QEMU_IO -c 'write -b 0 4M' $TEST_IMG | _filter_qemu_io
-$QEMU_IMG snapshot -a foo $TEST_IMG
+$QEMU_IMG snapshot -c foo "$TEST_IMG"
+$QEMU_IO -c 'write -b 0 4M' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG snapshot -a foo "$TEST_IMG"
 _check_test_img
 
 # success, all done
diff --git a/tests/qemu-iotests/031 b/tests/qemu-iotests/031
index 2d5e3b1..c9070b0 100755
--- a/tests/qemu-iotests/031
+++ b/tests/qemu-iotests/031
@@ -56,22 +56,22 @@ for IMGOPTS in "compat=0.10" "compat=1.1"; do
     echo === Create image with unknown header extension ===
     echo
     _make_test_img 64M
-    ./qcow2.py $TEST_IMG add-header-ext 0x12345678 "This is a test header extension"
-    ./qcow2.py $TEST_IMG dump-header
+    ./qcow2.py "$TEST_IMG" add-header-ext 0x12345678 "This is a test header extension"
+    ./qcow2.py "$TEST_IMG" dump-header
     _check_test_img
 
     echo
     echo === Rewrite header with no backing file ===
     echo
-    $QEMU_IMG rebase -u -b "" $TEST_IMG
-    ./qcow2.py $TEST_IMG dump-header
+    $QEMU_IMG rebase -u -b "" "$TEST_IMG"
+    ./qcow2.py "$TEST_IMG" dump-header
     _check_test_img
 
     echo
     echo === Add a backing file and format ===
     echo
-    $QEMU_IMG rebase -u -b "/some/backing/file/path" -F host_device $TEST_IMG
-    ./qcow2.py $TEST_IMG dump-header
+    $QEMU_IMG rebase -u -b "/some/backing/file/path" -F host_device "$TEST_IMG"
+    ./qcow2.py "$TEST_IMG" dump-header
 done
 
 # success, all done
diff --git a/tests/qemu-iotests/032 b/tests/qemu-iotests/032
index 7155568..b1ba5c3 100755
--- a/tests/qemu-iotests/032
+++ b/tests/qemu-iotests/032
@@ -55,12 +55,12 @@ _make_test_img 64M
 
 # Allocate every other cluster so that afterwards a big write request will
 # actually loop a while and issue many I/O requests for the lower layer
-for i in $(seq 0 128 4096); do echo "write ${i}k 64k"; done | $QEMU_IO $TEST_IMG | _filter_qemu_io
+for i in $(seq 0 128 4096); do echo "write ${i}k 64k"; done | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo === AIO request during close ===
 echo
-$QEMU_IO -c "aio_write 0 4M" -c "close" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "aio_write 0 4M" -c "close" "$TEST_IMG" | _filter_qemu_io
 _check_test_img
 
 # success, all done
diff --git a/tests/qemu-iotests/033 b/tests/qemu-iotests/033
index 9aee078..ea3351c 100755
--- a/tests/qemu-iotests/033
+++ b/tests/qemu-iotests/033
@@ -48,24 +48,24 @@ _make_test_img $size
 
 echo
 echo "== preparing image =="
-$QEMU_IO -c "write -P 0xa 0x200 0x400" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "write -P 0xa 0x20000 0x600" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "write -z 0x400 0x20000" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write -P 0xa 0x200 0x400" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0xa 0x20000 0x600" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -z 0x400 0x20000" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== verifying patterns (1) =="
-$QEMU_IO -c "read -P 0xa 0x200 0x200" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x0 0x400 0x20000" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0xa 0x20400 0x200" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read -P 0xa 0x200 0x200" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x0 0x400 0x20000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0xa 0x20400 0x200" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== rewriting zeroes =="
-$QEMU_IO -c "write -P 0xb 0x10000 0x10000" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "write -z 0x10000 0x10000" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write -P 0xb 0x10000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -z 0x10000 0x10000" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== verifying patterns (2) =="
-$QEMU_IO -c "read -P 0x0 0x400 0x20000" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read -P 0x0 0x400 0x20000" "$TEST_IMG" | _filter_qemu_io
 
 # success, all done
 echo "*** done"
diff --git a/tests/qemu-iotests/034 b/tests/qemu-iotests/034
index 8254df8..67f1959 100755
--- a/tests/qemu-iotests/034
+++ b/tests/qemu-iotests/034
@@ -49,63 +49,63 @@ echo
 echo "== creating backing file for COW tests =="
 
 _make_test_img $size
-$QEMU_IO -c "write -P 0x55 0 1M" $TEST_IMG | _filter_qemu_io
-mv $TEST_IMG $TEST_IMG.base
+$QEMU_IO -c "write -P 0x55 0 1M" "$TEST_IMG" | _filter_qemu_io
+mv "$TEST_IMG" "$TEST_IMG.base"
 
-_make_test_img -b $TEST_IMG.base 6G
+_make_test_img -b "$TEST_IMG.base" 6G
 
 echo
 echo "== zero write with backing file =="
-$QEMU_IO -c "write -z 64k 192k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "write -z 513k 13k" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write -z 64k 192k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -z 513k 13k" "$TEST_IMG" | _filter_qemu_io
 
 _check_test_img
 
 echo
 echo "== verifying patterns (3) =="
-$QEMU_IO -c "read -P 0x55 0 64k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x0 64k 192k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x55 256k 257k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x0 513k 13k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x55 526k 498k" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read -P 0x55 0 64k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x0 64k 192k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x55 256k 257k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x0 513k 13k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x55 526k 498k" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== overwriting zero cluster =="
-$QEMU_IO -c "write -P 0xa 60k 8k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "write -P 0xb 64k 8k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "write -P 0xc 76k 4k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "write -P 0xd 252k 8k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "write -P 0xe 248k 8k" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write -P 0xa 60k 8k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0xb 64k 8k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0xc 76k 4k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0xd 252k 8k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0xe 248k 8k" "$TEST_IMG" | _filter_qemu_io
 
 _check_test_img
 
 echo
 echo "== verifying patterns (4) =="
-$QEMU_IO -c "read -P 0x55 0 60k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0xa 60k 4k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0xb 64k 8k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x0 72k 4k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0xc 76k 4k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x0 80k 168k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0xe 248k 8k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0xd 256k 4k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x55 260k 64k" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read -P 0x55 0 60k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0xa 60k 4k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0xb 64k 8k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x0 72k 4k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0xc 76k 4k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x0 80k 168k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0xe 248k 8k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0xd 256k 4k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x55 260k 64k" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== re-zeroing overwritten area =="
-$QEMU_IO -c "write -z 64k 192k" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write -z 64k 192k" "$TEST_IMG" | _filter_qemu_io
 
 _check_test_img
 
 echo
 echo "== verifying patterns (5) =="
-$QEMU_IO -c "read -P 0x55 0 60k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0xa 60k 4k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x0 64k 192k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0xd 256k 4k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x55 260k 253k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x0 513k 13k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x55 526k 498k" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read -P 0x55 0 60k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0xa 60k 4k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x0 64k 192k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0xd 256k 4k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x55 260k 253k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x0 513k 13k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x55 526k 498k" "$TEST_IMG" | _filter_qemu_io
 
 # success, all done
 echo "*** done"
diff --git a/tests/qemu-iotests/035 b/tests/qemu-iotests/035
index 9d2d347..ebe9b8c 100755
--- a/tests/qemu-iotests/035
+++ b/tests/qemu-iotests/035
@@ -59,7 +59,7 @@ function generate_requests() {
     done
 }
 
-generate_requests | $QEMU_IO $TEST_IMG | _filter_qemu_io |\
+generate_requests | $QEMU_IO "$TEST_IMG" | _filter_qemu_io |\
 	sed -e 's/bytes at offset [0-9]*/bytes at offset XXX/g'
 
 echo
diff --git a/tests/qemu-iotests/036 b/tests/qemu-iotests/036
index 4dbfc57..e049a64 100755
--- a/tests/qemu-iotests/036
+++ b/tests/qemu-iotests/036
@@ -53,15 +53,15 @@ IMGOPTS="compat=1.1"
 echo === Create image with unknown autoclear feature bit ===
 echo
 _make_test_img 64M
-./qcow2.py $TEST_IMG set-feature-bit autoclear 63
-./qcow2.py $TEST_IMG dump-header
+./qcow2.py "$TEST_IMG" set-feature-bit autoclear 63
+./qcow2.py "$TEST_IMG" dump-header
 
 echo
 echo === Repair image ===
 echo
 _check_test_img -r all
 
-./qcow2.py $TEST_IMG dump-header
+./qcow2.py "$TEST_IMG" dump-header
 
 # success, all done
 echo "*** done"
diff --git a/tests/qemu-iotests/037 b/tests/qemu-iotests/037
index c11460b..743bae3 100755
--- a/tests/qemu-iotests/037
+++ b/tests/qemu-iotests/037
@@ -66,50 +66,50 @@ function backing_io()
     done
 }
 
-backing_io 0 256 write | $QEMU_IO $TEST_IMG | _filter_qemu_io
+backing_io 0 256 write | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
 
-mv $TEST_IMG $TEST_IMG.base
+mv "$TEST_IMG" "$TEST_IMG.base"
 
-_make_test_img -b $TEST_IMG.base 6G
+_make_test_img -b "$TEST_IMG.base" 6G
 
 echo
 echo "== COW in a single cluster =="
-$QEMU_IO -c "write -P 0x77 0 2k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "write -P 0x88 6k 2k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "write -P 0x99 9k 2k" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write -P 0x77 0 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x88 6k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x99 9k 2k" "$TEST_IMG" | _filter_qemu_io
 
-$QEMU_IO -c "read -P 0x77 0 2k" $TEST_IMG | _filter_qemu_io
-backing_io $((2 * 1024)) 8 read | $QEMU_IO $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x88 6k 2k" $TEST_IMG | _filter_qemu_io
-backing_io $((8 * 1024)) 2 read | $QEMU_IO $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x99 9k 2k" $TEST_IMG | _filter_qemu_io
-backing_io $((11 * 1024)) 2 read | $QEMU_IO $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read -P 0x77 0 2k" "$TEST_IMG" | _filter_qemu_io
+backing_io $((2 * 1024)) 8 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x88 6k 2k" "$TEST_IMG" | _filter_qemu_io
+backing_io $((8 * 1024)) 2 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x99 9k 2k" "$TEST_IMG" | _filter_qemu_io
+backing_io $((11 * 1024)) 2 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== COW in two-cluster allocations =="
-$QEMU_IO -c "write -P 0x77 16k 6k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "write -P 0x88 26k 6k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "write -P 0x99 33k 5k" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write -P 0x77 16k 6k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x88 26k 6k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x99 33k 5k" "$TEST_IMG" | _filter_qemu_io
 
-$QEMU_IO -c "read -P 0x77 16k 6k" $TEST_IMG | _filter_qemu_io
-backing_io $((22 * 1024)) 8 read | $QEMU_IO $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x88 26k 6k" $TEST_IMG | _filter_qemu_io
-backing_io $((32 * 1024)) 2 read | $QEMU_IO $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x99 33k 5k" $TEST_IMG | _filter_qemu_io
-backing_io $((38 * 1024)) 4 read | $QEMU_IO $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read -P 0x77 16k 6k" "$TEST_IMG" | _filter_qemu_io
+backing_io $((22 * 1024)) 8 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x88 26k 6k" "$TEST_IMG" | _filter_qemu_io
+backing_io $((32 * 1024)) 2 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x99 33k 5k" "$TEST_IMG" | _filter_qemu_io
+backing_io $((38 * 1024)) 4 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== COW in multi-cluster allocations =="
-$QEMU_IO -c "write -P 0x77 48k 15k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "write -P 0x88 66k 14k" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "write -P 0x99 83k 15k" $TEST_IMG | _filter_qemu_io
-
-$QEMU_IO -c "read -P 0x77 48k 15k" $TEST_IMG | _filter_qemu_io
-backing_io $((63 * 1024)) 6 read | $QEMU_IO $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x88 66k 14k" $TEST_IMG | _filter_qemu_io
-backing_io $((80 * 1024)) 6 read | $QEMU_IO $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0x99 83k 15k" $TEST_IMG | _filter_qemu_io
-backing_io $((98 * 1024)) 4 read | $QEMU_IO $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write -P 0x77 48k 15k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x88 66k 14k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x99 83k 15k" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0x77 48k 15k" "$TEST_IMG" | _filter_qemu_io
+backing_io $((63 * 1024)) 6 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x88 66k 14k" "$TEST_IMG" | _filter_qemu_io
+backing_io $((80 * 1024)) 6 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x99 83k 15k" "$TEST_IMG" | _filter_qemu_io
+backing_io $((98 * 1024)) 4 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
 
 _check_test_img
 
diff --git a/tests/qemu-iotests/038 b/tests/qemu-iotests/038
index 90de1a7..7bb7906 100755
--- a/tests/qemu-iotests/038
+++ b/tests/qemu-iotests/038
@@ -66,11 +66,11 @@ function backing_io()
     done
 }
 
-backing_io 0 256 write | $QEMU_IO $TEST_IMG | _filter_qemu_io
+backing_io 0 256 write | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
 
-mv $TEST_IMG $TEST_IMG.base
+mv "$TEST_IMG" "$TEST_IMG.base"
 
-_make_test_img -b $TEST_IMG.base 6G
+_make_test_img -b "$TEST_IMG.base" 6G
 
 echo
 echo "== Some concurrent requests touching the same cluster =="
@@ -94,7 +94,7 @@ function overlay_io()
     echo aio_write -P 0x90 4080k 80k
 }
 
-overlay_io | $QEMU_IO $TEST_IMG | _filter_qemu_io |\
+overlay_io | $QEMU_IO "$TEST_IMG" | _filter_qemu_io |\
     sed -e 's/bytes at offset [0-9]*/bytes at offset XXX/g' \
     -e 's/qemu-io> //g' | paste - - | sort | tr '\t' '\n'
 
@@ -124,7 +124,7 @@ function verify_io()
     done
 }
 
-verify_io | $QEMU_IO $TEST_IMG | _filter_qemu_io
+verify_io | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
 
 _check_test_img
 
diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039
index ae35175..f85b4ce 100755
--- a/tests/qemu-iotests/039
+++ b/tests/qemu-iotests/039
@@ -54,10 +54,10 @@ echo "== Checking that image is clean on shutdown =="
 IMGOPTS="compat=1.1,lazy_refcounts=on"
 _make_test_img $size
 
-$QEMU_IO -c "write -P 0x5a 0 512" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write -P 0x5a 0 512" ""$TEST_IMG"" | _filter_qemu_io
 
 # The dirty bit must not be set
-./qcow2.py $TEST_IMG dump-header | grep incompatible_features
+./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
 _check_test_img
 
 echo
@@ -68,20 +68,20 @@ _make_test_img $size
 
 old_ulimit=$(ulimit -c)
 ulimit -c 0 # do not produce a core dump on abort(3)
-$QEMU_IO -c "write -P 0x5a 0 512" -c "abort" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write -P 0x5a 0 512" -c "abort" "$TEST_IMG" | _filter_qemu_io
 ulimit -c "$old_ulimit"
 
 # The dirty bit must be set
-./qcow2.py $TEST_IMG dump-header | grep incompatible_features
+./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
 _check_test_img
 
 echo
 echo "== Read-only access must still work =="
 
-$QEMU_IO -r -c "read -P 0x5a 0 512" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -r -c "read -P 0x5a 0 512" "$TEST_IMG" | _filter_qemu_io
 
 # The dirty bit must be set
-./qcow2.py $TEST_IMG dump-header | grep incompatible_features
+./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
 
 echo
 echo "== Repairing the image file must succeed =="
@@ -89,12 +89,12 @@ echo "== Repairing the image file must succeed =="
 _check_test_img -r all
 
 # The dirty bit must not be set
-./qcow2.py $TEST_IMG dump-header | grep incompatible_features
+./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
 
 echo
 echo "