Merge remote-tracking branch 'otubo/seccomp' into staging
authorAnthony Liguori <aliguori@amazon.com>
Thu, 10 Oct 2013 20:15:46 +0000 (13:15 -0700)
committerAnthony Liguori <aliguori@amazon.com>
Thu, 10 Oct 2013 20:15:46 +0000 (13:15 -0700)
# By Eduardo Otubo
# Via Eduardo Otubo
* otubo/seccomp:
  seccomp: fine tuning whitelist by adding times()

Message-id: 1380047458-21673-1-git-send-email-otubo@linux.vnet.ibm.com
Signed-off-by: Anthony Liguori <aliguori@amazon.com>
179 files changed:
MAINTAINERS
arch_init.c
audio/mixeng.c
block.c
block/gluster.c
block/iscsi.c
block/qcow2-cluster.c
block/qcow2-refcount.c
block/qcow2.c
block/qcow2.h
block/qed.h
block/raw-posix.c
block/raw-win32.c
block/rbd.c
block/sheepdog.c
block/stream.c
block/vdi.c
block/vhdx.c
block/vmdk.c
block/vpc.c
blockdev.c
configure
exec.c
gdbstub.c
hw/9pfs/virtio-9p-xattr.c
hw/acpi/core.c
hw/acpi/piix4.c
hw/alpha/typhoon.c
hw/audio/hda-codec-common.h [new file with mode: 0644]
hw/audio/hda-codec.c
hw/block/xen_disk.c
hw/char/Makefile.objs
hw/char/sclpconsole-lm.c [new file with mode: 0644]
hw/char/sclpconsole.c
hw/char/sh_serial.c
hw/i386/pc_piix.c
hw/i386/smbios.c
hw/net/virtio-net.c
hw/pci-host/piix.c
hw/pci-host/q35.c
hw/pci/pci.c
hw/s390x/event-facility.c
hw/s390x/sclpquiesce.c
hw/scsi/scsi-bus.c
hw/usb/hcd-ohci.c
hw/xen/xen_backend.c
include/block/block_int.h
include/exec/exec-all.h
include/hw/i386/smbios.h
include/hw/pci/pci.h
include/hw/s390x/ebcdic.h [new file with mode: 0644]
include/hw/s390x/event-facility.h
include/hw/scsi/scsi.h
include/migration/vmstate.h
include/qapi/qmp/qdict.h
include/qemu/bitops.h
include/qemu/range.h
include/qemu/sockets.h
include/qemu/typedefs.h
include/sysemu/arch_init.h
include/sysemu/sysemu.h
linux-user/alpha/syscall_nr.h
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.img
pc-bios/s390-ccw/virtio.c
pc-bios/s390-ccw/virtio.h
qemu-char.c
qobject/qdict.c
roms/Makefile
roms/config.vga-cirrus [moved from roms/config.vga.cirrus with 100% similarity]
roms/config.vga-isavga [moved from roms/config.vga.isavga with 100% similarity]
roms/config.vga-qxl [moved from roms/config.vga.qxl with 100% similarity]
roms/config.vga-stdvga [moved from roms/config.vga.stdvga with 100% similarity]
roms/config.vga-vmware [moved from roms/config.vga.vmware with 100% similarity]
roms/openbios
roms/seabios
savevm.c
scripts/refresh-pxe-roms.sh
slirp/misc.c
slirp/socket.c
slirp/tcp_subr.c
slirp/udp.c
target-arm/iwmmxt_helper.c
target-i386/arch_memory_mapping.c
target-s390x/arch_dump.c
target-s390x/cpu.h
target-s390x/ioinst.c
target-s390x/ioinst.h
target-s390x/kvm.c
target-s390x/misc_helper.c
tcg/arm/tcg-target.c
tcg/optimize.c
tcg/ppc/tcg-target.c
tcg/ppc64/tcg-target.c
tcg/tci/tcg-target.c
tci.c
tests/.gitignore
tests/Makefile
tests/qemu-iotests/.gitignore
tests/qemu-iotests/001
tests/qemu-iotests/002
tests/qemu-iotests/003
tests/qemu-iotests/004
tests/qemu-iotests/005
tests/qemu-iotests/007
tests/qemu-iotests/008
tests/qemu-iotests/009
tests/qemu-iotests/010
tests/qemu-iotests/011
tests/qemu-iotests/012
tests/qemu-iotests/013
tests/qemu-iotests/014
tests/qemu-iotests/015
tests/qemu-iotests/016
tests/qemu-iotests/018
tests/qemu-iotests/019
tests/qemu-iotests/020
tests/qemu-iotests/021
tests/qemu-iotests/023
tests/qemu-iotests/024
tests/qemu-iotests/025
tests/qemu-iotests/026
tests/qemu-iotests/026.out
tests/qemu-iotests/026.out.nocache
tests/qemu-iotests/027
tests/qemu-iotests/028
tests/qemu-iotests/029
tests/qemu-iotests/031
tests/qemu-iotests/032
tests/qemu-iotests/033
tests/qemu-iotests/034
tests/qemu-iotests/035
tests/qemu-iotests/036
tests/qemu-iotests/037
tests/qemu-iotests/038
tests/qemu-iotests/039
tests/qemu-iotests/042
tests/qemu-iotests/043
tests/qemu-iotests/046
tests/qemu-iotests/047
tests/qemu-iotests/048
tests/qemu-iotests/049
tests/qemu-iotests/050
tests/qemu-iotests/051
tests/qemu-iotests/051.out
tests/qemu-iotests/052
tests/qemu-iotests/053
tests/qemu-iotests/054
tests/qemu-iotests/059
tests/qemu-iotests/059.out
tests/qemu-iotests/061
tests/qemu-iotests/061.out
tests/qemu-iotests/063
tests/qemu-iotests/common.config
tests/qemu-iotests/common.rc
tests/qemu-iotests/iotests.py
tests/qemu-iotests/sample_images/README [new file with mode: 0644]
util/oslib-posix.c
util/oslib-win32.c
util/path.c
util/qemu-sockets.c
vl.c
xen-all.c

index 0431d09..fbe1fd9 100644 (file)
@@ -50,8 +50,7 @@ Descriptions of section entries:
 
 General Project Administration
 ------------------------------
-M: Anthony Liguori <anthony@codemonkey.ws>
-M: Paul Brook <paul@codesourcery.com>
+M: Anthony Liguori <aliguori@amazon.com>
 
 Guest CPU cores (TCG):
 ----------------------
@@ -62,7 +61,6 @@ F: target-alpha/
 F: hw/alpha/
 
 ARM
-M: Paul Brook <paul@codesourcery.com>
 M: Peter Maydell <peter.maydell@linaro.org>
 S: Maintained
 F: target-arm/
@@ -83,8 +81,7 @@ F: hw/lm32/
 F: hw/char/lm32_*
 
 M68K
-M: Paul Brook <paul@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@codesourcery.com>
 M: Peter Maydell <peter.maydell@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@codesourcery.com>
 M: Peter Maydell <peter.maydell@linaro.org>
 S: Maintained
 F: hw/arm/realview*
@@ -285,13 +280,11 @@ S: Maintained
 F: hw/arm/spitz.c
 
 Stellaris
-M: Paul Brook <paul@codesourcery.com>
 M: Peter Maydell <peter.maydell@linaro.org>
 S: Maintained
 F: hw/*/stellaris*
 
 Versatile PB
-M: Paul Brook <paul@codesourcery.com>
 M: Peter Maydell <peter.maydell@linaro.org>
 S: Maintained
 F: hw/*/versatile*
@@ -327,18 +320,15 @@ F: hw/lm32/milkymist.c
 M68K Machines
 -------------
 an5206
-M: Paul Brook <paul@codesourcery.com>
-S: Maintained
+S: Orphan
 F: hw/m68k/an5206.c
 
 dummy_m68k
-M: Paul Brook <paul@codesourcery.com>
-S: Maintained
+S: Orphan
 F: hw/m68k/dummy_m68k.c
 
 mcf5208
-M: Paul Brook <paul@codesourcery.com>
-S: Maintained
+S: Orphan
 F: hw/m68k/mcf5208.c
 
 MicroBlaze Machines
@@ -509,7 +499,7 @@ F: hw/unicore32/
 X86 Machines
 ------------
 PC
-M: Anthony Liguori <anthony@codemonkey.ws>
+M: Anthony Liguori <aliguori@amazon.com>
 S: Supported
 F: hw/i386/pc.[ch]
 F: hw/i386/pc_piix.c
@@ -567,8 +557,7 @@ F: hw/scsi/*
 T: git git://github.com/bonzini/qemu.git scsi-next
 
 LSI53C895A
-M: Paul Brook <paul@codesourcery.com>
-S: Odd Fixes
+S: Orphan
 F: hw/scsi/lsi53c895a.c
 
 SSI
@@ -593,7 +582,7 @@ S: Supported
 F: hw/*/*vhost*
 
 virtio
-M: Anthony Liguori <anthony@codemonkey.ws>
+M: Anthony Liguori <aliguori@amazon.com>
 S: Supported
 F: hw/*/virtio*
 
@@ -638,6 +627,7 @@ Subsystems
 ----------
 Audio
 M: Vassili Karpov (malc) <av1474@comtv.ru>
+M: Gerd Hoffmann <kraxel@redhat.com>
 S: Maintained
 F: audio/
 F: hw/audio/
@@ -651,7 +641,7 @@ F: block/
 F: hw/block/
 
 Character Devices
-M: Anthony Liguori <anthony@codemonkey.ws>
+M: Anthony Liguori <aliguori@amazon.com>
 S: Maintained
 F: qemu-char.c
 
@@ -689,7 +679,7 @@ F: audio/spiceaudio.c
 F: hw/display/qxl*
 
 Graphics
-M: Anthony Liguori <anthony@codemonkey.ws>
+M: Anthony Liguori <aliguori@amazon.com>
 S: Maintained
 F: ui/
 
@@ -699,7 +689,7 @@ S: Odd Fixes
 F: ui/cocoa.m
 
 Main loop
-M: Anthony Liguori <anthony@codemonkey.ws>
+M: Anthony Liguori <aliguori@amazon.com>
 S: Supported
 F: vl.c
 
@@ -711,7 +701,7 @@ F: hmp.c
 F: hmp-commands.hx
 
 Network device layer
-M: Anthony Liguori <anthony@codemonkey.ws>
+M: Anthony Liguori <aliguori@amazon.com>
 M: Stefan Hajnoczi <stefanha@redhat.com>
 S: Maintained
 F: net/
index e47e139..7545d96 100644 (file)
@@ -150,10 +150,9 @@ int qemu_read_default_config_files(bool userconfig)
     return 0;
 }
 
-static inline bool is_zero_page(uint8_t *p)
+static inline bool is_zero_range(uint8_t *p, uint64_t size)
 {
-    return buffer_find_nonzero_offset(p, TARGET_PAGE_SIZE) ==
-        TARGET_PAGE_SIZE;
+    return buffer_find_nonzero_offset(p, size) == size;
 }
 
 /* struct contains XBZRLE cache and a static page
@@ -497,7 +496,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
                         acct_info.dup_pages++;
                     }
                 }
-            } else if (is_zero_page(p)) {
+            } else if (is_zero_range(p, TARGET_PAGE_SIZE)) {
                 acct_info.dup_pages++;
                 bytes_sent = save_block_hdr(f, block, offset, cont,
                                             RAM_SAVE_FLAG_COMPRESS);
@@ -710,15 +709,20 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
      */
     ram_control_after_iterate(f, RAM_CONTROL_ROUND);
 
+    bytes_transferred += total_sent;
+
+    /*
+     * Do not count these 8 bytes into total_sent, so that we can
+     * return 0 if no page had been dirtied.
+     */
+    qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
+    bytes_transferred += 8;
+
+    ret = qemu_file_get_error(f);
     if (ret < 0) {
-        bytes_transferred += total_sent;
         return ret;
     }
 
-    qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
-    total_sent += 8;
-    bytes_transferred += total_sent;
-
     return total_sent;
 }
 
@@ -844,13 +848,14 @@ static inline void *host_from_stream_offset(QEMUFile *f,
  */
 void ram_handle_compressed(void *host, uint8_t ch, uint64_t size)
 {
-    if (ch != 0 || !is_zero_page(host)) {
+    if (ch != 0 || !is_zero_range(host, size)) {
         memset(host, ch, size);
 #ifndef _WIN32
-        if (ch == 0 &&
-            (!kvm_enabled() || kvm_has_sync_mmu()) &&
-            getpagesize() <= TARGET_PAGE_SIZE) {
-            qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
+        if (ch == 0 && (!kvm_enabled() || kvm_has_sync_mmu())) {
+            size = size & ~(getpagesize() - 1);
+            if (size > 0) {
+                qemu_madvise(host, size, QEMU_MADV_DONTNEED);
+            }
         }
 #endif
     }
@@ -1113,9 +1118,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;
 }
 
@@ -1134,12 +1136,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
-    if (smbios_entry_add(optarg) < 0) {
-        exit(1);
-    }
+    smbios_entry_add(opts);
 #endif
 }
 
index 02a9d9f..0e4976f 100644 (file)
@@ -348,7 +348,6 @@ void mixeng_clear (struct st_sample *buf, int len)
 
 void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol)
 {
-#ifdef CONFIG_MIXEMU
     if (vol->mute) {
         mixeng_clear (buf, len);
         return;
@@ -364,9 +363,4 @@ void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol)
 #endif
         buf += 1;
     }
-#else
-    (void) buf;
-    (void) len;
-    (void) vol;
-#endif
 }
diff --git a/block.c b/block.c
index ea4956d..d7ca37e 100644 (file)
--- a/block.c
+++ b/block.c
@@ -792,7 +792,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
     /* Open the image, either directly or using a protocol */
     if (drv->bdrv_file_open) {
         assert(file == NULL);
-        assert(drv->bdrv_parse_filename || filename != NULL);
+        assert(!drv->bdrv_needs_filename || filename != NULL);
         ret = drv->bdrv_file_open(bs, options, open_flags, &local_err);
     } else {
         if (file == NULL) {
@@ -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");
         }
@@ -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;
@@ -911,7 +911,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
             goto fail;
         }
         qdict_del(options, "filename");
-    } else if (!drv->bdrv_parse_filename && !filename) {
+    } else if (drv->bdrv_needs_filename && !filename) {
         error_setg(errp, "The '%s' block driver requires a file name",
                    drv->format_name);
         ret = -EINVAL;
@@ -978,11 +978,12 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
     } else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) {
         QDECREF(options);
         return 0;
+    } else {
+        bdrv_get_full_backing_filename(bs, backing_filename,
+                                       sizeof(backing_filename));
     }
 
     bs->backing_hd = bdrv_new("");
-    bdrv_get_full_backing_filename(bs, backing_filename,
-                                   sizeof(backing_filename));
 
     if (bs->backing_format[0] != '\0') {
         back_drv = bdrv_find_format(bs->backing_format);
@@ -994,6 +995,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
     ret = bdrv_open(bs->backing_hd,
                     *backing_filename ? backing_filename : NULL, options,
                     back_flags, back_drv, &local_err);
+    pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+            bs->backing_hd->file->filename);
     if (ret < 0) {
         bdrv_unref(bs->backing_hd);
         bs->backing_hd = NULL;
@@ -1004,25 +1007,6 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
     return 0;
 }
 
-static void extract_subqdict(QDict *src, QDict **dst, const char *start)
-{
-    const QDictEntry *entry, *next;
-    const char *p;
-
-    *dst = qdict_new();
-    entry = qdict_first(src);
-
-    while (entry != NULL) {
-        next = qdict_next(src, entry);
-        if (strstart(entry->key, start, &p)) {
-            qobject_incref(entry->value);
-            qdict_put_obj(*dst, p, entry->value);
-            qdict_del(src, entry->key);
-        }
-        entry = next;
-    }
-}
-
 /*
  * Opens a disk image (raw, qcow2, vmdk, ...)
  *
@@ -1128,7 +1112,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
         flags |= BDRV_O_ALLOW_RDWR;
     }
 
-    extract_subqdict(options, &file_options, "file.");
+    qdict_extract_subqdict(options, &file_options, "file.");
 
     ret = bdrv_file_open(&file, filename, file_options,
                          bdrv_open_flags(bs, flags | BDRV_O_UNMAP), &local_err);
@@ -1166,7 +1150,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
     if ((flags & BDRV_O_NO_BACKING) == 0) {
         QDict *backing_options;
 
-        extract_subqdict(options, &backing_options, "backing.");
+        qdict_extract_subqdict(options, &backing_options, "backing.");
         ret = bdrv_open_backing_file(bs, backing_options, &local_err);
         if (ret < 0) {
             goto close_and_fail;
@@ -2669,7 +2653,7 @@ static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs,
             goto out;
         }
 
-        total_sectors = (len + BDRV_SECTOR_SIZE - 1) >> BDRV_SECTOR_BITS;
+        total_sectors = DIV_ROUND_UP(len, BDRV_SECTOR_SIZE);
         max_nb_sectors = MAX(0, total_sectors - sector_num);
         if (max_nb_sectors > 0) {
             ret = drv->bdrv_co_readv(bs, sector_num,
@@ -3159,13 +3143,14 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
 
     ret = bs->drv->bdrv_co_get_block_status(bs, sector_num, nb_sectors, pnum);
     if (ret < 0) {
+        *pnum = 0;
         return ret;
     }
 
     if (!(ret & BDRV_BLOCK_DATA)) {
         if (bdrv_has_zero_init(bs)) {
             ret |= BDRV_BLOCK_ZERO;
-        } else {
+        } else if (bs->backing_hd) {
             BlockDriverState *bs2 = bs->backing_hd;
             int64_t length2 = bdrv_getlength(bs2);
             if (length2 >= 0 && sector_num >= (length2 >> BDRV_SECTOR_BITS)) {
index 256de10..877686a 100644 (file)
@@ -611,6 +611,7 @@ static BlockDriver bdrv_gluster = {
     .format_name                  = "gluster",
     .protocol_name                = "gluster",
     .instance_size                = sizeof(BDRVGlusterState),
+    .bdrv_needs_filename          = true,
     .bdrv_file_open               = qemu_gluster_open,
     .bdrv_close                   = qemu_gluster_close,
     .bdrv_create                  = qemu_gluster_create,
@@ -631,6 +632,7 @@ static BlockDriver bdrv_gluster_tcp = {
     .format_name                  = "gluster",
     .protocol_name                = "gluster+tcp",
     .instance_size                = sizeof(BDRVGlusterState),
+    .bdrv_needs_filename          = true,
     .bdrv_file_open               = qemu_gluster_open,
     .bdrv_close                   = qemu_gluster_close,
     .bdrv_create                  = qemu_gluster_create,
@@ -651,6 +653,7 @@ static BlockDriver bdrv_gluster_unix = {
     .format_name                  = "gluster",
     .protocol_name                = "gluster+unix",
     .instance_size                = sizeof(BDRVGlusterState),
+    .bdrv_needs_filename          = true,
     .bdrv_file_open               = qemu_gluster_open,
     .bdrv_close                   = qemu_gluster_close,
     .bdrv_create                  = qemu_gluster_create,
@@ -671,6 +674,7 @@ static BlockDriver bdrv_gluster_rdma = {
     .format_name                  = "gluster",
     .protocol_name                = "gluster+rdma",
     .instance_size                = sizeof(BDRVGlusterState),
+    .bdrv_needs_filename          = true,
     .bdrv_file_open               = qemu_gluster_open,
     .bdrv_close                   = qemu_gluster_close,
     .bdrv_create                  = qemu_gluster_create,
index 4460382..a2a961e 100644 (file)
@@ -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,
@@ -1520,6 +1520,7 @@ static BlockDriver bdrv_iscsi = {
     .protocol_name   = "iscsi",
 
     .instance_size   = sizeof(IscsiLun),
+    .bdrv_needs_filename = true,
     .bdrv_file_open  = iscsi_open,
     .bdrv_close      = iscsi_close,
     .bdrv_create     = iscsi_create,
@@ -1528,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,
index 738ff73..0fd26bb 100644 (file)
@@ -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);
@@ -188,7 +191,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;
 
@@ -200,7 +203,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 +217,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;
@@ -265,8 +269,14 @@ 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;
+    if (l2_offset > 0) {
+        qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t),
+                            QCOW2_DISCARD_ALWAYS);
+    }
     return ret;
 }
 
@@ -278,23 +288,26 @@ 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;
-    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;
 
-    for (i = start; i < start + nb_clusters; i++) {
+    assert(qcow2_get_cluster_type(first_entry) != QCOW2_CLUSTER_COMPRESSED);
+
+    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)
@@ -487,8 +500,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], QCOW_OFLAG_ZERO);
         *cluster_offset = 0;
         break;
     case QCOW2_CLUSTER_UNALLOCATED:
@@ -499,8 +511,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], QCOW_OFLAG_ZERO);
         *cluster_offset &= L2E_OFFSET_MASK;
         break;
     default:
@@ -716,6 +727,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
     }
     qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
 
+    assert(l2_index + m->nb_clusters <= s->l2_size);
     for (i = 0; i < m->nb_clusters; i++) {
         /* if two concurrent writes happen to the same unallocated cluster
         * each write allocates separate cluster and writes data concurrently.
@@ -929,7 +941,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);
 
@@ -1509,8 +1521,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);
@@ -1550,11 +1562,12 @@ 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;
-                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
@@ -1575,8 +1588,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 */
@@ -1595,16 +1607,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;
             }
 
@@ -1612,8 +1628,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) {
@@ -1672,18 +1705,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;
     }
@@ -1717,7 +1749,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;
         }
index 4264148..2d67885 100644 (file)
@@ -874,7 +874,6 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
                         nb_csectors = ((offset >> s->csize_shift) &
                                        s->csize_mask) + 1;
                         if (addend != 0) {
-                            int ret;
                             ret = update_refcount(bs,
                                 (offset & s->cluster_offset_mask) & ~511,
                                 nb_csectors * 512, addend,
@@ -1035,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 */
 };
 
@@ -1482,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;
     }
@@ -1734,8 +1731,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;
                 }
index 318d95d..4a9888c 100644 (file)
@@ -52,7 +52,7 @@
 typedef struct {
     uint32_t magic;
     uint32_t len;
-} QCowExtension;
+} QEMU_PACKED QCowExtension;
 
 #define  QCOW2_EXT_MAGIC_END 0
 #define  QCOW2_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA
index c90e5d6..455e38d 100644 (file)
@@ -86,7 +86,7 @@ typedef struct QCowHeader {
 
     uint32_t refcount_order;
     uint32_t header_length;
-} QCowHeader;
+} QEMU_PACKED QCowHeader;
 
 typedef struct QCowSnapshot {
     uint64_t l1_table_offset;
index 2b4dded..5d65bea 100644 (file)
@@ -100,7 +100,7 @@ typedef struct {
     /* if (features & QED_F_BACKING_FILE) */
     uint32_t backing_filename_offset; /* in bytes from start of header */
     uint32_t backing_filename_size;   /* in bytes */
-} QEDHeader;
+} QEMU_PACKED QEDHeader;
 
 typedef struct {
     uint64_t offsets[0];            /* in bytes */
index 3ee5b62..f7f102d 100644 (file)
@@ -1200,6 +1200,7 @@ static BlockDriver bdrv_file = {
     .format_name = "file",
     .protocol_name = "file",
     .instance_size = sizeof(BDRVRawState),
+    .bdrv_needs_filename = true,
     .bdrv_probe = NULL, /* no probe for protocols */
     .bdrv_file_open = raw_open,
     .bdrv_reopen_prepare = raw_reopen_prepare,
@@ -1542,6 +1543,7 @@ static BlockDriver bdrv_host_device = {
     .format_name        = "host_device",
     .protocol_name        = "host_device",
     .instance_size      = sizeof(BDRVRawState),
+    .bdrv_needs_filename = true,
     .bdrv_probe_device  = hdev_probe_device,
     .bdrv_file_open     = hdev_open,
     .bdrv_close         = raw_close,
@@ -1667,6 +1669,7 @@ static BlockDriver bdrv_host_floppy = {
     .format_name        = "host_floppy",
     .protocol_name      = "host_floppy",
     .instance_size      = sizeof(BDRVRawState),
+    .bdrv_needs_filename = true,
     .bdrv_probe_device = floppy_probe_device,
     .bdrv_file_open     = floppy_open,
     .bdrv_close         = raw_close,
@@ -1769,6 +1772,7 @@ static BlockDriver bdrv_host_cdrom = {
     .format_name        = "host_cdrom",
     .protocol_name      = "host_cdrom",
     .instance_size      = sizeof(BDRVRawState),
+    .bdrv_needs_filename = true,
     .bdrv_probe_device = cdrom_probe_device,
     .bdrv_file_open     = cdrom_open,
     .bdrv_close         = raw_close,
@@ -1890,6 +1894,7 @@ static BlockDriver bdrv_host_cdrom = {
     .format_name        = "host_cdrom",
     .protocol_name      = "host_cdrom",
     .instance_size      = sizeof(BDRVRawState),
+    .bdrv_needs_filename = true,
     .bdrv_probe_device = cdrom_probe_device,
     .bdrv_file_open     = cdrom_open,
     .bdrv_close         = raw_close,
index 1e7651b..6ef320f 100644 (file)
@@ -459,6 +459,7 @@ static BlockDriver bdrv_file = {
     .format_name       = "file",
     .protocol_name     = "file",
     .instance_size     = sizeof(BDRVRawState),
+    .bdrv_needs_filename = true,
     .bdrv_file_open    = raw_open,
     .bdrv_close                = raw_close,
     .bdrv_create       = raw_create,
@@ -601,6 +602,7 @@ static BlockDriver bdrv_host_device = {
     .format_name       = "host_device",
     .protocol_name     = "host_device",
     .instance_size     = sizeof(BDRVRawState),
+    .bdrv_needs_filename = true,
     .bdrv_probe_device = hdev_probe_device,
     .bdrv_file_open    = hdev_open,
     .bdrv_close                = raw_close,
index 11086c3..4a1ea5b 100644 (file)
@@ -943,7 +943,7 @@ static int qemu_rbd_snap_list(BlockDriverState *bs,
     do {
         snaps = g_malloc(sizeof(*snaps) * max_snaps);
         snap_count = rbd_snap_list(s->image, snaps, &max_snaps);
-        if (snap_count < 0) {
+        if (snap_count <= 0) {
             g_free(snaps);
         }
     } while (snap_count == -ERANGE);
@@ -967,6 +967,7 @@ static int qemu_rbd_snap_list(BlockDriverState *bs,
         sn_info->vm_clock_nsec = 0;
     }
     rbd_snap_list_end(snaps);
+    g_free(snaps);
 
  done:
     *psn_tab = sn_tab;
@@ -1002,6 +1003,7 @@ static QEMUOptionParameter qemu_rbd_create_options[] = {
 static BlockDriver bdrv_rbd = {
     .format_name        = "rbd",
     .instance_size      = sizeof(BDRVRBDState),
+    .bdrv_needs_filename = true,
     .bdrv_file_open     = qemu_rbd_open,
     .bdrv_close         = qemu_rbd_close,
     .bdrv_create        = qemu_rbd_create,
index 38fb629..5f81c93 100644 (file)
@@ -2338,6 +2338,7 @@ static BlockDriver bdrv_sheepdog = {
     .format_name    = "sheepdog",
     .protocol_name  = "sheepdog",
     .instance_size  = sizeof(BDRVSheepdogState),
+    .bdrv_needs_filename = true,
     .bdrv_file_open = sd_open,
     .bdrv_close     = sd_close,
     .bdrv_create    = sd_create,
@@ -2366,6 +2367,7 @@ static BlockDriver bdrv_sheepdog_tcp = {
     .format_name    = "sheepdog",
     .protocol_name  = "sheepdog+tcp",
     .instance_size  = sizeof(BDRVSheepdogState),
+    .bdrv_needs_filename = true,
     .bdrv_file_open = sd_open,
     .bdrv_close     = sd_close,
     .bdrv_create    = sd_create,
@@ -2394,6 +2396,7 @@ static BlockDriver bdrv_sheepdog_unix = {
     .format_name    = "sheepdog",
     .protocol_name  = "sheepdog+unix",
     .instance_size  = sizeof(BDRVSheepdogState),
+    .bdrv_needs_filename = true,
     .bdrv_file_open = sd_open,
     .bdrv_close     = sd_close,
     .bdrv_create    = sd_create,
index 078ce4a..45837f4 100644 (file)
@@ -119,11 +119,12 @@ wait:
             break;
         }
 
+        copy = false;
+
         ret = bdrv_is_allocated(bs, sector_num,
                                 STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE, &n);
         if (ret == 1) {
             /* Allocated in the top, no need to copy.  */
-            copy = false;
         } else if (ret >= 0) {
             /* Copy if allocated in the intermediate images.  Limit to the
              * known-unallocated area [sector_num, sector_num+n).  */
@@ -138,7 +139,7 @@ wait:
             copy = (ret == 1);
         }
         trace_stream_one_iteration(s, sector_num, n, ret);
-        if (ret >= 0 && copy) {
+        if (copy) {
             if (s->common.speed) {
                 delay_ns = ratelimit_calculate_delay(&s->limit, n);
                 if (delay_ns > 0) {
index dcbc27c..b6ec002 100644 (file)
@@ -165,7 +165,7 @@ typedef struct {
     uuid_t uuid_link;
     uuid_t uuid_parent;
     uint64_t unused2[7];
-} VdiHeader;
+} QEMU_PACKED VdiHeader;
 
 typedef struct {
     /* The block map entries are little endian (even in memory). */
index b8aa49c..6cb0412 100644 (file)
@@ -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 = {
index 96ef1b5..5d56e31 100644 (file)
@@ -105,7 +105,7 @@ typedef struct VmdkExtent {
     uint32_t l2_cache_offsets[L2_CACHE_SIZE];
     uint32_t l2_cache_counts[L2_CACHE_SIZE];
 
-    unsigned int cluster_sectors;
+    int64_t cluster_sectors;
 } VmdkExtent;
 
 typedef struct BDRVVmdkState {
@@ -424,7 +424,7 @@ static int vmdk_add_extent(BlockDriverState *bs,
     extent->l1_size = l1_size;
     extent->l1_entry_sectors = l2_size * cluster_sectors;
     extent->l2_size = l2_size;
-    extent->cluster_sectors = cluster_sectors;
+    extent->cluster_sectors = flat ? sectors : cluster_sectors;
 
     if (s->num_extents > 1) {
         extent->end_sector = (*(extent - 1)).end_sector + extent->sectors;
@@ -741,7 +741,7 @@ 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, sectors, &extent);
+                            0, 0, 0, 0, 0, &extent);
             if (ret < 0) {
                 return ret;
             }
index db61274..b5dca39 100644 (file)
@@ -46,7 +46,7 @@ enum vhd_type {
 #define VHD_TIMESTAMP_BASE 946684800
 
 // always big-endian
-struct vhd_footer {
+typedef struct vhd_footer {
     char        creator[8]; // "conectix"
     uint32_t    features;
     uint32_t    version;
@@ -79,9 +79,9 @@ struct vhd_footer {
     uint8_t     uuid[16];
 
     uint8_t     in_saved_state;
-};
+} QEMU_PACKED VHDFooter;
 
-struct vhd_dyndisk_header {
+typedef struct vhd_dyndisk_header {
     char        magic[8]; // "cxsparse"
 
     // Offset of next header structure, 0xFFFFFFFF if none
@@ -111,7 +111,7 @@ struct vhd_dyndisk_header {
         uint32_t    reserved;
         uint64_t    data_offset;
     } parent_locator[8];
-};
+} QEMU_PACKED VHDDynDiskHeader;
 
 typedef struct BDRVVPCState {
     CoMutex lock;
@@ -160,8 +160,8 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
 {
     BDRVVPCState *s = bs->opaque;
     int i;
-    struct vhd_footer* footer;
-    struct vhd_dyndisk_header* dyndisk_header;
+    VHDFooter *footer;
+    VHDDynDiskHeader *dyndisk_header;
     uint8_t buf[HEADER_SIZE];
     uint32_t checksum;
     int disk_type = VHD_DYNAMIC;
@@ -172,7 +172,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
         goto fail;
     }
 
-    footer = (struct vhd_footer*) s->footer_buf;
+    footer = (VHDFooter *) s->footer_buf;
     if (strncmp(footer->creator, "conectix", 8)) {
         int64_t offset = bdrv_getlength(bs->file);
         if (offset < 0) {
@@ -224,7 +224,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
             goto fail;
         }
 
-        dyndisk_header = (struct vhd_dyndisk_header *) buf;
+        dyndisk_header = (VHDDynDiskHeader *) buf;
 
         if (strncmp(dyndisk_header->magic, "cxsparse", 8)) {
             ret = -EINVAL;
@@ -446,7 +446,7 @@ static int vpc_read(BlockDriverState *bs, int64_t sector_num,
     int ret;
     int64_t offset;
     int64_t sectors, sectors_per_block;
-    struct vhd_footer *footer = (struct vhd_footer *) s->footer_buf;
+    VHDFooter *footer = (VHDFooter *) s->footer_buf;
 
     if (cpu_to_be32(footer->type) == VHD_FIXED) {
         return bdrv_read(bs->file, sector_num, buf, nb_sectors);
@@ -495,7 +495,7 @@ static int vpc_write(BlockDriverState *bs, int64_t sector_num,
     int64_t offset;
     int64_t sectors, sectors_per_block;
     int ret;
-    struct vhd_footer *footer =  (struct vhd_footer *) s->footer_buf;
+    VHDFooter *footer =  (VHDFooter *) s->footer_buf;
 
     if (cpu_to_be32(footer->type) == VHD_FIXED) {
         return bdrv_write(bs->file, sector_num, buf, nb_sectors);
@@ -597,8 +597,8 @@ static int calculate_geometry(int64_t total_sectors, uint16_t* cyls,
 
 static int create_dynamic_disk(int fd, uint8_t *buf, int64_t total_sectors)
 {
-    struct vhd_dyndisk_header* dyndisk_header =
-        (struct vhd_dyndisk_header*) buf;
+    VHDDynDiskHeader *dyndisk_header =
+        (VHDDynDiskHeader *) buf;
     size_t block_size, num_bat_entries;
     int i;
     int ret = -EIO;
@@ -688,7 +688,7 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options,
                       Error **errp)
 {
     uint8_t buf[1024];
-    struct vhd_footer *footer = (struct vhd_footer *) buf;
+    VHDFooter *footer = (VHDFooter *) buf;
     QEMUOptionParameter *disk_type_param;
     int fd, i;
     uint16_t cyls = 0;
@@ -791,7 +791,7 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options,
 static int vpc_has_zero_init(BlockDriverState *bs)
 {
     BDRVVPCState *s = bs->opaque;
-    struct vhd_footer *footer =  (struct vhd_footer *) s->footer_buf;
+    VHDFooter *footer =  (VHDFooter *) s->footer_buf;
 
     if (cpu_to_be32(footer->type) == VHD_FIXED) {
         return bdrv_has_zero_init(bs->file);
index 8aa66a9..8c83f6f 100644 (file)
@@ -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 */
index 05e16da..23dbaaf 100755 (executable)
--- a/configure
+++ b/configure
@@ -215,7 +215,6 @@ linux_user="no"
 bsd_user="no"
 guest_base="yes"
 uname_release=""
-mixemu="no"
 aix="no"
 blobs="yes"
 pkgversion=""
@@ -869,8 +868,6 @@ for opt do
   ;;
   --enable-fdt) fdt="yes"
   ;;
-  --enable-mixemu) mixemu="yes"
-  ;;
   --disable-linux-aio) linux_aio="no"
   ;;
   --enable-linux-aio) linux_aio="yes"
@@ -981,6 +978,14 @@ for opt do
 done
 
 case "$cpu" in
+    ppc)
+           CPU_CFLAGS="-m32"
+           LDFLAGS="-m32 $LDFLAGS"
+           ;;
+    ppc64)
+           CPU_CFLAGS="-m64"
+           LDFLAGS="-m64 $LDFLAGS"
+           ;;
     sparc)
            LDFLAGS="-m32 $LDFLAGS"
            CPU_CFLAGS="-m32 -mcpu=ultrasparc"
@@ -1103,7 +1108,6 @@ echo "                           (affects only QEMU, not qemu-img)"
 echo "  --block-drv-ro-whitelist=L"
 echo "                           set block driver read-only whitelist"
 echo "                           (affects only QEMU, not qemu-img)"
-echo "  --enable-mixemu          enable mixer emulation"
 echo "  --disable-xen            disable xen backend driver support"
 echo "  --enable-xen             enable xen backend driver support"
 echo "  --disable-xen-pci-passthrough"
@@ -3694,7 +3698,6 @@ echo "mingw32 support   $mingw32"
 echo "Audio drivers     $audio_drv_list"
 echo "Block whitelist (rw) $block_drv_rw_whitelist"
 echo "Block whitelist (ro) $block_drv_ro_whitelist"
-echo "Mixer emulation   $mixemu"
 echo "VirtFS support    $virtfs"
 echo "VNC support       $vnc"
 if test "$vnc" = "yes" ; then
@@ -3792,7 +3795,7 @@ echo "libs_softmmu=$libs_softmmu" >> $config_host_mak
 echo "ARCH=$ARCH" >> $config_host_mak
 
 case "$cpu" in
-  arm|i386|x86_64|x32|ppc|aarch64)
+  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
@@ -3881,9 +3884,6 @@ if test "$audio_win_int" = "yes" ; then
 fi
 echo "CONFIG_BDRV_RW_WHITELIST=$block_drv_rw_whitelist" >> $config_host_mak
 echo "CONFIG_BDRV_RO_WHITELIST=$block_drv_ro_whitelist" >> $config_host_mak
-if test "$mixemu" = "yes" ; then
-  echo "CONFIG_MIXEMU=y" >> $config_host_mak
-fi
 if test "$vnc" = "yes" ; then
   echo "CONFIG_VNC=y" >> $config_host_mak
 fi
diff --git a/exec.c b/exec.c
index 26681ce..51c2369 100644 (file)
--- 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);
 
index 2b7f22b..0e5a3f5 100644 (file)
--- 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);
index 90ae565..3fae557 100644 (file)
@@ -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;
 
 }
index 7467b88..7138139 100644 (file)
@@ -324,12 +324,13 @@ static void acpi_notify_wakeup(Notifier *notifier, void *data)
             (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_TIMER_STATUS);
         break;
     case QEMU_WAKEUP_REASON_OTHER:
-    default:
         /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
            Pretend that resume was caused by power button */
         ar->pm1.evt.sts |=
             (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_POWER_BUTTON_STATUS);
         break;
+    default:
+        break;
     }
 }
 
index 0b8d1d9..b46bd5e 100644 (file)
@@ -380,6 +380,7 @@ static void piix4_reset(void *opaque)
         /* Mark SMM as already inited (until KVM supports SMM). */
         pci_conf[0x5B] = 0x02;
     }
+    pm_io_space_update(s);
     piix4_update_hotplug(s);
 }
 
index aac9a32..59e1bb8 100644 (file)
@@ -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;
diff --git a/hw/audio/hda-codec-common.h b/hw/audio/hda-codec-common.h
new file mode 100644 (file)
index 0000000..b4fdb51
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * Common code to disable/enable mixer emulation at run time
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * Written by Bandan Das <bsd@redhat.com>
+ * with important bits picked up from hda-codec.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * HDA codec descriptions
+ */
+
+#ifdef HDA_MIXER
+#define QEMU_HDA_ID_OUTPUT  ((QEMU_HDA_ID_VENDOR << 16) | 0x12)
+#define QEMU_HDA_ID_DUPLEX  ((QEMU_HDA_ID_VENDOR << 16) | 0x22)
+#define QEMU_HDA_ID_MICRO   ((QEMU_HDA_ID_VENDOR << 16) | 0x32)
+#define QEMU_HDA_AMP_CAPS                                               \
+    (AC_AMPCAP_MUTE |                                                   \
+     (QEMU_HDA_AMP_STEPS << AC_AMPCAP_OFFSET_SHIFT)    |                \
+     (QEMU_HDA_AMP_STEPS << AC_AMPCAP_NUM_STEPS_SHIFT) |                \
+     (3                  << AC_AMPCAP_STEP_SIZE_SHIFT))
+#else
+#define QEMU_HDA_ID_OUTPUT  ((QEMU_HDA_ID_VENDOR << 16) | 0x11)
+#define QEMU_HDA_ID_DUPLEX  ((QEMU_HDA_ID_VENDOR << 16) | 0x21)
+#define QEMU_HDA_ID_MICRO   ((QEMU_HDA_ID_VENDOR << 16) | 0x31)
+#define QEMU_HDA_AMP_CAPS   QEMU_HDA_AMP_NONE
+#endif
+
+
+/* common: audio output widget */
+static const desc_param glue(common_params_audio_dac_, PARAM)[] = {
+    {
+        .id  = AC_PAR_AUDIO_WIDGET_CAP,
+        .val = ((AC_WID_AUD_OUT << AC_WCAP_TYPE_SHIFT) |
+                AC_WCAP_FORMAT_OVRD |
+                AC_WCAP_AMP_OVRD |
+                AC_WCAP_OUT_AMP |
+                AC_WCAP_STEREO),
+    },{
+        .id  = AC_PAR_PCM,
+        .val = QEMU_HDA_PCM_FORMATS,
+    },{
+        .id  = AC_PAR_STREAM,
+        .val = AC_SUPFMT_PCM,
+    },{
+        .id  = AC_PAR_AMP_IN_CAP,
+        .val = QEMU_HDA_AMP_NONE,
+    },{
+        .id  = AC_PAR_AMP_OUT_CAP,
+        .val = QEMU_HDA_AMP_CAPS,
+    },
+};
+
+/* common: audio input widget */
+static const desc_param glue(common_params_audio_adc_, PARAM)[] = {
+    {
+        .id  = AC_PAR_AUDIO_WIDGET_CAP,
+        .val = ((AC_WID_AUD_IN << AC_WCAP_TYPE_SHIFT) |
+                AC_WCAP_CONN_LIST |
+                AC_WCAP_FORMAT_OVRD |
+                AC_WCAP_AMP_OVRD |
+                AC_WCAP_IN_AMP |
+                AC_WCAP_STEREO),
+    },{
+        .id  = AC_PAR_CONNLIST_LEN,
+        .val = 1,
+    },{
+        .id  = AC_PAR_PCM,
+        .val = QEMU_HDA_PCM_FORMATS,
+    },{
+        .id  = AC_PAR_STREAM,
+        .val = AC_SUPFMT_PCM,
+    },{
+        .id  = AC_PAR_AMP_IN_CAP,
+        .val = QEMU_HDA_AMP_CAPS,
+    },{
+        .id  = AC_PAR_AMP_OUT_CAP,
+        .val = QEMU_HDA_AMP_NONE,
+    },
+};
+
+/* common: pin widget (line-out) */
+static const desc_param glue(common_params_audio_lineout_, PARAM)[] = {
+    {
+        .id  = AC_PAR_AUDIO_WIDGET_CAP,
+        .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) |
+                AC_WCAP_CONN_LIST |
+                AC_WCAP_STEREO),
+    },{
+        .id  = AC_PAR_PIN_CAP,
+        .val = AC_PINCAP_OUT,
+    },{
+        .id  = AC_PAR_CONNLIST_LEN,
+        .val = 1,
+    },{
+        .id  = AC_PAR_AMP_IN_CAP,
+        .val = QEMU_HDA_AMP_NONE,
+    },{
+        .id  = AC_PAR_AMP_OUT_CAP,
+        .val = QEMU_HDA_AMP_NONE,
+    },
+};
+
+/* common: pin widget (line-in) */
+static const desc_param glue(common_params_audio_linein_, PARAM)[] = {
+    {
+        .id  = AC_PAR_AUDIO_WIDGET_CAP,
+        .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) |
+                AC_WCAP_STEREO),
+    },{
+        .id  = AC_PAR_PIN_CAP,
+        .val = AC_PINCAP_IN,
+    },{
+        .id  = AC_PAR_AMP_IN_CAP,
+        .val = QEMU_HDA_AMP_NONE,
+    },{
+        .id  = AC_PAR_AMP_OUT_CAP,
+        .val = QEMU_HDA_AMP_NONE,
+    },
+};
+
+/* output: root node */
+static const desc_param glue(output_params_root_, PARAM)[] = {
+    {
+        .id  = AC_PAR_VENDOR_ID,
+        .val = QEMU_HDA_ID_OUTPUT,
+    },{
+        .id  = AC_PAR_SUBSYSTEM_ID,
+        .val = QEMU_HDA_ID_OUTPUT,
+    },{
+        .id  = AC_PAR_REV_ID,
+        .val = 0x00100101,
+    },{
+        .id  = AC_PAR_NODE_COUNT,
+        .val = 0x00010001,
+    },
+};
+
+/* output: audio function */
+static const desc_param glue(output_params_audio_func_, PARAM)[] = {
+    {
+        .id  = AC_PAR_FUNCTION_TYPE,
+        .val = AC_GRP_AUDIO_FUNCTION,
+    },{
+        .id  = AC_PAR_SUBSYSTEM_ID,
+        .val = QEMU_HDA_ID_OUTPUT,
+    },{
+        .id  = AC_PAR_NODE_COUNT,
+        .val = 0x00020002,
+    },{
+        .id  = AC_PAR_PCM,
+        .val = QEMU_HDA_PCM_FORMATS,
+    },{
+        .id  = AC_PAR_STREAM,
+        .val = AC_SUPFMT_PCM,
+    },{
+        .id  = AC_PAR_AMP_IN_CAP,
+        .val = QEMU_HDA_AMP_NONE,
+    },{
+        .id  = AC_PAR_AMP_OUT_CAP,
+        .val = QEMU_HDA_AMP_NONE,
+    },{
+        .id  = AC_PAR_GPIO_CAP,
+        .val = 0,
+    },{
+        .id  = AC_PAR_AUDIO_FG_CAP,
+        .val = 0x00000808,
+    },{
+        .id  = AC_PAR_POWER_STATE,
+        .val = 0,
+    },
+};
+
+/* output: nodes */
+static const desc_node glue(output_nodes_, PARAM)[] = {
+    {
+        .nid     = AC_NODE_ROOT,
+        .name    = "root",
+        .params  = glue(output_params_root_, PARAM),
+        .nparams = ARRAY_SIZE(glue(output_params_root_, PARAM)),
+    },{
+        .nid     = 1,
+        .name    = "func",
+        .params  = glue(output_params_audio_func_, PARAM),
+        .nparams = ARRAY_SIZE(glue(output_params_audio_func_, PARAM)),
+    },{
+        .nid     = 2,
+        .name    = "dac",
+        .params  = glue(common_params_audio_dac_, PARAM),
+        .nparams = ARRAY_SIZE(glue(common_params_audio_dac_, PARAM)),
+        .stindex = 0,
+    },{
+        .nid     = 3,
+        .name    = "out",
+        .params  = glue(common_params_audio_lineout_, PARAM),
+        .nparams = ARRAY_SIZE(glue(common_params_audio_lineout_, PARAM)),
+        .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
+                    (AC_JACK_LINE_OUT     << AC_DEFCFG_DEVICE_SHIFT)    |
+                    (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
+                    (AC_JACK_COLOR_GREEN  << AC_DEFCFG_COLOR_SHIFT)     |
+                    0x10),
+        .pinctl  = AC_PINCTL_OUT_EN,
+        .conn    = (uint32_t[]) { 2 },
+    }
+};
+
+/* output: codec */
+static const desc_codec glue(output_, PARAM) = {
+    .name   = "output",
+    .iid    = QEMU_HDA_ID_OUTPUT,
+    .nodes  = glue(output_nodes_, PARAM),
+    .nnodes = ARRAY_SIZE(glue(output_nodes_, PARAM)),
+};
+
+/* duplex: root node */
+static const desc_param glue(duplex_params_root_, PARAM)[] = {
+    {
+        .id  = AC_PAR_VENDOR_ID,
+        .val = QEMU_HDA_ID_DUPLEX,
+    },{
+        .id  = AC_PAR_SUBSYSTEM_ID,
+        .val = QEMU_HDA_ID_DUPLEX,
+    },{
+        .id  = AC_PAR_REV_ID,
+        .val = 0x00100101,
+    },{
+        .id  = AC_PAR_NODE_COUNT,
+        .val = 0x00010001,
+    },
+};
+
+/* duplex: audio function */
+static const desc_param glue(duplex_params_audio_func_, PARAM)[] = {
+    {
+        .id  = AC_PAR_FUNCTION_TYPE,
+        .val = AC_GRP_AUDIO_FUNCTION,
+    },{
+        .id  = AC_PAR_SUBSYSTEM_ID,
+        .val = QEMU_HDA_ID_DUPLEX,
+    },{
+        .id  = AC_PAR_NODE_COUNT,
+        .val = 0x00020004,
+    },{
+        .id  = AC_PAR_PCM,
+        .val = QEMU_HDA_PCM_FORMATS,
+    },{
+        .id  = AC_PAR_STREAM,
+        .val = AC_SUPFMT_PCM,
+    },{
+        .id  = AC_PAR_AMP_IN_CAP,
+        .val = QEMU_HDA_AMP_NONE,
+    },{
+        .id  = AC_PAR_AMP_OUT_CAP,
+        .val = QEMU_HDA_AMP_NONE,
+    },{
+        .id  = AC_PAR_GPIO_CAP,
+        .val = 0,
+    },{
+        .id  = AC_PAR_AUDIO_FG_CAP,
+        .val = 0x00000808,
+    },{
+        .id  = AC_PAR_POWER_STATE,
+        .val = 0,
+    },
+};
+
+/* duplex: nodes */
+static const desc_node glue(duplex_nodes_, PARAM)[] = {
+    {
+        .nid     = AC_NODE_ROOT,
+        .name    = "root",
+        .params  = glue(duplex_params_root_, PARAM),
+        .nparams = ARRAY_SIZE(glue(duplex_params_root_, PARAM)),
+    },{
+        .nid     = 1,
+        .name    = "func",
+        .params  = glue(duplex_params_audio_func_, PARAM),
+        .nparams = ARRAY_SIZE(glue(duplex_params_audio_func_, PARAM)),
+    },{
+        .nid     = 2,
+        .name    = "dac",
+        .params  = glue(common_params_audio_dac_, PARAM),
+        .nparams = ARRAY_SIZE(glue(common_params_audio_dac_, PARAM)),
+        .stindex = 0,
+    },{
+        .nid     = 3,
+        .name    = "out",
+        .params  = glue(common_params_audio_lineout_, PARAM),
+        .nparams = ARRAY_SIZE(glue(common_params_audio_lineout_, PARAM)),
+        .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
+                    (AC_JACK_LINE_OUT     << AC_DEFCFG_DEVICE_SHIFT)    |
+                    (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
+                    (AC_JACK_COLOR_GREEN  << AC_DEFCFG_COLOR_SHIFT)     |
+                    0x10),
+        .pinctl  = AC_PINCTL_OUT_EN,
+        .conn    = (uint32_t[]) { 2 },
+    },{
+        .nid     = 4,
+        .name    = "adc",
+        .params  = glue(common_params_audio_adc_, PARAM),
+        .nparams = ARRAY_SIZE(glue(common_params_audio_adc_, PARAM)),
+        .stindex = 1,
+        .conn    = (uint32_t[]) { 5 },
+    },{
+        .nid     = 5,
+        .name    = "in",
+        .params  = glue(common_params_audio_linein_, PARAM),
+        .nparams = ARRAY_SIZE(glue(common_params_audio_linein_, PARAM)),
+        .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
+                    (AC_JACK_LINE_IN      << AC_DEFCFG_DEVICE_SHIFT)    |
+                    (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
+                    (AC_JACK_COLOR_RED    << AC_DEFCFG_COLOR_SHIFT)     |
+                    0x20),
+        .pinctl  = AC_PINCTL_IN_EN,
+    }
+};
+
+/* duplex: codec */
+static const desc_codec glue(duplex_, PARAM) = {
+    .name   = "duplex",
+    .iid    = QEMU_HDA_ID_DUPLEX,
+    .nodes  = glue(duplex_nodes_, PARAM),
+    .nnodes = ARRAY_SIZE(glue(duplex_nodes_, PARAM)),
+};
+
+/* micro: root node */
+static const desc_param glue(micro_params_root_, PARAM)[] = {
+    {
+        .id  = AC_PAR_VENDOR_ID,
+        .val = QEMU_HDA_ID_MICRO,
+    },{
+        .id  = AC_PAR_SUBSYSTEM_ID,
+        .val = QEMU_HDA_ID_MICRO,
+    },{
+        .id  = AC_PAR_REV_ID,
+        .val = 0x00100101,
+    },{
+        .id  = AC_PAR_NODE_COUNT,
+        .val = 0x00010001,
+    },
+};
+
+/* micro: audio function */
+static const desc_param glue(micro_params_audio_func_, PARAM)[] = {
+    {
+        .id  = AC_PAR_FUNCTION_TYPE,
+        .val = AC_GRP_AUDIO_FUNCTION,
+    },{
+        .id  = AC_PAR_SUBSYSTEM_ID,
+        .val = QEMU_HDA_ID_MICRO,
+    },{
+        .id  = AC_PAR_NODE_COUNT,
+        .val = 0x00020004,
+    },{
+        .id  = AC_PAR_PCM,
+        .val = QEMU_HDA_PCM_FORMATS,
+    },{
+        .id  = AC_PAR_STREAM,
+        .val = AC_SUPFMT_PCM,
+    },{
+        .id  = AC_PAR_AMP_IN_CAP,
+        .val = QEMU_HDA_AMP_NONE,
+    },{
+        .id  = AC_PAR_AMP_OUT_CAP,
+        .val = QEMU_HDA_AMP_NONE,
+    },{
+        .id  = AC_PAR_GPIO_CAP,
+        .val = 0,
+    },{
+        .id  = AC_PAR_AUDIO_FG_CAP,
+        .val = 0x00000808,
+    },{
+        .id  = AC_PAR_POWER_STATE,
+        .val = 0,
+    },
+};
+
+/* micro: nodes */
+static const desc_node glue(micro_nodes_, PARAM)[] = {
+    {
+        .nid     = AC_NODE_ROOT,
+        .name    = "root",
+        .params  = glue(micro_params_root_, PARAM),
+        .nparams = ARRAY_SIZE(glue(micro_params_root_, PARAM)),
+    },{
+        .nid     = 1,
+        .name    = "func",
+        .params  = glue(micro_params_audio_func_, PARAM),
+        .nparams = ARRAY_SIZE(glue(micro_params_audio_func_, PARAM)),
+    },{
+        .nid     = 2,
+        .name    = "dac",
+        .params  = glue(common_params_audio_dac_, PARAM),
+        .nparams = ARRAY_SIZE(glue(common_params_audio_dac_, PARAM)),
+        .stindex = 0,
+    },{
+        .nid     = 3,
+        .name    = "out",
+        .params  = glue(common_params_audio_lineout_, PARAM),
+        .nparams = ARRAY_SIZE(glue(common_params_audio_lineout_, PARAM)),
+        .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
+                    (AC_JACK_SPEAKER      << AC_DEFCFG_DEVICE_SHIFT)    |
+                    (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
+                    (AC_JACK_COLOR_GREEN  << AC_DEFCFG_COLOR_SHIFT)     |
+                    0x10),
+        .pinctl  = AC_PINCTL_OUT_EN,
+        .conn    = (uint32_t[]) { 2 },
+    },{
+        .nid     = 4,
+        .name    = "adc",
+        .params  = glue(common_params_audio_adc_, PARAM),
+        .nparams = ARRAY_SIZE(glue(common_params_audio_adc_, PARAM)),
+        .stindex = 1,
+        .conn    = (uint32_t[]) { 5 },
+    },{
+        .nid     = 5,
+        .name    = "in",
+        .params  = glue(common_params_audio_linein_, PARAM),
+        .nparams = ARRAY_SIZE(glue(common_params_audio_linein_, PARAM)),
+        .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
+                    (AC_JACK_MIC_IN       << AC_DEFCFG_DEVICE_SHIFT)    |
+                    (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
+                    (AC_JACK_COLOR_RED    << AC_DEFCFG_COLOR_SHIFT)     |
+                    0x20),
+        .pinctl  = AC_PINCTL_IN_EN,
+    }
+};
+
+/* micro: codec */
+static const desc_codec glue(micro_, PARAM) = {
+    .name   = "micro",
+    .iid    = QEMU_HDA_ID_MICRO,
+    .nodes  = glue(micro_nodes_, PARAM),
+    .nnodes = ARRAY_SIZE(glue(micro_nodes_, PARAM)),
+};
+
+#undef PARAM
+#undef HDA_MIXER
+#undef QEMU_HDA_ID_OUTPUT
+#undef QEMU_HDA_ID_DUPLEX
+#undef QEMU_HDA_ID_MICRO
+#undef QEMU_HDA_AMP_CAPS
index 9550c97..07a43bf 100644 (file)
@@ -118,428 +118,12 @@ static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as)
 #define QEMU_HDA_AMP_NONE    (0)
 #define QEMU_HDA_AMP_STEPS   0x4a
 
-#ifdef CONFIG_MIXEMU
-# define QEMU_HDA_ID_OUTPUT  ((QEMU_HDA_ID_VENDOR << 16) | 0x12)
-# define QEMU_HDA_ID_DUPLEX  ((QEMU_HDA_ID_VENDOR << 16) | 0x22)
-# define QEMU_HDA_ID_MICRO   ((QEMU_HDA_ID_VENDOR << 16) | 0x32)
-# define QEMU_HDA_AMP_CAPS                                              \
-    (AC_AMPCAP_MUTE |                                                   \
-     (QEMU_HDA_AMP_STEPS << AC_AMPCAP_OFFSET_SHIFT)    |                \
-     (QEMU_HDA_AMP_STEPS << AC_AMPCAP_NUM_STEPS_SHIFT) |                \
-     (3                  << AC_AMPCAP_STEP_SIZE_SHIFT))
-#else
-# define QEMU_HDA_ID_OUTPUT  ((QEMU_HDA_ID_VENDOR << 16) | 0x11)
-# define QEMU_HDA_ID_DUPLEX  ((QEMU_HDA_ID_VENDOR << 16) | 0x21)
-# define QEMU_HDA_ID_MICRO   ((QEMU_HDA_ID_VENDOR << 16) | 0x31)
-# define QEMU_HDA_AMP_CAPS   QEMU_HDA_AMP_NONE
-#endif
-
-/* common: audio output widget */
-static const desc_param common_params_audio_dac[] = {
-    {
-        .id  = AC_PAR_AUDIO_WIDGET_CAP,
-        .val = ((AC_WID_AUD_OUT << AC_WCAP_TYPE_SHIFT) |
-                AC_WCAP_FORMAT_OVRD |
-                AC_WCAP_AMP_OVRD |
-                AC_WCAP_OUT_AMP |
-                AC_WCAP_STEREO),
-    },{
-        .id  = AC_PAR_PCM,
-        .val = QEMU_HDA_PCM_FORMATS,
-    },{
-        .id  = AC_PAR_STREAM,
-        .val = AC_SUPFMT_PCM,
-    },{
-        .id  = AC_PAR_AMP_IN_CAP,
-        .val = QEMU_HDA_AMP_NONE,
-    },{
-        .id  = AC_PAR_AMP_OUT_CAP,
-        .val = QEMU_HDA_AMP_CAPS,
-    },
-};
-
-/* common: audio input widget */
-static const desc_param common_params_audio_adc[] = {
-    {
-        .id  = AC_PAR_AUDIO_WIDGET_CAP,
-        .val = ((AC_WID_AUD_IN << AC_WCAP_TYPE_SHIFT) |
-                AC_WCAP_CONN_LIST |
-                AC_WCAP_FORMAT_OVRD |
-                AC_WCAP_AMP_OVRD |
-                AC_WCAP_IN_AMP |
-                AC_WCAP_STEREO),
-    },{
-        .id  = AC_PAR_CONNLIST_LEN,
-        .val = 1,
-    },{
-        .id  = AC_PAR_PCM,
-        .val = QEMU_HDA_PCM_FORMATS,
-    },{
-        .id  = AC_PAR_STREAM,
-        .val = AC_SUPFMT_PCM,
-    },{
-        .id  = AC_PAR_AMP_IN_CAP,
-        .val = QEMU_HDA_AMP_CAPS,
-    },{
-        .id  = AC_PAR_AMP_OUT_CAP,
-        .val = QEMU_HDA_AMP_NONE,
-    },
-};
-
-/* common: pin widget (line-out) */
-static const desc_param common_params_audio_lineout[] = {
-    {
-        .id  = AC_PAR_AUDIO_WIDGET_CAP,
-        .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) |
-                AC_WCAP_CONN_LIST |
-                AC_WCAP_STEREO),
-    },{
-        .id  = AC_PAR_PIN_CAP,
-        .val = AC_PINCAP_OUT,
-    },{
-        .id  = AC_PAR_CONNLIST_LEN,
-        .val = 1,
-    },{
-        .id  = AC_PAR_AMP_IN_CAP,
-        .val = QEMU_HDA_AMP_NONE,
-    },{
-        .id  = AC_PAR_AMP_OUT_CAP,
-        .val = QEMU_HDA_AMP_NONE,
-    },
-};
-
-/* common: pin widget (line-in) */
-static const desc_param common_params_audio_linein[] = {
-    {
-        .id  = AC_PAR_AUDIO_WIDGET_CAP,
-        .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) |
-                AC_WCAP_STEREO),
-    },{
-        .id  = AC_PAR_PIN_CAP,
-        .val = AC_PINCAP_IN,
-    },{
-        .id  = AC_PAR_AMP_IN_CAP,
-        .val = QEMU_HDA_AMP_NONE,
-    },{
-        .id  = AC_PAR_AMP_OUT_CAP,
-        .val = QEMU_HDA_AMP_NONE,
-    },
-};
-
-/* output: root node */
-static const desc_param output_params_root[] = {
-    {
-        .id  = AC_PAR_VENDOR_ID,
-        .val = QEMU_HDA_ID_OUTPUT,
-    },{
-        .id  = AC_PAR_SUBSYSTEM_ID,
-        .val = QEMU_HDA_ID_OUTPUT,
-    },{
-        .id  = AC_PAR_REV_ID,
-        .val = 0x00100101,
-    },{
-        .id  = AC_PAR_NODE_COUNT,
-        .val = 0x00010001,
-    },
-};
+#define   PARAM mixemu
+#define   HDA_MIXER
+#include "hda-codec-common.h"
 
-/* output: audio function */
-static const desc_param output_params_audio_func[] = {
-    {
-        .id  = AC_PAR_FUNCTION_TYPE,
-        .val = AC_GRP_AUDIO_FUNCTION,
-    },{
-        .id  = AC_PAR_SUBSYSTEM_ID,
-        .val = QEMU_HDA_ID_OUTPUT,
-    },{
-        .id  = AC_PAR_NODE_COUNT,
-        .val = 0x00020002,
-    },{
-        .id  = AC_PAR_PCM,
-        .val = QEMU_HDA_PCM_FORMATS,
-    },{
-        .id  = AC_PAR_STREAM,
-        .val = AC_SUPFMT_PCM,
-    },{
-        .id  = AC_PAR_AMP_IN_CAP,
-        .val = QEMU_HDA_AMP_NONE,
-    },{
-        .id  = AC_PAR_AMP_OUT_CAP,
-        .val = QEMU_HDA_AMP_NONE,
-    },{
-        .id  = AC_PAR_GPIO_CAP,
-        .val = 0,
-    },{
-        .id  = AC_PAR_AUDIO_FG_CAP,
-        .val = 0x00000808,
-    },{
-        .id  = AC_PAR_POWER_STATE,
-        .val = 0,
-    },
-};
-
-/* output: nodes */
-static const desc_node output_nodes[] = {
-    {
-        .nid     = AC_NODE_ROOT,
-        .name    = "root",
-        .params  = output_params_root,
-        .nparams = ARRAY_SIZE(output_params_root),
-    },{
-        .nid     = 1,
-        .name    = "func",
-        .params  = output_params_audio_func,
-        .nparams = ARRAY_SIZE(output_params_audio_func),
-    },{
-        .nid     = 2,
-        .name    = "dac",
-        .params  = common_params_audio_dac,
-        .nparams = ARRAY_SIZE(common_params_audio_dac),
-        .stindex = 0,
-    },{
-        .nid     = 3,
-        .name    = "out",
-        .params  = common_params_audio_lineout,
-        .nparams = ARRAY_SIZE(common_params_audio_lineout),
-        .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
-                    (AC_JACK_LINE_OUT     << AC_DEFCFG_DEVICE_SHIFT)    |
-                    (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
-                    (AC_JACK_COLOR_GREEN  << AC_DEFCFG_COLOR_SHIFT)     |
-                    0x10),
-        .pinctl  = AC_PINCTL_OUT_EN,
-        .conn    = (uint32_t[]) { 2 },
-    }
-};
-
-/* output: codec */
-static const desc_codec output = {
-    .name   = "output",
-    .iid    = QEMU_HDA_ID_OUTPUT,
-    .nodes  = output_nodes,
-    .nnodes = ARRAY_SIZE(output_nodes),
-};
-
-/* duplex: root node */
-static const desc_param duplex_params_root[] = {
-    {
-        .id  = AC_PAR_VENDOR_ID,
-        .val = QEMU_HDA_ID_DUPLEX,
-    },{
-        .id  = AC_PAR_SUBSYSTEM_ID,
-        .val = QEMU_HDA_ID_DUPLEX,
-    },{
-        .id  = AC_PAR_REV_ID,
-        .val = 0x00100101,
-    },{
-        .id  = AC_PAR_NODE_COUNT,
-        .val = 0x00010001,
-    },
-};
-
-/* duplex: audio function */
-static const desc_param duplex_params_audio_func[] = {
-    {
-        .id  = AC_PAR_FUNCTION_TYPE,
-        .val = AC_GRP_AUDIO_FUNCTION,
-    },{
-        .id  = AC_PAR_SUBSYSTEM_ID,
-        .val = QEMU_HDA_ID_DUPLEX,
-    },{
-        .id  = AC_PAR_NODE_COUNT,
-        .val = 0x00020004,
-    },{
-        .id  = AC_PAR_PCM,
-        .val = QEMU_HDA_PCM_FORMATS,
-    },{
-        .id  = AC_PAR_STREAM,
-        .val = AC_SUPFMT_PCM,
-    },{
-        .id  = AC_PAR_AMP_IN_CAP,
-        .val = QEMU_HDA_AMP_NONE,
-    },{
-        .id  = AC_PAR_AMP_OUT_CAP,
-        .val = QEMU_HDA_AMP_NONE,
-    },{
-        .id  = AC_PAR_GPIO_CAP,
-        .val = 0,
-    },{
-        .id  = AC_PAR_AUDIO_FG_CAP,
-        .val = 0x00000808,
-    },{
-        .id  = AC_PAR_POWER_STATE,
-        .val = 0,
-    },
-};
-
-/* duplex: nodes */
-static const desc_node duplex_nodes[] = {
-    {
-        .nid     = AC_NODE_ROOT,
-        .name    = "root",
-        .params  = duplex_params_root,
-        .nparams = ARRAY_SIZE(duplex_params_root),
-    },{
-        .nid     = 1,
-        .name    = "func",
-        .params  = duplex_params_audio_func,
-        .nparams = ARRAY_SIZE(duplex_params_audio_func),
-    },{
-        .nid     = 2,
-        .name    = "dac",
-        .params  = common_params_audio_dac,
-        .nparams = ARRAY_SIZE(common_params_audio_dac),
-        .stindex = 0,
-    },{
-        .nid     = 3,
-        .name    = "out",
-        .params  = common_params_audio_lineout,
-        .nparams = ARRAY_SIZE(common_params_audio_lineout),
-        .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
-                    (AC_JACK_LINE_OUT     << AC_DEFCFG_DEVICE_SHIFT)    |
-                    (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
-                    (AC_JACK_COLOR_GREEN  << AC_DEFCFG_COLOR_SHIFT)     |
-                    0x10),
-        .pinctl  = AC_PINCTL_OUT_EN,
-        .conn    = (uint32_t[]) { 2 },
-    },{
-        .nid     = 4,
-        .name    = "adc",
-        .params  = common_params_audio_adc,
-        .nparams = ARRAY_SIZE(common_params_audio_adc),
-        .stindex = 1,
-        .conn    = (uint32_t[]) { 5 },
-    },{
-        .nid     = 5,
-        .name    = "in",
-        .params  = common_params_audio_linein,
-        .nparams = ARRAY_SIZE(common_params_audio_linein),
-        .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
-                    (AC_JACK_LINE_IN      << AC_DEFCFG_DEVICE_SHIFT)    |
-                    (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
-                    (AC_JACK_COLOR_RED    << AC_DEFCFG_COLOR_SHIFT)     |
-                    0x20),
-        .pinctl  = AC_PINCTL_IN_EN,
-    }
-};
-
-/* duplex: codec */
-static const desc_codec duplex = {
-    .name   = "duplex",
-    .iid    = QEMU_HDA_ID_DUPLEX,
-    .nodes  = duplex_nodes,
-    .nnodes = ARRAY_SIZE(duplex_nodes),
-};
-
-/* micro: root node */
-static const desc_param micro_params_root[] = {
-    {
-        .id  = AC_PAR_VENDOR_ID,
-        .val = QEMU_HDA_ID_MICRO,
-    },{
-        .id  = AC_PAR_SUBSYSTEM_ID,
-        .val = QEMU_HDA_ID_MICRO,
-    },{
-        .id  = AC_PAR_REV_ID,
-        .val = 0x00100101,
-    },{
-        .id  = AC_PAR_NODE_COUNT,
-        .val = 0x00010001,
-    },
-};
-
-/* micro: audio function */
-static const desc_param micro_params_audio_func[] = {
-    {
-        .id  = AC_PAR_FUNCTION_TYPE,
-        .val = AC_GRP_AUDIO_FUNCTION,
-    },{
-        .id  = AC_PAR_SUBSYSTEM_ID,
-        .val = QEMU_HDA_ID_MICRO,
-    },{
-        .id  = AC_PAR_NODE_COUNT,
-        .val = 0x00020004,
-    },{
-        .id  = AC_PAR_PCM,
-        .val = QEMU_HDA_PCM_FORMATS,
-    },{
-        .id  = AC_PAR_STREAM,
-        .val = AC_SUPFMT_PCM,
-    },{
-        .id  = AC_PAR_AMP_IN_CAP,
-        .val = QEMU_HDA_AMP_NONE,
-    },{
-        .id  = AC_PAR_AMP_OUT_CAP,
-        .val = QEMU_HDA_AMP_NONE,
-    },{
-        .id  = AC_PAR_GPIO_CAP,
-        .val = 0,
-    },{
-        .id  = AC_PAR_AUDIO_FG_CAP,
-        .val = 0x00000808,
-    },{
-        .id  = AC_PAR_POWER_STATE,
-        .val = 0,
-    },
-};
-
-/* micro: nodes */
-static const desc_node micro_nodes[] = {
-    {
-        .nid     = AC_NODE_ROOT,
-        .name    = "root",
-        .params  = micro_params_root,
-        .nparams = ARRAY_SIZE(micro_params_root),
-    },{
-        .nid     = 1,
-        .name    = "func",
-        .params  = micro_params_audio_func,
-        .nparams = ARRAY_SIZE(micro_params_audio_func),
-    },{
-        .nid     = 2,
-        .name    = "dac",
-        .params  = common_params_audio_dac,
-        .nparams = ARRAY_SIZE(common_params_audio_dac),
-        .stindex = 0,
-    },{
-        .nid     = 3,
-        .name    = "out",
-        .params  = common_params_audio_lineout,
-        .nparams = ARRAY_SIZE(common_params_audio_lineout),
-        .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
-                    (AC_JACK_SPEAKER      << AC_DEFCFG_DEVICE_SHIFT)    |
-                    (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
-                    (AC_JACK_COLOR_GREEN  << AC_DEFCFG_COLOR_SHIFT)     |
-                    0x10),
-        .pinctl  = AC_PINCTL_OUT_EN,
-        .conn    = (uint32_t[]) { 2 },
-    },{
-        .nid     = 4,
-        .name    = "adc",
-        .params  = common_params_audio_adc,
-        .nparams = ARRAY_SIZE(common_params_audio_adc),
-        .stindex = 1,
-        .conn    = (uint32_t[]) { 5 },
-    },{
-        .nid     = 5,
-        .name    = "in",
-        .params  = common_params_audio_linein,
-        .nparams = ARRAY_SIZE(common_params_audio_linein),
-        .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
-                    (AC_JACK_MIC_IN       << AC_DEFCFG_DEVICE_SHIFT)    |
-                    (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
-                    (AC_JACK_COLOR_RED    << AC_DEFCFG_COLOR_SHIFT)     |
-                    0x20),
-        .pinctl  = AC_PINCTL_IN_EN,
-    }
-};
-
-/* micro: codec */
-static const desc_codec micro = {
-    .name   = "micro",
-    .iid    = QEMU_HDA_ID_MICRO,
-    .nodes  = micro_nodes,
-    .nnodes = ARRAY_SIZE(micro_nodes),
-};
+#define   PARAM nomixemu
+#include  "hda-codec-common.h"
 
 /* -------------------------------------------------------------------------- */
 
@@ -585,6 +169,7 @@ struct HDAAudioState {
 
     /* properties */
     uint32_t debug;
+    bool     mixer;
 };
 
 static void hda_audio_input_cb(void *opaque, int avail)
@@ -1006,23 +591,42 @@ static const VMStateDescription vmstate_hda_audio = {
 };
 
 static Property hda_audio_properties[] = {
-    DEFINE_PROP_UINT32("debug", HDAAudioState, debug, 0),
+    DEFINE_PROP_UINT32("debug", HDAAudioState, debug,   0),
+    DEFINE_PROP_BOOL("mixer", HDAAudioState, mixer,  true),
     DEFINE_PROP_END_OF_LIST(),
 };
 
 static int hda_audio_init_output(HDACodecDevice *hda)
 {
-    return hda_audio_init(hda, &output);
+    HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
+
+    if (!a->mixer) {
+        return hda_audio_init(hda, &output_nomixemu);
+    } else {
+        return hda_audio_init(hda, &output_mixemu);
+    }
 }
 
 static int hda_audio_init_duplex(HDACodecDevice *hda)
 {
-    return hda_audio_init(hda, &duplex);
+    HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
+
+    if (!a->mixer) {
+        return hda_audio_init(hda, &duplex_nomixemu);
+    } else {
+        return hda_audio_init(hda, &duplex_mixemu);
+    }
 }
 
 static int hda_audio_init_micro(HDACodecDevice *hda)
 {
-    return hda_audio_init(hda, &micro);
+    HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
+
+    if (!a->mixer) {
+        return hda_audio_init(hda, &micro_nomixemu);
+    } else {
+        return hda_audio_init(hda, &micro_mixemu);
+    }
 }
 
 static void hda_audio_output_class_init(ObjectClass *klass, void *data)
index f35fc59..8742294 100644 (file)
@@ -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;
             }
index f8f3dbc..cbd6a00 100644 (file)
@@ -22,6 +22,6 @@ common-obj-$(CONFIG_IMX) += imx_serial.o
 common-obj-$(CONFIG_LM32) += lm32_juart.o
 common-obj-$(CONFIG_LM32) += lm32_uart.o
 common-obj-$(CONFIG_MILKYMIST) += milkymist-uart.o
-common-obj-$(CONFIG_SCLPCONSOLE) += sclpconsole.o
+common-obj-$(CONFIG_SCLPCONSOLE) += sclpconsole.o sclpconsole-lm.o
 
 obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o
diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c
new file mode 100644 (file)
index 0000000..9339067
--- /dev/null
@@ -0,0 +1,398 @@
+/*
+ * SCLP event types
+ *    Operations Command - Line Mode input
+ *    Message            - Line Mode output
+ *
+ * Copyright IBM, Corp. 2013
+ *
+ * Authors:
+ *  Heinz Graalfs <graalfs@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
+ * option) any later version.  See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "hw/qdev.h"
+#include "qemu/thread.h"
+#include "qemu/error-report.h"
+#include "sysemu/char.h"
+
+#include "hw/s390x/sclp.h"
+#include "hw/s390x/event-facility.h"
+#include "hw/s390x/ebcdic.h"
+
+#define SIZE_BUFFER 4096
+#define NEWLINE     "\n"
+
+typedef struct OprtnsCommand {
+    EventBufferHeader header;
+    MDMSU message_unit;
+    char data[0];
+} QEMU_PACKED OprtnsCommand;
+
+/* max size for line-mode data in 4K SCCB page */
+#define SIZE_CONSOLE_BUFFER (SCCB_DATA_LEN - sizeof(OprtnsCommand))
+
+typedef struct SCLPConsoleLM {
+    SCLPEvent event;
+    CharDriverState *chr;
+    bool echo;                  /* immediate echo of input if true        */
+    uint32_t write_errors;      /* errors writing to char layer           */
+    uint32_t length;            /* length of byte stream in buffer        */
+    uint8_t buf[SIZE_CONSOLE_BUFFER];
+    qemu_irq irq_console_read;
+} SCLPConsoleLM;
+
+/*
+*  Character layer call-back functions
+ *
+ * Allow 1 character at a time
+ *
+ * Accumulate bytes from character layer in console buffer,
+ * event_pending is set when a newline character is encountered
+ *
+ * The maximum command line length is limited by the maximum
+ * space available in an SCCB
+ */
+
+static int chr_can_read(void *opaque)
+{
+    SCLPConsoleLM *scon = opaque;
+
+    if (scon->event.event_pending) {
+        return 0;
+    } else if (SIZE_CONSOLE_BUFFER - scon->length) {
+        return 1;
+    }
+    return 0;
+}
+
+static void receive_from_chr_layer(SCLPConsoleLM *scon, const uint8_t *buf,
+                                   int size)
+{
+    assert(size == 1);
+
+    if (*buf == '\r' || *buf == '\n') {
+        scon->event.event_pending = true;
+        return;
+    }
+    scon->buf[scon->length] = *buf;
+    scon->length += 1;
+    if (scon->echo) {
+        qemu_chr_fe_write(scon->chr, buf, size);
+    }
+}
+
+/*
+ * Send data from a char device over to the guest
+ */
+static void chr_read(void *opaque, const uint8_t *buf, int size)
+{
+    SCLPConsoleLM *scon = opaque;
+
+    receive_from_chr_layer(scon, buf, size);
+    if (scon->event.event_pending) {
+        /* trigger SCLP read operation */
+        qemu_irq_raise(scon->irq_console_read);
+    }
+}
+
+/* functions to be called by event facility */
+
+static bool can_handle_event(uint8_t type)
+{
+    return type == SCLP_EVENT_MESSAGE || type == SCLP_EVENT_PMSGCMD;
+}
+
+static unsigned int send_mask(void)
+{
+    return SCLP_EVENT_MASK_OP_CMD | SCLP_EVENT_MASK_PMSGCMD;
+}
+
+static unsigned int receive_mask(void)
+{
+    return SCLP_EVENT_MASK_MSG | SCLP_EVENT_MASK_PMSGCMD;
+}
+
+/*
+ * Triggered by SCLP's read_event_data
+ * - convert ASCII byte stream to EBCDIC and
+ * - copy converted data into provided (SCLP) buffer
+ */
+static int get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size,
+                            int avail)
+{
+    int len;
+
+    SCLPConsoleLM *cons = DO_UPCAST(SCLPConsoleLM, event, event);
+
+    len = cons->length;
+    /* data need to fit into provided SCLP buffer */
+    if (len > avail) {
+        return 1;
+    }
+
+    ebcdic_put(buf, (char *)&cons->buf, len);
+    *size = len;
+    cons->length = 0;
+    /* data provided and no more data pending */
+    event->event_pending = false;
+    return 0;
+}
+
+static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr,
+                           int *slen)
+{
+    int avail, rc;
+    size_t src_len;
+    uint8_t *to;
+    OprtnsCommand *oc = (OprtnsCommand *) evt_buf_hdr;
+
+    if (!event->event_pending) {
+        /* no data pending */
+        return 0;
+    }
+
+    to = (uint8_t *)&oc->data;
+    avail = *slen - sizeof(OprtnsCommand);
+    rc = get_console_data(event, to, &src_len, avail);
+    if (rc) {
+        /* data didn't fit, try next SCCB */
+        return 1;
+    }
+
+    oc->message_unit.mdmsu.gds_id = GDS_ID_MDSMU;
+    oc->message_unit.mdmsu.length = cpu_to_be16(sizeof(struct MDMSU));
+
+    oc->message_unit.cpmsu.gds_id = GDS_ID_CPMSU;
+    oc->message_unit.cpmsu.length =
+        cpu_to_be16(sizeof(struct MDMSU) - sizeof(GdsVector));
+
+    oc->message_unit.text_command.gds_id = GDS_ID_TEXTCMD;
+    oc->message_unit.text_command.length =
+        cpu_to_be16(sizeof(struct MDMSU) - (2 * sizeof(GdsVector)));
+
+    oc->message_unit.self_def_text_message.key = GDS_KEY_SELFDEFTEXTMSG;
+    oc->message_unit.self_def_text_message.length =
+        cpu_to_be16(sizeof(struct MDMSU) - (3 * sizeof(GdsVector)));
+
+    oc->message_unit.text_message.key = GDS_KEY_TEXTMSG;
+    oc->message_unit.text_message.length =
+        cpu_to_be16(sizeof(GdsSubvector) + src_len);
+
+    oc->header.length = cpu_to_be16(sizeof(OprtnsCommand) + src_len);
+    oc->header.type = SCLP_EVENT_OPRTNS_COMMAND;
+    *slen = avail - src_len;
+
+    return 1;
+}
+
+/*
+ * Triggered by SCLP's write_event_data
+ *  - write console data to character layer
+ *  returns < 0 if an error occurred
+ */
+static int write_console_data(SCLPEvent *event, const uint8_t *buf, int len)
+{
+    int ret = 0;
+    const uint8_t *buf_offset;
+
+    SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event);
+
+    if (!scon->chr) {
+        /* If there's no backend, we can just say we consumed all data. */
+        return len;
+    }
+
+    buf_offset = buf;
+    while (len > 0) {
+        ret = qemu_chr_fe_write(scon->chr, buf, len);
+        if (ret == 0) {
+            /* a pty doesn't seem to be connected - no error */
+            len = 0;
+        } else if (ret == -EAGAIN || (ret > 0 && ret < len)) {
+            len -= ret;
+            buf_offset += ret;
+        } else {
+            len = 0;
+        }
+    }
+
+    return ret;
+}
+
+static int process_mdb(SCLPEvent *event, MDBO *mdbo)
+{
+    int rc;
+    int len;
+    uint8_t buffer[SIZE_BUFFER];
+
+    len = be16_to_cpu(mdbo->length);
+    len -= sizeof(mdbo->length) + sizeof(mdbo->type)
+            + sizeof(mdbo->mto.line_type_flags)
+            + sizeof(mdbo->mto.alarm_control)
+            + sizeof(mdbo->mto._reserved);
+
+    assert(len <= SIZE_BUFFER);
+
+    /* convert EBCDIC SCLP contents to ASCII console message */
+    ascii_put(buffer, mdbo->mto.message, len);
+    rc = write_console_data(event, (uint8_t *)NEWLINE, 1);
+    if (rc < 0) {
+        return rc;
+    }
+    return write_console_data(event, buffer, len);
+}
+
+static int write_event_data(SCLPEvent *event, EventBufferHeader *ebh)
+{
+    int len;
+    int written;
+    int errors = 0;
+    MDBO *mdbo;
+    SclpMsg *data = (SclpMsg *) ebh;
+    SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event);
+
+    len = be16_to_cpu(data->mdb.header.length);
+    if (len < sizeof(data->mdb.header)) {
+        return SCLP_RC_INCONSISTENT_LENGTHS;
+    }
+    len -= sizeof(data->mdb.header);
+
+    /* first check message buffers */
+    mdbo = data->mdb.mdbo;
+    while (len > 0) {
+        if (be16_to_cpu(mdbo->length) > len
+                || be16_to_cpu(mdbo->length) == 0) {
+            return SCLP_RC_INCONSISTENT_LENGTHS;
+        }
+        len -= be16_to_cpu(mdbo->length);
+        mdbo = (void *) mdbo + be16_to_cpu(mdbo->length);
+    }
+
+    /* then execute */
+    len = be16_to_cpu(data->mdb.header.length) - sizeof(data->mdb.header);
+    mdbo = data->mdb.mdbo;
+    while (len > 0) {
+        switch (be16_to_cpu(mdbo->type)) {
+        case MESSAGE_TEXT:
+            /* message text object */
+            written = process_mdb(event, mdbo);
+            if (written < 0) {
+                /* character layer error */
+                errors++;
+            }
+            break;
+        default: /* ignore */
+            break;
+        }
+        len -= be16_to_cpu(mdbo->length);
+        mdbo = (void *) mdbo + be16_to_cpu(mdbo->length);
+    }
+    if (errors) {
+        scon->write_errors += errors;
+    }
+    data->header.flags = SCLP_EVENT_BUFFER_ACCEPTED;
+
+    return SCLP_RC_NORMAL_COMPLETION;
+}
+
+static void trigger_console_data(void *opaque, int n, int level)
+{
+    sclp_service_interrupt(0);
+}
+
+/* functions for live migration */
+
+static const VMStateDescription vmstate_sclplmconsole = {
+    .name = "sclplmconsole",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_BOOL(event.event_pending, SCLPConsoleLM),
+        VMSTATE_UINT32(write_errors, SCLPConsoleLM),
+        VMSTATE_UINT32(length, SCLPConsoleLM),
+        VMSTATE_UINT8_ARRAY(buf, SCLPConsoleLM, SIZE_CONSOLE_BUFFER),
+        VMSTATE_END_OF_LIST()
+     }
+};
+
+/* qemu object creation and initialization functions */
+
+/* tell character layer our call-back functions */
+
+static int console_init(SCLPEvent *event)
+{
+    static bool console_available;
+
+    SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event);
+
+    if (console_available) {
+        error_report("Multiple line-mode operator consoles are not supported");
+        return -1;
+    }
+    console_available = true;
+
+    if (scon->chr) {
+        qemu_chr_add_handlers(scon->chr, chr_can_read, chr_read, NULL, scon);
+    }
+    scon->irq_console_read = *qemu_allocate_irqs(trigger_console_data, NULL, 1);
+
+    return 0;
+}
+
+static int console_exit(SCLPEvent *event)
+{
+    return 0;
+}
+
+static void console_reset(DeviceState *dev)
+{
+   SCLPEvent *event = SCLP_EVENT(dev);
+   SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event);
+
+   event->event_pending = false;
+   scon->length = 0;
+   scon->write_errors = 0;
+}
+
+static Property console_properties[] = {
+    DEFINE_PROP_CHR("chardev", SCLPConsoleLM, chr),
+    DEFINE_PROP_UINT32("write_errors", SCLPConsoleLM, write_errors, 0),
+    DEFINE_PROP_BOOL("echo", SCLPConsoleLM, echo, true),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void console_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SCLPEventClass *ec = SCLP_EVENT_CLASS(klass);
+
+    dc->props = console_properties;
+    dc->reset = console_reset;
+    dc->vmsd = &vmstate_sclplmconsole;
+    ec->init = console_init;
+    ec->exit = console_exit;
+    ec->get_send_mask = send_mask;
+    ec->get_receive_mask = receive_mask;
+    ec->can_handle_event = can_handle_event;
+    ec->read_event_data = read_event_data;
+    ec->write_event_data = write_event_data;
+}
+
+static const TypeInfo sclp_console_info = {
+    .name          = "sclplmconsole",
+    .parent        = TYPE_SCLP_EVENT,
+    .instance_size = sizeof(SCLPConsoleLM),
+    .class_init    = console_class_init,
+    .class_size    = sizeof(SCLPEventClass),
+};
+
+static void register_types(void)
+{
+    type_register_static(&sclp_console_info);
+}
+
+type_init(register_types)
index eb3988c..16d77c5 100644 (file)
@@ -31,12 +31,11 @@ typedef struct ASCIIConsoleData {
 typedef struct SCLPConsole {
     SCLPEvent event;
     CharDriverState *chr;
-    /* io vector                                                       */
-    uint8_t *iov;           /* iov buffer pointer                      */
-    uint8_t *iov_sclp;      /* pointer to SCLP read offset             */
-    uint8_t *iov_bs;        /* pointer byte stream read offset         */
-    uint32_t iov_data_len;  /* length of byte stream in buffer         */
-    uint32_t iov_sclp_rest; /* length of byte stream not read via SCLP */
+    uint8_t iov[SIZE_BUFFER_VT220];
+    uint32_t iov_sclp;      /* offset in buf for SCLP read operation       */
+    uint32_t iov_bs;        /* offset in buf for char layer read operation */
+    uint32_t iov_data_len;  /* length of byte stream in buffer             */
+    uint32_t iov_sclp_rest; /* length of byte stream not read via SCLP     */
     qemu_irq irq_read_vt220;
 } SCLPConsole;
 
@@ -47,7 +46,7 @@ static int chr_can_read(void *opaque)
 {
     SCLPConsole *scon = opaque;
 
-    return scon->iov ? SIZE_BUFFER_VT220 - scon->iov_data_len : 0;
+    return SIZE_BUFFER_VT220 - scon->iov_data_len;
 }
 
 /* Receive n bytes from character layer, save in iov buffer,
@@ -55,13 +54,11 @@ static int chr_can_read(void *opaque)
 static void receive_from_chr_layer(SCLPConsole *scon, const uint8_t *buf,
                                    int size)
 {
-    assert(scon->iov);
-
     /* read data must fit into current buffer */
     assert(size <= SIZE_BUFFER_VT220 - scon->iov_data_len);
 
     /* put byte-stream from character layer into buffer */
-    memcpy(scon->iov_bs, buf, size);
+    memcpy(&scon->iov[scon->iov_bs], buf, size);
     scon->iov_data_len += size;
     scon->iov_sclp_rest += size;
     scon->iov_bs += size;
@@ -80,34 +77,11 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
     qemu_irq_raise(scon->irq_read_vt220);
 }
 
-static void chr_event(void *opaque, int event)
-{
-    SCLPConsole *scon = opaque;
-
-    switch (event) {
-    case CHR_EVENT_OPENED:
-        if (!scon->iov) {
-            scon->iov = g_malloc0(SIZE_BUFFER_VT220);
-            scon->iov_sclp = scon->iov;
-            scon->iov_bs = scon->iov;
-            scon->iov_data_len = 0;
-            scon->iov_sclp_rest = 0;
-        }
-        break;
-    case CHR_EVENT_CLOSED:
-        if (scon->iov) {
-            g_free(scon->iov);
-            scon->iov = NULL;
-        }
-        break;
-    }
-}
-
 /* functions to be called by event facility */
 
-static int event_type(void)
+static bool can_handle_event(uint8_t type)
 {
-    return SCLP_EVENT_ASCII_CONSOLE_DATA;
+    return type == SCLP_EVENT_ASCII_CONSOLE_DATA;
 }
 
 static unsigned int send_mask(void)
@@ -134,17 +108,17 @@ static void get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size,
     /* if all data fit into provided SCLP buffer */
     if (avail >= cons->iov_sclp_rest) {
         /* copy character byte-stream to SCLP buffer */
-        memcpy(buf, cons->iov_sclp, cons->iov_sclp_rest);
+        memcpy(buf, &cons->iov[cons->iov_sclp], cons->iov_sclp_rest);
         *size = cons->iov_sclp_rest + 1;
-        cons->iov_sclp = cons->iov;
-        cons->iov_bs = cons->iov;
+        cons->iov_sclp = 0;
+        cons->iov_bs = 0;
         cons->iov_data_len = 0;
         cons->iov_sclp_rest = 0;
         event->event_pending = false;
         /* data provided and no more data pending */
     } else {
         /* if provided buffer is too small, just copy part */
-        memcpy(buf, cons->iov_sclp, avail);
+        memcpy(buf, &cons->iov[cons->iov_sclp], avail);
         *size = avail + 1;
         cons->iov_sclp_rest -= avail;
         cons->iov_sclp += avail;
@@ -223,9 +197,26 @@ static void trigger_ascii_console_data(void *opaque, int n, int level)
     sclp_service_interrupt(0);
 }
 
+static const VMStateDescription vmstate_sclpconsole = {
+    .name = "sclpconsole",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_BOOL(event.event_pending, SCLPConsole),
+        VMSTATE_UINT8_ARRAY(iov, SCLPConsole, SIZE_BUFFER_VT220),
+        VMSTATE_UINT32(iov_sclp, SCLPConsole),
+        VMSTATE_UINT32(iov_bs, SCLPConsole),
+        VMSTATE_UINT32(iov_data_len, SCLPConsole),
+        VMSTATE_UINT32(iov_sclp_rest, SCLPConsole),
+        VMSTATE_END_OF_LIST()
+     }
+};
+
 /* qemu object creation and initialization functions */
 
 /* tell character layer our call-back functions */
+
 static int console_init(SCLPEvent *event)
 {
     static bool console_available;
@@ -237,10 +228,9 @@ static int console_init(SCLPEvent *event)
         return -1;
     }
     console_available = true;
-    event->event_type = SCLP_EVENT_ASCII_CONSOLE_DATA;
     if (scon->chr) {
         qemu_chr_add_handlers(scon->chr, chr_can_read,
-                              chr_read, chr_event, scon);
+                              chr_read, NULL, scon);
     }
     scon->irq_read_vt220 = *qemu_allocate_irqs(trigger_ascii_console_data,
                                                NULL, 1);
@@ -248,6 +238,18 @@ static int console_init(SCLPEvent *event)
     return 0;
 }
 
+static void console_reset(DeviceState *dev)
+{
+   SCLPEvent *event = SCLP_EVENT(dev);
+   SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
+
+   event->event_pending = false;
+   scon->iov_sclp = 0;
+   scon->iov_bs = 0;
+   scon->iov_data_len = 0;
+   scon->iov_sclp_rest = 0;
+}
+
 static int console_exit(SCLPEvent *event)
 {
     return 0;
@@ -264,11 +266,13 @@ static void console_class_init(ObjectClass *klass, void *data)
     SCLPEventClass *ec = SCLP_EVENT_CLASS(klass);
 
     dc->props = console_properties;
+    dc->reset = console_reset;
+    dc->vmsd = &vmstate_sclpconsole;
     ec->init = console_init;
     ec->exit = console_exit;
     ec->get_send_mask = send_mask;
     ec->get_receive_mask = receive_mask;
-    ec->event_type = event_type;
+    ec->can_handle_event = can_handle_event;
     ec->read_event_data = read_event_data;
     ec->write_event_data = write_event_data;
 }
index 6223a55..9328dd1 100644 (file)
@@ -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;
index 907792b..c6042c7 100644 (file)
@@ -741,6 +741,7 @@ static QEMUMachine xenfv_machine = {
     .init = pc_xen_hvm_init,
     .max_cpus = HVM_MAX_VCPUS,
     .default_machine_opts = "accel=xen",
+    .hot_add_cpu = pc_hot_add_cpu,
 };
 #endif
 
index e708cb8..d3f1ee6 100644 (file)
@@ -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@hp.com>
+ *  Markus Armbruster <armbru@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,10 +44,117 @@ 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 bool smbios_immutable;
+
+static struct {
+    bool seen;
+    int headertype;
+    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),
+    .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)
 {
@@ -54,57 +164,33 @@ 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.
  */
 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);
     }
 }
 
-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);
@@ -124,76 +210,94 @@ 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_maybe_add_str(int type, int offset, const char *data)
 {
-    char buf[1024];
-    unsigned char major, minor;
-
-    if (get_param_value(buf, sizeof(buf), "vendor", t))
-        smbios_add_field(0, offsetof(struct smbios_type_0, vendor_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "version", t))
-        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))
-        smbios_add_field(0, offsetof(struct smbios_type_0,
+    if (data) {
+        smbios_add_field(type, offset, data, strlen(data) + 1);
+    }
+}
+
+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),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "release", t)) {
-        if (sscanf(buf, "%hhu.%hhu", &major, &minor) != 2) {
-            error_report("Invalid release");
-            exit(1);
-        }
+                         type0.date);
+    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(const char *t)
+static void smbios_build_type_1_fields(void)
 {
-    char buf[1024];
-
-    if (get_param_value(buf, sizeof(buf), "manufacturer", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, manufacturer_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "product", t))
-        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))
-        smbios_add_field(1, offsetof(struct smbios_type_1, version_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "serial", t))
-        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) {
-            error_report("Invalid UUID");
-            exit(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);
+    }
+}
+
+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;
     }
-    if (get_param_value(buf, sizeof(buf), "sku", t))
-        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))
-        smbios_add_field(1, offsetof(struct smbios_type_1, family_str),
-                         buf, strlen(buf) + 1);
 }
 
-int 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)) {
+    assert(!smbios_immutable);
+    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 +312,8 @@ int 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);
         }
 
@@ -222,18 +326,57 @@ 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)) {
-        unsigned long type = strtoul(buf, NULL, 0);
+    val = qemu_opt_get(opts, "type");
+    if (val) {
+        unsigned long type = strtoul(val, NULL, 0);
+
+        smbios_check_collision(type, SMBIOS_FIELD_ENTRY);
+
         switch (type) {
         case 0:
-            smbios_build_type_0_fields(t);
-            return 0;
+            qemu_opts_validate(opts, qemu_smbios_type0_opts, &local_err);
+            if (local_err) {
+                error_report("%s", error_get_pretty(local_err));
+                exit(1);
+            }
+            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:
-            smbios_build_type_1_fields(t);
-            return 0;
+            qemu_opts_validate(opts, qemu_smbios_type1_opts, &local_err);
+            if (local_err) {
+                error_report("%s", error_get_pretty(local_err));
+                exit(1);
+            }
+            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",
                          type);
@@ -242,5 +385,5 @@ int smbios_entry_add(const char *t)
     }
 
     error_report("Must specify type= or file=");
-    return -1;
+    exit(1);
 }
index dd41008..22dbd05 100644 (file)
@@ -314,6 +314,7 @@ static void virtio_net_reset(VirtIODevice *vdev)
     n->mac_table.uni_overflow = 0;
     memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
     memcpy(&n->mac[0], &n->nic->conf->macaddr, sizeof(n->mac));
+    qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
     memset(n->vlans, 0, MAX_VLAN >> 3);
 }
 
index 221d82b..c041149 100644 (file)
@@ -235,18 +235,24 @@ static void i440fx_pcihost_get_pci_hole64_start(Object *obj, Visitor *v,
                                                 void *opaque, const char *name,
                                                 Error **errp)
 {
-    I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
+    PCIHostState *h = PCI_HOST_BRIDGE(obj);
+    Range w64;
+
+    pci_bus_get_w64_range(h->bus, &w64);
 
-    visit_type_uint64(v, &s->pci_info.w64.begin, name, errp);
+    visit_type_uint64(v, &w64.begin, name, errp);
 }
 
 static void i440fx_pcihost_get_pci_hole64_end(Object *obj, Visitor *v,
                                               void *opaque, const char *name,
                                               Error **errp)
 {
-    I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
+    PCIHostState *h = PCI_HOST_BRIDGE(obj);
+    Range w64;
+
+    pci_bus_get_w64_range(h->bus, &w64);
 
-    visit_type_uint64(v, &s->pci_info.w64.end, name, errp);
+    visit_type_uint64(v, &w64.end, name, errp);
 }
 
 static void i440fx_pcihost_initfn(Object *obj)
index 0cb652d..ad703a4 100644 (file)
@@ -89,18 +89,24 @@ static void q35_host_get_pci_hole64_start(Object *obj, Visitor *v,
                                           void *opaque, const char *name,
                                           Error **errp)
 {
-    Q35PCIHost *s = Q35_HOST_DEVICE(obj);
+    PCIHostState *h = PCI_HOST_BRIDGE(obj);
+    Range w64;
+
+    pci_bus_get_w64_range(h->bus, &w64);
 
-    visit_type_uint64(v, &s->mch.pci_info.w64.begin, name, errp);
+    visit_type_uint64(v, &w64.begin, name, errp);
 }
 
 static void q35_host_get_pci_hole64_end(Object *obj, Visitor *v,
                                         void *opaque, const char *name,
                                         Error **errp)
 {
-    Q35PCIHost *s = Q35_HOST_DEVICE(obj);
+    PCIHostState *h = PCI_HOST_BRIDGE(obj);
+    Range w64;
 
-    visit_type_uint64(v, &s->mch.pci_info.w64.end, name, errp);
+    pci_bus_get_w64_range(h->bus, &w64);
+
+    visit_type_uint64(v, &w64.end, name, errp);
 }
 
 static Property mch_props[] = {
@@ -214,6 +220,16 @@ static void mch_update_pciexbar(MCHPCIState *mch)
     }
     addr = pciexbar & addr_mask;
     pcie_host_mmcfg_update(pehb, enable, addr, length);
+    /* Leave enough space for the MCFG BAR */
+    /*
+     * TODO: this matches current bios behaviour, but it's not a power of two,
+     * which means an MTRR can't cover it exactly.
+     */
+    if (enable) {
+        mch->pci_info.w32.begin = addr + length;
+    } else {
+        mch->pci_info.w32.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT;
+    }
 }
 
 /* PAM */
index ad1c1ca..00554a0 100644 (file)
@@ -1028,8 +1028,10 @@ static pcibus_t pci_bar_address(PCIDevice *d,
         }
         new_addr = pci_get_long(d->config + bar) & ~(size - 1);
         last_addr = new_addr + size - 1;
-        /* NOTE: we have only 64K ioports on PC */
-        if (last_addr <= new_addr || new_addr == 0 || last_addr > UINT16_MAX) {
+        /* Check if 32 bit BAR wraps around explicitly.
+         * TODO: make priorities correct and remove this work around.
+         */
+        if (last_addr <= new_addr || new_addr == 0 || last_addr >= UINT32_MAX) {
             return PCI_BAR_UNMAPPED;
         }
         return new_addr;
@@ -2257,6 +2259,56 @@ void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque)
     bus->iommu_opaque = opaque;
 }
 
+static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
+{
+    Range *range = opaque;
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
+    uint16_t cmd = pci_get_word(dev->config + PCI_COMMAND);
+    int r;
+
+    if (!(cmd & PCI_COMMAND_MEMORY)) {
+        return;
+    }
+
+    if (pc->is_bridge) {
+        pcibus_t base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
+        pcibus_t limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
+
+        base = MAX(base, 0x1ULL << 32);
+
+        if (limit >= base) {
+            Range pref_range;
+            pref_range.begin = base;
+            pref_range.end = limit + 1;
+            range_extend(range, &pref_range);
+        }
+    }
+    for (r = 0; r < PCI_NUM_REGIONS; ++r) {
+        PCIIORegion *region = &dev->io_regions[r];
+        Range region_range;
+
+        if (!region->size ||
+            (region->type & PCI_BASE_ADDRESS_SPACE_IO) ||
+            !(region->type & PCI_BASE_ADDRESS_MEM_TYPE_64)) {
+            continue;
+        }
+        region_range.begin = pci_get_quad(dev->config + pci_bar(dev, r));
+        region_range.end = region_range.begin + region->size;
+
+        region_range.begin = MAX(region_range.begin, 0x1ULL << 32);
+
+        if (region_range.end - 1 >= region_range.begin) {
+            range_extend(range, &region_range);
+        }
+    }
+}
+
+void pci_bus_get_w64_range(PCIBus *bus, Range *range)
+{
+    range->begin = range->end = 0;
+    pci_for_each_device_under_bus(bus, pci_dev_get_w64, range);
+}
+
 static const TypeInfo pci_device_type_info = {
     .name = TYPE_PCI_DEVICE,
     .parent = TYPE_DEVICE,
index a3aceef..25951a0 100644 (file)
@@ -120,7 +120,7 @@ static uint16_t handle_write_event_buf(SCLPEventFacility *ef,
         ec = SCLP_EVENT_GET_CLASS(event);
 
         if (ec->write_event_data &&
-            ec->event_type() == event_buf->type) {
+            ec->can_handle_event(event_buf->type)) {
             rc = ec->write_event_data(event, event_buf);
             break;
         }
@@ -183,7 +183,7 @@ static uint16_t handle_sccb_read_events(SCLPEventFacility *ef, SCCB *sccb,
 {
     uint16_t rc;
     int slen;
-    unsigned elen = 0;
+    unsigned elen;
     BusChild *kid;
     SCLPEvent *event;
     SCLPEventClass *ec;
@@ -203,11 +203,11 @@ static uint16_t handle_sccb_read_events(SCLPEventFacility *ef, SCCB *sccb,
 
         if (mask & ec->get_send_mask()) {
             if (ec->read_event_data(event, event_buf, &slen)) {
+                elen = be16_to_cpu(event_buf->length);
+                event_buf = (EventBufferHeader *) ((char *)event_buf + elen);
                 rc = SCLP_RC_NORMAL_COMPLETION;
             }
         }
-        elen = be16_to_cpu(event_buf->length);
-        event_buf = (void *) event_buf + elen;
     }
 
     if (sccb->h.control_mask[2] & SCLP_VARIABLE_LENGTH_RESPONSE) {
@@ -338,10 +338,19 @@ static int init_event_facility(S390SCLPDevice *sdev)
     return 0;
 }
 
+static void reset_event_facility(DeviceState *dev)
+{
+    S390SCLPDevice *sdev = SCLP_S390_DEVICE(dev);
+
+    sdev->ef->receive_mask = 0;
+}
+
 static void init_event_facility_class(ObjectClass *klass, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(klass);
     S390SCLPDeviceClass *k = SCLP_S390_DEVICE_CLASS(klass);
 
+    dc->reset = reset_event_facility;
     k->init = init_event_facility;
 }
 
index 5fadc86..a3c4bd6 100644 (file)
@@ -22,9 +22,9 @@ typedef struct SignalQuiesce {
     uint8_t unit;
 } QEMU_PACKED SignalQuiesce;
 
-static int event_type(void)
+static bool can_handle_event(uint8_t type)
 {
-    return SCLP_EVENT_SIGNAL_QUIESCE;
+    return type == SCLP_EVENT_SIGNAL_QUIESCE;
 }
 
 static unsigned int send_mask(void)
@@ -65,6 +65,17 @@ static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr,
     return 1;
 }
 
+static const VMStateDescription vmstate_sclpquiesce = {
+    .name = "sclpquiesce",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_BOOL(event_pending, SCLPEvent),
+        VMSTATE_END_OF_LIST()
+     }
+};
+
 typedef struct QuiesceNotifier QuiesceNotifier;
 
 static struct QuiesceNotifier {
@@ -84,8 +95,6 @@ static void quiesce_powerdown_req(Notifier *n, void *opaque)
 
 static int quiesce_init(SCLPEvent *event)
 {
-    event->event_type = SCLP_EVENT_SIGNAL_QUIESCE;
-
     qn.notifier.notify = quiesce_powerdown_req;
     qn.event = event;
 
@@ -94,15 +103,25 @@ static int quiesce_init(SCLPEvent *event)
     return 0;
 }
 
+static void quiesce_reset(DeviceState *dev)
+{
+   SCLPEvent *event = SCLP_EVENT(dev);
+
+   event->event_pending = false;
+}
+
 static void quiesce_class_init(ObjectClass *klass, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(klass);
     SCLPEventClass *k = SCLP_EVENT_CLASS(klass);
 
+    dc->reset = quiesce_reset;
+    dc->vmsd = &vmstate_sclpquiesce;
     k->init = quiesce_init;
 
     k->get_send_mask = send_mask;
     k->get_receive_mask = receive_mask;
-    k->event_type = event_type;
+    k->can_handle_event = can_handle_event;
     k->read_event_data = read_event_data;
     k->write_event_data = NULL;
 }
index 4d36841..24ec52f 100644 (file)
@@ -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;
index 35f0878..0396e33 100644 (file)
@@ -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;
index d82ce5d..197795f 100644 (file)
@@ -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;
     }
index 3eeb6fe..211087a 100644 (file)
@@ -73,6 +73,12 @@ struct BlockDriver {
     /* Any driver implementing this callback is expected to be able to handle
      * NULL file names in its .bdrv_open() implementation */
     void (*bdrv_parse_filename)(const char *filename, QDict *options, Error **errp);
+    /* Drivers not implementing bdrv_parse_filename nor bdrv_open should have
+     * this field set to true, except ones that are defined only by their
+     * child's bs.
+     * An example of the last type will be the quorum block driver.
+     */
+    bool bdrv_needs_filename;
 
     /* For handling image reopen for split or non-split files */
     int (*bdrv_reopen_prepare)(BDRVReopenState *reopen_state,
index 77242e2..8dd1594 100644 (file)
@@ -324,23 +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 (_ARCH_PPC) && !defined (_ARCH_PPC64)
-#  define GETRA_LDST(RA)   (*(int32_t *)((RA) - 4))
-# elif 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)
 {
index 9babeaf..b08ec71 100644 (file)
@@ -13,8 +13,9 @@
  *
  */
 
-int smbios_entry_add(const char *t);
-void smbios_add_field(int type, int offset, const void *data, size_t len);
+#include "qemu/option.h"
+
+void smbios_entry_add(QemuOpts *opts);
 uint8_t *smbios_get_table(size_t *length);
 
 /*
index 37979aa..4b90e5d 100644 (file)
@@ -397,6 +397,7 @@ const char *pci_root_bus_path(PCIDevice *dev);
 PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
 int pci_qdev_find_device(const char *id, PCIDevice **pdev);
 PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root, const char *devaddr);
+void pci_bus_get_w64_range(PCIBus *bus, Range *range);
 
 int pci_parse_devaddr(const char *addr, int *domp, int *busp,
                       unsigned int *slotp, unsigned int *funcp);
diff --git a/include/hw/s390x/ebcdic.h b/include/hw/s390x/ebcdic.h
new file mode 100644 (file)
index 0000000..1d6fde9
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * EBCDIC/ASCII conversion Support
+ *
+ * Copyright (c) 2011 Alexander Graf
+ * Copyright IBM, Corp. 2013
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
+ * option) any later version.  See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef EBCDIC_H_
+#define EBCDIC_H_
+
+/* EBCDIC handling */
+static const uint8_t ebcdic2ascii[] = {
+    0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
+    0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+    0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
+    0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+    0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
+    0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
+    0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
+    0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
+    0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
+    0x87, 0xA4, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21,
+    0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
+    0x8D, 0xE1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
+    0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
+    0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+    0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+    0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+    0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+    0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
+    0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+    0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
+    0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+    0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
+    0x9B, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
+    0xAB, 0x07, 0xAA, 0x7C, 0x07, 0x07, 0x07, 0x07,
+    0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+    0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
+    0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+    0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
+    0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+    0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07,
+};
+
+static const uint8_t ascii2ebcdic[] = {
+    0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
+    0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+    0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
+    0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F,
+    0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
+    0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
+    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+    0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
+    0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+    0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
+    0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
+    0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D,
+    0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+    0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+    0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+    0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF
+};
+
+static inline void ebcdic_put(uint8_t *p, const char *ascii, int len)
+{
+    int i;
+
+    for (i = 0; i < len; i++) {
+        p[i] = ascii2ebcdic[(uint8_t)ascii[i]];
+    }
+}
+
+static inline void ascii_put(uint8_t *p, const char *ebcdic, int len)
+{
+    int i;
+
+    for (i = 0; i < len; i++) {
+        p[i] = ebcdic2ascii[(uint8_t)ebcdic[i]];
+    }
+}
+
+#endif /* EBCDIC_H_ */
index 791ab2a..7ce7079 100644 (file)
 #include "qemu/thread.h"
 
 /* SCLP event types */
+#define SCLP_EVENT_OPRTNS_COMMAND               0x01
+#define SCLP_EVENT_MESSAGE                      0x02
+#define SCLP_EVENT_PMSGCMD                      0x09
 #define SCLP_EVENT_ASCII_CONSOLE_DATA           0x1a
 #define SCLP_EVENT_SIGNAL_QUIESCE               0x1d
 
 /* SCLP event masks */
 #define SCLP_EVENT_MASK_SIGNAL_QUIESCE          0x00000008
 #define SCLP_EVENT_MASK_MSG_ASCII               0x00000040
+#define SCLP_EVENT_MASK_OP_CMD                  0x80000000
+#define SCLP_EVENT_MASK_MSG                     0x40000000
+#define SCLP_EVENT_MASK_PMSGCMD                 0x00800000
 
 #define SCLP_UNCONDITIONAL_READ                 0x00
 #define SCLP_SELECTIVE_READ                     0x01
@@ -43,8 +49,8 @@ typedef struct WriteEventMask {
     uint16_t mask_length;
     uint32_t cp_receive_mask;
     uint32_t cp_send_mask;
-    uint32_t send_mask;
     uint32_t receive_mask;
+    uint32_t send_mask;
 } QEMU_PACKED WriteEventMask;
 
 typedef struct EventBufferHeader {
@@ -54,6 +60,80 @@ typedef struct EventBufferHeader {
     uint16_t _reserved;
 } QEMU_PACKED EventBufferHeader;
 
+typedef struct MdbHeader {
+    uint16_t length;
+    uint16_t type;
+    uint32_t tag;
+    uint32_t revision_code;
+} QEMU_PACKED MdbHeader;
+
+typedef struct MTO {
+    uint16_t line_type_flags;
+    uint8_t  alarm_control;
+    uint8_t  _reserved[3];
+    char     message[];
+} QEMU_PACKED MTO;
+
+typedef struct GO {
+    uint32_t domid;
+    uint8_t  hhmmss_time[8];
+    uint8_t  th_time[3];
+    uint8_t  _reserved_0;
+    uint8_t  dddyyyy_date[7];
+    uint8_t  _reserved_1;
+    uint16_t general_msg_flags;
+    uint8_t  _reserved_2[10];
+    uint8_t  originating_system_name[8];
+    uint8_t  job_guest_name[8];
+} QEMU_PACKED GO;
+
+#define MESSAGE_TEXT 0x0004
+
+typedef struct MDBO {
+    uint16_t length;
+    uint16_t type;
+    union {
+        GO go;
+        MTO mto;
+    };
+} QEMU_PACKED MDBO;
+
+typedef struct MDB {
+    MdbHeader header;
+    MDBO mdbo[0];
+} QEMU_PACKED MDB;
+
+typedef struct SclpMsg {
+    EventBufferHeader header;
+    MDB mdb;
+} QEMU_PACKED SclpMsg;
+
+#define GDS_ID_MDSMU                            0x1310
+#define GDS_ID_CPMSU                            0x1212
+#define GDS_ID_TEXTCMD                          0x1320
+
+typedef struct GdsVector {
+    uint16_t length;
+    uint16_t gds_id;
+} QEMU_PACKED GdsVector;
+
+#define GDS_KEY_SELFDEFTEXTMSG                  0x31
+#define GDS_KEY_TEXTMSG                         0x30
+
+typedef struct GdsSubvector {
+    uint8_t length;
+    uint8_t key;
+} QEMU_PACKED GdsSubvector;
+
+/* MDS Message Unit */
+typedef struct MDMSU {
+    GdsVector mdmsu;
+    GdsVector cpmsu;
+    GdsVector text_command;
+    GdsSubvector self_def_text_message;
+    GdsSubvector text_message;
+} QEMU_PACKED MDMSU;
+
 typedef struct WriteEventData {
     SCCBHeader h;
     EventBufferHeader ebh;
@@ -68,7 +148,6 @@ typedef struct ReadEventData {
 typedef struct SCLPEvent {
     DeviceState qdev;
     bool event_pending;
-    uint32_t event_type;
     char *name;
 } SCLPEvent;
 
@@ -88,9 +167,8 @@ typedef struct SCLPEventClass {
 
     int (*write_event_data)(SCLPEvent *event, EventBufferHeader *evt_buf_hdr);
 
-    /* returns the supported event type */
-    int (*event_type)(void);
-
+    /* can we handle this event type? */
+    bool (*can_handle_event)(uint8_t type);
 } SCLPEventClass;
 
 #endif
index 1b66510..76f6ac2 100644 (file)
@@ -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;
index 1c31b5d..9d09e60 100644 (file)
@@ -310,8 +310,18 @@ extern const VMStateInfo vmstate_info_bitmap;
     .offset       = vmstate_offset_value(_state, _field, _type),     \
 }
 
-#define VMSTATE_STRUCT_POINTER_TEST(_field, _state, _test, _vmsd, _type) { \
+#define VMSTATE_STRUCT_POINTER_V(_field, _state, _version, _vmsd, _type) { \
     .name         = (stringify(_field)),                             \
+    .version_id   = (_version),                                        \
+    .vmsd         = &(_vmsd),                                        \
+    .size         = sizeof(_type),                                   \
+    .flags        = VMS_STRUCT|VMS_POINTER,                          \
+    .offset       = vmstate_offset_value(_state, _field, _type),     \
+}
+
+#define VMSTATE_STRUCT_POINTER_TEST_V(_field, _state, _test, _version, _vmsd, _type) { \
+    .name         = (stringify(_field)),                             \
+    .version_id   = (_version),                                        \
     .field_exists = (_test),                                         \
     .vmsd         = &(_vmsd),                                        \
     .size         = sizeof(_type),                                   \
@@ -497,7 +507,10 @@ extern const VMStateInfo vmstate_info_bitmap;
     VMSTATE_STRUCT_TEST(_field, _state, NULL, _version, _vmsd, _type)
 
 #define VMSTATE_STRUCT_POINTER(_field, _state, _vmsd, _type)          \
-    VMSTATE_STRUCT_POINTER_TEST(_field, _state, NULL, _vmsd, _type)
+    VMSTATE_STRUCT_POINTER_V(_field, _state, 0, _vmsd, _type)
+
+#define VMSTATE_STRUCT_POINTER_TEST(_field, _state, _test, _vmsd, _type)     \
+    VMSTATE_STRUCT_POINTER_TEST_V(_field, _state, _test, 0, _vmsd, _type)
 
 #define VMSTATE_STRUCT_ARRAY(_field, _state, _num, _version, _vmsd, _type) \
     VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, NULL, _version,   \
index d6855d1..5cefd80 100644 (file)
@@ -67,4 +67,6 @@ const char *qdict_get_try_str(const QDict *qdict, const char *key);
 QDict *qdict_clone_shallow(const QDict *src);
 void qdict_flatten(QDict *qdict);
 
+void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start);
+
 #endif /* QDICT_H */
index 06e2e6f..304c90c 100644 (file)
@@ -184,6 +184,86 @@ static inline unsigned long hweight_long(unsigned long w)
 }
 
 /**
+ * rol8 - rotate an 8-bit value left
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline uint8_t rol8(uint8_t word, unsigned int shift)
+{
+    return (word << shift) | (word >> (8 - shift));
+}
+
+/**
+ * ror8 - rotate an 8-bit value right
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline uint8_t ror8(uint8_t word, unsigned int shift)
+{
+    return (word >> shift) | (word << (8 - shift));
+}
+
+/**
+ * rol16 - rotate a 16-bit value left
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline uint16_t rol16(uint16_t word, unsigned int shift)
+{
+    return (word << shift) | (word >> (16 - shift));
+}
+
+/**
+ * ror16 - rotate a 16-bit value right
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline uint16_t ror16(uint16_t word, unsigned int shift)
+{
+    return (word >> shift) | (word << (16 - shift));
+}
+
+/**
+ * rol32 - rotate a 32-bit value left
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline uint32_t rol32(uint32_t word, unsigned int shift)
+{
+    return (word << shift) | (word >> (32 - shift));
+}
+
+/**
+ * ror32 - rotate a 32-bit value right
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline uint32_t ror32(uint32_t word, unsigned int shift)
+{
+    return (word >> shift) | (word << (32 - shift));
+}
+
+/**
+ * rol64 - rotate a 64-bit value left
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline uint64_t rol64(uint64_t word, unsigned int shift)
+{
+    return (word << shift) | (word >> (64 - shift));
+}
+
+/**
+ * ror64 - rotate a 64-bit value right
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline uint64_t ror64(uint64_t word, unsigned int shift)
+{
+    return (word >> shift) | (word << (64 - shift));
+}
+
+/**
  * extract32:
  * @value: the value to extract the bit field from
  * @start: the lowest bit in the bit field (numbered from 0)
index b76cc0d..aae9720 100644 (file)
@@ -2,6 +2,7 @@
 #define QEMU_RANGE_H
 
 #include <inttypes.h>
+#include <qemu/typedefs.h>
 
 /*
  * Operations on 64 bit address ranges.
@@ -15,7 +16,24 @@ struct Range {
     uint64_t begin; /* First byte of the range, or 0 if empty. */
     uint64_t end;   /* 1 + the last byte. 0 if range empty or ends at ~0x0LL. */
 };
-typedef struct Range Range;
+
+static inline void range_extend(Range *range, Range *extend_by)
+{
+    if (!extend_by->begin && !extend_by->end) {
+        return;
+    }
+    if (!range->begin && !range->end) {
+        *range = *extend_by;
+        return;
+    }
+    if (range->begin > extend_by->begin) {
+        range->begin = extend_by->begin;
+    }
+    /* Compare last byte in case region ends at ~0x0LL */
+    if (range->end - 1 < extend_by->end - 1) {
+        range->end = extend_by->end;
+    }
+}
 
 /* Get last byte of a range from offset + length.
  * Undefined for ranges that wrap around 0. */
index c5174d7..45588d7 100644 (file)
@@ -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);
 
index 3205540..a4c1b84 100644 (file)
@@ -68,5 +68,6 @@ typedef struct QEMUSGList QEMUSGList;
 typedef struct SHPCDevice SHPCDevice;
 typedef struct FWCfgState FWCfgState;
 typedef struct PcGuestInfo PcGuestInfo;
+typedef struct Range Range;
 
 #endif /* QEMU_TYPEDEFS_H */
index dece913..be71bca 100644 (file)
@@ -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);
index e2c6f58..cd5791e 100644 (file)
@@ -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"
@@ -41,9 +42,11 @@ int vm_stop(RunState state);
 int vm_stop_force_state(RunState state);
 
 typedef enum WakeupReason {
-    QEMU_WAKEUP_REASON_OTHER = 0,
+    /* Always keep QEMU_WAKEUP_REASON_NONE = 0 */
+    QEMU_WAKEUP_REASON_NONE = 0,
     QEMU_WAKEUP_REASON_RTC,
     QEMU_WAKEUP_REASON_PMTIMER,
+    QEMU_WAKEUP_REASON_OTHER,
 } WakeupReason;
 
 void qemu_system_reset_request(void);
index ac2b6e2..d52d76e 100644 (file)
@@ -20,7 +20,7 @@
 #define TARGET_NR_lseek                 19
 #define TARGET_NR_getxpid               20
 #define TARGET_NR_osf_mount             21
-#define TARGET_NR_umount                22
+#define TARGET_NR_umount2               22
 #define TARGET_NR_setuid                23
 #define TARGET_NR_getxuid               24
 #define TARGET_NR_exec_with_loader      25     /* not implemented */
 #define TARGET_NR_sysinfo              318
 #define TARGET_NR__sysctl              319
 /* 320 was sys_idle.  */
-#define TARGET_NR_oldumount            321
+#define TARGET_NR_umount               321
 #define TARGET_NR_swapon               322
 #define TARGET_NR_times                323
 #define TARGET_NR_personality  324
index 439c2a9..7381012 100644 (file)
@@ -20,6 +20,7 @@
      IOCTL(TIOCSCTTY, 0, TYPE_INT)
      IOCTL(TIOCGPGRP, IOC_R, MK_PTR(TYPE_INT))
      IOCTL(TIOCSPGRP, IOC_W, MK_PTR(TYPE_INT))
+     IOCTL(TIOCGSID, IOC_W, MK_PTR(TYPE_INT))
      IOCTL(TIOCOUTQ, IOC_R, MK_PTR(TYPE_INT))
      IOCTL(TIOCSTI, IOC_W, MK_PTR(TYPE_INT))
      IOCTL(TIOCMGET, IOC_R, MK_PTR(TYPE_INT))
index 5cd6d91..a1fe5ed 100644 (file)
@@ -131,7 +131,7 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
     return sp;
 }
 
-int loader_exec(const char * filename, char ** argv, char ** envp,
+int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
              struct target_pt_regs * regs, struct image_info *infop,
              struct linux_binprm *bprm)
 {
@@ -140,11 +140,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
 
     bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
     memset(bprm->page, 0, sizeof(bprm->page));
-    retval = open(filename, O_RDONLY);
-    if (retval < 0) {
-        return -errno;
-    }
-    bprm->fd = retval;
+    bprm->fd = fdexec;
     bprm->filename = (char *)filename;
     bprm->argc = count(argv);
     bprm->argv = argv;
index 01e3cd4..1561950 100644 (file)
@@ -1861,7 +1861,7 @@ static const uint8_t mips_syscall_args[] = {
        MIPS_SYS(sys_lseek      , 3)
        MIPS_SYS(sys_getpid     , 0)    /* 4020 */
        MIPS_SYS(sys_mount      , 5)
-       MIPS_SYS(sys_oldumount  , 1)
+       MIPS_SYS(sys_umount     , 1)
        MIPS_SYS(sys_setuid     , 1)
        MIPS_SYS(sys_getuid     , 0)
        MIPS_SYS(sys_stime      , 1)    /* 4025 */
@@ -1891,7 +1891,7 @@ static const uint8_t mips_syscall_args[] = {
        MIPS_SYS(sys_geteuid    , 0)
        MIPS_SYS(sys_getegid    , 0)    /* 4050 */
        MIPS_SYS(sys_acct       , 0)
-       MIPS_SYS(sys_umount     , 2)
+       MIPS_SYS(sys_umount2    , 2)
        MIPS_SYS(sys_ni_syscall , 0)
        MIPS_SYS(sys_ioctl      , 3)
        MIPS_SYS(sys_fcntl      , 3)    /* 4055 */
@@ -2400,12 +2400,31 @@ done_syscall:
                 if (env->hflags & MIPS_HFLAG_M16) {
                     if (env->insn_flags & ASE_MICROMIPS) {
                         /* microMIPS mode */
-                        abi_ulong instr[2];
-
-                        ret = get_user_u16(instr[0], env->active_tc.PC) ||
-                              get_user_u16(instr[1], env->active_tc.PC + 2);
+                        ret = get_user_u16(trap_instr, env->active_tc.PC);
+                        if (ret != 0) {
+                            goto error;
+                        }
 
-                        trap_instr = (instr[0] << 16) | instr[1];
+                        if ((trap_instr >> 10) == 0x11) {
+                            /* 16-bit instruction */
+                            code = trap_instr & 0xf;
+                        } else {
+                            /* 32-bit instruction */
+                            abi_ulong instr_lo;
+
+                            ret = get_user_u16(instr_lo,
+                                               env->active_tc.PC + 2);
+                            if (ret != 0) {
+                                goto error;
+                            }
+                            trap_instr = (trap_instr << 16) | instr_lo;
+                            code = ((trap_instr >> 6) & ((1 << 20) - 1));
+                            /* Unfortunately, microMIPS also suffers from
+                               the old assembler bug...  */
+                            if (code >= (1 << 10)) {
+                                code >>= 10;
+                            }
+                        }
                     } else {
                         /* MIPS16e mode */
                         ret = get_user_u16(trap_instr, env->active_tc.PC);
@@ -2413,26 +2432,21 @@ done_syscall:
                             goto error;
                         }
                         code = (trap_instr >> 6) & 0x3f;
-                        if (do_break(env, &info, code) != 0) {
-                            goto error;
-                        }
-                        break;
                     }
                 } else {
                     ret = get_user_ual(trap_instr, env->active_tc.PC);
-                }
-
-                if (ret != 0) {
-                    goto error;
-                }
+                    if (ret != 0) {
+                        goto error;
+                    }
 
-                /* As described in the original Linux kernel code, the
-                 * below checks on 'code' are to work around an old
-                 * assembly bug.
-                 */
-                code = ((trap_instr >> 6) & ((1 << 20) - 1));
-                if (code >= (1 << 10)) {
-                    code >>= 10;
+                    /* As described in the original Linux kernel code, the
+                     * below checks on 'code' are to work around an old
+                     * assembly bug.
+                     */
+                    code = ((trap_instr >> 6) & ((1 << 20) - 1));
+                    if (code >= (1 << 10)) {
+                        code >>= 10;
+                    }
                 }
 
                 if (do_break(env, &info, code) != 0) {
@@ -3618,6 +3632,26 @@ static int parse_args(int argc, char **argv)
     return optind;
 }
 
+static int get_execfd(char **envp)
+{
+    typedef struct {
+        long a_type;
+        long a_val;
+    } auxv_t;
+    auxv_t *auxv;
+
+    while (*envp++ != NULL) {
+        ;
+    }
+
+    for (auxv = (auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) {
+        if (auxv->a_type == AT_EXECFD) {
+            return auxv->a_val;
+        }
+    }
+    return -1;
+}
+
 int main(int argc, char **argv, char **envp)
 {
     struct target_pt_regs regs1, *regs = &regs1;
@@ -3632,6 +3666,7 @@ int main(int argc, char **argv, char **envp)
     int target_argc;
     int i;
     int ret;
+    int execfd;
 
     module_call_init(MODULE_INIT_QOM);
 
@@ -3809,7 +3844,16 @@ int main(int argc, char **argv, char **envp)
     env->opaque = ts;
     task_settid(ts);
 
-    ret = loader_exec(filename, target_argv, target_environ, regs,
+    execfd = get_execfd(envp);
+    if (execfd < 0) {
+        execfd = open(filename, O_RDONLY);
+    }
+    if (execfd < 0) {
+        printf("Error while loading %s: %s\n", filename, strerror(-execfd));
+        _exit(1);
+    }
+
+    ret = loader_exec(execfd, filename, target_argv, target_environ, regs,
         info, &bprm);
     if (ret != 0) {
         printf("Error while loading %s: %s\n", filename, strerror(-ret));
index 617cac1..da64e87 100644 (file)
@@ -174,7 +174,7 @@ struct linux_binprm {
 void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
 abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
                               abi_ulong stringp, int push_ptr);
-int loader_exec(const char * filename, char ** argv, char ** envp,
+int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
              struct target_pt_regs * regs, struct image_info *infop,
              struct linux_binprm *);
 
index 08f115d..cf5841a 100644 (file)
 #ifdef TARGET_NR_oldstat
 { TARGET_NR_oldstat, "oldstat" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_oldumount
-{ TARGET_NR_oldumount, "oldumount" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_olduname
 { TARGET_NR_olduname, "olduname" , NULL, NULL, NULL },
 #endif
 #ifdef TARGET_NR_pipe2
 { TARGET_NR_pipe2, "pipe2", NULL, NULL, NULL },
 #endif
+#ifdef TARGET_NR_atomic_cmpxchg_32
+{ TARGET_NR_atomic_cmpxchg_32, "atomic_cmpxchg_32", NULL, NULL, NULL },
+#endif
+#ifdef TARGET_NR_atomic_barrier
+{ TARGET_NR_atomic_barrier, "atomic_barrier", NULL, NULL, NULL },
+#endif
index c62d875..4a14a43 100644 (file)
@@ -106,6 +106,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
 #include <linux/dm-ioctl.h>
 #include <linux/reboot.h>
 #include <linux/route.h>
+#include <linux/filter.h>
 #include "linux_loop.h"
 #include "cpu-uname.h"
 
@@ -1149,11 +1150,15 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
             break;
         }
 
-        cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
+        if (tswap32(target_cmsg->cmsg_level) == TARGET_SOL_SOCKET) {
+            cmsg->cmsg_level = SOL_SOCKET;
+        } else {
+            cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
+        }
         cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
         cmsg->cmsg_len = CMSG_LEN(len);
 
-        if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
+        if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
             gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
             memcpy(data, target_data, len);
         } else {
@@ -1204,11 +1209,15 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
             break;
         }
 
-        target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
+        if (cmsg->cmsg_level == SOL_SOCKET) {
+            target_cmsg->cmsg_level = tswap32(TARGET_SOL_SOCKET);
+        } else {
+            target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
+        }
         target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
         target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(len));
 
-        if ((cmsg->cmsg_level == TARGET_SOL_SOCKET) &&
+        if ((cmsg->cmsg_level == SOL_SOCKET) &&
                                 (cmsg->cmsg_type == SCM_RIGHTS)) {
             int *fd = (int *)data;
             int *target_fd = (int *)target_data;
@@ -1216,7 +1225,7 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
 
             for (i = 0; i < numfds; i++)
                 target_fd[i] = tswap32(fd[i]);
-        } else if ((cmsg->cmsg_level == TARGET_SOL_SOCKET) &&
+        } else if ((cmsg->cmsg_level == SOL_SOCKET) &&
                                 (cmsg->cmsg_type == SO_TIMESTAMP) &&
                                 (len == sizeof(struct timeval))) {
             /* copy struct timeval to target */
@@ -1314,6 +1323,26 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
             goto unimplemented;
         }
         break;
+    case SOL_IPV6:
+        switch (optname) {
+        case IPV6_MTU_DISCOVER:
+        case IPV6_MTU:
+        case IPV6_V6ONLY:
+        case IPV6_RECVPKTINFO:
+            val = 0;
+            if (optlen < sizeof(uint32_t)) {
+                return -TARGET_EINVAL;
+            }
+            if (get_user_u32(val, optval_addr)) {
+                return -TARGET_EFAULT;
+            }
+            ret = get_errno(setsockopt(sockfd, level, optname,
+                                       &val, sizeof(val)));
+            break;
+        default:
+            goto unimplemented;
+        }
+        break;
     case SOL_RAW:
         switch (optname) {
         case ICMP_FILTER:
@@ -1357,6 +1386,49 @@ set_timeout:
         case TARGET_SO_SNDTIMEO:
                 optname = SO_SNDTIMEO;
                 goto set_timeout;
+        case TARGET_SO_ATTACH_FILTER:
+        {
+                struct target_sock_fprog *tfprog;
+                struct target_sock_filter *tfilter;
+                struct sock_fprog fprog;
+                struct sock_filter *filter;
+                int i;
+
+                if (optlen != sizeof(*tfprog)) {
+                    return -TARGET_EINVAL;
+                }
+                if (!lock_user_struct(VERIFY_READ, tfprog, optval_addr, 0)) {
+                    return -TARGET_EFAULT;
+                }
+                if (!lock_user_struct(VERIFY_READ, tfilter,
+                                      tswapal(tfprog->filter), 0)) {
+                    unlock_user_struct(tfprog, optval_addr, 1);
+                    return -TARGET_EFAULT;
+                }
+
+                fprog.len = tswap16(tfprog->len);
+                filter = malloc(fprog.len * sizeof(*filter));
+                if (filter == NULL) {
+                    unlock_user_struct(tfilter, tfprog->filter, 1);
+                    unlock_user_struct(tfprog, optval_addr, 1);
+                    return -TARGET_ENOMEM;
+                }
+                for (i = 0; i < fprog.len; i++) {
+                    filter[i].code = tswap16(tfilter[i].code);
+                    filter[i].jt = tfilter[i].jt;
+                    filter[i].jf = tfilter[i].jf;
+                    filter[i].k = tswap32(tfilter[i].k);
+                }
+                fprog.filter = filter;
+
+                ret = get_errno(setsockopt(sockfd, SOL_SOCKET,
+                                SO_ATTACH_FILTER, &fprog, sizeof(fprog)));
+                free(filter);
+
+                unlock_user_struct(tfilter, tfprog->filter, 1);
+                unlock_user_struct(tfprog, optval_addr, 1);
+                return ret;
+        }
             /* Options with 'int' argument.  */
         case TARGET_SO_DEBUG:
                optname = SO_DEBUG;
@@ -1701,7 +1773,7 @@ static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
     free(vec);
 }
 
-static inline void target_to_host_sock_type(int *type)
+static inline int target_to_host_sock_type(int *type)
 {
     int host_type = 0;
     int target_type = *type;
@@ -1718,22 +1790,56 @@ static inline void target_to_host_sock_type(int *type)
         break;
     }
     if (target_type & TARGET_SOCK_CLOEXEC) {
+#if defined(SOCK_CLOEXEC)
         host_type |= SOCK_CLOEXEC;
+#else
+        return -TARGET_EINVAL;
+#endif
     }
     if (target_type & TARGET_SOCK_NONBLOCK) {
+#if defined(SOCK_NONBLOCK)
         host_type |= SOCK_NONBLOCK;
+#elif !defined(O_NONBLOCK)
+        return -TARGET_EINVAL;
+#endif
     }
     *type = host_type;
+    return 0;
+}
+
+/* Try to emulate socket type flags after socket creation.  */
+static int sock_flags_fixup(int fd, int target_type)
+{
+#if !defined(SOCK_NONBLOCK) && defined(O_NONBLOCK)
+    if (target_type & TARGET_SOCK_NONBLOCK) {
+        int flags = fcntl(fd, F_GETFL);
+        if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) {
+            close(fd);
+            return -TARGET_EINVAL;
+        }
+    }
+#endif
+    return fd;
 }
 
 /* do_socket() Must return target values and target errnos. */
 static abi_long do_socket(int domain, int type, int protocol)
 {
-    target_to_host_sock_type(&type);
+    int target_type = type;
+    int ret;
+
+    ret = target_to_host_sock_type(&type);
+    if (ret) {
+        return ret;
+    }
 
     if (domain == PF_NETLINK)
         return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
-    return get_errno(socket(domain, type, protocol));
+    ret = get_errno(socket(domain, type, protocol));
+    if (ret >= 0) {
+        ret = sock_flags_fixup(ret, target_type);
+    }
+    return ret;
 }
 
 /* do_bind() Must return target values and target errnos. */
@@ -5071,22 +5177,70 @@ static int is_proc_myself(const char *filename, const char *entry)
     return 0;
 }
 
+#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
+static int is_proc(const char *filename, const char *entry)
+{
+    return strcmp(filename, entry) == 0;
+}
+
+static int open_net_route(void *cpu_env, int fd)
+{
+    FILE *fp;
+    char *line = NULL;
+    size_t len = 0;
+    ssize_t read;
+
+    fp = fopen("/proc/net/route", "r");
+    if (fp == NULL) {
+        return -EACCES;
+    }
+
+    /* read header */
+
+    read = getline(&line, &len, fp);
+    dprintf(fd, "%s", line);
+
+    /* read routes */
+
+    while ((read = getline(&line, &len, fp)) != -1) {
+        char iface[16];
+        uint32_t dest, gw, mask;
+        unsigned int flags, refcnt, use, metric, mtu, window, irtt;
+        sscanf(line, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
+                     iface, &dest, &gw, &flags, &refcnt, &use, &metric,
+                     &mask, &mtu, &window, &irtt);
+        dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
+                iface, tswap32(dest), tswap32(gw), flags, refcnt, use,
+                metric, tswap32(mask), mtu, window, irtt);
+    }
+
+    free(line);
+    fclose(fp);
+
+    return 0;
+}
+#endif
+
 static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
 {
     struct fake_open {
         const char *filename;
         int (*fill)(void *cpu_env, int fd);
+        int (*cmp)(const char *s1, const char *s2);
     };
     const struct fake_open *fake_open;
     static const struct fake_open fakes[] = {
-        { "maps", open_self_maps },
-        { "stat", open_self_stat },
-        { "auxv", open_self_auxv },
-        { NULL, NULL }
+        { "maps", open_self_maps, is_proc_myself },
+        { "stat", open_self_stat, is_proc_myself },
+        { "auxv", open_self_auxv, is_proc_myself },
+#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
+        { "/proc/net/route", open_net_route, is_proc },
+#endif
+        { NULL, NULL, NULL }
     };
 
     for (fake_open = fakes; fake_open->filename; fake_open++) {
-        if (is_proc_myself(pathname, fake_open->filename)) {
+        if (fake_open->cmp(pathname, fake_open->filename)) {
             break;
         }
     }
@@ -5697,7 +5851,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             unlock_user(p, arg1, 0);
         }
         break;
-#ifdef TARGET_NR_umount2 /* not on alpha */
+#ifdef TARGET_NR_umount2
     case TARGET_NR_umount2:
         if (!(p = lock_user_string(arg1)))
             goto efault;
@@ -9013,6 +9167,34 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
     }
 #endif
+#ifdef TARGET_NR_atomic_cmpxchg_32
+    case TARGET_NR_atomic_cmpxchg_32:
+    {
+        /* should use start_exclusive from main.c */
+        abi_ulong mem_value;
+        if (get_user_u32(mem_value, arg6)) {
+            target_siginfo_t info;
+            info.si_signo = SIGSEGV;
+            info.si_errno = 0;
+            info.si_code = TARGET_SEGV_MAPERR;
+            info._sifields._sigfault._addr = arg6;
+            queue_signal((CPUArchState *)cpu_env, info.si_signo, &info);
+            ret = 0xdeadbeef;
+
+        }
+        if (mem_value == arg2)
+            put_user_u32(arg1, arg6);
+        ret = mem_value;
+        break;
+    }
+#endif
+#ifdef TARGET_NR_atomic_barrier
+    case TARGET_NR_atomic_barrier:
+    {
+        /* Like the kernel implementation and the qemu arm barrier, no-op this? */
+        break;
+    }
+#endif
     default:
     unimplemented:
         gemu_log("qemu: Unsupported syscall: %d\n", num);
index 2ebe356..5f53a28 100644 (file)
@@ -119,6 +119,18 @@ struct target_sockaddr {
     uint8_t sa_data[14];
 };
 
+struct target_sock_filter {
+    abi_ushort code;
+    uint8_t jt;
+    uint8_t jf;
+    abi_uint k;
+};
+
+struct target_sock_fprog {
+    abi_ushort len;
+    abi_ulong filter;
+};
+
 struct target_in_addr {
     uint32_t s_addr; /* big endian */
 };
index 05a155b..f94f3b4 100644 (file)
@@ -356,6 +356,7 @@ typedef struct RDMAContext {
      */
     struct rdma_cm_id *cm_id;               /* connection manager ID */
     struct rdma_cm_id *listen_id;
+    bool connected;
 
     struct ibv_context          *verbs;
     struct rdma_event_channel   *channel;
@@ -510,19 +511,21 @@ static int qemu_rdma_exchange_send(RDMAContext *rdma, RDMAControlHeader *head,
                                    int *resp_idx,
                                    int (*callback)(RDMAContext *rdma));
 
-static inline uint64_t ram_chunk_index(uint8_t *start, uint8_t *host)
+static inline uint64_t ram_chunk_index(const uint8_t *start,
+                                       const uint8_t *host)
 {
     return ((uintptr_t) host - (uintptr_t) start) >> RDMA_REG_CHUNK_SHIFT;
 }
 
-static inline uint8_t *ram_chunk_start(RDMALocalBlock *rdma_ram_block,
+static inline uint8_t *ram_chunk_start(const RDMALocalBlock *rdma_ram_block,
                                        uint64_t i)
 {
     return (uint8_t *) (((uintptr_t) rdma_ram_block->local_host_addr)
                                     + (i << RDMA_REG_CHUNK_SHIFT));
 }
 
-static inline uint8_t *ram_chunk_end(RDMALocalBlock *rdma_ram_block, uint64_t i)
+static inline uint8_t *ram_chunk_end(const RDMALocalBlock *rdma_ram_block,
+                                     uint64_t i)
 {
     uint8_t *result = ram_chunk_start(rdma_ram_block, i) +
                                          (1UL << RDMA_REG_CHUNK_SHIFT);
@@ -2194,7 +2197,7 @@ static void qemu_rdma_cleanup(RDMAContext *rdma)
     struct rdma_cm_event *cm_event;
     int ret, idx;
 
-    if (rdma->cm_id) {
+    if (rdma->cm_id && rdma->connected) {
         if (rdma->error_state) {
             RDMAControlHeader head = { .len = 0,
                                        .type = RDMA_CONTROL_ERROR,
@@ -2213,7 +2216,7 @@ static void qemu_rdma_cleanup(RDMAContext *rdma)
             }
         }
         DDPRINTF("Disconnected.\n");
-        rdma->cm_id = NULL;
+        rdma->connected = false;
     }
 
     g_free(rdma->block);
@@ -2235,7 +2238,7 @@ static void qemu_rdma_cleanup(RDMAContext *rdma)
     }
 
     if (rdma->qp) {
-        ibv_destroy_qp(rdma->qp);
+        rdma_destroy_qp(rdma->cm_id);
         rdma->qp = NULL;
     }
     if (rdma->cq) {
@@ -2372,6 +2375,7 @@ static int qemu_rdma_connect(RDMAContext *rdma, Error **errp)
         rdma->cm_id = NULL;
         goto err_rdma_source_connect;
     }
+    rdma->connected = true;
 
     memcpy(&cap, cm_event->param.conn.private_data, sizeof(cap));
     network_to_caps(&cap);
@@ -2906,6 +2910,7 @@ static int qemu_rdma_accept(RDMAContext *rdma)
     }
 
     rdma_ack_cm_event(cm_event);
+    rdma->connected = true;
 
     ret = qemu_rdma_post_recv_control(rdma, RDMA_WRID_READY);
     if (ret) {
index 200d404..2b1ab20 100644 (file)
@@ -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));
@@ -567,7 +568,8 @@ static void *migration_thread(void *opaque)
         if (!qemu_file_rate_limit(s->file)) {
             DPRINTF("iterate\n");
             pending_size = qemu_savevm_state_pending(s->file, max_size);
-            DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
+            DPRINTF("pending size %" PRIu64 " max %" PRIu64 "\n",
+                    pending_size, max_size);
             if (pending_size && pending_size >= max_size) {
                 qemu_savevm_state_iterate(s->file);
             } else {
index e61309d..fb21e20 100644 (file)
@@ -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;
     }
index e404a22..d70be16 100644 (file)
@@ -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
index 48dbe32..528372b 100644 (file)
Binary files a/pc-bios/acpi-dsdt.aml and b/pc-bios/acpi-dsdt.aml differ
index cccc487..697440c 100644 (file)
Binary files a/pc-bios/bios.bin and b/pc-bios/bios.bin differ
index c6b3319..550273a 100644 (file)
Binary files a/pc-bios/openbios-ppc and b/pc-bios/openbios-ppc differ
index 2aa400c..01105fc 100644 (file)
Binary files a/pc-bios/openbios-sparc32 and b/pc-bios/openbios-sparc32 differ
index f6ee286..62c9e77 100644 (file)
Binary files a/pc-bios/openbios-sparc64 and b/pc-bios/openbios-sparc64 differ
index 91ab67c..4d23746 100644 (file)
Binary files a/pc-bios/q35-acpi-dsdt.aml and b/pc-bios/q35-acpi-dsdt.aml differ
index 05fc7c2..6727f0c 100644 (file)
Binary files a/pc-bios/s390-ccw.img and b/pc-bios/s390-ccw.img differ
index 49f2d29..4d6e48f 100644 (file)
@@ -123,6 +123,7 @@ static void vring_init(struct vring *vr, unsigned int num, void *p,
     /* We're running with interrupts off anyways, so don't bother */
     vr->used->flags = VRING_USED_F_NO_NOTIFY;
     vr->used->idx = 0;
+    vr->used_idx = 0;
 
     debug_print_addr("init vr", vr);
 }
@@ -150,8 +151,6 @@ static void vring_send_buf(struct vring *vr, void *p, int len, int flags)
     if (!(flags & VRING_DESC_F_NEXT)) {
         vr->avail->idx++;
     }
-
-    vr->used->idx = vr->next_idx;
 }
 
 static u64 get_clock(void)
@@ -180,7 +179,8 @@ static int vring_wait_reply(struct vring *vr, int timeout)
     struct subchannel_id schid = vr->schid;
     int r = 0;
 
-    while (vr->used->idx == vr->next_idx) {
+    /* Wait until the used index has moved. */
+    while (vr->used->idx == vr->used_idx) {
         vring_notify(schid);
         if (timeout && (get_second() >= target_second)) {
             r = 1;
@@ -189,6 +189,7 @@ static int vring_wait_reply(struct vring *vr, int timeout)
         yield();
     }
 
+    vr->used_idx = vr->used->idx;
     vr->next_idx = 0;
     vr->desc[0].len = 0;
     vr->desc[0].flags = 0;
index 86fdd57..772a63f 100644 (file)
@@ -115,6 +115,7 @@ struct vring_used {
 struct vring {
     unsigned int num;
     int next_idx;
+    int used_idx;
     struct vring_desc *desc;
     struct vring_avail *avail;
     struct vring_used *used;
index f7f5464..13474de 100644 (file)
@@ -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);
@@ -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);
index 472f106..0f3e0a6 100644 (file)
@@ -527,3 +527,24 @@ void qdict_flatten(QDict *qdict)
 {
     qdict_do_flatten(qdict, qdict, NULL);
 }
+
+/* extract all the src QDict entries starting by start into dst */
+void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start)
+
+{
+    const QDictEntry *entry, *next;
+    const char *p;
+
+    *dst = qdict_new();
+    entry = qdict_first(src);
+
+    while (entry != NULL) {
+        next = qdict_next(src, entry);
+        if (strstart(entry->key, start, &p)) {
+            qobject_incref(entry->value);
+            qdict_put_obj(*dst, p, entry->value);
+            qdict_del(src, entry->key);
+        }
+        entry = next;
+    }
+}
index 7a228ae..10d5a65 100644 (file)
@@ -1,6 +1,8 @@
 
-vgabios_variants := stdvga cirrus vmware qxl
+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
@@ -16,6 +18,22 @@ 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)
+x86_64_cross_prefix := $(call find-cross-prefix,x86_64)
+
+#
 # EfiRom utility is shipped with edk2 / tianocore, in BaseTools/
 #
 # We need that to combine multiple images (legacy bios,
@@ -32,46 +50,91 @@ 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)"
+       @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))
 
-lgplvgabios-%:
-       make -C vgabios vgabios-$*.bin
+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
 
+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-%: 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="" \
+               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))
+
 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 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
similarity index 100%
rename from roms/config.vga.qxl
rename to roms/config.vga-qxl
index 0f3d51e..d363cf5 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 0f3d51ef22ec9166beb3ed434d253029ed7cfe84
+Subproject commit d363cf50c50c268da7e6d0bf707adde1893d1ab9
index d4f7d90..ece025f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d4f7d90f47462b4e8836899adc5060fbde5253e9
+Subproject commit ece025f5980bae88fa677bc9c0d24d2e580e205d
index 4a3c819..2f631d4 100644 (file)
--- a/savevm.c
+++ b/savevm.c
@@ -566,6 +566,13 @@ QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops)
     return f;
 }
 
+/*
+ * Get last error for stream f
+ *
+ * Return negative error value if there has been an error on previous
+ * operations, return 0 if no error happened.
+ *
+ */
 int qemu_file_get_error(QEMUFile *f)
 {
     return f->last_error;
@@ -642,7 +649,7 @@ void ram_control_after_iterate(QEMUFile *f, uint64_t flags)
 
 void ram_control_load_hook(QEMUFile *f, uint64_t flags)
 {
-    int ret = 0;
+    int ret = -EINVAL;
 
     if (f->ops->hook_ram_load) {
         ret = f->ops->hook_ram_load(f, f->opaque, flags);
index 14d5860..90fc0b3 100755 (executable)
 # 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
index c0d4899..6c1636f 100644 (file)
@@ -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);
index 25d60e7..37ac5cf 100644 (file)
@@ -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 */
index 043f28f..7571c5a 100644 (file)
@@ -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);
index b105f87..8cc6cb6 100644 (file)
@@ -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;
index 7953b53..e6cfa62 100644 (file)
@@ -577,7 +577,7 @@ uint64_t HELPER(iwmmxt_rorl)(CPUARMState *env, uint64_t x, uint32_t n)
 
 uint64_t HELPER(iwmmxt_rorq)(CPUARMState *env, uint64_t x, uint32_t n)
 {
-    x = (x >> n) | (x << (64 - n));
+    x = ror64(x, n);
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x);
     return x;
 }
index 2566a04..462f984 100644 (file)
@@ -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)
index 9d36116..5cbb53c 100644 (file)
@@ -151,6 +151,7 @@ static int s390x_write_all_elf64_notes(const char *note_name,
     int ret = -1;
 
     for (nf = note_func; nf->note_contents_func; nf++) {
+        memset(&note, 0, sizeof(note));
         note.hdr.n_namesz = cpu_to_be32(sizeof(note.name));
         note.hdr.n_descsz = cpu_to_be32(nf->contents_size);
         strncpy(note.name, note_name, sizeof(note.name));
index 8be5648..a2c077b 100644 (file)
@@ -148,6 +148,7 @@ typedef struct CPUS390XState {
 } CPUS390XState;
 
 #include "cpu-qom.h"
+#include <sysemu/kvm.h>
 
 /* distinguish between 24 bit and 31 bit addressing */
 #define HIGH_ORDER_BIT 0x80000000
@@ -692,6 +693,14 @@ static inline const char *cc_name(int cc_op)
     return cc_names[cc_op];
 }
 
+static inline void setcc(S390CPU *cpu, uint64_t cc)
+{
+    CPUS390XState *env = &cpu->env;
+
+    env->psw.mask &= ~(3ull << 44);
+    env->psw.mask |= (cc & 3) << 44;
+}
+
 typedef struct LowCore
 {
     /* prefix area: defined by architecture */
@@ -1058,8 +1067,6 @@ void program_interrupt(CPUS390XState *env, uint32_t code, int ilen);
 void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
                                      uintptr_t retaddr);
 
-#include <sysemu/kvm.h>
-
 #ifdef CONFIG_KVM
 void kvm_s390_io_interrupt(S390CPU *cpu, uint16_t subchannel_id,
                            uint16_t subchannel_nr, uint32_t io_int_parm,
index 85fd285..8d6363d 100644 (file)
@@ -36,7 +36,7 @@ int ioinst_disassemble_sch_ident(uint32_t value, int *m, int *cssid, int *ssid,
     return 0;
 }
 
-int ioinst_handle_xsch(CPUS390XState *env, uint64_t reg1)
+void ioinst_handle_xsch(S390CPU *cpu, uint64_t reg1)
 {
     int cssid, ssid, schid, m;
     SubchDev *sch;
@@ -44,8 +44,8 @@ int ioinst_handle_xsch(CPUS390XState *env, uint64_t reg1)
     int cc;
 
     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
-        program_interrupt(env, PGM_OPERAND, 2);
-        return -EIO;
+        program_interrupt(&cpu->env, PGM_OPERAND, 2);
+        return;
     }
     trace_ioinst_sch_id("xsch", cssid, ssid, schid);
     sch = css_find_subch(m, cssid, ssid, schid);
@@ -66,11 +66,10 @@ int ioinst_handle_xsch(CPUS390XState *env, uint64_t reg1)
         cc = 1;
         break;
     }
-
-    return cc;
+    setcc(cpu, cc);
 }
 
-int ioinst_handle_csch(CPUS390XState *env, uint64_t reg1)
+void ioinst_handle_csch(S390CPU *cpu, uint64_t reg1)
 {
     int cssid, ssid, schid, m;
     SubchDev *sch;
@@ -78,8 +77,8 @@ int ioinst_handle_csch(CPUS390XState *env, uint64_t reg1)
     int cc;
 
     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
-        program_interrupt(env, PGM_OPERAND, 2);
-        return -EIO;
+        program_interrupt(&cpu->env, PGM_OPERAND, 2);
+        return;
     }
     trace_ioinst_sch_id("csch", cssid, ssid, schid);
     sch = css_find_subch(m, cssid, ssid, schid);
@@ -91,10 +90,10 @@ int ioinst_handle_csch(CPUS390XState *env, uint64_t reg1)
     } else {
         cc = 0;
     }
-    return cc;
+    setcc(cpu, cc);
 }
 
-int ioinst_handle_hsch(CPUS390XState *env, uint64_t reg1)
+void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1)
 {
     int cssid, ssid, schid, m;
     SubchDev *sch;
@@ -102,8 +101,8 @@ int ioinst_handle_hsch(CPUS390XState *env, uint64_t reg1)
     int cc;
 
     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
-        program_interrupt(env, PGM_OPERAND, 2);
-        return -EIO;
+        program_interrupt(&cpu->env, PGM_OPERAND, 2);
+        return;
     }
     trace_ioinst_sch_id("hsch", cssid, ssid, schid);
     sch = css_find_subch(m, cssid, ssid, schid);
@@ -124,8 +123,7 @@ int ioinst_handle_hsch(CPUS390XState *env, uint64_t reg1)
         cc = 1;
         break;
     }
-
-    return cc;
+    setcc(cpu, cc);
 }
 
 static int ioinst_schib_valid(SCHIB *schib)
@@ -141,7 +139,7 @@ static int ioinst_schib_valid(SCHIB *schib)
     return 1;
 }
 
-int ioinst_handle_msch(CPUS390XState *env, uint64_t reg1, uint32_t ipb)
+void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
 {
     int cssid, ssid, schid, m;
     SubchDev *sch;
@@ -150,22 +148,21 @@ int ioinst_handle_msch(CPUS390XState *env, uint64_t reg1, uint32_t ipb)
     int ret = -ENODEV;
     int cc;
     hwaddr len = sizeof(*schib);
+    CPUS390XState *env = &cpu->env;
 
     addr = decode_basedisp_s(env, ipb);
     if (addr & 3) {
         program_interrupt(env, PGM_SPECIFICATION, 2);
-        return -EIO;
+        return;
     }
     schib = s390_cpu_physical_memory_map(env, addr, &len, 0);
     if (!schib || len != sizeof(*schib)) {
         program_interrupt(env, PGM_ADDRESSING, 2);
-        cc = -EIO;
         goto out;
     }
     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
         !ioinst_schib_valid(schib)) {
         program_interrupt(env, PGM_OPERAND, 2);
-        cc = -EIO;
         goto out;
     }
     trace_ioinst_sch_id("msch", cssid, ssid, schid);
@@ -187,9 +184,10 @@ int ioinst_handle_msch(CPUS390XState *env, uint64_t reg1, uint32_t ipb)
         cc = 1;
         break;
     }
+    setcc(cpu, cc);
+
 out:
     s390_cpu_physical_memory_unmap(env, schib, len, 0);
-    return cc;
 }
 
 static void copy_orb_from_guest(ORB *dest, const ORB *src)
@@ -213,7 +211,7 @@ static int ioinst_orb_valid(ORB *orb)
     return 1;
 }
 
-int ioinst_handle_ssch(CPUS390XState *env, uint64_t reg1, uint32_t ipb)
+void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
 {
     int cssid, ssid, schid, m;
     SubchDev *sch;
@@ -222,23 +220,22 @@ int ioinst_handle_ssch(CPUS390XState *env, uint64_t reg1, uint32_t ipb)
     int ret = -ENODEV;
     int cc;
     hwaddr len = sizeof(*orig_orb);
+    CPUS390XState *env = &cpu->env;
 
     addr = decode_basedisp_s(env, ipb);
     if (addr & 3) {
         program_interrupt(env, PGM_SPECIFICATION, 2);
-        return -EIO;
+        return;
     }
     orig_orb = s390_cpu_physical_memory_map(env, addr, &len, 0);
     if (!orig_orb || len != sizeof(*orig_orb)) {
         program_interrupt(env, PGM_ADDRESSING, 2);
-        cc = -EIO;
         goto out;
     }
     copy_orb_from_guest(&orb, orig_orb);
     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
         !ioinst_orb_valid(&orb)) {
         program_interrupt(env, PGM_OPERAND, 2);
-        cc = -EIO;
         goto out;
     }
     trace_ioinst_sch_id("ssch", cssid, ssid, schid);
@@ -260,38 +257,39 @@ int ioinst_handle_ssch(CPUS390XState *env, uint64_t reg1, uint32_t ipb)
         cc = 1;
         break;
     }
+    setcc(cpu, cc);
 
 out:
     s390_cpu_physical_memory_unmap(env, orig_orb, len, 0);
-    return cc;
 }
 
-int ioinst_handle_stcrw(CPUS390XState *env, uint32_t ipb)
+void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb)
 {
     CRW *crw;
     uint64_t addr;
     int cc;
     hwaddr len = sizeof(*crw);
+    CPUS390XState *env = &cpu->env;
 
     addr = decode_basedisp_s(env, ipb);
     if (addr & 3) {
         program_interrupt(env, PGM_SPECIFICATION, 2);
-        return -EIO;
+        return;
     }
     crw = s390_cpu_physical_memory_map(env, addr, &len, 1);
     if (!crw || len != sizeof(*crw)) {
         program_interrupt(env, PGM_ADDRESSING, 2);
-        cc = -EIO;
         goto out;
     }
     cc = css_do_stcrw(crw);
     /* 0 - crw stored, 1 - zeroes stored */
+    setcc(cpu, cc);
+
 out:
     s390_cpu_physical_memory_unmap(env, crw, len, 1);
-    return cc;
 }
 
-int ioinst_handle_stsch(CPUS390XState *env, uint64_t reg1, uint32_t ipb)
+void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
 {
     int cssid, ssid, schid, m;
     SubchDev *sch;
@@ -299,22 +297,21 @@ int ioinst_handle_stsch(CPUS390XState *env, uint64_t reg1, uint32_t ipb)
     int cc;
     SCHIB *schib;
     hwaddr len = sizeof(*schib);
+    CPUS390XState *env = &cpu->env;
 
     addr = decode_basedisp_s(env, ipb);
     if (addr & 3) {
         program_interrupt(env, PGM_SPECIFICATION, 2);
-        return -EIO;
+        return;
     }
     schib = s390_cpu_physical_memory_map(env, addr, &len, 1);
     if (!schib || len != sizeof(*schib)) {
         program_interrupt(env, PGM_ADDRESSING, 2);
-        cc = -EIO;
         goto out;
     }
 
     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
         program_interrupt(env, PGM_OPERAND, 2);
-        cc = -EIO;
         goto out;
     }
     trace_ioinst_sch_id("stsch", cssid, ssid, schid);
@@ -336,9 +333,10 @@ int ioinst_handle_stsch(CPUS390XState *env, uint64_t reg1, uint32_t ipb)
             cc = 0;
         }
     }
+    setcc(cpu, cc);
+
 out:
     s390_cpu_physical_memory_unmap(env, schib, len, 1);
-    return cc;
 }
 
 int ioinst_handle_tsch(CPUS390XState *env, uint64_t reg1, uint32_t ipb)
@@ -575,7 +573,7 @@ static void ioinst_handle_chsc_unimplemented(ChscResp *res)
     res->param = 0;
 }
 
-int ioinst_handle_chsc(CPUS390XState *env, uint32_t ipb)
+void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb)
 {
     ChscReq *req;
     ChscResp *res;
@@ -584,7 +582,7 @@ int ioinst_handle_chsc(CPUS390XState *env, uint32_t ipb)
     uint16_t len;
     uint16_t command;
     hwaddr map_size = TARGET_PAGE_SIZE;
-    int ret = 0;
+    CPUS390XState *env = &cpu->env;
 
     trace_ioinst("chsc");
     reg = (ipb >> 20) & 0x00f;
@@ -592,19 +590,17 @@ int ioinst_handle_chsc(CPUS390XState *env, uint32_t ipb)
     /* Page boundary? */
     if (addr & 0xfff) {
         program_interrupt(env, PGM_SPECIFICATION, 2);
-        return -EIO;
+        return;
     }
     req = s390_cpu_physical_memory_map(env, addr, &map_size, 1);
     if (!req || map_size != TARGET_PAGE_SIZE) {
         program_interrupt(env, PGM_ADDRESSING, 2);
-        ret = -EIO;
         goto out;
     }
     len = be16_to_cpu(req->len);
     /* Length field valid? */
     if ((len < 16) || (len > 4088) || (len & 7)) {
         program_interrupt(env, PGM_OPERAND, 2);
-        ret = -EIO;
         goto out;
     }
     memset((char *)req + len, 0, TARGET_PAGE_SIZE - len);
@@ -628,7 +624,6 @@ int ioinst_handle_chsc(CPUS390XState *env, uint32_t ipb)
 
 out:
     s390_cpu_physical_memory_unmap(env, req, map_size, 1);
-    return ret;
 }
 
 int ioinst_handle_tpi(CPUS390XState *env, uint32_t ipb)
@@ -666,18 +661,19 @@ out:
 #define SCHM_REG1_UPD(_reg) ((_reg & 0x0000000000000002) >> 1)
 #define SCHM_REG1_DCT(_reg) (_reg & 0x0000000000000001)
 
-int ioinst_handle_schm(CPUS390XState *env, uint64_t reg1, uint64_t reg2,
-                       uint32_t ipb)
+void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2,
+                        uint32_t ipb)
 {
     uint8_t mbk;
     int update;
     int dct;
+    CPUS390XState *env = &cpu->env;
 
     trace_ioinst("schm");
 
     if (SCHM_REG1_RES(reg1)) {
         program_interrupt(env, PGM_OPERAND, 2);
-        return -EIO;
+        return;
     }
 
     mbk = SCHM_REG1_MBK(reg1);
@@ -686,15 +682,13 @@ int ioinst_handle_schm(CPUS390XState *env, uint64_t reg1, uint64_t reg2,
 
     if (update && (reg2 & 0x000000000000001f)) {
         program_interrupt(env, PGM_OPERAND, 2);
-        return -EIO;
+        return;
     }
 
     css_do_schm(mbk, update, dct, update ? reg2 : 0);
-
-    return 0;
 }
 
-int ioinst_handle_rsch(CPUS390XState *env, uint64_t reg1)
+void ioinst_handle_rsch(S390CPU *cpu, uint64_t reg1)
 {
     int cssid, ssid, schid, m;
     SubchDev *sch;
@@ -702,8 +696,8 @@ int ioinst_handle_rsch(CPUS390XState *env, uint64_t reg1)
     int cc;
 
     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
-        program_interrupt(env, PGM_OPERAND, 2);
-        return -EIO;
+        program_interrupt(&cpu->env, PGM_OPERAND, 2);
+        return;
     }
     trace_ioinst_sch_id("rsch", cssid, ssid, schid);
     sch = css_find_subch(m, cssid, ssid, schid);
@@ -724,24 +718,23 @@ int ioinst_handle_rsch(CPUS390XState *env, uint64_t reg1)
         cc = 1;
         break;
     }
-
-    return cc;
-
+    setcc(cpu, cc);
 }
 
 #define RCHP_REG1_RES(_reg) (_reg & 0x00000000ff00ff00)
 #define RCHP_REG1_CSSID(_reg) ((_reg & 0x0000000000ff0000) >> 16)
 #define RCHP_REG1_CHPID(_reg) (_reg & 0x00000000000000ff)
-int ioinst_handle_rchp(CPUS390XState *env, uint64_t reg1)
+void ioinst_handle_rchp(S390CPU *cpu, uint64_t reg1)
 {
     int cc;
     uint8_t cssid;
     uint8_t chpid;
     int ret;
+    CPUS390XState *env = &cpu->env;
 
     if (RCHP_REG1_RES(reg1)) {
         program_interrupt(env, PGM_OPERAND, 2);
-        return -EIO;
+        return;
     }
 
     cssid = RCHP_REG1_CSSID(reg1);
@@ -764,19 +757,16 @@ int ioinst_handle_rchp(CPUS390XState *env, uint64_t reg1)
     default:
         /* Invalid channel subsystem. */
         program_interrupt(env, PGM_OPERAND, 2);
-        return -EIO;
+        return;
     }
-
-    return cc;
+    setcc(cpu, cc);
 }
 
 #define SAL_REG1_INVALID(_reg) (_reg & 0x0000000080000000)
-int ioinst_handle_sal(CPUS390XState *env, uint64_t reg1)
+void ioinst_handle_sal(S390CPU *cpu, uint64_t reg1)
 {
     /* We do not provide address limit checking, so let's suppress it. */
     if (SAL_REG1_INVALID(reg1) || reg1 & 0x000000000000ffff) {
-        program_interrupt(env, PGM_OPERAND, 2);
-        return -EIO;
+        program_interrupt(&cpu->env, PGM_OPERAND, 2);
     }
-    return 0;
 }
index 7bed291..613da49 100644 (file)
@@ -214,20 +214,20 @@ typedef struct IOIntCode {
 
 int ioinst_disassemble_sch_ident(uint32_t value, int *m, int *cssid, int *ssid,
                                  int *schid);
-int ioinst_handle_xsch(CPUS390XState *env, uint64_t reg1);
-int ioinst_handle_csch(CPUS390XState *env, uint64_t reg1);
-int ioinst_handle_hsch(CPUS390XState *env, uint64_t reg1);
-int ioinst_handle_msch(CPUS390XState *env, uint64_t reg1, uint32_t ipb);
-int ioinst_handle_ssch(CPUS390XState *env, uint64_t reg1, uint32_t ipb);
-int ioinst_handle_stcrw(CPUS390XState *env, uint32_t ipb);
-int ioinst_handle_stsch(CPUS390XState *env, uint64_t reg1, uint32_t ipb);
+void ioinst_handle_xsch(S390CPU *cpu, uint64_t reg1);
+void ioinst_handle_csch(S390CPU *cpu, uint64_t reg1);
+void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1);
+void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
+void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
+void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb);
+void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
 int ioinst_handle_tsch(CPUS390XState *env, uint64_t reg1, uint32_t ipb);
-int ioinst_handle_chsc(CPUS390XState *env, uint32_t ipb);
+void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb);
 int ioinst_handle_tpi(CPUS390XState *env, uint32_t ipb);
-int ioinst_handle_schm(CPUS390XState *env, uint64_t reg1, uint64_t reg2,
-                       uint32_t ipb);
-int ioinst_handle_rsch(CPUS390XState *env, uint64_t reg1);
-int ioinst_handle_rchp(CPUS390XState *env, uint64_t reg1);
-int ioinst_handle_sal(CPUS390XState *env, uint64_t reg1);
+void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2,
+                        uint32_t ipb);
+void ioinst_handle_rsch(S390CPU *cpu, uint64_t reg1);
+void ioinst_handle_rchp(S390CPU *cpu, uint64_t reg1);
+void ioinst_handle_sal(S390CPU *cpu, uint64_t reg1);
 
 #endif
index 4923e0a..a444f69 100644 (file)
@@ -418,18 +418,6 @@ static void enter_pgmcheck(S390CPU *cpu, uint16_t code)
     kvm_s390_interrupt(cpu, KVM_S390_PROGRAM_INT, code);
 }
 
-static inline void setcc(S390CPU *cpu, uint64_t cc)
-{
-    CPUS390XState *env = &cpu->env;
-    CPUState *cs = CPU(cpu);
-
-    cs->kvm_run->psw_mask &= ~(3ull << 44);
-    cs->kvm_run->psw_mask |= (cc & 3) << 44;
-
-    env->psw.mask &= ~(3ul << 44);
-    env->psw.mask |= (cc & 3) << 44;
-}
-
 static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run,
                                  uint16_t ipbh0)
 {
@@ -439,6 +427,10 @@ static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run,
     int r = 0;
 
     cpu_synchronize_state(CPU(cpu));
+    if (env->psw.mask & PSW_MASK_PSTATE) {
+        enter_pgmcheck(cpu, PGM_PRIVILEGED);
+        return 0;
+    }
     sccb = env->regs[ipbh0 & 0xf];
     code = env->regs[(ipbh0 & 0xf0) >> 4];
 
@@ -454,8 +446,6 @@ static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run,
 static int kvm_handle_css_inst(S390CPU *cpu, struct kvm_run *run,
                                uint8_t ipa0, uint8_t ipa1, uint8_t ipb)
 {
-    int r = 0;
-    int no_cc = 0;
     CPUS390XState *env = &cpu->env;
     CPUState *cs = CPU(cpu);
 
@@ -469,69 +459,61 @@ static int kvm_handle_css_inst(S390CPU *cpu, struct kvm_run *run,
 
     switch (ipa1) {
     case PRIV_XSCH:
-        r = ioinst_handle_xsch(env, env->regs[1]);
+        ioinst_handle_xsch(cpu, env->regs[1]);
         break;
     case PRIV_CSCH:
-        r = ioinst_handle_csch(env, env->regs[1]);
+        ioinst_handle_csch(cpu, env->regs[1]);
         break;
     case PRIV_HSCH:
-        r = ioinst_handle_hsch(env, env->regs[1]);
+        ioinst_handle_hsch(cpu, env->regs[1]);
         break;
     case PRIV_MSCH:
-        r = ioinst_handle_msch(env, env->regs[1], run->s390_sieic.ipb);
+        ioinst_handle_msch(cpu, env->regs[1], run->s390_sieic.ipb);
         break;
     case PRIV_SSCH:
-        r = ioinst_handle_ssch(env, env->regs[1], run->s390_sieic.ipb);
+        ioinst_handle_ssch(cpu, env->regs[1], run->s390_sieic.ipb);
         break;
     case PRIV_STCRW:
-        r = ioinst_handle_stcrw(env, run->s390_sieic.ipb);
+        ioinst_handle_stcrw(cpu, run->s390_sieic.ipb);
         break;
     case PRIV_STSCH:
-        r = ioinst_handle_stsch(env, env->regs[1], run->s390_sieic.ipb);
+        ioinst_handle_stsch(cpu, env->regs[1], run->s390_sieic.ipb);
         break;
     case PRIV_TSCH:
         /* We should only get tsch via KVM_EXIT_S390_TSCH. */
         fprintf(stderr, "Spurious tsch intercept\n");
         break;
     case PRIV_CHSC:
-        r = ioinst_handle_chsc(env, run->s390_sieic.ipb);
+        ioinst_handle_chsc(cpu, run->s390_sieic.ipb);
         break;
     case PRIV_TPI:
         /* This should have been handled by kvm already. */
         fprintf(stderr, "Spurious tpi intercept\n");
         break;
     case PRIV_SCHM:
-        no_cc = 1;
-        r = ioinst_handle_schm(env, env->regs[1], env->regs[2],
-                               run->s390_sieic.ipb);
+        ioinst_handle_schm(cpu, env->regs[1], env->regs[2],
+                           run->s390_sieic.ipb);
         break;
     case PRIV_RSCH:
-        r = ioinst_handle_rsch(env, env->regs[1]);
+        ioinst_handle_rsch(cpu, env->regs[1]);
         break;
     case PRIV_RCHP:
-        r = ioinst_handle_rchp(env, env->regs[1]);
+        ioinst_handle_rchp(cpu, env->regs[1]);
         break;
     case PRIV_STCPS:
         /* We do not provide this instruction, it is suppressed. */
-        no_cc = 1;
-        r = 0;
         break;
     case PRIV_SAL:
-        no_cc = 1;
-        r = ioinst_handle_sal(env, env->regs[1]);
+        ioinst_handle_sal(cpu, env->regs[1]);
         break;
     case PRIV_SIGA:
         /* Not provided, set CC = 3 for subchannel not operational */
-        r = 3;
+        setcc(cpu, 3);
         break;
     default:
         return -1;
     }
 
-    if (r >= 0 && !no_cc) {
-        setcc(cpu, r);
-    }
-
     return 0;
 }
 
index 1690907..10d0425 100644 (file)
@@ -33,6 +33,7 @@
 #include "exec/softmmu_exec.h"
 #include "sysemu/cpus.h"
 #include "sysemu/sysemu.h"
+#include "hw/s390x/ebcdic.h"
 #endif
 
 /* #define DEBUG_HELPER */
@@ -72,86 +73,6 @@ void HELPER(exception)(CPUS390XState *env, uint32_t excp)
 
 #ifndef CONFIG_USER_ONLY
 
-/* EBCDIC handling */
-static const uint8_t ebcdic2ascii[] = {
-    0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
-    0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-    0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
-    0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-    0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
-    0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
-    0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
-    0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
-    0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
-    0x87, 0xA4, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21,
-    0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
-    0x8D, 0xE1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
-    0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
-    0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
-    0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-    0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
-    0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-    0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
-    0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
-    0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
-    0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-    0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
-    0x9B, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
-    0xAB, 0x07, 0xAA, 0x7C, 0x07, 0x07, 0x07, 0x07,
-    0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
-    0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
-    0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
-    0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
-    0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
-    0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
-    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-    0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07,
-};
-
-static const uint8_t ascii2ebcdic[] = {
-    0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
-    0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-    0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
-    0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F,
-    0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
-    0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
-    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
-    0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
-    0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
-    0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
-    0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
-    0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D,
-    0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-    0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
-    0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
-    0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
-    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-    0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-    0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF
-};
-
-static inline void ebcdic_put(uint8_t *p, const char *ascii, int len)
-{
-    int i;
-
-    for (i = 0; i < len; i++) {
-        p[i] = ascii2ebcdic[(uint8_t)ascii[i]];
-    }
-}
-
 void program_interrupt(CPUS390XState *env, uint32_t code, int ilen)
 {
     qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n",
@@ -192,6 +113,29 @@ static void cpu_reset_all(void)
     }
 }
 
+static void cpu_full_reset_all(void)
+{
+    CPUState *cpu;
+
+    CPU_FOREACH(cpu) {
+        cpu_reset(cpu);
+    }
+}
+
+static int modified_clear_reset(S390CPU *cpu)
+{
+    S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
+
+    pause_all_vcpus();
+    cpu_synchronize_all_states();
+    cpu_full_reset_all();
+    io_subsystem_reset();
+    scc->load_normal(CPU(cpu));
+    cpu_synchronize_all_post_reset();
+    resume_all_vcpus();
+    return 0;
+}
+
 static int load_normal_reset(S390CPU *cpu)
 {
     S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
@@ -225,6 +169,9 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3)
     }
 
     switch (subcode) {
+    case 0:
+        modified_clear_reset(s390_env_get_cpu(env));
+        break;
     case 1:
         load_normal_reset(s390_env_get_cpu(env));
         break;
index eb0e84c..622cc49 100644 (file)
@@ -175,20 +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);
-#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);
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14);
 #endif
         break;
 
@@ -207,6 +199,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;
 
@@ -320,6 +313,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)
@@ -379,13 +375,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)
@@ -810,6 +810,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)
@@ -975,34 +999,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);
     }
 }
 
@@ -1057,23 +1074,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
@@ -1117,53 +1140,62 @@ 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)
 
-/* Load and compare a TLB entry, leaving the flags set.  Leaves R2 pointing
-   to the tlb entry.  Clobbers R1 and TMP.  */
+/* We're expecting to use an 8-bit immediate and to mask.  */
+QEMU_BUILD_BUG_ON(CPU_TLB_BITS > 8);
 
-static void tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
-                             int s_bits, int tlb_offset)
+/* 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.  Returns the register
+   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)
 {
     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]                                    (5)
+     *   cmpeq  r0, tmp, lsl #TARGET_PAGE_BITS
      */
-#  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);
-    if (tlb_offset > 0xff) {
+    /* We checked that the offset is contained within 16 bits above.  */
+    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,
@@ -1175,14 +1207,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);
         }
     }
 
@@ -1192,6 +1221,9 @@ static void 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));
 
@@ -1199,6 +1231,8 @@ 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));
     }
+
+    return TCG_REG_R2;
 }
 
 /* Record the context of a call to the out of line helper code for the slow
@@ -1232,7 +1266,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);
 
@@ -1243,46 +1278,46 @@ 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;
     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);
-        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:
+        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;
-    default:
-        abort();
     }
 
     tcg_out_goto(s, COND_AL, (tcg_target_long)lb->raddr);
@@ -1320,13 +1355,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 */
 
@@ -1336,7 +1368,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
@@ -1353,53 +1385,63 @@ 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));
+    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.  */
     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_read));
+    tcg_out_bl_noaddr(s, COND_NE);
 
     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_bswap32(s, COND_AL, data_reg2, data_reg2);
-            tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
-        } 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);
+        {
+            /* 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;
     }
@@ -1450,9 +1492,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 {
@@ -1474,7 +1520,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
@@ -1491,51 +1537,49 @@ 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));
-
-    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));
+    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_AL, 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_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, addend);
         } 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, addend);
         }
         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, addend);
         } 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, addend);
         }
         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, addend, addr_reg);
+            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
+            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);
         } 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, addend, addr_reg);
+            tcg_out_st32_12(s, COND_EQ, data_reg2, 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);
+
     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 */
@@ -1576,13 +1620,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);
@@ -1991,7 +2036,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" } },
@@ -2003,7 +2048,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" } },
index b29bf25..89e2d6a 100644 (file)
@@ -238,20 +238,16 @@ static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
         return (int64_t)x >> (int64_t)y;
 
     case INDEX_op_rotr_i32:
-        x = ((uint32_t)x << (32 - y)) | ((uint32_t)x >> y);
-        return x;
+        return ror32(x, y);
 
     case INDEX_op_rotr_i64:
-        x = ((uint64_t)x << (64 - y)) | ((uint64_t)x >> y);
-        return x;
+        return ror64(x, y);
 
     case INDEX_op_rotl_i32:
-        x = ((uint32_t)x << y) | ((uint32_t)x >> (32 - y));
-        return x;
+        return rol32(x, y);
 
     case INDEX_op_rotl_i64:
-        x = ((uint64_t)x << y) | ((uint64_t)x >> (64 - y));
-        return x;
+        return rol64(x, y);
 
     CASE_OP_32_64(not):
         return ~x;
index 2595556..97e33ed 100644 (file)
@@ -450,7 +450,9 @@ static const uint32_t tcg_to_bc[] = {
 
 static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
 {
-    tcg_out32 (s, OR | SAB (arg, ret, arg));
+    if (ret != arg) {
+        tcg_out32(s, OR | SAB(arg, ret, arg));
+    }
 }
 
 static void tcg_out_movi(TCGContext *s, TCGType type,
@@ -490,7 +492,8 @@ static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target)
     }
 }
 
-static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg)
+static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg,
+                          int lk)
 {
 #ifdef _CALL_AIX
     int reg;
@@ -504,14 +507,14 @@ static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg)
     tcg_out32 (s, LWZ | RT (0) | RA (reg));
     tcg_out32 (s, MTSPR | RA (0) | CTR);
     tcg_out32 (s, LWZ | RT (2) | RA (reg) | 4);
-    tcg_out32 (s, BCCTR | BO_ALWAYS | LK);
+    tcg_out32 (s, BCCTR | BO_ALWAYS | lk);
 #else
     if (const_arg) {
-        tcg_out_b (s, LK, arg);
+        tcg_out_b (s, lk, arg);
     }
     else {
         tcg_out32 (s, MTSPR | RS (arg) | LR);
-        tcg_out32 (s, BCLR | BO_ALWAYS | LK);
+        tcg_out32 (s, BCLR | BO_ALWAYS | lk);
     }
 #endif
 }
@@ -549,118 +552,128 @@ static void add_qemu_ldst_label (TCGContext *s,
     label->label_ptr[0] = label_ptr;
 }
 
-/* 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 *ld_trampolines[4];
 static void *st_trampolines[4];
 
-static void tcg_out_tlb_check (TCGContext *s, int r0, int r1, int r2,
-                               int addr_reg, int addr_reg2, int s_bits,
-                               int offset1, int offset2, uint8_t **label_ptr)
+/* 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.
+   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,
+                              int mem_index, int is_load, uint8_t **label_ptr)
 {
+    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);
     uint16_t retranst;
+    TCGReg base = TCG_AREG0;
+
+    /* Extract the page index, shifted into place for tlb index.  */
+    tcg_out32(s, (RLWINM
+                  | RA(r0)
+                  | RS(addrlo)
+                  | SH(32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
+                  | MB(32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS))
+                  | ME(31 - CPU_TLB_ENTRY_BITS)));
+
+    /* Compensate for very large offsets.  */
+    if (add_off >= 0x8000) {
+        /* Most target env are smaller than 32k; none are larger than 64k.
+           Simplify the logic here merely to offset by 0x7ff0, giving us a
+           range just shy of 64k.  Check this assumption.  */
+        QEMU_BUILD_BUG_ON(offsetof(CPUArchState,
+                                   tlb_table[NB_MMU_MODES - 1][1])
+                          > 0x7ff0 + 0x7fff);
+        tcg_out32(s, ADDI | RT(r1) | RA(base) | 0x7ff0);
+        base = r1;
+        cmp_off -= 0x7ff0;
+        add_off -= 0x7ff0;
+    }
 
-    tcg_out32 (s, (RLWINM
-                   | RA (r0)
-                   | RS (addr_reg)
-                   | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
-                   | MB (32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS))
-                   | ME (31 - CPU_TLB_ENTRY_BITS)
-                   )
-        );
-    tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0));
-    tcg_out32 (s, (LWZU
-                   | RT (r1)
-                   | RA (r0)
-                   | offset1
-                   )
-        );
-    tcg_out32 (s, (RLWINM
-                   | RA (r2)
-                   | RS (addr_reg)
-                   | SH (0)
-                   | MB ((32 - s_bits) & 31)
-                   | ME (31 - TARGET_PAGE_BITS)
-                   )
-        );
+    /* Clear the non-page, non-alignment bits from the address.  */
+    tcg_out32(s, (RLWINM
+                  | RA(r2)
+                  | RS(addrlo)
+                  | SH(0)
+                  | MB((32 - s_bits) & 31)
+                  | ME(31 - TARGET_PAGE_BITS)));
 
-    tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1));
-#if TARGET_LONG_BITS == 64
-    tcg_out32 (s, LWZ | RT (r1) | RA (r0) | 4);
-    tcg_out32 (s, CMP | BF (6) | RA (addr_reg2) | RB (r1));
-    tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
-#endif
-    *label_ptr = s->code_ptr;
-    retranst = ((uint16_t *) s->code_ptr)[1] & ~3;
-    tcg_out32 (s, BC | BI (7, CR_EQ) | retranst | BO_COND_FALSE);
+    tcg_out32(s, ADD | RT(r0) | RA(r0) | RB(base));
+    base = r0;
 
-    /* r0 now contains &env->tlb_table[mem_index][index].addr_x */
-    tcg_out32 (s, (LWZ
-                   | RT (r0)
-                   | RA (r0)
-                   | offset2
-                   )
-        );
-    /* r0 = env->tlb_table[mem_index][index].addend */
-    tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
-    /* r0 = env->tlb_table[mem_index][index].addend + addr */
+    /* Load the tlb comparator.  */
+    tcg_out32(s, LWZ | RT(r1) | RA(base) | (cmp_off & 0xffff));
 
+    tcg_out32(s, CMP | BF(7) | RA(r2) | RB(r1));
+
+    if (TARGET_LONG_BITS == 64) {
+        tcg_out32(s, LWZ | RT(r1) | RA(base) | ((cmp_off + 4) & 0xffff));
+    }
+
+    /* Load the tlb addend for use on the fast path.
+       Do this asap to minimize load delay.  */
+    tcg_out32(s, LWZ | RT(r0) | RA(base) | (add_off & 0xffff));
+
+    if (TARGET_LONG_BITS == 64) {
+        tcg_out32(s, CMP | BF(6) | RA(addrhi) | RB(r1));
+        tcg_out32(s, CRAND | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));
+    }
+
+    /* Use a conditional branch-and-link so that we load a pointer to
+       somewhere within the current opcode, for passing on to the helper.
+       This address cannot be used for a tail call, but it's shorter
+       than forming an address from scratch.  */
+    *label_ptr = s->code_ptr;
+    retranst = ((uint16_t *) s->code_ptr)[1] & ~3;
+    tcg_out32(s, BC | BI(7, CR_EQ) | retranst | BO_COND_FALSE | LK);
 }
 #endif
 
 static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
 {
-    int addr_reg, data_reg, data_reg2, r0, r1, rbase, bswap;
+    TCGReg addrlo, datalo, datahi, rbase;
+    int bswap;
 #ifdef CONFIG_SOFTMMU
-    int mem_index, s_bits, r2, addr_reg2;
+    int mem_index;
+    TCGReg addrhi;
     uint8_t *label_ptr;
 #endif
 
-    data_reg = *args++;
-    if (opc == 3)
-        data_reg2 = *args++;
-    else
-        data_reg2 = 0;
-    addr_reg = *args++;
+    datalo = *args++;
+    datahi = (opc == 3 ? *args++ : 0);
+    addrlo = *args++;
 
 #ifdef CONFIG_SOFTMMU
-#if TARGET_LONG_BITS == 64
-    addr_reg2 = *args++;
-#else
-    addr_reg2 = 0;
-#endif
+    addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
     mem_index = *args;
-    s_bits = opc & 3;
-    r0 = 3;
-    r1 = 4;
-    r2 = 0;
-    rbase = 0;
-
-    tcg_out_tlb_check (
-        s, r0, r1, r2, addr_reg, addr_reg2, s_bits,
-        offsetof (CPUArchState, tlb_table[mem_index][0].addr_read),
-        offsetof (CPUTLBEntry, addend) - offsetof (CPUTLBEntry, addr_read),
-        &label_ptr
-        );
+
+    tcg_out_tlb_check(s, TCG_REG_R3, TCG_REG_R4, TCG_REG_R0, addrlo,
+                      addrhi, opc & 3, mem_index, 0, &label_ptr);
+    rbase = TCG_REG_R3;
 #else  /* !CONFIG_SOFTMMU */
-    r0 = addr_reg;
-    r1 = 3;
     rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
 #endif
 
@@ -673,106 +686,72 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
     switch (opc) {
     default:
     case 0:
-        tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0));
+        tcg_out32(s, LBZX | TAB(datalo, rbase, addrlo));
         break;
     case 0|4:
-        tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0));
-        tcg_out32 (s, EXTSB | RA (data_reg) | RS (data_reg));
+        tcg_out32(s, LBZX | TAB(datalo, rbase, addrlo));
+        tcg_out32(s, EXTSB | RA(datalo) | RS(datalo));
         break;
     case 1:
-        if (bswap)
-            tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0));
-        else
-            tcg_out32 (s, LHZX | TAB (data_reg, rbase, r0));
+        tcg_out32(s, (bswap ? LHBRX : LHZX) | TAB(datalo, rbase, addrlo));
         break;
     case 1|4:
         if (bswap) {
-            tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0));
-            tcg_out32 (s, EXTSH | RA (data_reg) | RS (data_reg));
+            tcg_out32(s, LHBRX | TAB(datalo, rbase, addrlo));
+            tcg_out32(s, EXTSH | RA(datalo) | RS(datalo));
+        } else {
+            tcg_out32(s, LHAX | TAB(datalo, rbase, addrlo));
         }
-        else tcg_out32 (s, LHAX | TAB (data_reg, rbase, r0));
         break;
     case 2:
-        if (bswap)
-            tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
-        else
-            tcg_out32 (s, LWZX | TAB (data_reg, rbase, r0));
+        tcg_out32(s, (bswap ? LWBRX : LWZX) | TAB(datalo, rbase, addrlo));
         break;
     case 3:
         if (bswap) {
-            tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
-            tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
-            tcg_out32 (s, LWBRX | TAB (data_reg2, rbase, r1));
-        }
-        else {
-#ifdef CONFIG_USE_GUEST_BASE
-            tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
-            tcg_out32 (s, LWZX | TAB (data_reg2, rbase, r0));
-            tcg_out32 (s, LWZX | TAB (data_reg, rbase, r1));
-#else
-            if (r0 == data_reg2) {
-                tcg_out32 (s, LWZ | RT (0) | RA (r0));
-                tcg_out32 (s, LWZ | RT (data_reg) | RA (r0) | 4);
-                tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 0);
-            }
-            else {
-                tcg_out32 (s, LWZ | RT (data_reg2) | RA (r0));
-                tcg_out32 (s, LWZ | RT (data_reg) | RA (r0) | 4);
-            }
-#endif
+            tcg_out32(s, ADDI | RT(TCG_REG_R0) | RA(addrlo) | 4);
+            tcg_out32(s, LWBRX | TAB(datalo, rbase, addrlo));
+            tcg_out32(s, LWBRX | TAB(datahi, rbase, TCG_REG_R0));
+        } else if (rbase != 0) {
+            tcg_out32(s, ADDI | RT(TCG_REG_R0) | RA(addrlo) | 4);
+            tcg_out32(s, LWZX | TAB(datahi, rbase, addrlo));
+            tcg_out32(s, LWZX | TAB(datalo, rbase, TCG_REG_R0));
+        } else if (addrlo == datahi) {
+            tcg_out32(s, LWZ | RT(datalo) | RA(addrlo) | 4);
+            tcg_out32(s, LWZ | RT(datahi) | RA(addrlo));
+        } else {
+            tcg_out32(s, LWZ | RT(datahi) | RA(addrlo));
+            tcg_out32(s, LWZ | RT(datalo) | RA(addrlo) | 4);
         }
         break;
     }
 #ifdef CONFIG_SOFTMMU
-    add_qemu_ldst_label (s,
-                         1,
-                         opc,
-                         data_reg,
-                         data_reg2,
-                         addr_reg,
-                         addr_reg2,
-                         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);
 #endif
 }
 
 static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
 {
-    int addr_reg, r0, r1, data_reg, data_reg2, bswap, rbase;
+    TCGReg addrlo, datalo, datahi, rbase;
+    int bswap;
 #ifdef CONFIG_SOFTMMU
-    int mem_index, r2, addr_reg2;
+    int mem_index;
+    TCGReg addrhi;
     uint8_t *label_ptr;
 #endif
 
-    data_reg = *args++;
-    if (opc == 3)
-        data_reg2 = *args++;
-    else
-        data_reg2 = 0;
-    addr_reg = *args++;
+    datalo = *args++;
+    datahi = (opc == 3 ? *args++ : 0);
+    addrlo = *args++;
 
 #ifdef CONFIG_SOFTMMU
-#if TARGET_LONG_BITS == 64
-    addr_reg2 = *args++;
-#else
-    addr_reg2 = 0;
-#endif
+    addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
     mem_index = *args;
-    r0 = 3;
-    r1 = 4;
-    r2 = 0;
-    rbase = 0;
-
-    tcg_out_tlb_check (
-        s, r0, r1, r2, addr_reg, addr_reg2, opc & 3,
-        offsetof (CPUArchState, tlb_table[mem_index][0].addr_write),
-        offsetof (CPUTLBEntry, addend) - offsetof (CPUTLBEntry, addr_write),
-        &label_ptr
-        );
+
+    tcg_out_tlb_check(s, TCG_REG_R3, TCG_REG_R4, TCG_REG_R0, addrlo,
+                      addrhi, opc & 3, mem_index, 0, &label_ptr);
+    rbase = TCG_REG_R3;
 #else  /* !CONFIG_SOFTMMU */
-    r0 = addr_reg;
-    r1 = 3;
     rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
 #endif
 
@@ -783,180 +762,132 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
 #endif
     switch (opc) {
     case 0:
-        tcg_out32 (s, STBX | SAB (data_reg, rbase, r0));
+        tcg_out32(s, STBX | SAB(datalo, rbase, addrlo));
         break;
     case 1:
-        if (bswap)
-            tcg_out32 (s, STHBRX | SAB (data_reg, rbase, r0));
-        else
-            tcg_out32 (s, STHX | SAB (data_reg, rbase, r0));
+        tcg_out32(s, (bswap ? STHBRX : STHX) | SAB(datalo, rbase, addrlo));
         break;
     case 2:
-        if (bswap)
-            tcg_out32 (s, STWBRX | SAB (data_reg, rbase, r0));
-        else
-            tcg_out32 (s, STWX | SAB (data_reg, rbase, r0));
+        tcg_out32(s, (bswap ? STWBRX : STWX) | SAB(datalo, rbase, addrlo));
         break;
     case 3:
         if (bswap) {
-            tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
-            tcg_out32 (s, STWBRX | SAB (data_reg,  rbase, r0));
-            tcg_out32 (s, STWBRX | SAB (data_reg2, rbase, r1));
-        }
-        else {
-#ifdef CONFIG_USE_GUEST_BASE
-            tcg_out32 (s, STWX | SAB (data_reg2, rbase, r0));
-            tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
-            tcg_out32 (s, STWX | SAB (data_reg,  rbase, r1));
-#else
-            tcg_out32 (s, STW | RS (data_reg2) | RA (r0));
-            tcg_out32 (s, STW | RS (data_reg) | RA (r0) | 4);
-#endif
+            tcg_out32(s, ADDI | RT(TCG_REG_R0) | RA(addrlo) | 4);
+            tcg_out32(s, STWBRX | SAB(datalo, rbase, addrlo));
+            tcg_out32(s, STWBRX | SAB(datahi, rbase, TCG_REG_R0));
+        } else if (rbase != 0) {
+            tcg_out32(s, ADDI | RT(TCG_REG_R0) | RA(addrlo) | 4);
+            tcg_out32(s, STWX | SAB(datahi, rbase, addrlo));
+            tcg_out32(s, STWX | SAB(datalo, rbase, TCG_REG_R0));
+        } else {
+            tcg_out32(s, STW | RS(datahi) | RA(addrlo));
+            tcg_out32(s, STW | RS(datalo) | RA(addrlo) | 4);
         }
         break;
     }
 
 #ifdef CONFIG_SOFTMMU
-    add_qemu_ldst_label (s,
-                         0,
-                         opc,
-                         data_reg,
-                         data_reg2,
-                         addr_reg,
-                         addr_reg2,
-                         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);
 #endif
 }
 
 #if defined(CONFIG_SOFTMMU)
-static void tcg_out_qemu_ld_slow_path (TCGContext *s, TCGLabelQemuLdst *label)
+static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
 {
-    int s_bits;
-    int ir;
-    int opc = label->opc;
-    int mem_index = label->mem_index;
-    int data_reg = label->datalo_reg;
-    int data_reg2 = label->datahi_reg;
-    int addr_reg = label->addrlo_reg;
-    uint8_t *raddr = label->raddr;
-    uint8_t **label_ptr = &label->label_ptr[0];
-
-    s_bits = opc & 3;
-
-    /* resolve label address */
-    reloc_pc14 (label_ptr[0], (tcg_target_long) s->code_ptr);
-
-    /* slow path */
-    ir = 4;
-#if TARGET_LONG_BITS == 32
-    tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg);
-#else
+    TCGReg ir, datalo, datahi;
+
+    reloc_pc14 (l->label_ptr[0], (uintptr_t)s->code_ptr);
+
+    ir = TCG_REG_R4;
+    if (TARGET_LONG_BITS == 32) {
+        tcg_out_mov(s, TCG_TYPE_I32, ir++, l->addrlo_reg);
+    } else {
 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
-    ir |= 1;
-#endif
-    tcg_out_mov (s, TCG_TYPE_I32, ir++, label->addrhi_reg);
-    tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg);
+        ir |= 1;
 #endif
-    tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index);
-    tcg_out_call (s, (tcg_target_long) ld_trampolines[s_bits], 1);
-    tcg_out32 (s, (tcg_target_long) raddr);
-    switch (opc) {
+        tcg_out_mov(s, TCG_TYPE_I32, ir++, l->addrhi_reg);
+        tcg_out_mov(s, TCG_TYPE_I32, ir++, l->addrlo_reg);
+    }
+    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]);
+
+    datalo = l->datalo_reg;
+    switch (l->opc) {
     case 0|4:
-        tcg_out32 (s, EXTSB | RA (data_reg) | RS (3));
+        tcg_out32(s, EXTSB | RA(datalo) | RS(TCG_REG_R3));
         break;
     case 1|4:
-        tcg_out32 (s, EXTSH | RA (data_reg) | RS (3));
+        tcg_out32(s, EXTSH | RA(datalo) | RS(TCG_REG_R3));
         break;
     case 0:
     case 1:
     case 2:
-        if (data_reg != 3)
-            tcg_out_mov (s, TCG_TYPE_I32, data_reg, 3);
+        tcg_out_mov(s, TCG_TYPE_I32, datalo, TCG_REG_R3);
         break;
     case 3:
-        if (data_reg == 3) {
-            if (data_reg2 == 4) {
-                tcg_out_mov (s, TCG_TYPE_I32, 0, 4);
-                tcg_out_mov (s, TCG_TYPE_I32, 4, 3);
-                tcg_out_mov (s, TCG_TYPE_I32, 3, 0);
-            }
-            else {
-                tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 3);
-                tcg_out_mov (s, TCG_TYPE_I32, 3, 4);
-            }
-        }
-        else {
-            if (data_reg != 4) tcg_out_mov (s, TCG_TYPE_I32, data_reg, 4);
-            if (data_reg2 != 3) tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 3);
+        datahi = l->datahi_reg;
+        if (datalo != TCG_REG_R3) {
+            tcg_out_mov(s, TCG_TYPE_I32, datalo, TCG_REG_R4);
+            tcg_out_mov(s, TCG_TYPE_I32, datahi, TCG_REG_R3);
+        } else if (datahi != TCG_REG_R4) {
+            tcg_out_mov(s, TCG_TYPE_I32, datahi, TCG_REG_R3);
+            tcg_out_mov(s, TCG_TYPE_I32, datalo, TCG_REG_R4);
+        } else {
+            tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R0, TCG_REG_R4);
+            tcg_out_mov(s, TCG_TYPE_I32, datahi, TCG_REG_R3);
+            tcg_out_mov(s, TCG_TYPE_I32, datalo, TCG_REG_R0);
         }
         break;
     }
-    /* Jump to the code corresponding to next IR of qemu_st */
-    tcg_out_b (s, 0, (tcg_target_long) raddr);
+    tcg_out_b (s, 0, (uintptr_t)l->raddr);
 }
 
-static void tcg_out_qemu_st_slow_path (TCGContext *s, TCGLabelQemuLdst *label)
+static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
 {
-    int ir;
-    int opc = label->opc;
-    int mem_index = label->mem_index;
-    int data_reg = label->datalo_reg;
-    int data_reg2 = label->datahi_reg;
-    int addr_reg = label->addrlo_reg;
-    uint8_t *raddr = label->raddr;
-    uint8_t **label_ptr = &label->label_ptr[0];
-
-    /* resolve label address */
-    reloc_pc14 (label_ptr[0], (tcg_target_long) s->code_ptr);
-
-    /* slow path */
-    ir = 4;
-#if TARGET_LONG_BITS == 32
-    tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg);
-#else
+    TCGReg ir, datalo;
+
+    reloc_pc14 (l->label_ptr[0], (tcg_target_long) s->code_ptr);
+
+    ir = TCG_REG_R4;
+    if (TARGET_LONG_BITS == 32) {
+        tcg_out_mov (s, TCG_TYPE_I32, ir++, l->addrlo_reg);
+    } else {
 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
-    ir |= 1;
-#endif
-    tcg_out_mov (s, TCG_TYPE_I32, ir++, label->addrhi_reg);
-    tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg);
+        ir |= 1;
 #endif
+        tcg_out_mov (s, TCG_TYPE_I32, ir++, l->addrhi_reg);
+        tcg_out_mov (s, TCG_TYPE_I32, ir++, l->addrlo_reg);
+    }
 
-    switch (opc) {
+    datalo = l->datalo_reg;
+    switch (l->opc) {
     case 0:
-        tcg_out32 (s, (RLWINM
-                       | RA (ir)
-                       | RS (data_reg)
-                       | SH (0)
-                       | MB (24)
-                       | ME (31)));
+        tcg_out32(s, (RLWINM | RA (ir) | RS (datalo)
+                      | SH (0) | MB (24) | ME (31)));
         break;
     case 1:
-        tcg_out32 (s, (RLWINM
-                       | RA (ir)
-                       | RS (data_reg)
-                       | SH (0)
-                       | MB (16)
-                       | ME (31)));
+        tcg_out32(s, (RLWINM | RA (ir) | RS (datalo)
+                      | SH (0) | MB (16) | ME (31)));
         break;
     case 2:
-        tcg_out_mov (s, TCG_TYPE_I32, ir, data_reg);
+        tcg_out_mov(s, TCG_TYPE_I32, ir, datalo);
         break;
     case 3:
 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
         ir |= 1;
 #endif
-        tcg_out_mov (s, TCG_TYPE_I32, ir++, data_reg2);
-        tcg_out_mov (s, TCG_TYPE_I32, ir, data_reg);
+        tcg_out_mov(s, TCG_TYPE_I32, ir++, l->datahi_reg);
+        tcg_out_mov(s, TCG_TYPE_I32, ir, datalo);
         break;
     }
     ir++;
 
-    tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index);
-    tcg_out_call (s, (tcg_target_long) st_trampolines[opc], 1);
-    tcg_out32 (s, (tcg_target_long) raddr);
-    tcg_out_b (s, 0, (tcg_target_long) raddr);
+    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, 0, (uintptr_t)l->raddr);
 }
 
 void tcg_out_tb_finalize(TCGContext *s)
@@ -980,11 +911,8 @@ void tcg_out_tb_finalize(TCGContext *s)
 #ifdef CONFIG_SOFTMMU
 static void emit_ldst_trampoline (TCGContext *s, const void *ptr)
 {
-    tcg_out32 (s, MFSPR | RT (3) | LR);
-    tcg_out32 (s, ADDI | RT (3) | RA (3) | 4);
-    tcg_out32 (s, MTSPR | RS (3) | LR);
     tcg_out_mov (s, TCG_TYPE_I32, 3, TCG_AREG0);
-    tcg_out_b (s, 0, (tcg_target_long) ptr);
+    tcg_out_call (s, (tcg_target_long) ptr, 1, 0);
 }
 #endif
 
@@ -1493,7 +1421,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
         }
         break;
     case INDEX_op_call:
-        tcg_out_call (s, args[0], const_args[0]);
+        tcg_out_call (s, args[0], const_args[0], LK);
         break;
     case INDEX_op_movi_i32:
         tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
@@ -2018,7 +1946,7 @@ static const TCGTargetOpDef ppc_op_defs[] = {
     { 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_ld64, { "L", "L", "L" } },
 
     { INDEX_op_qemu_st8, { "K", "K" } },
     { INDEX_op_qemu_st16, { "K", "K" } },
@@ -2030,7 +1958,7 @@ static const TCGTargetOpDef ppc_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, { "r", "L", "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 0bd1e0c..332f4d8 100644 (file)
 
 static uint8_t *tb_ret_addr;
 
-#define FAST_PATH
-
 #if TARGET_LONG_BITS == 32
-#define LD_ADDR LWZU
+#define LD_ADDR LWZ
 #define CMP_L 0
 #else
-#define LD_ADDR LDU
+#define LD_ADDR LD
 #define CMP_L (1<<21)
 #endif
 
@@ -99,7 +97,7 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
 #endif
 
 static const int tcg_target_reg_alloc_order[] = {
-    TCG_REG_R14,
+    TCG_REG_R14,  /* call saved registers */
     TCG_REG_R15,
     TCG_REG_R16,
     TCG_REG_R17,
@@ -109,29 +107,24 @@ static const int tcg_target_reg_alloc_order[] = {
     TCG_REG_R21,
     TCG_REG_R22,
     TCG_REG_R23,
+    TCG_REG_R24,
+    TCG_REG_R25,
+    TCG_REG_R26,
+    TCG_REG_R27,
     TCG_REG_R28,
     TCG_REG_R29,
     TCG_REG_R30,
     TCG_REG_R31,
-#ifdef __APPLE__
-    TCG_REG_R2,
-#endif
-    TCG_REG_R3,
-    TCG_REG_R4,
-    TCG_REG_R5,
-    TCG_REG_R6,
-    TCG_REG_R7,
-    TCG_REG_R8,
-    TCG_REG_R9,
-    TCG_REG_R10,
-#ifndef __APPLE__
+    TCG_REG_R12,  /* call clobbered, non-arguments */
     TCG_REG_R11,
-#endif
-    TCG_REG_R12,
-    TCG_REG_R24,
-    TCG_REG_R25,
-    TCG_REG_R26,
-    TCG_REG_R27
+    TCG_REG_R10,  /* call clobbered, arguments */
+    TCG_REG_R9,
+    TCG_REG_R8,
+    TCG_REG_R7,
+    TCG_REG_R6,
+    TCG_REG_R5,
+    TCG_REG_R4,
+    TCG_REG_R3,
 };
 
 static const int tcg_target_call_iarg_regs[] = {
@@ -173,58 +166,74 @@ static const int tcg_target_callee_save_regs[] = {
     TCG_REG_R31
 };
 
-static uint32_t reloc_pc24_val (void *pc, tcg_target_long target)
+static inline bool in_range_b(tcg_target_long target)
+{
+    return target == sextract64(target, 0, 26);
+}
+
+static uint32_t reloc_pc24_val(void *pc, tcg_target_long target)
 {
     tcg_target_long disp;
 
-    disp = target - (tcg_target_long) pc;
-    if ((disp << 38) >> 38 != disp)
-        tcg_abort ();
+    disp = target - (tcg_target_long)pc;
+    assert(in_range_b(disp));
 
     return disp & 0x3fffffc;
 }
 
-static void reloc_pc24 (void *pc, tcg_target_long target)
+static void reloc_pc24(void *pc, tcg_target_long target)
 {
-    *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3fffffc)
-        | reloc_pc24_val (pc, target);
+    *(uint32_t *)pc = (*(uint32_t *)pc & ~0x3fffffc)
+        | reloc_pc24_val(pc, target);
 }
 
-static uint16_t reloc_pc14_val (void *pc, tcg_target_long target)
+static uint16_t reloc_pc14_val(void *pc, tcg_target_long target)
 {
     tcg_target_long disp;
 
-    disp = target - (tcg_target_long) pc;
-    if (disp != (int16_t) disp)
-        tcg_abort ();
+    disp = target - (tcg_target_long)pc;
+    if (disp != (int16_t) disp) {
+        tcg_abort();
+    }
 
     return disp & 0xfffc;
 }
 
-static void reloc_pc14 (void *pc, tcg_target_long target)
+static void reloc_pc14(void *pc, tcg_target_long target)
+{
+    *(uint32_t *)pc = (*(uint32_t *)pc & ~0xfffc) | reloc_pc14_val(pc, target);
+}
+
+static inline void tcg_out_b_noaddr(TCGContext *s, int insn)
+{
+    unsigned retrans = *(uint32_t *)s->code_ptr & 0x3fffffc;
+    tcg_out32(s, insn | retrans);
+}
+
+static inline void tcg_out_bc_noaddr(TCGContext *s, int insn)
 {
-    *(uint32_t *) pc = (*(uint32_t *) pc & ~0xfffc)
-        | reloc_pc14_val (pc, target);
+    unsigned retrans = *(uint32_t *)s->code_ptr & 0xfffc;
+    tcg_out32(s, insn | retrans);
 }
 
-static void patch_reloc (uint8_t *code_ptr, int type,
-                         intptr_t value, intptr_t addend)
+static void patch_reloc(uint8_t *code_ptr, int type,
+                        intptr_t value, intptr_t addend)
 {
     value += addend;
     switch (type) {
     case R_PPC_REL14:
-        reloc_pc14 (code_ptr, value);
+        reloc_pc14(code_ptr, value);
         break;
     case R_PPC_REL24:
-        reloc_pc24 (code_ptr, value);
+        reloc_pc24(code_ptr, value);
         break;
     default:
-        tcg_abort ();
+        tcg_abort();
     }
 }
 
 /* parse target specific constraints */
-static int target_parse_constraint (TCGArgConstraint *ct, const char **pct_str)
+static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
 {
     const char *ct_str;
 
@@ -232,29 +241,29 @@ static int target_parse_constraint (TCGArgConstraint *ct, const char **pct_str)
     switch (ct_str[0]) {
     case 'A': case 'B': case 'C': case 'D':
         ct->ct |= TCG_CT_REG;
-        tcg_regset_set_reg (ct->u.regs, 3 + ct_str[0] - 'A');
+        tcg_regset_set_reg(ct->u.regs, 3 + ct_str[0] - 'A');
         break;
     case 'r':
         ct->ct |= TCG_CT_REG;
-        tcg_regset_set32 (ct->u.regs, 0, 0xffffffff);
+        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
         break;
     case 'L':                   /* qemu_ld constraint */
         ct->ct |= TCG_CT_REG;
-        tcg_regset_set32 (ct->u.regs, 0, 0xffffffff);
-        tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3);
+        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
 #ifdef CONFIG_SOFTMMU
-        tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4);
-        tcg_regset_reset_reg (ct->u.regs, TCG_REG_R5);
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
 #endif
         break;
     case 'S':                   /* qemu_st constraint */
         ct->ct |= TCG_CT_REG;
-        tcg_regset_set32 (ct->u.regs, 0, 0xffffffff);
-        tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3);
+        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
 #ifdef CONFIG_SOFTMMU
-        tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4);
-        tcg_regset_reset_reg (ct->u.regs, TCG_REG_R5);
-        tcg_regset_reset_reg (ct->u.regs, TCG_REG_R6);
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
 #endif
         break;
     case 'I':
@@ -284,8 +293,8 @@ static int target_parse_constraint (TCGArgConstraint *ct, const char **pct_str)
 }
 
 /* test if a constant matches the constraint */
-static int tcg_target_const_match (tcg_target_long val,
-                                   const TCGArgConstraint *arg_ct)
+static int tcg_target_const_match(tcg_target_long val,
+                                  const TCGArgConstraint *arg_ct)
 {
     int ct = arg_ct->ct;
     if (ct & TCG_CT_CONST) {
@@ -425,7 +434,7 @@ static int tcg_target_const_match (tcg_target_long val,
 #define STHX   XO31(407)
 #define STWX   XO31(151)
 
-#define SPR(a,b) ((((a)<<5)|(b))<<11)
+#define SPR(a, b) ((((a)<<5)|(b))<<11)
 #define LR     SPR(8, 0)
 #define CTR    SPR(9, 0)
 
@@ -439,7 +448,7 @@ static int tcg_target_const_match (tcg_target_long val,
 #define SRADI  XO31(413<<1)
 
 #define TW     XO31( 4)
-#define TRAP   (TW | TO (31))
+#define TRAP   (TW | TO(31))
 
 #define RT(r) ((r)<<21)
 #define RS(r) ((r)<<21)
@@ -467,9 +476,9 @@ static int tcg_target_const_match (tcg_target_long val,
 #define BB(n, c) (((c)+((n)*4))<<11)
 #define BC_(n, c) (((c)+((n)*4))<<6)
 
-#define BO_COND_TRUE  BO (12)
-#define BO_COND_FALSE BO ( 4)
-#define BO_ALWAYS     BO (20)
+#define BO_COND_TRUE  BO(12)
+#define BO_COND_FALSE BO( 4)
+#define BO_ALWAYS     BO(20)
 
 enum {
     CR_LT,
@@ -479,16 +488,16 @@ enum {
 };
 
 static const uint32_t tcg_to_bc[] = {
-    [TCG_COND_EQ]  = BC | BI (7, CR_EQ) | BO_COND_TRUE,
-    [TCG_COND_NE]  = BC | BI (7, CR_EQ) | BO_COND_FALSE,
-    [TCG_COND_LT]  = BC | BI (7, CR_LT) | BO_COND_TRUE,
-    [TCG_COND_GE]  = BC | BI (7, CR_LT) | BO_COND_FALSE,
-    [TCG_COND_LE]  = BC | BI (7, CR_GT) | BO_COND_FALSE,
-    [TCG_COND_GT]  = BC | BI (7, CR_GT) | BO_COND_TRUE,
-    [TCG_COND_LTU] = BC | BI (7, CR_LT) | BO_COND_TRUE,
-    [TCG_COND_GEU] = BC | BI (7, CR_LT) | BO_COND_FALSE,
-    [TCG_COND_LEU] = BC | BI (7, CR_GT) | BO_COND_FALSE,
-    [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
+    [TCG_COND_EQ]  = BC | BI(7, CR_EQ) | BO_COND_TRUE,
+    [TCG_COND_NE]  = BC | BI(7, CR_EQ) | BO_COND_FALSE,
+    [TCG_COND_LT]  = BC | BI(7, CR_LT) | BO_COND_TRUE,
+    [TCG_COND_GE]  = BC | BI(7, CR_LT) | BO_COND_FALSE,
+    [TCG_COND_LE]  = BC | BI(7, CR_GT) | BO_COND_FALSE,
+    [TCG_COND_GT]  = BC | BI(7, CR_GT) | BO_COND_TRUE,
+    [TCG_COND_LTU] = BC | BI(7, CR_LT) | BO_COND_TRUE,
+    [TCG_COND_GEU] = BC | BI(7, CR_LT) | BO_COND_FALSE,
+    [TCG_COND_LEU] = BC | BI(7, CR_GT) | BO_COND_FALSE,
+    [TCG_COND_GTU] = BC | BI(7, CR_GT) | BO_COND_TRUE,
 };
 
 /* The low bit here is set if the RA and RB fields must be inverted.  */
@@ -508,15 +517,17 @@ static const uint32_t tcg_to_isel[] = {
 static inline void tcg_out_mov(TCGContext *s, TCGType type,
                                TCGReg ret, TCGReg arg)
 {
-    tcg_out32 (s, OR | SAB (arg, ret, arg));
+    if (ret != arg) {
+        tcg_out32(s, OR | SAB(arg, ret, arg));
+    }
 }
 
 static inline void tcg_out_rld(TCGContext *s, int op, TCGReg ra, TCGReg rs,
                                int sh, int mb)
 {
-    sh = SH (sh & 0x1f) | (((sh >> 5) & 1) << 1);
-    mb = MB64 ((mb >> 5) | ((mb << 1) & 0x3f));
-    tcg_out32 (s, op | RA (ra) | RS (rs) | sh | mb);
+    sh = SH(sh & 0x1f) | (((sh >> 5) & 1) << 1);
+    mb = MB64((mb >> 5) | ((mb << 1) & 0x3f));
+    tcg_out32(s, op | RA(ra) | RS(rs) | sh | mb);
 }
 
 static inline void tcg_out_rlw(TCGContext *s, int op, TCGReg ra, TCGReg rs,
@@ -636,8 +647,8 @@ static void tcg_out_andi32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
     } else if (mask_operand(c, &mb, &me)) {
         tcg_out_rlw(s, RLWINM, dst, src, 0, mb, me);
     } else {
-        tcg_out_movi(s, TCG_TYPE_I32, 0, c);
-        tcg_out32(s, AND | SAB(src, dst, 0));
+        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R0, c);
+        tcg_out32(s, AND | SAB(src, dst, TCG_REG_R0));
     }
 }
 
@@ -658,8 +669,8 @@ static void tcg_out_andi64(TCGContext *s, TCGReg dst, TCGReg src, uint64_t c)
             tcg_out_rld(s, RLDICL, dst, src, 0, mb);
         }
     } else {
-        tcg_out_movi(s, TCG_TYPE_I64, 0, c);
-        tcg_out32(s, AND | SAB(src, dst, 0));
+        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, c);
+        tcg_out32(s, AND | SAB(src, dst, TCG_REG_R0));
     }
 }
 
@@ -686,123 +697,115 @@ static void tcg_out_xori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
     tcg_out_zori32(s, dst, src, c, XORI, XORIS);
 }
 
-static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target)
+static void tcg_out_b(TCGContext *s, int mask, tcg_target_long target)
 {
     tcg_target_long disp;
 
-    disp = target - (tcg_target_long) s->code_ptr;
-    if ((disp << 38) >> 38 == disp)
-        tcg_out32 (s, B | (disp & 0x3fffffc) | mask);
-    else {
-        tcg_out_movi (s, TCG_TYPE_I64, 0, (tcg_target_long) target);
-        tcg_out32 (s, MTSPR | RS (0) | CTR);
-        tcg_out32 (s, BCCTR | BO_ALWAYS | mask);
+    disp = target - (tcg_target_long)s->code_ptr;
+    if (in_range_b(disp)) {
+        tcg_out32(s, B | (disp & 0x3fffffc) | mask);
+    else {
+        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, (tcg_target_long)target);
+        tcg_out32(s, MTSPR | RS(TCG_REG_R0) | CTR);
+        tcg_out32(s, BCCTR | BO_ALWAYS | mask);
     }
 }
 
-static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg)
+static void tcg_out_call(TCGContext *s, tcg_target_long arg, int const_arg)
 {
 #ifdef __APPLE__
     if (const_arg) {
-        tcg_out_b (s, LK, arg);
-    }
-    else {
-        tcg_out32 (s, MTSPR | RS (arg) | LR);
-        tcg_out32 (s, BCLR | BO_ALWAYS | LK);
+        tcg_out_b(s, LK, arg);
+    } else {
+        tcg_out32(s, MTSPR | RS(arg) | LR);
+        tcg_out32(s, BCLR | BO_ALWAYS | LK);
     }
 #else
-    int reg;
+    TCGReg reg = arg;
+    int ofs = 0;
 
     if (const_arg) {
-        reg = 2;
-        tcg_out_movi (s, TCG_TYPE_I64, reg, arg);
+        /* Look through the descriptor.  If the branch is in range, and we
+           don't have to spend too much effort on building the toc.  */
+        intptr_t tgt = ((intptr_t *)arg)[0];
+        intptr_t toc = ((intptr_t *)arg)[1];
+        intptr_t diff = tgt - (intptr_t)s->code_ptr;
+
+        if (in_range_b(diff) && toc == (uint32_t)toc) {
+            tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R2, toc);
+            tcg_out_b(s, LK, tgt);
+            return;
+        }
+
+        /* Fold the low bits of the constant into the addresses below.  */
+        ofs = (int16_t)arg;
+        if (ofs + 8 < 0x8000) {
+            arg -= ofs;
+        } else {
+            ofs = 0;
+        }
+        reg = TCG_REG_R2;
+        tcg_out_movi(s, TCG_TYPE_I64, reg, arg);
     }
-    else reg = arg;
 
-    tcg_out32 (s, LD | RT (0) | RA (reg));
-    tcg_out32 (s, MTSPR | RA (0) | CTR);
-    tcg_out32 (s, LD | RT (11) | RA (reg) | 16);
-    tcg_out32 (s, LD | RT (2) | RA (reg) | 8);
-    tcg_out32 (s, BCCTR | BO_ALWAYS | LK);
+    tcg_out32(s, LD | TAI(TCG_REG_R0, reg, ofs));
+    tcg_out32(s, MTSPR | RA(TCG_REG_R0) | CTR);
+    tcg_out32(s, LD | TAI(TCG_REG_R2, reg, ofs + 8));
+    tcg_out32(s, BCCTR | BO_ALWAYS | LK);
 #endif
 }
 
-static void tcg_out_ldst(TCGContext *s, TCGReg ret, TCGReg addr,
-                         int offset, int op1, int op2)
+static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
+                             TCGReg base, tcg_target_long offset)
 {
-    if (offset == (int16_t) offset) {
-        tcg_out32(s, op1 | TAI(ret, addr, offset));
-    } else {
-        tcg_out_movi(s, TCG_TYPE_I64, 0, offset);
-        tcg_out32(s, op2 | TAB(ret, addr, 0));
-    }
-}
+    tcg_target_long orig = offset, l0, l1, extra = 0, align = 0;
+    TCGReg rs = TCG_REG_R2;
 
-static void tcg_out_ldsta(TCGContext *s, TCGReg ret, TCGReg addr,
-                          int offset, int op1, int op2)
-{
-    if (offset == (int16_t) (offset & ~3)) {
-        tcg_out32(s, op1 | TAI(ret, addr, offset));
-    } else {
-        tcg_out_movi(s, TCG_TYPE_I64, 0, offset);
-        tcg_out32(s, op2 | TAB(ret, addr, 0));
-    }
-}
-
-#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,
-};
+    assert(rt != TCG_REG_R2 && base != TCG_REG_R2);
 
-/* 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,
-};
+    switch (opi) {
+    case LD: case LWA:
+        align = 3;
+        /* FALLTHRU */
+    default:
+        if (rt != TCG_REG_R0) {
+            rs = rt;
+        }
+        break;
+    case STD:
+        align = 3;
+        break;
+    case STB: case STH: case STW:
+        break;
+    }
 
-static void tcg_out_tlb_read(TCGContext *s, TCGReg r0, TCGReg r1, TCGReg r2,
-                             TCGReg addr_reg, int s_bits, int offset)
-{
-#if TARGET_LONG_BITS == 32
-    tcg_out_ext32u(s, addr_reg, addr_reg);
-
-    tcg_out_rlw(s, RLWINM, r0, addr_reg,
-                32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
-                32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS),
-                31 - CPU_TLB_ENTRY_BITS);
-    tcg_out32(s, ADD | TAB(r0, r0, TCG_AREG0));
-    tcg_out32(s, LWZU | TAI(r1, r0, offset));
-    tcg_out_rlw(s, RLWINM, r2, addr_reg, 0,
-                (32 - s_bits) & 31, 31 - TARGET_PAGE_BITS);
-#else
-    tcg_out_rld (s, RLDICL, r0, addr_reg,
-                 64 - TARGET_PAGE_BITS,
-                 64 - CPU_TLB_BITS);
-    tcg_out_shli64(s, r0, r0, CPU_TLB_ENTRY_BITS);
+    /* For unaligned, or very large offsets, use the indexed form.  */
+    if (offset & align || offset != (int32_t)offset) {
+        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R2, orig);
+        tcg_out32(s, opx | TAB(rt, base, TCG_REG_R2));
+        return;
+    }
 
-    tcg_out32(s, ADD | TAB(r0, r0, TCG_AREG0));
-    tcg_out32(s, LD_ADDR | TAI(r1, r0, offset));
+    l0 = (int16_t)offset;
+    offset = (offset - l0) >> 16;
+    l1 = (int16_t)offset;
 
-    if (!s_bits) {
-        tcg_out_rld (s, RLDICR, r2, addr_reg, 0, 63 - TARGET_PAGE_BITS);
+    if (l1 < 0 && orig >= 0) {
+        extra = 0x4000;
+        l1 = (int16_t)(offset - 0x4000);
     }
-    else {
-        tcg_out_rld (s, RLDICL, r2, addr_reg,
-                     64 - TARGET_PAGE_BITS,
-                     TARGET_PAGE_BITS - s_bits);
-        tcg_out_rld (s, RLDICL, r2, r2, TARGET_PAGE_BITS, 0);
+    if (l1) {
+        tcg_out32(s, ADDIS | TAI(rs, base, l1));
+        base = rs;
+    }
+    if (extra) {
+        tcg_out32(s, ADDIS | TAI(rs, base, extra));
+        base = rs;
+    }
+    if (opi != ADDI || base != rt || l0 != 0) {
+        tcg_out32(s, opi | TAI(rt, base, l0));
     }
-#endif
 }
-#endif
 
 static const uint32_t qemu_ldx_opc[8] = {
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -826,105 +829,251 @@ static const uint32_t qemu_exts_opc[4] = {
     EXTSB, EXTSH, EXTSW, 0
 };
 
-static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
+#if defined (CONFIG_SOFTMMU)
+/* 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,
+};
+
+/* 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,
+};
+
+/* Perform the TLB load and compare.  Places the result of the comparison
+   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,
+                               int mem_index, bool is_read)
 {
-    TCGReg addr_reg, data_reg, r0, r1, rbase;
-    uint32_t insn, s_bits;
-#ifdef CONFIG_SOFTMMU
-    TCGReg r2, ir;
-    int mem_index;
-    void *label1_ptr, *label2_ptr;
-#endif
+    int cmp_off
+        = (is_read
+           ? 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);
+    TCGReg base = TCG_AREG0;
+
+    /* Extract the page index, shifted into place for tlb index.  */
+    if (TARGET_LONG_BITS == 32) {
+        /* Zero-extend the address into a place helpful for further use.  */
+        tcg_out_ext32u(s, TCG_REG_R4, addr_reg);
+        addr_reg = TCG_REG_R4;
+    } else {
+        tcg_out_rld(s, RLDICL, TCG_REG_R3, addr_reg,
+                    64 - TARGET_PAGE_BITS, 64 - CPU_TLB_BITS);
+    }
 
-    data_reg = *args++;
-    addr_reg = *args++;
-    s_bits = opc & 3;
+    /* Compensate for very large offsets.  */
+    if (add_off >= 0x8000) {
+        /* Most target env are smaller than 32k; none are larger than 64k.
+           Simplify the logic here merely to offset by 0x7ff0, giving us a
+           range just shy of 64k.  Check this assumption.  */
+        QEMU_BUILD_BUG_ON(offsetof(CPUArchState,
+                                   tlb_table[NB_MMU_MODES - 1][1])
+                          > 0x7ff0 + 0x7fff);
+        tcg_out32(s, ADDI | TAI(TCG_REG_R2, base, 0x7ff0));
+        base = TCG_REG_R2;
+        cmp_off -= 0x7ff0;
+        add_off -= 0x7ff0;
+    }
 
-#ifdef CONFIG_SOFTMMU
-    mem_index = *args;
+    /* Extraction and shifting, part 2.  */
+    if (TARGET_LONG_BITS == 32) {
+        tcg_out_rlw(s, RLWINM, TCG_REG_R3, addr_reg,
+                    32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
+                    32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS),
+                    31 - CPU_TLB_ENTRY_BITS);
+    } else {
+        tcg_out_shli64(s, TCG_REG_R3, TCG_REG_R3, CPU_TLB_ENTRY_BITS);
+    }
 
-    r0 = 3;
-    r1 = 4;
-    r2 = 0;
-    rbase = 0;
+    tcg_out32(s, ADD | TAB(TCG_REG_R3, TCG_REG_R3, base));
 
-    tcg_out_tlb_read (s, r0, r1, r2, addr_reg, s_bits,
-                      offsetof (CPUArchState, tlb_table[mem_index][0].addr_read));
+    /* Load the tlb comparator.  */
+    tcg_out32(s, LD_ADDR | TAI(TCG_REG_R2, TCG_REG_R3, cmp_off));
 
-    tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L);
+    /* Load the TLB addend for use on the fast path.  Do this asap
+       to minimize any load use delay.  */
+    tcg_out32(s, LD | TAI(TCG_REG_R3, TCG_REG_R3, add_off));
 
-    label1_ptr = s->code_ptr;
-#ifdef FAST_PATH
-    tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
-#endif
+    /* Clear the non-page, non-alignment bits from the address.  */
+    if (TARGET_LONG_BITS == 32) {
+        tcg_out_rlw(s, RLWINM, TCG_REG_R0, addr_reg, 0,
+                    (32 - s_bits) & 31, 31 - TARGET_PAGE_BITS);
+    } else if (!s_bits) {
+        tcg_out_rld(s, RLDICR, TCG_REG_R0, addr_reg, 0, 63 - TARGET_PAGE_BITS);
+    } else {
+        tcg_out_rld(s, RLDICL, TCG_REG_R0, addr_reg,
+                    64 - TARGET_PAGE_BITS, TARGET_PAGE_BITS - s_bits);
+        tcg_out_rld(s, RLDICL, TCG_REG_R0, TCG_REG_R0, TARGET_PAGE_BITS, 0);
+    }
+
+    tcg_out32(s, CMP | BF(7) | RA(TCG_REG_R0) | RB(TCG_REG_R2) | CMP_L);
+
+    return 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,
+                                int data_reg, int addr_reg, int mem_index,
+                                uint8_t *raddr, uint8_t *label_ptr)
+{
+    int idx;
+    TCGLabelQemuLdst *label;
 
-    /* slow path */
-    ir = 3;
-    tcg_out_mov (s, TCG_TYPE_I64, ir++, TCG_AREG0);
-    tcg_out_mov (s, TCG_TYPE_I64, ir++, addr_reg);
-    tcg_out_movi (s, TCG_TYPE_I64, ir++, mem_index);
+    if (s->nb_qemu_ldst_labels >= TCG_MAX_QEMU_LDST) {
+        tcg_abort();
+    }
+
+    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;
+    label->addrlo_reg = addr_reg;
+    label->mem_index = mem_index;
+    label->raddr = raddr;
+    label->label_ptr[0] = label_ptr;
+}
+
+static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
+{
+    int opc = lb->opc;
+    int s_bits = opc & 3;
+
+    reloc_pc14(lb->label_ptr[0], (uintptr_t)s->code_ptr);
+
+    tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_AREG0);
 
-    tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
+    /* If the address needed to be zero-extended, we'll have already
+       placed it in R4.  The only remaining case is 64-bit guest.  */
+    tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R4, lb->addrlo_reg);
+
+    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);
 
     if (opc & 4) {
-        insn = qemu_exts_opc[s_bits];
-        tcg_out32(s, insn | RA(data_reg) | RS(3));
-    } else if (data_reg != 3) {
-        tcg_out_mov(s, TCG_TYPE_I64, data_reg, 3);
+        uint32_t insn = qemu_exts_opc[s_bits];
+        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);
     }
-    label2_ptr = s->code_ptr;
-    tcg_out32 (s, B);
 
-    /* label1: fast path */
-#ifdef FAST_PATH
-    reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
+    tcg_out_b(s, 0, (uintptr_t)lb->raddr);
+}
+
+static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
+{
+    int opc = lb->opc;
+
+    reloc_pc14(lb->label_ptr[0], (uintptr_t)s->code_ptr);
+
+    tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R3, TCG_AREG0);
+
+    /* If the address needed to be zero-extended, we'll have already
+       placed it in R4.  The only remaining case is 64-bit guest.  */
+    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)));
+    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_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)
+{
+    TCGReg addr_reg, data_reg, rbase;
+    uint32_t insn, s_bits;
+#ifdef CONFIG_SOFTMMU
+    int mem_index;
+    void *label_ptr;
 #endif
 
-    /* r0 now contains &env->tlb_table[mem_index][index].addr_read */
-    tcg_out32(s, LD | TAI(r0, r0,
-                          offsetof(CPUTLBEntry, addend)
-                          - offsetof(CPUTLBEntry, addr_read)));
-    /* r0 = env->tlb_table[mem_index][index].addend */
-    tcg_out32(s, ADD | TAB(r0, r0, addr_reg));
-    /* r0 = env->tlb_table[mem_index][index].addend + addr */
+    data_reg = *args++;
+    addr_reg = *args++;
+    s_bits = opc & 3;
+
+#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. */
+    label_ptr = s->code_ptr;
+    tcg_out_bc_noaddr(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
+
+    rbase = TCG_REG_R3;
 #else  /* !CONFIG_SOFTMMU */
-#if TARGET_LONG_BITS == 32
-    tcg_out_ext32u(s, addr_reg, addr_reg);
-#endif
-    r0 = addr_reg;
-    r1 = 3;
     rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
+    if (TARGET_LONG_BITS == 32) {
+        tcg_out_ext32u(s, TCG_REG_R2, addr_reg);
+        addr_reg = TCG_REG_R2;
+    }
 #endif
 
     insn = qemu_ldx_opc[opc];
     if (!HAVE_ISA_2_06 && insn == LDBRX) {
-        tcg_out32(s, ADDI | TAI(r1, r0, 4));
-        tcg_out32(s, LWBRX | TAB(data_reg, rbase, r0));
-        tcg_out32(s, LWBRX | TAB(      r1, rbase, r1));
-        tcg_out_rld(s, RLDIMI, data_reg, r1, 32, 0);
+        tcg_out32(s, ADDI | TAI(TCG_REG_R0, addr_reg, 4));
+        tcg_out32(s, LWBRX | TAB(data_reg, rbase, addr_reg));
+        tcg_out32(s, LWBRX | TAB(TCG_REG_R0, rbase, TCG_REG_R0));
+        tcg_out_rld(s, RLDIMI, data_reg, TCG_REG_R0, 32, 0);
     } else if (insn) {
-        tcg_out32(s, insn | TAB(data_reg, rbase, r0));
+        tcg_out32(s, insn | TAB(data_reg, rbase, addr_reg));
     } else {
         insn = qemu_ldx_opc[s_bits];
-        tcg_out32(s, insn | TAB(data_reg, rbase, r0));
+        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));
+        tcg_out32(s, insn | RA(data_reg) | RS(data_reg));
     }
 
 #ifdef CONFIG_SOFTMMU
-    reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
+    add_qemu_ldst_label(s, true, opc, data_reg, addr_reg, mem_index,
+                        s->code_ptr, label_ptr);
 #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, int opc)
 {
-    TCGReg addr_reg, r0, r1, rbase, data_reg;
+    TCGReg addr_reg, rbase, data_reg;
     uint32_t insn;
 #ifdef CONFIG_SOFTMMU
-    TCGReg r2, ir;
     int mem_index;
-    void *label1_ptr, *label2_ptr;
+    void *label_ptr;
 #endif
 
     data_reg = *args++;
@@ -933,158 +1082,122 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
 #ifdef CONFIG_SOFTMMU
     mem_index = *args;
 
-    r0 = 3;
-    r1 = 4;
-    r2 = 0;
-    rbase = 0;
-
-    tcg_out_tlb_read (s, r0, r1, r2, addr_reg, opc,
-                      offsetof (CPUArchState, tlb_table[mem_index][0].addr_write));
-
-    tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L);
-
-    label1_ptr = s->code_ptr;
-#ifdef FAST_PATH
-    tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
-#endif
-
-    /* slow path */
-    ir = 3;
-    tcg_out_mov (s, TCG_TYPE_I64, ir++, TCG_AREG0);
-    tcg_out_mov (s, TCG_TYPE_I64, ir++, addr_reg);
-    tcg_out_rld (s, RLDICL, ir++, data_reg, 0, 64 - (1 << (3 + opc)));
-    tcg_out_movi (s, TCG_TYPE_I64, ir++, mem_index);
+    addr_reg = tcg_out_tlb_read(s, opc, addr_reg, mem_index, false);
 
-    tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1);
-
-    label2_ptr = s->code_ptr;
-    tcg_out32 (s, B);
-
-    /* label1: fast path */
-#ifdef FAST_PATH
-    reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
-#endif
-
-    tcg_out32 (s, (LD
-                   | RT (r0)
-                   | RA (r0)
-                   | (offsetof (CPUTLBEntry, addend)
-                      - offsetof (CPUTLBEntry, addr_write))
-                   ));
-    /* r0 = env->tlb_table[mem_index][index].addend */
-    tcg_out32(s, ADD | TAB(r0, r0, addr_reg));
-    /* r0 = env->tlb_table[mem_index][index].addend + addr */
+    /* Load a pointer into the current opcode w/conditional branch-link. */
+    label_ptr = s->code_ptr;
+    tcg_out_bc_noaddr(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
 
+    rbase = TCG_REG_R3;
 #else  /* !CONFIG_SOFTMMU */
-#if TARGET_LONG_BITS == 32
-    tcg_out_ext32u(s, addr_reg, addr_reg);
-#endif
-    r1 = 3;
-    r0 = addr_reg;
     rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
+    if (TARGET_LONG_BITS == 32) {
+        tcg_out_ext32u(s, TCG_REG_R2, addr_reg);
+        addr_reg = TCG_REG_R2;
+    }
 #endif
 
     insn = qemu_stx_opc[opc];
     if (!HAVE_ISA_2_06 && insn == STDBRX) {
-        tcg_out32(s, STWBRX | SAB(data_reg, rbase, r0));
-        tcg_out32(s, ADDI | TAI(r1, r0, 4));
-        tcg_out_shri64(s, 0, data_reg, 32);
-        tcg_out32(s, STWBRX | SAB(0, rbase, r1));
+        tcg_out32(s, STWBRX | SAB(data_reg, rbase, addr_reg));
+        tcg_out32(s, ADDI | TAI(TCG_REG_R2, addr_reg, 4));
+        tcg_out_shri64(s, TCG_REG_R0, data_reg, 32);
+        tcg_out32(s, STWBRX | SAB(TCG_REG_R0, rbase, TCG_REG_R2));
     } else {
-        tcg_out32(s, insn | SAB(data_reg, rbase, r0));
+        tcg_out32(s, insn | SAB(data_reg, rbase, addr_reg));
     }
 
 #ifdef CONFIG_SOFTMMU
-    reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
+    add_qemu_ldst_label(s, false, opc, data_reg, addr_reg, mem_index,
+                        s->code_ptr, label_ptr);
 #endif
 }
 
-static void tcg_target_qemu_prologue (TCGContext *s)
+#define FRAME_SIZE ((int) \
+    ((8                     /* back chain */              \
+      + 8                   /* CR */                      \
+      + 8                   /* LR */                      \
+      + 8                   /* compiler doubleword */     \
+      + 8                   /* link editor doubleword */  \
+      + 8                   /* TOC save area */           \
+      + TCG_STATIC_CALL_ARGS_SIZE                         \
+      + CPU_TEMP_BUF_NLONGS * sizeof(long)                \
+      + ARRAY_SIZE(tcg_target_callee_save_regs) * 8       \
+      + 15) & ~15))
+
+#define REG_SAVE_BOT (FRAME_SIZE - ARRAY_SIZE(tcg_target_callee_save_regs) * 8)
+
+static void tcg_target_qemu_prologue(TCGContext *s)
 {
-    int i, frame_size;
-#ifndef __APPLE__
-    uint64_t addr;
-#endif
+    int i;
 
-    frame_size = 0
-        + 8                     /* back chain */
-        + 8                     /* CR */
-        + 8                     /* LR */
-        + 8                     /* compiler doubleword */
-        + 8                     /* link editor doubleword */
-        + 8                     /* TOC save area */
-        + TCG_STATIC_CALL_ARGS_SIZE
-        + ARRAY_SIZE (tcg_target_callee_save_regs) * 8
-        + CPU_TEMP_BUF_NLONGS * sizeof(long)
-        ;
-    frame_size = (frame_size + 15) & ~15;
-
-    tcg_set_frame (s, TCG_REG_CALL_STACK, frame_size
-                   - CPU_TEMP_BUF_NLONGS * sizeof (long),
-                   CPU_TEMP_BUF_NLONGS * sizeof (long));
+    tcg_set_frame(s, TCG_REG_CALL_STACK,
+                  REG_SAVE_BOT - CPU_TEMP_BUF_NLONGS * sizeof(long),
+                  CPU_TEMP_BUF_NLONGS * sizeof(long));
 
 #ifndef __APPLE__
     /* First emit adhoc function descriptor */
-    addr = (uint64_t) s->code_ptr + 24;
-    tcg_out32 (s, addr >> 32); tcg_out32 (s, addr); /* entry point */
+    tcg_out64(s, (uint64_t)s->code_ptr + 24); /* entry point */
     s->code_ptr += 16;          /* skip TOC and environment pointer */
 #endif
 
     /* Prologue */
-    tcg_out32 (s, MFSPR | RT (0) | LR);
-    tcg_out32 (s, STDU | RS (1) | RA (1) | (-frame_size & 0xffff));
-    for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
-        tcg_out32 (s, (STD
-                       | RS (tcg_target_callee_save_regs[i])
-                       | RA (1)
-                       | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE)
-                       )
-            );
-    tcg_out32 (s, STD | RS (0) | RA (1) | (frame_size + 16));
+    tcg_out32(s, MFSPR | RT(TCG_REG_R0) | LR);
+    tcg_out32(s, STDU | SAI(TCG_REG_R1, TCG_REG_R1, -FRAME_SIZE));
+    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
+        tcg_out32(s, STD | SAI(tcg_target_callee_save_regs[i], 1, 
+                               REG_SAVE_BOT + i * 8));
+    }
+    tcg_out32(s, STD | SAI(TCG_REG_R0, TCG_REG_R1, FRAME_SIZE + 16));
 
 #ifdef CONFIG_USE_GUEST_BASE
     if (GUEST_BASE) {
-        tcg_out_movi (s, TCG_TYPE_I64, TCG_GUEST_BASE_REG, GUEST_BASE);
-        tcg_regset_set_reg (s->reserved_regs, TCG_GUEST_BASE_REG);
+        tcg_out_movi(s, TCG_TYPE_I64, 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]);
-    tcg_out32 (s, MTSPR | RS (tcg_target_call_iarg_regs[1]) | CTR);
-    tcg_out32 (s, BCCTR | BO_ALWAYS);
+    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
+    tcg_out32(s, MTSPR | RS(tcg_target_call_iarg_regs[1]) | CTR);
+    tcg_out32(s, BCCTR | BO_ALWAYS);
 
     /* Epilogue */
     tb_ret_addr = s->code_ptr;
 
-    for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
-        tcg_out32 (s, (LD
-                       | RT (tcg_target_callee_save_regs[i])
-                       | RA (1)
-                       | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE)
-                       )
-            );
-    tcg_out32(s, LD | TAI(0, 1, frame_size + 16));
-    tcg_out32(s, MTSPR | RS(0) | LR);
-    tcg_out32(s, ADDI | TAI(1, 1, frame_size));
+    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
+        tcg_out32(s, LD | TAI(tcg_target_callee_save_regs[i], TCG_REG_R1,
+                              REG_SAVE_BOT + i * 8));
+    }
+    tcg_out32(s, LD | TAI(TCG_REG_R0, TCG_REG_R1, FRAME_SIZE + 16));
+    tcg_out32(s, MTSPR | RS(TCG_REG_R0) | LR);
+    tcg_out32(s, ADDI | TAI(TCG_REG_R1, TCG_REG_R1, FRAME_SIZE));
     tcg_out32(s, BCLR | BO_ALWAYS);
 }
 
-static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
-                       intptr_t arg2)
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
+                              TCGReg arg1, intptr_t arg2)
 {
-    if (type == TCG_TYPE_I32)
-        tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
-    else
-        tcg_out_ldsta (s, ret, arg1, arg2, LD, LDX);
+    int opi, opx;
+
+    if (type == TCG_TYPE_I32) {
+        opi = LWZ, opx = LWZX;
+    } else {
+        opi = LD, opx = LDX;
+    }
+    tcg_out_mem_long(s, opi, opx, ret, arg1, arg2);
 }
 
-static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
-                       intptr_t arg2)
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
+                              TCGReg arg1, intptr_t arg2)
 {
-    if (type == TCG_TYPE_I32)
-        tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
-    else
-        tcg_out_ldsta (s, arg, arg1, arg2, STD, STDX);
+    int opi, opx;
+
+    if (type == TCG_TYPE_I32) {
+        opi = STW, opx = STWX;
+    } else {
+        opi = STD, opx = STDX;
+    }
+    tcg_out_mem_long(s, opi, opx, arg, arg1, arg2);
 }
 
 static void tcg_out_cmp(TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
@@ -1106,8 +1219,7 @@ static void tcg_out_cmp(TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
                 op = CMPI;
                 imm = 1;
                 break;
-            }
-            else if ((uint16_t) arg2 == arg2) {
+            } else if ((uint16_t) arg2 == arg2) {
                 op = CMPLI;
                 imm = 1;
                 break;
@@ -1148,7 +1260,7 @@ static void tcg_out_cmp(TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
         break;
 
     default:
-        tcg_abort ();
+        tcg_abort();
     }
     op |= BF(cr) | ((type == TCG_TYPE_I64) << 21);
 
@@ -1156,8 +1268,8 @@ static void tcg_out_cmp(TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
         tcg_out32(s, op | RA(arg1) | (arg2 & 0xffff));
     } else {
         if (const_arg2) {
-            tcg_out_movi(s, type, 0, arg2);
-            arg2 = 0;
+            tcg_out_movi(s, type, TCG_REG_R0, arg2);
+            arg2 = TCG_REG_R0;
         }
         tcg_out32(s, op | RA(arg1) | RB(arg2));
     }
@@ -1178,8 +1290,8 @@ static void tcg_out_setcond_ne0(TCGContext *s, TCGReg dst, TCGReg src)
         tcg_out32(s, ADDIC | TAI(dst, src, -1));
         tcg_out32(s, SUBFE | TAB(dst, dst, src));
     } else {
-        tcg_out32(s, ADDIC | TAI(0, src, -1));
-        tcg_out32(s, SUBFE | TAB(dst, 0, src));
+        tcg_out32(s, ADDIC | TAI(TCG_REG_R0, src, -1));
+        tcg_out32(s, SUBFE | TAB(dst, TCG_REG_R0, src));
     }
 }
 
@@ -1292,13 +1404,13 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
     case TCG_COND_GE:
     case TCG_COND_GEU:
         sh = 31;
-        crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_LT) | BB (7, CR_LT);
+        crop = CRNOR | BT(7, CR_EQ) | BA(7, CR_LT) | BB(7, CR_LT);
         goto crtest;
 
     case TCG_COND_LE:
     case TCG_COND_LEU:
         sh = 31;
-        crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_GT) | BB (7, CR_GT);
+        crop = CRNOR | BT(7, CR_EQ) | BA(7, CR_GT) | BB(7, CR_GT);
     crtest:
         tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
         if (crop) {
@@ -1309,22 +1421,19 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
         break;
 
     default:
-        tcg_abort ();
+        tcg_abort();
     }
 }
 
-static void tcg_out_bc (TCGContext *s, int bc, int label_index)
+static void tcg_out_bc(TCGContext *s, int bc, int label_index)
 {
     TCGLabel *l = &s->labels[label_index];
 
-    if (l->has_value)
-        tcg_out32 (s, bc | reloc_pc14_val (s->code_ptr, l->u.value));
-    else {
-        uint16_t val = *(uint16_t *) &s->code_ptr[2];
-
-        /* Thanks to Andrzej Zaborowski */
-        tcg_out32 (s, bc | (val & 0xfffc));
-        tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0);
+    if (l->has_value) {
+        tcg_out32(s, bc | reloc_pc14_val(s->code_ptr, l->u.value));
+    } else {
+        tcg_out_reloc(s, s->code_ptr, R_PPC_REL14, label_index, 0);
+        tcg_out_bc_noaddr(s, bc);
     }
 }
 
@@ -1360,7 +1469,7 @@ static void tcg_out_movcond(TCGContext *s, TCGType type, TCGCond cond,
         }
         /* V1 == 0 is handled by isel; V2 == 0 must be handled by hand.  */
         if (v2 == 0) {
-            tcg_out_movi(s, type, 0, 0);
+            tcg_out_movi(s, type, TCG_REG_R0, 0);
         }
         tcg_out32(s, isel | TAB(dest, v1, v2));
     } else {
@@ -1384,37 +1493,36 @@ static void tcg_out_movcond(TCGContext *s, TCGType type, TCGCond cond,
     }
 }
 
-void ppc_tb_set_jmp_target (unsigned long jmp_addr, unsigned long addr)
+void ppc_tb_set_jmp_target(unsigned long jmp_addr, unsigned long addr)
 {
     TCGContext s;
     unsigned long patch_size;
 
     s.code_ptr = (uint8_t *) jmp_addr;
-    tcg_out_b (&s, 0, addr);
+    tcg_out_b(&s, 0, addr);
     patch_size = s.code_ptr - (uint8_t *) jmp_addr;
-    flush_icache_range (jmp_addr, jmp_addr + patch_size);
+    flush_icache_range(jmp_addr, jmp_addr + patch_size);
 }
 
-static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
-                        const int *const_args)
+static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
+                       const int *const_args)
 {
     TCGArg a0, a1, a2;
     int c;
 
     switch (opc) {
     case INDEX_op_exit_tb:
-        tcg_out_movi (s, TCG_TYPE_I64, TCG_REG_R3, args[0]);
-        tcg_out_b (s, 0, (tcg_target_long) tb_ret_addr);
+        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R3, args[0]);
+        tcg_out_b(s, 0, (tcg_target_long)tb_ret_addr);
         break;
     case INDEX_op_goto_tb:
         if (s->tb_jmp_offset) {
-            /* direct jump method */
-
+            /* Direct jump method.  */
             s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
             s->code_ptr += 28;
-        }
-        else {
-            tcg_abort ();
+        } else {
+            /* Indirect jump method.  */
+            tcg_abort();
         }
         s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
         break;
@@ -1423,83 +1531,70 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
             TCGLabel *l = &s->labels[args[0]];
 
             if (l->has_value) {
-                tcg_out_b (s, 0, l->u.value);
-            }
-            else {
-                uint32_t val = *(uint32_t *) s->code_ptr;
-
-                /* Thanks to Andrzej Zaborowski */
-                tcg_out32 (s, B | (val & 0x3fffffc));
-                tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0);
+                tcg_out_b(s, 0, l->u.value);
+            } else {
+                tcg_out_reloc(s, s->code_ptr, R_PPC_REL24, args[0], 0);
+                tcg_out_b_noaddr(s, B);
             }
         }
         break;
     case INDEX_op_call:
-        tcg_out_call (s, args[0], const_args[0]);
+        tcg_out_call(s, args[0], const_args[0]);
         break;
     case INDEX_op_movi_i32:
-        tcg_out_movi (s, TCG_TYPE_I32, args[0], args[1]);
+        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
         break;
     case INDEX_op_movi_i64:
-        tcg_out_movi (s, TCG_TYPE_I64, args[0], args[1]);
+        tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
         break;
     case INDEX_op_ld8u_i32:
     case INDEX_op_ld8u_i64:
-        tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
+        tcg_out_mem_long(s, LBZ, LBZX, args[0], args[1], args[2]);
         break;
     case INDEX_op_ld8s_i32:
     case INDEX_op_ld8s_i64:
-        tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
-        tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0]));
+        tcg_out_mem_long(s, LBZ, LBZX, args[0], args[1], args[2]);
+        tcg_out32(s, EXTSB | RS(args[0]) | RA(args[0]));
         break;
     case INDEX_op_ld16u_i32:
     case INDEX_op_ld16u_i64:
-        tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX);
+        tcg_out_mem_long(s, LHZ, LHZX, args[0], args[1], args[2]);
         break;
     case INDEX_op_ld16s_i32:
     case INDEX_op_ld16s_i64:
-        tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX);
+        tcg_out_mem_long(s, LHA, LHAX, args[0], args[1], args[2]);
         break;
     case INDEX_op_ld_i32:
     case INDEX_op_ld32u_i64:
-        tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX);
+        tcg_out_mem_long(s, LWZ, LWZX, args[0], args[1], args[2]);
         break;
     case INDEX_op_ld32s_i64:
-        tcg_out_ldsta (s, args[0], args[1], args[2], LWA, LWAX);
+        tcg_out_mem_long(s, LWA, LWAX, args[0], args[1], args[2]);
         break;
     case INDEX_op_ld_i64:
-        tcg_out_ldsta (s, args[0], args[1], args[2], LD, LDX);
+        tcg_out_mem_long(s, LD, LDX, args[0], args[1], args[2]);
         break;
     case INDEX_op_st8_i32:
     case INDEX_op_st8_i64:
-        tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX);
+        tcg_out_mem_long(s, STB, STBX, args[0], args[1], args[2]);
         break;
     case INDEX_op_st16_i32:
     case INDEX_op_st16_i64:
-        tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX);
+        tcg_out_mem_long(s, STH, STHX, args[0], args[1], args[2]);
         break;
     case INDEX_op_st_i32:
     case INDEX_op_st32_i64:
-        tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX);
+        tcg_out_mem_long(s, STW, STWX, args[0], args[1], args[2]);
         break;
     case INDEX_op_st_i64:
-        tcg_out_ldsta (s, args[0], args[1], args[2], STD, STDX);
+        tcg_out_mem_long(s, STD, STDX, args[0], args[1], args[2]);
         break;
 
     case INDEX_op_add_i32:
         a0 = args[0], a1 = args[1], a2 = args[2];
         if (const_args[2]) {
-            int32_t l, h;
         do_addi_32:
-            l = (int16_t)a2;
-            h = a2 - l;
-            if (h) {
-                tcg_out32(s, ADDIS | TAI(a0, a1, h >> 16));
-                a1 = a0;
-            }
-            if (l || a0 != a1) {
-                tcg_out32(s, ADDI | TAI(a0, a1, l));
-            }
+            tcg_out_mem_long(s, ADDI, ADD, a0, a1, (int32_t)a2);
         } else {
             tcg_out32(s, ADD | TAB(a0, a1, a2));
         }
@@ -1607,32 +1702,33 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
         break;
 
     case INDEX_op_div_i32:
-        tcg_out32 (s, DIVW | TAB (args[0], args[1], args[2]));
+        tcg_out32(s, DIVW | TAB(args[0], args[1], args[2]));
         break;
 
     case INDEX_op_divu_i32:
-        tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
+        tcg_out32(s, DIVWU | TAB(args[0], args[1], args[2]));
         break;
 
     case INDEX_op_shl_i32:
         if (const_args[2]) {
             tcg_out_rlw(s, RLWINM, args[0], args[1], args[2], 0, 31 - args[2]);
         } else {
-            tcg_out32 (s, SLW | SAB (args[1], args[0], args[2]));
+            tcg_out32(s, SLW | SAB(args[1], args[0], args[2]));
         }
         break;
     case INDEX_op_shr_i32:
         if (const_args[2]) {
             tcg_out_rlw(s, RLWINM, args[0], args[1], 32 - args[2], args[2], 31);
         } else {
-            tcg_out32 (s, SRW | SAB (args[1], args[0], args[2]));
+            tcg_out32(s, SRW | SAB(args[1], args[0], args[2]));
         }
         break;
     case INDEX_op_sar_i32:
-        if (const_args[2])
-            tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2]));
-        else
-            tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2]));
+        if (const_args[2]) {
+            tcg_out32(s, SRAWI | RS(args[1]) | RA(args[0]) | SH(args[2]));
+        } else {
+            tcg_out32(s, SRAW | SAB(args[1], args[0], args[2]));
+        }
         break;
     case INDEX_op_rotl_i32:
         if (const_args[2]) {
@@ -1646,8 +1742,8 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
         if (const_args[2]) {
             tcg_out_rlw(s, RLWINM, args[0], args[1], 32 - args[2], 0, 31);
         } else {
-            tcg_out32(s, SUBFIC | TAI(0, args[2], 32));
-            tcg_out32(s, RLWNM | SAB(args[1], args[0], 0)
+            tcg_out32(s, SUBFIC | TAI(TCG_REG_R0, args[2], 32));
+            tcg_out32(s, RLWNM | SAB(args[1], args[0], TCG_REG_R0)
                          | MB(0) | ME(31));
         }
         break;
@@ -1664,43 +1760,19 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
 
     case INDEX_op_neg_i32:
     case INDEX_op_neg_i64:
-        tcg_out32 (s, NEG | RT (args[0]) | RA (args[1]));
+        tcg_out32(s, NEG | RT(args[0]) | RA(args[1]));
         break;
 
     case INDEX_op_not_i32:
     case INDEX_op_not_i64:
-        tcg_out32 (s, NOR | SAB (args[1], args[0], args[1]));
+        tcg_out32(s, NOR | SAB(args[1], args[0], args[1]));
         break;
 
     case INDEX_op_add_i64:
         a0 = args[0], a1 = args[1], a2 = args[2];
         if (const_args[2]) {
-            int32_t l0, h1, h2;
         do_addi_64:
-            /* We can always split any 32-bit signed constant into 3 pieces.
-               Note the positive 0x80000000 coming from the sub_i64 path,
-               handled with the same code we need for eg 0x7fff8000.  */
-            assert(a2 == (int32_t)a2 || a2 == 0x80000000);
-            l0 = (int16_t)a2;
-            h1 = a2 - l0;
-            h2 = 0;
-            if (h1 < 0 && (int64_t)a2 > 0) {
-                h2 = 0x40000000;
-                h1 = a2 - h2 - l0;
-            }
-            assert((TCGArg)h2 + h1 + l0 == a2);
-
-            if (h2) {
-                tcg_out32(s, ADDIS | TAI(a0, a1, h2 >> 16));
-                a1 = a0;
-            }
-            if (h1) {
-                tcg_out32(s, ADDIS | TAI(a0, a1, h1 >> 16));
-                a1 = a0;
-            }
-            if (l0 || a0 != a1) {
-                tcg_out32(s, ADDI | TAI(a0, a1, l0));
-            }
+            tcg_out_mem_long(s, ADDI, ADD, a0, a1, a2);
         } else {
             tcg_out32(s, ADD | TAB(a0, a1, a2));
         }
@@ -1722,24 +1794,26 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
         break;
 
     case INDEX_op_shl_i64:
-        if (const_args[2])
+        if (const_args[2]) {
             tcg_out_shli64(s, args[0], args[1], args[2]);
-        else
-            tcg_out32 (s, SLD | SAB (args[1], args[0], args[2]));
+        } else {
+            tcg_out32(s, SLD | SAB(args[1], args[0], args[2]));
+        }
         break;
     case INDEX_op_shr_i64:
-        if (const_args[2])
+        if (const_args[2]) {
             tcg_out_shri64(s, args[0], args[1], args[2]);
-        else
-            tcg_out32 (s, SRD | SAB (args[1], args[0], args[2]));
+        } else {
+            tcg_out32(s, SRD | SAB(args[1], args[0], args[2]));
+        }
         break;
     case INDEX_op_sar_i64:
         if (const_args[2]) {
-            int sh = SH (args[2] & 0x1f) | (((args[2] >> 5) & 1) << 1);
-            tcg_out32 (s, SRADI | RA (args[0]) | RS (args[1]) | sh);
+            int sh = SH(args[2] & 0x1f) | (((args[2] >> 5) & 1) << 1);
+            tcg_out32(s, SRADI | RA(args[0]) | RS(args[1]) | sh);
+        } else {
+            tcg_out32(s, SRAD | SAB(args[1], args[0], args[2]));
         }
-        else
-            tcg_out32 (s, SRAD | SAB (args[1], args[0], args[2]));
         break;
     case INDEX_op_rotl_i64:
         if (const_args[2]) {
@@ -1752,8 +1826,8 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
         if (const_args[2]) {
             tcg_out_rld(s, RLDICL, args[0], args[1], 64 - args[2], 0);
         } else {
-            tcg_out32(s, SUBFIC | TAI(0, args[2], 64));
-            tcg_out32(s, RLDCL | SAB(args[1], args[0], 0) | MB64(0));
+            tcg_out32(s, SUBFIC | TAI(TCG_REG_R0, args[2], 64));
+            tcg_out32(s, RLDCL | SAB(args[1], args[0], TCG_REG_R0) | MB64(0));
         }
         break;
 
@@ -1766,45 +1840,45 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
         }
         break;
     case INDEX_op_div_i64:
-        tcg_out32 (s, DIVD | TAB (args[0], args[1], args[2]));
+        tcg_out32(s, DIVD | TAB(args[0], args[1], args[2]));
         break;
     case INDEX_op_divu_i64:
-        tcg_out32 (s, DIVDU | TAB (args[0], args[1], args[2]));
+        tcg_out32(s, DIVDU | TAB(args[0], args[1], args[2]));
         break;
 
     case INDEX_op_qemu_ld8u:
-        tcg_out_qemu_ld (s, args, 0);
+        tcg_out_qemu_ld(s, args, 0);
         break;
     case INDEX_op_qemu_ld8s:
-        tcg_out_qemu_ld (s, args, 0 | 4);
+        tcg_out_qemu_ld(s, args, 0 | 4);
         break;
     case INDEX_op_qemu_ld16u:
-        tcg_out_qemu_ld (s, args, 1);
+        tcg_out_qemu_ld(s, args, 1);
         break;
     case INDEX_op_qemu_ld16s:
-        tcg_out_qemu_ld (s, args, 1 | 4);
+        tcg_out_qemu_ld(s, args, 1 | 4);
         break;
     case INDEX_op_qemu_ld32:
     case INDEX_op_qemu_ld32u:
-        tcg_out_qemu_ld (s, args, 2);
+        tcg_out_qemu_ld(s, args, 2);
         break;
     case INDEX_op_qemu_ld32s:
-        tcg_out_qemu_ld (s, args, 2 | 4);
+        tcg_out_qemu_ld(s, args, 2 | 4);
         break;
     case INDEX_op_qemu_ld64:
-        tcg_out_qemu_ld (s, args, 3);
+        tcg_out_qemu_ld(s, args, 3);
         break;
     case INDEX_op_qemu_st8:
-        tcg_out_qemu_st (s, args, 0);
+        tcg_out_qemu_st(s, args, 0);
         break;
     case INDEX_op_qemu_st16:
-        tcg_out_qemu_st (s, args, 1);
+        tcg_out_qemu_st(s, args, 1);
         break;
     case INDEX_op_qemu_st32:
-        tcg_out_qemu_st (s, args, 2);
+        tcg_out_qemu_st(s, args, 2);
         break;
     case INDEX_op_qemu_st64:
-        tcg_out_qemu_st (s, args, 3);
+        tcg_out_qemu_st(s, args, 3);
         break;
 
     case INDEX_op_ext8s_i32:
@@ -1819,16 +1893,16 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
         c = EXTSW;
         goto gen_ext;
     gen_ext:
-        tcg_out32 (s, c | RS (args[1]) | RA (args[0]));
+        tcg_out32(s, c | RS(args[1]) | RA(args[0]));
         break;
 
     case INDEX_op_setcond_i32:
-        tcg_out_setcond (s, TCG_TYPE_I32, args[3], args[0], args[1], args[2],
-                         const_args[2]);
+        tcg_out_setcond(s, TCG_TYPE_I32, args[3], args[0], args[1], args[2],
+                        const_args[2]);
         break;
     case INDEX_op_setcond_i64:
-        tcg_out_setcond (s, TCG_TYPE_I64, args[3], args[0], args[1], args[2],
-                         const_args[2]);
+        tcg_out_setcond(s, TCG_TYPE_I64, args[3], args[0], args[1], args[2],
+                        const_args[2]);
         break;
 
     case INDEX_op_bswap16_i32:
@@ -1870,9 +1944,9 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
         break;
 
     case INDEX_op_bswap64_i64:
-        a0 = args[0], a1 = args[1], a2 = 0;
+        a0 = args[0], a1 = args[1], a2 = TCG_REG_R0;
         if (a0 == a1) {
-            a0 = 0;
+            a0 = TCG_REG_R0;
             a2 = a1;
         }
 
@@ -1980,8 +2054,8 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
         break;
 
     default:
-        tcg_dump_ops (s);
-        tcg_abort ();
+        tcg_dump_ops(s);
+        tcg_abort();
     }
 }
 
@@ -2109,7 +2183,7 @@ static const TCGTargetOpDef ppc_op_defs[] = {
     { -1 },
 };
 
-static void tcg_target_init (TCGContext *s)
+static void tcg_target_init(TCGContext *s)
 {
 #ifdef CONFIG_GETAUXVAL
     unsigned long hwcap = getauxval(AT_HWCAP);
@@ -2118,13 +2192,11 @@ static void tcg_target_init (TCGContext *s)
     }
 #endif
 
-    tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
-    tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
-    tcg_regset_set32 (tcg_target_call_clobber_regs, 0,
+    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
+    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
+    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
                      (1 << TCG_REG_R0) |
-#ifdef __APPLE__
                      (1 << TCG_REG_R2) |
-#endif
                      (1 << TCG_REG_R3) |
                      (1 << TCG_REG_R4) |
                      (1 << TCG_REG_R5) |
@@ -2134,16 +2206,65 @@ static void tcg_target_init (TCGContext *s)
                      (1 << TCG_REG_R9) |
                      (1 << TCG_REG_R10) |
                      (1 << TCG_REG_R11) |
-                     (1 << TCG_REG_R12)
-        );
+                     (1 << TCG_REG_R12));
 
-    tcg_regset_clear (s->reserved_regs);
-    tcg_regset_set_reg (s->reserved_regs, TCG_REG_R0);
-    tcg_regset_set_reg (s->reserved_regs, TCG_REG_R1);
-#ifndef __APPLE__
-    tcg_regset_set_reg (s->reserved_regs, TCG_REG_R2);
+    tcg_regset_clear(s->reserved_regs);
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0); /* tcg temp */
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1); /* stack pointer */
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2); /* mem temp */
+#ifdef __APPLE__
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R11); /* ??? */
 #endif
-    tcg_regset_set_reg (s->reserved_regs, TCG_REG_R13);
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13); /* thread pointer */
+
+    tcg_add_target_add_op_defs(ppc_op_defs);
+}
+
+typedef struct {
+    DebugFrameCIE cie;
+    DebugFrameFDEHeader fde;
+    uint8_t fde_def_cfa[4];
+    uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2 + 3];
+} DebugFrame;
+
+/* We're expecting a 2 byte uleb128 encoded value.  */
+QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
+
+#define ELF_HOST_MACHINE EM_PPC64
+
+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 = 0x78,             /* sleb128 -8 */
+    .cie.return_column = 65,
+
+    /* Total FDE size does not include the "len" member.  */
+    .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
+
+    .fde_def_cfa = {
+        12, 1,                          /* DW_CFA_def_cfa r1, ... */
+        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
+        (FRAME_SIZE >> 7)
+    },
+    .fde_reg_ofs = {
+        0x11, 65, 0x7e,                 /* DW_CFA_offset_extended_sf, lr, 16 */
+    }
+};
+
+void tcg_register_jit(void *buf, size_t buf_size)
+{
+    uint8_t *p = &debug_frame.fde_reg_ofs[3];
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i, p += 2) {
+        p[0] = 0x80 + tcg_target_callee_save_regs[i];
+        p[1] = (FRAME_SIZE - (REG_SAVE_BOT + i * 8)) / 8;
+    }
+
+    debug_frame.fde.func_start = (tcg_target_long) buf;
+    debug_frame.fde.func_len = buf_size;
 
-    tcg_add_target_add_op_defs (ppc_op_defs);
+    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
 }
index 233ab3b..4976bec 100644 (file)
@@ -670,7 +670,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
     case INDEX_op_shl_i64:
     case INDEX_op_shr_i64:
     case INDEX_op_sar_i64:
-        /* TODO: Implementation of rotl_i64, rotr_i64 missing in tci.c. */
     case INDEX_op_rotl_i64:     /* Optional (TCG_TARGET_HAS_rot_i64). */
     case INDEX_op_rotr_i64:     /* Optional (TCG_TARGET_HAS_rot_i64). */
         tcg_out_r(s, args[0]);
diff --git a/tci.c b/tci.c
index 6d64891..0202ed9 100644 (file)
--- a/tci.c
+++ b/tci.c
@@ -688,13 +688,13 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
             t0 = *tb_ptr++;
             t1 = tci_read_ri32(&tb_ptr);
             t2 = tci_read_ri32(&tb_ptr);
-            tci_write_reg32(t0, (t1 << t2) | (t1 >> (32 - t2)));
+            tci_write_reg32(t0, rol32(t1, t2));
             break;
         case INDEX_op_rotr_i32:
             t0 = *tb_ptr++;
             t1 = tci_read_ri32(&tb_ptr);
             t2 = tci_read_ri32(&tb_ptr);
-            tci_write_reg32(t0, (t1 >> t2) | (t1 << (32 - t2)));
+            tci_write_reg32(t0, ror32(t1, t2));
             break;
 #endif
 #if TCG_TARGET_HAS_deposit_i32
@@ -952,8 +952,16 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
             break;
 #if TCG_TARGET_HAS_rot_i64
         case INDEX_op_rotl_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri64(&tb_ptr);
+            t2 = tci_read_ri64(&tb_ptr);
+            tci_write_reg64(t0, rol64(t1, t2));
+            break;
         case INDEX_op_rotr_i64:
-            TODO();
+            t0 = *tb_ptr++;
+            t1 = tci_read_ri64(&tb_ptr);
+            t2 = tci_read_ri64(&tb_ptr);
+            tci_write_reg64(t0, ror64(t1, t2));
             break;
 #endif
 #if TCG_TARGET_HAS_deposit_i64
index ae5280e..425757c 100644 (file)
@@ -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]
@@ -21,3 +23,4 @@ test-thread-pool
 test-x86-cpuid
 test-xbzrle
 *-test
+qapi-schema/*.test.*
index 994fef1..915ae5e 100644 (file)
@@ -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
 
index 62b4002..0541f80 100644 (file)
@@ -2,6 +2,7 @@ check.log
 check.time
 *.out.bad
 *.notrun
+socket_scm_helper
 
 # ignore everything in the scratch directory
 scratch/
index bd88dde..4e16469 100755 (executable)
@@ -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
index 51d0a8f..6a865aa 100755 (executable)
@@ -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"
index ee25fb8..98638d4 100755 (executable)
@@ -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"
index c76451c..651072e 100755 (executable)
@@ -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
index b7970e3..9abcb84 100755 (executable)
@@ -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"
index 6fa7603..fe1a743 100755 (executable)
@@ -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
index 2c53bac..2d28efd 100755 (executable)
@@ -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
index 25368c8..57a43f5 100755 (executable)
@@ -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"
index 7b57929..896a005 100755 (executable)
@@ -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"
index b03df68..1c5158a 100755 (executable)
@@ -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
index 4052956..7c5b689 100755 (executable)
@@ -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"
index ce40d5c..389f4b8 100755 (executable)
@@ -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
index a6d0aea..0edeb4b 100755 (executable)
@@ -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
index 44c134f..099d757 100755 (executable)
@@ -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"
index a1467b8..b87a32b 100755 (executable)
@@ -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"
index 453ce61..15fcfe5 100755 (executable)
@@ -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
index 8872b30..cd3582c 100755 (executable)
@@ -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
index 2fb0ff8..b3c86d8 100755 (executable)
@@ -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
index 6da79eb..1c69024 100755 (executable)
@@ -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
 
index 4f31b56..090ed23 100755 (executable)
@@ -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
index 554b74b..be974f0 100755 (executable)
@@ -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
index 7062aa6..a7241cc 100755 (executable)
@@ -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"
index 107a3ff..ebe29d0 100755 (executable)
@@ -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"
 
index 0764389..1504579 100644 (file)
@@ -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 
index 33bad0d..c9d242e 100644 (file)
@@ -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 
index 7d90481..3fa81b8 100755 (executable)
@@ -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"
index b091ba9..93a9fa6 100755 (executable)
@@ -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
 
index 0ad5e45..b424726 100755 (executable)
@@ -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
index 2d5e3b1..c9070b0 100755 (executable)
@@ -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
index 7155568..b1ba5c3 100755 (executable)
@@ -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
index 9aee078..ea3351c 100755 (executable)
@@ -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"
index 8254df8..67f1959 100755 (executable)
@@ -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"
index 9d2d347..ebe9b8c 100755 (executable)
@@ -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
index 4dbfc57..e049a64 100755 (executable)
@@ -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"
index c11460b..743bae3 100755 (executable)
@@ -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
 
index 90de1a7..7bb7906 100755 (executable)
@@ -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
 
index ae35175..f85b4ce 100755 (executable)
@@ -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 "== Data should still be accessible after repair =="
 
-$QEMU_IO -c "read -P 0x5a 0 512" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read -P 0x5a 0 512" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== Opening a dirty image read/write should repair it =="
@@ -104,16 +104,16 @@ _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
 
-$QEMU_IO -c "write 0 512" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "write 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
 
 echo
 echo "== Creating an image file with lazy_refcounts=off =="
@@ -123,11 +123,11 @@ _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 not be set since lazy_refcounts=off
-./qcow2.py $TEST_IMG dump-header | grep incompatible_features
+./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
 _check_test_img
 
 # success, all done
index 16b2fdb..94ce3a9 100755 (executable)
@@ -48,27 +48,27 @@ echo "== Creating zero size image =="
 _make_test_img 0
 _check_test_img
 
-mv $TEST_IMG $TEST_IMG.orig
+mv "$TEST_IMG" "$TEST_IMG.orig"
 
 echo
 echo "== Converting the image =="
 
-$QEMU_IMG convert -O $IMGFMT $TEST_IMG.orig $TEST_IMG
+$QEMU_IMG convert -O $IMGFMT "$TEST_IMG.orig" "$TEST_IMG"
 _check_test_img
 
 echo
 echo "== Converting the image, compressed =="
 
 if [ "$IMGFMT" == "qcow2" ]; then
-    $QEMU_IMG convert -c -O $IMGFMT $TEST_IMG.orig $TEST_IMG
+    $QEMU_IMG convert -c -O $IMGFMT "$TEST_IMG.orig" "$TEST_IMG"
 fi
 _check_test_img
 
 echo
 echo "== Rebasing the image =="
 
-$QEMU_IMG rebase -u -b $TEST_IMG.orig $TEST_IMG
-$QEMU_IMG rebase -b $TEST_IMG.orig $TEST_IMG
+$QEMU_IMG rebase -u -b "$TEST_IMG.orig" "$TEST_IMG"
+$QEMU_IMG rebase -b "$TEST_IMG.orig" "$TEST_IMG"
 _check_test_img
 
 # success, all done
index 478773d..d7f1231 100755 (executable)
@@ -31,7 +31,7 @@ status=1      # failure is the default!
 _cleanup()
 {
     _cleanup_test_img
-    rm -f $TEST_IMG.[123].base
+    rm -f "$TEST_IMG".[123].base
 }
 trap "_cleanup; exit \$status" 0 1 2 3 15
 
@@ -47,39 +47,39 @@ _supported_os Linux
 
 size=128M
 _make_test_img $size
-$QEMU_IMG rebase -u -b $TEST_IMG $TEST_IMG
+$QEMU_IMG rebase -u -b "$TEST_IMG" "$TEST_IMG"
 
 echo
 echo "== backing file references self =="
 _img_info --backing-chain
 
 _make_test_img $size
-mv $TEST_IMG $TEST_IMG.base
-_make_test_img -b $TEST_IMG.base $size
-$QEMU_IMG rebase -u -b $TEST_IMG $TEST_IMG.base
+mv "$TEST_IMG" "$TEST_IMG.base"
+_make_test_img -b "$TEST_IMG.base" $size
+$QEMU_IMG rebase -u -b "$TEST_IMG" "$TEST_IMG.base"
 
 echo
 echo "== parent references self =="
 _img_info --backing-chain
 
 _make_test_img $size
-mv $TEST_IMG $TEST_IMG.1.base
-_make_test_img -b $TEST_IMG.1.base $size
-mv $TEST_IMG $TEST_IMG.2.base
-_make_test_img -b $TEST_IMG.2.base $size
-mv $TEST_IMG $TEST_IMG.3.base
-_make_test_img -b $TEST_IMG.3.base $size
-$QEMU_IMG rebase -u -b $TEST_IMG.2.base $TEST_IMG.1.base
+mv "$TEST_IMG" "$TEST_IMG.1.base"
+_make_test_img -b "$TEST_IMG.1.base" $size
+mv "$TEST_IMG" "$TEST_IMG.2.base"
+_make_test_img -b "$TEST_IMG.2.base" $size
+mv "$TEST_IMG" "$TEST_IMG.3.base"
+_make_test_img -b "$TEST_IMG.3.base" $size
+$QEMU_IMG rebase -u -b "$TEST_IMG.2.base" "$TEST_IMG.1.base"
 
 echo
 echo "== ancestor references another ancestor =="
 _img_info --backing-chain
 
 _make_test_img $size
-mv $TEST_IMG $TEST_IMG.1.base
-_make_test_img -b $TEST_IMG.1.base $size
-mv $TEST_IMG $TEST_IMG.2.base
-_make_test_img -b $TEST_IMG.2.base $size
+mv "$TEST_IMG" "$TEST_IMG.1.base"
+_make_test_img -b "$TEST_IMG.1.base" $size
+mv "$TEST_IMG" "$TEST_IMG.2.base"
+_make_test_img -b "$TEST_IMG.2.base" $size
 
 echo
 echo "== finite chain of length 3 (human) =="
index 987bfff..3f17ceb 100755 (executable)
@@ -66,11 +66,11 @@ function backing_io()
     done
 }
 
-backing_io 0 32 write | $QEMU_IO $TEST_IMG | _filter_qemu_io
+backing_io 0 32 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 =="
@@ -185,7 +185,7 @@ aio_flush
 EOF
 }
 
-overlay_io | $QEMU_IO blkdebug::$TEST_IMG | _filter_qemu_io |\
+overlay_io | $QEMU_IO blkdebug::"$TEST_IMG" | _filter_qemu_io |\
        sed -e 's/bytes at offset [0-9]*/bytes at offset XXX/g'
 
 echo
@@ -252,7 +252,7 @@ function verify_io()
     echo read -P 17  0x11c000 0x4000
 }
 
-verify_io | $QEMU_IO $TEST_IMG | _filter_qemu_io
+verify_io | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
 
 _check_test_img
 
index 0cf36b4..c35cd09 100755 (executable)
@@ -66,7 +66,7 @@ read -P 0x55 1M 128k
 EOF
 }
 
-qemu_io_cmds | $QEMU_IO $TEST_IMG | _filter_qemu_io
+qemu_io_cmds | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
 _check_test_img
 
 # success, all done
index 7cce049..9b9d118 100755 (executable)
@@ -31,13 +31,13 @@ _cleanup()
 {
     echo "Cleanup"
     _cleanup_test_img
-    rm ${TEST_IMG2}
+    rm "${TEST_IMG2}"
 }
 trap "_cleanup; exit \$status" 0 1 2 3 15
 
 _compare()
 {
-    $QEMU_IMG compare "$@" $TEST_IMG ${TEST_IMG2}
+    $QEMU_IMG compare "$@" "$TEST_IMG" "${TEST_IMG2}"
     echo $?
 }
 
@@ -59,12 +59,12 @@ _make_test_img $size
 io_pattern write 524288 $CLUSTER_SIZE $CLUSTER_SIZE 4 45
 
 # Compare identical images
-cp $TEST_IMG ${TEST_IMG2}
+cp "$TEST_IMG" "${TEST_IMG2}"
 _compare
 _compare -q
 
 # Compare images with different size
-$QEMU_IMG resize $TEST_IMG +512M
+$QEMU_IMG resize "$TEST_IMG" +512M
 _compare
 _compare -s
 
index 6c6017e..93aa0ea 100755 (executable)
@@ -63,13 +63,13 @@ sizes+="1024.0 1024.0b 1.5k 1.5K 1.5M 1.5G 1.5T"
 echo "== 1. Traditional size parameter =="
 echo
 for s in $sizes; do
-    test_qemu_img create -f $IMGFMT $TEST_IMG $s
+    test_qemu_img create -f $IMGFMT "$TEST_IMG" $s
 done
 
 echo "== 2. Specifying size via -o =="
 echo
 for s in $sizes; do
-    test_qemu_img create -f $IMGFMT -o size=$s $TEST_IMG
+    test_qemu_img create -f $IMGFMT -o size=$s "$TEST_IMG"
 done
 
 echo "== 3. Invalid sizes =="
@@ -77,8 +77,8 @@ echo
 sizes="-1024 -1k 1kilobyte foobar"
 
 for s in $sizes; do
-    test_qemu_img create -f $IMGFMT $TEST_IMG -- $s
-    test_qemu_img create -f $IMGFMT -o size=$s $TEST_IMG
+    test_qemu_img create -f $IMGFMT "$TEST_IMG" -- $s
+    test_qemu_img create -f $IMGFMT -o size=$s "$TEST_IMG"
 done
 
 echo "== Check correct interpretation of suffixes for cluster size =="
@@ -87,35 +87,35 @@ sizes="1024 1024b 1k 1K 1M "
 sizes+="1024.0 1024.0b 0.5k 0.5K 0.5M"
 
 for s in $sizes; do
-    test_qemu_img create -f $IMGFMT -o cluster_size=$s $TEST_IMG 64M
+    test_qemu_img create -f $IMGFMT -o cluster_size=$s "$TEST_IMG" 64M
 done
 
 echo "== Check compat level option =="
 echo
-test_qemu_img create -f $IMGFMT -o compat=0.10 $TEST_IMG 64M
-test_qemu_img create -f $IMGFMT -o compat=1.1 $TEST_IMG 64M
+test_qemu_img create -f $IMGFMT -o compat=0.10 "$TEST_IMG" 64M
+test_qemu_img create -f $IMGFMT -o compat=1.1 "$TEST_IMG" 64M
 
-test_qemu_img create -f $IMGFMT -o compat=0.42 $TEST_IMG 64M
-test_qemu_img create -f $IMGFMT -o compat=foobar $TEST_IMG 64M
+test_qemu_img create -f $IMGFMT -o compat=0.42 "$TEST_IMG" 64M
+test_qemu_img create -f $IMGFMT -o compat=foobar "$TEST_IMG" 64M
 
 echo "== Check preallocation option =="
 echo
-test_qemu_img create -f $IMGFMT -o preallocation=off $TEST_IMG 64M
-test_qemu_img create -f $IMGFMT -o preallocation=metadata $TEST_IMG 64M
-test_qemu_img create -f $IMGFMT -o preallocation=1234 $TEST_IMG 64M
+test_qemu_img create -f $IMGFMT -o preallocation=off "$TEST_IMG" 64M
+test_qemu_img create -f $IMGFMT -o preallocation=metadata "$TEST_IMG" 64M
+test_qemu_img create -f $IMGFMT -o preallocation=1234 "$TEST_IMG" 64M
 
 echo "== Check encryption option =="
 echo
-test_qemu_img create -f $IMGFMT -o encryption=off $TEST_IMG 64M
-test_qemu_img create -f $IMGFMT -o encryption=on $TEST_IMG 64M
+test_qemu_img create -f $IMGFMT -o encryption=off "$TEST_IMG" 64M
+test_qemu_img create -f $IMGFMT -o encryption=on "$TEST_IMG" 64M
 
 echo "== Check lazy_refcounts option (only with v3) =="
 echo
-test_qemu_img create -f $IMGFMT -o compat=1.1,lazy_refcounts=off $TEST_IMG 64M
-test_qemu_img create -f $IMGFMT -o compat=1.1,lazy_refcounts=on $TEST_IMG 64M
+test_qemu_img create -f $IMGFMT -o compat=1.1,lazy_refcounts=off "$TEST_IMG" 64M
+test_qemu_img create -f $IMGFMT -o compat=1.1,lazy_refcounts=on "$TEST_IMG" 64M
 
-test_qemu_img create -f $IMGFMT -o compat=0.10,lazy_refcounts=off $TEST_IMG 64M
-test_qemu_img create -f $IMGFMT -o compat=0.10,lazy_refcounts=on $TEST_IMG 64M
+test_qemu_img create -f $IMGFMT -o compat=0.10,lazy_refcounts=off "$TEST_IMG" 64M
+test_qemu_img create -f $IMGFMT -o compat=0.10,lazy_refcounts=on "$TEST_IMG" 64M
 
 # success, all done
 echo "*** done"
index 05793e2..07802bc 100755 (executable)
@@ -31,8 +31,8 @@ status=1      # failure is the default!
 _cleanup()
 {
     _cleanup_test_img
-    rm -f $TEST_IMG.old
-    rm -f $TEST_IMG.new
+    rm -f "$TEST_IMG.old"
+    rm -f "$TEST_IMG.new"
 }
 trap "_cleanup; exit \$status" 0 1 2 3 15
 
@@ -53,21 +53,21 @@ echo "== Creating images =="
 
 size=10M
 _make_test_img $size
-$QEMU_IO -c "write -P 0x40 0 1048576" $TEST_IMG | _filter_qemu_io
-mv $TEST_IMG $TEST_IMG.old
+$QEMU_IO -c "write -P 0x40 0 1048576" "$TEST_IMG" | _filter_qemu_io
+mv "$TEST_IMG" "$TEST_IMG.old"
 
 _make_test_img $size
-$QEMU_IO -c "write -P 0x5a 0 1048576" $TEST_IMG | _filter_qemu_io
-mv $TEST_IMG $TEST_IMG.new
+$QEMU_IO -c "write -P 0x5a 0 1048576" "$TEST_IMG" | _filter_qemu_io
+mv "$TEST_IMG" "$TEST_IMG.new"
 
-_make_test_img -b $TEST_IMG.old $size
-$QEMU_IO -c "write -z 0 1048576" $TEST_IMG | _filter_qemu_io
+_make_test_img -b "$TEST_IMG.old" $size
+$QEMU_IO -c "write -z 0 1048576" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== Rebasing the image =="
 
-$QEMU_IMG rebase -b $TEST_IMG.new $TEST_IMG
-$QEMU_IO -c "read -P 0x00 0 1048576" $TEST_IMG | _filter_qemu_io
+$QEMU_IMG rebase -b "$TEST_IMG.new" "$TEST_IMG"
+$QEMU_IO -c "read -P 0x00 0 1048576" "$TEST_IMG" | _filter_qemu_io
 
 # success, all done
 echo "*** done"
index 1f39c6a..356c375 100755 (executable)
@@ -45,7 +45,14 @@ _supported_os Linux
 function do_run_qemu()
 {
     echo Testing: "$@"
-    echo quit | $QEMU -nographic -monitor stdio -serial none "$@"
+    (
+        if ! test -t 0; then
+            while read cmd; do
+                echo $cmd
+            done
+        fi
+        echo quit
+    ) | $QEMU -nographic -monitor stdio -serial none "$@"
     echo
 }
 
@@ -57,26 +64,34 @@ function run_qemu()
 size=128M
 
 _make_test_img $size
+cp $TEST_IMG $TEST_IMG.orig
+mv $TEST_IMG $TEST_IMG.base
+_make_test_img -b $TEST_IMG.base $size
 
 echo
 echo === Unknown option ===
 echo
 
-run_qemu -drive file=$TEST_IMG,format=qcow2,unknown_opt=
-run_qemu -drive file=$TEST_IMG,format=qcow2,unknown_opt=on
-run_qemu -drive file=$TEST_IMG,format=qcow2,unknown_opt=1234
-run_qemu -drive file=$TEST_IMG,format=qcow2,unknown_opt=foo
+run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=
+run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=on
+run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=1234
+run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=foo
 
+echo
+echo === Overriding backing file ===
+echo
+
+echo "info block" | run_qemu -drive file=$TEST_IMG,driver=qcow2,backing.file.filename=$TEST_IMG.orig -nodefaults
 
 echo
 echo === Enable and disable lazy refcounting on the command line, plus some invalid values ===
 echo
 
-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=on
-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=off
-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=
-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=42
-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=foo
+run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=on
+run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=off
+run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=
+run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=42
+run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=foo
 
 
 echo
@@ -85,8 +100,8 @@ echo
 
 _make_test_img -ocompat=0.10 $size
 
-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=on
-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=off
+run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=on
+run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=off
 
 echo
 echo === No medium ===
@@ -112,21 +127,21 @@ echo
 echo === Read-only ===
 echo
 
-run_qemu -drive file=$TEST_IMG,if=floppy,readonly=on
-run_qemu -drive file=$TEST_IMG,if=ide,media=cdrom,readonly=on
-run_qemu -drive file=$TEST_IMG,if=scsi,media=cdrom,readonly=on
+run_qemu -drive file="$TEST_IMG",if=floppy,readonly=on
+run_qemu -drive file="$TEST_IMG",if=ide,media=cdrom,readonly=on
+run_qemu -drive file="$TEST_IMG",if=scsi,media=cdrom,readonly=on
 
-run_qemu -drive file=$TEST_IMG,if=ide,readonly=on
-run_qemu -drive file=$TEST_IMG,if=virtio,readonly=on
-run_qemu -drive file=$TEST_IMG,if=scsi,readonly=on
+run_qemu -drive file="$TEST_IMG",if=ide,readonly=on
+run_qemu -drive file="$TEST_IMG",if=virtio,readonly=on
+run_qemu -drive file="$TEST_IMG",if=scsi,readonly=on
 
-run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device ide-cd,drive=disk
-run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk
+run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-cd,drive=disk
+run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk
 
-run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device ide-drive,drive=disk
-run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device ide-hd,drive=disk
-run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk
-run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk
+run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-drive,drive=disk
+run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-hd,drive=disk
+run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk
+run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk
 
 echo
 echo === Cache modes ===
@@ -146,8 +161,8 @@ echo
 echo === Specifying the protocol layer ===
 echo
 
-run_qemu -drive file=$TEST_IMG,file.driver=file
-run_qemu -drive file=$TEST_IMG,file.driver=qcow2
+run_qemu -drive file="$TEST_IMG",file.driver=file
+run_qemu -drive file="$TEST_IMG",file.driver=qcow2
 
 echo
 echo === Parsing protocol from file name ===
index 88e8fa7..04bb236 100644 (file)
@@ -1,5 +1,6 @@
 QA output created by 051
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base' 
 
 === Unknown option ===
 
@@ -16,6 +17,16 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo
 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: could not open disk image TEST_DIR/t.qcow2: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt'
 
 
+=== Overriding backing file ===
+
+Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig -nodefaults
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K
+ide0-hd0: TEST_DIR/t.qcow2 (qcow2)
+    Backing file:     TEST_DIR/t.qcow2.orig (chain depth: 1)
+ [not inserted](qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+
+
 === Enable and disable lazy refcounting on the command line, plus some invalid values ===
 
 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on
index 14a5126..f5f9683 100755 (executable)
@@ -41,6 +41,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 _supported_fmt generic
 _supported_proto generic
 _supported_os Linux
+_unsupported_qemu_io_options --nocache
 
 
 size=128M
@@ -48,12 +49,12 @@ _make_test_img $size
 
 echo
 echo "== reading whole image =="
-$QEMU_IO -s -c "read 0 $size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -s -c "read 0 $size" "$TEST_IMG" | _filter_qemu_io
 
 echo
 echo "== writing whole image does not modify image =="
-$QEMU_IO -s -c "write -P 0xa 0 $size" $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c "read -P 0 0 $size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -s -c "write -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 0 $size" "$TEST_IMG" | _filter_qemu_io
 
 # success, all done
 echo "*** done"
index bc56992..e589e5f 100755 (executable)
@@ -30,7 +30,7 @@ status=1      # failure is the default!
 
 _cleanup()
 {
-       rm -f $TEST_IMG.orig
+       rm -f "$TEST_IMG.orig"
        _cleanup_test_img
 }
 trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -47,13 +47,13 @@ echo
 echo "== Creating single sector image =="
 
 _make_test_img 512
-$QEMU_IO -c "write -P0xa 0 512" $TEST_IMG | _filter_qemu_io
-mv $TEST_IMG $TEST_IMG.orig
+$QEMU_IO -c "write -P0xa 0 512" "$TEST_IMG" | _filter_qemu_io
+mv "$TEST_IMG" "$TEST_IMG.orig"
 
 echo
 echo "== Converting the image, compressed =="
 
-$QEMU_IMG convert -c -O $IMGFMT $TEST_IMG.orig $TEST_IMG
+$QEMU_IMG convert -c -O $IMGFMT "$TEST_IMG.orig" "$TEST_IMG"
 _check_test_img
 
 echo
@@ -64,7 +64,7 @@ _img_info | grep '^virtual size:'
 echo
 echo "== Verifying the compressed image =="
 
-$QEMU_IO -c "read -P0xa 0 512" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read -P0xa 0 512" "$TEST_IMG" | _filter_qemu_io
 
 # success, all done
 echo "*** done"
index b360429..5a0d1b1 100755 (executable)
@@ -49,7 +49,7 @@ _make_test_img $((1024*1024))T
 echo
 echo "creating too large image (1 EB) using qcow2.py"
 _make_test_img 4G
-./qcow2.py $TEST_IMG set-header size $((1024 ** 6))
+./qcow2.py "$TEST_IMG" set-header size $((1024 ** 6))
 _check_test_img
 
 # success, all done
index b03429d..dd6addf 100755 (executable)
@@ -51,20 +51,25 @@ echo "=== Testing invalid granularity ==="
 echo
 _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
+{ $QEMU_IO -c "read 0 512" "$TEST_IMG"; } 2>&1 | _filter_qemu_io | _filter_testdir
 
 echo "=== Testing too big L2 table size ==="
 echo
 _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
+{ $QEMU_IO -c "read 0 512" "$TEST_IMG"; } 2>&1 | _filter_qemu_io | _filter_testdir
 
 echo "=== Testing too big L1 table size ==="
 echo
 _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
+{ $QEMU_IO -c "read 0 512" "$TEST_IMG"; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+echo "=== Testing monolithicFlat creation and opening ==="
+echo
+IMGOPTS="subformat=monolithicFlat" _make_test_img 2G
+$QEMU_IMG info $TEST_IMG | _filter_testdir
 
 # success, all done
 echo "*** done"
index 9e715e5..9159dbe 100644 (file)
@@ -3,18 +3,25 @@ QA output created by 059
 
 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
+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 ===
 
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
 L2 table size too big
-qemu-io: can't open device TEST_DIR/t.vmdk
+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 ===
 
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
 L1 size too big
-qemu-io: can't open device TEST_DIR/t.vmdk
+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 ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648
+image: TEST_DIR/t.vmdk
+file format: vmdk
+virtual size: 2.0G (2147483648 bytes)
+disk size: 4.0K
 *** done
index 5f04bfa..fa9319d 100755 (executable)
@@ -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
index d42127f..4027e00 100644 (file)
@@ -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
index de0cbbd..2ab8f20 100755 (executable)
@@ -32,7 +32,7 @@ status=1      # failure is the default!
 _cleanup()
 {
        _cleanup_test_img
-       rm -f $TEST_IMG.orig $TEST_IMG.raw $TEST_IMG.raw2
+       rm -f "$TEST_IMG.orig" "$TEST_IMG.raw" "$TEST_IMG.raw2"
 }
 trap "_cleanup; exit \$status" 0 1 2 3 15
 
@@ -49,47 +49,47 @@ _make_test_img 4M
 
 echo "== Testing conversion with -n fails with no target file =="
 # check .orig file does not exist
-rm -f $TEST_IMG.orig
-if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n $TEST_IMG $TEST_IMG.orig >/dev/null 2>&1; then
+rm -f "$TEST_IMG.orig"
+if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG.orig" >/dev/null 2>&1; then
     exit 1
 fi
 
 echo "== Testing conversion with -n succeeds with a target file =="
-rm -f $TEST_IMG.orig
-cp $TEST_IMG $TEST_IMG.orig
-if ! $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n $TEST_IMG $TEST_IMG.orig ; then
+rm -f "$TEST_IMG.orig"
+cp "$TEST_IMG" "$TEST_IMG.orig"
+if ! $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG.orig" ; then
     exit 1
 fi
 
 echo "== Testing conversion to raw is the same after conversion with -n =="
 # compare the raw files
-if ! $QEMU_IMG convert -f $IMGFMT -O raw $TEST_IMG $TEST_IMG.raw1 ; then
+if ! $QEMU_IMG convert -f $IMGFMT -O raw "$TEST_IMG" "$TEST_IMG.raw1" ; then
     exit 1
 fi
 
-if ! $QEMU_IMG convert -f $IMGFMT -O raw $TEST_IMG.orig $TEST_IMG.raw2 ; then
+if ! $QEMU_IMG convert -f $IMGFMT -O raw "$TEST_IMG.orig" "$TEST_IMG.raw2" ; then
     exit 1
 fi
 
-if ! cmp $TEST_IMG.raw1 $TEST_IMG.raw2 ; then
+if ! cmp "$TEST_IMG.raw1" "$TEST_IMG.raw2" ; then
     exit 1
 fi
 
 echo "== Testing conversion back to original format =="
-if ! $QEMU_IMG convert -f raw -O $IMGFMT -n $TEST_IMG.raw2 $TEST_IMG ; then
+if ! $QEMU_IMG convert -f raw -O $IMGFMT -n "$TEST_IMG.raw2" "$TEST_IMG" ; then
     exit 1
 fi
 _check_test_img
 
 echo "== Testing conversion to a smaller file fails =="
-rm -f $TEST_IMG.orig
-mv $TEST_IMG $TEST_IMG.orig
+rm -f "$TEST_IMG.orig"
+mv "$TEST_IMG" "$TEST_IMG.orig"
 _make_test_img 2M
-if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n $TEST_IMG.orig $TEST_IMG >/dev/null 2>&1; then
+if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG.orig" "$TEST_IMG" >/dev/null 2>&1; then
     exit 1
 fi
 
-rm -f $TEST_IMG.orig $TEST_IMG.raw $TEST_IMG.raw2
+rm -f "$TEST_IMG.orig" "$TEST_IMG.raw" "$TEST_IMG.raw2"
 
 echo "*** done"
 rm -f $seq.full
index d794e62..d90a8bc 100644 (file)
@@ -125,6 +125,17 @@ fi
 
 export TEST_DIR
 
+if [ -z "$SAMPLE_IMG_DIR" ]; then
+        SAMPLE_IMG_DIR=`pwd`/sample_images
+fi
+
+if [ ! -d "$SAMPLE_IMG_DIR" ]; then
+    echo "common.config: Error: \$SAMPLE_IMG_DIR ($SAMPLE_IMG_DIR) is not a directory"
+    exit 1
+fi
+
+export SAMPLE_IMG_DIR
+
 _readlink()
 {
     if [ $# -ne 1 ]; then
index 28b39e4..1b22db0 100644 (file)
@@ -91,6 +91,18 @@ _set_default_imgopts()
     fi
 }
 
+_use_sample_img()
+{
+    SAMPLE_IMG_FILE="${1%\.bz2}"
+    TEST_IMG="$TEST_DIR/$SAMPLE_IMG_FILE"
+    bzcat "$SAMPLE_IMG_DIR/$1" > "$TEST_IMG"
+    if [ $? -ne 0 ]
+    then
+        echo "_use_sample_img error, cannot extract '$SAMPLE_IMG_DIR/$1'"
+        exit 1
+    fi
+}
+
 _make_test_img()
 {
     # extra qemu-img options can be added by tests
@@ -152,20 +164,24 @@ _cleanup_test_img()
 
         nbd)
             kill $QEMU_NBD_PID
-            rm -f $TEST_IMG_FILE
+            rm -f "$TEST_IMG_FILE"
             ;;
         file)
-            rm -f $TEST_DIR/t.$IMGFMT
-            rm -f $TEST_DIR/t.$IMGFMT.orig
-            rm -f $TEST_DIR/t.$IMGFMT.base
+            rm -f "$TEST_DIR/t.$IMGFMT"
+            rm -f "$TEST_DIR/t.$IMGFMT.orig"
+            rm -f "$TEST_DIR/t.$IMGFMT.base"
+            if [ -n "$SAMPLE_IMG_FILE" ]
+            then
+                rm -f "$TEST_DIR/$SAMPLE_IMG_FILE"
+            fi
             ;;
 
         rbd)
-            rbd rm $TEST_DIR/t.$IMGFMT > /dev/null
+            rbd rm "$TEST_DIR/t.$IMGFMT" > /dev/null
             ;;
 
         sheepdog)
-            collie vdi delete $TEST_DIR/t.$IMGFMT
+            collie vdi delete "$TEST_DIR/t.$IMGFMT"
             ;;
 
     esac
@@ -173,7 +189,7 @@ _cleanup_test_img()
 
 _check_test_img()
 {
-    $QEMU_IMG check "$@" -f $IMGFMT $TEST_IMG 2>&1 | _filter_testdir | \
+    $QEMU_IMG check "$@" -f $IMGFMT "$TEST_IMG" 2>&1 | _filter_testdir | \
         sed -e '/allocated.*fragmented.*compressed clusters/d' \
             -e 's/qemu-img: This image format does not support checks/No errors were found on the image./' \
             -e '/Image end offset: [0-9]\+/d'
@@ -181,7 +197,7 @@ _check_test_img()
 
 _img_info()
 {
-    $QEMU_IMG info "$@" $TEST_IMG 2>&1 | \
+    $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" \
index 87b4a3a..376d6e8 100644 (file)
@@ -21,7 +21,7 @@ import re
 import subprocess
 import string
 import unittest
-import sys; sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'QMP'))
+import sys; sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'scripts', 'qmp'))
 import qmp
 import struct
 
diff --git a/tests/qemu-iotests/sample_images/README b/tests/qemu-iotests/sample_images/README
new file mode 100644 (file)
index 0000000..507af5f
--- /dev/null
@@ -0,0 +1,8 @@
+This is for small sample images to be used with qemu-iotests, intended for
+non-native formats that QEMU supports for compatibility.  The idea is to use
+the native tool to create the sample image.
+
+For instance, a VHDX image in this directory would be an image created not by
+QEMU itself, but rather created by Hyper-V.
+
+Sample images added here must be compressed with bzip2.
index 253bc3d..e00a44c 100644 (file)
@@ -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;
index 983b7a2..776ccfa 100644 (file)
@@ -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);
index f0c6962..623219e 100644 (file)
@@ -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;
 
index 095716e..6b97dc1 100644 (file)
@@ -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) {
diff --git a/vl.c b/vl.c
index 4e709d5..7e1f408 100644 (file)
--- 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;
@@ -1718,14 +1719,14 @@ static pid_t shutdown_pid;
 static int powerdown_requested;
 static int debug_requested;
 static int suspend_requested;
-static int wakeup_requested;
+static WakeupReason wakeup_reason;
 static NotifierList powerdown_notifiers =
     NOTIFIER_LIST_INITIALIZER(powerdown_notifiers);
 static NotifierList suspend_notifiers =
     NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
 static NotifierList wakeup_notifiers =
     NOTIFIER_LIST_INITIALIZER(wakeup_notifiers);
-static uint32_t wakeup_reason_mask = ~0;
+static uint32_t wakeup_reason_mask = ~(1 << QEMU_WAKEUP_REASON_NONE);
 static RunState vmstop_requested = RUN_STATE_MAX;
 
 int qemu_shutdown_requested_get(void)
@@ -1775,11 +1776,9 @@ static int qemu_suspend_requested(void)
     return r;
 }
 
-static int qemu_wakeup_requested(void)
+static WakeupReason qemu_wakeup_requested(void)
 {
-    int r = wakeup_requested;
-    wakeup_requested = 0;
-    return r;
+    return wakeup_reason;
 }
 
 static int qemu_powerdown_requested(void)
@@ -1896,8 +1895,7 @@ void qemu_system_wakeup_request(WakeupReason reason)
         return;
     }
     runstate_set(RUN_STATE_RUNNING);
-    notifier_list_notify(&wakeup_notifiers, &reason);
-    wakeup_requested = 1;
+    wakeup_reason = reason;
     qemu_notify_event();
 }
 
@@ -1989,6 +1987,8 @@ static bool main_loop_should_exit(void)
         pause_all_vcpus();
         cpu_synchronize_all_states();
         qemu_system_reset(VMRESET_SILENT);
+        notifier_list_notify(&wakeup_notifiers, &wakeup_reason);
+        wakeup_reason = QEMU_WAKEUP_REASON_NONE;
         resume_all_vcpus();
         monitor_protocol_event(QEVENT_WAKEUP, NULL);
     }
@@ -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;
@@ -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");
@@ -3587,6 +3588,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) {
@@ -4048,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;
index 839f14f..9a27899 100644 (file)
--- a/xen-all.c
+++ b/xen-all.c
@@ -98,6 +98,7 @@ typedef struct XenIOState {
 
     Notifier exit;
     Notifier suspend;
+    Notifier wakeup;
 } XenIOState;
 
 /* Xen specific function for piix pci */
@@ -613,13 +614,13 @@ static ioreq_t *cpu_get_ioreq(XenIOState *state)
     }
 
     if (port != -1) {
-        for (i = 0; i < smp_cpus; i++) {
+        for (i = 0; i < max_cpus; i++) {
             if (state->ioreq_local_port[i] == port) {
                 break;
             }
         }
 
-        if (i == smp_cpus) {
+        if (i == max_cpus) {
             hw_error("Fatal error while trying to get io event!\n");
         }
 
@@ -948,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);
@@ -1060,6 +1061,11 @@ static void xen_read_physmap(XenIOState *state)
     free(entries);
 }
 
+static void xen_wakeup_notifier(Notifier *notifier, void *data)
+{
+    xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 0);
+}
+
 int xen_hvm_init(MemoryRegion **ram_memory)
 {
     int i, rc;
@@ -1089,6 +1095,9 @@ int xen_hvm_init(MemoryRegion **ram_memory)
     state->suspend.notify = xen_suspend_notifier;
     qemu_register_suspend_notifier(&state->suspend);
 
+    state->wakeup.notify = xen_wakeup_notifier;
+    qemu_register_wakeup_notifier(&state->wakeup);
+
     xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn);
     DPRINTF("shared page at pfn %lx\n", ioreq_pfn);
     state->shared_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
@@ -1106,10 +1115,10 @@ int xen_hvm_init(MemoryRegion **ram_memory)
         hw_error("map buffered IO page returned error %d", errno);
     }
 
-    state->ioreq_local_port = g_malloc0(smp_cpus * sizeof (evtchn_port_t));
+    state->ioreq_local_port = g_malloc0(max_cpus * sizeof (evtchn_port_t));
 
     /* FIXME: how about if we overflow the page here? */
-    for (i = 0; i < smp_cpus; i++) {
+    for (i = 0; i < max_cpus; i++) {
         rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
                                         xen_vcpu_eport(state->shared_page, i));
         if (rc == -1) {