[Spice-commits] 121 commits - MAINTAINERS Makefile backends/rng.c configure disas/i386.c docs/qmp docs/specs exec.c hw/acpi hw/arm hw/display hw/i386 hw/ide hw/intc hw/misc hw/net hw/pci hw/virtio hw/xen include/exec include/hw include/qemu include/qom include/sysemu kvm-all.c linux-user/s390x linux-user/syscall.c monitor.c net/net.c net/tap-linux.c pc-bios/kvmvapic.bin pc-bios/multiboot.bin pc-bios/sgabios.bin qmp.c qom/Makefile.objs qom/object_interfaces.c scripts/create_config scripts/dump-guest-memory.py scripts/tracetool target-arm/cpu.c target-arm/cpu.h target-arm/helper-a64.c target-arm/helper-a64.h target-arm/helper.c target-arm/helper.h target-arm/translate-a64.c target-arm/translate.c tcg/i386 tcg/tcg.c tests/acpi-test-data tests/acpi-test.c trace/simple.c translate-all.c vl.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Mon Feb 3 07:05:56 PST 2014


 MAINTAINERS                                  |    1 
 Makefile                                     |    2 
 backends/rng.c                               |   17 
 configure                                    |    4 
 disas/i386.c                                 |    8 
 docs/qmp/qmp-events.txt                      |    2 
 docs/specs/acpi_cpu_hotplug.txt              |    4 
 exec.c                                       |    6 
 hw/acpi/Makefile.objs                        |    3 
 hw/acpi/cpu_hotplug.c                        |   64 
 hw/acpi/ich9.c                               |   14 
 hw/acpi/pcihp.c                              |  316 +++
 hw/acpi/piix4.c                              |  155 -
 hw/arm/boot.c                                |    9 
 hw/arm/xilinx_zynq.c                         |    7 
 hw/display/blizzard_template.h               |   40 
 hw/display/pl110_template.h                  |   12 
 hw/display/pxa2xx_template.h                 |   22 
 hw/display/tc6393xb_template.h               |   14 
 hw/display/xenfb.c                           |    7 
 hw/i386/Makefile.objs                        |    2 
 hw/i386/acpi-build.c                         |  364 ++-
 hw/i386/acpi-dsdt-cpu-hotplug.dsl            |   14 
 hw/i386/acpi-dsdt-isa.dsl                    |   11 
 hw/i386/acpi-dsdt-pci-crs.dsl                |   15 
 hw/i386/acpi-dsdt.dsl                        |   76 
 hw/i386/acpi-dsdt.hex.generated              |  217 +-
 hw/i386/pc.c                                 |    1 
 hw/i386/pc_q35.c                             |   20 
 hw/i386/q35-acpi-dsdt.dsl                    |   19 
 hw/i386/q35-acpi-dsdt.hex.generated          |   74 
 hw/i386/ssdt-pcihp.dsl                       |   11 
 hw/i386/ssdt-pcihp.hex.generated             |   20 
 hw/i386/ssdt-proc.hex.generated              |    6 
 hw/ide/core.c                                |    1 
 hw/intc/arm_gic.c                            |   21 
 hw/misc/applesmc.c                           |    1 
 hw/misc/vfio.c                               |   78 
 hw/net/lan9118.c                             |    6 
 hw/net/vhost_net.c                           |    2 
 hw/pci/pci.c                                 |   48 
 hw/virtio/virtio-balloon.c                   |    7 
 hw/virtio/virtio-rng.c                       |   15 
 hw/xen/xen_pt.c                              |    8 
 include/exec/exec-all.h                      |    1 
 include/exec/ram_addr.h                      |    2 
 include/hw/acpi/cpu_hotplug.h                |   27 
 include/hw/acpi/cpu_hotplug_defs.h           |   24 
 include/hw/acpi/ich9.h                       |    4 
 include/hw/acpi/pcihp.h                      |   72 
 include/hw/i386/pc.h                         |    7 
 include/hw/intc/arm_gic_common.h             |    1 
 include/hw/isa/isa.h                         |    7 
 include/hw/pci/pci.h                         |   14 
 include/qemu/timer.h                         |    6 
 include/qom/object_interfaces.h              |   62 
 include/sysemu/rng.h                         |   11 
 kvm-all.c                                    |    1 
 linux-user/s390x/syscall.h                   |    2 
 linux-user/syscall.c                         |    4 
 monitor.c                                    |    4 
 net/net.c                                    |    5 
 net/tap-linux.c                              |   14 
 qmp.c                                        |   22 
 qom/Makefile.objs                            |    1 
 qom/object_interfaces.c                      |   32 
 scripts/create_config                        |    4 
 scripts/dump-guest-memory.py                 |  339 +++
 scripts/tracetool/backend/simple.py          |    6 
 target-arm/cpu.c                             |    1 
 target-arm/cpu.h                             |    2 
 target-arm/helper-a64.c                      |   31 
 target-arm/helper-a64.h                      |    1 
 target-arm/helper.c                          |   45 
 target-arm/helper.h                          |    1 
 target-arm/translate-a64.c                   | 2707 ++++++++++++++++++++++++++-
 target-arm/translate.c                       |  251 ++
 tcg/i386/tcg-target.c                        |  145 -
 tcg/tcg.c                                    |    2 
 tests/acpi-test-data/pc/APIC                 |binary
 tests/acpi-test-data/pc/DSDT                 |binary
 tests/acpi-test-data/pc/FACP                 |binary
 tests/acpi-test-data/pc/FACS                 |binary
 tests/acpi-test-data/pc/HPET                 |binary
 tests/acpi-test-data/pc/SSDT                 |binary
 tests/acpi-test-data/q35/APIC                |binary
 tests/acpi-test-data/q35/DSDT                |binary
 tests/acpi-test-data/q35/FACP                |binary
 tests/acpi-test-data/q35/FACS                |binary
 tests/acpi-test-data/q35/HPET                |binary
 tests/acpi-test-data/q35/MCFG                |binary
 tests/acpi-test-data/q35/SSDT                |binary
 tests/acpi-test-data/rebuild-expected-aml.sh |   36 
 tests/acpi-test.c                            |  305 ++-
 trace/simple.c                               |   24 
 translate-all.c                              |   14 
 vl.c                                         |   36 
 97 files changed, 5464 insertions(+), 553 deletions(-)

New commits:
commit 2f61120c10da9128357510debc8e66880cd2bfdc
Merge: b4a8c9a 056f49f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sat Feb 1 23:32:23 2014 +0000

    Merge remote-tracking branch 'qmp-unstable/queue/qmp' into staging
    
    * qmp-unstable/queue/qmp:
      monitor: Cleanup mon->outbuf on write error
      virtio_rng: replace custom backend API with UserCreatable.complete() callback
      add optional 2nd stage initialization to -object/object-add commands
      vl.c: -object: don't ignore duplicate 'id'
      object_add: consolidate error handling
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit b4a8c9ae9758efb6873097f415e9972127ccf418
Merge: 850bbe1 5b0adce
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sat Feb 1 23:06:11 2014 +0000

    Merge remote-tracking branch 'pmaydell/tags/pull-target-arm-20140131' into staging
    
    target-arm queue:
     * implementation of first part of the A64 Neon instruction set
     * v8 AArch32 rounding and 16<->64 fp conversion instructions
     * fix MIDR value on Zynq boards
     * some minor bugfixes/code cleanups
    
    # gpg: Signature made Fri 31 Jan 2014 15:06:34 GMT using RSA key ID 14360CDE
    # gpg: Good signature from "Peter Maydell <peter.maydell at linaro.org>"
    
    * pmaydell/tags/pull-target-arm-20140131: (34 commits)
      arm_gic: Fix GICD_ICPENDR and GICD_ISPENDR writes
      arm_gic: Introduce define for GIC_NR_SGIS
      target-arm: A64: Add SIMD shift by immediate
      target-arm: A64: Add simple SIMD 3-same floating point ops
      target-arm: A64: Add integer ops from SIMD 3-same group
      target-arm: A64: Add logic ops from SIMD 3 same group
      target-arm: A64: Add top level decode for SIMD 3-same group
      target-arm: A64: Add SIMD scalar 3 same add, sub and compare ops
      target-arm: A64: Add SIMD three-different ABDL instructions
      target-arm: A64: Add SIMD three-different multiply accumulate insns
      target-arm: Add AArch32 SIMD VCVTA, VCVTN, VCVTP and VCVTM
      target-arm: Add AArch32 FP VCVTA, VCVTN, VCVTP and VCVTM
      target-arm: Add AArch32 SIMD VRINTA, VRINTN, VRINTP, VRINTM, VRINTZ
      target-arm: Add set_neon_rmode helper
      target-arm: Add support for AArch32 SIMD VRINTX
      target-arm: Add support for AArch32 FP VRINTX
      target-arm: Add support for AArch32 FP VRINTZ
      target-arm: Add support for AArch32 FP VRINTR
      target-arm: Add AArch32 FP VRINTA, VRINTN, VRINTP and VRINTM
      target-arm: Move arm_rmode_to_sf to a shared location.
      ...
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit 850bbe1b94445cb84a2f648bc2e8c35ef6188eb4
Merge: bd88091 8b6d140
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sat Feb 1 21:07:59 2014 +0000

    Merge remote-tracking branch 'remotes/awilliam/tags/vfio-pci-for-qemu-20140128.0' into staging
    
    vfio-pci updates include:
     - Destroy MemoryRegions on device teardown
     - Print warnings around PCI option ROM failures
     - Skip bogus mappings from 64bit BAR sizing
     - Act on DMA mapping failures
     - Fix alignment to avoid MSI-X table mapping
     - Fix debug macro typo
    
    # gpg: Signature made Tue 28 Jan 2014 15:27:47 GMT using RSA key ID 3BB08B22
    # gpg: Can't check signature: public key not found
    
    * remotes/awilliam/tags/vfio-pci-for-qemu-20140128.0:
      vfio: correct debug macro typo
      vfio: fix mapping of MSIX bar
      kvm: initialize qemu_host_page_size
      vfio-pci: Fail initfn on DMA mapping errors
      vfio: Filter out bogus mappings
      vfio: Do not reattempt a failed rom read
      vfio: warn if host device rom can't be read
      vfio: Destroy memory regions
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit bd88091cfbc3627ac436b5a554340cd263c93b56
Merge: 89e4a51 360e607
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sat Feb 1 20:43:07 2014 +0000

    Merge remote-tracking branch 'remotes/sstabellini/xen-140130' into staging
    
    * remotes/sstabellini/xen-140130:
      address_space_translate: do not cross page boundaries
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit 5b0adce156216fb24dcc5f1683e8b686f3793fff
Author: Christoffer Dall <christoffer.dall at linaro.org>
Date:   Fri Jan 31 14:47:38 2014 +0000

    arm_gic: Fix GICD_ICPENDR and GICD_ISPENDR writes
    
    Fix two bugs that would allow changing the state of SGIs through the
    ICPENDR and ISPENDRs.
    
    Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 98c6ff5..1c4a114 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -428,7 +428,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
         if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < GIC_NR_SGIS) {
-            irq = 0;
+            value = 0;
         }
 
         for (i = 0; i < 8; i++) {
@@ -441,6 +441,10 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
         irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
         if (irq >= s->num_irq)
             goto bad_reg;
+        if (irq < GIC_NR_SGIS) {
+            value = 0;
+        }
+
         for (i = 0; i < 8; i++) {
             /* ??? This currently clears the pending bit for all CPUs, even
                for per-CPU interrupts.  It's unclear whether this is the
commit 41ab7b55108e2699e7c2e77788465cb52a0b2c08
Author: Christoffer Dall <christoffer.dall at linaro.org>
Date:   Fri Jan 31 14:47:38 2014 +0000

    arm_gic: Introduce define for GIC_NR_SGIS
    
    Instead of hardcoding 16 various places in the code, use a define to
    make it more clear what is going on.
    
    Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 9409684..98c6ff5 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -380,8 +380,10 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
         irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
         if (irq >= s->num_irq)
             goto bad_reg;
-        if (irq < 16)
-          value = 0xff;
+        if (irq < GIC_NR_SGIS) {
+            value = 0xff;
+        }
+
         for (i = 0; i < 8; i++) {
             if (value & (1 << i)) {
                 int mask =
@@ -406,8 +408,10 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
         irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
         if (irq >= s->num_irq)
             goto bad_reg;
-        if (irq < 16)
-          value = 0;
+        if (irq < GIC_NR_SGIS) {
+            value = 0;
+        }
+
         for (i = 0; i < 8; i++) {
             if (value & (1 << i)) {
                 int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
@@ -423,8 +427,9 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
         irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
         if (irq >= s->num_irq)
             goto bad_reg;
-        if (irq < 16)
-          irq = 0;
+        if (irq < GIC_NR_SGIS) {
+            irq = 0;
+        }
 
         for (i = 0; i < 8; i++) {
             if (value & (1 << i)) {
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
index 0d232df..8a2aa00 100644
--- a/include/hw/intc/arm_gic_common.h
+++ b/include/hw/intc/arm_gic_common.h
@@ -27,6 +27,7 @@
 #define GIC_MAXIRQ 1020
 /* First 32 are private to each CPU (SGIs and PPIs). */
 #define GIC_INTERNAL 32
+#define GIC_NR_SGIS 16
 /* Maximum number of possible CPU interfaces, determined by GIC architecture */
 #define GIC_NCPU 8
 
commit 4d1cef840d526c80244175c208260f165f9226db
Author: Alex Bennée <alex.bennee at linaro.org>
Date:   Fri Jan 31 14:47:37 2014 +0000

    target-arm: A64: Add SIMD shift by immediate
    
    This implements a subset of the AdvSIMD shift operations (namely all the
    none saturating or narrowing ones). The actual shift generation code
    itself is common for both the scalar and vector cases but wrapped with
    either vector element iteration or the fp reg access.
    
    The rounding operations need to take special care to correctly reflect
    the result of adding rounding bits on high bits as the intermediates do
    not truncate.
    
    Signed-off-by: Alex Bennée <alex.bennee at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 509982c..6c1ec1e 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -5503,15 +5503,216 @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
     unsupported_encoding(s, insn);
 }
 
+/*
+ * Common SSHR[RA]/USHR[RA] - Shift right (optional rounding/accumulate)
+ *
+ * This code is handles the common shifting code and is used by both
+ * the vector and scalar code.
+ */
+static void handle_shri_with_rndacc(TCGv_i64 tcg_res, TCGv_i64 tcg_src,
+                                    TCGv_i64 tcg_rnd, bool accumulate,
+                                    bool is_u, int size, int shift)
+{
+    bool extended_result = false;
+    bool round = !TCGV_IS_UNUSED_I64(tcg_rnd);
+    int ext_lshift = 0;
+    TCGv_i64 tcg_src_hi;
+
+    if (round && size == 3) {
+        extended_result = true;
+        ext_lshift = 64 - shift;
+        tcg_src_hi = tcg_temp_new_i64();
+    } else if (shift == 64) {
+        if (!accumulate && is_u) {
+            /* result is zero */
+            tcg_gen_movi_i64(tcg_res, 0);
+            return;
+        }
+    }
+
+    /* Deal with the rounding step */
+    if (round) {
+        if (extended_result) {
+            TCGv_i64 tcg_zero = tcg_const_i64(0);
+            if (!is_u) {
+                /* take care of sign extending tcg_res */
+                tcg_gen_sari_i64(tcg_src_hi, tcg_src, 63);
+                tcg_gen_add2_i64(tcg_src, tcg_src_hi,
+                                 tcg_src, tcg_src_hi,
+                                 tcg_rnd, tcg_zero);
+            } else {
+                tcg_gen_add2_i64(tcg_src, tcg_src_hi,
+                                 tcg_src, tcg_zero,
+                                 tcg_rnd, tcg_zero);
+            }
+            tcg_temp_free_i64(tcg_zero);
+        } else {
+            tcg_gen_add_i64(tcg_src, tcg_src, tcg_rnd);
+        }
+    }
+
+    /* Now do the shift right */
+    if (round && extended_result) {
+        /* extended case, >64 bit precision required */
+        if (ext_lshift == 0) {
+            /* special case, only high bits matter */
+            tcg_gen_mov_i64(tcg_src, tcg_src_hi);
+        } else {
+            tcg_gen_shri_i64(tcg_src, tcg_src, shift);
+            tcg_gen_shli_i64(tcg_src_hi, tcg_src_hi, ext_lshift);
+            tcg_gen_or_i64(tcg_src, tcg_src, tcg_src_hi);
+        }
+    } else {
+        if (is_u) {
+            if (shift == 64) {
+                /* essentially shifting in 64 zeros */
+                tcg_gen_movi_i64(tcg_src, 0);
+            } else {
+                tcg_gen_shri_i64(tcg_src, tcg_src, shift);
+            }
+        } else {
+            if (shift == 64) {
+                /* effectively extending the sign-bit */
+                tcg_gen_sari_i64(tcg_src, tcg_src, 63);
+            } else {
+                tcg_gen_sari_i64(tcg_src, tcg_src, shift);
+            }
+        }
+    }
+
+    if (accumulate) {
+        tcg_gen_add_i64(tcg_res, tcg_res, tcg_src);
+    } else {
+        tcg_gen_mov_i64(tcg_res, tcg_src);
+    }
+
+    if (extended_result) {
+        tcg_temp_free_i64(tcg_src_hi);
+    }
+}
+
+/* Common SHL/SLI - Shift left with an optional insert */
+static void handle_shli_with_ins(TCGv_i64 tcg_res, TCGv_i64 tcg_src,
+                                 bool insert, int shift)
+{
+    if (insert) { /* SLI */
+        tcg_gen_deposit_i64(tcg_res, tcg_res, tcg_src, shift, 64 - shift);
+    } else { /* SHL */
+        tcg_gen_shli_i64(tcg_res, tcg_src, shift);
+    }
+}
+
+/* SSHR[RA]/USHR[RA] - Scalar shift right (optional rounding/accumulate) */
+static void handle_scalar_simd_shri(DisasContext *s,
+                                    bool is_u, int immh, int immb,
+                                    int opcode, int rn, int rd)
+{
+    const int size = 3;
+    int immhb = immh << 3 | immb;
+    int shift = 2 * (8 << size) - immhb;
+    bool accumulate = false;
+    bool round = false;
+    TCGv_i64 tcg_rn;
+    TCGv_i64 tcg_rd;
+    TCGv_i64 tcg_round;
+
+    if (!extract32(immh, 3, 1)) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    switch (opcode) {
+    case 0x02: /* SSRA / USRA (accumulate) */
+        accumulate = true;
+        break;
+    case 0x04: /* SRSHR / URSHR (rounding) */
+        round = true;
+        break;
+    case 0x06: /* SRSRA / URSRA (accum + rounding) */
+        accumulate = round = true;
+        break;
+    }
+
+    if (round) {
+        uint64_t round_const = 1ULL << (shift - 1);
+        tcg_round = tcg_const_i64(round_const);
+    } else {
+        TCGV_UNUSED_I64(tcg_round);
+    }
+
+    tcg_rn = read_fp_dreg(s, rn);
+    tcg_rd = accumulate ? read_fp_dreg(s, rd) : tcg_temp_new_i64();
+
+    handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
+                               accumulate, is_u, size, shift);
+
+    write_fp_dreg(s, rd, tcg_rd);
+
+    tcg_temp_free_i64(tcg_rn);
+    tcg_temp_free_i64(tcg_rd);
+    if (round) {
+        tcg_temp_free_i64(tcg_round);
+    }
+}
+
+/* SHL/SLI - Scalar shift left */
+static void handle_scalar_simd_shli(DisasContext *s, bool insert,
+                                    int immh, int immb, int opcode,
+                                    int rn, int rd)
+{
+    int size = 32 - clz32(immh) - 1;
+    int immhb = immh << 3 | immb;
+    int shift = immhb - (8 << size);
+    TCGv_i64 tcg_rn = new_tmp_a64(s);
+    TCGv_i64 tcg_rd = new_tmp_a64(s);
+
+    if (!extract32(immh, 3, 1)) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    tcg_rn = read_fp_dreg(s, rn);
+    tcg_rd = insert ? read_fp_dreg(s, rd) : tcg_temp_new_i64();
+
+    handle_shli_with_ins(tcg_rd, tcg_rn, insert, shift);
+
+    write_fp_dreg(s, rd, tcg_rd);
+
+    tcg_temp_free_i64(tcg_rn);
+    tcg_temp_free_i64(tcg_rd);
+}
+
 /* C3.6.9 AdvSIMD scalar shift by immediate
  *  31 30  29 28         23 22  19 18  16 15    11  10 9    5 4    0
  * +-----+---+-------------+------+------+--------+---+------+------+
  * | 0 1 | U | 1 1 1 1 1 0 | immh | immb | opcode | 1 |  Rn  |  Rd  |
  * +-----+---+-------------+------+------+--------+---+------+------+
+ *
+ * This is the scalar version so it works on a fixed sized registers
  */
 static void disas_simd_scalar_shift_imm(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rd = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int opcode = extract32(insn, 11, 5);
+    int immb = extract32(insn, 16, 3);
+    int immh = extract32(insn, 19, 4);
+    bool is_u = extract32(insn, 29, 1);
+
+    switch (opcode) {
+    case 0x00: /* SSHR / USHR */
+    case 0x02: /* SSRA / USRA */
+    case 0x04: /* SRSHR / URSHR */
+    case 0x06: /* SRSRA / URSRA */
+        handle_scalar_simd_shri(s, is_u, immh, immb, opcode, rn, rd);
+        break;
+    case 0x0a: /* SHL / SLI */
+        handle_scalar_simd_shli(s, is_u, immh, immb, opcode, rn, rd);
+        break;
+    default:
+        unsupported_encoding(s, insn);
+        break;
+    }
 }
 
 /* C3.6.10 AdvSIMD scalar three different
@@ -5816,6 +6017,148 @@ static void disas_simd_scalar_indexed(DisasContext *s, uint32_t insn)
     unsupported_encoding(s, insn);
 }
 
+/* SSHR[RA]/USHR[RA] - Vector shift right (optional rounding/accumulate) */
+static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
+                                 int immh, int immb, int opcode, int rn, int rd)
+{
+    int size = 32 - clz32(immh) - 1;
+    int immhb = immh << 3 | immb;
+    int shift = 2 * (8 << size) - immhb;
+    bool accumulate = false;
+    bool round = false;
+    int dsize = is_q ? 128 : 64;
+    int esize = 8 << size;
+    int elements = dsize/esize;
+    TCGMemOp memop = size | (is_u ? 0 : MO_SIGN);
+    TCGv_i64 tcg_rn = new_tmp_a64(s);
+    TCGv_i64 tcg_rd = new_tmp_a64(s);
+    TCGv_i64 tcg_round;
+    int i;
+
+    if (extract32(immh, 3, 1) && !is_q) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    if (size > 3 && !is_q) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    switch (opcode) {
+    case 0x02: /* SSRA / USRA (accumulate) */
+        accumulate = true;
+        break;
+    case 0x04: /* SRSHR / URSHR (rounding) */
+        round = true;
+        break;
+    case 0x06: /* SRSRA / URSRA (accum + rounding) */
+        accumulate = round = true;
+        break;
+    }
+
+    if (round) {
+        uint64_t round_const = 1ULL << (shift - 1);
+        tcg_round = tcg_const_i64(round_const);
+    } else {
+        TCGV_UNUSED_I64(tcg_round);
+    }
+
+    for (i = 0; i < elements; i++) {
+        read_vec_element(s, tcg_rn, rn, i, memop);
+        if (accumulate) {
+            read_vec_element(s, tcg_rd, rd, i, memop);
+        }
+
+        handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
+                                accumulate, is_u, size, shift);
+
+        write_vec_element(s, tcg_rd, rd, i, size);
+    }
+
+    if (!is_q) {
+        clear_vec_high(s, rd);
+    }
+
+    if (round) {
+        tcg_temp_free_i64(tcg_round);
+    }
+}
+
+/* SHL/SLI - Vector shift left */
+static void handle_vec_simd_shli(DisasContext *s, bool is_q, bool insert,
+                                int immh, int immb, int opcode, int rn, int rd)
+{
+    int size = 32 - clz32(immh) - 1;
+    int immhb = immh << 3 | immb;
+    int shift = immhb - (8 << size);
+    int dsize = is_q ? 128 : 64;
+    int esize = 8 << size;
+    int elements = dsize/esize;
+    TCGv_i64 tcg_rn = new_tmp_a64(s);
+    TCGv_i64 tcg_rd = new_tmp_a64(s);
+    int i;
+
+    if (extract32(immh, 3, 1) && !is_q) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    if (size > 3 && !is_q) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    for (i = 0; i < elements; i++) {
+        read_vec_element(s, tcg_rn, rn, i, size);
+        if (insert) {
+            read_vec_element(s, tcg_rd, rd, i, size);
+        }
+
+        handle_shli_with_ins(tcg_rd, tcg_rn, insert, shift);
+
+        write_vec_element(s, tcg_rd, rd, i, size);
+    }
+
+    if (!is_q) {
+        clear_vec_high(s, rd);
+    }
+}
+
+/* USHLL/SHLL - Vector shift left with widening */
+static void handle_vec_simd_wshli(DisasContext *s, bool is_q, bool is_u,
+                                 int immh, int immb, int opcode, int rn, int rd)
+{
+    int size = 32 - clz32(immh) - 1;
+    int immhb = immh << 3 | immb;
+    int shift = immhb - (8 << size);
+    int dsize = 64;
+    int esize = 8 << size;
+    int elements = dsize/esize;
+    TCGv_i64 tcg_rn = new_tmp_a64(s);
+    TCGv_i64 tcg_rd = new_tmp_a64(s);
+    int i;
+
+    if (size >= 3) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    /* For the LL variants the store is larger than the load,
+     * so if rd == rn we would overwrite parts of our input.
+     * So load everything right now and use shifts in the main loop.
+     */
+    read_vec_element(s, tcg_rn, rn, is_q ? 1 : 0, MO_64);
+
+    for (i = 0; i < elements; i++) {
+        tcg_gen_shri_i64(tcg_rd, tcg_rn, i * esize);
+        ext_and_shift_reg(tcg_rd, tcg_rd, size | (!is_u << 2), 0);
+        tcg_gen_shli_i64(tcg_rd, tcg_rd, shift);
+        write_vec_element(s, tcg_rd, rd, i, size + 1);
+    }
+}
+
+
 /* C3.6.14 AdvSIMD shift by immediate
  *  31  30   29 28         23 22  19 18  16 15    11  10 9    5 4    0
  * +---+---+---+-------------+------+------+--------+---+------+------+
@@ -5824,7 +6167,35 @@ static void disas_simd_scalar_indexed(DisasContext *s, uint32_t insn)
  */
 static void disas_simd_shift_imm(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rd = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int opcode = extract32(insn, 11, 5);
+    int immb = extract32(insn, 16, 3);
+    int immh = extract32(insn, 19, 4);
+    bool is_u = extract32(insn, 29, 1);
+    bool is_q = extract32(insn, 30, 1);
+
+    switch (opcode) {
+    case 0x00: /* SSHR / USHR */
+    case 0x02: /* SSRA / USRA (accumulate) */
+    case 0x04: /* SRSHR / URSHR (rounding) */
+    case 0x06: /* SRSRA / URSRA (accum + rounding) */
+        handle_vec_simd_shri(s, is_q, is_u, immh, immb, opcode, rn, rd);
+        break;
+    case 0x0a: /* SHL / SLI */
+        handle_vec_simd_shli(s, is_q, is_u, immh, immb, opcode, rn, rd);
+        break;
+    case 0x14: /* SSHLL / USHLL */
+        handle_vec_simd_wshli(s, is_q, is_u, immh, immb, opcode, rn, rd);
+        break;
+    default:
+        /* We don't currently implement any of the Narrow or saturating shifts;
+         * nor do we implement the fixed-point conversions in this
+         * encoding group (SCVTF, FCVTZS, UCVTF, FCVTZU).
+         */
+        unsupported_encoding(s, insn);
+        return;
+    }
 }
 
 static void handle_3rd_widening(DisasContext *s, int is_q, int is_u, int size,
commit 845ea09acc4b5ab8335530aaaf94531c368ba934
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jan 31 14:47:37 2014 +0000

    target-arm: A64: Add simple SIMD 3-same floating point ops
    
    Implement a simple subset of the SIMD 3-same floating point
    operations. This includes a common helper function used for both
    scalar and vector ops; FABD is the only currently implemented
    shared op.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 9e7401c..509982c 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -5577,6 +5577,131 @@ static void handle_3same_64(DisasContext *s, int opcode, bool u,
     }
 }
 
+/* Handle the 3-same-operands float operations; shared by the scalar
+ * and vector encodings. The caller must filter out any encodings
+ * not allocated for the encoding it is dealing with.
+ */
+static void handle_3same_float(DisasContext *s, int size, int elements,
+                               int fpopcode, int rd, int rn, int rm)
+{
+    int pass;
+    TCGv_ptr fpst = get_fpstatus_ptr();
+
+    for (pass = 0; pass < elements; pass++) {
+        if (size) {
+            /* Double */
+            TCGv_i64 tcg_op1 = tcg_temp_new_i64();
+            TCGv_i64 tcg_op2 = tcg_temp_new_i64();
+            TCGv_i64 tcg_res = tcg_temp_new_i64();
+
+            read_vec_element(s, tcg_op1, rn, pass, MO_64);
+            read_vec_element(s, tcg_op2, rm, pass, MO_64);
+
+            switch (fpopcode) {
+            case 0x18: /* FMAXNM */
+                gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
+                break;
+            case 0x1a: /* FADD */
+                gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
+                break;
+            case 0x1e: /* FMAX */
+                gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
+                break;
+            case 0x38: /* FMINNM */
+                gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
+                break;
+            case 0x3a: /* FSUB */
+                gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
+                break;
+            case 0x3e: /* FMIN */
+                gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
+                break;
+            case 0x5b: /* FMUL */
+                gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
+                break;
+            case 0x5f: /* FDIV */
+                gen_helper_vfp_divd(tcg_res, tcg_op1, tcg_op2, fpst);
+                break;
+            case 0x7a: /* FABD */
+                gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
+                gen_helper_vfp_absd(tcg_res, tcg_res);
+                break;
+            default:
+                g_assert_not_reached();
+            }
+
+            write_vec_element(s, tcg_res, rd, pass, MO_64);
+
+            tcg_temp_free_i64(tcg_res);
+            tcg_temp_free_i64(tcg_op1);
+            tcg_temp_free_i64(tcg_op2);
+        } else {
+            /* Single */
+            TCGv_i32 tcg_op1 = tcg_temp_new_i32();
+            TCGv_i32 tcg_op2 = tcg_temp_new_i32();
+            TCGv_i32 tcg_res = tcg_temp_new_i32();
+
+            read_vec_element_i32(s, tcg_op1, rn, pass, MO_32);
+            read_vec_element_i32(s, tcg_op2, rm, pass, MO_32);
+
+            switch (fpopcode) {
+            case 0x1a: /* FADD */
+                gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
+                break;
+            case 0x1e: /* FMAX */
+                gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
+                break;
+            case 0x18: /* FMAXNM */
+                gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
+                break;
+            case 0x38: /* FMINNM */
+                gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
+                break;
+            case 0x3a: /* FSUB */
+                gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
+                break;
+            case 0x3e: /* FMIN */
+                gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
+                break;
+            case 0x5b: /* FMUL */
+                gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
+                break;
+            case 0x5f: /* FDIV */
+                gen_helper_vfp_divs(tcg_res, tcg_op1, tcg_op2, fpst);
+                break;
+            case 0x7a: /* FABD */
+                gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
+                gen_helper_vfp_abss(tcg_res, tcg_res);
+                break;
+            default:
+                g_assert_not_reached();
+            }
+
+            if (elements == 1) {
+                /* scalar single so clear high part */
+                TCGv_i64 tcg_tmp = tcg_temp_new_i64();
+
+                tcg_gen_extu_i32_i64(tcg_tmp, tcg_res);
+                write_vec_element(s, tcg_tmp, rd, pass, MO_64);
+                tcg_temp_free_i64(tcg_tmp);
+            } else {
+                write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
+            }
+
+            tcg_temp_free_i32(tcg_res);
+            tcg_temp_free_i32(tcg_op1);
+            tcg_temp_free_i32(tcg_op2);
+        }
+    }
+
+    tcg_temp_free_ptr(fpst);
+
+    if ((elements << size) < 4) {
+        /* scalar, or non-quad vector op */
+        clear_vec_high(s, rd);
+    }
+}
+
 /* C3.6.11 AdvSIMD scalar three same
  *  31 30  29 28       24 23  22  21 20  16 15    11  10 9    5 4    0
  * +-----+---+-----------+------+---+------+--------+---+------+------+
@@ -5605,15 +5730,19 @@ static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn)
         case 0x3f: /* FRSQRTS */
         case 0x5c: /* FCMGE */
         case 0x5d: /* FACGE */
-        case 0x7a: /* FABD  */
         case 0x7c: /* FCMGT */
         case 0x7d: /* FACGT */
             unsupported_encoding(s, insn);
             return;
+        case 0x7a: /* FABD */
+            break;
         default:
             unallocated_encoding(s);
             return;
         }
+
+        handle_3same_float(s, extract32(size, 0, 1), 1, fpopcode, rd, rn, rm);
+        return;
     }
 
     switch (opcode) {
@@ -6028,7 +6157,64 @@ static void disas_simd_3same_pair(DisasContext *s, uint32_t insn)
 /* Floating point op subgroup of C3.6.16. */
 static void disas_simd_3same_float(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    /* For floating point ops, the U, size[1] and opcode bits
+     * together indicate the operation. size[0] indicates single
+     * or double.
+     */
+    int fpopcode = extract32(insn, 11, 5)
+        | (extract32(insn, 23, 1) << 5)
+        | (extract32(insn, 29, 1) << 6);
+    int is_q = extract32(insn, 30, 1);
+    int size = extract32(insn, 22, 1);
+    int rm = extract32(insn, 16, 5);
+    int rn = extract32(insn, 5, 5);
+    int rd = extract32(insn, 0, 5);
+
+    int datasize = is_q ? 128 : 64;
+    int esize = 32 << size;
+    int elements = datasize / esize;
+
+    if (size == 1 && !is_q) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    switch (fpopcode) {
+    case 0x58: /* FMAXNMP */
+    case 0x5a: /* FADDP */
+    case 0x5e: /* FMAXP */
+    case 0x78: /* FMINNMP */
+    case 0x7e: /* FMINP */
+        /* pairwise ops */
+        unsupported_encoding(s, insn);
+        return;
+    case 0x1b: /* FMULX */
+    case 0x1c: /* FCMEQ */
+    case 0x1f: /* FRECPS */
+    case 0x3f: /* FRSQRTS */
+    case 0x5c: /* FCMGE */
+    case 0x5d: /* FACGE */
+    case 0x7c: /* FCMGT */
+    case 0x7d: /* FACGT */
+    case 0x19: /* FMLA */
+    case 0x39: /* FMLS */
+        unsupported_encoding(s, insn);
+        return;
+    case 0x18: /* FMAXNM */
+    case 0x1a: /* FADD */
+    case 0x1e: /* FMAX */
+    case 0x38: /* FMINNM */
+    case 0x3a: /* FSUB */
+    case 0x3e: /* FMIN */
+    case 0x5b: /* FMUL */
+    case 0x5f: /* FDIV */
+    case 0x7a: /* FABD */
+        handle_3same_float(s, size, elements, fpopcode, rd, rn, rm);
+        return;
+    default:
+        unallocated_encoding(s);
+        return;
+    }
 }
 
 /* Integer op subgroup of C3.6.16. */
commit 1f8a73af12ddfb9cf9a90261338b466b7dbf7ab9
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jan 31 14:47:37 2014 +0000

    target-arm: A64: Add integer ops from SIMD 3-same group
    
    Add some of the integer operations in the SIMD 3-same group:
    specifically, the comparisons, addition and subtraction.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index aa53ddc..9e7401c 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -72,6 +72,9 @@ typedef struct AArch64DecodeTable {
     AArch64DecodeFn *disas_fn;
 } AArch64DecodeTable;
 
+/* Function prototype for gen_ functions for calling Neon helpers */
+typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32);
+
 /* initialize TCG globals.  */
 void a64_translate_init(void)
 {
@@ -787,6 +790,25 @@ static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx,
     }
 }
 
+static void write_vec_element_i32(DisasContext *s, TCGv_i32 tcg_src,
+                                  int destidx, int element, TCGMemOp memop)
+{
+    int vect_off = vec_reg_offset(destidx, element, memop & MO_SIZE);
+    switch (memop) {
+    case MO_8:
+        tcg_gen_st8_i32(tcg_src, cpu_env, vect_off);
+        break;
+    case MO_16:
+        tcg_gen_st16_i32(tcg_src, cpu_env, vect_off);
+        break;
+    case MO_32:
+        tcg_gen_st_i32(tcg_src, cpu_env, vect_off);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+}
+
 /* Clear the high 64 bits of a 128 bit vector (in general non-quad
  * vector ops all need to do this).
  */
@@ -6012,7 +6034,148 @@ static void disas_simd_3same_float(DisasContext *s, uint32_t insn)
 /* Integer op subgroup of C3.6.16. */
 static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int is_q = extract32(insn, 30, 1);
+    int u = extract32(insn, 29, 1);
+    int size = extract32(insn, 22, 2);
+    int opcode = extract32(insn, 11, 5);
+    int rm = extract32(insn, 16, 5);
+    int rn = extract32(insn, 5, 5);
+    int rd = extract32(insn, 0, 5);
+    int pass;
+
+    switch (opcode) {
+    case 0x13: /* MUL, PMUL */
+        if (u && size != 0) {
+            unallocated_encoding(s);
+            return;
+        }
+        /* fall through */
+    case 0x0: /* SHADD, UHADD */
+    case 0x2: /* SRHADD, URHADD */
+    case 0x4: /* SHSUB, UHSUB */
+    case 0xc: /* SMAX, UMAX */
+    case 0xd: /* SMIN, UMIN */
+    case 0xe: /* SABD, UABD */
+    case 0xf: /* SABA, UABA */
+    case 0x12: /* MLA, MLS */
+        if (size == 3) {
+            unallocated_encoding(s);
+            return;
+        }
+        unsupported_encoding(s, insn);
+        return;
+    case 0x1: /* SQADD */
+    case 0x5: /* SQSUB */
+    case 0x8: /* SSHL, USHL */
+    case 0x9: /* SQSHL, UQSHL */
+    case 0xa: /* SRSHL, URSHL */
+    case 0xb: /* SQRSHL, UQRSHL */
+        if (size == 3 && !is_q) {
+            unallocated_encoding(s);
+            return;
+        }
+        unsupported_encoding(s, insn);
+        return;
+    case 0x16: /* SQDMULH, SQRDMULH */
+        if (size == 0 || size == 3) {
+            unallocated_encoding(s);
+            return;
+        }
+        unsupported_encoding(s, insn);
+        return;
+    default:
+        if (size == 3 && !is_q) {
+            unallocated_encoding(s);
+            return;
+        }
+        break;
+    }
+
+    if (size == 3) {
+        for (pass = 0; pass < (is_q ? 2 : 1); pass++) {
+            TCGv_i64 tcg_op1 = tcg_temp_new_i64();
+            TCGv_i64 tcg_op2 = tcg_temp_new_i64();
+            TCGv_i64 tcg_res = tcg_temp_new_i64();
+
+            read_vec_element(s, tcg_op1, rn, pass, MO_64);
+            read_vec_element(s, tcg_op2, rm, pass, MO_64);
+
+            handle_3same_64(s, opcode, u, tcg_res, tcg_op1, tcg_op2);
+
+            write_vec_element(s, tcg_res, rd, pass, MO_64);
+
+            tcg_temp_free_i64(tcg_res);
+            tcg_temp_free_i64(tcg_op1);
+            tcg_temp_free_i64(tcg_op2);
+        }
+    } else {
+        for (pass = 0; pass < (is_q ? 4 : 2); pass++) {
+            TCGv_i32 tcg_op1 = tcg_temp_new_i32();
+            TCGv_i32 tcg_op2 = tcg_temp_new_i32();
+            TCGv_i32 tcg_res = tcg_temp_new_i32();
+            NeonGenTwoOpFn *genfn;
+
+            read_vec_element_i32(s, tcg_op1, rn, pass, MO_32);
+            read_vec_element_i32(s, tcg_op2, rm, pass, MO_32);
+
+            switch (opcode) {
+            case 0x6: /* CMGT, CMHI */
+            {
+                static NeonGenTwoOpFn * const fns[3][2] = {
+                    { gen_helper_neon_cgt_s8, gen_helper_neon_cgt_u8 },
+                    { gen_helper_neon_cgt_s16, gen_helper_neon_cgt_u16 },
+                    { gen_helper_neon_cgt_s32, gen_helper_neon_cgt_u32 },
+                };
+                genfn = fns[size][u];
+                break;
+            }
+            case 0x7: /* CMGE, CMHS */
+            {
+                static NeonGenTwoOpFn * const fns[3][2] = {
+                    { gen_helper_neon_cge_s8, gen_helper_neon_cge_u8 },
+                    { gen_helper_neon_cge_s16, gen_helper_neon_cge_u16 },
+                    { gen_helper_neon_cge_s32, gen_helper_neon_cge_u32 },
+                };
+                genfn = fns[size][u];
+                break;
+            }
+            case 0x10: /* ADD, SUB */
+            {
+                static NeonGenTwoOpFn * const fns[3][2] = {
+                    { gen_helper_neon_add_u8, gen_helper_neon_sub_u8 },
+                    { gen_helper_neon_add_u16, gen_helper_neon_sub_u16 },
+                    { tcg_gen_add_i32, tcg_gen_sub_i32 },
+                };
+                genfn = fns[size][u];
+                break;
+            }
+            case 0x11: /* CMTST, CMEQ */
+            {
+                static NeonGenTwoOpFn * const fns[3][2] = {
+                    { gen_helper_neon_tst_u8, gen_helper_neon_ceq_u8 },
+                    { gen_helper_neon_tst_u16, gen_helper_neon_ceq_u16 },
+                    { gen_helper_neon_tst_u32, gen_helper_neon_ceq_u32 },
+                };
+                genfn = fns[size][u];
+                break;
+            }
+            default:
+                g_assert_not_reached();
+            }
+
+            genfn(tcg_res, tcg_op1, tcg_op2);
+
+            write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
+
+            tcg_temp_free_i32(tcg_res);
+            tcg_temp_free_i32(tcg_op1);
+            tcg_temp_free_i32(tcg_op2);
+        }
+    }
+
+    if (!is_q) {
+        clear_vec_high(s, rd);
+    }
 }
 
 /* C3.6.16 AdvSIMD three same
commit 956d272eb2996e4d95f8a674256f8a63a0c1e8d4
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jan 31 14:47:37 2014 +0000

    target-arm: A64: Add logic ops from SIMD 3 same group
    
    Add support for the logical operations (ORR, AND, BIC, ORN, EOR, BSL,
    BIT and BIF) from the SIMD 3 register same group (C3.6.16).
    
    Signed-off-by: Alex Bennée <alex.bennee at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index a215f083..aa53ddc 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -5923,7 +5923,78 @@ static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
 /* Logic op (opcode == 3) subgroup of C3.6.16. */
 static void disas_simd_3same_logic(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rd = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int rm = extract32(insn, 16, 5);
+    int size = extract32(insn, 22, 2);
+    bool is_u = extract32(insn, 29, 1);
+    bool is_q = extract32(insn, 30, 1);
+    TCGv_i64 tcg_op1 = tcg_temp_new_i64();
+    TCGv_i64 tcg_op2 = tcg_temp_new_i64();
+    TCGv_i64 tcg_res[2];
+    int pass;
+
+    tcg_res[0] = tcg_temp_new_i64();
+    tcg_res[1] = tcg_temp_new_i64();
+
+    for (pass = 0; pass < (is_q ? 2 : 1); pass++) {
+        read_vec_element(s, tcg_op1, rn, pass, MO_64);
+        read_vec_element(s, tcg_op2, rm, pass, MO_64);
+
+        if (!is_u) {
+            switch (size) {
+            case 0: /* AND */
+                tcg_gen_and_i64(tcg_res[pass], tcg_op1, tcg_op2);
+                break;
+            case 1: /* BIC */
+                tcg_gen_andc_i64(tcg_res[pass], tcg_op1, tcg_op2);
+                break;
+            case 2: /* ORR */
+                tcg_gen_or_i64(tcg_res[pass], tcg_op1, tcg_op2);
+                break;
+            case 3: /* ORN */
+                tcg_gen_orc_i64(tcg_res[pass], tcg_op1, tcg_op2);
+                break;
+            }
+        } else {
+            if (size != 0) {
+                /* B* ops need res loaded to operate on */
+                read_vec_element(s, tcg_res[pass], rd, pass, MO_64);
+            }
+
+            switch (size) {
+            case 0: /* EOR */
+                tcg_gen_xor_i64(tcg_res[pass], tcg_op1, tcg_op2);
+                break;
+            case 1: /* BSL bitwise select */
+                tcg_gen_xor_i64(tcg_op1, tcg_op1, tcg_op2);
+                tcg_gen_and_i64(tcg_op1, tcg_op1, tcg_res[pass]);
+                tcg_gen_xor_i64(tcg_res[pass], tcg_op2, tcg_op1);
+                break;
+            case 2: /* BIT, bitwise insert if true */
+                tcg_gen_xor_i64(tcg_op1, tcg_op1, tcg_res[pass]);
+                tcg_gen_and_i64(tcg_op1, tcg_op1, tcg_op2);
+                tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
+                break;
+            case 3: /* BIF, bitwise insert if false */
+                tcg_gen_xor_i64(tcg_op1, tcg_op1, tcg_res[pass]);
+                tcg_gen_andc_i64(tcg_op1, tcg_op1, tcg_op2);
+                tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
+                break;
+            }
+        }
+    }
+
+    write_vec_element(s, tcg_res[0], rd, 0, MO_64);
+    if (!is_q) {
+        tcg_gen_movi_i64(tcg_res[1], 0);
+    }
+    write_vec_element(s, tcg_res[1], rd, 1, MO_64);
+
+    tcg_temp_free_i64(tcg_op1);
+    tcg_temp_free_i64(tcg_op2);
+    tcg_temp_free_i64(tcg_res[0]);
+    tcg_temp_free_i64(tcg_res[1]);
 }
 
 /* Pairwise op subgroup of C3.6.16. */
commit e1cea1144aff6498ddbcd60e2bff4172869b10d4
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jan 31 14:47:37 2014 +0000

    target-arm: A64: Add top level decode for SIMD 3-same group
    
    Add top level decode for the A64 SIMD three regs same group
    (C3.6.16), splitting it into the pairwise, logical, float and
    integer subgroups.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index f0ebbb5..a215f083 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -5920,6 +5920,30 @@ static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
     }
 }
 
+/* Logic op (opcode == 3) subgroup of C3.6.16. */
+static void disas_simd_3same_logic(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* Pairwise op subgroup of C3.6.16. */
+static void disas_simd_3same_pair(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* Floating point op subgroup of C3.6.16. */
+static void disas_simd_3same_float(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* Integer op subgroup of C3.6.16. */
+static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
 /* C3.6.16 AdvSIMD three same
  *  31  30  29  28       24 23  22  21 20  16 15    11  10 9    5 4    0
  * +---+---+---+-----------+------+---+------+--------+---+------+------+
@@ -5928,7 +5952,26 @@ static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
  */
 static void disas_simd_three_reg_same(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int opcode = extract32(insn, 11, 5);
+
+    switch (opcode) {
+    case 0x3: /* logic ops */
+        disas_simd_3same_logic(s, insn);
+        break;
+    case 0x17: /* ADDP */
+    case 0x14: /* SMAXP, UMAXP */
+    case 0x15: /* SMINP, UMINP */
+        /* Pairwise operations */
+        disas_simd_3same_pair(s, insn);
+        break;
+    case 0x18 ... 0x31:
+        /* floating point ops, sz[1] and U are part of opcode */
+        disas_simd_3same_float(s, insn);
+        break;
+    default:
+        disas_simd_3same_int(s, insn);
+        break;
+    }
 }
 
 /* C3.6.17 AdvSIMD two reg misc
commit b305dba6cf2957bc67aa6072978c65026ce478fb
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jan 31 14:47:36 2014 +0000

    target-arm: A64: Add SIMD scalar 3 same add, sub and compare ops
    
    Implement the add, sub and compare ops from the SIMD "scalar three same"
    group.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index e098efd..f0ebbb5 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -5503,6 +5503,58 @@ static void disas_simd_scalar_three_reg_diff(DisasContext *s, uint32_t insn)
     unsupported_encoding(s, insn);
 }
 
+static void handle_3same_64(DisasContext *s, int opcode, bool u,
+                            TCGv_i64 tcg_rd, TCGv_i64 tcg_rn, TCGv_i64 tcg_rm)
+{
+    /* Handle 64x64->64 opcodes which are shared between the scalar
+     * and vector 3-same groups. We cover every opcode where size == 3
+     * is valid in either the three-reg-same (integer, not pairwise)
+     * or scalar-three-reg-same groups. (Some opcodes are not yet
+     * implemented.)
+     */
+    TCGCond cond;
+
+    switch (opcode) {
+    case 0x6: /* CMGT, CMHI */
+        /* 64 bit integer comparison, result = test ? (2^64 - 1) : 0.
+         * We implement this using setcond (test) and then negating.
+         */
+        cond = u ? TCG_COND_GTU : TCG_COND_GT;
+    do_cmop:
+        tcg_gen_setcond_i64(cond, tcg_rd, tcg_rn, tcg_rm);
+        tcg_gen_neg_i64(tcg_rd, tcg_rd);
+        break;
+    case 0x7: /* CMGE, CMHS */
+        cond = u ? TCG_COND_GEU : TCG_COND_GE;
+        goto do_cmop;
+    case 0x11: /* CMTST, CMEQ */
+        if (u) {
+            cond = TCG_COND_EQ;
+            goto do_cmop;
+        }
+        /* CMTST : test is "if (X & Y != 0)". */
+        tcg_gen_and_i64(tcg_rd, tcg_rn, tcg_rm);
+        tcg_gen_setcondi_i64(TCG_COND_NE, tcg_rd, tcg_rd, 0);
+        tcg_gen_neg_i64(tcg_rd, tcg_rd);
+        break;
+    case 0x10: /* ADD, SUB */
+        if (u) {
+            tcg_gen_sub_i64(tcg_rd, tcg_rn, tcg_rm);
+        } else {
+            tcg_gen_add_i64(tcg_rd, tcg_rn, tcg_rm);
+        }
+        break;
+    case 0x1: /* SQADD */
+    case 0x5: /* SQSUB */
+    case 0x8: /* SSHL, USHL */
+    case 0x9: /* SQSHL, UQSHL */
+    case 0xa: /* SRSHL, URSHL */
+    case 0xb: /* SQRSHL, UQRSHL */
+    default:
+        g_assert_not_reached();
+    }
+}
+
 /* C3.6.11 AdvSIMD scalar three same
  *  31 30  29 28       24 23  22  21 20  16 15    11  10 9    5 4    0
  * +-----+---+-----------+------+---+------+--------+---+------+------+
@@ -5511,7 +5563,84 @@ static void disas_simd_scalar_three_reg_diff(DisasContext *s, uint32_t insn)
  */
 static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rd = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int opcode = extract32(insn, 11, 5);
+    int rm = extract32(insn, 16, 5);
+    int size = extract32(insn, 22, 2);
+    bool u = extract32(insn, 29, 1);
+    TCGv_i64 tcg_rn;
+    TCGv_i64 tcg_rm;
+    TCGv_i64 tcg_rd;
+
+    if (opcode >= 0x18) {
+        /* Floating point: U, size[1] and opcode indicate operation */
+        int fpopcode = opcode | (extract32(size, 1, 1) << 5) | (u << 6);
+        switch (fpopcode) {
+        case 0x1b: /* FMULX */
+        case 0x1c: /* FCMEQ */
+        case 0x1f: /* FRECPS */
+        case 0x3f: /* FRSQRTS */
+        case 0x5c: /* FCMGE */
+        case 0x5d: /* FACGE */
+        case 0x7a: /* FABD  */
+        case 0x7c: /* FCMGT */
+        case 0x7d: /* FACGT */
+            unsupported_encoding(s, insn);
+            return;
+        default:
+            unallocated_encoding(s);
+            return;
+        }
+    }
+
+    switch (opcode) {
+    case 0x1: /* SQADD, UQADD */
+    case 0x5: /* SQSUB, UQSUB */
+    case 0x8: /* SSHL, USHL */
+    case 0xa: /* SRSHL, URSHL */
+        unsupported_encoding(s, insn);
+        return;
+    case 0x6: /* CMGT, CMHI */
+    case 0x7: /* CMGE, CMHS */
+    case 0x11: /* CMTST, CMEQ */
+    case 0x10: /* ADD, SUB (vector) */
+        if (size != 3) {
+            unallocated_encoding(s);
+            return;
+        }
+        break;
+    case 0x9: /* SQSHL, UQSHL */
+    case 0xb: /* SQRSHL, UQRSHL */
+        unsupported_encoding(s, insn);
+        return;
+    case 0x16: /* SQDMULH, SQRDMULH (vector) */
+        if (size != 1 && size != 2) {
+            unallocated_encoding(s);
+            return;
+        }
+        unsupported_encoding(s, insn);
+        return;
+    default:
+        unallocated_encoding(s);
+        return;
+    }
+
+    tcg_rn = read_fp_dreg(s, rn);       /* op1 */
+    tcg_rm = read_fp_dreg(s, rm);       /* op2 */
+    tcg_rd = tcg_temp_new_i64();
+
+    /* For the moment we only support the opcodes which are
+     * 64-bit-width only. The size != 3 cases will
+     * be handled later when the relevant ops are implemented.
+     */
+    handle_3same_64(s, opcode, u, tcg_rd, tcg_rn, tcg_rm);
+
+    write_fp_dreg(s, rd, tcg_rd);
+
+    tcg_temp_free_i64(tcg_rn);
+    tcg_temp_free_i64(tcg_rm);
+    tcg_temp_free_i64(tcg_rd);
 }
 
 /* C3.6.12 AdvSIMD scalar two reg misc
commit 0ae39320bd0783f1a1d4ac63ec9ba48ca41764dc
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jan 31 14:47:36 2014 +0000

    target-arm: A64: Add SIMD three-different ABDL instructions
    
    Implement the absolute-difference instructions in the SIMD
    three-different group: SABAL, SABAL2, UABAL, UABAL2, SABDL,
    SABDL2, UABDL, UABDL2.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index e8479a5..e098efd 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -5602,6 +5602,21 @@ static void handle_3rd_widening(DisasContext *s, int is_q, int is_u, int size,
             }
 
             switch (opcode) {
+            case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
+            case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
+            {
+                TCGv_i64 tcg_tmp1 = tcg_temp_new_i64();
+                TCGv_i64 tcg_tmp2 = tcg_temp_new_i64();
+
+                tcg_gen_sub_i64(tcg_tmp1, tcg_op1, tcg_op2);
+                tcg_gen_sub_i64(tcg_tmp2, tcg_op2, tcg_op1);
+                tcg_gen_movcond_i64(is_u ? TCG_COND_GEU : TCG_COND_GE,
+                                    tcg_passres,
+                                    tcg_op1, tcg_op2, tcg_tmp1, tcg_tmp2);
+                tcg_temp_free_i64(tcg_tmp1);
+                tcg_temp_free_i64(tcg_tmp2);
+                break;
+            }
             case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
             case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
             case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
@@ -5640,6 +5655,22 @@ static void handle_3rd_widening(DisasContext *s, int is_q, int is_u, int size,
             }
 
             switch (opcode) {
+            case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
+            case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
+                if (size == 0) {
+                    if (is_u) {
+                        gen_helper_neon_abdl_u16(tcg_passres, tcg_op1, tcg_op2);
+                    } else {
+                        gen_helper_neon_abdl_s16(tcg_passres, tcg_op1, tcg_op2);
+                    }
+                } else {
+                    if (is_u) {
+                        gen_helper_neon_abdl_u32(tcg_passres, tcg_op1, tcg_op2);
+                    } else {
+                        gen_helper_neon_abdl_s32(tcg_passres, tcg_op1, tcg_op2);
+                    }
+                }
+                break;
             case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
             case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
             case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
@@ -5739,10 +5770,10 @@ static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
         /* fall through */
     case 0:
     case 2:
-    case 5:
-    case 7:
         unsupported_encoding(s, insn);
         break;
+    case 5:
+    case 7:
     case 8:
     case 10:
     case 12:
commit a08582f41e94b5a7ee3e53ad1e719d24431aa675
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jan 31 14:47:36 2014 +0000

    target-arm: A64: Add SIMD three-different multiply accumulate insns
    
    Add support for the multiply-accumulate instructions from the
    SIMD three-different instructions group (C3.6.15):
     * skeleton decode of unallocated encodings and split of
       the group into its three sub-parts
     * framework for handling the 64x64->128 widening subpart
     * implementation of the multiply-accumulate instructions
       SMLAL, SMLAL2, UMLAL, UMLAL2, SMLSL, SMLSL2, UMLSL, UMLSL2,
       UMULL, UMULL2, SMULL, SMULL2
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index c22bbb5..e8479a5 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -700,6 +700,9 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
  * zero extend as we are filling a partial chunk of the vector register.
  * These functions don't support 128 bit loads/stores, which would be
  * normal load/store operations.
+ *
+ * The _i32 versions are useful when operating on 32 bit quantities
+ * (eg for floating point single or using Neon helper functions).
  */
 
 /* Get value of an element within a vector register */
@@ -735,6 +738,32 @@ static void read_vec_element(DisasContext *s, TCGv_i64 tcg_dest, int srcidx,
     }
 }
 
+static void read_vec_element_i32(DisasContext *s, TCGv_i32 tcg_dest, int srcidx,
+                                 int element, TCGMemOp memop)
+{
+    int vect_off = vec_reg_offset(srcidx, element, memop & MO_SIZE);
+    switch (memop) {
+    case MO_8:
+        tcg_gen_ld8u_i32(tcg_dest, cpu_env, vect_off);
+        break;
+    case MO_16:
+        tcg_gen_ld16u_i32(tcg_dest, cpu_env, vect_off);
+        break;
+    case MO_8|MO_SIGN:
+        tcg_gen_ld8s_i32(tcg_dest, cpu_env, vect_off);
+        break;
+    case MO_16|MO_SIGN:
+        tcg_gen_ld16s_i32(tcg_dest, cpu_env, vect_off);
+        break;
+    case MO_32:
+    case MO_32|MO_SIGN:
+        tcg_gen_ld_i32(tcg_dest, cpu_env, vect_off);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+}
+
 /* Set value of an element within a vector register */
 static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx,
                               int element, TCGMemOp memop)
@@ -5518,6 +5547,150 @@ static void disas_simd_shift_imm(DisasContext *s, uint32_t insn)
     unsupported_encoding(s, insn);
 }
 
+static void handle_3rd_widening(DisasContext *s, int is_q, int is_u, int size,
+                                int opcode, int rd, int rn, int rm)
+{
+    /* 3-reg-different widening insns: 64 x 64 -> 128 */
+    TCGv_i64 tcg_res[2];
+    int pass, accop;
+
+    tcg_res[0] = tcg_temp_new_i64();
+    tcg_res[1] = tcg_temp_new_i64();
+
+    /* Does this op do an adding accumulate, a subtracting accumulate,
+     * or no accumulate at all?
+     */
+    switch (opcode) {
+    case 5:
+    case 8:
+    case 9:
+        accop = 1;
+        break;
+    case 10:
+    case 11:
+        accop = -1;
+        break;
+    default:
+        accop = 0;
+        break;
+    }
+
+    if (accop != 0) {
+        read_vec_element(s, tcg_res[0], rd, 0, MO_64);
+        read_vec_element(s, tcg_res[1], rd, 1, MO_64);
+    }
+
+    /* size == 2 means two 32x32->64 operations; this is worth special
+     * casing because we can generally handle it inline.
+     */
+    if (size == 2) {
+        for (pass = 0; pass < 2; pass++) {
+            TCGv_i64 tcg_op1 = tcg_temp_new_i64();
+            TCGv_i64 tcg_op2 = tcg_temp_new_i64();
+            TCGv_i64 tcg_passres;
+            TCGMemOp memop = MO_32 | (is_u ? 0 : MO_SIGN);
+
+            int elt = pass + is_q * 2;
+
+            read_vec_element(s, tcg_op1, rn, elt, memop);
+            read_vec_element(s, tcg_op2, rm, elt, memop);
+
+            if (accop == 0) {
+                tcg_passres = tcg_res[pass];
+            } else {
+                tcg_passres = tcg_temp_new_i64();
+            }
+
+            switch (opcode) {
+            case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
+            case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
+            case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
+                tcg_gen_mul_i64(tcg_passres, tcg_op1, tcg_op2);
+                break;
+            default:
+                g_assert_not_reached();
+            }
+
+            if (accop > 0) {
+                tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
+                tcg_temp_free_i64(tcg_passres);
+            } else if (accop < 0) {
+                tcg_gen_sub_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
+                tcg_temp_free_i64(tcg_passres);
+            }
+
+            tcg_temp_free_i64(tcg_op1);
+            tcg_temp_free_i64(tcg_op2);
+        }
+    } else {
+        /* size 0 or 1, generally helper functions */
+        for (pass = 0; pass < 2; pass++) {
+            TCGv_i32 tcg_op1 = tcg_temp_new_i32();
+            TCGv_i32 tcg_op2 = tcg_temp_new_i32();
+            TCGv_i64 tcg_passres;
+            int elt = pass + is_q * 2;
+
+            read_vec_element_i32(s, tcg_op1, rn, elt, MO_32);
+            read_vec_element_i32(s, tcg_op2, rm, elt, MO_32);
+
+            if (accop == 0) {
+                tcg_passres = tcg_res[pass];
+            } else {
+                tcg_passres = tcg_temp_new_i64();
+            }
+
+            switch (opcode) {
+            case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
+            case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
+            case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
+                if (size == 0) {
+                    if (is_u) {
+                        gen_helper_neon_mull_u8(tcg_passres, tcg_op1, tcg_op2);
+                    } else {
+                        gen_helper_neon_mull_s8(tcg_passres, tcg_op1, tcg_op2);
+                    }
+                } else {
+                    if (is_u) {
+                        gen_helper_neon_mull_u16(tcg_passres, tcg_op1, tcg_op2);
+                    } else {
+                        gen_helper_neon_mull_s16(tcg_passres, tcg_op1, tcg_op2);
+                    }
+                }
+                break;
+            default:
+                g_assert_not_reached();
+            }
+            tcg_temp_free_i32(tcg_op1);
+            tcg_temp_free_i32(tcg_op2);
+
+            if (accop > 0) {
+                if (size == 0) {
+                    gen_helper_neon_addl_u16(tcg_res[pass], tcg_res[pass],
+                                             tcg_passres);
+                } else {
+                    gen_helper_neon_addl_u32(tcg_res[pass], tcg_res[pass],
+                                             tcg_passres);
+                }
+                tcg_temp_free_i64(tcg_passres);
+            } else if (accop < 0) {
+                if (size == 0) {
+                    gen_helper_neon_subl_u16(tcg_res[pass], tcg_res[pass],
+                                             tcg_passres);
+                } else {
+                    gen_helper_neon_subl_u32(tcg_res[pass], tcg_res[pass],
+                                             tcg_passres);
+                }
+                tcg_temp_free_i64(tcg_passres);
+            }
+        }
+    }
+
+    write_vec_element(s, tcg_res[0], rd, 0, MO_64);
+    write_vec_element(s, tcg_res[1], rd, 1, MO_64);
+    tcg_temp_free_i64(tcg_res[0]);
+    tcg_temp_free_i64(tcg_res[1]);
+}
+
 /* C3.6.15 AdvSIMD three different
  *   31  30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
@@ -5526,7 +5699,65 @@ static void disas_simd_shift_imm(DisasContext *s, uint32_t insn)
  */
 static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    /* Instructions in this group fall into three basic classes
+     * (in each case with the operation working on each element in
+     * the input vectors):
+     * (1) widening 64 x 64 -> 128 (with possibly Vd as an extra
+     *     128 bit input)
+     * (2) wide 64 x 128 -> 128
+     * (3) narrowing 128 x 128 -> 64
+     * Here we do initial decode, catch unallocated cases and
+     * dispatch to separate functions for each class.
+     */
+    int is_q = extract32(insn, 30, 1);
+    int is_u = extract32(insn, 29, 1);
+    int size = extract32(insn, 22, 2);
+    int opcode = extract32(insn, 12, 4);
+    int rm = extract32(insn, 16, 5);
+    int rn = extract32(insn, 5, 5);
+    int rd = extract32(insn, 0, 5);
+
+    switch (opcode) {
+    case 1: /* SADDW, SADDW2, UADDW, UADDW2 */
+    case 3: /* SSUBW, SSUBW2, USUBW, USUBW2 */
+        /* 64 x 128 -> 128 */
+        unsupported_encoding(s, insn);
+        break;
+    case 4: /* ADDHN, ADDHN2, RADDHN, RADDHN2 */
+    case 6: /* SUBHN, SUBHN2, RSUBHN, RSUBHN2 */
+        /* 128 x 128 -> 64 */
+        unsupported_encoding(s, insn);
+        break;
+    case 9:
+    case 11:
+    case 13:
+    case 14:
+        if (is_u) {
+            unallocated_encoding(s);
+            return;
+        }
+        /* fall through */
+    case 0:
+    case 2:
+    case 5:
+    case 7:
+        unsupported_encoding(s, insn);
+        break;
+    case 8:
+    case 10:
+    case 12:
+        /* 64 x 64 -> 128 */
+        if (size == 3) {
+            unallocated_encoding(s);
+            return;
+        }
+        handle_3rd_widening(s, is_q, is_u, size, opcode, rd, rn, rm);
+        break;
+    default:
+        /* opcode 15 not allocated */
+        unallocated_encoding(s);
+        break;
+    }
 }
 
 /* C3.6.16 AdvSIMD three same
commit 901ad5259fab785537f8c6b3713fce85d2ebceb1
Author: Will Newton <will.newton at linaro.org>
Date:   Fri Jan 31 14:47:35 2014 +0000

    target-arm: Add AArch32 SIMD VCVTA, VCVTN, VCVTP and VCVTM
    
    Add support for the AArch32 Advanced SIMD VCVTA, VCVTN, VCVTP
    and VCVTM instructions.
    
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 0fcc159..e701c0f 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4778,6 +4778,14 @@ static const uint8_t neon_3r_sizes[] = {
 #define NEON_2RM_VRINTM 45
 #define NEON_2RM_VCVT_F32_F16 46
 #define NEON_2RM_VRINTP 47
+#define NEON_2RM_VCVTAU 48
+#define NEON_2RM_VCVTAS 49
+#define NEON_2RM_VCVTNU 50
+#define NEON_2RM_VCVTNS 51
+#define NEON_2RM_VCVTPU 52
+#define NEON_2RM_VCVTPS 53
+#define NEON_2RM_VCVTMU 54
+#define NEON_2RM_VCVTMS 55
 #define NEON_2RM_VRECPE 56
 #define NEON_2RM_VRSQRTE 57
 #define NEON_2RM_VRECPE_F 58
@@ -4792,7 +4800,8 @@ static int neon_2rm_is_float_op(int op)
     /* Return true if this neon 2reg-misc op is float-to-float */
     return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
             (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
-            op == NEON_2RM_VRINTM || op == NEON_2RM_VRINTP ||
+            op == NEON_2RM_VRINTM ||
+            (op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
             op >= NEON_2RM_VRECPE_F);
 }
 
@@ -4845,6 +4854,14 @@ static const uint8_t neon_2rm_sizes[] = {
     [NEON_2RM_VRINTM] = 0x4,
     [NEON_2RM_VCVT_F32_F16] = 0x2,
     [NEON_2RM_VRINTP] = 0x4,
+    [NEON_2RM_VCVTAU] = 0x4,
+    [NEON_2RM_VCVTAS] = 0x4,
+    [NEON_2RM_VCVTNU] = 0x4,
+    [NEON_2RM_VCVTNS] = 0x4,
+    [NEON_2RM_VCVTPU] = 0x4,
+    [NEON_2RM_VCVTPS] = 0x4,
+    [NEON_2RM_VCVTMU] = 0x4,
+    [NEON_2RM_VCVTMS] = 0x4,
     [NEON_2RM_VRECPE] = 0x4,
     [NEON_2RM_VRSQRTE] = 0x4,
     [NEON_2RM_VRECPE_F] = 0x4,
@@ -6588,6 +6605,40 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
                             tcg_temp_free_ptr(fpstatus);
                             break;
                         }
+                        case NEON_2RM_VCVTAU:
+                        case NEON_2RM_VCVTAS:
+                        case NEON_2RM_VCVTNU:
+                        case NEON_2RM_VCVTNS:
+                        case NEON_2RM_VCVTPU:
+                        case NEON_2RM_VCVTPS:
+                        case NEON_2RM_VCVTMU:
+                        case NEON_2RM_VCVTMS:
+                        {
+                            bool is_signed = !extract32(insn, 7, 1);
+                            TCGv_ptr fpst = get_fpstatus_ptr(1);
+                            TCGv_i32 tcg_rmode, tcg_shift;
+                            int rmode = fp_decode_rm[extract32(insn, 8, 2)];
+
+                            tcg_shift = tcg_const_i32(0);
+                            tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
+                            gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
+                                                      cpu_env);
+
+                            if (is_signed) {
+                                gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
+                                                     tcg_shift, fpst);
+                            } else {
+                                gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
+                                                     tcg_shift, fpst);
+                            }
+
+                            gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
+                                                      cpu_env);
+                            tcg_temp_free_i32(tcg_rmode);
+                            tcg_temp_free_i32(tcg_shift);
+                            tcg_temp_free_ptr(fpst);
+                            break;
+                        }
                         case NEON_2RM_VRECPE:
                             gen_helper_recpe_u32(tmp, tmp, cpu_env);
                             break;
commit c9975a838736c9479b2e17fff7e50a2a83b1009e
Author: Will Newton <will.newton at linaro.org>
Date:   Fri Jan 31 14:47:35 2014 +0000

    target-arm: Add AArch32 FP VCVTA, VCVTN, VCVTP and VCVTM
    
    Add support for the AArch32 floating-point VCVTA, VCVTN, VCVTP
    and VCVTM instructions.
    
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 5a8ca24..0fcc159 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2797,6 +2797,63 @@ static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
     return 0;
 }
 
+static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
+                       int rounding)
+{
+    bool is_signed = extract32(insn, 7, 1);
+    TCGv_ptr fpst = get_fpstatus_ptr(0);
+    TCGv_i32 tcg_rmode, tcg_shift;
+
+    tcg_shift = tcg_const_i32(0);
+
+    tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
+    gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
+
+    if (dp) {
+        TCGv_i64 tcg_double, tcg_res;
+        TCGv_i32 tcg_tmp;
+        /* Rd is encoded as a single precision register even when the source
+         * is double precision.
+         */
+        rd = ((rd << 1) & 0x1e) | ((rd >> 4) & 0x1);
+        tcg_double = tcg_temp_new_i64();
+        tcg_res = tcg_temp_new_i64();
+        tcg_tmp = tcg_temp_new_i32();
+        tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
+        if (is_signed) {
+            gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
+        } else {
+            gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
+        }
+        tcg_gen_trunc_i64_i32(tcg_tmp, tcg_res);
+        tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
+        tcg_temp_free_i32(tcg_tmp);
+        tcg_temp_free_i64(tcg_res);
+        tcg_temp_free_i64(tcg_double);
+    } else {
+        TCGv_i32 tcg_single, tcg_res;
+        tcg_single = tcg_temp_new_i32();
+        tcg_res = tcg_temp_new_i32();
+        tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
+        if (is_signed) {
+            gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
+        } else {
+            gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
+        }
+        tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
+        tcg_temp_free_i32(tcg_res);
+        tcg_temp_free_i32(tcg_single);
+    }
+
+    gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
+    tcg_temp_free_i32(tcg_rmode);
+
+    tcg_temp_free_i32(tcg_shift);
+
+    tcg_temp_free_ptr(fpst);
+
+    return 0;
+}
 
 /* Table for converting the most common AArch32 encoding of
  * rounding mode to arm_fprounding order (which matches the
@@ -2835,6 +2892,10 @@ static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
         /* VRINTA, VRINTN, VRINTP, VRINTM */
         int rounding = fp_decode_rm[extract32(insn, 16, 2)];
         return handle_vrint(insn, rd, rm, dp, rounding);
+    } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40) {
+        /* VCVTA, VCVTN, VCVTP, VCVTM */
+        int rounding = fp_decode_rm[extract32(insn, 16, 2)];
+        return handle_vcvt(insn, rd, rm, dp, rounding);
     }
     return 1;
 }
commit 34f7b0a276ed2679c5e420ed1bc6525689ac5abd
Author: Will Newton <will.newton at linaro.org>
Date:   Fri Jan 31 14:47:35 2014 +0000

    target-arm: Add AArch32 SIMD VRINTA, VRINTN, VRINTP, VRINTM, VRINTZ
    
    Add support for the AArch32 Advanced SIMD VRINTA, VRINTN, VRINTP
    VRINTM and VRINTZ instructions.
    
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index c179817..5a8ca24 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4709,9 +4709,14 @@ static const uint8_t neon_3r_sizes[] = {
 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
 #define NEON_2RM_VSHLL 38
+#define NEON_2RM_VRINTN 40
 #define NEON_2RM_VRINTX 41
+#define NEON_2RM_VRINTA 42
+#define NEON_2RM_VRINTZ 43
 #define NEON_2RM_VCVT_F16_F32 44
+#define NEON_2RM_VRINTM 45
 #define NEON_2RM_VCVT_F32_F16 46
+#define NEON_2RM_VRINTP 47
 #define NEON_2RM_VRECPE 56
 #define NEON_2RM_VRSQRTE 57
 #define NEON_2RM_VRECPE_F 58
@@ -4725,7 +4730,9 @@ static int neon_2rm_is_float_op(int op)
 {
     /* Return true if this neon 2reg-misc op is float-to-float */
     return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
-            op == NEON_2RM_VRINTX || op >= NEON_2RM_VRECPE_F);
+            (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
+            op == NEON_2RM_VRINTM || op == NEON_2RM_VRINTP ||
+            op >= NEON_2RM_VRECPE_F);
 }
 
 /* Each entry in this array has bit n set if the insn allows
@@ -4769,9 +4776,14 @@ static const uint8_t neon_2rm_sizes[] = {
     [NEON_2RM_VMOVN] = 0x7,
     [NEON_2RM_VQMOVN] = 0x7,
     [NEON_2RM_VSHLL] = 0x7,
+    [NEON_2RM_VRINTN] = 0x4,
     [NEON_2RM_VRINTX] = 0x4,
+    [NEON_2RM_VRINTA] = 0x4,
+    [NEON_2RM_VRINTZ] = 0x4,
     [NEON_2RM_VCVT_F16_F32] = 0x2,
+    [NEON_2RM_VRINTM] = 0x4,
     [NEON_2RM_VCVT_F32_F16] = 0x2,
+    [NEON_2RM_VRINTP] = 0x4,
     [NEON_2RM_VRECPE] = 0x4,
     [NEON_2RM_VRSQRTE] = 0x4,
     [NEON_2RM_VRECPE_F] = 0x4,
@@ -6482,6 +6494,32 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
                             }
                             neon_store_reg(rm, pass, tmp2);
                             break;
+                        case NEON_2RM_VRINTN:
+                        case NEON_2RM_VRINTA:
+                        case NEON_2RM_VRINTM:
+                        case NEON_2RM_VRINTP:
+                        case NEON_2RM_VRINTZ:
+                        {
+                            TCGv_i32 tcg_rmode;
+                            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+                            int rmode;
+
+                            if (op == NEON_2RM_VRINTZ) {
+                                rmode = FPROUNDING_ZERO;
+                            } else {
+                                rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
+                            }
+
+                            tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
+                            gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
+                                                      cpu_env);
+                            gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
+                            gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
+                                                      cpu_env);
+                            tcg_temp_free_ptr(fpstatus);
+                            tcg_temp_free_i32(tcg_rmode);
+                            break;
+                        }
                         case NEON_2RM_VRINTX:
                         {
                             TCGv_ptr fpstatus = get_fpstatus_ptr(1);
commit 43630e585300465b72ecf328822c8611724307de
Author: Will Newton <will.newton at linaro.org>
Date:   Fri Jan 31 14:47:35 2014 +0000

    target-arm: Add set_neon_rmode helper
    
    This helper sets the rounding mode in the standard_fp_status word to
    allow NEON instructions to modify the rounding mode whilst using the
    standard FPSCR values for everything else.
    
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index b1541b9..ca5b000 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4048,6 +4048,23 @@ uint32_t HELPER(set_rmode)(uint32_t rmode, CPUARMState *env)
     return prev_rmode;
 }
 
+/* Set the current fp rounding mode in the standard fp status and return
+ * the old one. This is for NEON instructions that need to change the
+ * rounding mode but wish to use the standard FPSCR values for everything
+ * else. Always set the rounding mode back to the correct value after
+ * modifying it.
+ * The argument is a softfloat float_round_ value.
+ */
+uint32_t HELPER(set_neon_rmode)(uint32_t rmode, CPUARMState *env)
+{
+    float_status *fp_status = &env->vfp.standard_fp_status;
+
+    uint32_t prev_rmode = get_float_rounding_mode(fp_status);
+    set_float_rounding_mode(rmode, fp_status);
+
+    return prev_rmode;
+}
+
 /* Half precision conversions.  */
 static float32 do_fcvt_f16_to_f32(uint32_t a, CPUARMState *env, float_status *s)
 {
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 70872df..71b8411 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -149,6 +149,7 @@ DEF_HELPER_3(vfp_ultod, f64, i64, i32, ptr)
 DEF_HELPER_3(vfp_uqtod, f64, i64, i32, ptr)
 
 DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, env)
+DEF_HELPER_FLAGS_2(set_neon_rmode, TCG_CALL_NO_RWG, i32, i32, env)
 
 DEF_HELPER_2(vfp_fcvt_f16_to_f32, f32, i32, env)
 DEF_HELPER_2(vfp_fcvt_f32_to_f16, i32, f32, env)
commit 2ce7062501c715aae0ad37c3923a3710dd8914df
Author: Will Newton <will.newton at linaro.org>
Date:   Fri Jan 31 14:47:34 2014 +0000

    target-arm: Add support for AArch32 SIMD VRINTX
    
    Add support for the AArch32 Advanced SIMD VRINTX instruction.
    
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 9eb5b92..c179817 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4709,6 +4709,7 @@ static const uint8_t neon_3r_sizes[] = {
 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
 #define NEON_2RM_VSHLL 38
+#define NEON_2RM_VRINTX 41
 #define NEON_2RM_VCVT_F16_F32 44
 #define NEON_2RM_VCVT_F32_F16 46
 #define NEON_2RM_VRECPE 56
@@ -4724,7 +4725,7 @@ static int neon_2rm_is_float_op(int op)
 {
     /* Return true if this neon 2reg-misc op is float-to-float */
     return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
-            op >= NEON_2RM_VRECPE_F);
+            op == NEON_2RM_VRINTX || op >= NEON_2RM_VRECPE_F);
 }
 
 /* Each entry in this array has bit n set if the insn allows
@@ -4768,6 +4769,7 @@ static const uint8_t neon_2rm_sizes[] = {
     [NEON_2RM_VMOVN] = 0x7,
     [NEON_2RM_VQMOVN] = 0x7,
     [NEON_2RM_VSHLL] = 0x7,
+    [NEON_2RM_VRINTX] = 0x4,
     [NEON_2RM_VCVT_F16_F32] = 0x2,
     [NEON_2RM_VCVT_F32_F16] = 0x2,
     [NEON_2RM_VRECPE] = 0x4,
@@ -6480,6 +6482,13 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
                             }
                             neon_store_reg(rm, pass, tmp2);
                             break;
+                        case NEON_2RM_VRINTX:
+                        {
+                            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+                            gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
+                            tcg_temp_free_ptr(fpstatus);
+                            break;
+                        }
                         case NEON_2RM_VRECPE:
                             gen_helper_recpe_u32(tmp, tmp, cpu_env);
                             break;
commit 4e82bc01ecc46e90346f731065528b1d47971eba
Author: Will Newton <will.newton at linaro.org>
Date:   Fri Jan 31 14:47:34 2014 +0000

    target-arm: Add support for AArch32 FP VRINTX
    
    Add support for the AArch32 floating-point VRINTX instruction.
    
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 9afb19f..9eb5b92 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3406,6 +3406,17 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
                         tcg_temp_free_ptr(fpst);
                         break;
                     }
+                    case 14: /* vrintx */
+                    {
+                        TCGv_ptr fpst = get_fpstatus_ptr(0);
+                        if (dp) {
+                            gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);
+                        } else {
+                            gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);
+                        }
+                        tcg_temp_free_ptr(fpst);
+                        break;
+                    }
                     case 15: /* single<->double conversion */
                         if (dp)
                             gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
commit a290c62a7521a5695e12bb9022f8b953c2f50f54
Author: Will Newton <will.newton at linaro.org>
Date:   Fri Jan 31 14:47:34 2014 +0000

    target-arm: Add support for AArch32 FP VRINTZ
    
    Add support for the AArch32 floating-point VRINTZ instruction.
    
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 2b3157c..9afb19f 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3390,6 +3390,22 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
                         tcg_temp_free_ptr(fpst);
                         break;
                     }
+                    case 13: /* vrintz */
+                    {
+                        TCGv_ptr fpst = get_fpstatus_ptr(0);
+                        TCGv_i32 tcg_rmode;
+                        tcg_rmode = tcg_const_i32(float_round_to_zero);
+                        gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
+                        if (dp) {
+                            gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
+                        } else {
+                            gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
+                        }
+                        gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
+                        tcg_temp_free_i32(tcg_rmode);
+                        tcg_temp_free_ptr(fpst);
+                        break;
+                    }
                     case 15: /* single<->double conversion */
                         if (dp)
                             gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
commit 664c6733d72c589cd9f6ccee305e7b7ce36ea06d
Author: Will Newton <will.newton at linaro.org>
Date:   Fri Jan 31 14:47:34 2014 +0000

    target-arm: Add support for AArch32 FP VRINTR
    
    Add support for the AArch32 floating-point VRINTR instruction.
    
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 2db6812..2b3157c 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3379,6 +3379,17 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
                         gen_vfp_F1_ld0(dp);
                         gen_vfp_cmpe(dp);
                         break;
+                    case 12: /* vrintr */
+                    {
+                        TCGv_ptr fpst = get_fpstatus_ptr(0);
+                        if (dp) {
+                            gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
+                        } else {
+                            gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
+                        }
+                        tcg_temp_free_ptr(fpst);
+                        break;
+                    }
                     case 15: /* single<->double conversion */
                         if (dp)
                             gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
commit 7655f39bde5de92b4a3c154a5a8735476c34f458
Author: Will Newton <will.newton at linaro.org>
Date:   Fri Jan 31 14:47:33 2014 +0000

    target-arm: Add AArch32 FP VRINTA, VRINTN, VRINTP and VRINTM
    
    Add support for AArch32 ARMv8 FP VRINTA, VRINTN, VRINTP and VRINTM
    instructions.
    
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 8d240e1..2db6812 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2759,6 +2759,56 @@ static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
     return 0;
 }
 
+static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
+                        int rounding)
+{
+    TCGv_ptr fpst = get_fpstatus_ptr(0);
+    TCGv_i32 tcg_rmode;
+
+    tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
+    gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
+
+    if (dp) {
+        TCGv_i64 tcg_op;
+        TCGv_i64 tcg_res;
+        tcg_op = tcg_temp_new_i64();
+        tcg_res = tcg_temp_new_i64();
+        tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
+        gen_helper_rintd(tcg_res, tcg_op, fpst);
+        tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
+        tcg_temp_free_i64(tcg_op);
+        tcg_temp_free_i64(tcg_res);
+    } else {
+        TCGv_i32 tcg_op;
+        TCGv_i32 tcg_res;
+        tcg_op = tcg_temp_new_i32();
+        tcg_res = tcg_temp_new_i32();
+        tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
+        gen_helper_rints(tcg_res, tcg_op, fpst);
+        tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
+        tcg_temp_free_i32(tcg_op);
+        tcg_temp_free_i32(tcg_res);
+    }
+
+    gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
+    tcg_temp_free_i32(tcg_rmode);
+
+    tcg_temp_free_ptr(fpst);
+    return 0;
+}
+
+
+/* Table for converting the most common AArch32 encoding of
+ * rounding mode to arm_fprounding order (which matches the
+ * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
+ */
+static const uint8_t fp_decode_rm[] = {
+    FPROUNDING_TIEAWAY,
+    FPROUNDING_TIEEVEN,
+    FPROUNDING_POSINF,
+    FPROUNDING_NEGINF,
+};
+
 static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
 {
     uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
@@ -2781,6 +2831,10 @@ static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
         return handle_vsel(insn, rd, rn, rm, dp);
     } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
         return handle_vminmaxnm(insn, rd, rn, rm, dp);
+    } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40) {
+        /* VRINTA, VRINTN, VRINTP, VRINTM */
+        int rounding = fp_decode_rm[extract32(insn, 16, 2)];
+        return handle_vrint(insn, rd, rm, dp, rounding);
     }
     return 1;
 }
commit 9972da669fd3d3e3423d2bf6cb2c11fa9239f862
Author: Will Newton <will.newton at linaro.org>
Date:   Fri Jan 31 14:47:33 2014 +0000

    target-arm: Move arm_rmode_to_sf to a shared location.
    
    This function will be needed for AArch32 ARMv8 support, so move it to
    helper.c where it can be used by both targets. Also moves the code out
    of line, but as it is quite a large function I don't believe this
    should be a significant performance impact.
    
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 198b6b8..383c582 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -496,6 +496,8 @@ enum arm_fprounding {
     FPROUNDING_ODD
 };
 
+int arm_rmode_to_sf(int rmode);
+
 enum arm_cpu_mode {
   ARM_CPU_MODE_USR = 0x10,
   ARM_CPU_MODE_FIQ = 0x11,
diff --git a/target-arm/helper.c b/target-arm/helper.c
index c708f15..b1541b9 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4418,3 +4418,31 @@ float64 HELPER(rintd)(float64 x, void *fp_status)
 
     return ret;
 }
+
+/* Convert ARM rounding mode to softfloat */
+int arm_rmode_to_sf(int rmode)
+{
+    switch (rmode) {
+    case FPROUNDING_TIEAWAY:
+        rmode = float_round_ties_away;
+        break;
+    case FPROUNDING_ODD:
+        /* FIXME: add support for TIEAWAY and ODD */
+        qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
+                      rmode);
+    case FPROUNDING_TIEEVEN:
+    default:
+        rmode = float_round_nearest_even;
+        break;
+    case FPROUNDING_POSINF:
+        rmode = float_round_up;
+        break;
+    case FPROUNDING_NEGINF:
+        rmode = float_round_down;
+        break;
+    case FPROUNDING_ZERO:
+        rmode = float_round_to_zero;
+        break;
+    }
+    return rmode;
+}
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 7cfb55b..c22bbb5 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -3608,34 +3608,6 @@ static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
     }
 }
 
-/* Convert ARM rounding mode to softfloat */
-static inline int arm_rmode_to_sf(int rmode)
-{
-    switch (rmode) {
-    case FPROUNDING_TIEAWAY:
-        rmode = float_round_ties_away;
-        break;
-    case FPROUNDING_ODD:
-        /* FIXME: add support for TIEAWAY and ODD */
-        qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
-                      rmode);
-    case FPROUNDING_TIEEVEN:
-    default:
-        rmode = float_round_nearest_even;
-        break;
-    case FPROUNDING_POSINF:
-        rmode = float_round_up;
-        break;
-    case FPROUNDING_NEGINF:
-        rmode = float_round_down;
-        break;
-    case FPROUNDING_ZERO:
-        rmode = float_round_to_zero;
-        break;
-    }
-    return rmode;
-}
-
 static void handle_fp_compare(DisasContext *s, bool is_double,
                               unsigned int rn, unsigned int rm,
                               bool cmp_with_zero, bool signal_all_nans)
commit 2cdaca90ddf3291f308a10623c1a802ef760bac1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Jan 31 14:47:33 2014 +0000

    display: avoid multi-statement macro
    
    For blizzard, pl110 and tc6393xb this is harmless, but for pxa2xx
    Coverity noticed that it is used inside an "if" statement.
    Fix it because it's the file with the highest number of defects
    in the whole QEMU tree!  Use "do...while (0)", or just remove the
    semicolon if there's a single statement in the macro.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/display/blizzard_template.h b/hw/display/blizzard_template.h
index a8a8899..b7ef27c 100644
--- a/hw/display/blizzard_template.h
+++ b/hw/display/blizzard_template.h
@@ -18,25 +18,35 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#define SKIP_PIXEL(to)		to += deststep
+#define SKIP_PIXEL(to)         (to += deststep)
 #if DEPTH == 8
-# define PIXEL_TYPE		uint8_t
-# define COPY_PIXEL(to, from)	*to = from; SKIP_PIXEL(to)
-# define COPY_PIXEL1(to, from)	*to ++ = from
+# define PIXEL_TYPE            uint8_t
+# define COPY_PIXEL(to, from)  do { *to = from; SKIP_PIXEL(to); } while (0)
+# define COPY_PIXEL1(to, from) (*to++ = from)
 #elif DEPTH == 15 || DEPTH == 16
-# define PIXEL_TYPE		uint16_t
-# define COPY_PIXEL(to, from)	*to = from; SKIP_PIXEL(to)
-# define COPY_PIXEL1(to, from)	*to ++ = from
+# define PIXEL_TYPE            uint16_t
+# define COPY_PIXEL(to, from)  do { *to = from; SKIP_PIXEL(to); } while (0)
+# define COPY_PIXEL1(to, from) (*to++ = from)
 #elif DEPTH == 24
-# define PIXEL_TYPE		uint8_t
-# define COPY_PIXEL(to, from)	\
-    to[0] = from; to[1] = (from) >> 8; to[2] = (from) >> 16; SKIP_PIXEL(to)
-# define COPY_PIXEL1(to, from)	\
-    *to ++ = from; *to ++ = (from) >> 8; *to ++ = (from) >> 16
+# define PIXEL_TYPE            uint8_t
+# define COPY_PIXEL(to, from) \
+    do {                      \
+        to[0] = from;         \
+        to[1] = (from) >> 8;  \
+        to[2] = (from) >> 16; \
+        SKIP_PIXEL(to);       \
+    } while (0)
+
+# define COPY_PIXEL1(to, from) \
+    do {                       \
+        *to++ = from;          \
+        *to++ = (from) >> 8;   \
+        *to++ = (from) >> 16;  \
+    } while (0)
 #elif DEPTH == 32
-# define PIXEL_TYPE		uint32_t
-# define COPY_PIXEL(to, from)	*to = from; SKIP_PIXEL(to)
-# define COPY_PIXEL1(to, from)	*to ++ = from
+# define PIXEL_TYPE            uint32_t
+# define COPY_PIXEL(to, from)  do { *to = from; SKIP_PIXEL(to); } while (0)
+# define COPY_PIXEL1(to, from) (*to++ = from)
 #else
 # error unknown bit depth
 #endif
diff --git a/hw/display/pl110_template.h b/hw/display/pl110_template.h
index e738e4a..36ba791 100644
--- a/hw/display/pl110_template.h
+++ b/hw/display/pl110_template.h
@@ -14,12 +14,16 @@
 #if BITS == 8
 #define COPY_PIXEL(to, from) *(to++) = from
 #elif BITS == 15 || BITS == 16
-#define COPY_PIXEL(to, from) *(uint16_t *)to = from; to += 2;
+#define COPY_PIXEL(to, from) do { *(uint16_t *)to = from; to += 2; } while (0)
 #elif BITS == 24
-#define COPY_PIXEL(to, from) \
-  *(to++) = from; *(to++) = (from) >> 8; *(to++) = (from) >> 16
+#define COPY_PIXEL(to, from)    \
+    do {                        \
+        *(to++) = from;         \
+        *(to++) = (from) >> 8;  \
+        *(to++) = (from) >> 16; \
+    } while (0)
 #elif BITS == 32
-#define COPY_PIXEL(to, from) *(uint32_t *)to = from; to += 4;
+#define COPY_PIXEL(to, from) do { *(uint32_t *)to = from; to += 4; } while (0)
 #else
 #error unknown bit depth
 #endif
diff --git a/hw/display/pxa2xx_template.h b/hw/display/pxa2xx_template.h
index 1cbe36c..c64eebc 100644
--- a/hw/display/pxa2xx_template.h
+++ b/hw/display/pxa2xx_template.h
@@ -11,14 +11,26 @@
 
 # define SKIP_PIXEL(to)		to += deststep
 #if BITS == 8
-# define COPY_PIXEL(to, from)	*to = from; SKIP_PIXEL(to)
+# define COPY_PIXEL(to, from)  do { *to = from; SKIP_PIXEL(to); } while (0)
 #elif BITS == 15 || BITS == 16
-# define COPY_PIXEL(to, from)	*(uint16_t *) to = from; SKIP_PIXEL(to)
+# define COPY_PIXEL(to, from)    \
+    do {                         \
+        *(uint16_t *) to = from; \
+        SKIP_PIXEL(to);          \
+    } while (0)
 #elif BITS == 24
-# define COPY_PIXEL(to, from)	\
-	*(uint16_t *) to = from; *(to + 2) = (from) >> 16; SKIP_PIXEL(to)
+# define COPY_PIXEL(to, from)     \
+    do {                          \
+        *(uint16_t *) to = from;  \
+        *(to + 2) = (from) >> 16; \
+        SKIP_PIXEL(to);           \
+    } while (0)
 #elif BITS == 32
-# define COPY_PIXEL(to, from)	*(uint32_t *) to = from; SKIP_PIXEL(to)
+# define COPY_PIXEL(to, from)    \
+    do {                         \
+        *(uint32_t *) to = from; \
+        SKIP_PIXEL(to);          \
+    } while (0)
 #else
 # error unknown bit depth
 #endif
diff --git a/hw/display/tc6393xb_template.h b/hw/display/tc6393xb_template.h
index 154aafd..78629c0 100644
--- a/hw/display/tc6393xb_template.h
+++ b/hw/display/tc6393xb_template.h
@@ -22,14 +22,18 @@
  */
 
 #if BITS == 8
-# define SET_PIXEL(addr, color)	*(uint8_t*)addr = color;
+# define SET_PIXEL(addr, color)  (*(uint8_t *)addr = color)
 #elif BITS == 15 || BITS == 16
-# define SET_PIXEL(addr, color)	*(uint16_t*)addr = color;
+# define SET_PIXEL(addr, color)  (*(uint16_t *)addr = color)
 #elif BITS == 24
-# define SET_PIXEL(addr, color)	\
-    addr[0] = color; addr[1] = (color) >> 8; addr[2] = (color) >> 16;
+# define SET_PIXEL(addr, color)  \
+    do {                         \
+        addr[0] = color;         \
+        addr[1] = (color) >> 8;  \
+        addr[2] = (color) >> 16; \
+    } while (0)
 #elif BITS == 32
-# define SET_PIXEL(addr, color)	*(uint32_t*)addr = color;
+# define SET_PIXEL(addr, color)  (*(uint32_t *)addr = color)
 #else
 # error unknown bit depth
 #endif
commit b48adc0d301464d627d6d0f83dee911a2138187f
Author: Alistair Francis <alistair.francis at xilinx.com>
Date:   Fri Jan 31 14:47:33 2014 +0000

    ZYNQ: Implement board MIDR control for Zynq
    
    This patch uses the fact that the midr variable is now a property
    This patch sets the midr variable to the boards custom midr
    
    Signed-off-by: Alistair Francis <alistair.francis at xilinx.com>
    Message-id: a3754b10d150af72e4688a993e484fa2b9b8fa21.1390176489.git.alistair.francis at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 98e0958..9ee21e7 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -37,6 +37,7 @@
 #define IRQ_OFFSET 32 /* pic interrupts start from index 32 */
 
 #define MPCORE_PERIPHBASE 0xF8F00000
+#define ZYNQ_BOARD_MIDR 0x413FC090
 
 static const int dma_irqs[8] = {
     46, 47, 48, 49, 72, 73, 74, 75
@@ -125,6 +126,12 @@ static void zynq_init(QEMUMachineInitArgs *args)
 
     cpu = ARM_CPU(object_new(object_class_get_name(cpu_oc)));
 
+    object_property_set_int(OBJECT(cpu), ZYNQ_BOARD_MIDR, "midr", &err);
+    if (err) {
+        error_report("%s", error_get_pretty(err));
+        exit(1);
+    }
+
     object_property_set_int(OBJECT(cpu), MPCORE_PERIPHBASE, "reset-cbar", &err);
     if (err) {
         error_report("%s", error_get_pretty(err));
commit 51a9b04bd3b01e11a1db4fc2ac2f1d324fbd30aa
Author: Alistair Francis <alistair.francis at xilinx.com>
Date:   Fri Jan 31 14:47:32 2014 +0000

    ARM: Convert MIDR to a property
    
    Convert the MIDR register to a property. This allows boards to later set
    a custom MIDR value. This has been done in such a way to maintain
    compatibility with all existing CPUs and boards
    
    Signed-off-by: Alistair Francis <alistair.francis at xilinx.com>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 878613f2f12d4162f12629522fd99de8df904856.1390176489.git.alistair.francis at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 52efd5d..45ad7f0 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -982,6 +982,7 @@ static const ARMCPUInfo arm_cpus[] = {
 
 static Property arm_cpu_properties[] = {
     DEFINE_PROP_BOOL("start-powered-off", ARMCPU, start_powered_off, false),
+    DEFINE_PROP_UINT32("midr", ARMCPU, midr, 0),
     DEFINE_PROP_END_OF_LIST()
 };
 
commit 83bfffec72ad447dfc80a4eab320403175ffe4e3
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jan 31 14:47:32 2014 +0000

    hw/arm/boot: Don't set up ATAGS for autogenerated dtb booting
    
    The code which decides whether to set up the ATAGS data structure on
    reset was using the wrong conditional, which meant we were creating
    an ATAGS structure when doing a device-tree boot if the dtb was
    autogenerated by the board. This is harmless, but unnecessary, so
    bring it in to line with user-provided-dtb boots.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 1388326833-656-1-git-send-email-peter.maydell at linaro.org

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 1c1b0e5..4036262 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -173,6 +173,11 @@ static void default_reset_secondary(ARMCPU *cpu,
     env->regs[15] = info->smp_loader_start;
 }
 
+static inline bool have_dtb(const struct arm_boot_info *info)
+{
+    return info->dtb_filename || info->get_dtb;
+}
+
 #define WRITE_WORD(p, value) do { \
     stl_phys_notdirty(p, value);  \
     p += 4;                       \
@@ -421,7 +426,7 @@ static void do_cpu_reset(void *opaque)
                     env->regs[15] = info->loader_start;
                 }
 
-                if (!info->dtb_filename) {
+                if (!have_dtb(info)) {
                     if (old_param) {
                         set_kernel_args_old(info);
                     } else {
@@ -542,7 +547,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
         /* for device tree boot, we pass the DTB directly in r2. Otherwise
          * we point to the kernel args.
          */
-        if (info->dtb_filename || info->get_dtb) {
+        if (have_dtb(info)) {
             /* Place the DTB after the initrd in memory. Note that some
              * kernels will trash anything in the 4K page the initrd
              * ends in, so make sure the DTB isn't caught up in that.
commit 360a6f2dbde39211107620a3d38b8cc8cc5281ee
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jan 31 14:47:32 2014 +0000

    target-arm: A64: Add SIMD scalar copy instructions
    
    Add support for the SIMD scalar copy instruction group (C3.6.7),
    which consists of the single instruction DUP (element, scalar).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 69c75c0..7cfb55b 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -5108,6 +5108,35 @@ static void handle_simd_dupe(DisasContext *s, int is_q, int rd, int rn,
     tcg_temp_free_i64(tmp);
 }
 
+/* C6.3.31 DUP (element, scalar)
+ *  31                   21 20    16 15        10  9    5 4    0
+ * +-----------------------+--------+-------------+------+------+
+ * | 0 1 0 1 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 0 1 |  Rn  |  Rd  |
+ * +-----------------------+--------+-------------+------+------+
+ */
+static void handle_simd_dupes(DisasContext *s, int rd, int rn,
+                              int imm5)
+{
+    int size = ctz32(imm5);
+    int index;
+    TCGv_i64 tmp;
+
+    if (size > 3) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    index = imm5 >> (size + 1);
+
+    /* This instruction just extracts the specified element and
+     * zero-extends it into the bottom of the destination register.
+     */
+    tmp = tcg_temp_new_i64();
+    read_vec_element(s, tmp, rn, index, size);
+    write_fp_dreg(s, rd, tmp);
+    tcg_temp_free_i64(tmp);
+}
+
 /* C6.3.32 DUP (General)
  *
  *  31  30   29              21 20    16 15        10  9    5 4    0
@@ -5425,7 +5454,19 @@ static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
  */
 static void disas_simd_scalar_copy(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rd = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int imm4 = extract32(insn, 11, 4);
+    int imm5 = extract32(insn, 16, 5);
+    int op = extract32(insn, 29, 1);
+
+    if (op != 0 || imm4 != 0) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    /* DUP (element, scalar) */
+    handle_simd_dupes(s, rd, rn, imm5);
 }
 
 /* C3.6.8 AdvSIMD scalar pairwise
commit f3f8c4f4d2fc7dda192393f998e63c7a83fb7554
Author: Alex Bennée <alex.bennee at linaro.org>
Date:   Fri Jan 31 14:47:32 2014 +0000

    target-arm: A64: Add SIMD modified immediate group
    
    This patch adds support for the AdvSIMD modified immediate group
    (C3.6.6) with all its suboperations (movi, orr, fmov, mvni, bic).
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    [AJB: new decode struct, minor bug fixes, optimisation]
    Signed-off-by: Alex Bennée <alex.bennee at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 6521f73..69c75c0 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -5293,10 +5293,128 @@ static void disas_simd_copy(DisasContext *s, uint32_t insn)
  * +---+---+----+---------------------+-----+-------+----+---+-------+------+
  * | 0 | Q | op | 0 1 1 1 1 0 0 0 0 0 | abc | cmode | o2 | 1 | defgh |  Rd  |
  * +---+---+----+---------------------+-----+-------+----+---+-------+------+
+ *
+ * There are a number of operations that can be carried out here:
+ *   MOVI - move (shifted) imm into register
+ *   MVNI - move inverted (shifted) imm into register
+ *   ORR  - bitwise OR of (shifted) imm with register
+ *   BIC  - bitwise clear of (shifted) imm with register
  */
 static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rd = extract32(insn, 0, 5);
+    int cmode = extract32(insn, 12, 4);
+    int cmode_3_1 = extract32(cmode, 1, 3);
+    int cmode_0 = extract32(cmode, 0, 1);
+    int o2 = extract32(insn, 11, 1);
+    uint64_t abcdefgh = extract32(insn, 5, 5) | (extract32(insn, 16, 3) << 5);
+    bool is_neg = extract32(insn, 29, 1);
+    bool is_q = extract32(insn, 30, 1);
+    uint64_t imm = 0;
+    TCGv_i64 tcg_rd, tcg_imm;
+    int i;
+
+    if (o2 != 0 || ((cmode == 0xf) && is_neg && !is_q)) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    /* See AdvSIMDExpandImm() in ARM ARM */
+    switch (cmode_3_1) {
+    case 0: /* Replicate(Zeros(24):imm8, 2) */
+    case 1: /* Replicate(Zeros(16):imm8:Zeros(8), 2) */
+    case 2: /* Replicate(Zeros(8):imm8:Zeros(16), 2) */
+    case 3: /* Replicate(imm8:Zeros(24), 2) */
+    {
+        int shift = cmode_3_1 * 8;
+        imm = bitfield_replicate(abcdefgh << shift, 32);
+        break;
+    }
+    case 4: /* Replicate(Zeros(8):imm8, 4) */
+    case 5: /* Replicate(imm8:Zeros(8), 4) */
+    {
+        int shift = (cmode_3_1 & 0x1) * 8;
+        imm = bitfield_replicate(abcdefgh << shift, 16);
+        break;
+    }
+    case 6:
+        if (cmode_0) {
+            /* Replicate(Zeros(8):imm8:Ones(16), 2) */
+            imm = (abcdefgh << 16) | 0xffff;
+        } else {
+            /* Replicate(Zeros(16):imm8:Ones(8), 2) */
+            imm = (abcdefgh << 8) | 0xff;
+        }
+        imm = bitfield_replicate(imm, 32);
+        break;
+    case 7:
+        if (!cmode_0 && !is_neg) {
+            imm = bitfield_replicate(abcdefgh, 8);
+        } else if (!cmode_0 && is_neg) {
+            int i;
+            imm = 0;
+            for (i = 0; i < 8; i++) {
+                if ((abcdefgh) & (1 << i)) {
+                    imm |= 0xffULL << (i * 8);
+                }
+            }
+        } else if (cmode_0) {
+            if (is_neg) {
+                imm = (abcdefgh & 0x3f) << 48;
+                if (abcdefgh & 0x80) {
+                    imm |= 0x8000000000000000ULL;
+                }
+                if (abcdefgh & 0x40) {
+                    imm |= 0x3fc0000000000000ULL;
+                } else {
+                    imm |= 0x4000000000000000ULL;
+                }
+            } else {
+                imm = (abcdefgh & 0x3f) << 19;
+                if (abcdefgh & 0x80) {
+                    imm |= 0x80000000;
+                }
+                if (abcdefgh & 0x40) {
+                    imm |= 0x3e000000;
+                } else {
+                    imm |= 0x40000000;
+                }
+                imm |= (imm << 32);
+            }
+        }
+        break;
+    }
+
+    if (cmode_3_1 != 7 && is_neg) {
+        imm = ~imm;
+    }
+
+    tcg_imm = tcg_const_i64(imm);
+    tcg_rd = new_tmp_a64(s);
+
+    for (i = 0; i < 2; i++) {
+        int foffs = i ? fp_reg_hi_offset(rd) : fp_reg_offset(rd, MO_64);
+
+        if (i == 1 && !is_q) {
+            /* non-quad ops clear high half of vector */
+            tcg_gen_movi_i64(tcg_rd, 0);
+        } else if ((cmode & 0x9) == 0x1 || (cmode & 0xd) == 0x9) {
+            tcg_gen_ld_i64(tcg_rd, cpu_env, foffs);
+            if (is_neg) {
+                /* AND (BIC) */
+                tcg_gen_and_i64(tcg_rd, tcg_rd, tcg_imm);
+            } else {
+                /* ORR */
+                tcg_gen_or_i64(tcg_rd, tcg_rd, tcg_imm);
+            }
+        } else {
+            /* MOVI */
+            tcg_gen_mov_i64(tcg_rd, tcg_imm);
+        }
+        tcg_gen_st_i64(tcg_rd, cpu_env, foffs);
+    }
+
+    tcg_temp_free_i64(tcg_imm);
 }
 
 /* C3.6.7 AdvSIMD scalar copy
commit 67bb93890d7b435f294f1e47ee7adc5662cc0842
Author: Alex Bennée <alex.bennee at linaro.org>
Date:   Fri Jan 31 14:47:31 2014 +0000

    target-arm: A64: Add SIMD copy operations
    
    This adds support for the all the AdvSIMD vector copy operations
    (ARM ARM 3.6.5).
    
    Signed-off-by: Alex Bennée <alex.bennee at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index de4f518..6521f73 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -5069,6 +5069,173 @@ static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
     tcg_temp_free_i64(tcg_res);
 }
 
+/* C6.3.31 DUP (Element, Vector)
+ *
+ *  31  30   29              21 20    16 15        10  9    5 4    0
+ * +---+---+-------------------+--------+-------------+------+------+
+ * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 0 1 |  Rn  |  Rd  |
+ * +---+---+-------------------+--------+-------------+------+------+
+ *
+ * size: encoded in imm5 (see ARM ARM LowestSetBit())
+ */
+static void handle_simd_dupe(DisasContext *s, int is_q, int rd, int rn,
+                             int imm5)
+{
+    int size = ctz32(imm5);
+    int esize = 8 << size;
+    int elements = (is_q ? 128 : 64) / esize;
+    int index, i;
+    TCGv_i64 tmp;
+
+    if (size > 3 || (size == 3 && !is_q)) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    index = imm5 >> (size + 1);
+
+    tmp = tcg_temp_new_i64();
+    read_vec_element(s, tmp, rn, index, size);
+
+    for (i = 0; i < elements; i++) {
+        write_vec_element(s, tmp, rd, i, size);
+    }
+
+    if (!is_q) {
+        clear_vec_high(s, rd);
+    }
+
+    tcg_temp_free_i64(tmp);
+}
+
+/* C6.3.32 DUP (General)
+ *
+ *  31  30   29              21 20    16 15        10  9    5 4    0
+ * +---+---+-------------------+--------+-------------+------+------+
+ * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 1 1 |  Rn  |  Rd  |
+ * +---+---+-------------------+--------+-------------+------+------+
+ *
+ * size: encoded in imm5 (see ARM ARM LowestSetBit())
+ */
+static void handle_simd_dupg(DisasContext *s, int is_q, int rd, int rn,
+                             int imm5)
+{
+    int size = ctz32(imm5);
+    int esize = 8 << size;
+    int elements = (is_q ? 128 : 64)/esize;
+    int i = 0;
+
+    if (size > 3 || ((size == 3) && !is_q)) {
+        unallocated_encoding(s);
+        return;
+    }
+    for (i = 0; i < elements; i++) {
+        write_vec_element(s, cpu_reg(s, rn), rd, i, size);
+    }
+    if (!is_q) {
+        clear_vec_high(s, rd);
+    }
+}
+
+/* C6.3.150 INS (Element)
+ *
+ *  31                   21 20    16 15  14    11  10 9    5 4    0
+ * +-----------------------+--------+------------+---+------+------+
+ * | 0 1 1 0 1 1 1 0 0 0 0 |  imm5  | 0 |  imm4  | 1 |  Rn  |  Rd  |
+ * +-----------------------+--------+------------+---+------+------+
+ *
+ * size: encoded in imm5 (see ARM ARM LowestSetBit())
+ * index: encoded in imm5<4:size+1>
+ */
+static void handle_simd_inse(DisasContext *s, int rd, int rn,
+                             int imm4, int imm5)
+{
+    int size = ctz32(imm5);
+    int src_index, dst_index;
+    TCGv_i64 tmp;
+
+    if (size > 3) {
+        unallocated_encoding(s);
+        return;
+    }
+    dst_index = extract32(imm5, 1+size, 5);
+    src_index = extract32(imm4, size, 4);
+
+    tmp = tcg_temp_new_i64();
+
+    read_vec_element(s, tmp, rn, src_index, size);
+    write_vec_element(s, tmp, rd, dst_index, size);
+
+    tcg_temp_free_i64(tmp);
+}
+
+
+/* C6.3.151 INS (General)
+ *
+ *  31                   21 20    16 15        10  9    5 4    0
+ * +-----------------------+--------+-------------+------+------+
+ * | 0 1 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 1 1 1 |  Rn  |  Rd  |
+ * +-----------------------+--------+-------------+------+------+
+ *
+ * size: encoded in imm5 (see ARM ARM LowestSetBit())
+ * index: encoded in imm5<4:size+1>
+ */
+static void handle_simd_insg(DisasContext *s, int rd, int rn, int imm5)
+{
+    int size = ctz32(imm5);
+    int idx;
+
+    if (size > 3) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    idx = extract32(imm5, 1 + size, 4 - size);
+    write_vec_element(s, cpu_reg(s, rn), rd, idx, size);
+}
+
+/*
+ * C6.3.321 UMOV (General)
+ * C6.3.237 SMOV (General)
+ *
+ *  31  30   29              21 20    16 15    12   10 9    5 4    0
+ * +---+---+-------------------+--------+-------------+------+------+
+ * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 1 U 1 1 |  Rn  |  Rd  |
+ * +---+---+-------------------+--------+-------------+------+------+
+ *
+ * U: unsigned when set
+ * size: encoded in imm5 (see ARM ARM LowestSetBit())
+ */
+static void handle_simd_umov_smov(DisasContext *s, int is_q, int is_signed,
+                                  int rn, int rd, int imm5)
+{
+    int size = ctz32(imm5);
+    int element;
+    TCGv_i64 tcg_rd;
+
+    /* Check for UnallocatedEncodings */
+    if (is_signed) {
+        if (size > 2 || (size == 2 && !is_q)) {
+            unallocated_encoding(s);
+            return;
+        }
+    } else {
+        if (size > 3
+            || (size < 3 && is_q)
+            || (size == 3 && !is_q)) {
+            unallocated_encoding(s);
+            return;
+        }
+    }
+    element = extract32(imm5, 1+size, 4);
+
+    tcg_rd = cpu_reg(s, rd);
+    read_vec_element(s, tcg_rd, rn, element, size | (is_signed ? MO_SIGN : 0));
+    if (is_signed && !is_q) {
+        tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
+    }
+}
+
 /* C3.6.5 AdvSIMD copy
  *   31  30  29  28             21 20  16 15  14  11 10  9    5 4    0
  * +---+---+----+-----------------+------+---+------+---+------+------+
@@ -5077,7 +5244,48 @@ static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
  */
 static void disas_simd_copy(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rd = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int imm4 = extract32(insn, 11, 4);
+    int op = extract32(insn, 29, 1);
+    int is_q = extract32(insn, 30, 1);
+    int imm5 = extract32(insn, 16, 5);
+
+    if (op) {
+        if (is_q) {
+            /* INS (element) */
+            handle_simd_inse(s, rd, rn, imm4, imm5);
+        } else {
+            unallocated_encoding(s);
+        }
+    } else {
+        switch (imm4) {
+        case 0:
+            /* DUP (element - vector) */
+            handle_simd_dupe(s, is_q, rd, rn, imm5);
+            break;
+        case 1:
+            /* DUP (general) */
+            handle_simd_dupg(s, is_q, rd, rn, imm5);
+            break;
+        case 3:
+            if (is_q) {
+                /* INS (general) */
+                handle_simd_insg(s, rd, rn, imm5);
+            } else {
+                unallocated_encoding(s);
+            }
+            break;
+        case 5:
+        case 7:
+            /* UMOV/SMOV (is_q indicates 32/64; imm4 indicates signedness) */
+            handle_simd_umov_smov(s, is_q, (imm4 == 5), rn, rd, imm5);
+            break;
+        default:
+            unallocated_encoding(s);
+            break;
+        }
+    }
 }
 
 /* C3.6.6 AdvSIMD modified immediate
commit 4a0ff1ce73a9e06ecb655019820229de74244432
Author: Michael Matz <matz at suse.de>
Date:   Fri Jan 31 14:47:31 2014 +0000

    target-arm: A64: Add SIMD across-lanes instructions
    
    Add support for the SIMD "across lanes" instruction group (C3.6.4).
    
    Signed-off-by: Michael Matz <matz at suse.de>
    [PMM: Updated to current codebase, added fp min/max ops,
     added unallocated encoding checks]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 59e2a85..de4f518 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -4883,6 +4883,29 @@ static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
     tcg_temp_free_i64(tcg_resh);
 }
 
+static void do_minmaxop(DisasContext *s, TCGv_i32 tcg_elt1, TCGv_i32 tcg_elt2,
+                        int opc, bool is_min, TCGv_ptr fpst)
+{
+    /* Helper function for disas_simd_across_lanes: do a single precision
+     * min/max operation on the specified two inputs,
+     * and return the result in tcg_elt1.
+     */
+    if (opc == 0xc) {
+        if (is_min) {
+            gen_helper_vfp_minnums(tcg_elt1, tcg_elt1, tcg_elt2, fpst);
+        } else {
+            gen_helper_vfp_maxnums(tcg_elt1, tcg_elt1, tcg_elt2, fpst);
+        }
+    } else {
+        assert(opc == 0xf);
+        if (is_min) {
+            gen_helper_vfp_mins(tcg_elt1, tcg_elt1, tcg_elt2, fpst);
+        } else {
+            gen_helper_vfp_maxs(tcg_elt1, tcg_elt1, tcg_elt2, fpst);
+        }
+    }
+}
+
 /* C3.6.4 AdvSIMD across lanes
  *   31  30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
@@ -4891,7 +4914,159 @@ static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
  */
 static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rd = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int size = extract32(insn, 22, 2);
+    int opcode = extract32(insn, 12, 5);
+    bool is_q = extract32(insn, 30, 1);
+    bool is_u = extract32(insn, 29, 1);
+    bool is_fp = false;
+    bool is_min = false;
+    int esize;
+    int elements;
+    int i;
+    TCGv_i64 tcg_res, tcg_elt;
+
+    switch (opcode) {
+    case 0x1b: /* ADDV */
+        if (is_u) {
+            unallocated_encoding(s);
+            return;
+        }
+        /* fall through */
+    case 0x3: /* SADDLV, UADDLV */
+    case 0xa: /* SMAXV, UMAXV */
+    case 0x1a: /* SMINV, UMINV */
+        if (size == 3 || (size == 2 && !is_q)) {
+            unallocated_encoding(s);
+            return;
+        }
+        break;
+    case 0xc: /* FMAXNMV, FMINNMV */
+    case 0xf: /* FMAXV, FMINV */
+        if (!is_u || !is_q || extract32(size, 0, 1)) {
+            unallocated_encoding(s);
+            return;
+        }
+        /* Bit 1 of size field encodes min vs max, and actual size is always
+         * 32 bits: adjust the size variable so following code can rely on it
+         */
+        is_min = extract32(size, 1, 1);
+        is_fp = true;
+        size = 2;
+        break;
+    default:
+        unallocated_encoding(s);
+        return;
+    }
+
+    esize = 8 << size;
+    elements = (is_q ? 128 : 64) / esize;
+
+    tcg_res = tcg_temp_new_i64();
+    tcg_elt = tcg_temp_new_i64();
+
+    /* These instructions operate across all lanes of a vector
+     * to produce a single result. We can guarantee that a 64
+     * bit intermediate is sufficient:
+     *  + for [US]ADDLV the maximum element size is 32 bits, and
+     *    the result type is 64 bits
+     *  + for FMAX*V, FMIN*V, ADDV the intermediate type is the
+     *    same as the element size, which is 32 bits at most
+     * For the integer operations we can choose to work at 64
+     * or 32 bits and truncate at the end; for simplicity
+     * we use 64 bits always. The floating point
+     * ops do require 32 bit intermediates, though.
+     */
+    if (!is_fp) {
+        read_vec_element(s, tcg_res, rn, 0, size | (is_u ? 0 : MO_SIGN));
+
+        for (i = 1; i < elements; i++) {
+            read_vec_element(s, tcg_elt, rn, i, size | (is_u ? 0 : MO_SIGN));
+
+            switch (opcode) {
+            case 0x03: /* SADDLV / UADDLV */
+            case 0x1b: /* ADDV */
+                tcg_gen_add_i64(tcg_res, tcg_res, tcg_elt);
+                break;
+            case 0x0a: /* SMAXV / UMAXV */
+                tcg_gen_movcond_i64(is_u ? TCG_COND_GEU : TCG_COND_GE,
+                                    tcg_res,
+                                    tcg_res, tcg_elt, tcg_res, tcg_elt);
+                break;
+            case 0x1a: /* SMINV / UMINV */
+                tcg_gen_movcond_i64(is_u ? TCG_COND_LEU : TCG_COND_LE,
+                                    tcg_res,
+                                    tcg_res, tcg_elt, tcg_res, tcg_elt);
+                break;
+                break;
+            default:
+                g_assert_not_reached();
+            }
+
+        }
+    } else {
+        /* Floating point ops which work on 32 bit (single) intermediates.
+         * Note that correct NaN propagation requires that we do these
+         * operations in exactly the order specified by the pseudocode.
+         */
+        TCGv_i32 tcg_elt1 = tcg_temp_new_i32();
+        TCGv_i32 tcg_elt2 = tcg_temp_new_i32();
+        TCGv_i32 tcg_elt3 = tcg_temp_new_i32();
+        TCGv_ptr fpst = get_fpstatus_ptr();
+
+        assert(esize == 32);
+        assert(elements == 4);
+
+        read_vec_element(s, tcg_elt, rn, 0, MO_32);
+        tcg_gen_trunc_i64_i32(tcg_elt1, tcg_elt);
+        read_vec_element(s, tcg_elt, rn, 1, MO_32);
+        tcg_gen_trunc_i64_i32(tcg_elt2, tcg_elt);
+
+        do_minmaxop(s, tcg_elt1, tcg_elt2, opcode, is_min, fpst);
+
+        read_vec_element(s, tcg_elt, rn, 2, MO_32);
+        tcg_gen_trunc_i64_i32(tcg_elt2, tcg_elt);
+        read_vec_element(s, tcg_elt, rn, 3, MO_32);
+        tcg_gen_trunc_i64_i32(tcg_elt3, tcg_elt);
+
+        do_minmaxop(s, tcg_elt2, tcg_elt3, opcode, is_min, fpst);
+
+        do_minmaxop(s, tcg_elt1, tcg_elt2, opcode, is_min, fpst);
+
+        tcg_gen_extu_i32_i64(tcg_res, tcg_elt1);
+        tcg_temp_free_i32(tcg_elt1);
+        tcg_temp_free_i32(tcg_elt2);
+        tcg_temp_free_i32(tcg_elt3);
+        tcg_temp_free_ptr(fpst);
+    }
+
+    tcg_temp_free_i64(tcg_elt);
+
+    /* Now truncate the result to the width required for the final output */
+    if (opcode == 0x03) {
+        /* SADDLV, UADDLV: result is 2*esize */
+        size++;
+    }
+
+    switch (size) {
+    case 0:
+        tcg_gen_ext8u_i64(tcg_res, tcg_res);
+        break;
+    case 1:
+        tcg_gen_ext16u_i64(tcg_res, tcg_res);
+        break;
+    case 2:
+        tcg_gen_ext32u_i64(tcg_res, tcg_res);
+        break;
+    case 3:
+        break;
+    default:
+        g_assert_not_reached();
+    }
+
+    write_fp_dreg(s, rd, tcg_res);
+    tcg_temp_free_i64(tcg_res);
 }
 
 /* C3.6.5 AdvSIMD copy
commit 5fa5469c08f6e51eed26d6d54e0be8682723d3df
Author: Michael Matz <matz at suse.de>
Date:   Fri Jan 31 14:47:31 2014 +0000

    target-arm: A64: Add SIMD ZIP/UZP/TRN
    
    Add support for the SIMD ZIP/UZIP/TRN instruction group
    (C3.6.3).
    
    Signed-off-by: Michael Matz <matz at suse.de>
    [PMM: use new do_vec_get/set etc functions and generally update to new
     codebase standards; refactor to pull per-element loop outside switch]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 7a6b00a..59e2a85 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -4806,7 +4806,81 @@ static void disas_simd_tb(DisasContext *s, uint32_t insn)
  */
 static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rd = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int rm = extract32(insn, 16, 5);
+    int size = extract32(insn, 22, 2);
+    /* opc field bits [1:0] indicate ZIP/UZP/TRN;
+     * bit 2 indicates 1 vs 2 variant of the insn.
+     */
+    int opcode = extract32(insn, 12, 2);
+    bool part = extract32(insn, 14, 1);
+    bool is_q = extract32(insn, 30, 1);
+    int esize = 8 << size;
+    int i, ofs;
+    int datasize = is_q ? 128 : 64;
+    int elements = datasize / esize;
+    TCGv_i64 tcg_res, tcg_resl, tcg_resh;
+
+    if (opcode == 0 || (size == 3 && !is_q)) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    tcg_resl = tcg_const_i64(0);
+    tcg_resh = tcg_const_i64(0);
+    tcg_res = tcg_temp_new_i64();
+
+    for (i = 0; i < elements; i++) {
+        switch (opcode) {
+        case 1: /* UZP1/2 */
+        {
+            int midpoint = elements / 2;
+            if (i < midpoint) {
+                read_vec_element(s, tcg_res, rn, 2 * i + part, size);
+            } else {
+                read_vec_element(s, tcg_res, rm,
+                                 2 * (i - midpoint) + part, size);
+            }
+            break;
+        }
+        case 2: /* TRN1/2 */
+            if (i & 1) {
+                read_vec_element(s, tcg_res, rm, (i & ~1) + part, size);
+            } else {
+                read_vec_element(s, tcg_res, rn, (i & ~1) + part, size);
+            }
+            break;
+        case 3: /* ZIP1/2 */
+        {
+            int base = part * elements / 2;
+            if (i & 1) {
+                read_vec_element(s, tcg_res, rm, base + (i >> 1), size);
+            } else {
+                read_vec_element(s, tcg_res, rn, base + (i >> 1), size);
+            }
+            break;
+        }
+        default:
+            g_assert_not_reached();
+        }
+
+        ofs = i * esize;
+        if (ofs < 64) {
+            tcg_gen_shli_i64(tcg_res, tcg_res, ofs);
+            tcg_gen_or_i64(tcg_resl, tcg_resl, tcg_res);
+        } else {
+            tcg_gen_shli_i64(tcg_res, tcg_res, ofs - 64);
+            tcg_gen_or_i64(tcg_resh, tcg_resh, tcg_res);
+        }
+    }
+
+    tcg_temp_free_i64(tcg_res);
+
+    write_vec_element(s, tcg_resl, rd, 0, MO_64);
+    tcg_temp_free_i64(tcg_resl);
+    write_vec_element(s, tcg_resh, rd, 1, MO_64);
+    tcg_temp_free_i64(tcg_resh);
 }
 
 /* C3.6.4 AdvSIMD across lanes
commit 7c51048fa918f64806adf0f76166e9940d772eb1
Author: Michael Matz <matz at suse.de>
Date:   Fri Jan 31 14:47:31 2014 +0000

    target-arm: A64: Add SIMD TBL/TBLX
    
    Add support for the SIMD TBL/TBLX instructions (group C3.6.2).
    
    Signed-off-by: Michael Matz <matz at suse.de>
    [PMM: rewritten to do more of the decode in translate-a64.c,
     and to do only one 64 bit pass at a time in the helper]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 4ce0d01..6ca958a 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -122,3 +122,34 @@ uint64_t HELPER(vfp_cmped_a64)(float64 x, float64 y, void *fp_status)
 {
     return float_rel_to_flags(float64_compare(x, y, fp_status));
 }
+
+uint64_t HELPER(simd_tbl)(CPUARMState *env, uint64_t result, uint64_t indices,
+                          uint32_t rn, uint32_t numregs)
+{
+    /* Helper function for SIMD TBL and TBX. We have to do the table
+     * lookup part for the 64 bits worth of indices we're passed in.
+     * result is the initial results vector (either zeroes for TBL
+     * or some guest values for TBX), rn the register number where
+     * the table starts, and numregs the number of registers in the table.
+     * We return the results of the lookups.
+     */
+    int shift;
+
+    for (shift = 0; shift < 64; shift += 8) {
+        int index = extract64(indices, shift, 8);
+        if (index < 16 * numregs) {
+            /* Convert index (a byte offset into the virtual table
+             * which is a series of 128-bit vectors concatenated)
+             * into the correct vfp.regs[] element plus a bit offset
+             * into that element, bearing in mind that the table
+             * can wrap around from V31 to V0.
+             */
+            int elt = (rn * 2 + (index >> 3)) % 64;
+            int bitidx = (index & 7) * 8;
+            uint64_t val = extract64(env->vfp.regs[elt], bitidx, 8);
+
+            result = deposit64(result, shift, 8, val);
+        }
+    }
+    return result;
+}
diff --git a/target-arm/helper-a64.h b/target-arm/helper-a64.h
index bca19f3..99832ee 100644
--- a/target-arm/helper-a64.h
+++ b/target-arm/helper-a64.h
@@ -26,3 +26,4 @@ DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr)
 DEF_HELPER_3(vfp_cmpes_a64, i64, f32, f32, ptr)
 DEF_HELPER_3(vfp_cmpd_a64, i64, f64, f64, ptr)
 DEF_HELPER_3(vfp_cmped_a64, i64, f64, f64, ptr)
+DEF_HELPER_FLAGS_5(simd_tbl, TCG_CALL_NO_RWG_SE, i64, env, i64, i64, i32, i32)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 75b0039..7a6b00a 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -4742,7 +4742,60 @@ static void disas_simd_ext(DisasContext *s, uint32_t insn)
  */
 static void disas_simd_tb(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int op2 = extract32(insn, 22, 2);
+    int is_q = extract32(insn, 30, 1);
+    int rm = extract32(insn, 16, 5);
+    int rn = extract32(insn, 5, 5);
+    int rd = extract32(insn, 0, 5);
+    int is_tblx = extract32(insn, 12, 1);
+    int len = extract32(insn, 13, 2);
+    TCGv_i64 tcg_resl, tcg_resh, tcg_idx;
+    TCGv_i32 tcg_regno, tcg_numregs;
+
+    if (op2 != 0) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    /* This does a table lookup: for every byte element in the input
+     * we index into a table formed from up to four vector registers,
+     * and then the output is the result of the lookups. Our helper
+     * function does the lookup operation for a single 64 bit part of
+     * the input.
+     */
+    tcg_resl = tcg_temp_new_i64();
+    tcg_resh = tcg_temp_new_i64();
+
+    if (is_tblx) {
+        read_vec_element(s, tcg_resl, rd, 0, MO_64);
+    } else {
+        tcg_gen_movi_i64(tcg_resl, 0);
+    }
+    if (is_tblx && is_q) {
+        read_vec_element(s, tcg_resh, rd, 1, MO_64);
+    } else {
+        tcg_gen_movi_i64(tcg_resh, 0);
+    }
+
+    tcg_idx = tcg_temp_new_i64();
+    tcg_regno = tcg_const_i32(rn);
+    tcg_numregs = tcg_const_i32(len + 1);
+    read_vec_element(s, tcg_idx, rm, 0, MO_64);
+    gen_helper_simd_tbl(tcg_resl, cpu_env, tcg_resl, tcg_idx,
+                        tcg_regno, tcg_numregs);
+    if (is_q) {
+        read_vec_element(s, tcg_idx, rm, 1, MO_64);
+        gen_helper_simd_tbl(tcg_resh, cpu_env, tcg_resh, tcg_idx,
+                            tcg_regno, tcg_numregs);
+    }
+    tcg_temp_free_i64(tcg_idx);
+    tcg_temp_free_i32(tcg_regno);
+    tcg_temp_free_i32(tcg_numregs);
+
+    write_vec_element(s, tcg_resl, rd, 0, MO_64);
+    tcg_temp_free_i64(tcg_resl);
+    write_vec_element(s, tcg_resh, rd, 1, MO_64);
+    tcg_temp_free_i64(tcg_resh);
 }
 
 /* C3.6.3 ZIP/UZP/TRN
commit 5c73747f3cc29471f9fbfe630ef15902e65f53b3
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jan 31 14:47:30 2014 +0000

    target-arm: A64: Add SIMD EXT
    
    Add support for the SIMD EXT instruction (the only one in its
    group, C3.6.1).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 8060c9f..75b0039 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -4646,6 +4646,25 @@ static void disas_data_proc_fp(DisasContext *s, uint32_t insn)
     }
 }
 
+static void do_ext64(DisasContext *s, TCGv_i64 tcg_left, TCGv_i64 tcg_right,
+                     int pos)
+{
+    /* Extract 64 bits from the middle of two concatenated 64 bit
+     * vector register slices left:right. The extracted bits start
+     * at 'pos' bits into the right (least significant) side.
+     * We return the result in tcg_right, and guarantee not to
+     * trash tcg_left.
+     */
+    TCGv_i64 tcg_tmp = tcg_temp_new_i64();
+    assert(pos > 0 && pos < 64);
+
+    tcg_gen_shri_i64(tcg_right, tcg_right, pos);
+    tcg_gen_shli_i64(tcg_tmp, tcg_left, 64 - pos);
+    tcg_gen_or_i64(tcg_right, tcg_right, tcg_tmp);
+
+    tcg_temp_free_i64(tcg_tmp);
+}
+
 /* C3.6.1 EXT
  *   31  30 29         24 23 22  21 20  16 15  14  11 10  9    5 4    0
  * +---+---+-------------+-----+---+------+---+------+---+------+------+
@@ -4654,7 +4673,65 @@ static void disas_data_proc_fp(DisasContext *s, uint32_t insn)
  */
 static void disas_simd_ext(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int is_q = extract32(insn, 30, 1);
+    int op2 = extract32(insn, 22, 2);
+    int imm4 = extract32(insn, 11, 4);
+    int rm = extract32(insn, 16, 5);
+    int rn = extract32(insn, 5, 5);
+    int rd = extract32(insn, 0, 5);
+    int pos = imm4 << 3;
+    TCGv_i64 tcg_resl, tcg_resh;
+
+    if (op2 != 0 || (!is_q && extract32(imm4, 3, 1))) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    tcg_resh = tcg_temp_new_i64();
+    tcg_resl = tcg_temp_new_i64();
+
+    /* Vd gets bits starting at pos bits into Vm:Vn. This is
+     * either extracting 128 bits from a 128:128 concatenation, or
+     * extracting 64 bits from a 64:64 concatenation.
+     */
+    if (!is_q) {
+        read_vec_element(s, tcg_resl, rn, 0, MO_64);
+        if (pos != 0) {
+            read_vec_element(s, tcg_resh, rm, 0, MO_64);
+            do_ext64(s, tcg_resh, tcg_resl, pos);
+        }
+        tcg_gen_movi_i64(tcg_resh, 0);
+    } else {
+        TCGv_i64 tcg_hh;
+        typedef struct {
+            int reg;
+            int elt;
+        } EltPosns;
+        EltPosns eltposns[] = { {rn, 0}, {rn, 1}, {rm, 0}, {rm, 1} };
+        EltPosns *elt = eltposns;
+
+        if (pos >= 64) {
+            elt++;
+            pos -= 64;
+        }
+
+        read_vec_element(s, tcg_resl, elt->reg, elt->elt, MO_64);
+        elt++;
+        read_vec_element(s, tcg_resh, elt->reg, elt->elt, MO_64);
+        elt++;
+        if (pos != 0) {
+            do_ext64(s, tcg_resh, tcg_resl, pos);
+            tcg_hh = tcg_temp_new_i64();
+            read_vec_element(s, tcg_hh, elt->reg, elt->elt, MO_64);
+            do_ext64(s, tcg_hh, tcg_resh, pos);
+            tcg_temp_free_i64(tcg_hh);
+        }
+    }
+
+    write_vec_element(s, tcg_resl, rd, 0, MO_64);
+    tcg_temp_free_i64(tcg_resl);
+    write_vec_element(s, tcg_resh, rd, 1, MO_64);
+    tcg_temp_free_i64(tcg_resh);
 }
 
 /* C3.6.2 TBL/TBX
commit 384b26fb06f72e822730d3b8f51fd71a5fec5eee
Author: Alex Bennée <alex.bennee at linaro.org>
Date:   Fri Jan 31 14:47:30 2014 +0000

    target-arm: A64: Add decode skeleton for SIMD data processing insns
    
    Add decode skeleton and function placeholders for all the SIMD data
    processing instructions. Due to the complexity of this part of the
    table the normal extract and switch approach gets very messy very
    quickly, so we use a simple data-driven pattern-and-mask approach.
    
    Signed-off-by: Alex Bennée <alex.bennee at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 6e31740..8060c9f 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -61,6 +61,17 @@ enum a64_shift_type {
     A64_SHIFT_TYPE_ROR = 3
 };
 
+/* Table based decoder typedefs - used when the relevant bits for decode
+ * are too awkwardly scattered across the instruction (eg SIMD).
+ */
+typedef void AArch64DecodeFn(DisasContext *s, uint32_t insn);
+
+typedef struct AArch64DecodeTable {
+    uint32_t pattern;
+    uint32_t mask;
+    AArch64DecodeFn *disas_fn;
+} AArch64DecodeTable;
+
 /* initialize TCG globals.  */
 void a64_translate_init(void)
 {
@@ -846,6 +857,31 @@ static inline void gen_check_sp_alignment(DisasContext *s)
 }
 
 /*
+ * This provides a simple table based table lookup decoder. It is
+ * intended to be used when the relevant bits for decode are too
+ * awkwardly placed and switch/if based logic would be confusing and
+ * deeply nested. Since it's a linear search through the table, tables
+ * should be kept small.
+ *
+ * It returns the first handler where insn & mask == pattern, or
+ * NULL if there is no match.
+ * The table is terminated by an empty mask (i.e. 0)
+ */
+static inline AArch64DecodeFn *lookup_disas_fn(const AArch64DecodeTable *table,
+                                               uint32_t insn)
+{
+    const AArch64DecodeTable *tptr = table;
+
+    while (tptr->mask) {
+        if ((insn & tptr->mask) == tptr->pattern) {
+            return tptr->disas_fn;
+        }
+        tptr++;
+    }
+    return NULL;
+}
+
+/*
  * the instruction disassembly implemented here matches
  * the instruction encoding classifications in chapter 3 (C3)
  * of the ARM Architecture Reference Manual (DDI0487A_a)
@@ -4610,13 +4646,281 @@ static void disas_data_proc_fp(DisasContext *s, uint32_t insn)
     }
 }
 
+/* C3.6.1 EXT
+ *   31  30 29         24 23 22  21 20  16 15  14  11 10  9    5 4    0
+ * +---+---+-------------+-----+---+------+---+------+---+------+------+
+ * | 0 | Q | 1 0 1 1 1 0 | op2 | 0 |  Rm  | 0 | imm4 | 0 |  Rn  |  Rd  |
+ * +---+---+-------------+-----+---+------+---+------+---+------+------+
+ */
+static void disas_simd_ext(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.2 TBL/TBX
+ *   31  30 29         24 23 22  21 20  16 15  14 13  12  11 10 9    5 4    0
+ * +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
+ * | 0 | Q | 0 0 1 1 1 0 | op2 | 0 |  Rm  | 0 | len | op | 0 0 |  Rn  |  Rd  |
+ * +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
+ */
+static void disas_simd_tb(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.3 ZIP/UZP/TRN
+ *   31  30 29         24 23  22  21 20   16 15 14 12 11 10 9    5 4    0
+ * +---+---+-------------+------+---+------+---+------------------+------+
+ * | 0 | Q | 0 0 1 1 1 0 | size | 0 |  Rm  | 0 | opc | 1 0 |  Rn  |  Rd  |
+ * +---+---+-------------+------+---+------+---+------------------+------+
+ */
+static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.4 AdvSIMD across lanes
+ *   31  30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
+ * +---+---+---+-----------+------+-----------+--------+-----+------+------+
+ * | 0 | Q | U | 0 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
+ * +---+---+---+-----------+------+-----------+--------+-----+------+------+
+ */
+static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.5 AdvSIMD copy
+ *   31  30  29  28             21 20  16 15  14  11 10  9    5 4    0
+ * +---+---+----+-----------------+------+---+------+---+------+------+
+ * | 0 | Q | op | 0 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 |  Rn  |  Rd  |
+ * +---+---+----+-----------------+------+---+------+---+------+------+
+ */
+static void disas_simd_copy(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.6 AdvSIMD modified immediate
+ *  31  30   29  28                 19 18 16 15   12  11  10  9     5 4    0
+ * +---+---+----+---------------------+-----+-------+----+---+-------+------+
+ * | 0 | Q | op | 0 1 1 1 1 0 0 0 0 0 | abc | cmode | o2 | 1 | defgh |  Rd  |
+ * +---+---+----+---------------------+-----+-------+----+---+-------+------+
+ */
+static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.7 AdvSIMD scalar copy
+ *  31 30  29  28             21 20  16 15  14  11 10  9    5 4    0
+ * +-----+----+-----------------+------+---+------+---+------+------+
+ * | 0 1 | op | 1 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 |  Rn  |  Rd  |
+ * +-----+----+-----------------+------+---+------+---+------+------+
+ */
+static void disas_simd_scalar_copy(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.8 AdvSIMD scalar pairwise
+ *  31 30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
+ * +-----+---+-----------+------+-----------+--------+-----+------+------+
+ * | 0 1 | U | 1 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
+ * +-----+---+-----------+------+-----------+--------+-----+------+------+
+ */
+static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.9 AdvSIMD scalar shift by immediate
+ *  31 30  29 28         23 22  19 18  16 15    11  10 9    5 4    0
+ * +-----+---+-------------+------+------+--------+---+------+------+
+ * | 0 1 | U | 1 1 1 1 1 0 | immh | immb | opcode | 1 |  Rn  |  Rd  |
+ * +-----+---+-------------+------+------+--------+---+------+------+
+ */
+static void disas_simd_scalar_shift_imm(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.10 AdvSIMD scalar three different
+ *  31 30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
+ * +-----+---+-----------+------+---+------+--------+-----+------+------+
+ * | 0 1 | U | 1 1 1 1 0 | size | 1 |  Rm  | opcode | 0 0 |  Rn  |  Rd  |
+ * +-----+---+-----------+------+---+------+--------+-----+------+------+
+ */
+static void disas_simd_scalar_three_reg_diff(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.11 AdvSIMD scalar three same
+ *  31 30  29 28       24 23  22  21 20  16 15    11  10 9    5 4    0
+ * +-----+---+-----------+------+---+------+--------+---+------+------+
+ * | 0 1 | U | 1 1 1 1 0 | size | 1 |  Rm  | opcode | 1 |  Rn  |  Rd  |
+ * +-----+---+-----------+------+---+------+--------+---+------+------+
+ */
+static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.12 AdvSIMD scalar two reg misc
+ *  31 30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
+ * +-----+---+-----------+------+-----------+--------+-----+------+------+
+ * | 0 1 | U | 1 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
+ * +-----+---+-----------+------+-----------+--------+-----+------+------+
+ */
+static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.13 AdvSIMD scalar x indexed element
+ *  31 30  29 28       24 23  22 21  20  19  16 15 12  11  10 9    5 4    0
+ * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
+ * | 0 1 | U | 1 1 1 1 1 | size | L | M |  Rm  | opc | H | 0 |  Rn  |  Rd  |
+ * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
+ */
+static void disas_simd_scalar_indexed(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.14 AdvSIMD shift by immediate
+ *  31  30   29 28         23 22  19 18  16 15    11  10 9    5 4    0
+ * +---+---+---+-------------+------+------+--------+---+------+------+
+ * | 0 | Q | U | 0 1 1 1 1 0 | immh | immb | opcode | 1 |  Rn  |  Rd  |
+ * +---+---+---+-------------+------+------+--------+---+------+------+
+ */
+static void disas_simd_shift_imm(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.15 AdvSIMD three different
+ *   31  30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
+ * +---+---+---+-----------+------+---+------+--------+-----+------+------+
+ * | 0 | Q | U | 0 1 1 1 0 | size | 1 |  Rm  | opcode | 0 0 |  Rn  |  Rd  |
+ * +---+---+---+-----------+------+---+------+--------+-----+------+------+
+ */
+static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.16 AdvSIMD three same
+ *  31  30  29  28       24 23  22  21 20  16 15    11  10 9    5 4    0
+ * +---+---+---+-----------+------+---+------+--------+---+------+------+
+ * | 0 | Q | U | 0 1 1 1 0 | size | 1 |  Rm  | opcode | 1 |  Rn  |  Rd  |
+ * +---+---+---+-----------+------+---+------+--------+---+------+------+
+ */
+static void disas_simd_three_reg_same(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.17 AdvSIMD two reg misc
+ *   31  30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
+ * +---+---+---+-----------+------+-----------+--------+-----+------+------+
+ * | 0 | Q | U | 0 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
+ * +---+---+---+-----------+------+-----------+--------+-----+------+------+
+ */
+static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.18 AdvSIMD vector x indexed element
+ *   31  30  29 28       24 23  22 21  20  19  16 15 12  11  10 9    5 4    0
+ * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
+ * | 0 | Q | U | 0 1 1 1 1 | size | L | M |  Rm  | opc | H | 0 |  Rn  |  Rd  |
+ * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
+ */
+static void disas_simd_indexed_vector(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.19 Crypto AES
+ *  31             24 23  22 21       17 16    12 11 10 9    5 4    0
+ * +-----------------+------+-----------+--------+-----+------+------+
+ * | 0 1 0 0 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 |  Rn  |  Rd  |
+ * +-----------------+------+-----------+--------+-----+------+------+
+ */
+static void disas_crypto_aes(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.20 Crypto three-reg SHA
+ *  31             24 23  22  21 20  16  15 14    12 11 10 9    5 4    0
+ * +-----------------+------+---+------+---+--------+-----+------+------+
+ * | 0 1 0 1 1 1 1 0 | size | 0 |  Rm  | 0 | opcode | 0 0 |  Rn  |  Rd  |
+ * +-----------------+------+---+------+---+--------+-----+------+------+
+ */
+static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6.21 Crypto two-reg SHA
+ *  31             24 23  22 21       17 16    12 11 10 9    5 4    0
+ * +-----------------+------+-----------+--------+-----+------+------+
+ * | 0 1 0 1 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 |  Rn  |  Rd  |
+ * +-----------------+------+-----------+--------+-----+------+------+
+ */
+static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
+{
+    unsupported_encoding(s, insn);
+}
+
+/* C3.6 Data processing - SIMD, inc Crypto
+ *
+ * As the decode gets a little complex we are using a table based
+ * approach for this part of the decode.
+ */
+static const AArch64DecodeTable data_proc_simd[] = {
+    /* pattern  ,  mask     ,  fn                        */
+    { 0x0e200400, 0x9f200400, disas_simd_three_reg_same },
+    { 0x0e200000, 0x9f200c00, disas_simd_three_reg_diff },
+    { 0x0e200800, 0x9f3e0c00, disas_simd_two_reg_misc },
+    { 0x0e300800, 0x9f3e0c00, disas_simd_across_lanes },
+    { 0x0e000400, 0x9fe08400, disas_simd_copy },
+    { 0x0f000000, 0x9f000400, disas_simd_indexed_vector },
+    /* simd_mod_imm decode is a subset of simd_shift_imm, so must precede it */
+    { 0x0f000400, 0x9ff80400, disas_simd_mod_imm },
+    { 0x0f000400, 0x9f800400, disas_simd_shift_imm },
+    { 0x0e000000, 0xbf208c00, disas_simd_tb },
+    { 0x0e000800, 0xbf208c00, disas_simd_zip_trn },
+    { 0x2e000000, 0xbf208400, disas_simd_ext },
+    { 0x5e200400, 0xdf200400, disas_simd_scalar_three_reg_same },
+    { 0x5e200000, 0xdf200c00, disas_simd_scalar_three_reg_diff },
+    { 0x5e200800, 0xdf3e0c00, disas_simd_scalar_two_reg_misc },
+    { 0x5e300800, 0xdf3e0c00, disas_simd_scalar_pairwise },
+    { 0x5e000400, 0xdfe08400, disas_simd_scalar_copy },
+    { 0x5f000000, 0xdf000400, disas_simd_scalar_indexed },
+    { 0x5f000400, 0xdf800400, disas_simd_scalar_shift_imm },
+    { 0x4e280800, 0xff3e0c00, disas_crypto_aes },
+    { 0x5e000000, 0xff208c00, disas_crypto_three_reg_sha },
+    { 0x5e280800, 0xff3e0c00, disas_crypto_two_reg_sha },
+    { 0x00000000, 0x00000000, NULL }
+};
+
 static void disas_data_proc_simd(DisasContext *s, uint32_t insn)
 {
     /* Note that this is called with all non-FP cases from
      * table C3-6 so it must UNDEF for entries not specifically
      * allocated to instructions in that table.
      */
-    unsupported_encoding(s, insn);
+    AArch64DecodeFn *fn = lookup_disas_fn(&data_proc_simd[0], insn);
+    if (fn) {
+        fn(s, insn);
+    } else {
+        unallocated_encoding(s);
+    }
 }
 
 /* C3.6 Data processing - SIMD and floating point */
commit df54e47d2b86c636b4d22f663dbffce6a3cffd81
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jan 31 14:47:30 2014 +0000

    target-arm: A64: Add SIMD ld/st single
    
    Implement the SIMD ld/st single structure instructions.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index e4fdf00..6e31740 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -2087,10 +2087,150 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
     tcg_temp_free_i64(tcg_addr);
 }
 
-/* AdvSIMD load/store single structure */
+/* C3.3.3 AdvSIMD load/store single structure
+ *
+ *  31  30  29           23 22 21 20       16 15 13 12  11  10 9    5 4    0
+ * +---+---+---------------+-----+-----------+-----+---+------+------+------+
+ * | 0 | Q | 0 0 1 1 0 1 0 | L R | 0 0 0 0 0 | opc | S | size |  Rn  |  Rt  |
+ * +---+---+---------------+-----+-----------+-----+---+------+------+------+
+ *
+ * C3.3.4 AdvSIMD load/store single structure (post-indexed)
+ *
+ *  31  30  29           23 22 21 20       16 15 13 12  11  10 9    5 4    0
+ * +---+---+---------------+-----+-----------+-----+---+------+------+------+
+ * | 0 | Q | 0 0 1 1 0 1 1 | L R |     Rm    | opc | S | size |  Rn  |  Rt  |
+ * +---+---+---------------+-----+-----------+-----+---+------+------+------+
+ *
+ * Rt: first (or only) SIMD&FP register to be transferred
+ * Rn: base address or SP
+ * Rm (post-index only): post-index register (when !31) or size dependent #imm
+ * index = encoded in Q:S:size dependent on size
+ *
+ * lane_size = encoded in R, opc
+ * transfer width = encoded in opc, S, size
+ */
 static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rt = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int size = extract32(insn, 10, 2);
+    int S = extract32(insn, 12, 1);
+    int opc = extract32(insn, 13, 3);
+    int R = extract32(insn, 21, 1);
+    int is_load = extract32(insn, 22, 1);
+    int is_postidx = extract32(insn, 23, 1);
+    int is_q = extract32(insn, 30, 1);
+
+    int scale = extract32(opc, 1, 2);
+    int selem = (extract32(opc, 0, 1) << 1 | R) + 1;
+    bool replicate = false;
+    int index = is_q << 3 | S << 2 | size;
+    int ebytes, xs;
+    TCGv_i64 tcg_addr, tcg_rn;
+
+    switch (scale) {
+    case 3:
+        if (!is_load || S) {
+            unallocated_encoding(s);
+            return;
+        }
+        scale = size;
+        replicate = true;
+        break;
+    case 0:
+        break;
+    case 1:
+        if (extract32(size, 0, 1)) {
+            unallocated_encoding(s);
+            return;
+        }
+        index >>= 1;
+        break;
+    case 2:
+        if (extract32(size, 1, 1)) {
+            unallocated_encoding(s);
+            return;
+        }
+        if (!extract32(size, 0, 1)) {
+            index >>= 2;
+        } else {
+            if (S) {
+                unallocated_encoding(s);
+                return;
+            }
+            index >>= 3;
+            scale = 3;
+        }
+        break;
+    default:
+        g_assert_not_reached();
+    }
+
+    ebytes = 1 << scale;
+
+    if (rn == 31) {
+        gen_check_sp_alignment(s);
+    }
+
+    tcg_rn = cpu_reg_sp(s, rn);
+    tcg_addr = tcg_temp_new_i64();
+    tcg_gen_mov_i64(tcg_addr, tcg_rn);
+
+    for (xs = 0; xs < selem; xs++) {
+        if (replicate) {
+            /* Load and replicate to all elements */
+            uint64_t mulconst;
+            TCGv_i64 tcg_tmp = tcg_temp_new_i64();
+
+            tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr,
+                                get_mem_index(s), MO_TE + scale);
+            switch (scale) {
+            case 0:
+                mulconst = 0x0101010101010101ULL;
+                break;
+            case 1:
+                mulconst = 0x0001000100010001ULL;
+                break;
+            case 2:
+                mulconst = 0x0000000100000001ULL;
+                break;
+            case 3:
+                mulconst = 0;
+                break;
+            default:
+                g_assert_not_reached();
+            }
+            if (mulconst) {
+                tcg_gen_muli_i64(tcg_tmp, tcg_tmp, mulconst);
+            }
+            write_vec_element(s, tcg_tmp, rt, 0, MO_64);
+            if (is_q) {
+                write_vec_element(s, tcg_tmp, rt, 1, MO_64);
+            } else {
+                clear_vec_high(s, rt);
+            }
+            tcg_temp_free_i64(tcg_tmp);
+        } else {
+            /* Load/store one element per register */
+            if (is_load) {
+                do_vec_ld(s, rt, index, tcg_addr, MO_TE + scale);
+            } else {
+                do_vec_st(s, rt, index, tcg_addr, MO_TE + scale);
+            }
+        }
+        tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
+        rt = (rt + 1) % 32;
+    }
+
+    if (is_postidx) {
+        int rm = extract32(insn, 16, 5);
+        if (rm == 31) {
+            tcg_gen_mov_i64(tcg_rn, tcg_addr);
+        } else {
+            tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
+        }
+    }
+    tcg_temp_free_i64(tcg_addr);
 }
 
 /* C3.3 Loads and stores */
commit 72430bf5eb7f7309e705705af9798d13aa94e80d
Author: Alex Bennée <alex.bennee at linaro.org>
Date:   Fri Jan 31 14:47:30 2014 +0000

    target-arm: A64: Add SIMD ld/st multiple
    
    This adds support support for the SIMD load/store
    multiple category of instructions.
    
    This also brings in a couple of helper functions for manipulating
    sections of the SIMD registers:
    
      * do_vec_get - fetch value from a slice of a vector register
      * do_vec_set - set a slice of a vector register
    
    which use vec_reg_offset for consistent processing of offsets in an
    endian aware manner. There are also additional helpers:
    
      * do_vec_ld - load value into SIMD
      * do_vec_st - store value from SIMD
    
    which load or store a slice of a vector register to memory.
    These don't zero extend like the fp variants.
    
    Signed-off-by: Alex Bennée <alex.bennee at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index cf80c46..e4fdf00 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -308,6 +308,28 @@ static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
     return v;
 }
 
+/* Return the offset into CPUARMState of an element of specified
+ * size, 'element' places in from the least significant end of
+ * the FP/vector register Qn.
+ */
+static inline int vec_reg_offset(int regno, int element, TCGMemOp size)
+{
+    int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
+#ifdef HOST_WORDS_BIGENDIAN
+    /* This is complicated slightly because vfp.regs[2n] is
+     * still the low half and  vfp.regs[2n+1] the high half
+     * of the 128 bit vector, even on big endian systems.
+     * Calculate the offset assuming a fully bigendian 128 bits,
+     * then XOR to account for the order of the two 64 bit halves.
+     */
+    offs += (16 - ((element + 1) * (1 << size)));
+    offs ^= 8;
+#else
+    offs += element * (1 << size);
+#endif
+    return offs;
+}
+
 /* Return the offset into CPUARMState of a slice (from
  * the least significant end) of FP register Qn (ie
  * Dn, Sn, Hn or Bn).
@@ -661,6 +683,108 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
 }
 
 /*
+ * Vector load/store helpers.
+ *
+ * The principal difference between this and a FP load is that we don't
+ * zero extend as we are filling a partial chunk of the vector register.
+ * These functions don't support 128 bit loads/stores, which would be
+ * normal load/store operations.
+ */
+
+/* Get value of an element within a vector register */
+static void read_vec_element(DisasContext *s, TCGv_i64 tcg_dest, int srcidx,
+                             int element, TCGMemOp memop)
+{
+    int vect_off = vec_reg_offset(srcidx, element, memop & MO_SIZE);
+    switch (memop) {
+    case MO_8:
+        tcg_gen_ld8u_i64(tcg_dest, cpu_env, vect_off);
+        break;
+    case MO_16:
+        tcg_gen_ld16u_i64(tcg_dest, cpu_env, vect_off);
+        break;
+    case MO_32:
+        tcg_gen_ld32u_i64(tcg_dest, cpu_env, vect_off);
+        break;
+    case MO_8|MO_SIGN:
+        tcg_gen_ld8s_i64(tcg_dest, cpu_env, vect_off);
+        break;
+    case MO_16|MO_SIGN:
+        tcg_gen_ld16s_i64(tcg_dest, cpu_env, vect_off);
+        break;
+    case MO_32|MO_SIGN:
+        tcg_gen_ld32s_i64(tcg_dest, cpu_env, vect_off);
+        break;
+    case MO_64:
+    case MO_64|MO_SIGN:
+        tcg_gen_ld_i64(tcg_dest, cpu_env, vect_off);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+}
+
+/* Set value of an element within a vector register */
+static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx,
+                              int element, TCGMemOp memop)
+{
+    int vect_off = vec_reg_offset(destidx, element, memop & MO_SIZE);
+    switch (memop) {
+    case MO_8:
+        tcg_gen_st8_i64(tcg_src, cpu_env, vect_off);
+        break;
+    case MO_16:
+        tcg_gen_st16_i64(tcg_src, cpu_env, vect_off);
+        break;
+    case MO_32:
+        tcg_gen_st32_i64(tcg_src, cpu_env, vect_off);
+        break;
+    case MO_64:
+        tcg_gen_st_i64(tcg_src, cpu_env, vect_off);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+}
+
+/* Clear the high 64 bits of a 128 bit vector (in general non-quad
+ * vector ops all need to do this).
+ */
+static void clear_vec_high(DisasContext *s, int rd)
+{
+    TCGv_i64 tcg_zero = tcg_const_i64(0);
+
+    write_vec_element(s, tcg_zero, rd, 1, MO_64);
+    tcg_temp_free_i64(tcg_zero);
+}
+
+/* Store from vector register to memory */
+static void do_vec_st(DisasContext *s, int srcidx, int element,
+                      TCGv_i64 tcg_addr, int size)
+{
+    TCGMemOp memop = MO_TE + size;
+    TCGv_i64 tcg_tmp = tcg_temp_new_i64();
+
+    read_vec_element(s, tcg_tmp, srcidx, element, size);
+    tcg_gen_qemu_st_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
+
+    tcg_temp_free_i64(tcg_tmp);
+}
+
+/* Load from memory to vector register */
+static void do_vec_ld(DisasContext *s, int destidx, int element,
+                      TCGv_i64 tcg_addr, int size)
+{
+    TCGMemOp memop = MO_TE + size;
+    TCGv_i64 tcg_tmp = tcg_temp_new_i64();
+
+    tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
+    write_vec_element(s, tcg_tmp, destidx, element, size);
+
+    tcg_temp_free_i64(tcg_tmp);
+}
+
+/*
  * This utility function is for doing register extension with an
  * optional shift. You will likely want to pass a temporary for the
  * destination register. See DecodeRegExtend() in the ARM ARM.
@@ -1835,10 +1959,132 @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn)
     }
 }
 
-/* AdvSIMD load/store multiple structures */
+/* C3.3.1 AdvSIMD load/store multiple structures
+ *
+ *  31  30  29           23 22  21         16 15    12 11  10 9    5 4    0
+ * +---+---+---------------+---+-------------+--------+------+------+------+
+ * | 0 | Q | 0 0 1 1 0 0 0 | L | 0 0 0 0 0 0 | opcode | size |  Rn  |  Rt  |
+ * +---+---+---------------+---+-------------+--------+------+------+------+
+ *
+ * C3.3.2 AdvSIMD load/store multiple structures (post-indexed)
+ *
+ *  31  30  29           23 22  21  20     16 15    12 11  10 9    5 4    0
+ * +---+---+---------------+---+---+---------+--------+------+------+------+
+ * | 0 | Q | 0 0 1 1 0 0 1 | L | 0 |   Rm    | opcode | size |  Rn  |  Rt  |
+ * +---+---+---------------+---+---+---------+--------+------+------+------+
+ *
+ * Rt: first (or only) SIMD&FP register to be transferred
+ * Rn: base address or SP
+ * Rm (post-index only): post-index register (when !31) or size dependent #imm
+ */
 static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rt = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int size = extract32(insn, 10, 2);
+    int opcode = extract32(insn, 12, 4);
+    bool is_store = !extract32(insn, 22, 1);
+    bool is_postidx = extract32(insn, 23, 1);
+    bool is_q = extract32(insn, 30, 1);
+    TCGv_i64 tcg_addr, tcg_rn;
+
+    int ebytes = 1 << size;
+    int elements = (is_q ? 128 : 64) / (8 << size);
+    int rpt;    /* num iterations */
+    int selem;  /* structure elements */
+    int r;
+
+    if (extract32(insn, 31, 1) || extract32(insn, 21, 1)) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    /* From the shared decode logic */
+    switch (opcode) {
+    case 0x0:
+        rpt = 1;
+        selem = 4;
+        break;
+    case 0x2:
+        rpt = 4;
+        selem = 1;
+        break;
+    case 0x4:
+        rpt = 1;
+        selem = 3;
+        break;
+    case 0x6:
+        rpt = 3;
+        selem = 1;
+        break;
+    case 0x7:
+        rpt = 1;
+        selem = 1;
+        break;
+    case 0x8:
+        rpt = 1;
+        selem = 2;
+        break;
+    case 0xa:
+        rpt = 2;
+        selem = 1;
+        break;
+    default:
+        unallocated_encoding(s);
+        return;
+    }
+
+    if (size == 3 && !is_q && selem != 1) {
+        /* reserved */
+        unallocated_encoding(s);
+        return;
+    }
+
+    if (rn == 31) {
+        gen_check_sp_alignment(s);
+    }
+
+    tcg_rn = cpu_reg_sp(s, rn);
+    tcg_addr = tcg_temp_new_i64();
+    tcg_gen_mov_i64(tcg_addr, tcg_rn);
+
+    for (r = 0; r < rpt; r++) {
+        int e;
+        for (e = 0; e < elements; e++) {
+            int tt = (rt + r) % 32;
+            int xs;
+            for (xs = 0; xs < selem; xs++) {
+                if (is_store) {
+                    do_vec_st(s, tt, e, tcg_addr, size);
+                } else {
+                    do_vec_ld(s, tt, e, tcg_addr, size);
+
+                    /* For non-quad operations, setting a slice of the low
+                     * 64 bits of the register clears the high 64 bits (in
+                     * the ARM ARM pseudocode this is implicit in the fact
+                     * that 'rval' is a 64 bit wide variable). We optimize
+                     * by noticing that we only need to do this the first
+                     * time we touch a register.
+                     */
+                    if (!is_q && e == 0 && (r == 0 || xs == selem - 1)) {
+                        clear_vec_high(s, tt);
+                    }
+                }
+                tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
+                tt = (tt + 1) % 32;
+            }
+        }
+    }
+
+    if (is_postidx) {
+        int rm = extract32(insn, 16, 5);
+        if (rm == 31) {
+            tcg_gen_mov_i64(tcg_rn, tcg_addr);
+        } else {
+            tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
+        }
+    }
+    tcg_temp_free_i64(tcg_addr);
 }
 
 /* AdvSIMD load/store single structure */
commit 89e4a51ca9546a7bbe1998c4e3d4a3ac3a0c19be
Merge: 0159a64 736ec16
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jan 31 11:13:08 2014 +0000

    Merge remote-tracking branch 'stefanha/tags/tracing-pull-request' into staging
    
    Tracing pull request
    
    # gpg: Signature made Mon 27 Jan 2014 14:51:09 GMT using RSA key ID 81AB73C8
    # gpg: Good signature from "Stefan Hajnoczi <stefanha at redhat.com>"
    # gpg:                 aka "Stefan Hajnoczi <stefanha at gmail.com>"
    # gpg: WARNING: This key is not certified with a trusted signature!
    # gpg:          There is no indication that the signature belongs to the owner.
    # Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35  775A 9CA4 ABB3 81AB 73C8
    
    * stefanha/tags/tracing-pull-request:
      trace: fix simple trace "disable" keyword
      trace: add glib 2.32+ static GMutex support
      trace: [simple] Do not include "trace/simple.h" in generated tracer headers
      tracing: start trace processing thread in final child process
    
    Message-id: 1390834386-23139-1-git-send-email-stefanha at redhat.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit 0159a64397fc8e6c85de73613d83a3612c840664
Merge: 97374ce a75143e
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jan 31 00:23:27 2014 +0000

    Merge remote-tracking branch 'mst/tags/for_anthony' into staging
    
    acpi,pci,pc,virtio fixes and enhancements
    
    This includes new unit-tests for acpi by Marcel,
    hotplug for pci bridges by myself (piix only so far)
    and cpu hotplug for q35.
    And a bunch of fixes all over the place as usual.
    
    I included the patch to fix memory alignment for q35
    as well - even though it limits 32 bit guests to 3G (they
    previously could address more memory with PAE).
    To remove the limit, this will have to be fixed in seabios.
    
    I also added self as virtio co-maintainer so I don't need
    to troll the list for patches to review.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    
    # gpg: Signature made Sun 26 Jan 2014 11:12:09 GMT using RSA key ID D28D5469
    # gpg: Good signature from "Michael S. Tsirkin <mst at kernel.org>"
    # gpg:                 aka "Michael S. Tsirkin <mst at redhat.com>"
    # gpg: WARNING: This key is not certified with a trusted signature!
    # gpg:          There is no indication that the signature belongs to the owner.
    # Primary key fingerprint: 0270 606B 6F3C DF3D 0B17  0970 C350 3912 AFBE 8E67
    #      Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA  8A0D 281F 0DB8 D28D 5469
    
    * mst/tags/for_anthony: (35 commits)
      MAINTAINERS: add self as virtio co-maintainer
      q35: document gigabyte_align
      q35: gigabyte alignment for ram
      acpi: Fix PCI hole handling on build_srat()
      pc: Save size of RAM below 4GB
      hw/pci: fix error flow in pci multifunction init
      acpi-test: update expected AML since recent changes
      pc: ACPI: update acpi-dsdt.hex.generated q35-acpi-dsdt.hex.generated
      pc: ACPI: unify source of CPU hotplug IO base/len
      pc: ACPI: expose PRST IO range via _CRS
      pc: Q35 DSDT: exclude CPU hotplug IO range from PCI bus resources
      pc: PIIX DSDT: exclude CPU/PCI hotplug & GPE0 IO range from PCI bus resources
      pc: set PRST base in DSDT depending on chipset
      acpi: ich9: add CPU hotplug handling to Q35 machine
      acpi: factor out common cpu hotplug code for PIIX4/Q35
      acpi-build: enable hotplug for PCI bridges
      piix4: add acpi pci hotplug support
      pcihp: generalization of piix4 acpi
      pci: add pci_for_each_bus_depth_first
      pc: make: fix dependencies: rebuild when included file is changed
      ...
    
    Message-id: 1390735289-15563-1-git-send-email-mst at redhat.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit 97374ce538883af677fd94803b71df2d55a9a4de
Merge: 8e02b35 794798e
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Jan 31 00:13:02 2014 +0000

    Merge remote-tracking branch 'sstabellini/xen-170114' into staging
    
    * sstabellini/xen-170114:
      xen_pt: Fix passthrough of device with ROM.
      xen_pt: Fix debug output.
      xenfb: map framebuffer read-only and handle unmap errors
    
    Message-id: alpine.DEB.2.02.1401171537140.21510 at kaball.uk.xensource.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit 8e02b359267f8919de799525a4ccd4d37ef2d127
Merge: dc08f85 1f149e7
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Jan 30 22:25:39 2014 +0000

    Merge remote-tracking branch 'stefanha/tags/net-pull-request' into staging
    
    Net patches
    
    # gpg: Signature made Mon 27 Jan 2014 14:45:35 GMT using RSA key ID 81AB73C8
    # gpg: Can't check signature: public key not found
    
    * stefanha/tags/net-pull-request:
      tap-linux: Get features once and use it many times
      Fix lan9118 buffer length handling
      Fix lan9118 TX "CMD A" handling
      net: Use g_strdup_printf instead of snprintf.
    
    Message-id: 1390834129-19625-1-git-send-email-stefanha at redhat.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit dc08f85188b5976d93bff25ab9e68cf3ce62b12f
Merge: 0706f7c 2d23d5e
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Jan 30 19:02:16 2014 +0000

    Merge remote-tracking branch 'rth/tcg-movbe' into staging
    
    * rth/tcg-movbe:
      tcg/i386: cleanup useless #ifdef
      tcg/i386: use movbe instruction in qemu_ldst routines
      tcg/i386: add support for three-byte opcodes
      tcg/i386: remove hardcoded P_REXW value
      disas/i386.c: disassemble movbe instruction
    
    Message-id: 1390692772-15282-1-git-send-email-rth at twiddle.net
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit 360e607b88a23d378f6efaa769c76d26f538234d
Author: Stefano Stabellini <Stefano.Stabellini at eu.citrix.com>
Date:   Thu Jan 30 12:46:05 2014 +0000

    address_space_translate: do not cross page boundaries
    
    The following commit:
    
    commit 149f54b53b7666a3facd45e86eece60ce7d3b114
    Author: Paolo Bonzini <pbonzini at redhat.com>
    Date:   Fri May 24 12:59:37 2013 +0200
    
        memory: add address_space_translate
    
    breaks Xen support in QEMU, in particular the Xen mapcache. The effect
    is that one Windows XP installation out of ten would end up with BSOD.
    
    The reason is that after this commit l in address_space_rw can span a
    page boundary, however qemu_get_ram_ptr still calls xen_map_cache asking
    to map a single page (if block->offset == 0).
    
    Fix the issue by reverting to the previous behaviour: do not return a
    length from address_space_translate_internal that can span a page
    boundary.
    
    Also in address_space_translate do not ignore the length returned by
    address_space_translate_internal.
    
    This patch should be backported to QEMU 1.6.x.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Signed-off-by: Anthony Perard <anthony.perard at citrix.com>
    Tested-by: Paolo Bonzini <pbonzini at redhat.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Cc: qemu-stable at nongnu.org

diff --git a/exec.c b/exec.c
index 2435d9e..9ad0a4b 100644
--- a/exec.c
+++ b/exec.c
@@ -325,7 +325,7 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x
                                  hwaddr *plen, bool resolve_subpage)
 {
     MemoryRegionSection *section;
-    Int128 diff;
+    Int128 diff, diff_page;
 
     section = address_space_lookup_region(d, addr, resolve_subpage);
     /* Compute offset within MemoryRegionSection */
@@ -334,7 +334,9 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x
     /* Compute offset within MemoryRegion */
     *xlat = addr + section->offset_within_region;
 
+    diff_page = int128_make64(((addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE) - addr);
     diff = int128_sub(section->mr->size, int128_make64(addr));
+    diff = int128_min(diff, diff_page);
     *plen = int128_get64(int128_min(diff, int128_make64(*plen)));
     return section;
 }
@@ -349,7 +351,7 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr,
     hwaddr len = *plen;
 
     for (;;) {
-        section = address_space_translate_internal(as->dispatch, addr, &addr, plen, true);
+        section = address_space_translate_internal(as->dispatch, addr, &addr, &len, true);
         mr = section->mr;
 
         if (!mr->iommu_ops) {
commit 0706f7c85b3c0783f92d44b551f362884db0f4bd
Merge: 18d13fa 2c02d1a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Jan 30 13:56:00 2014 +0000

    Merge remote-tracking branch 'mjt/tags/trivial-patches-2014-01-16' into staging
    
    trivial-patches for 2014-01-16
    
    # gpg: Signature made Thu 16 Jan 2014 17:29:05 GMT using RSA key ID 74F0C838
    # gpg: Good signature from "Michael Tokarev <mjt at tls.msk.ru>"
    # gpg:                 aka "Michael Tokarev <mjt at corpit.ru>"
    # gpg:                 aka "Michael Tokarev <mjt at debian.org>"
    # gpg: WARNING: This key is not certified with a trusted signature!
    # gpg:          There is no indication that the signature belongs to the owner.
    # Primary key fingerprint: 6EE1 95D1 886E 8FFB 810D  4324 457C E0A0 8044 65C5
    #      Subkey fingerprint: E190 8639 3B10 B51B AC2C  8B73 5253 C5AD 74F0 C838
    
    Message-id: 1389893719-16336-1-git-send-email-mjt at msgid.tls.msk.ru
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit 18d13fa293af8e54e15c4651f99b24a139c9eb43
Author: Alexander Graf <agraf at suse.de>
Date:   Sun Jan 19 16:53:31 2014 +0100

    TCG: Fix I64-on-32bit-host temporaries
    
    We have cache pools of temporaries that we can reuse later when they've
    already been allocated before.
    
    These cache pools differenciate between the target TCG variable type they
    contain. So we have one pool for I32 and one pool for I64 variables.
    
    On a 32bit system, we can't work with 64bit registers though. So instead we
    spawn two I32 temporaries for every I64 temporary we create. All caching
    works the same way as on a real 64-bit system though: We create a cache entry
    in the 64bit array for the first i32 index.
    
    However, when we free such a temporary we free it to the pool of its type
    (which is always i32 on 32bit systems) rather than its base_type (which is
    i64 or i32 depending on the variable). This means we put a temporary that
    is of base_type == i64 into the i32 preallocated temporary pool.
    
    Eventually, this results in failures like this on 32bit hosts:
    
      qemu-system-ppc64: tcg/tcg.c:515: tcg_temp_new_internal: Assertion `ts->base_type == type' failed.
    
    This patch makes the free routine use the base_type instead for the free case,
    so it's consistent with the temporary allocation. It fixes the above failure
    for me.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Message-id: 1390146811-59936-1-git-send-email-agraf at suse.de
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 712438c..acd02b9 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -586,7 +586,7 @@ static void tcg_temp_free_internal(int idx)
     assert(ts->temp_allocated != 0);
     ts->temp_allocated = 0;
 
-    k = ts->type + (ts->temp_local ? TCG_TYPE_COUNT : 0);
+    k = ts->base_type + (ts->temp_local ? TCG_TYPE_COUNT : 0);
     set_bit(idx, s->free_temps[k].l);
 }
 
commit 056f49ff2cf645dc484956b00b65a3aa18a1a9a3
Author: Stratos Psomadakis <psomas at grnet.gr>
Date:   Mon Jan 27 12:30:15 2014 +0200

    monitor: Cleanup mon->outbuf on write error
    
    In case monitor_flush() fails to write the contents of mon->outbuf to
    the output device, mon->outbuf is not cleaned up properly. Check the
    return code of the qemu_chr_fe_write() function and cleanup the outbuf
    if it fails.
    
    References: http://lists.nongnu.org/archive/html/qemu-devel/2014-01/msg02890.html
    
    Signed-off-by: Stratos Psomadakis <psomas at grnet.gr>
    Signed-off-by: Dimitris Aragiorgis <dimara at grnet.gr>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/monitor.c b/monitor.c
index 80456fb..cba56bc 100644
--- a/monitor.c
+++ b/monitor.c
@@ -288,8 +288,8 @@ void monitor_flush(Monitor *mon)
 
     if (len && !mon->mux_out) {
         rc = qemu_chr_fe_write(mon->chr, (const uint8_t *) buf, len);
-        if (rc == len) {
-            /* all flushed */
+        if ((rc < 0 && errno != EAGAIN) || (rc == len)) {
+            /* all flushed or error */
             QDECREF(mon->outbuf);
             mon->outbuf = qstring_new();
             return;
commit 57d3e1b3f52d07d215ed96df946ee01f8d9f9526
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Jan 16 17:34:39 2014 +0100

    virtio_rng: replace custom backend API with UserCreatable.complete() callback
    
    in addition fix default backend leak by releasing it if its
    initialization failed.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/backends/rng.c b/backends/rng.c
index 7bab806..8b8d5a4 100644
--- a/backends/rng.c
+++ b/backends/rng.c
@@ -41,9 +41,9 @@ static bool rng_backend_prop_get_opened(Object *obj, Error **errp)
     return s->opened;
 }
 
-void rng_backend_open(RngBackend *s, Error **errp)
+static void rng_backend_complete(UserCreatable *uc, Error **errp)
 {
-    object_property_set_bool(OBJECT(s), true, "opened", errp);
+    object_property_set_bool(OBJECT(uc), true, "opened", errp);
 }
 
 static void rng_backend_prop_set_opened(Object *obj, bool value, Error **errp)
@@ -77,12 +77,20 @@ static void rng_backend_init(Object *obj)
                              NULL);
 }
 
+static void rng_backend_class_init(ObjectClass *oc, void *data)
+{
+    UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+
+    ucc->complete = rng_backend_complete;
+}
+
 static const TypeInfo rng_backend_info = {
     .name = TYPE_RNG_BACKEND,
     .parent = TYPE_OBJECT,
     .instance_size = sizeof(RngBackend),
     .instance_init = rng_backend_init,
     .class_size = sizeof(RngBackendClass),
+    .class_init = rng_backend_class_init,
     .abstract = true,
     .interfaces = (InterfaceInfo[]) {
         { TYPE_USER_CREATABLE },
diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index 755fdee..a16e3bc 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -15,6 +15,7 @@
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-rng.h"
 #include "sysemu/rng.h"
+#include "qom/object_interfaces.h"
 
 static bool is_guest_ready(VirtIORNG *vrng)
 {
@@ -148,6 +149,14 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp)
     if (vrng->conf.rng == NULL) {
         vrng->conf.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM));
 
+        user_creatable_complete(OBJECT(vrng->conf.default_backend),
+                                &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
+            object_unref(OBJECT(vrng->conf.default_backend));
+            return;
+        }
+
         object_property_add_child(OBJECT(dev),
                                   "default-backend",
                                   OBJECT(vrng->conf.default_backend),
@@ -166,12 +175,6 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp)
         return;
     }
 
-    rng_backend_open(vrng->rng, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        return;
-    }
-
     vrng->vq = virtio_add_queue(vdev, 8, handle_input);
 
     assert(vrng->conf.max_bytes <= INT64_MAX);
diff --git a/include/sysemu/rng.h b/include/sysemu/rng.h
index 7637fac..0a27c9b 100644
--- a/include/sysemu/rng.h
+++ b/include/sysemu/rng.h
@@ -79,15 +79,4 @@ void rng_backend_request_entropy(RngBackend *s, size_t size,
  * to stop tracking any request.
  */
 void rng_backend_cancel_requests(RngBackend *s);
-
-/**
- * rng_backend_open:
- * @s: the backend to open
- * @errp: a pointer to return the #Error object if an error occurs.
- *
- * This function will open the backend if it is not already open.  Calling this
- * function on an already opened backend will not result in an error.
- */
-void rng_backend_open(RngBackend *s, Error **errp);
-
 #endif
commit 269e09f3fc922b800d118d9c8a721be46b5462a3
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Jan 16 17:34:38 2014 +0100

    add optional 2nd stage initialization to -object/object-add commands
    
    Introduces USER_CREATABLE interface that must be implemented by
    objects which are designed to created with -object CLI option or
    object-add QMP command.
    
    Interface provides an ability to do an optional second stage
    initialization of the object created with -object/object-add
    commands. By providing complete() callback, which is called
    after the object properties were set.
    
    It allows to:
     * prevents misusing of -object/object-add by filtering out
       objects that are not designed for it.
     * generalize second stage backend initialization instead of
       adding custom APIs to perform it
     * early error detection of backend initialization at -object/
       object-add time rather than through a proxy DEVICE object
       that tries to use backend.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/backends/rng.c b/backends/rng.c
index 85cb83f..7bab806 100644
--- a/backends/rng.c
+++ b/backends/rng.c
@@ -12,6 +12,7 @@
 
 #include "sysemu/rng.h"
 #include "qapi/qmp/qerror.h"
+#include "qom/object_interfaces.h"
 
 void rng_backend_request_entropy(RngBackend *s, size_t size,
                                  EntropyReceiveFunc *receive_entropy,
@@ -83,6 +84,10 @@ static const TypeInfo rng_backend_info = {
     .instance_init = rng_backend_init,
     .class_size = sizeof(RngBackendClass),
     .abstract = true,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_USER_CREATABLE },
+        { }
+    }
 };
 
 static void register_types(void)
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
new file mode 100644
index 0000000..b792283
--- /dev/null
+++ b/include/qom/object_interfaces.h
@@ -0,0 +1,62 @@
+#ifndef OBJECT_INTERFACES_H
+#define OBJECT_INTERFACES_H
+
+#include "qom/object.h"
+
+#define TYPE_USER_CREATABLE "user-creatable"
+
+#define USER_CREATABLE_CLASS(klass) \
+     OBJECT_CLASS_CHECK(UserCreatableClass, (klass), \
+                        TYPE_USER_CREATABLE)
+#define USER_CREATABLE_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(UserCreatableClass, (obj), \
+                      TYPE_USER_CREATABLE)
+#define USER_CREATABLE(obj) \
+     INTERFACE_CHECK(UserCreatable, (obj), \
+                     TYPE_USER_CREATABLE)
+
+
+typedef struct UserCreatable {
+    /* <private> */
+    Object Parent;
+} UserCreatable;
+
+/**
+ * UserCreatableClass:
+ * @parent_class: the base class
+ * @complete: callback to be called after @obj's properties are set.
+ *
+ * Interface is designed to work with -object/object-add/object_add
+ * commands.
+ * Interface is mandatory for objects that are designed to be user
+ * creatable (i.e. -object/object-add/object_add, will accept only
+ * objects that inherit this interface).
+ *
+ * Interface also provides an optional ability to do the second
+ * stage * initialization of the object after its properties were
+ * set.
+ *
+ * For objects created without using -object/object-add/object_add,
+ * @user_creatable_complete() wrapper should be called manually if
+ * object's type implements USER_CREATABLE interface and needs
+ * complete() callback to be called.
+ */
+typedef struct UserCreatableClass {
+    /* <private> */
+    InterfaceClass parent_class;
+
+    /* <public> */
+    void (*complete)(UserCreatable *uc, Error **errp);
+} UserCreatableClass;
+
+/**
+ * user_creatable_complete:
+ * @obj: the object whose complete() method is called if defined
+ * @errp: if an error occurs, a pointer to an area to store the error
+ *
+ * Wrapper to call complete() method if one of types it's inherited
+ * from implements USER_CREATABLE interface, otherwise the call does
+ * nothing.
+ */
+void user_creatable_complete(Object *obj, Error **errp);
+#endif
diff --git a/qmp.c b/qmp.c
index a67e0c4..d0d98e7 100644
--- a/qmp.c
+++ b/qmp.c
@@ -27,6 +27,7 @@
 #include "qapi/qmp/qobject.h"
 #include "qapi/qmp-input-visitor.h"
 #include "hw/boards.h"
+#include "qom/object_interfaces.h"
 
 NameInfo *qmp_query_name(Error **errp)
 {
@@ -554,6 +555,17 @@ void object_add(const char *type, const char *id, const QDict *qdict,
         }
     }
 
+    if (!object_dynamic_cast(obj, TYPE_USER_CREATABLE)) {
+        error_setg(&local_err, "object '%s' isn't supported by object-add",
+                   id);
+        goto out;
+    }
+
+    user_creatable_complete(obj, &local_err);
+    if (local_err) {
+        goto out;
+    }
+
     object_property_add_child(container_get(object_get_root(), "/objects"),
                               id, obj, &local_err);
 out:
diff --git a/qom/Makefile.objs b/qom/Makefile.objs
index 6a93ac7..985003b 100644
--- a/qom/Makefile.objs
+++ b/qom/Makefile.objs
@@ -1,2 +1,3 @@
 common-obj-y = object.o container.o qom-qobject.o
 common-obj-y += cpu.o
+common-obj-y += object_interfaces.o
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
new file mode 100644
index 0000000..6360818
--- /dev/null
+++ b/qom/object_interfaces.c
@@ -0,0 +1,32 @@
+#include "qom/object_interfaces.h"
+#include "qemu/module.h"
+
+void user_creatable_complete(Object *obj, Error **errp)
+{
+
+    UserCreatableClass *ucc;
+    UserCreatable *uc =
+        (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
+
+    if (!uc) {
+        return;
+    }
+
+    ucc = USER_CREATABLE_GET_CLASS(uc);
+    if (ucc->complete) {
+        ucc->complete(uc, errp);
+    }
+}
+
+static void register_types(void)
+{
+    static const TypeInfo uc_interface_info = {
+        .name          = TYPE_USER_CREATABLE,
+        .parent        = TYPE_INTERFACE,
+        .class_size = sizeof(UserCreatableClass),
+    };
+
+    type_register_static(&uc_interface_info);
+}
+
+type_init(register_types)
diff --git a/vl.c b/vl.c
index cf3de56..9c2619f 100644
--- a/vl.c
+++ b/vl.c
@@ -170,6 +170,7 @@ int main(int argc, char **argv)
 
 #include "ui/qemu-spice.h"
 #include "qapi/string-input-visitor.h"
+#include "qom/object_interfaces.h"
 
 //#define DEBUG_NET
 //#define DEBUG_SLIRP
@@ -2816,9 +2817,21 @@ static int object_create(QemuOpts *opts, void *opaque)
         return -1;
     }
 
+    if (!object_dynamic_cast(obj, TYPE_USER_CREATABLE)) {
+        error_setg(&local_err, "object '%s' isn't supported by -object",
+                   id);
+        goto out;
+    }
+
+    user_creatable_complete(obj, &local_err);
+    if (local_err) {
+        goto out;
+    }
+
     object_property_add_child(container_get(object_get_root(), "/objects"),
                               id, obj, &local_err);
 
+out:
     object_unref(obj);
     if (local_err) {
         qerror_report_err(local_err);
commit 90e9cf28e57a3e1d6caa0a28b0a332ff982ccb0b
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Jan 16 17:34:37 2014 +0100

    vl.c: -object: don't ignore duplicate 'id'
    
    object_property_add_child() may fail if 'id' matches
    an already existing object. Which means an incorrect
    command line.
    So instead of silently ignoring error, report it and
    terminate QEMU.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/vl.c b/vl.c
index 7f4fe0d..cf3de56 100644
--- a/vl.c
+++ b/vl.c
@@ -2800,6 +2800,7 @@ static int object_create(QemuOpts *opts, void *opaque)
 {
     const char *type = qemu_opt_get(opts, "qom-type");
     const char *id = qemu_opts_id(opts);
+    Error *local_err = NULL;
     Object *obj;
 
     g_assert(type != NULL);
@@ -2816,8 +2817,14 @@ static int object_create(QemuOpts *opts, void *opaque)
     }
 
     object_property_add_child(container_get(object_get_root(), "/objects"),
-                              id, obj, NULL);
+                              id, obj, &local_err);
+
     object_unref(obj);
+    if (local_err) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -1;
+    }
     return 0;
 }
 
commit 69252c046741a0955ddb90250f416a2199305091
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Jan 16 17:34:36 2014 +0100

    object_add: consolidate error handling
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qmp.c b/qmp.c
index 0f46171..a67e0c4 100644
--- a/qmp.c
+++ b/qmp.c
@@ -549,15 +549,17 @@ void object_add(const char *type, const char *id, const QDict *qdict,
         for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
             object_property_set(obj, v, e->key, &local_err);
             if (local_err) {
-                error_propagate(errp, local_err);
-                object_unref(obj);
-                return;
+                goto out;
             }
         }
     }
 
     object_property_add_child(container_get(object_get_root(), "/objects"),
-                              id, obj, errp);
+                              id, obj, &local_err);
+out:
+    if (local_err) {
+        error_propagate(errp, local_err);
+    }
     object_unref(obj);
 }
 
commit 8b6d14087d487203f4d1a67aeaddc3be6c73f49f
Author: Bandan Das <bsd at redhat.com>
Date:   Tue Jan 28 08:23:19 2014 -0700

    vfio: correct debug macro typo
    
    Change to DEBUG_VFIO in vfio_msi_interrupt() for debug
    messages to get printed
    
    Signed-off-by: Bandan Das <bsd at redhat.com>
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index 8a1f1a1..8db182f 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -599,7 +599,7 @@ static void vfio_msi_interrupt(void *opaque)
         return;
     }
 
-#ifdef VFIO_DEBUG
+#ifdef DEBUG_VFIO
     MSIMessage msg;
 
     if (vdev->interrupt == VFIO_INT_MSIX) {
commit 736ec1677f1ae7e64f2f3436ca3775c48f79678c
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Jan 15 11:10:30 2014 +0800

    trace: fix simple trace "disable" keyword
    
    The trace-events "disable" keyword turns an event into a nop at
    compile-time.  This is important for high-frequency events that can
    impact performance.
    
    The "disable" keyword is currently broken in the simple trace backend.
    This patch fixes the problem as follows:
    
    Trace events are identified by their TraceEventID number.  When events
    are disabled there are two options for assigning TraceEventID numbers:
    1. Skip disabled events and don't assign them a number.
    2. Assign numbers for all events regardless of the disabled keyword.
    
    The simple trace backend and its binary file format uses approach #1.
    
    The tracetool infrastructure has been using approach #2 for a while.
    
    The result is that the numbers used in simple trace files do not
    correspond with TraceEventIDs.  In trace/simple.c we assumed that they
    are identical and therefore emitted bogus numbers.
    
    This patch fixes the bug by using TraceEventID for trace_event_id()
    while sticking to approach #1 for simple trace file numbers.  This
    preserves simple trace file format compatibility.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/scripts/tracetool/backend/simple.py b/scripts/tracetool/backend/simple.py
index 30faac9..3dde372 100644
--- a/scripts/tracetool/backend/simple.py
+++ b/scripts/tracetool/backend/simple.py
@@ -56,7 +56,7 @@ def c(events):
 
 
         out('',
-            '    TraceEvent *eventp = trace_event_id(%(event_id)s);',
+            '    TraceEvent *eventp = trace_event_id(%(event_enum)s);',
             '    bool _state = trace_event_get_state_dynamic(eventp);',
             '    if (!_state) {',
             '        return;',
@@ -65,6 +65,7 @@ def c(events):
             '    if (trace_record_start(&rec, %(event_id)s, %(size_str)s)) {',
             '        return; /* Trace Buffer Full, Event Dropped ! */',
             '    }',
+            event_enum = 'TRACE_' + event.name.upper(),
             event_id = num,
             size_str = sizestr,
             )
commit 05735a2a9cf37f5dc11ece998906431dda707258
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Thu Dec 12 15:50:11 2013 +0100

    trace: add glib 2.32+ static GMutex support
    
    The GStaticMutex API was deprecated in glib 2.32.  We cannot switch over
    to GMutex unconditionally since we would drop support for older glib
    versions.  But the deprecated API warnings during build are annoying so
    use static GMutex when possible.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/trace/simple.c b/trace/simple.c
index 410172e..57572c4 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -40,7 +40,17 @@
  * Trace records are written out by a dedicated thread.  The thread waits for
  * records to become available, writes them out, and then waits again.
  */
+#if GLIB_CHECK_VERSION(2, 32, 0)
+static GMutex trace_lock;
+#define lock_trace_lock() g_mutex_lock(&trace_lock)
+#define unlock_trace_lock() g_mutex_unlock(&trace_lock)
+#define get_trace_lock_mutex() (&trace_lock)
+#else
 static GStaticMutex trace_lock = G_STATIC_MUTEX_INIT;
+#define lock_trace_lock() g_static_mutex_lock(&trace_lock)
+#define unlock_trace_lock() g_static_mutex_unlock(&trace_lock)
+#define get_trace_lock_mutex() g_static_mutex_get_mutex(&trace_lock)
+#endif
 
 /* g_cond_new() was deprecated in glib 2.31 but we still need to support it */
 #if GLIB_CHECK_VERSION(2, 31, 0)
@@ -140,27 +150,26 @@ static bool get_trace_record(unsigned int idx, TraceRecord **recordptr)
  */
 static void flush_trace_file(bool wait)
 {
-    g_static_mutex_lock(&trace_lock);
+    lock_trace_lock();
     trace_available = true;
     g_cond_signal(trace_available_cond);
 
     if (wait) {
-        g_cond_wait(trace_empty_cond, g_static_mutex_get_mutex(&trace_lock));
+        g_cond_wait(trace_empty_cond, get_trace_lock_mutex());
     }
 
-    g_static_mutex_unlock(&trace_lock);
+    unlock_trace_lock();
 }
 
 static void wait_for_trace_records_available(void)
 {
-    g_static_mutex_lock(&trace_lock);
+    lock_trace_lock();
     while (!(trace_available && trace_writeout_enabled)) {
         g_cond_signal(trace_empty_cond);
-        g_cond_wait(trace_available_cond,
-                    g_static_mutex_get_mutex(&trace_lock));
+        g_cond_wait(trace_available_cond, get_trace_lock_mutex());
     }
     trace_available = false;
-    g_static_mutex_unlock(&trace_lock);
+    unlock_trace_lock();
 }
 
 static gpointer writeout_thread(gpointer opaque)
commit b618c28831eda2531acc5c1feb9dbb3047d19391
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Tue Jan 14 16:52:55 2014 +0100

    trace: [simple] Do not include "trace/simple.h" in generated tracer headers
    
    The header is not necessary, given that the simple backend does not define any
    inlined tracing routines.
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/scripts/tracetool/backend/simple.py b/scripts/tracetool/backend/simple.py
index 37ef599..30faac9 100644
--- a/scripts/tracetool/backend/simple.py
+++ b/scripts/tracetool/backend/simple.py
@@ -93,9 +93,6 @@ def c(events):
 
 
 def h(events):
-    out('#include "trace/simple.h"',
-        '')
-
     for event in events:
         out('void trace_%(name)s(%(args)s);',
             name = event.name,
diff --git a/trace/simple.c b/trace/simple.c
index 1e3f691..410172e 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -19,6 +19,7 @@
 #include "qemu/timer.h"
 #include "trace.h"
 #include "trace/control.h"
+#include "trace/simple.h"
 
 /** Trace file header event ID */
 #define HEADER_EVENT_ID (~(uint64_t)0) /* avoids conflicting with TraceEventIDs */
commit 8a745f2a9296ad2cf6bda33534ed298f2625a4ad
Author: Michael Mueller <mimu at linux.vnet.ibm.com>
Date:   Mon Sep 23 16:36:54 2013 +0200

    tracing: start trace processing thread in final child process
    
    When running with trace backend e.g. "simple" the writer thread needs to be
    implemented in the same process context as the trace points that will be
    processed. Under libvirtd control, qemu gets first started in daemonized
    mode to privide its capabilities. Creating the writer thread in the initial
    process context then leads to a dead lock because the thread gets termined
    together with the initial parent. (-daemonize)
    
    Signed-off-by: Michael Mueller <mimu at linux.vnet.ibm.com>
    Signed-off-by: Christian Borntraeger <borntraeger at de.ibm.com>
    [minor whitespace fixes]
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/vl.c b/vl.c
index 7f4fe0d..63f4d55 100644
--- a/vl.c
+++ b/vl.c
@@ -3879,8 +3879,10 @@ int main(int argc, char **argv, char **envp)
         qemu_set_log(mask);
     }
 
-    if (!trace_backend_init(trace_events, trace_file)) {
-        exit(1);
+    if (!is_daemonized()) {
+        if (!trace_backend_init(trace_events, trace_file)) {
+            exit(1);
+        }
     }
 
     /* If no data_dir is specified then try to find it relative to the
@@ -4379,6 +4381,12 @@ int main(int argc, char **argv, char **envp)
 
     os_setup_post();
 
+    if (is_daemonized()) {
+        if (!trace_backend_init(trace_events, trace_file)) {
+            exit(1);
+        }
+    }
+
     main_loop();
     bdrv_close_all();
     pause_all_vcpus();
commit 1f149e721feb617d14a3ee4f5911c47b29866a54
Author: Kusanagi Kouichi <slash at ac.auone-net.jp>
Date:   Sat Jan 18 14:38:45 2014 +0900

    tap-linux: Get features once and use it many times
    
    Signed-off-by: Kusanagi Kouichi <slash at ac.auone-net.jp>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/net/tap-linux.c b/net/tap-linux.c
index 36c09e2..812bf2d 100644
--- a/net/tap-linux.c
+++ b/net/tap-linux.c
@@ -52,14 +52,17 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
     memset(&ifr, 0, sizeof(ifr));
     ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
 
-    if (ioctl(fd, TUNGETFEATURES, &features) == 0 &&
-        features & IFF_ONE_QUEUE) {
+    if (ioctl(fd, TUNGETFEATURES, &features) == -1) {
+        error_report("warning: TUNGETFEATURES failed: %s", strerror(errno));
+        features = 0;
+    }
+
+    if (features & IFF_ONE_QUEUE) {
         ifr.ifr_flags |= IFF_ONE_QUEUE;
     }
 
     if (*vnet_hdr) {
-        if (ioctl(fd, TUNGETFEATURES, &features) == 0 &&
-            features & IFF_VNET_HDR) {
+        if (features & IFF_VNET_HDR) {
             *vnet_hdr = 1;
             ifr.ifr_flags |= IFF_VNET_HDR;
         } else {
@@ -82,8 +85,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
     }
 
     if (mq_required) {
-        if ((ioctl(fd, TUNGETFEATURES, &features) != 0) ||
-            !(features & IFF_MULTI_QUEUE)) {
+        if (!(features & IFF_MULTI_QUEUE)) {
             error_report("multiqueue required, but no kernel "
                          "support for IFF_MULTI_QUEUE available");
             close(fd);
commit c444dfabfc21cb5f093862100e333b808eea32e4
Author: Roy Franz <roy.franz at linaro.org>
Date:   Tue Jan 7 20:19:52 2014 -0800

    Fix lan9118 buffer length handling
    
    The 9118 ethernet controller supports transmission of multi-buffer packets
    with arbitrary byte alignment of the start and end bytes.  All writes to
    the packet fifo are 32 bits, so the controller discards bytes at the beginning
    and end of each buffer based on the 'Data start offset' and 'Buffer size'
    of the TX command 'A' format.
    
    This patch uses the provided buffer length to limit the bytes transmitted.
    Previously all the bytes of the last 32-bit word written to the TX fifo
    were added to the internal transmit buffer structure resulting in more bytes
    being transmitted than were submitted to the hardware in the command.  This
    resulted in extra bytes being inserted into the middle of multi-buffer
    packets when the non-final buffers had non-32bit aligned ending addresses.
    
    Signed-off-by: Roy Franz <roy.franz at linaro.org>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
index bb0c503..e528290 100644
--- a/hw/net/lan9118.c
+++ b/hw/net/lan9118.c
@@ -763,7 +763,7 @@ static void tx_fifo_push(lan9118_state *s, uint32_t val)
         if (s->txp->buffer_size <= 0 && s->txp->pad != 0) {
             s->txp->pad--;
         } else {
-            n = 4;
+            n = MIN(4, s->txp->buffer_size + s->txp->offset);
             while (s->txp->offset) {
                 val >>= 8;
                 n--;
commit 2ad657e3f3af66def47554186a58f1748787a527
Author: Roy Franz <roy.franz at linaro.org>
Date:   Tue Jan 7 20:19:51 2014 -0800

    Fix lan9118 TX "CMD A" handling
    
    The 9118 ethernet controller supports transmission of multi-buffer packets
    with arbitrary byte alignment of the start and end bytes.  All writes to
    the packet fifo are 32 bits, so the controller discards bytes at the beginning
    and end of each buffer based on the 'Data start offset' and 'Buffer size'
    of the TX command 'A' format.
    
    This patch changes the buffer size and offset internal state variables to be
    updated on every "TX command A" write.  Previously they were only updated for
    the first segment, which resulted incorrect behavior for packets with more
    than one segment. Each segment of the packet has its own CMD A command, with
    its own buffer size and start offset.
    
    Also update extraction of fields from the CMD A word to use extract32().
    
    Signed-off-by: Roy Franz <roy.franz at linaro.org>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
index 2315f99..bb0c503 100644
--- a/hw/net/lan9118.c
+++ b/hw/net/lan9118.c
@@ -727,14 +727,14 @@ static void tx_fifo_push(lan9118_state *s, uint32_t val)
         s->txp->cmd_a = val & 0x831f37ff;
         s->txp->fifo_used++;
         s->txp->state = TX_B;
+        s->txp->buffer_size = extract32(s->txp->cmd_a, 0, 11);
+        s->txp->offset = extract32(s->txp->cmd_a, 16, 5);
         break;
     case TX_B:
         if (s->txp->cmd_a & 0x2000) {
             /* First segment */
             s->txp->cmd_b = val;
             s->txp->fifo_used++;
-            s->txp->buffer_size = s->txp->cmd_a & 0x7ff;
-            s->txp->offset = (s->txp->cmd_a >> 16) & 0x1f;
             /* End alignment does not include command words.  */
             n = (s->txp->buffer_size + s->txp->offset + 3) >> 2;
             switch ((n >> 24) & 3) {
commit 4bf2c138ddefc6ff17f6c4b947320c60aa0c38a0
Author: Hani Benhabiles <kroosec at gmail.com>
Date:   Thu Jan 9 19:34:27 2014 +0100

    net: Use g_strdup_printf instead of snprintf.
    
    assign_name() in net/net.c is using snprintf + g_strdup to get the same
    result as g_strdup_printf.
    
    Signed-off-by: Hani Benhabiles <kroosec at gmail.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/net/net.c b/net/net.c
index f8db85f..2c3af20 100644
--- a/net/net.c
+++ b/net/net.c
@@ -164,7 +164,6 @@ void qemu_macaddr_default_if_unset(MACAddr *macaddr)
 static char *assign_name(NetClientState *nc1, const char *model)
 {
     NetClientState *nc;
-    char buf[256];
     int id = 0;
 
     QTAILQ_FOREACH(nc, &net_clients, next) {
@@ -176,9 +175,7 @@ static char *assign_name(NetClientState *nc1, const char *model)
         }
     }
 
-    snprintf(buf, sizeof(buf), "%s.%d", model, id);
-
-    return g_strdup(buf);
+    return g_strdup_printf("%s.%d", model, id);
 }
 
 static void qemu_net_client_destructor(NetClientState *nc)
commit a75143eda2ddf581b51e96c000974bcdfe2cbd10
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun Jan 26 12:39:55 2014 +0200

    MAINTAINERS: add self as virtio co-maintainer
    
    This will help make sure I get Cc'd on patches.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/MAINTAINERS b/MAINTAINERS
index fb53242..adc5973 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -610,6 +610,7 @@ F: hw/*/*vhost*
 
 virtio
 M: Anthony Liguori <aliguori at amazon.com>
+M: Michael S. Tsirkin <mst at redhat.com>
 S: Supported
 F: hw/*/virtio*
 
commit 4e17997d49d6e3a426fd465dfbdf5a4dc04639f4
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Dec 16 13:55:06 2013 +0200

    q35: document gigabyte_align
    
    Document the logic behind the below/above 4G split.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 7104645..a7f6260 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -51,6 +51,10 @@
 static bool has_pci_info;
 static bool has_acpi_build = true;
 static bool smbios_type1_defaults = true;
+/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
+ * host addresses aligned at 1Gbyte boundaries.  This way we can use 1GByte
+ * pages in the host.
+ */
 static bool gigabyte_align = true;
 
 /* PC hardware initialisation */
@@ -93,6 +97,15 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
 
     kvmclock_create();
 
+    /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory
+     * and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping
+     * also known as MMCFG).
+     * If it doesn't, we need to split it in chunks below and above 4G.
+     * In any case, try to make sure that guest addresses aligned at
+     * 1G boundaries get mapped to host addresses aligned at 1G boundaries.
+     * For old machine types, use whatever split we used historically to avoid
+     * breaking migration.
+     */
     if (args->ram_size >= 0xb0000000) {
         ram_addr_t lowmem = gigabyte_align ? 0x80000000 : 0xb0000000;
         above_4g_mem_size = args->ram_size - lowmem;
commit 9a305c8fc7bb567e9f754ddfe5fb102aaeeb770a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Dec 16 10:11:28 2013 +0100

    q35: gigabyte alignment for ram
    
    Map 2G (q35) of memory below 4G, so the RAM pieces
    are nicely aligned to gigabyte borders.
    
    Keep old memory layout for (a) old machine types and (b) in case all
    memory fits below 4G and thus we don't have to split RAM into pieces
    in the first place.  The later makes sure this change doesn't take
    away memory from 32bit guests.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 07f38ff..7104645 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -51,6 +51,7 @@
 static bool has_pci_info;
 static bool has_acpi_build = true;
 static bool smbios_type1_defaults = true;
+static bool gigabyte_align = true;
 
 /* PC hardware initialisation */
 static void pc_q35_init(QEMUMachineInitArgs *args)
@@ -93,8 +94,9 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
     kvmclock_create();
 
     if (args->ram_size >= 0xb0000000) {
-        above_4g_mem_size = args->ram_size - 0xb0000000;
-        below_4g_mem_size = 0xb0000000;
+        ram_addr_t lowmem = gigabyte_align ? 0x80000000 : 0xb0000000;
+        above_4g_mem_size = args->ram_size - lowmem;
+        below_4g_mem_size = lowmem;
     } else {
         above_4g_mem_size = 0;
         below_4g_mem_size = args->ram_size;
@@ -228,6 +230,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
 static void pc_compat_1_7(QEMUMachineInitArgs *args)
 {
     smbios_type1_defaults = false;
+    gigabyte_align = false;
 }
 
 static void pc_compat_1_6(QEMUMachineInitArgs *args)
commit 4c8a949b2416158a311abefc09a20153aa107e93
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Jan 9 17:12:43 2014 -0200

    acpi: Fix PCI hole handling on build_srat()
    
    The original SeaBIOS code used the RamSize variable, that was used by
    SeaBIOS for the size of RAM below 4GB, not for all RAM. When copied to
    QEMU, the code was changed to use the full RAM size, and this broke the
    build_srat() code that handles the PCI hole.
    
    Change build_srat() to use ram_size_below_4g instead of ram_size, to
    restore the original behavior from SeaBIOS.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 9cd3d0e..50e83f3 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1080,16 +1080,16 @@ build_srat(GArray *table_data, GArray *linker,
         next_base = mem_base + mem_len;
 
         /* Cut out the ACPI_PCI hole */
-        if (mem_base <= guest_info->ram_size &&
-            next_base > guest_info->ram_size) {
-            mem_len -= next_base - guest_info->ram_size;
+        if (mem_base <= guest_info->ram_size_below_4g &&
+            next_base > guest_info->ram_size_below_4g) {
+            mem_len -= next_base - guest_info->ram_size_below_4g;
             if (mem_len > 0) {
                 numamem = acpi_data_push(table_data, sizeof *numamem);
                 acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
             }
             mem_base = 1ULL << 32;
-            mem_len = next_base - guest_info->ram_size;
-            next_base += (1ULL << 32) - guest_info->ram_size;
+            mem_len = next_base - guest_info->ram_size_below_4g;
+            next_base += (1ULL << 32) - guest_info->ram_size_below_4g;
         }
         numamem = acpi_data_push(table_data, sizeof *numamem);
         acpi_build_srat_memory(numamem, mem_base, mem_len, i - 1, 1);
commit f30ee8a9682be4abfcb05c6389894f8cfc35c3f0
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Jan 9 17:12:42 2014 -0200

    pc: Save size of RAM below 4GB
    
    The ram_below_4g value will be useful in other places, such as the ACPI
    table code, and other code that currently requires passing
    below_4g_mem_size around in function arguments.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 6f0be37..348b15f 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1072,6 +1072,7 @@ PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
     PcGuestInfo *guest_info = &guest_info_state->info;
     int i, j;
 
+    guest_info->ram_size_below_4g = below_4g_mem_size;
     guest_info->ram_size = below_4g_mem_size + above_4g_mem_size;
     guest_info->apic_id_limit = pc_apic_id_limit(max_cpus);
     guest_info->apic_xrupt_override = kvm_allows_irq0_override();
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 92eabeb..3e1e81b 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -35,7 +35,7 @@ typedef struct PcPciInfo {
 struct PcGuestInfo {
     bool has_pci_info;
     bool isapc_ram_fw;
-    hwaddr ram_size;
+    hwaddr ram_size, ram_size_below_4g;
     unsigned apic_id_limit;
     bool apic_xrupt_override;
     uint64_t numa_nodes;
commit 306077640a652e090779498aadbeb0c605feaacd
Author: Marcel Apfelbaum <marcel.a at redhat.com>
Date:   Tue Jan 21 18:37:51 2014 +0200

    hw/pci: fix error flow in pci multifunction init
    
    Scenario:
      - There is a non multifunction pci device A on 00:0X.0.
      - Hot-plug another multifunction pci device B at 00:0X.1.
      - The operation will fail of course.
      - Try to hot-plug the B device 2-3 more times, qemu will crash.
    
    Reason: The error flow leaves the B's address space into global address spaces
    list, but the device object is freed. Fixed that.
    
    Signed-off-by: Marcel Apfelbaum <marcel.a at redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 2aca8a4..1221f32 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -793,6 +793,15 @@ static void pci_config_free(PCIDevice *pci_dev)
     g_free(pci_dev->used);
 }
 
+static void do_pci_unregister_device(PCIDevice *pci_dev)
+{
+    pci_dev->bus->devices[pci_dev->devfn] = NULL;
+    pci_config_free(pci_dev);
+
+    address_space_destroy(&pci_dev->bus_master_as);
+    memory_region_destroy(&pci_dev->bus_master_enable_region);
+}
+
 /* -1 for devfn means auto assign */
 static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
                                          const char *name, int devfn)
@@ -858,7 +867,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
         pci_init_mask_bridge(pci_dev);
     }
     if (pci_init_multifunction(bus, pci_dev)) {
-        pci_config_free(pci_dev);
+        do_pci_unregister_device(pci_dev);
         return NULL;
     }
 
@@ -873,15 +882,6 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     return pci_dev;
 }
 
-static void do_pci_unregister_device(PCIDevice *pci_dev)
-{
-    pci_dev->bus->devices[pci_dev->devfn] = NULL;
-    pci_config_free(pci_dev);
-
-    address_space_destroy(&pci_dev->bus_master_as);
-    memory_region_destroy(&pci_dev->bus_master_enable_region);
-}
-
 static void pci_unregister_io_regions(PCIDevice *pci_dev)
 {
     PCIIORegion *r;
commit b8124cecb55b3bc4e7dee0ff34b294942044d74a
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Jan 20 14:00:12 2014 +0200

    acpi-test: update expected AML since recent changes
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/tests/acpi-test-data/pc/DSDT b/tests/acpi-test-data/pc/DSDT
index b12e5eb..fbf1c3e 100644
Binary files a/tests/acpi-test-data/pc/DSDT and b/tests/acpi-test-data/pc/DSDT differ
diff --git a/tests/acpi-test-data/pc/SSDT b/tests/acpi-test-data/pc/SSDT
index 5ab1b96..a51c68e 100644
Binary files a/tests/acpi-test-data/pc/SSDT and b/tests/acpi-test-data/pc/SSDT differ
diff --git a/tests/acpi-test-data/q35/DSDT b/tests/acpi-test-data/q35/DSDT
index 59243b9..5086b83 100644
Binary files a/tests/acpi-test-data/q35/DSDT and b/tests/acpi-test-data/q35/DSDT differ
diff --git a/tests/acpi-test-data/q35/SSDT b/tests/acpi-test-data/q35/SSDT
index 186e748..9c6cad8 100644
Binary files a/tests/acpi-test-data/q35/SSDT and b/tests/acpi-test-data/q35/SSDT differ
commit 2867534f3d1daa970eba2afdb9b401388bd75b56
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Jan 9 17:36:39 2014 +0100

    pc: ACPI: update acpi-dsdt.hex.generated q35-acpi-dsdt.hex.generated
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/i386/acpi-dsdt.hex.generated b/hw/i386/acpi-dsdt.hex.generated
index f8bd4ea..1e58801 100644
--- a/hw/i386/acpi-dsdt.hex.generated
+++ b/hw/i386/acpi-dsdt.hex.generated
@@ -3,12 +3,12 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x53,
 0x44,
 0x54,
-0x37,
+0x87,
 0x11,
 0x0,
 0x0,
 0x1,
-0xd8,
+0xb8,
 0x42,
 0x58,
 0x50,
@@ -860,8 +860,8 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x4e,
 0x1,
 0x10,
-0x4c,
-0x1b,
+0x4b,
+0x1e,
 0x2f,
 0x3,
 0x5f,
@@ -879,6 +879,53 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x5b,
 0x82,
 0x2d,
+0x53,
+0x4d,
+0x43,
+0x5f,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x6,
+0x10,
+0x0,
+0x1,
+0x8,
+0x5f,
+0x53,
+0x54,
+0x41,
+0xb,
+0x0,
+0xff,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x10,
+0xa,
+0xd,
+0x47,
+0x1,
+0x0,
+0x3,
+0x0,
+0x3,
+0x1,
+0x20,
+0x22,
+0x40,
+0x0,
+0x79,
+0x0,
+0x5b,
+0x82,
+0x2d,
 0x52,
 0x54,
 0x43,
@@ -1305,7 +1352,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x79,
 0x0,
 0x10,
-0x4b,
+0x48,
 0x8,
 0x2e,
 0x5f,
@@ -1371,79 +1418,76 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x45,
 0x4a,
 0x20,
+0x5b,
+0x80,
+0x42,
+0x4e,
+0x4d,
+0x52,
+0x1,
+0xb,
+0x10,
+0xae,
+0xa,
+0x4,
+0x5b,
+0x81,
+0xb,
+0x42,
+0x4e,
+0x4d,
+0x52,
+0x43,
+0x42,
+0x4e,
+0x55,
+0x4d,
+0x20,
+0x5b,
+0x1,
+0x42,
+0x4c,
+0x43,
+0x4b,
+0x0,
 0x14,
-0x11,
+0x25,
 0x50,
 0x43,
 0x45,
 0x4a,
-0x1,
+0x2,
+0x5b,
+0x23,
+0x42,
+0x4c,
+0x43,
+0x4b,
+0xff,
+0xff,
 0x70,
-0x79,
-0x1,
 0x68,
-0x0,
 0x42,
-0x30,
-0x45,
-0x4a,
-0xa4,
-0x0,
-0x14,
-0x36,
-0x50,
-0x43,
 0x4e,
-0x46,
-0x0,
-0x70,
-0x0,
-0x60,
-0xa2,
-0x2c,
-0x95,
-0x60,
-0xa,
-0x1f,
-0x75,
-0x60,
-0xa0,
-0x11,
-0x7b,
-0x50,
-0x43,
-0x49,
 0x55,
+0x4d,
+0x70,
 0x79,
 0x1,
-0x60,
+0x69,
 0x0,
-0x0,
-0x50,
-0x43,
-0x4e,
-0x54,
-0x60,
-0x1,
-0xa0,
-0x12,
-0x7b,
-0x50,
+0x42,
+0x30,
+0x45,
+0x4a,
+0x5b,
+0x27,
+0x42,
+0x4c,
 0x43,
-0x49,
-0x44,
-0x79,
-0x1,
-0x60,
-0x0,
+0x4b,
+0xa4,
 0x0,
-0x50,
-0x43,
-0x4e,
-0x54,
-0x60,
-0xa,
-0x3,
 0x10,
 0x4a,
 0xa0,
@@ -4248,8 +4292,8 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x75,
 0x60,
 0x10,
-0x4e,
-0x9,
+0x42,
+0xc,
 0x5f,
 0x47,
 0x50,
@@ -4277,12 +4321,31 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x30,
 0x0,
 0x14,
-0x15,
+0x39,
 0x5f,
 0x45,
 0x30,
 0x31,
 0x0,
+0x5b,
+0x23,
+0x5c,
+0x2f,
+0x3,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x42,
+0x4c,
+0x43,
+0x4b,
+0xff,
+0xff,
 0x5c,
 0x2f,
 0x3,
@@ -4297,7 +4360,24 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x50,
 0x43,
 0x4e,
-0x46,
+0x54,
+0x5b,
+0x27,
+0x5c,
+0x2f,
+0x3,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x42,
+0x4c,
+0x43,
+0x4b,
 0x14,
 0x10,
 0x5f,
@@ -4407,3 +4487,6 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x46,
 0x0
 };
+static unsigned short piix_dsdt_applesmc_sta[] = {
+0x384
+};
diff --git a/hw/i386/q35-acpi-dsdt.hex.generated b/hw/i386/q35-acpi-dsdt.hex.generated
index 111ad3e..6d885a9 100644
--- a/hw/i386/q35-acpi-dsdt.hex.generated
+++ b/hw/i386/q35-acpi-dsdt.hex.generated
@@ -3,12 +3,12 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 0x53,
 0x44,
 0x54,
-0xb0,
+0xdf,
 0x1c,
 0x0,
 0x0,
 0x1,
-0xfe,
+0xff,
 0x42,
 0x58,
 0x50,
@@ -1033,8 +1033,8 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 0x4e,
 0x1,
 0x10,
-0x4c,
-0x1b,
+0x4b,
+0x1e,
 0x2f,
 0x3,
 0x5f,
@@ -1052,6 +1052,53 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 0x5b,
 0x82,
 0x2d,
+0x53,
+0x4d,
+0x43,
+0x5f,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x6,
+0x10,
+0x0,
+0x1,
+0x8,
+0x5f,
+0x53,
+0x54,
+0x41,
+0xb,
+0x0,
+0xff,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x10,
+0xa,
+0xd,
+0x47,
+0x1,
+0x0,
+0x3,
+0x0,
+0x3,
+0x1,
+0x20,
+0x22,
+0x40,
+0x0,
+0x79,
+0x0,
+0x5b,
+0x82,
+0x2d,
 0x52,
 0x54,
 0x43,
@@ -7229,12 +7276,19 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 0x30,
 0x0,
 0x14,
-0x10,
+0x6,
 0x5f,
 0x4c,
 0x30,
 0x31,
 0x0,
+0x14,
+0x10,
+0x5f,
+0x45,
+0x30,
+0x32,
+0x0,
 0x5c,
 0x2e,
 0x5f,
@@ -7250,13 +7304,6 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 0x5f,
 0x4c,
 0x30,
-0x32,
-0x0,
-0x14,
-0x6,
-0x5f,
-0x4c,
-0x30,
 0x33,
 0x0,
 0x14,
@@ -7344,3 +7391,6 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 0x46,
 0x0
 };
+static unsigned short q35_dsdt_applesmc_sta[] = {
+0x431
+};
diff --git a/hw/i386/ssdt-pcihp.hex.generated b/hw/i386/ssdt-pcihp.hex.generated
index b3c2cd5..610a631 100644
--- a/hw/i386/ssdt-pcihp.hex.generated
+++ b/hw/i386/ssdt-pcihp.hex.generated
@@ -5,19 +5,19 @@ static unsigned char ssdt_pcihp_adr[] = {
 0x44
 };
 static unsigned char ssdt_pcihp_end[] = {
-0x58
+0x5b
 };
 static unsigned char ssdp_pcihp_aml[] = {
 0x53,
 0x53,
 0x44,
 0x54,
-0x58,
+0x5b,
 0x0,
 0x0,
 0x0,
 0x1,
-0x76,
+0xe8,
 0x42,
 0x58,
 0x50,
@@ -45,7 +45,7 @@ static unsigned char ssdp_pcihp_aml[] = {
 0x13,
 0x20,
 0x10,
-0x33,
+0x36,
 0x5c,
 0x2e,
 0x5f,
@@ -58,7 +58,7 @@ static unsigned char ssdp_pcihp_aml[] = {
 0x30,
 0x5b,
 0x82,
-0x26,
+0x29,
 0x53,
 0x41,
 0x41,
@@ -81,17 +81,20 @@ static unsigned char ssdp_pcihp_aml[] = {
 0xaa,
 0x0,
 0x14,
-0xf,
+0x12,
 0x5f,
 0x45,
 0x4a,
 0x30,
 0x1,
-0xa4,
 0x50,
 0x43,
 0x45,
 0x4a,
+0x42,
+0x53,
+0x45,
+0x4c,
 0x5f,
 0x53,
 0x55,
@@ -103,6 +106,3 @@ static unsigned char ssdt_pcihp_start[] = {
 static unsigned char ssdt_pcihp_id[] = {
 0x3d
 };
-static unsigned char ssdt_pcihp_ej0[] = {
-0x4a
-};
diff --git a/hw/i386/ssdt-proc.hex.generated b/hw/i386/ssdt-proc.hex.generated
index bb9920d..97e28d4 100644
--- a/hw/i386/ssdt-proc.hex.generated
+++ b/hw/i386/ssdt-proc.hex.generated
@@ -11,7 +11,7 @@ static unsigned char ssdp_proc_aml[] = {
 0x0,
 0x0,
 0x1,
-0xb8,
+0x78,
 0x42,
 0x58,
 0x50,
@@ -47,8 +47,8 @@ static unsigned char ssdp_proc_aml[] = {
 0x41,
 0x41,
 0xaa,
-0x10,
-0xb0,
+0x0,
+0x0,
 0x0,
 0x0,
 0x0,
commit e4cf8ed08a1b8b996f9939de0d8eda4ed8a3d25e
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Jan 9 17:36:38 2014 +0100

    pc: ACPI: unify source of CPU hotplug IO base/len
    
    use C headers defines as source of IO base/len for respective
    values in ASL code.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 12f8dde..5d55a3c 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -51,8 +51,6 @@
 #define PCI_EJ_BASE 0xae08
 #define PCI_RMV_BASE 0xae0c
 
-#define PIIX4_PROC_BASE 0xaf00
-
 #define PIIX4_PCI_HOTPLUG_STATUS 2
 
 struct pci_status {
@@ -706,7 +704,8 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
         pci_bus_hotplug(bus, piix4_device_hotplug, DEVICE(s));
     }
 
-    AcpiCpuHotplug_init(parent, OBJECT(s), &s->gpe_cpu, PIIX4_PROC_BASE);
+    AcpiCpuHotplug_init(parent, OBJECT(s), &s->gpe_cpu,
+                        PIIX4_CPU_HOTPLUG_IO_BASE);
     s->cpu_added_notifier.notify = piix4_cpu_added_req;
     qemu_register_cpu_added_notifier(&s->cpu_added_notifier);
 }
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index d58a103..3df1612 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -17,7 +17,7 @@ iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
 ifdef IASL
 #IASL Present. Generate hex files from .dsl
 hw/i386/%.hex: $(SRC_PATH)/hw/i386/%.dsl $(SRC_PATH)/scripts/acpi_extract_preprocess.py $(SRC_PATH)/scripts/acpi_extract.py
-	$(call quiet-command, cpp -P $(QEMU_DGFLAGS) $< -o $*.dsl.i.orig, "  CPP $(TARGET_DIR)$*.dsl.i.orig")
+	$(call quiet-command, cpp -P $(QEMU_DGFLAGS) $(QEMU_INCLUDES) $< -o $*.dsl.i.orig, "  CPP $(TARGET_DIR)$*.dsl.i.orig")
 	$(call quiet-command, $(PYTHON) $(SRC_PATH)/scripts/acpi_extract_preprocess.py $*.dsl.i.orig > $*.dsl.i, "  ACPI_PREPROCESS $(TARGET_DIR)$*.dsl.i")
 	$(call quiet-command, $(IASL) $(call iasl-option,$(IASL),-Pn,) -vs -l -tc -p $* $*.dsl.i $(if $(V), , > /dev/null) 2>&1 ,"  IASL $(TARGET_DIR)$*.dsl.i")
 	$(call quiet-command, $(PYTHON) $(SRC_PATH)/scripts/acpi_extract.py $*.lst > $*.off, "  ACPI_EXTRACT $(TARGET_DIR)$*.off")
diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
index f91eafd..dee4843 100644
--- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl
+++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
@@ -53,7 +53,7 @@ Scope(\_SB) {
         Sleep(200)
     }
 
-#define CPU_STATUS_LEN 32
+#define CPU_STATUS_LEN ACPI_GPE_PROC_LEN
     OperationRegion(PRST, SystemIO, CPU_STATUS_BASE, CPU_STATUS_LEN)
     Field(PRST, ByteAcc, NoLock, Preserve) {
         PRS, 256
diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
index d89dcda..b23d5e0 100644
--- a/hw/i386/acpi-dsdt.dsl
+++ b/hw/i386/acpi-dsdt.dsl
@@ -329,7 +329,8 @@ DefinitionBlock (
         }
     }
 
-#define CPU_STATUS_BASE 0xaf00
+#include "hw/acpi/cpu_hotplug_defs.h"
+#define CPU_STATUS_BASE PIIX4_CPU_HOTPLUG_IO_BASE
 #include "acpi-dsdt-cpu-hotplug.dsl"
 
 
diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
index 9e070ee..d618e9e 100644
--- a/hw/i386/q35-acpi-dsdt.dsl
+++ b/hw/i386/q35-acpi-dsdt.dsl
@@ -421,7 +421,8 @@ DefinitionBlock (
         define_gsi_link(GSIH, 0, 0x17)
     }
 
-#define CPU_STATUS_BASE 0x0CD8
+#include "hw/acpi/cpu_hotplug_defs.h"
+#define CPU_STATUS_BASE ICH9_CPU_HOTPLUG_IO_BASE
 #include "acpi-dsdt-cpu-hotplug.dsl"
 
 
diff --git a/include/hw/acpi/cpu_hotplug_defs.h b/include/hw/acpi/cpu_hotplug_defs.h
index 47a35e3..2725b50 100644
--- a/include/hw/acpi/cpu_hotplug_defs.h
+++ b/include/hw/acpi/cpu_hotplug_defs.h
@@ -19,5 +19,6 @@
 #define ACPI_CPU_HOTPLUG_STATUS 4
 #define ACPI_GPE_PROC_LEN 32
 #define ICH9_CPU_HOTPLUG_IO_BASE 0x0CD8
+#define PIIX4_CPU_HOTPLUG_IO_BASE 0xaf00
 
 #endif
commit 61a3f63560ccd2b5e8c9134e9213a1cff36f26bf
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Jan 9 17:36:37 2014 +0100

    pc: ACPI: expose PRST IO range via _CRS
    
    .. so OSPM could notice resource conflict if there is any.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
index 1dfbb4f..f91eafd 100644
--- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl
+++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
@@ -16,6 +16,7 @@
 /****************************************************************
  * CPU hotplug
  ****************************************************************/
+#define CPU_HOTPLUG_RESOURCE_DEVICE PRES
 
 Scope(\_SB) {
     /* Objects filled in by run-time generated SSDT */
@@ -52,7 +53,8 @@ Scope(\_SB) {
         Sleep(200)
     }
 
-    OperationRegion(PRST, SystemIO, CPU_STATUS_BASE, 32)
+#define CPU_STATUS_LEN 32
+    OperationRegion(PRST, SystemIO, CPU_STATUS_BASE, CPU_STATUS_LEN)
     Field(PRST, ByteAcc, NoLock, Preserve) {
         PRS, 256
     }
@@ -89,4 +91,14 @@ Scope(\_SB) {
             Increment(Local0)
         }
     }
+
+    Device(CPU_HOTPLUG_RESOURCE_DEVICE) {
+        Name(_HID, "ACPI0004")
+
+        Name(_CRS, ResourceTemplate() {
+            IO(Decode16, CPU_STATUS_BASE, CPU_STATUS_BASE, 0, CPU_STATUS_LEN)
+        })
+
+        Name(_STA, 0xB) /* present, functioning, decoding, not shown in UI */
+    }
 }
commit 562e56a9f8e627b2a4ef60037507361ce3cb4e6d
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Jan 9 17:36:36 2014 +0100

    pc: Q35 DSDT: exclude CPU hotplug IO range from PCI bus resources
    
    ... for range defined at hw/acpi/ich9.c:ICH9_PROC_BASE
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/i386/acpi-dsdt-pci-crs.dsl b/hw/i386/acpi-dsdt-pci-crs.dsl
index 8b631d1..4648e90 100644
--- a/hw/i386/acpi-dsdt-pci-crs.dsl
+++ b/hw/i386/acpi-dsdt-pci-crs.dsl
@@ -30,13 +30,6 @@ Scope(\_SB.PCI0) {
             0x01,               // Address Alignment
             0x08,               // Address Length
             )
-        WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
-            0x0000,             // Address Space Granularity
-            0x0000,             // Address Range Minimum
-            0x0CF7,             // Address Range Maximum
-            0x0000,             // Address Translation Offset
-            0x0CF8,             // Address Length
-            ,, , TypeStatic)
         BOARD_SPECIFIC_PCI_RESOURSES
         DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
             0x00000000,         // Address Space Granularity
diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
index f501c8d..d89dcda 100644
--- a/hw/i386/acpi-dsdt.dsl
+++ b/hw/i386/acpi-dsdt.dsl
@@ -38,6 +38,13 @@ DefinitionBlock (
 #define BOARD_SPECIFIC_PCI_RESOURSES \
      WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
          0x0000, \
+         0x0000, \
+         0x0CF7, \
+         0x0000, \
+         0x0CF8, \
+         ,, , TypeStatic) \
+     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
+         0x0000, \
          0x0D00, \
          0xADFF, \
          0x0000, \
diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
index f3e5921..9e070ee 100644
--- a/hw/i386/q35-acpi-dsdt.dsl
+++ b/hw/i386/q35-acpi-dsdt.dsl
@@ -51,6 +51,14 @@ DefinitionBlock (
 #define BOARD_SPECIFIC_PCI_RESOURSES \
      WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
          0x0000, \
+         0x0000, \
+         0x0CD7, \
+         0x0000, \
+         0x0CD8, \
+         ,, , TypeStatic) \
+     /* 0xcd8-0xcf7 hole for CPU hotplug, hw/acpi/ich9.c:ICH9_PROC_BASE */ \
+     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
+         0x0000, \
          0x0D00, \
          0xFFFF, \
          0x0000, \
commit 1aa149b479a479323121251f1e8e676765cb354d
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Jan 9 17:36:35 2014 +0100

    pc: PIIX DSDT: exclude CPU/PCI hotplug & GPE0 IO range from PCI bus resources
    
    .. so that they might not be used by PCI devices.
    
    Note:
    Resort to concatenating templates with preprocessor help,
    because 1.0b spec isn't supporting ConcatenateResTemplate,
    as result Windows XP fails to execute PCI0._CRS method if
    ConcatenateResTemplate() is used.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/i386/acpi-dsdt-pci-crs.dsl b/hw/i386/acpi-dsdt-pci-crs.dsl
index b375a19..8b631d1 100644
--- a/hw/i386/acpi-dsdt-pci-crs.dsl
+++ b/hw/i386/acpi-dsdt-pci-crs.dsl
@@ -37,13 +37,7 @@ Scope(\_SB.PCI0) {
             0x0000,             // Address Translation Offset
             0x0CF8,             // Address Length
             ,, , TypeStatic)
-        WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
-            0x0000,             // Address Space Granularity
-            0x0D00,             // Address Range Minimum
-            0xFFFF,             // Address Range Maximum
-            0x0000,             // Address Translation Offset
-            0xF300,             // Address Length
-            ,, , TypeStatic)
+        BOARD_SPECIFIC_PCI_RESOURSES
         DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
             0x00000000,         // Address Space Granularity
             0x000A0000,         // Address Range Minimum
diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
index 3dc4789..f501c8d 100644
--- a/hw/i386/acpi-dsdt.dsl
+++ b/hw/i386/acpi-dsdt.dsl
@@ -35,6 +35,38 @@ DefinitionBlock (
 /****************************************************************
  * PCI Bus definition
  ****************************************************************/
+#define BOARD_SPECIFIC_PCI_RESOURSES \
+     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
+         0x0000, \
+         0x0D00, \
+         0xADFF, \
+         0x0000, \
+         0xA100, \
+         ,, , TypeStatic) \
+     /* 0xae00-0xae0e hole for PCI hotplug, hw/acpi/piix4.c:PCI_HOTPLUG_ADDR */ \
+     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
+         0x0000, \
+         0xAE0F, \
+         0xAEFF, \
+         0x0000, \
+         0x00F1, \
+         ,, , TypeStatic) \
+     /* 0xaf00-0xaf1f hole for CPU hotplug, hw/acpi/piix4.c:PIIX4_PROC_BASE */ \
+     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
+         0x0000, \
+         0xAF20, \
+         0xAFDF, \
+         0x0000, \
+         0x00C0, \
+         ,, , TypeStatic) \
+     /* 0xafe0-0xafe3 hole for ACPI.GPE0, hw/acpi/piix4.c:GPE_BASE */ \
+     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
+         0x0000, \
+         0xAFE4, \
+         0xFFFF, \
+         0x0000, \
+         0x501C, \
+         ,, , TypeStatic)
 
     Scope(\_SB) {
         Device(PCI0) {
diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
index 9a43947..f3e5921 100644
--- a/hw/i386/q35-acpi-dsdt.dsl
+++ b/hw/i386/q35-acpi-dsdt.dsl
@@ -48,6 +48,14 @@ DefinitionBlock (
 /****************************************************************
  * PCI Bus definition
  ****************************************************************/
+#define BOARD_SPECIFIC_PCI_RESOURSES \
+     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
+         0x0000, \
+         0x0D00, \
+         0xFFFF, \
+         0x0000, \
+         0xF300, \
+         ,, , TypeStatic)
 
     Scope(\_SB) {
         Device(PCI0) {
commit 4782434f3cc016fbab16228e92e90265cf6db908
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Jan 9 17:36:34 2014 +0100

    pc: set PRST base in DSDT depending on chipset
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
index 995b415..1dfbb4f 100644
--- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl
+++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
@@ -52,7 +52,7 @@ Scope(\_SB) {
         Sleep(200)
     }
 
-    OperationRegion(PRST, SystemIO, 0xaf00, 32)
+    OperationRegion(PRST, SystemIO, CPU_STATUS_BASE, 32)
     Field(PRST, ByteAcc, NoLock, Preserve) {
         PRS, 256
     }
diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
index 6d76f30..3dc4789 100644
--- a/hw/i386/acpi-dsdt.dsl
+++ b/hw/i386/acpi-dsdt.dsl
@@ -290,6 +290,7 @@ DefinitionBlock (
         }
     }
 
+#define CPU_STATUS_BASE 0xaf00
 #include "acpi-dsdt-cpu-hotplug.dsl"
 
 
diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
index ee38fd6..9a43947 100644
--- a/hw/i386/q35-acpi-dsdt.dsl
+++ b/hw/i386/q35-acpi-dsdt.dsl
@@ -405,6 +405,7 @@ DefinitionBlock (
         define_gsi_link(GSIH, 0, 0x17)
     }
 
+#define CPU_STATUS_BASE 0x0CD8
 #include "acpi-dsdt-cpu-hotplug.dsl"
 
 
commit d6610bc2adc19a632cb14fc094378cbf5cd60868
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Jan 9 17:36:32 2014 +0100

    acpi: ich9: add CPU hotplug handling to Q35 machine
    
    .. use IO port 0cd8-0xcf7 range for CPU present bitmap
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/docs/specs/acpi_cpu_hotplug.txt b/docs/specs/acpi_cpu_hotplug.txt
index f6f5774..340b751 100644
--- a/docs/specs/acpi_cpu_hotplug.txt
+++ b/docs/specs/acpi_cpu_hotplug.txt
@@ -10,7 +10,9 @@ ACPI GPE block (IO ports 0xafe0-0xafe3, byte access):
 Generic ACPI GPE block. Bit 2 (GPE.2) used to notify CPU
 hot-add/remove event to ACPI BIOS, via SCI interrupt.
 
-CPU present bitmap (IO port 0xaf00-0xaf1f, 1-byte access):
+CPU present bitmap for:
+  ICH9-LPC (IO port 0x0cd8-0xcf7, 1-byte access)
+  PIIX-PM  (IO port 0xaf00-0xaf1f, 1-byte access)
 ---------------------------------------------------------------
 One bit per CPU. Bit position reflects corresponding CPU APIC ID.
 Read-only.
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 30f0df8..0afac42 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -185,6 +185,15 @@ static void pm_powerdown_req(Notifier *n, void *opaque)
     acpi_pm1_evt_power_down(&pm->acpi_regs);
 }
 
+static void ich9_cpu_added_req(Notifier *n, void *opaque)
+{
+    ICH9LPCPMRegs *pm = container_of(n, ICH9LPCPMRegs, cpu_added_notifier);
+
+    assert(pm != NULL);
+    AcpiCpuHotplug_add(&pm->acpi_regs.gpe, &pm->gpe_cpu, CPU(opaque));
+    acpi_update_sci(&pm->acpi_regs, pm->irq);
+}
+
 void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
                   qemu_irq sci_irq)
 {
@@ -210,6 +219,11 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
     qemu_register_reset(pm_reset, pm);
     pm->powerdown_notifier.notify = pm_powerdown_req;
     qemu_register_powerdown_notifier(&pm->powerdown_notifier);
+
+    AcpiCpuHotplug_init(pci_address_space_io(lpc_pci), OBJECT(lpc_pci),
+                        &pm->gpe_cpu, ICH9_CPU_HOTPLUG_IO_BASE);
+    pm->cpu_added_notifier.notify = ich9_cpu_added_req;
+    qemu_register_cpu_added_notifier(&pm->cpu_added_notifier);
 }
 
 static void ich9_pm_get_gpe0_blk(Object *obj, Visitor *v,
diff --git a/include/hw/acpi/cpu_hotplug_defs.h b/include/hw/acpi/cpu_hotplug_defs.h
index c6c4f78..47a35e3 100644
--- a/include/hw/acpi/cpu_hotplug_defs.h
+++ b/include/hw/acpi/cpu_hotplug_defs.h
@@ -18,5 +18,6 @@
  */
 #define ACPI_CPU_HOTPLUG_STATUS 4
 #define ACPI_GPE_PROC_LEN 32
+#define ICH9_CPU_HOTPLUG_IO_BASE 0x0CD8
 
 #endif
diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h
index 82fcf9f..104f419 100644
--- a/include/hw/acpi/ich9.h
+++ b/include/hw/acpi/ich9.h
@@ -22,6 +22,7 @@
 #define HW_ACPI_ICH9_H
 
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/cpu_hotplug.h"
 
 typedef struct ICH9LPCPMRegs {
     /*
@@ -42,6 +43,9 @@ typedef struct ICH9LPCPMRegs {
 
     uint32_t pm_io_base;
     Notifier powerdown_notifier;
+
+    AcpiCpuHotplug gpe_cpu;
+    Notifier cpu_added_notifier;
 } ICH9LPCPMRegs;
 
 void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
commit 81cea5e7f2aa61c6c5d33d28bceb81276603d3c9
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Jan 9 17:36:31 2014 +0100

    acpi: factor out common cpu hotplug code for PIIX4/Q35
    
    .. so it could be used for adding CPU hotplug to Q35 machine
    
    Add an additional header with that will be shared between
    C and ASL code: include/hw/acpi/cpu_hotplug_defs.h
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index 841eca2..397d32b 100644
--- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs
@@ -1 +1 @@
-common-obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o pcihp.o
+common-obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o pcihp.o cpu_hotplug.o
diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c
new file mode 100644
index 0000000..48928dc
--- /dev/null
+++ b/hw/acpi/cpu_hotplug.c
@@ -0,0 +1,64 @@
+/*
+ * QEMU ACPI hotplug utilities
+ *
+ * Copyright (C) 2013 Red Hat Inc
+ *
+ * Authors:
+ *   Igor Mammedov <imammedo at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "hw/hw.h"
+#include "hw/acpi/cpu_hotplug.h"
+
+static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
+{
+    AcpiCpuHotplug *cpus = opaque;
+    uint64_t val = cpus->sts[addr];
+
+    return val;
+}
+
+static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data,
+                             unsigned int size)
+{
+    /* TODO: implement VCPU removal on guest signal that CPU can be removed */
+}
+
+static const MemoryRegionOps AcpiCpuHotplug_ops = {
+    .read = cpu_status_read,
+    .write = cpu_status_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
+void AcpiCpuHotplug_add(ACPIGPE *gpe, AcpiCpuHotplug *g, CPUState *cpu)
+{
+    CPUClass *k = CPU_GET_CLASS(cpu);
+    int64_t cpu_id;
+
+    *gpe->sts = *gpe->sts | ACPI_CPU_HOTPLUG_STATUS;
+    cpu_id = k->get_arch_id(CPU(cpu));
+    g->sts[cpu_id / 8] |= (1 << (cpu_id % 8));
+}
+
+void AcpiCpuHotplug_init(MemoryRegion *parent, Object *owner,
+                         AcpiCpuHotplug *gpe_cpu, uint16_t base)
+{
+    CPUState *cpu;
+
+    CPU_FOREACH(cpu) {
+        CPUClass *cc = CPU_GET_CLASS(cpu);
+        int64_t id = cc->get_arch_id(cpu);
+
+        g_assert((id / 8) < ACPI_GPE_PROC_LEN);
+        gpe_cpu->sts[id / 8] |= (1 << (id % 8));
+    }
+    memory_region_init_io(&gpe_cpu->io, owner, &AcpiCpuHotplug_ops,
+                          gpe_cpu, "acpi-cpu-hotplug", ACPI_GPE_PROC_LEN);
+    memory_region_add_subregion(parent, base, &gpe_cpu->io);
+}
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 1aa35bc..12f8dde 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -31,6 +31,7 @@
 #include "exec/address-spaces.h"
 #include "hw/acpi/piix4.h"
 #include "hw/acpi/pcihp.h"
+#include "hw/acpi/cpu_hotplug.h"
 
 //#define DEBUG
 
@@ -51,20 +52,14 @@
 #define PCI_RMV_BASE 0xae0c
 
 #define PIIX4_PROC_BASE 0xaf00
-#define PIIX4_PROC_LEN 32
 
 #define PIIX4_PCI_HOTPLUG_STATUS 2
-#define PIIX4_CPU_HOTPLUG_STATUS 4
 
 struct pci_status {
     uint32_t up; /* deprecated, maintained for migration compatibility */
     uint32_t down;
 };
 
-typedef struct CPUStatus {
-    uint8_t sts[PIIX4_PROC_LEN];
-} CPUStatus;
-
 typedef struct PIIX4PMState {
     /*< private >*/
     PCIDevice parent_obj;
@@ -74,7 +69,6 @@ typedef struct PIIX4PMState {
     uint32_t io_base;
 
     MemoryRegion io_gpe;
-    MemoryRegion io_cpu;
     ACPIREGS ar;
 
     APMState apm;
@@ -102,7 +96,7 @@ typedef struct PIIX4PMState {
     uint8_t disable_s4;
     uint8_t s4_val;
 
-    CPUStatus gpe_cpu;
+    AcpiCpuHotplug gpe_cpu;
     Notifier cpu_added_notifier;
 } PIIX4PMState;
 
@@ -683,61 +677,13 @@ static const MemoryRegionOps piix4_pci_ops = {
     },
 };
 
-static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
-{
-    PIIX4PMState *s = opaque;
-    CPUStatus *cpus = &s->gpe_cpu;
-    uint64_t val = cpus->sts[addr];
-
-    return val;
-}
-
-static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data,
-                             unsigned int size)
-{
-    /* TODO: implement VCPU removal on guest signal that CPU can be removed */
-}
-
-static const MemoryRegionOps cpu_hotplug_ops = {
-    .read = cpu_status_read,
-    .write = cpu_status_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-    .valid = {
-        .min_access_size = 1,
-        .max_access_size = 1,
-    },
-};
-
-typedef enum {
-    PLUG,
-    UNPLUG,
-} HotplugEventType;
-
-static void piix4_cpu_hotplug_req(PIIX4PMState *s, CPUState *cpu,
-                                  HotplugEventType action)
-{
-    CPUStatus *g = &s->gpe_cpu;
-    ACPIGPE *gpe = &s->ar.gpe;
-    CPUClass *k = CPU_GET_CLASS(cpu);
-    int64_t cpu_id;
-
-    assert(s != NULL);
-
-    *gpe->sts = *gpe->sts | PIIX4_CPU_HOTPLUG_STATUS;
-    cpu_id = k->get_arch_id(CPU(cpu));
-    if (action == PLUG) {
-        g->sts[cpu_id / 8] |= (1 << (cpu_id % 8));
-    } else {
-        g->sts[cpu_id / 8] &= ~(1 << (cpu_id % 8));
-    }
-    acpi_update_sci(&s->ar, s->irq);
-}
-
 static void piix4_cpu_added_req(Notifier *n, void *opaque)
 {
     PIIX4PMState *s = container_of(n, PIIX4PMState, cpu_added_notifier);
 
-    piix4_cpu_hotplug_req(s, CPU(opaque), PLUG);
+    assert(s != NULL);
+    AcpiCpuHotplug_add(&s->ar.gpe, &s->gpe_cpu, CPU(opaque));
+    acpi_update_sci(&s->ar, s->irq);
 }
 
 static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
@@ -746,8 +692,6 @@ static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
 static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
                                            PCIBus *bus, PIIX4PMState *s)
 {
-    CPUState *cpu;
-
     memory_region_init_io(&s->io_gpe, OBJECT(s), &piix4_gpe_ops, s,
                           "acpi-gpe0", GPE_LEN);
     memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe);
@@ -762,16 +706,7 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
         pci_bus_hotplug(bus, piix4_device_hotplug, DEVICE(s));
     }
 
-    CPU_FOREACH(cpu) {
-        CPUClass *cc = CPU_GET_CLASS(cpu);
-        int64_t id = cc->get_arch_id(cpu);
-
-        g_assert((id / 8) < PIIX4_PROC_LEN);
-        s->gpe_cpu.sts[id / 8] |= (1 << (id % 8));
-    }
-    memory_region_init_io(&s->io_cpu, OBJECT(s), &cpu_hotplug_ops, s,
-                          "acpi-cpu-hotplug", PIIX4_PROC_LEN);
-    memory_region_add_subregion(parent, PIIX4_PROC_BASE, &s->io_cpu);
+    AcpiCpuHotplug_init(parent, OBJECT(s), &s->gpe_cpu, PIIX4_PROC_BASE);
     s->cpu_added_notifier.notify = piix4_cpu_added_req;
     qemu_register_cpu_added_notifier(&s->cpu_added_notifier);
 }
diff --git a/include/hw/acpi/cpu_hotplug.h b/include/hw/acpi/cpu_hotplug.h
new file mode 100644
index 0000000..4576400
--- /dev/null
+++ b/include/hw/acpi/cpu_hotplug.h
@@ -0,0 +1,27 @@
+/*
+ * QEMU ACPI hotplug utilities
+ *
+ * Copyright (C) 2013 Red Hat Inc
+ *
+ * Authors:
+ *   Igor Mammedov <imammedo at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#ifndef ACPI_HOTPLUG_H
+#define ACPI_HOTPLUG_H
+
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/cpu_hotplug_defs.h"
+
+typedef struct AcpiCpuHotplug {
+    MemoryRegion io;
+    uint8_t sts[ACPI_GPE_PROC_LEN];
+} AcpiCpuHotplug;
+
+void AcpiCpuHotplug_add(ACPIGPE *gpe, AcpiCpuHotplug *g, CPUState *cpu);
+
+void AcpiCpuHotplug_init(MemoryRegion *parent, Object *owner,
+                         AcpiCpuHotplug *gpe_cpu, uint16_t base);
+#endif
diff --git a/include/hw/acpi/cpu_hotplug_defs.h b/include/hw/acpi/cpu_hotplug_defs.h
new file mode 100644
index 0000000..c6c4f78
--- /dev/null
+++ b/include/hw/acpi/cpu_hotplug_defs.h
@@ -0,0 +1,22 @@
+/*
+ * QEMU ACPI hotplug utilities shared defines
+ *
+ * Copyright (C) 2013 Red Hat Inc
+ *
+ * Authors:
+ *   Igor Mammedov <imammedo at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#ifndef ACPI_HOTPLUG_DEFS_H
+#define ACPI_HOTPLUG_DEFS_H
+
+/*
+ * ONLY DEFINEs are permited in this file since it's shared
+ * between C and ASL code.
+ */
+#define ACPI_CPU_HOTPLUG_STATUS 4
+#define ACPI_GPE_PROC_LEN 32
+
+#endif
commit 99fd437dee468609de8218f0eb3b16621fb6a9c9
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Oct 14 18:01:29 2013 +0300

    acpi-build: enable hotplug for PCI bridges
    
    This enables support for device hotplug behind
    pci bridges. Bridge devices themselves need
    to be pre-configured on qemu command line.
    
    Design:
        - at machine init time, assign "bsel" property to bridges with
          hotplug support
        - dynamically (At ACPI table read) generate ACPI code to handle
          hotplug events for each bridge with "bsel" property
    
    Note: ACPI doesn't support adding or removing bridges by hotplug.
    We detect and prevent removal of bridges by hotplug,
    unless they were added by hotplug previously
    (and so, are not described by ACPI).
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 1d62866..9cd3d0e 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -40,6 +40,7 @@
 
 /* Supported chipsets: */
 #include "hw/acpi/piix4.h"
+#include "hw/acpi/pcihp.h"
 #include "hw/i386/ich9.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/pci-host/q35.h"
@@ -79,6 +80,12 @@ typedef struct AcpiMiscInfo {
     uint16_t pvpanic_port;
 } AcpiMiscInfo;
 
+typedef struct AcpiBuildPciBusHotplugState {
+    GArray *device_table;
+    GArray *notify_table;
+    struct AcpiBuildPciBusHotplugState *parent;
+} AcpiBuildPciBusHotplugState;
+
 static void acpi_get_dsdt(AcpiMiscInfo *info)
 {
     uint16_t *applesmc_sta;
@@ -179,38 +186,6 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
                                                NULL);
 }
 
-static void acpi_get_hotplug_info(AcpiMiscInfo *misc)
-{
-    int i;
-    PCIBus *bus = find_i440fx();
-
-    if (!bus) {
-        /* Only PIIX supports ACPI hotplug */
-        memset(misc->slot_hotplug_enable, 0, sizeof misc->slot_hotplug_enable);
-        return;
-    }
-
-    memset(misc->slot_hotplug_enable, 0xff,
-           DIV_ROUND_UP(PCI_SLOT_MAX, BITS_PER_BYTE));
-
-    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
-        PCIDeviceClass *pc;
-        PCIDevice *pdev = bus->devices[i];
-
-        if (!pdev) {
-            continue;
-        }
-
-        pc = PCI_DEVICE_GET_CLASS(pdev);
-
-        if (pc->no_hotplug) {
-            int slot = PCI_SLOT(i);
-
-            clear_bit(slot, misc->slot_hotplug_enable);
-        }
-    }
-}
-
 static void acpi_get_misc_info(AcpiMiscInfo *info)
 {
     info->has_hpet = hpet_find();
@@ -376,6 +351,12 @@ static void build_package(GArray *package, uint8_t op, unsigned min_bytes)
     build_prepend_byte(package, op);
 }
 
+static void build_extop_package(GArray *package, uint8_t op)
+{
+    build_package(package, op, 1);
+    build_prepend_byte(package, 0x5B); /* ExtOpPrefix */
+}
+
 static void build_append_value(GArray *table, uint32_t value, int size)
 {
     uint8_t prefix;
@@ -402,8 +383,44 @@ static void build_append_value(GArray *table, uint32_t value, int size)
     }
 }
 
-static void build_append_notify_target(GArray *method, GArray *target_name,
-                                       uint32_t value, int size)
+static void build_append_int(GArray *table, uint32_t value)
+{
+    if (value == 0x00) {
+        build_append_byte(table, 0x00); /* ZeroOp */
+    } else if (value == 0x01) {
+        build_append_byte(table, 0x01); /* OneOp */
+    } else if (value <= 0xFF) {
+        build_append_value(table, value, 1);
+    } else if (value <= 0xFFFFF) {
+        build_append_value(table, value, 2);
+    } else {
+        build_append_value(table, value, 4);
+    }
+}
+
+static GArray *build_alloc_method(const char *name, uint8_t arg_count)
+{
+    GArray *method = build_alloc_array();
+
+    build_append_nameseg(method, "%s", name);
+    build_append_byte(method, arg_count); /* MethodFlags: ArgCount */
+
+    return method;
+}
+
+static void build_append_and_cleanup_method(GArray *device, GArray *method)
+{
+    uint8_t op = 0x14; /* MethodOp */
+
+    build_package(method, op, 0);
+
+    build_append_array(device, method);
+    build_free_array(method);
+}
+
+static void build_append_notify_target_ifequal(GArray *method,
+                                               GArray *target_name,
+                                               uint32_t value, int size)
 {
     GArray *notify = build_alloc_array();
     uint8_t op = 0xA0; /* IfOp */
@@ -423,6 +440,7 @@ static void build_append_notify_target(GArray *method, GArray *target_name,
     build_free_array(notify);
 }
 
+/* End here */
 #define ACPI_PORT_SMI_CMD           0x00b2 /* TODO: this is APM_CNT_IOPORT */
 
 static inline void *acpi_data_push(GArray *table_data, unsigned size)
@@ -632,44 +650,236 @@ static inline char acpi_get_hex(uint32_t val)
 #include "hw/i386/ssdt-pcihp.hex"
 
 static void
-build_append_notify(GArray *device, const char *name,
-                    const char *format, int skip, int count)
+build_append_notify_method(GArray *device, const char *name,
+                           const char *format, int count)
 {
     int i;
-    GArray *method = build_alloc_array();
-    uint8_t op = 0x14; /* MethodOp */
+    GArray *method = build_alloc_method(name, 2);
 
-    build_append_nameseg(method, "%s", name);
-    build_append_byte(method, 0x02); /* MethodFlags: ArgCount */
-    for (i = skip; i < count; i++) {
+    for (i = 0; i < count; i++) {
         GArray *target = build_alloc_array();
         build_append_nameseg(target, format, i);
         assert(i < 256); /* Fits in 1 byte */
-        build_append_notify_target(method, target, i, 1);
+        build_append_notify_target_ifequal(method, target, i, 1);
         build_free_array(target);
     }
-    build_package(method, op, 2);
 
-    build_append_array(device, method);
-    build_free_array(method);
+    build_append_and_cleanup_method(device, method);
 }
 
-static void patch_pcihp(int slot, uint8_t *ssdt_ptr, uint32_t eject)
+static void patch_pcihp(int slot, uint8_t *ssdt_ptr)
 {
-    ssdt_ptr[ACPI_PCIHP_OFFSET_HEX] = acpi_get_hex(slot >> 4);
-    ssdt_ptr[ACPI_PCIHP_OFFSET_HEX + 1] = acpi_get_hex(slot);
+    unsigned devfn = PCI_DEVFN(slot, 0);
+
+    ssdt_ptr[ACPI_PCIHP_OFFSET_HEX] = acpi_get_hex(devfn >> 4);
+    ssdt_ptr[ACPI_PCIHP_OFFSET_HEX + 1] = acpi_get_hex(devfn);
     ssdt_ptr[ACPI_PCIHP_OFFSET_ID] = slot;
     ssdt_ptr[ACPI_PCIHP_OFFSET_ADR + 2] = slot;
+}
+
+/* Assign BSEL property to all buses.  In the future, this can be changed
+ * to only assign to buses that support hotplug.
+ */
+static void *acpi_set_bsel(PCIBus *bus, void *opaque)
+{
+    unsigned *bsel_alloc = opaque;
+    unsigned *bus_bsel;
+
+    if (bus->qbus.allow_hotplug) {
+        bus_bsel = g_malloc(sizeof *bus_bsel);
+
+        *bus_bsel = (*bsel_alloc)++;
+        object_property_add_uint32_ptr(OBJECT(bus), ACPI_PCIHP_PROP_BSEL,
+                                       bus_bsel, NULL);
+    }
+
+    return bsel_alloc;
+}
+
+static void acpi_set_pci_info(void)
+{
+    PCIBus *bus = find_i440fx(); /* TODO: Q35 support */
+    unsigned bsel_alloc = 0;
+
+    if (bus) {
+        /* Scan all PCI buses. Set property to enable acpi based hotplug. */
+        pci_for_each_bus_depth_first(bus, acpi_set_bsel, NULL, &bsel_alloc);
+    }
+}
+
+static void build_pci_bus_state_init(AcpiBuildPciBusHotplugState *state,
+                                     AcpiBuildPciBusHotplugState *parent)
+{
+    state->parent = parent;
+    state->device_table = build_alloc_array();
+    state->notify_table = build_alloc_array();
+}
+
+static void build_pci_bus_state_cleanup(AcpiBuildPciBusHotplugState *state)
+{
+    build_free_array(state->device_table);
+    build_free_array(state->notify_table);
+}
+
+static void *build_pci_bus_begin(PCIBus *bus, void *parent_state)
+{
+    AcpiBuildPciBusHotplugState *parent = parent_state;
+    AcpiBuildPciBusHotplugState *child = g_malloc(sizeof *child);
+
+    build_pci_bus_state_init(child, parent);
+
+    return child;
+}
+
+static void build_pci_bus_end(PCIBus *bus, void *bus_state)
+{
+    AcpiBuildPciBusHotplugState *child = bus_state;
+    AcpiBuildPciBusHotplugState *parent = child->parent;
+    GArray *bus_table = build_alloc_array();
+    DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX);
+    uint8_t op;
+    int i;
+    QObject *bsel;
+    GArray *method;
+    bool bus_hotplug_support = false;
+
+    if (bus->parent_dev) {
+        op = 0x82; /* DeviceOp */
+        build_append_nameseg(bus_table, "S%.02X_",
+                             bus->parent_dev->devfn);
+        build_append_byte(bus_table, 0x08); /* NameOp */
+        build_append_nameseg(bus_table, "_SUN");
+        build_append_value(bus_table, PCI_SLOT(bus->parent_dev->devfn), 1);
+        build_append_byte(bus_table, 0x08); /* NameOp */
+        build_append_nameseg(bus_table, "_ADR");
+        build_append_value(bus_table, (PCI_SLOT(bus->parent_dev->devfn) << 16) |
+                           PCI_FUNC(bus->parent_dev->devfn), 4);
+    } else {
+        op = 0x10; /* ScopeOp */;
+        build_append_nameseg(bus_table, "PCI0");
+    }
 
-    /* Runtime patching of ACPI_EJ0: to disable hotplug for a slot,
-     * replace the method name: _EJ0 by ACPI_EJ0_.
+    bsel = object_property_get_qobject(OBJECT(bus), ACPI_PCIHP_PROP_BSEL, NULL);
+    if (bsel) {
+        build_append_byte(bus_table, 0x08); /* NameOp */
+        build_append_nameseg(bus_table, "BSEL");
+        build_append_int(bus_table, qint_get_int(qobject_to_qint(bsel)));
+
+        memset(slot_hotplug_enable, 0xff, sizeof slot_hotplug_enable);
+
+        for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+            PCIDeviceClass *pc;
+            PCIDevice *pdev = bus->devices[i];
+
+            if (!pdev) {
+                continue;
+            }
+
+            pc = PCI_DEVICE_GET_CLASS(pdev);
+
+            if (pc->no_hotplug || pc->is_bridge) {
+                int slot = PCI_SLOT(i);
+
+                clear_bit(slot, slot_hotplug_enable);
+            }
+        }
+
+        /* Append Device object for each slot which supports eject */
+        for (i = 0; i < PCI_SLOT_MAX; i++) {
+            bool can_eject = test_bit(i, slot_hotplug_enable);
+            if (can_eject) {
+                void *pcihp = acpi_data_push(bus_table,
+                                             ACPI_PCIHP_SIZEOF);
+                memcpy(pcihp, ACPI_PCIHP_AML, ACPI_PCIHP_SIZEOF);
+                patch_pcihp(i, pcihp);
+                bus_hotplug_support = true;
+            }
+        }
+
+        method = build_alloc_method("DVNT", 2);
+
+        for (i = 0; i < PCI_SLOT_MAX; i++) {
+            GArray *notify;
+            uint8_t op;
+
+            if (!test_bit(i, slot_hotplug_enable)) {
+                continue;
+            }
+
+            notify = build_alloc_array();
+            op = 0xA0; /* IfOp */
+
+            build_append_byte(notify, 0x7B); /* AndOp */
+            build_append_byte(notify, 0x68); /* Arg0Op */
+            build_append_int(notify, 0x1 << i);
+            build_append_byte(notify, 0x00); /* NullName */
+            build_append_byte(notify, 0x86); /* NotifyOp */
+            build_append_nameseg(notify, "S%.02X_", PCI_DEVFN(i, 0));
+            build_append_byte(notify, 0x69); /* Arg1Op */
+
+            /* Pack it up */
+            build_package(notify, op, 0);
+
+            build_append_array(method, notify);
+
+            build_free_array(notify);
+        }
+
+        build_append_and_cleanup_method(bus_table, method);
+    }
+
+    /* Append PCNT method to notify about events on local and child buses.
+     * Add unconditionally for root since DSDT expects it.
      */
-    /* Sanity check */
-    assert(!memcmp(ssdt_ptr + ACPI_PCIHP_OFFSET_EJ0, "_EJ0", 4));
+    if (bus_hotplug_support || child->notify_table->len || !bus->parent_dev) {
+        method = build_alloc_method("PCNT", 0);
+
+        /* If bus supports hotplug select it and notify about local events */
+        if (bsel) {
+            build_append_byte(method, 0x70); /* StoreOp */
+            build_append_int(method, qint_get_int(qobject_to_qint(bsel)));
+            build_append_nameseg(method, "BNUM");
+            build_append_nameseg(method, "DVNT");
+            build_append_nameseg(method, "PCIU");
+            build_append_int(method, 1); /* Device Check */
+            build_append_nameseg(method, "DVNT");
+            build_append_nameseg(method, "PCID");
+            build_append_int(method, 3); /* Eject Request */
+        }
+
+        /* Notify about child bus events in any case */
+        build_append_array(method, child->notify_table);
+
+        build_append_and_cleanup_method(bus_table, method);
+
+        /* Append description of child buses */
+        build_append_array(bus_table, child->device_table);
+
+        /* Pack it up */
+        if (bus->parent_dev) {
+            build_extop_package(bus_table, op);
+        } else {
+            build_package(bus_table, op, 0);
+        }
 
-    if (!eject) {
-        memcpy(ssdt_ptr + ACPI_PCIHP_OFFSET_EJ0, "EJ0_", 4);
+        /* Append our bus description to parent table */
+        build_append_array(parent->device_table, bus_table);
+
+        /* Also tell parent how to notify us, invoking PCNT method.
+         * At the moment this is not needed for root as we have a single root.
+         */
+        if (bus->parent_dev) {
+            build_append_byte(parent->notify_table, '^'); /* ParentPrefixChar */
+            build_append_byte(parent->notify_table, 0x2E); /* DualNamePrefix */
+            build_append_nameseg(parent->notify_table, "S%.02X_",
+                                 bus->parent_dev->devfn);
+            build_append_nameseg(parent->notify_table, "PCNT");
+        }
     }
+
+    build_free_array(bus_table);
+    build_pci_bus_state_cleanup(child);
+    g_free(child);
 }
 
 static void patch_pci_windows(PcPciInfo *pci, uint8_t *start, unsigned size)
@@ -741,7 +951,7 @@ build_ssdt(GArray *table_data, GArray *linker,
          *   Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}
          */
         /* Arg0 = Processor ID = APIC ID */
-        build_append_notify(sb_scope, "NTFY", "CP%0.02X", 0, acpi_cpus);
+        build_append_notify_method(sb_scope, "NTFY", "CP%0.02X", acpi_cpus);
 
         /* build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })" */
         build_append_byte(sb_scope, 0x08); /* NameOp */
@@ -763,24 +973,19 @@ build_ssdt(GArray *table_data, GArray *linker,
         }
 
         {
-            GArray *pci0 = build_alloc_array();
-            uint8_t op = 0x10; /* ScopeOp */;
+            AcpiBuildPciBusHotplugState hotplug_state;
+            PCIBus *bus = find_i440fx(); /* TODO: Q35 support */
 
-            build_append_nameseg(pci0, "PCI0");
+            build_pci_bus_state_init(&hotplug_state, NULL);
 
-            /* build Device object for each slot */
-            for (i = 1; i < PCI_SLOT_MAX; i++) {
-                bool eject = test_bit(i, misc->slot_hotplug_enable);
-                void *pcihp = acpi_data_push(pci0, ACPI_PCIHP_SIZEOF);
-
-                memcpy(pcihp, ACPI_PCIHP_AML, ACPI_PCIHP_SIZEOF);
-                patch_pcihp(i, pcihp, eject);
+            if (bus) {
+                /* Scan all PCI buses. Generate tables to support hotplug. */
+                pci_for_each_bus_depth_first(bus, build_pci_bus_begin,
+                                             build_pci_bus_end, &hotplug_state);
             }
 
-            build_append_notify(pci0, "PCNT", "S%0.02X_", 1, PCI_SLOT_MAX);
-            build_package(pci0, op, 3);
-            build_append_array(sb_scope, pci0);
-            build_free_array(pci0);
+            build_append_array(sb_scope, hotplug_state.device_table);
+            build_pci_bus_state_cleanup(&hotplug_state);
         }
 
         build_package(sb_scope, op, 3);
@@ -1063,7 +1268,6 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
     acpi_get_cpu_info(&cpu);
     acpi_get_pm_info(&pm);
     acpi_get_dsdt(&misc);
-    acpi_get_hotplug_info(&misc);
     acpi_get_misc_info(&misc);
     acpi_get_pci_info(&pci);
 
@@ -1208,6 +1412,8 @@ void acpi_setup(PcGuestInfo *guest_info)
 
     build_state->guest_info = guest_info;
 
+    acpi_set_pci_info();
+
     acpi_build_tables_init(&tables);
     acpi_build(build_state->guest_info, &tables);
 
diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
index b87c6e0..6d76f30 100644
--- a/hw/i386/acpi-dsdt.dsl
+++ b/hw/i386/acpi-dsdt.dsl
@@ -134,32 +134,28 @@ DefinitionBlock (
             B0EJ, 32,
         }
 
+        OperationRegion(BNMR, SystemIO, 0xae10, 0x04)
+        Field(BNMR, DWordAcc, NoLock, WriteAsZeros) {
+            BNUM, 32,
+        }
+
+        /* Lock to protect access to fields above. */
+        Mutex(BLCK, 0)
+
         /* Methods called by bulk generated PCI devices below */
 
         /* Methods called by hotplug devices */
-        Method(PCEJ, 1, NotSerialized) {
+        Method(PCEJ, 2, NotSerialized) {
             // _EJ0 method - eject callback
-            Store(ShiftLeft(1, Arg0), B0EJ)
+            Acquire(BLCK, 0xFFFF)
+            Store(Arg0, BNUM)
+            Store(ShiftLeft(1, Arg1), B0EJ)
+            Release(BLCK)
             Return (0x0)
         }
 
         /* Hotplug notification method supplied by SSDT */
         External(\_SB.PCI0.PCNT, MethodObj)
-
-        /* PCI hotplug notify method */
-        Method(PCNF, 0) {
-            // Local0 = iterator
-            Store(Zero, Local0)
-            While (LLess(Local0, 31)) {
-                Increment(Local0)
-                If (And(PCIU, ShiftLeft(1, Local0))) {
-                    PCNT(Local0, 1)
-                }
-                If (And(PCID, ShiftLeft(1, Local0))) {
-                    PCNT(Local0, 3)
-                }
-            }
-        }
     }
 
 
@@ -308,7 +304,9 @@ DefinitionBlock (
         }
         Method(_E01) {
             // PCI hotplug event
-            \_SB.PCI0.PCNF()
+            Acquire(\_SB.PCI0.BLCK, 0xFFFF)
+            \_SB.PCI0.PCNT()
+            Release(\_SB.PCI0.BLCK)
         }
         Method(_E02) {
             // CPU hotplug event
diff --git a/hw/i386/ssdt-pcihp.dsl b/hw/i386/ssdt-pcihp.dsl
index d29a5b9..cc245c3 100644
--- a/hw/i386/ssdt-pcihp.dsl
+++ b/hw/i386/ssdt-pcihp.dsl
@@ -25,6 +25,7 @@ DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1)
     /* Objects supplied by DSDT */
     External(\_SB.PCI0, DeviceObj)
     External(\_SB.PCI0.PCEJ, MethodObj)
+    External(BSEL, IntObj)
 
     Scope(\_SB.PCI0) {
 
@@ -33,19 +34,17 @@ DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1)
         ACPI_EXTRACT_DEVICE_END ssdt_pcihp_end
         ACPI_EXTRACT_DEVICE_STRING ssdt_pcihp_name
 
-        // Method _EJ0 can be patched by BIOS to EJ0_
-        // at runtime, if the slot is detected to not support hotplug.
-        // Extract the offset of the address dword and the
-        // _EJ0 name to allow this patching.
+        // Extract the offsets of the device name, address dword and the slot
+        // name byte - we fill them in for each device.
         Device(SAA) {
             ACPI_EXTRACT_NAME_BYTE_CONST ssdt_pcihp_id
             Name(_SUN, 0xAA)
             ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcihp_adr
             Name(_ADR, 0xAA0000)
-            ACPI_EXTRACT_METHOD_STRING ssdt_pcihp_ej0
             Method(_EJ0, 1) {
-                Return (PCEJ(_SUN))
+                PCEJ(BSEL, _SUN)
             }
         }
+
     }
 }
commit 9e047b982452c633882b486682966c1d97097015
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Oct 14 18:01:20 2013 +0300

    piix4: add acpi pci hotplug support
    
    Add support for acpi pci hotplug using the
    new infrastructure.
    PIIX4 legacy interface is maintained as is for
    machine types 1.7 and older.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 20353b9..1aa35bc 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -30,6 +30,7 @@
 #include "hw/nvram/fw_cfg.h"
 #include "exec/address-spaces.h"
 #include "hw/acpi/piix4.h"
+#include "hw/acpi/pcihp.h"
 
 //#define DEBUG
 
@@ -73,7 +74,6 @@ typedef struct PIIX4PMState {
     uint32_t io_base;
 
     MemoryRegion io_gpe;
-    MemoryRegion io_pci;
     MemoryRegion io_cpu;
     ACPIREGS ar;
 
@@ -88,11 +88,16 @@ typedef struct PIIX4PMState {
     Notifier machine_ready;
     Notifier powerdown_notifier;
 
-    /* for pci hotplug */
+    /* for legacy pci hotplug (compatible with qemu 1.6 and older) */
+    MemoryRegion io_pci;
     struct pci_status pci0_status;
     uint32_t pci0_hotplug_enable;
     uint32_t pci0_slot_device_present;
 
+    /* for new pci hotplug (with PCI2PCI bridge support) */
+    AcpiPciHpState acpi_pci_hotplug;
+    bool use_acpi_pci_hotplug;
+
     uint8_t disable_s3;
     uint8_t disable_s4;
     uint8_t s4_val;
@@ -263,6 +268,18 @@ static int acpi_load_old(QEMUFile *f, void *opaque, int version_id)
     return ret;
 }
 
+static bool vmstate_test_use_acpi_pci_hotplug(void *opaque, int version_id)
+{
+    PIIX4PMState *s = opaque;
+    return s->use_acpi_pci_hotplug;
+}
+
+static bool vmstate_test_no_use_acpi_pci_hotplug(void *opaque, int version_id)
+{
+    PIIX4PMState *s = opaque;
+    return !s->use_acpi_pci_hotplug;
+}
+
 /* qemu-kvm 1.2 uses version 3 but advertised as 2
  * To support incoming qemu-kvm 1.2 migration, change version_id
  * and minimum_version_id to 2 below (which breaks migration from
@@ -285,8 +302,12 @@ static const VMStateDescription vmstate_acpi = {
         VMSTATE_TIMER(ar.tmr.timer, PIIX4PMState),
         VMSTATE_INT64(ar.tmr.overflow_time, PIIX4PMState),
         VMSTATE_STRUCT(ar.gpe, PIIX4PMState, 2, vmstate_gpe, ACPIGPE),
-        VMSTATE_STRUCT(pci0_status, PIIX4PMState, 2, vmstate_pci_status,
-                       struct pci_status),
+        VMSTATE_STRUCT_TEST(pci0_status, PIIX4PMState,
+                            vmstate_test_no_use_acpi_pci_hotplug,
+                            2, vmstate_pci_status,
+                            struct pci_status),
+        VMSTATE_PCI_HOTPLUG(acpi_pci_hotplug, PIIX4PMState,
+                            vmstate_test_use_acpi_pci_hotplug),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -364,7 +385,11 @@ static void piix4_reset(void *opaque)
         pci_conf[0x5B] = 0x02;
     }
     pm_io_space_update(s);
-    piix4_update_hotplug(s);
+    if (s->use_acpi_pci_hotplug) {
+        acpi_pcihp_reset(&s->acpi_pci_hotplug);
+    } else {
+        piix4_update_hotplug(s);
+    }
 }
 
 static void piix4_pm_powerdown_req(Notifier *n, void *opaque)
@@ -375,6 +400,26 @@ static void piix4_pm_powerdown_req(Notifier *n, void *opaque)
     acpi_pm1_evt_power_down(&s->ar);
 }
 
+static int piix4_acpi_pci_hotplug(DeviceState *qdev, PCIDevice *dev,
+                                  PCIHotplugState state)
+{
+    PIIX4PMState *s = PIIX4_PM(qdev);
+    int ret = acpi_pcihp_device_hotplug(&s->acpi_pci_hotplug, dev, state);
+    if (ret < 0) {
+        return ret;
+    }
+    s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
+
+    acpi_update_sci(&s->ar, s->irq);
+    return 0;
+}
+
+static void piix4_update_bus_hotplug(PCIBus *bus, void *opaque)
+{
+    PIIX4PMState *s = opaque;
+    pci_bus_hotplug(bus, piix4_acpi_pci_hotplug, DEVICE(s));
+}
+
 static void piix4_pm_machine_ready(Notifier *n, void *opaque)
 {
     PIIX4PMState *s = container_of(n, PIIX4PMState, machine_ready);
@@ -388,6 +433,10 @@ static void piix4_pm_machine_ready(Notifier *n, void *opaque)
     pci_conf[0x63] = 0x60;
     pci_conf[0x67] = (memory_region_present(io_as, 0x3f8) ? 0x08 : 0) |
         (memory_region_present(io_as, 0x2f8) ? 0x90 : 0);
+
+    if (s->use_acpi_pci_hotplug) {
+        pci_for_each_bus(d->bus, piix4_update_bus_hotplug, s);
+    }
 }
 
 static void piix4_pm_add_propeties(PIIX4PMState *s)
@@ -509,6 +558,8 @@ static Property piix4_pm_properties[] = {
     DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0),
     DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, 0),
     DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2),
+    DEFINE_PROP_BOOL("acpi-pci-hotplug-with-bridge-support", PIIX4PMState,
+                     use_acpi_pci_hotplug, true),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -701,11 +752,15 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
                           "acpi-gpe0", GPE_LEN);
     memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe);
 
-    memory_region_init_io(&s->io_pci, OBJECT(s), &piix4_pci_ops, s,
-                          "acpi-pci-hotplug", PCI_HOTPLUG_SIZE);
-    memory_region_add_subregion(parent, PCI_HOTPLUG_ADDR,
-                                &s->io_pci);
-    pci_bus_hotplug(bus, piix4_device_hotplug, DEVICE(s));
+    if (s->use_acpi_pci_hotplug) {
+        acpi_pcihp_init(&s->acpi_pci_hotplug, bus, parent);
+    } else {
+        memory_region_init_io(&s->io_pci, OBJECT(s), &piix4_pci_ops, s,
+                              "acpi-pci-hotplug", PCI_HOTPLUG_SIZE);
+        memory_region_add_subregion(parent, PCI_HOTPLUG_ADDR,
+                                    &s->io_pci);
+        pci_bus_hotplug(bus, piix4_device_hotplug, DEVICE(s));
+    }
 
     CPU_FOREACH(cpu) {
         CPUClass *cc = CPU_GET_CLASS(cpu);
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 7fe2bd1..92eabeb 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -265,6 +265,11 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
             .driver   = TYPE_USB_DEVICE,\
             .property = "msos-desc",\
             .value    = "no",\
+        },\
+        {\
+            .driver   = "PIIX4_PM",\
+            .property = "acpi-pci-hotplug-with-bridge-support",\
+            .value    = "off",\
         }
 
 #define PC_COMPAT_1_6 \
commit db4728e6fec0364b866d3106125974eedc00e091
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Oct 14 18:01:11 2013 +0300

    pcihp: generalization of piix4 acpi
    
    Add ACPI based PCI hotplug library with bridge hotplug
    support.
    Design
       - each bus gets assigned "bsel" property.
       - ACPI code writes this number
         to a new BNUM register, then uses existing
         UP/DOWN registers to probe slot status;
         to eject, write number to BNUM register,
         then slot into existing EJ.
    
    The interface is actually backwards-compatible with
    existing PIIX4 ACPI (though not migration compatible).
    
    This is split out from PIIX4 codebase so we can
    reuse it for Q35 as well.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index a0b63b5..841eca2 100644
--- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs
@@ -1,2 +1 @@
-common-obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o
-
+common-obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o pcihp.o
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
new file mode 100644
index 0000000..3fa3d7c
--- /dev/null
+++ b/hw/acpi/pcihp.c
@@ -0,0 +1,316 @@
+/*
+ * QEMU<->ACPI BIOS PCI hotplug interface
+ *
+ * QEMU supports PCI hotplug via ACPI. This module
+ * implements the interface between QEMU and the ACPI BIOS.
+ * Interface specification - see docs/specs/acpi_pci_hotplug.txt
+ *
+ * Copyright (c) 2013, Red Hat Inc, Michael S. Tsirkin (mst at redhat.com)
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "hw/acpi/pcihp.h"
+
+#include "hw/hw.h"
+#include "hw/i386/pc.h"
+#include "hw/pci/pci.h"
+#include "hw/acpi/acpi.h"
+#include "sysemu/sysemu.h"
+#include "qemu/range.h"
+#include "exec/ioport.h"
+#include "exec/address-spaces.h"
+#include "hw/pci/pci_bus.h"
+#include "qom/qom-qobject.h"
+#include "qapi/qmp/qint.h"
+
+//#define DEBUG
+
+#ifdef DEBUG
+# define ACPI_PCIHP_DPRINTF(format, ...)     printf(format, ## __VA_ARGS__)
+#else
+# define ACPI_PCIHP_DPRINTF(format, ...)     do { } while (0)
+#endif
+
+#define PCI_HOTPLUG_ADDR 0xae00
+#define PCI_HOTPLUG_SIZE 0x0014
+#define PCI_UP_BASE 0xae00
+#define PCI_DOWN_BASE 0xae04
+#define PCI_EJ_BASE 0xae08
+#define PCI_RMV_BASE 0xae0c
+#define PCI_SEL_BASE 0xae10
+
+typedef struct AcpiPciHpFind {
+    int bsel;
+    PCIBus *bus;
+} AcpiPciHpFind;
+
+static int acpi_pcihp_get_bsel(PCIBus *bus)
+{
+    QObject *o = object_property_get_qobject(OBJECT(bus),
+                                             ACPI_PCIHP_PROP_BSEL, NULL);
+    int64_t bsel = -1;
+    if (o) {
+        bsel = qint_get_int(qobject_to_qint(o));
+    }
+    if (bsel < 0) {
+        return -1;
+    }
+    return bsel;
+}
+
+static void acpi_pcihp_test_hotplug_bus(PCIBus *bus, void *opaque)
+{
+    AcpiPciHpFind *find = opaque;
+    if (find->bsel == acpi_pcihp_get_bsel(bus)) {
+        find->bus = bus;
+    }
+}
+
+static PCIBus *acpi_pcihp_find_hotplug_bus(AcpiPciHpState *s, int bsel)
+{
+    AcpiPciHpFind find = { .bsel = bsel, .bus = NULL };
+
+    if (bsel < 0) {
+        return NULL;
+    }
+
+    pci_for_each_bus(s->root, acpi_pcihp_test_hotplug_bus, &find);
+
+    /* Make bsel 0 eject root bus if bsel property is not set,
+     * for compatibility with non acpi setups.
+     * TODO: really needed?
+     */
+    if (!bsel && !find.bus) {
+        find.bus = s->root;
+    }
+    return find.bus;
+}
+
+static bool acpi_pcihp_pc_no_hotplug(AcpiPciHpState *s, PCIDevice *dev)
+{
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
+    /*
+     * ACPI doesn't allow hotplug of bridge devices.  Don't allow
+     * hot-unplug of bridge devices unless they were added by hotplug
+     * (and so, not described by acpi).
+     */
+    return (pc->is_bridge && !dev->qdev.hotplugged) || pc->no_hotplug;
+}
+
+static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slots)
+{
+    BusChild *kid, *next;
+    int slot = ffs(slots) - 1;
+    bool slot_free = true;
+    PCIBus *bus = acpi_pcihp_find_hotplug_bus(s, bsel);
+
+    if (!bus) {
+        return;
+    }
+
+    /* Mark request as complete */
+    s->acpi_pcihp_pci_status[bsel].down &= ~(1U << slot);
+
+    QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) {
+        DeviceState *qdev = kid->child;
+        PCIDevice *dev = PCI_DEVICE(qdev);
+        if (PCI_SLOT(dev->devfn) == slot) {
+            if (acpi_pcihp_pc_no_hotplug(s, dev)) {
+                slot_free = false;
+            } else {
+                object_unparent(OBJECT(qdev));
+            }
+        }
+    }
+    if (slot_free) {
+        s->acpi_pcihp_pci_status[bsel].device_present &= ~(1U << slot);
+    }
+}
+
+static void acpi_pcihp_update_hotplug_bus(AcpiPciHpState *s, int bsel)
+{
+    BusChild *kid, *next;
+    PCIBus *bus = acpi_pcihp_find_hotplug_bus(s, bsel);
+
+    /* Execute any pending removes during reset */
+    while (s->acpi_pcihp_pci_status[bsel].down) {
+        acpi_pcihp_eject_slot(s, bsel, s->acpi_pcihp_pci_status[bsel].down);
+    }
+
+    s->acpi_pcihp_pci_status[bsel].hotplug_enable = ~0;
+    s->acpi_pcihp_pci_status[bsel].device_present = 0;
+
+    if (!bus) {
+        return;
+    }
+    QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) {
+        DeviceState *qdev = kid->child;
+        PCIDevice *pdev = PCI_DEVICE(qdev);
+        int slot = PCI_SLOT(pdev->devfn);
+
+        if (acpi_pcihp_pc_no_hotplug(s, pdev)) {
+            s->acpi_pcihp_pci_status[bsel].hotplug_enable &= ~(1U << slot);
+        }
+
+        s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot);
+    }
+}
+
+static void acpi_pcihp_update(AcpiPciHpState *s)
+{
+    int i;
+
+    for (i = 0; i < ACPI_PCIHP_MAX_HOTPLUG_BUS; ++i) {
+        acpi_pcihp_update_hotplug_bus(s, i);
+    }
+}
+
+void acpi_pcihp_reset(AcpiPciHpState *s)
+{
+    acpi_pcihp_update(s);
+}
+
+static void enable_device(AcpiPciHpState *s, unsigned bsel, int slot)
+{
+    s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot);
+}
+
+static void disable_device(AcpiPciHpState *s, unsigned bsel, int slot)
+{
+    s->acpi_pcihp_pci_status[bsel].down |= (1U << slot);
+}
+
+int acpi_pcihp_device_hotplug(AcpiPciHpState *s, PCIDevice *dev,
+                              PCIHotplugState state)
+{
+    int slot = PCI_SLOT(dev->devfn);
+    int bsel = acpi_pcihp_get_bsel(dev->bus);
+    if (bsel < 0) {
+        return -1;
+    }
+
+    /* Don't send event when device is enabled during qemu machine creation:
+     * it is present on boot, no hotplug event is necessary. We do send an
+     * event when the device is disabled later. */
+    if (state == PCI_COLDPLUG_ENABLED) {
+        s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot);
+        return 0;
+    }
+
+    if (state == PCI_HOTPLUG_ENABLED) {
+        enable_device(s, bsel, slot);
+    } else {
+        disable_device(s, bsel, slot);
+    }
+
+    return 0;
+}
+
+static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
+{
+    AcpiPciHpState *s = opaque;
+    uint32_t val = 0;
+    int bsel = s->hotplug_select;
+
+    if (bsel < 0 || bsel > ACPI_PCIHP_MAX_HOTPLUG_BUS) {
+        return 0;
+    }
+
+    switch (addr) {
+    case PCI_UP_BASE - PCI_HOTPLUG_ADDR:
+        /* Manufacture an "up" value to cause a device check on any hotplug
+         * slot with a device.  Extra device checks are harmless. */
+        val = s->acpi_pcihp_pci_status[bsel].device_present &
+            s->acpi_pcihp_pci_status[bsel].hotplug_enable;
+        ACPI_PCIHP_DPRINTF("pci_up_read %" PRIu32 "\n", val);
+        break;
+    case PCI_DOWN_BASE - PCI_HOTPLUG_ADDR:
+        val = s->acpi_pcihp_pci_status[bsel].down;
+        ACPI_PCIHP_DPRINTF("pci_down_read %" PRIu32 "\n", val);
+        break;
+    case PCI_EJ_BASE - PCI_HOTPLUG_ADDR:
+        /* No feature defined yet */
+        ACPI_PCIHP_DPRINTF("pci_features_read %" PRIu32 "\n", val);
+        break;
+    case PCI_RMV_BASE - PCI_HOTPLUG_ADDR:
+        val = s->acpi_pcihp_pci_status[bsel].hotplug_enable;
+        ACPI_PCIHP_DPRINTF("pci_rmv_read %" PRIu32 "\n", val);
+        break;
+    case PCI_SEL_BASE - PCI_HOTPLUG_ADDR:
+        val = s->hotplug_select;
+        ACPI_PCIHP_DPRINTF("pci_sel_read %" PRIu32 "\n", val);
+    default:
+        break;
+    }
+
+    return val;
+}
+
+static void pci_write(void *opaque, hwaddr addr, uint64_t data,
+                      unsigned int size)
+{
+    AcpiPciHpState *s = opaque;
+    switch (addr) {
+    case PCI_EJ_BASE - PCI_HOTPLUG_ADDR:
+        if (s->hotplug_select >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
+            break;
+        }
+        acpi_pcihp_eject_slot(s, s->hotplug_select, data);
+        ACPI_PCIHP_DPRINTF("pciej write %" HWADDR_PRIx " <== %" PRIu64 "\n",
+                      addr, data);
+        break;
+    case PCI_SEL_BASE - PCI_HOTPLUG_ADDR:
+        s->hotplug_select = data;
+        ACPI_PCIHP_DPRINTF("pcisel write %" HWADDR_PRIx " <== %" PRIu64 "\n",
+                      addr, data);
+    default:
+        break;
+    }
+}
+
+static const MemoryRegionOps acpi_pcihp_io_ops = {
+    .read = pci_read,
+    .write = pci_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+void acpi_pcihp_init(AcpiPciHpState *s, PCIBus *root_bus,
+                     MemoryRegion *address_space_io)
+{
+    s->root= root_bus;
+    memory_region_init_io(&s->io, NULL, &acpi_pcihp_io_ops, s,
+                          "acpi-pci-hotplug",
+                          PCI_HOTPLUG_SIZE);
+    memory_region_add_subregion(address_space_io, PCI_HOTPLUG_ADDR, &s->io);
+}
+
+const VMStateDescription vmstate_acpi_pcihp_pci_status = {
+    .name = "acpi_pcihp_pci_status",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_UINT32(up, AcpiPciHpPciStatus),
+        VMSTATE_UINT32(down, AcpiPciHpPciStatus),
+        VMSTATE_END_OF_LIST()
+    }
+};
diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h
new file mode 100644
index 0000000..6230e60
--- /dev/null
+++ b/include/hw/acpi/pcihp.h
@@ -0,0 +1,72 @@
+/*
+ * QEMU<->ACPI BIOS PCI hotplug interface
+ *
+ * QEMU supports PCI hotplug via ACPI. This module
+ * implements the interface between QEMU and the ACPI BIOS.
+ * Interface specification - see docs/specs/acpi_pci_hotplug.txt
+ *
+ * Copyright (c) 2013, Red Hat Inc, Michael S. Tsirkin (mst at redhat.com)
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#ifndef HW_ACPI_PCIHP_H
+#define HW_ACPI_PCIHP_H
+
+#include <inttypes.h>
+#include <qemu/typedefs.h>
+#include "hw/pci/pci.h" /* for PCIHotplugState */
+
+typedef struct AcpiPciHpPciStatus {
+    uint32_t up; /* deprecated, maintained for migration compatibility */
+    uint32_t down;
+    uint32_t hotplug_enable;
+    uint32_t device_present;
+} AcpiPciHpPciStatus;
+
+#define ACPI_PCIHP_PROP_BSEL "acpi-pcihp-bsel"
+#define ACPI_PCIHP_MAX_HOTPLUG_BUS 256
+
+typedef struct AcpiPciHpState {
+    AcpiPciHpPciStatus acpi_pcihp_pci_status[ACPI_PCIHP_MAX_HOTPLUG_BUS];
+    uint32_t hotplug_select;
+    PCIBus *root;
+    MemoryRegion io;
+} AcpiPciHpState;
+
+void acpi_pcihp_init(AcpiPciHpState *, PCIBus *root,
+                     MemoryRegion *address_space_io);
+
+/* Invoke on device hotplug */
+int acpi_pcihp_device_hotplug(AcpiPciHpState *, PCIDevice *,
+                              PCIHotplugState state);
+
+/* Called on reset */
+void acpi_pcihp_reset(AcpiPciHpState *s);
+
+extern const VMStateDescription vmstate_acpi_pcihp_pci_status;
+
+#define VMSTATE_PCI_HOTPLUG(pcihp, state, test_pcihp) \
+        VMSTATE_UINT32_TEST(pcihp.hotplug_select, state, \
+                            test_pcihp), \
+        VMSTATE_STRUCT_ARRAY_TEST(pcihp.acpi_pcihp_pci_status, state, \
+                                  ACPI_PCIHP_MAX_HOTPLUG_BUS, \
+                                  test_pcihp, 1, \
+                                  vmstate_acpi_pcihp_pci_status, \
+                                  AcpiPciHpPciStatus)
+
+#endif
commit eb0acfdde604930688c47fe1ba99bec2bd84b7ad
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Oct 14 18:01:07 2013 +0300

    pci: add pci_for_each_bus_depth_first
    
    Useful for ACPI hotplug.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index aa2a395..2aca8a4 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1704,6 +1704,34 @@ static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num)
     return NULL;
 }
 
+void pci_for_each_bus_depth_first(PCIBus *bus,
+                                  void *(*begin)(PCIBus *bus, void *parent_state),
+                                  void (*end)(PCIBus *bus, void *state),
+                                  void *parent_state)
+{
+    PCIBus *sec;
+    void *state;
+
+    if (!bus) {
+        return;
+    }
+
+    if (begin) {
+        state = begin(bus, parent_state);
+    } else {
+        state = parent_state;
+    }
+
+    QLIST_FOREACH(sec, &bus->child, sibling) {
+        pci_for_each_bus_depth_first(sec, begin, end, state);
+    }
+
+    if (end) {
+        end(bus, state);
+    }
+}
+
+
 PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn)
 {
     bus = pci_find_bus_nr(bus, bus_num);
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 754b82d..5252346 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -387,6 +387,20 @@ int pci_bus_num(PCIBus *s);
 void pci_for_each_device(PCIBus *bus, int bus_num,
                          void (*fn)(PCIBus *bus, PCIDevice *d, void *opaque),
                          void *opaque);
+void pci_for_each_bus_depth_first(PCIBus *bus,
+                                  void *(*begin)(PCIBus *bus, void *parent_state),
+                                  void (*end)(PCIBus *bus, void *state),
+                                  void *parent_state);
+
+/* Use this wrapper when specific scan order is not required. */
+static inline
+void pci_for_each_bus(PCIBus *bus,
+                      void (*fn)(PCIBus *bus, void *opaque),
+                      void *opaque)
+{
+    pci_for_each_bus_depth_first(bus, NULL, fn, opaque);
+}
+
 PCIBus *pci_find_primary_bus(void);
 PCIBus *pci_device_root_bus(const PCIDevice *d);
 const char *pci_root_bus_path(PCIDevice *dev);
commit 4d25299cb2b57a16fd3194e938eeb78d219400ba
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Jan 9 17:36:33 2014 +0100

    pc: make: fix dependencies: rebuild when included file is changed
    
    some *.dsl files include another *.dsl files but there weren't
    any dependicies and when included file changed target table wasn't
    rebuild. Fix this by using the same auto dependency generation
    as for C files.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 09ac433..d58a103 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -17,7 +17,7 @@ iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
 ifdef IASL
 #IASL Present. Generate hex files from .dsl
 hw/i386/%.hex: $(SRC_PATH)/hw/i386/%.dsl $(SRC_PATH)/scripts/acpi_extract_preprocess.py $(SRC_PATH)/scripts/acpi_extract.py
-	$(call quiet-command, cpp -P $< -o $*.dsl.i.orig, "  CPP $(TARGET_DIR)$*.dsl.i.orig")
+	$(call quiet-command, cpp -P $(QEMU_DGFLAGS) $< -o $*.dsl.i.orig, "  CPP $(TARGET_DIR)$*.dsl.i.orig")
 	$(call quiet-command, $(PYTHON) $(SRC_PATH)/scripts/acpi_extract_preprocess.py $*.dsl.i.orig > $*.dsl.i, "  ACPI_PREPROCESS $(TARGET_DIR)$*.dsl.i")
 	$(call quiet-command, $(IASL) $(call iasl-option,$(IASL),-Pn,) -vs -l -tc -p $* $*.dsl.i $(if $(V), , > /dev/null) 2>&1 ,"  IASL $(TARGET_DIR)$*.dsl.i")
 	$(call quiet-command, $(PYTHON) $(SRC_PATH)/scripts/acpi_extract.py $*.lst > $*.off, "  ACPI_EXTRACT $(TARGET_DIR)$*.off")
commit 0651596cbed8c0806aa2d7e436201f28b2fe179a
Author: Marcel Apfelbaum <marcel.a at redhat.com>
Date:   Thu Jan 16 17:50:48 2014 +0200

    acpi unit-test: do not fail on asl mismatch
    
    The asl comparison will break every time the ACPI
    tables are updated. This may break the git bisect.
    Instead of failing print a warning on stderr
    including the retained asl files, so they can be
    compared offline.
    
    Signed-off-by: Marcel Apfelbaum <marcel.a at redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/tests/acpi-test.c b/tests/acpi-test.c
index 6095d07..31f5359 100644
--- a/tests/acpi-test.c
+++ b/tests/acpi-test.c
@@ -34,6 +34,7 @@ typedef struct {
     gchar *asl;            /* asl code generated from aml */
     gsize asl_len;
     gchar *asl_file;
+    bool asl_file_retain;   /* do not delete the temp asl */
 } QEMU_PACKED AcpiSdtTable;
 
 typedef struct {
@@ -161,7 +162,7 @@ static void free_test_data(test_data *data)
             g_free(temp->asl);
         }
         if (temp->asl_file) {
-            if (g_strstr_len(temp->asl_file, -1, "asl-")) {
+            if (!temp->asl_file_retain) {
                 unlink(temp->asl_file);
             }
             g_free(temp->asl_file);
@@ -532,7 +533,15 @@ static void test_acpi_asl(test_data *data)
         load_asl(exp_data.tables, exp_sdt);
         exp_asl = normalize_asl(exp_sdt->asl);
 
-        g_assert(!g_strcmp0(asl->str, exp_asl->str));
+        if (g_strcmp0(asl->str, exp_asl->str)) {
+            sdt->asl_file_retain = true;
+            exp_sdt->asl_file_retain = true;
+            fprintf(stderr,
+                    "acpi-test: Warning! %.4s mismatch. "
+                    "Orig asl: %s, expected asl %s.\n",
+                    (gchar *)&exp_sdt->header.signature,
+                    sdt->asl_file, exp_sdt->asl_file);
+        }
         g_string_free(asl, true);
         g_string_free(exp_asl, true);
     }
commit 69d09245d19765fd461cc3d3a7d79686007c4474
Author: Marcel Apfelbaum <marcel.a at redhat.com>
Date:   Thu Jan 16 17:50:47 2014 +0200

    acpi unit-test: resolved iasl crash
    
    It seems that iasl has an issue when disassembles
    some ACPI tables using the command line:
    iasl -e DSDT -e SSDT -d HPET
    
    Modified the iasl command line to "iasl -d HPET"
    until the problem is solved. The command line
    remained the same for DSDT and SSDT tables.
    
    Reported-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Marcel Apfelbaum <marcel.a at redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/tests/acpi-test.c b/tests/acpi-test.c
index a3d2b34..6095d07 100644
--- a/tests/acpi-test.c
+++ b/tests/acpi-test.c
@@ -23,6 +23,7 @@
 #define MACHINE_Q35 "q35"
 
 #define ACPI_REBUILD_EXPECTED_AML "TEST_ACPI_REBUILD_AML"
+#define ACPI_SSDT_SIGNATURE 0x54445353 /* SSDT */
 
 /* DSDT and SSDTs format */
 typedef struct {
@@ -403,6 +404,11 @@ static void dump_aml_files(test_data *data, bool rebuild)
     }
 }
 
+static bool compare_signature(AcpiSdtTable *sdt, uint32_t signature)
+{
+   return sdt->header.signature == signature;
+}
+
 static void load_asl(GArray *sdts, AcpiSdtTable *sdt)
 {
     AcpiSdtTable *temp;
@@ -419,9 +425,15 @@ static void load_asl(GArray *sdts, AcpiSdtTable *sdt)
 
     /* build command line */
     g_string_append_printf(command_line, " -p %s ", sdt->asl_file);
-    for (i = 0; i < 2; ++i) { /* reference DSDT and SSDT */
-        temp = &g_array_index(sdts, AcpiSdtTable, i);
-        g_string_append_printf(command_line, "-e %s ", temp->aml_file);
+    if (compare_signature(sdt, ACPI_DSDT_SIGNATURE) ||
+        compare_signature(sdt, ACPI_SSDT_SIGNATURE)) {
+        for (i = 0; i < sdts->len; ++i) {
+            temp = &g_array_index(sdts, AcpiSdtTable, i);
+            if (compare_signature(temp, ACPI_DSDT_SIGNATURE) ||
+                compare_signature(temp, ACPI_SSDT_SIGNATURE)) {
+                g_string_append_printf(command_line, "-e %s ", temp->aml_file);
+            }
+        }
     }
     g_string_append_printf(command_line, "-d %s", sdt->aml_file);
 
commit a3a74ab90ea81cafaf4d03824d47a6d028ea996d
Author: Marcel Apfelbaum <marcel.a at redhat.com>
Date:   Thu Jan 16 17:50:46 2014 +0200

    acpi unit-test: renamed ssdt_tables to tables
    
    Just a refactoring, ssdt_tables name was confusing as
    it included other tables as well.
    
    Signed-off-by: Marcel Apfelbaum <marcel.a at redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/tests/acpi-test.c b/tests/acpi-test.c
index b5ab70a..a3d2b34 100644
--- a/tests/acpi-test.c
+++ b/tests/acpi-test.c
@@ -44,7 +44,7 @@ typedef struct {
     AcpiFacsDescriptorRev1 facs_table;
     uint32_t *rsdt_tables_addr;
     int rsdt_tables_nr;
-    GArray *ssdt_tables; /* first is DSDT */
+    GArray *tables;
 } test_data;
 
 #define LOW(x) ((x) & 0xff)
@@ -145,8 +145,8 @@ static void free_test_data(test_data *data)
         g_free(data->rsdt_tables_addr);
     }
 
-    for (i = 0; i < data->ssdt_tables->len; ++i) {
-        temp = &g_array_index(data->ssdt_tables, AcpiSdtTable, i);
+    for (i = 0; i < data->tables->len; ++i) {
+        temp = &g_array_index(data->tables, AcpiSdtTable, i);
         if (temp->aml) {
             g_free(temp->aml);
         }
@@ -167,7 +167,7 @@ static void free_test_data(test_data *data)
         }
     }
 
-    g_array_free(data->ssdt_tables, false);
+    g_array_free(data->tables, false);
 }
 
 static uint8_t acpi_checksum(const uint8_t *data, int len)
@@ -342,27 +342,27 @@ static void test_acpi_dsdt_table(test_data *data)
     uint32_t addr = data->fadt_table.dsdt;
 
     memset(&dsdt_table, 0, sizeof(dsdt_table));
-    data->ssdt_tables = g_array_new(false, true, sizeof(AcpiSdtTable));
+    data->tables = g_array_new(false, true, sizeof(AcpiSdtTable));
 
     test_dst_table(&dsdt_table, addr);
     g_assert_cmphex(dsdt_table.header.signature, ==, ACPI_DSDT_SIGNATURE);
 
     /* Place DSDT first */
-    g_array_append_val(data->ssdt_tables, dsdt_table);
+    g_array_append_val(data->tables, dsdt_table);
 }
 
-static void test_acpi_ssdt_tables(test_data *data)
+static void test_acpi_tables(test_data *data)
 {
-    int ssdt_tables_nr = data->rsdt_tables_nr - 1; /* fadt is first */
+    int tables_nr = data->rsdt_tables_nr - 1; /* fadt is first */
     int i;
 
-    for (i = 0; i < ssdt_tables_nr; i++) {
+    for (i = 0; i < tables_nr; i++) {
         AcpiSdtTable ssdt_table;
 
         memset(&ssdt_table, 0 , sizeof(ssdt_table));
         uint32_t addr = data->rsdt_tables_addr[i + 1]; /* fadt is first */
         test_dst_table(&ssdt_table, addr);
-        g_array_append_val(data->ssdt_tables, ssdt_table);
+        g_array_append_val(data->tables, ssdt_table);
     }
 }
 
@@ -375,8 +375,8 @@ static void dump_aml_files(test_data *data, bool rebuild)
     ssize_t ret;
     int i;
 
-    for (i = 0; i < data->ssdt_tables->len; ++i) {
-        sdt = &g_array_index(data->ssdt_tables, AcpiSdtTable, i);
+    for (i = 0; i < data->tables->len; ++i) {
+        sdt = &g_array_index(data->tables, AcpiSdtTable, i);
         g_assert(sdt->aml);
 
         if (rebuild) {
@@ -474,10 +474,10 @@ static GArray *load_expected_aml(test_data *data)
     GError *error = NULL;
     gboolean ret;
 
-    GArray *exp_ssdt_tables = g_array_new(false, true, sizeof(AcpiSdtTable));
-    for (i = 0; i < data->ssdt_tables->len; ++i) {
+    GArray *exp_tables = g_array_new(false, true, sizeof(AcpiSdtTable));
+    for (i = 0; i < data->tables->len; ++i) {
         AcpiSdtTable exp_sdt;
-        sdt = &g_array_index(data->ssdt_tables, AcpiSdtTable, i);
+        sdt = &g_array_index(data->tables, AcpiSdtTable, i);
 
         memset(&exp_sdt, 0, sizeof(exp_sdt));
         exp_sdt.header.signature = sdt->header.signature;
@@ -493,10 +493,10 @@ static GArray *load_expected_aml(test_data *data)
         g_assert(exp_sdt.aml);
         g_assert(exp_sdt.aml_len);
 
-        g_array_append_val(exp_ssdt_tables, exp_sdt);
+        g_array_append_val(exp_tables, exp_sdt);
     }
 
-    return exp_ssdt_tables;
+    return exp_tables;
 }
 
 static void test_acpi_asl(test_data *data)
@@ -506,18 +506,18 @@ static void test_acpi_asl(test_data *data)
     test_data exp_data;
 
     memset(&exp_data, 0, sizeof(exp_data));
-    exp_data.ssdt_tables = load_expected_aml(data);
+    exp_data.tables = load_expected_aml(data);
     dump_aml_files(data, false);
-    for (i = 0; i < data->ssdt_tables->len; ++i) {
+    for (i = 0; i < data->tables->len; ++i) {
         GString *asl, *exp_asl;
 
-        sdt = &g_array_index(data->ssdt_tables, AcpiSdtTable, i);
-        exp_sdt = &g_array_index(exp_data.ssdt_tables, AcpiSdtTable, i);
+        sdt = &g_array_index(data->tables, AcpiSdtTable, i);
+        exp_sdt = &g_array_index(exp_data.tables, AcpiSdtTable, i);
 
-        load_asl(data->ssdt_tables, sdt);
+        load_asl(data->tables, sdt);
         asl = normalize_asl(sdt->asl);
 
-        load_asl(exp_data.ssdt_tables, exp_sdt);
+        load_asl(exp_data.tables, exp_sdt);
         exp_asl = normalize_asl(exp_sdt->asl);
 
         g_assert(!g_strcmp0(asl->str, exp_asl->str));
@@ -570,7 +570,7 @@ static void test_acpi_one(const char *params, test_data *data)
     test_acpi_fadt_table(data);
     test_acpi_facs_table(data);
     test_acpi_dsdt_table(data);
-    test_acpi_ssdt_tables(data);
+    test_acpi_tables(data);
 
     if (iasl) {
         if (getenv(ACPI_REBUILD_EXPECTED_AML)) {
commit 084137ddbbb30f5f85298711dc2d501a625d37ab
Author: Alexey Kardashevskiy <aik at ozlabs.ru>
Date:   Mon Jan 13 18:33:53 2014 +1100

    tests: fix acpi to work on bigendian host
    
    Double endianness convertion make this test failing on POWERPC machine
    running in big-endian.
    
    This fixes the test to success on big-endian host.
    
    Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/tests/acpi-test.c b/tests/acpi-test.c
index 89c4b81..b5ab70a 100644
--- a/tests/acpi-test.c
+++ b/tests/acpi-test.c
@@ -61,13 +61,13 @@ typedef struct {
             field = readb(addr);               \
             break;                             \
         case 2:                                \
-            field = le16_to_cpu(readw(addr));  \
+            field = readw(addr);               \
             break;                             \
         case 4:                                \
-            field = le32_to_cpu(readl(addr));  \
+            field = readl(addr);               \
             break;                             \
         case 8:                                \
-            field = le64_to_cpu(readq(addr));  \
+            field = readq(addr);               \
             break;                             \
         default:                               \
             g_assert(false);                   \
commit 4500bc98a6aab1734d865afaeade3509eb65b560
Author: Marcel Apfelbaum <marcel.a at redhat.com>
Date:   Thu Dec 26 16:54:25 2013 +0200

    acpi unit-test: hook to rebuild expected aml files
    
    When running the test with TEST_ACPI_REBUILD_AML=y environment
    variable, the test will rebuild and validate the expected aml
    files.
    
    Signed-off-by: Marcel Apfelbaum <marcel.a at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/tests/acpi-test.c b/tests/acpi-test.c
index 83e5aed..89c4b81 100644
--- a/tests/acpi-test.c
+++ b/tests/acpi-test.c
@@ -13,6 +13,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <glib.h>
+#include <glib/gstdio.h>
 #include "qemu-common.h"
 #include "libqtest.h"
 #include "qemu/compiler.h"
@@ -21,6 +22,8 @@
 #define MACHINE_PC "pc"
 #define MACHINE_Q35 "q35"
 
+#define ACPI_REBUILD_EXPECTED_AML "TEST_ACPI_REBUILD_AML"
+
 /* DSDT and SSDTs format */
 typedef struct {
     AcpiTableHeader header;
@@ -363,10 +366,11 @@ static void test_acpi_ssdt_tables(test_data *data)
     }
 }
 
-static void dump_aml_files(test_data *data)
+static void dump_aml_files(test_data *data, bool rebuild)
 {
     AcpiSdtTable *sdt;
     GError *error = NULL;
+    gchar *aml_file = NULL;
     gint fd;
     ssize_t ret;
     int i;
@@ -375,8 +379,16 @@ static void dump_aml_files(test_data *data)
         sdt = &g_array_index(data->ssdt_tables, AcpiSdtTable, i);
         g_assert(sdt->aml);
 
-        fd = g_file_open_tmp("aml-XXXXXX", &sdt->aml_file, &error);
-        g_assert_no_error(error);
+        if (rebuild) {
+            aml_file = g_strdup_printf("%s/%s/%.4s", data_dir, data->machine,
+                                       (gchar *)&sdt->header.signature);
+            fd = g_open(aml_file, O_WRONLY|O_TRUNC|O_CREAT,
+                        S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
+        } else {
+            fd = g_file_open_tmp("aml-XXXXXX", &sdt->aml_file, &error);
+            g_assert_no_error(error);
+        }
+        g_assert(fd >= 0);
 
         ret = qemu_write_full(fd, sdt, sizeof(AcpiTableHeader));
         g_assert(ret == sizeof(AcpiTableHeader));
@@ -384,6 +396,10 @@ static void dump_aml_files(test_data *data)
         g_assert(ret == sdt->aml_len);
 
         close(fd);
+
+        if (aml_file) {
+            g_free(aml_file);
+        }
     }
 }
 
@@ -491,7 +507,7 @@ static void test_acpi_asl(test_data *data)
 
     memset(&exp_data, 0, sizeof(exp_data));
     exp_data.ssdt_tables = load_expected_aml(data);
-    dump_aml_files(data);
+    dump_aml_files(data, false);
     for (i = 0; i < data->ssdt_tables->len; ++i) {
         GString *asl, *exp_asl;
 
@@ -557,7 +573,11 @@ static void test_acpi_one(const char *params, test_data *data)
     test_acpi_ssdt_tables(data);
 
     if (iasl) {
-        test_acpi_asl(data);
+        if (getenv(ACPI_REBUILD_EXPECTED_AML)) {
+            dump_aml_files(data, true);
+        } else {
+            test_acpi_asl(data);
+        }
     }
 
     qtest_quit(global_qtest);
commit cebc92a2131be21cc4dc5f72f1e243061cd96b1f
Author: Marcel Apfelbaum <marcel.a at redhat.com>
Date:   Thu Dec 26 16:54:24 2013 +0200

    acpi unit-test: added script to rebuild the expected aml files
    
    Acpi unit-test will fail every time the acpi tables change.
    This script rebuild the expected aml files, so the test
    will pass. It also validates the modifications.
    
    Signed-off-by: Marcel Apfelbaum <marcel.a at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/tests/acpi-test-data/rebuild-expected-aml.sh b/tests/acpi-test-data/rebuild-expected-aml.sh
new file mode 100755
index 0000000..ab98498
--- /dev/null
+++ b/tests/acpi-test-data/rebuild-expected-aml.sh
@@ -0,0 +1,36 @@
+#! /bin/bash
+
+#
+# Rebuild expected AML files for acpi unit-test
+#
+# Copyright (c) 2013 Red Hat Inc.
+#
+# Authors:
+#  Marcel Apfelbaum <marcel.a at redhat.com>
+#
+# This work is licensed under the terms of the GNU GPLv2.
+# See the COPYING.LIB file in the top-level directory.
+
+qemu=
+
+if [ -e x86_64-softmmu/qemu-system-x86_64 ]; then
+    qemu="x86_64-softmmu/qemu-system-x86_64"
+elif [ -e i386-softmmu/qemu-system-i386 ]; then
+    qemu="i386-softmmu/qemu-system-i386"
+else
+    echo "Run 'make' to build the qemu exectutable!"
+    echo "Run this script from the build directory."
+    exit 1;
+fi
+
+if [ ! -e "tests/acpi-test" ]; then
+    echo "Test: acpi-test is required! Run make check before this script."
+    echo "Run this script from the build directory."
+    exit 1;
+fi
+
+TEST_ACPI_REBUILD_AML=y QTEST_QEMU_BINARY=$qemu tests/acpi-test
+
+echo "The files were rebuilt and can be added to git."
+echo "However, if new files were created, please copy them manually" \
+     "to tests/acpi-test-data/pc/ or tests/acpi-test-data/q35/ ."
commit cc8fa0e80836c51ba644d910cd89540a5bc83fc2
Author: Marcel Apfelbaum <marcel.a at redhat.com>
Date:   Thu Dec 26 16:54:23 2013 +0200

    acpi unit-test: extract iasl executable from configuration
    
    The test checked if iasl is installed by running "iasl"
    and checking the error output.
    It is better to use the iasl executable as appears
    in configuration.
    
    Signed-off-by: Marcel Apfelbaum <marcel.a at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/tests/acpi-test.c b/tests/acpi-test.c
index c3fc603..83e5aed 100644
--- a/tests/acpi-test.c
+++ b/tests/acpi-test.c
@@ -127,6 +127,11 @@ static uint8_t boot_sector[0x7e000] = {
 
 static const char *disk = "tests/acpi-test-disk.raw";
 static const char *data_dir = "tests/acpi-test-data";
+#ifdef CONFIG_IASL
+static const char *iasl = stringify(CONFIG_IASL);
+#else
+static const char *iasl;
+#endif
 
 static void free_test_data(test_data *data)
 {
@@ -358,26 +363,6 @@ static void test_acpi_ssdt_tables(test_data *data)
     }
 }
 
-static bool iasl_installed(void)
-{
-    gchar *out = NULL, *out_err = NULL;
-    bool ret;
-
-    /* pass 'out' and 'out_err' in order to be redirected */
-    ret = g_spawn_command_line_sync("iasl", &out, &out_err, NULL, NULL);
-
-    if (out_err) {
-        ret = ret && (out_err[0] == '\0');
-        g_free(out_err);
-    }
-
-    if (out) {
-        g_free(out);
-    }
-
-    return ret;
-}
-
 static void dump_aml_files(test_data *data)
 {
     AcpiSdtTable *sdt;
@@ -406,7 +391,7 @@ static void load_asl(GArray *sdts, AcpiSdtTable *sdt)
 {
     AcpiSdtTable *temp;
     GError *error = NULL;
-    GString *command_line = g_string_new("'iasl' ");
+    GString *command_line = g_string_new(iasl);
     gint fd;
     gchar *out, *out_err;
     gboolean ret;
@@ -417,7 +402,7 @@ static void load_asl(GArray *sdts, AcpiSdtTable *sdt)
     close(fd);
 
     /* build command line */
-    g_string_append_printf(command_line, "-p %s ", sdt->asl_file);
+    g_string_append_printf(command_line, " -p %s ", sdt->asl_file);
     for (i = 0; i < 2; ++i) { /* reference DSDT and SSDT */
         temp = &g_array_index(sdts, AcpiSdtTable, i);
         g_string_append_printf(command_line, "-e %s ", temp->aml_file);
@@ -571,7 +556,7 @@ static void test_acpi_one(const char *params, test_data *data)
     test_acpi_dsdt_table(data);
     test_acpi_ssdt_tables(data);
 
-    if (iasl_installed()) {
+    if (iasl) {
         test_acpi_asl(data);
     }
 
commit 9dd6cabdd3bfa49d4f594956e8ee93f8996460c7
Author: Marcel Apfelbaum <marcel.a at redhat.com>
Date:   Thu Dec 26 16:54:22 2013 +0200

    configure: add CONFIG_IASL to config-host.h
    
    Acpi unit-tests will extract iasl executable
    from CONFIG_IASL define.
    
    Signed-off-by: Marcel Apfelbaum <marcel.a at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/scripts/create_config b/scripts/create_config
index b1adbf5..06f5316 100755
--- a/scripts/create_config
+++ b/scripts/create_config
@@ -26,6 +26,10 @@ case $line in
     # save for the next definitions
     prefix=${line#*=}
     ;;
+ IASL=*) # iasl executable
+    value=${line#*=}
+    echo "#define CONFIG_IASL $value"
+    ;;
  CONFIG_AUDIO_DRIVERS=*)
     drivers=${line#*=}
     echo "#define CONFIG_AUDIO_DRIVERS \\"
commit 9e8458c0232356a0c0eebb4fa4928fd02250c5f4
Author: Marcel Apfelbaum <marcel.a at redhat.com>
Date:   Thu Dec 26 16:54:21 2013 +0200

    acpi unit-test: compare DSDT and SSDT tables against expected values
    
    This test will run only if iasl is installed on the host machine.
    The test plan:
     1. Dumps the ACPI tables as AML on the disk.
     2. Runs iasl to disassembly the tables into ASL files.
     3. Runs iasl to disassembly the offline AML files into ASL files.
     4. Compares the ASL files.
    
    The test runs for both default machine and q35.
    In case the test fails, it can be easily tweaked to
    show the differences between the ASL files and
    understand the issue.
    
    Signed-off-by: Marcel Apfelbaum <marcel.a at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/tests/acpi-test.c b/tests/acpi-test.c
index df1af83..c3fc603 100644
--- a/tests/acpi-test.c
+++ b/tests/acpi-test.c
@@ -18,14 +18,22 @@
 #include "qemu/compiler.h"
 #include "hw/i386/acpi-defs.h"
 
+#define MACHINE_PC "pc"
+#define MACHINE_Q35 "q35"
+
 /* DSDT and SSDTs format */
 typedef struct {
     AcpiTableHeader header;
-    uint8_t *aml;
-    int aml_len;
-} AcpiSdtTable;
+    gchar *aml;            /* aml bytecode from guest */
+    gsize aml_len;
+    gchar *aml_file;
+    gchar *asl;            /* asl code generated from aml */
+    gsize asl_len;
+    gchar *asl_file;
+} QEMU_PACKED AcpiSdtTable;
 
 typedef struct {
+    const char *machine;
     uint32_t rsdp_addr;
     AcpiRsdpDescriptor rsdp_table;
     AcpiRsdtDescriptorRev1 rsdt_table;
@@ -33,8 +41,7 @@ typedef struct {
     AcpiFacsDescriptorRev1 facs_table;
     uint32_t *rsdt_tables_addr;
     int rsdt_tables_nr;
-    AcpiSdtTable dsdt_table;
-    GArray *ssdt_tables;
+    GArray *ssdt_tables; /* first is DSDT */
 } test_data;
 
 #define LOW(x) ((x) & 0xff)
@@ -91,8 +98,10 @@ typedef struct {
 
 /* Boot sector code: write SIGNATURE into memory,
  * then halt.
+ * Q35 machine requires a minimum 0x7e000 bytes disk.
+ * (bug or feature?)
  */
-static uint8_t boot_sector[0x200] = {
+static uint8_t boot_sector[0x7e000] = {
     /* 7c00: mov $0xdead,%ax */
     [0x00] = 0xb8,
     [0x01] = LOW(SIGNATURE),
@@ -117,17 +126,40 @@ static uint8_t boot_sector[0x200] = {
 };
 
 static const char *disk = "tests/acpi-test-disk.raw";
+static const char *data_dir = "tests/acpi-test-data";
 
 static void free_test_data(test_data *data)
 {
+    AcpiSdtTable *temp;
     int i;
 
-    g_free(data->rsdt_tables_addr);
+    if (data->rsdt_tables_addr) {
+        g_free(data->rsdt_tables_addr);
+    }
+
     for (i = 0; i < data->ssdt_tables->len; ++i) {
-        g_free(g_array_index(data->ssdt_tables, AcpiSdtTable, i).aml);
+        temp = &g_array_index(data->ssdt_tables, AcpiSdtTable, i);
+        if (temp->aml) {
+            g_free(temp->aml);
+        }
+        if (temp->aml_file) {
+            if (g_strstr_len(temp->aml_file, -1, "aml-")) {
+                unlink(temp->aml_file);
+            }
+            g_free(temp->aml_file);
+        }
+        if (temp->asl) {
+            g_free(temp->asl);
+        }
+        if (temp->asl_file) {
+            if (g_strstr_len(temp->asl_file, -1, "asl-")) {
+                unlink(temp->asl_file);
+            }
+            g_free(temp->asl_file);
+        }
     }
+
     g_array_free(data->ssdt_tables, false);
-    g_free(data->dsdt_table.aml);
 }
 
 static uint8_t acpi_checksum(const uint8_t *data, int len)
@@ -292,34 +324,207 @@ static void test_dst_table(AcpiSdtTable *sdt_table, uint32_t addr)
     ACPI_READ_ARRAY_PTR(sdt_table->aml, sdt_table->aml_len, addr);
 
     checksum = acpi_checksum((uint8_t *)sdt_table, sizeof(AcpiTableHeader)) +
-               acpi_checksum(sdt_table->aml, sdt_table->aml_len);
+               acpi_checksum((uint8_t *)sdt_table->aml, sdt_table->aml_len);
     g_assert(!checksum);
 }
 
 static void test_acpi_dsdt_table(test_data *data)
 {
-    AcpiSdtTable *dsdt_table = &data->dsdt_table;
+    AcpiSdtTable dsdt_table;
     uint32_t addr = data->fadt_table.dsdt;
 
-    test_dst_table(dsdt_table, addr);
-    g_assert_cmphex(dsdt_table->header.signature, ==, ACPI_DSDT_SIGNATURE);
+    memset(&dsdt_table, 0, sizeof(dsdt_table));
+    data->ssdt_tables = g_array_new(false, true, sizeof(AcpiSdtTable));
+
+    test_dst_table(&dsdt_table, addr);
+    g_assert_cmphex(dsdt_table.header.signature, ==, ACPI_DSDT_SIGNATURE);
+
+    /* Place DSDT first */
+    g_array_append_val(data->ssdt_tables, dsdt_table);
 }
 
 static void test_acpi_ssdt_tables(test_data *data)
 {
-    GArray *ssdt_tables;
     int ssdt_tables_nr = data->rsdt_tables_nr - 1; /* fadt is first */
     int i;
 
-    ssdt_tables = g_array_sized_new(false, true, sizeof(AcpiSdtTable),
-                                    ssdt_tables_nr);
     for (i = 0; i < ssdt_tables_nr; i++) {
         AcpiSdtTable ssdt_table;
+
+        memset(&ssdt_table, 0 , sizeof(ssdt_table));
         uint32_t addr = data->rsdt_tables_addr[i + 1]; /* fadt is first */
         test_dst_table(&ssdt_table, addr);
-        g_array_append_val(ssdt_tables, ssdt_table);
+        g_array_append_val(data->ssdt_tables, ssdt_table);
     }
-    data->ssdt_tables = ssdt_tables;
+}
+
+static bool iasl_installed(void)
+{
+    gchar *out = NULL, *out_err = NULL;
+    bool ret;
+
+    /* pass 'out' and 'out_err' in order to be redirected */
+    ret = g_spawn_command_line_sync("iasl", &out, &out_err, NULL, NULL);
+
+    if (out_err) {
+        ret = ret && (out_err[0] == '\0');
+        g_free(out_err);
+    }
+
+    if (out) {
+        g_free(out);
+    }
+
+    return ret;
+}
+
+static void dump_aml_files(test_data *data)
+{
+    AcpiSdtTable *sdt;
+    GError *error = NULL;
+    gint fd;
+    ssize_t ret;
+    int i;
+
+    for (i = 0; i < data->ssdt_tables->len; ++i) {
+        sdt = &g_array_index(data->ssdt_tables, AcpiSdtTable, i);
+        g_assert(sdt->aml);
+
+        fd = g_file_open_tmp("aml-XXXXXX", &sdt->aml_file, &error);
+        g_assert_no_error(error);
+
+        ret = qemu_write_full(fd, sdt, sizeof(AcpiTableHeader));
+        g_assert(ret == sizeof(AcpiTableHeader));
+        ret = qemu_write_full(fd, sdt->aml, sdt->aml_len);
+        g_assert(ret == sdt->aml_len);
+
+        close(fd);
+    }
+}
+
+static void load_asl(GArray *sdts, AcpiSdtTable *sdt)
+{
+    AcpiSdtTable *temp;
+    GError *error = NULL;
+    GString *command_line = g_string_new("'iasl' ");
+    gint fd;
+    gchar *out, *out_err;
+    gboolean ret;
+    int i;
+
+    fd = g_file_open_tmp("asl-XXXXXX.dsl", &sdt->asl_file, &error);
+    g_assert_no_error(error);
+    close(fd);
+
+    /* build command line */
+    g_string_append_printf(command_line, "-p %s ", sdt->asl_file);
+    for (i = 0; i < 2; ++i) { /* reference DSDT and SSDT */
+        temp = &g_array_index(sdts, AcpiSdtTable, i);
+        g_string_append_printf(command_line, "-e %s ", temp->aml_file);
+    }
+    g_string_append_printf(command_line, "-d %s", sdt->aml_file);
+
+    /* pass 'out' and 'out_err' in order to be redirected */
+    g_spawn_command_line_sync(command_line->str, &out, &out_err, NULL, &error);
+    g_assert_no_error(error);
+
+    ret = g_file_get_contents(sdt->asl_file, (gchar **)&sdt->asl,
+                              &sdt->asl_len, &error);
+    g_assert(ret);
+    g_assert_no_error(error);
+    g_assert(sdt->asl_len);
+
+    g_free(out);
+    g_free(out_err);
+    g_string_free(command_line, true);
+}
+
+#define COMMENT_END "*/"
+#define DEF_BLOCK "DefinitionBlock ("
+#define BLOCK_NAME_END ".aml"
+
+static GString *normalize_asl(gchar *asl_code)
+{
+    GString *asl = g_string_new(asl_code);
+    gchar *comment, *block_name;
+
+    /* strip comments (different generation days) */
+    comment = g_strstr_len(asl->str, asl->len, COMMENT_END);
+    if (comment) {
+        asl = g_string_erase(asl, 0, comment + sizeof(COMMENT_END) - asl->str);
+    }
+
+    /* strip def block name (it has file path in it) */
+    if (g_str_has_prefix(asl->str, DEF_BLOCK)) {
+        block_name = g_strstr_len(asl->str, asl->len, BLOCK_NAME_END);
+        g_assert(block_name);
+        asl = g_string_erase(asl, 0,
+                             block_name + sizeof(BLOCK_NAME_END) - asl->str);
+    }
+
+    return asl;
+}
+
+static GArray *load_expected_aml(test_data *data)
+{
+    int i;
+    AcpiSdtTable *sdt;
+    gchar *aml_file;
+    GError *error = NULL;
+    gboolean ret;
+
+    GArray *exp_ssdt_tables = g_array_new(false, true, sizeof(AcpiSdtTable));
+    for (i = 0; i < data->ssdt_tables->len; ++i) {
+        AcpiSdtTable exp_sdt;
+        sdt = &g_array_index(data->ssdt_tables, AcpiSdtTable, i);
+
+        memset(&exp_sdt, 0, sizeof(exp_sdt));
+        exp_sdt.header.signature = sdt->header.signature;
+
+        aml_file = g_strdup_printf("%s/%s/%.4s", data_dir, data->machine,
+                                   (gchar *)&exp_sdt.header.signature);
+        exp_sdt.aml_file = aml_file;
+        g_assert(g_file_test(aml_file, G_FILE_TEST_EXISTS));
+        ret = g_file_get_contents(aml_file, &exp_sdt.aml,
+                                  &exp_sdt.aml_len, &error);
+        g_assert(ret);
+        g_assert_no_error(error);
+        g_assert(exp_sdt.aml);
+        g_assert(exp_sdt.aml_len);
+
+        g_array_append_val(exp_ssdt_tables, exp_sdt);
+    }
+
+    return exp_ssdt_tables;
+}
+
+static void test_acpi_asl(test_data *data)
+{
+    int i;
+    AcpiSdtTable *sdt, *exp_sdt;
+    test_data exp_data;
+
+    memset(&exp_data, 0, sizeof(exp_data));
+    exp_data.ssdt_tables = load_expected_aml(data);
+    dump_aml_files(data);
+    for (i = 0; i < data->ssdt_tables->len; ++i) {
+        GString *asl, *exp_asl;
+
+        sdt = &g_array_index(data->ssdt_tables, AcpiSdtTable, i);
+        exp_sdt = &g_array_index(exp_data.ssdt_tables, AcpiSdtTable, i);
+
+        load_asl(data->ssdt_tables, sdt);
+        asl = normalize_asl(sdt->asl);
+
+        load_asl(exp_data.ssdt_tables, exp_sdt);
+        exp_asl = normalize_asl(exp_sdt->asl);
+
+        g_assert(!g_strcmp0(asl->str, exp_asl->str));
+        g_string_free(asl, true);
+        g_string_free(exp_asl, true);
+    }
+
+    free_test_data(&exp_data);
 }
 
 static void test_acpi_one(const char *params, test_data *data)
@@ -329,10 +534,14 @@ static void test_acpi_one(const char *params, test_data *data)
     uint8_t signature_high;
     uint16_t signature;
     int i;
+    const char *device = "";
 
-    memset(data, 0, sizeof(*data));
-    args = g_strdup_printf("-net none -display none %s %s",
-                           params ? params : "", disk);
+    if (!g_strcmp0(data->machine, MACHINE_Q35)) {
+        device = ",id=hd -device ide-hd,drive=hd";
+    }
+
+    args = g_strdup_printf("-net none -display none %s -drive file=%s%s,",
+                           params ? params : "", disk, device);
     qtest_start(args);
 
    /* Wait at most 1 minute */
@@ -362,6 +571,10 @@ static void test_acpi_one(const char *params, test_data *data)
     test_acpi_dsdt_table(data);
     test_acpi_ssdt_tables(data);
 
+    if (iasl_installed()) {
+        test_acpi_asl(data);
+    }
+
     qtest_quit(global_qtest);
     g_free(args);
 }
@@ -373,8 +586,14 @@ static void test_acpi_tcg(void)
     /* Supplying -machine accel argument overrides the default (qtest).
      * This is to make guest actually run.
      */
+    memset(&data, 0, sizeof(data));
+    data.machine = MACHINE_PC;
     test_acpi_one("-machine accel=tcg", &data);
+    free_test_data(&data);
 
+    memset(&data, 0, sizeof(data));
+    data.machine = MACHINE_Q35;
+    test_acpi_one("-machine q35,accel=tcg", &data);
     free_test_data(&data);
 }
 
commit c2304b52f1b20fa79d299177d1fe75df2d265bfa
Author: Marcel Apfelbaum <marcel.a at redhat.com>
Date:   Thu Dec 26 16:54:20 2013 +0200

    configure: added acpi unit-test files
    
    Ensure configure will set-up links for the files
    if the build is created in other directory.
    
    Signed-off-by: Marcel Apfelbaum <marcel.a at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/configure b/configure
index b472694..236764a 100755
--- a/configure
+++ b/configure
@@ -4774,6 +4774,10 @@ for bios_file in \
 do
     FILES="$FILES pc-bios/`basename $bios_file`"
 done
+for test_file in `find $source_path/tests/acpi-test-data -type f`
+do
+    FILES="$FILES tests/acpi-test-data`echo $test_file | sed -e 's/.*acpi-test-data//'`"
+done
 mkdir -p $DIRS
 for f in $FILES ; do
     if [ -e "$source_path/$f" ] && [ "$source_path" != `pwd` ]; then
commit d259793808052dbef6d2d90cdb09150d03b8413b
Author: Marcel Apfelbaum <marcel.a at redhat.com>
Date:   Thu Dec 26 16:54:19 2013 +0200

    acpi unit-test: add test files
    
    Added unit-test's expected aml files to be compared
    with the actual ACPI tables.
    
    Signed-off-by: Marcel Apfelbaum <marcel.a at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/tests/acpi-test-data/pc/APIC b/tests/acpi-test-data/pc/APIC
new file mode 100644
index 0000000..84509e0
Binary files /dev/null and b/tests/acpi-test-data/pc/APIC differ
diff --git a/tests/acpi-test-data/pc/DSDT b/tests/acpi-test-data/pc/DSDT
new file mode 100644
index 0000000..b12e5eb
Binary files /dev/null and b/tests/acpi-test-data/pc/DSDT differ
diff --git a/tests/acpi-test-data/pc/FACP b/tests/acpi-test-data/pc/FACP
new file mode 100644
index 0000000..0639999
Binary files /dev/null and b/tests/acpi-test-data/pc/FACP differ
diff --git a/tests/acpi-test-data/pc/FACS b/tests/acpi-test-data/pc/FACS
new file mode 100644
index 0000000..fc67ecc
Binary files /dev/null and b/tests/acpi-test-data/pc/FACS differ
diff --git a/tests/acpi-test-data/pc/HPET b/tests/acpi-test-data/pc/HPET
new file mode 100644
index 0000000..df689b8
Binary files /dev/null and b/tests/acpi-test-data/pc/HPET differ
diff --git a/tests/acpi-test-data/pc/SSDT b/tests/acpi-test-data/pc/SSDT
new file mode 100644
index 0000000..5ab1b96
Binary files /dev/null and b/tests/acpi-test-data/pc/SSDT differ
diff --git a/tests/acpi-test-data/q35/APIC b/tests/acpi-test-data/q35/APIC
new file mode 100644
index 0000000..84509e0
Binary files /dev/null and b/tests/acpi-test-data/q35/APIC differ
diff --git a/tests/acpi-test-data/q35/DSDT b/tests/acpi-test-data/q35/DSDT
new file mode 100644
index 0000000..59243b9
Binary files /dev/null and b/tests/acpi-test-data/q35/DSDT differ
diff --git a/tests/acpi-test-data/q35/FACP b/tests/acpi-test-data/q35/FACP
new file mode 100644
index 0000000..19f3ac3
Binary files /dev/null and b/tests/acpi-test-data/q35/FACP differ
diff --git a/tests/acpi-test-data/q35/FACS b/tests/acpi-test-data/q35/FACS
new file mode 100644
index 0000000..fc67ecc
Binary files /dev/null and b/tests/acpi-test-data/q35/FACS differ
diff --git a/tests/acpi-test-data/q35/HPET b/tests/acpi-test-data/q35/HPET
new file mode 100644
index 0000000..df689b8
Binary files /dev/null and b/tests/acpi-test-data/q35/HPET differ
diff --git a/tests/acpi-test-data/q35/MCFG b/tests/acpi-test-data/q35/MCFG
new file mode 100644
index 0000000..79ceb27
Binary files /dev/null and b/tests/acpi-test-data/q35/MCFG differ
diff --git a/tests/acpi-test-data/q35/SSDT b/tests/acpi-test-data/q35/SSDT
new file mode 100644
index 0000000..186e748
Binary files /dev/null and b/tests/acpi-test-data/q35/SSDT differ
commit 4dd72e04c2c4759782d0eb3e3aff6a36889c1e18
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Dec 22 15:51:22 2013 +0100

    virtio: Fix return value for dummy function vhost_net_virtqueue_pending
    
    cgcc complains that -ENOSYS is not a good value for 'bool'.
    
    A dummy virtio will never have pending queue entries, so let us return
    false.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 006576d..854997d 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -321,7 +321,7 @@ void vhost_net_ack_features(struct vhost_net *net, unsigned features)
 
 bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
 {
-    return -ENOSYS;
+    return false;
 }
 
 void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
commit 8977557ae418f9b9ff5c35ee39161a33f2368e6a
Author: Gabriel L. Somlo <gsomlo at gmail.com>
Date:   Mon Jan 13 15:27:13 2014 -0500

    ACPI: Fix AppleSMC _STA size
    
    Minimize the storage used for AppleSMC's _STA (8bit), relying on ASL
    to implicitly convert it to the officially specified 32bit value.
    
    Signed-off-by: Gabriel Somlo <somlo at cmu.edu>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 30bfcd2..1d62866 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -81,7 +81,7 @@ typedef struct AcpiMiscInfo {
 
 static void acpi_get_dsdt(AcpiMiscInfo *info)
 {
-    unsigned short applesmc_sta_val, *applesmc_sta_off;
+    uint16_t *applesmc_sta;
     Object *piix = piix4_pm_find();
     Object *lpc = ich9_lpc_find();
     assert(!!piix != !!lpc);
@@ -89,18 +89,17 @@ static void acpi_get_dsdt(AcpiMiscInfo *info)
     if (piix) {
         info->dsdt_code = AcpiDsdtAmlCode;
         info->dsdt_size = sizeof AcpiDsdtAmlCode;
-        applesmc_sta_off = piix_dsdt_applesmc_sta;
+        applesmc_sta = piix_dsdt_applesmc_sta;
     }
     if (lpc) {
         info->dsdt_code = Q35AcpiDsdtAmlCode;
         info->dsdt_size = sizeof Q35AcpiDsdtAmlCode;
-        applesmc_sta_off = q35_dsdt_applesmc_sta;
+        applesmc_sta = q35_dsdt_applesmc_sta;
     }
 
     /* Patch in appropriate value for AppleSMC _STA */
-    applesmc_sta_val = applesmc_find() ? 0x0b : 0x00;
-    *(uint16_t *)(info->dsdt_code + *applesmc_sta_off) =
-        cpu_to_le16(applesmc_sta_val);
+    *(uint8_t *)(info->dsdt_code + *applesmc_sta) =
+        applesmc_find() ? 0x0b : 0x00;
 }
 
 static
diff --git a/hw/i386/acpi-dsdt-isa.dsl b/hw/i386/acpi-dsdt-isa.dsl
index 46942c1..deb37de 100644
--- a/hw/i386/acpi-dsdt-isa.dsl
+++ b/hw/i386/acpi-dsdt-isa.dsl
@@ -19,8 +19,8 @@ Scope(\_SB.PCI0.ISA) {
     Device (SMC) {
         Name(_HID, EisaId("APP0001"))
         /* _STA will be patched to 0x0B if AppleSMC is present */
-        ACPI_EXTRACT_NAME_WORD_CONST DSDT_APPLESMC_STA
-        Name(_STA, 0xFF00)
+        ACPI_EXTRACT_NAME_BYTE_CONST DSDT_APPLESMC_STA
+        Name(_STA, 0xF0)
         Name(_CRS, ResourceTemplate () {
             IO (Decode16, 0x0300, 0x0300, 0x01, 0x20)
             IRQNoFlags() { 6 }
commit 15bce1b7c55c69f47e13c9eb2a4b80f41da26581
Author: Gabriel L. Somlo <gsomlo at gmail.com>
Date:   Sun Dec 22 10:34:56 2013 -0500

    Add DSDT node for AppleSMC
    
    AppleSMC (-device isa-applesmc) is required to boot OS X guests.
    OS X expects a SMC node to be present in the ACPI DSDT. This patch
    adds a SMC node to the DSDT, and dynamically patches the return value
    of SMC._STA to either 0x0B if the chip is present, or otherwise to 0x00,
    before booting the guest.
    
    Signed-off-by: Gabriel Somlo <somlo at cmu.edu>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 48312f5..30bfcd2 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -36,6 +36,7 @@
 #include "hw/nvram/fw_cfg.h"
 #include "bios-linker-loader.h"
 #include "hw/loader.h"
+#include "hw/isa/isa.h"
 
 /* Supported chipsets: */
 #include "hw/acpi/piix4.h"
@@ -80,6 +81,7 @@ typedef struct AcpiMiscInfo {
 
 static void acpi_get_dsdt(AcpiMiscInfo *info)
 {
+    unsigned short applesmc_sta_val, *applesmc_sta_off;
     Object *piix = piix4_pm_find();
     Object *lpc = ich9_lpc_find();
     assert(!!piix != !!lpc);
@@ -87,11 +89,18 @@ static void acpi_get_dsdt(AcpiMiscInfo *info)
     if (piix) {
         info->dsdt_code = AcpiDsdtAmlCode;
         info->dsdt_size = sizeof AcpiDsdtAmlCode;
+        applesmc_sta_off = piix_dsdt_applesmc_sta;
     }
     if (lpc) {
         info->dsdt_code = Q35AcpiDsdtAmlCode;
         info->dsdt_size = sizeof Q35AcpiDsdtAmlCode;
+        applesmc_sta_off = q35_dsdt_applesmc_sta;
     }
+
+    /* Patch in appropriate value for AppleSMC _STA */
+    applesmc_sta_val = applesmc_find() ? 0x0b : 0x00;
+    *(uint16_t *)(info->dsdt_code + *applesmc_sta_off) =
+        cpu_to_le16(applesmc_sta_val);
 }
 
 static
diff --git a/hw/i386/acpi-dsdt-isa.dsl b/hw/i386/acpi-dsdt-isa.dsl
index 89caa16..46942c1 100644
--- a/hw/i386/acpi-dsdt-isa.dsl
+++ b/hw/i386/acpi-dsdt-isa.dsl
@@ -16,6 +16,17 @@
 /* Common legacy ISA style devices. */
 Scope(\_SB.PCI0.ISA) {
 
+    Device (SMC) {
+        Name(_HID, EisaId("APP0001"))
+        /* _STA will be patched to 0x0B if AppleSMC is present */
+        ACPI_EXTRACT_NAME_WORD_CONST DSDT_APPLESMC_STA
+        Name(_STA, 0xFF00)
+        Name(_CRS, ResourceTemplate () {
+            IO (Decode16, 0x0300, 0x0300, 0x01, 0x20)
+            IRQNoFlags() { 6 }
+        })
+    }
+
     Device(RTC) {
         Name(_HID, EisaId("PNP0B00"))
         Name(_CRS, ResourceTemplate() {
diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
index a377424..b87c6e0 100644
--- a/hw/i386/acpi-dsdt.dsl
+++ b/hw/i386/acpi-dsdt.dsl
@@ -114,6 +114,7 @@ DefinitionBlock (
         }
     }
 
+#define DSDT_APPLESMC_STA piix_dsdt_applesmc_sta
 #include "acpi-dsdt-isa.dsl"
 
 
diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
index 7934a9d..ee38fd6 100644
--- a/hw/i386/q35-acpi-dsdt.dsl
+++ b/hw/i386/q35-acpi-dsdt.dsl
@@ -171,6 +171,7 @@ DefinitionBlock (
         }
     }
 
+#define DSDT_APPLESMC_STA q35_dsdt_applesmc_sta
 #include "acpi-dsdt-isa.dsl"
 
 
diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c
index 1e8d183..627adb9 100644
--- a/hw/misc/applesmc.c
+++ b/hw/misc/applesmc.c
@@ -66,7 +66,6 @@ struct AppleSMCData {
     QLIST_ENTRY(AppleSMCData) node;
 };
 
-#define TYPE_APPLE_SMC "isa-applesmc"
 #define APPLE_SMC(obj) OBJECT_CHECK(AppleSMCState, (obj), TYPE_APPLE_SMC)
 
 typedef struct AppleSMCState AppleSMCState;
diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h
index fa45a5b..e0c749f 100644
--- a/include/hw/isa/isa.h
+++ b/include/hw/isa/isa.h
@@ -20,6 +20,13 @@
 #define TYPE_ISA_BUS "ISA"
 #define ISA_BUS(obj) OBJECT_CHECK(ISABus, (obj), TYPE_ISA_BUS)
 
+#define TYPE_APPLE_SMC "isa-applesmc"
+
+static inline bool applesmc_find(void)
+{
+    return object_resolve_path_type("", TYPE_APPLE_SMC, NULL);
+}
+
 typedef struct ISADeviceClass {
     DeviceClass parent_class;
 } ISADeviceClass;
commit 3e16d14fd93ca6059134ba6b4f65c1c3e4cd3a18
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Tue Dec 17 01:37:06 2013 +0100

    Python-lang gdb script to extract x86_64 guest vmcore from qemu coredump
    
    When qemu dies unexpectedly, for example in response to an explicit
    abort() call, or (more importantly) when an external signal is delivered
    to it that results in a coredump, sometimes it is useful to extract the
    guest vmcore from the qemu process' memory image. The guest vmcore might
    help understand an emulation problem in qemu, or help debug the guest.
    
    This script reimplements (and cuts many features of) the
    qmp_dump_guest_memory() command in gdb/Python,
    
      https://sourceware.org/gdb/current/onlinedocs/gdb/Python-API.html
    
    working off the saved memory image of the qemu process. The docstring in
    the patch (serving as gdb help text) describes the limitations relative to
    the QMP command.
    
    Dependencies of qmp_dump_guest_memory() have been reimplemented as needed.
    I sought to follow the general structure, sticking to original function
    names where possible. However, keeping it simple prevailed in some places.
    
    The patch has been tested with a 4 VCPU, 768 MB, RHEL-6.4
    (2.6.32-358.el6.x86_64) guest:
    
    - The script printed
    
    > guest RAM blocks:
    > target_start     target_end       host_addr        message count
    > ---------------- ---------------- ---------------- ------- -----
    > 0000000000000000 00000000000a0000 00007f95d0000000 added       1
    > 00000000000a0000 00000000000b0000 00007f960ac00000 added       2
    > 00000000000c0000 00000000000ca000 00007f95d00c0000 added       3
    > 00000000000ca000 00000000000cd000 00007f95d00ca000 joined      3
    > 00000000000cd000 00000000000d0000 00007f95d00cd000 joined      3
    > 00000000000d0000 00000000000f0000 00007f95d00d0000 joined      3
    > 00000000000f0000 0000000000100000 00007f95d00f0000 joined      3
    > 0000000000100000 0000000030000000 00007f95d0100000 joined      3
    > 00000000fc000000 00000000fc800000 00007f960ac00000 added       4
    > 00000000fffe0000 0000000100000000 00007f9618800000 added       5
    > dumping range at 00007f95d0000000 for length 00000000000a0000
    > dumping range at 00007f960ac00000 for length 0000000000010000
    > dumping range at 00007f95d00c0000 for length 000000002ff40000
    > dumping range at 00007f960ac00000 for length 0000000000800000
    > dumping range at 00007f9618800000 for length 0000000000020000
    
    - The vmcore was checked with "readelf", comparing the results against a
      vmcore written by qmp_dump_guest_memory():
    
    > --- theirs      2013-09-12 17:38:59.797289404 +0200
    > +++ mine        2013-09-12 17:39:03.820289404 +0200
    > @@ -27,16 +27,16 @@
    >    Type           Offset             VirtAddr           PhysAddr
    >                   FileSiz            MemSiz              Flags  Align
    >    NOTE           0x0000000000000190 0x0000000000000000 0x0000000000000000
    > -                 0x0000000000000ca0 0x0000000000000ca0         0
    > -  LOAD           0x0000000000000e30 0x0000000000000000 0x0000000000000000
    > +                 0x000000000000001c 0x000000000000001c         0
    > +  LOAD           0x00000000000001ac 0x0000000000000000 0x0000000000000000
    >                   0x00000000000a0000 0x00000000000a0000         0
    > -  LOAD           0x00000000000a0e30 0x0000000000000000 0x00000000000a0000
    > +  LOAD           0x00000000000a01ac 0x0000000000000000 0x00000000000a0000
    >                   0x0000000000010000 0x0000000000010000         0
    > -  LOAD           0x00000000000b0e30 0x0000000000000000 0x00000000000c0000
    > +  LOAD           0x00000000000b01ac 0x0000000000000000 0x00000000000c0000
    >                   0x000000002ff40000 0x000000002ff40000         0
    > -  LOAD           0x000000002fff0e30 0x0000000000000000 0x00000000fc000000
    > +  LOAD           0x000000002fff01ac 0x0000000000000000 0x00000000fc000000
    >                   0x0000000000800000 0x0000000000800000         0
    > -  LOAD           0x00000000307f0e30 0x0000000000000000 0x00000000fffe0000
    > +  LOAD           0x00000000307f01ac 0x0000000000000000 0x00000000fffe0000
    >                   0x0000000000020000 0x0000000000020000         0
    >
    >  There is no dynamic section in this file.
    > @@ -47,13 +47,6 @@
    >
    >  No version information found in this file.
    >
    > -Notes at offset 0x00000190 with length 0x00000ca0:
    > +Notes at offset 0x00000190 with length 0x0000001c:
    >    Owner                Data size       Description
    > -  CORE         0x00000150      NT_PRSTATUS (prstatus structure)
    > -  CORE         0x00000150      NT_PRSTATUS (prstatus structure)
    > -  CORE         0x00000150      NT_PRSTATUS (prstatus structure)
    > -  CORE         0x00000150      NT_PRSTATUS (prstatus structure)
    > -  QEMU         0x000001b0      Unknown note type: (0x00000000)
    > -  QEMU         0x000001b0      Unknown note type: (0x00000000)
    > -  QEMU         0x000001b0      Unknown note type: (0x00000000)
    > -  QEMU         0x000001b0      Unknown note type: (0x00000000)
    > +  NONE         0x00000005      Unknown note type: (0x00000000)
    
    - The vmcore was checked with "crash" too, again comparing the results
      against a vmcore written by qmp_dump_guest_memory():
    
    > --- guest.vmcore.log2   2013-09-12 17:52:27.074289201 +0200
    > +++ example.dump.log2   2013-09-12 17:52:15.904289203 +0200
    > @@ -22,11 +22,11 @@
    >  This GDB was configured as "x86_64-unknown-linux-gnu"...
    >
    >       KERNEL: /usr/lib/debug/lib/modules/2.6.32-358.el6.x86_64/vmlinux
    > -    DUMPFILE: /home/lacos/tmp/guest.vmcore
    > +    DUMPFILE: /home/lacos/tmp/example.dump
    >          CPUS: 4
    > -        DATE: Thu Sep 12 17:16:11 2013
    > -      UPTIME: 00:01:09
    > -LOAD AVERAGE: 0.07, 0.03, 0.00
    > +        DATE: Thu Sep 12 17:17:41 2013
    > +      UPTIME: 00:00:38
    > +LOAD AVERAGE: 0.18, 0.05, 0.01
    >         TASKS: 130
    >      NODENAME: localhost.localdomain
    >       RELEASE: 2.6.32-358.el6.x86_64
    > @@ -38,12 +38,12 @@
    >       COMMAND: "swapper"
    >          TASK: ffffffff81a8d020  (1 of 4)  [THREAD_INFO: ffffffff81a00000]
    >           CPU: 0
    > -       STATE: TASK_RUNNING (PANIC)
    > +       STATE: TASK_RUNNING (ACTIVE)
    > +     WARNING: panic task not found
    >
    >  crash> bt
    >  PID: 0      TASK: ffffffff81a8d020  CPU: 0   COMMAND: "swapper"
    > - #0 [ffffffff81a01ed0] default_idle at ffffffff8101495d
    > - #1 [ffffffff81a01ef0] cpu_idle at ffffffff81009fc6
    > + #0 [ffffffff81a01ef0] cpu_idle at ffffffff81009fc6
    >  crash> task ffffffff81a8d020
    >  PID: 0      TASK: ffffffff81a8d020  CPU: 0   COMMAND: "swapper"
    >  struct task_struct {
    > @@ -75,7 +75,7 @@
    >        prev = 0xffffffff81a8d080
    >      },
    >      on_rq = 0,
    > -    exec_start = 8618466836,
    > +    exec_start = 7469214014,
    >      sum_exec_runtime = 0,
    >      vruntime = 0,
    >      prev_sum_exec_runtime = 0,
    > @@ -149,7 +149,7 @@
    >    },
    >    tasks = {
    >      next = 0xffff88002d621948,
    > -    prev = 0xffff880029618f28
    > +    prev = 0xffff880023b74488
    >    },
    >    pushable_tasks = {
    >      prio = 140,
    > @@ -165,7 +165,7 @@
    >      }
    >    },
    >    mm = 0x0,
    > -  active_mm = 0xffff88002929b780,
    > +  active_mm = 0xffff8800297eb980,
    >    exit_state = 0,
    >    exit_code = 0,
    >    exit_signal = 0,
    > @@ -177,7 +177,7 @@
    >    sched_reset_on_fork = 0,
    >    pid = 0,
    >    tgid = 0,
    > -  stack_canary = 2483693585637059287,
    > +  stack_canary = 7266362296181431986,
    >    real_parent = 0xffffffff81a8d020,
    >    parent = 0xffffffff81a8d020,
    >    children = {
    > @@ -224,14 +224,14 @@
    >    set_child_tid = 0x0,
    >    clear_child_tid = 0x0,
    >    utime = 0,
    > -  stime = 3,
    > +  stime = 2,
    >    utimescaled = 0,
    > -  stimescaled = 3,
    > +  stimescaled = 2,
    >    gtime = 0,
    >    prev_utime = 0,
    >    prev_stime = 0,
    >    nvcsw = 0,
    > -  nivcsw = 1000,
    > +  nivcsw = 1764,
    >    start_time = {
    >      tv_sec = 0,
    >      tv_nsec = 0
    
    - <name_dropping>I asked for Dave Anderson's help with verifying the
      extracted vmcore, and his comments make me think I should post
      this.</name_dropping>
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/scripts/dump-guest-memory.py b/scripts/dump-guest-memory.py
new file mode 100644
index 0000000..1ed8b67
--- /dev/null
+++ b/scripts/dump-guest-memory.py
@@ -0,0 +1,339 @@
+# This python script adds a new gdb command, "dump-guest-memory". It
+# should be loaded with "source dump-guest-memory.py" at the (gdb)
+# prompt.
+#
+# Copyright (C) 2013, Red Hat, Inc.
+#
+# Authors:
+#   Laszlo Ersek <lersek at redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later. See
+# the COPYING file in the top-level directory.
+#
+# The leading docstring doesn't have idiomatic Python formatting. It is
+# printed by gdb's "help" command (the first line is printed in the
+# "help data" summary), and it should match how other help texts look in
+# gdb.
+
+import struct
+
+class DumpGuestMemory(gdb.Command):
+    """Extract guest vmcore from qemu process coredump.
+
+The sole argument is FILE, identifying the target file to write the
+guest vmcore to.
+
+This GDB command reimplements the dump-guest-memory QMP command in
+python, using the representation of guest memory as captured in the qemu
+coredump. The qemu process that has been dumped must have had the
+command line option "-machine dump-guest-core=on".
+
+For simplicity, the "paging", "begin" and "end" parameters of the QMP
+command are not supported -- no attempt is made to get the guest's
+internal paging structures (ie. paging=false is hard-wired), and guest
+memory is always fully dumped.
+
+Only x86_64 guests are supported.
+
+The CORE/NT_PRSTATUS and QEMU notes (that is, the VCPUs' statuses) are
+not written to the vmcore. Preparing these would require context that is
+only present in the KVM host kernel module when the guest is alive. A
+fake ELF note is written instead, only to keep the ELF parser of "crash"
+happy.
+
+Dependent on how busted the qemu process was at the time of the
+coredump, this command might produce unpredictable results. If qemu
+deliberately called abort(), or it was dumped in response to a signal at
+a halfway fortunate point, then its coredump should be in reasonable
+shape and this command should mostly work."""
+
+    TARGET_PAGE_SIZE = 0x1000
+    TARGET_PAGE_MASK = 0xFFFFFFFFFFFFF000
+
+    # Various ELF constants
+    EM_X86_64   = 62        # AMD x86-64 target machine
+    ELFDATA2LSB = 1         # little endian
+    ELFCLASS64  = 2
+    ELFMAG      = "\x7FELF"
+    EV_CURRENT  = 1
+    ET_CORE     = 4
+    PT_LOAD     = 1
+    PT_NOTE     = 4
+
+    # Special value for e_phnum. This indicates that the real number of
+    # program headers is too large to fit into e_phnum. Instead the real
+    # value is in the field sh_info of section 0.
+    PN_XNUM = 0xFFFF
+
+    # Format strings for packing and header size calculation.
+    ELF64_EHDR = ("4s" # e_ident/magic
+                  "B"  # e_ident/class
+                  "B"  # e_ident/data
+                  "B"  # e_ident/version
+                  "B"  # e_ident/osabi
+                  "8s" # e_ident/pad
+                  "H"  # e_type
+                  "H"  # e_machine
+                  "I"  # e_version
+                  "Q"  # e_entry
+                  "Q"  # e_phoff
+                  "Q"  # e_shoff
+                  "I"  # e_flags
+                  "H"  # e_ehsize
+                  "H"  # e_phentsize
+                  "H"  # e_phnum
+                  "H"  # e_shentsize
+                  "H"  # e_shnum
+                  "H"  # e_shstrndx
+                 )
+    ELF64_PHDR = ("I"  # p_type
+                  "I"  # p_flags
+                  "Q"  # p_offset
+                  "Q"  # p_vaddr
+                  "Q"  # p_paddr
+                  "Q"  # p_filesz
+                  "Q"  # p_memsz
+                  "Q"  # p_align
+                 )
+
+    def __init__(self):
+        super(DumpGuestMemory, self).__init__("dump-guest-memory",
+                                              gdb.COMMAND_DATA,
+                                              gdb.COMPLETE_FILENAME)
+        self.uintptr_t     = gdb.lookup_type("uintptr_t")
+        self.elf64_ehdr_le = struct.Struct("<%s" % self.ELF64_EHDR)
+        self.elf64_phdr_le = struct.Struct("<%s" % self.ELF64_PHDR)
+
+    def int128_get64(self, val):
+        assert (val["hi"] == 0)
+        return val["lo"]
+
+    def qtailq_foreach(self, head, field_str):
+        var_p = head["tqh_first"]
+        while (var_p != 0):
+            var = var_p.dereference()
+            yield var
+            var_p = var[field_str]["tqe_next"]
+
+    def qemu_get_ram_block(self, ram_addr):
+        ram_blocks = gdb.parse_and_eval("ram_list.blocks")
+        for block in self.qtailq_foreach(ram_blocks, "next"):
+            if (ram_addr - block["offset"] < block["length"]):
+                return block
+        raise gdb.GdbError("Bad ram offset %x" % ram_addr)
+
+    def qemu_get_ram_ptr(self, ram_addr):
+        block = self.qemu_get_ram_block(ram_addr)
+        return block["host"] + (ram_addr - block["offset"])
+
+    def memory_region_get_ram_ptr(self, mr):
+        if (mr["alias"] != 0):
+            return (self.memory_region_get_ram_ptr(mr["alias"].dereference()) +
+                    mr["alias_offset"])
+        return self.qemu_get_ram_ptr(mr["ram_addr"] & self.TARGET_PAGE_MASK)
+
+    def guest_phys_blocks_init(self):
+        self.guest_phys_blocks = []
+
+    def guest_phys_blocks_append(self):
+        print "guest RAM blocks:"
+        print ("target_start     target_end       host_addr        message "
+               "count")
+        print ("---------------- ---------------- ---------------- ------- "
+               "-----")
+
+        current_map_p = gdb.parse_and_eval("address_space_memory.current_map")
+        current_map = current_map_p.dereference()
+        for cur in range(current_map["nr"]):
+            flat_range   = (current_map["ranges"] + cur).dereference()
+            mr           = flat_range["mr"].dereference()
+
+            # we only care about RAM
+            if (not mr["ram"]):
+                continue
+
+            section_size = self.int128_get64(flat_range["addr"]["size"])
+            target_start = self.int128_get64(flat_range["addr"]["start"])
+            target_end   = target_start + section_size
+            host_addr    = (self.memory_region_get_ram_ptr(mr) +
+                            flat_range["offset_in_region"])
+            predecessor = None
+
+            # find continuity in guest physical address space
+            if (len(self.guest_phys_blocks) > 0):
+                predecessor = self.guest_phys_blocks[-1]
+                predecessor_size = (predecessor["target_end"] -
+                                    predecessor["target_start"])
+
+                # the memory API guarantees monotonically increasing
+                # traversal
+                assert (predecessor["target_end"] <= target_start)
+
+                # we want continuity in both guest-physical and
+                # host-virtual memory
+                if (predecessor["target_end"] < target_start or
+                    predecessor["host_addr"] + predecessor_size != host_addr):
+                    predecessor = None
+
+            if (predecessor is None):
+                # isolated mapping, add it to the list
+                self.guest_phys_blocks.append({"target_start": target_start,
+                                               "target_end"  : target_end,
+                                               "host_addr"   : host_addr})
+                message = "added"
+            else:
+                # expand predecessor until @target_end; predecessor's
+                # start doesn't change
+                predecessor["target_end"] = target_end
+                message = "joined"
+
+            print ("%016x %016x %016x %-7s %5u" %
+                   (target_start, target_end, host_addr.cast(self.uintptr_t),
+                    message, len(self.guest_phys_blocks)))
+
+    def cpu_get_dump_info(self):
+        # We can't synchronize the registers with KVM post-mortem, and
+        # the bits in (first_x86_cpu->env.hflags) seem to be stale; they
+        # may not reflect long mode for example. Hence just assume the
+        # most common values. This also means that instruction pointer
+        # etc. will be bogus in the dump, but at least the RAM contents
+        # should be valid.
+        self.dump_info = {"d_machine": self.EM_X86_64,
+                          "d_endian" : self.ELFDATA2LSB,
+                          "d_class"  : self.ELFCLASS64}
+
+    def encode_elf64_ehdr_le(self):
+        return self.elf64_ehdr_le.pack(
+                                 self.ELFMAG,                 # e_ident/magic
+                                 self.dump_info["d_class"],   # e_ident/class
+                                 self.dump_info["d_endian"],  # e_ident/data
+                                 self.EV_CURRENT,             # e_ident/version
+                                 0,                           # e_ident/osabi
+                                 "",                          # e_ident/pad
+                                 self.ET_CORE,                # e_type
+                                 self.dump_info["d_machine"], # e_machine
+                                 self.EV_CURRENT,             # e_version
+                                 0,                           # e_entry
+                                 self.elf64_ehdr_le.size,     # e_phoff
+                                 0,                           # e_shoff
+                                 0,                           # e_flags
+                                 self.elf64_ehdr_le.size,     # e_ehsize
+                                 self.elf64_phdr_le.size,     # e_phentsize
+                                 self.phdr_num,               # e_phnum
+                                 0,                           # e_shentsize
+                                 0,                           # e_shnum
+                                 0                            # e_shstrndx
+                                )
+
+    def encode_elf64_note_le(self):
+        return self.elf64_phdr_le.pack(self.PT_NOTE,         # p_type
+                                       0,                    # p_flags
+                                       (self.memory_offset -
+                                        len(self.note)),     # p_offset
+                                       0,                    # p_vaddr
+                                       0,                    # p_paddr
+                                       len(self.note),       # p_filesz
+                                       len(self.note),       # p_memsz
+                                       0                     # p_align
+                                      )
+
+    def encode_elf64_load_le(self, offset, start_hwaddr, range_size):
+        return self.elf64_phdr_le.pack(self.PT_LOAD, # p_type
+                                       0,            # p_flags
+                                       offset,       # p_offset
+                                       0,            # p_vaddr
+                                       start_hwaddr, # p_paddr
+                                       range_size,   # p_filesz
+                                       range_size,   # p_memsz
+                                       0             # p_align
+                                      )
+
+    def note_init(self, name, desc, type):
+        # name must include a trailing NUL
+        namesz = (len(name) + 1 + 3) / 4 * 4
+        descsz = (len(desc)     + 3) / 4 * 4
+        fmt = ("<"   # little endian
+               "I"   # n_namesz
+               "I"   # n_descsz
+               "I"   # n_type
+               "%us" # name
+               "%us" # desc
+               % (namesz, descsz))
+        self.note = struct.pack(fmt,
+                                len(name) + 1, len(desc), type, name, desc)
+
+    def dump_init(self):
+        self.guest_phys_blocks_init()
+        self.guest_phys_blocks_append()
+        self.cpu_get_dump_info()
+        # we have no way to retrieve the VCPU status from KVM
+        # post-mortem
+        self.note_init("NONE", "EMPTY", 0)
+
+        # Account for PT_NOTE.
+        self.phdr_num = 1
+
+        # We should never reach PN_XNUM for paging=false dumps: there's
+        # just a handful of discontiguous ranges after merging.
+        self.phdr_num += len(self.guest_phys_blocks)
+        assert (self.phdr_num < self.PN_XNUM)
+
+        # Calculate the ELF file offset where the memory dump commences:
+        #
+        #   ELF header
+        #   PT_NOTE
+        #   PT_LOAD: 1
+        #   PT_LOAD: 2
+        #   ...
+        #   PT_LOAD: len(self.guest_phys_blocks)
+        #   ELF note
+        #   memory dump
+        self.memory_offset = (self.elf64_ehdr_le.size +
+                              self.elf64_phdr_le.size * self.phdr_num +
+                              len(self.note))
+
+    def dump_begin(self, vmcore):
+        vmcore.write(self.encode_elf64_ehdr_le())
+        vmcore.write(self.encode_elf64_note_le())
+        running = self.memory_offset
+        for block in self.guest_phys_blocks:
+            range_size = block["target_end"] - block["target_start"]
+            vmcore.write(self.encode_elf64_load_le(running,
+                                                   block["target_start"],
+                                                   range_size))
+            running += range_size
+        vmcore.write(self.note)
+
+    def dump_iterate(self, vmcore):
+        qemu_core = gdb.inferiors()[0]
+        for block in self.guest_phys_blocks:
+            cur  = block["host_addr"]
+            left = block["target_end"] - block["target_start"]
+            print ("dumping range at %016x for length %016x" %
+                   (cur.cast(self.uintptr_t), left))
+            while (left > 0):
+                chunk_size = min(self.TARGET_PAGE_SIZE, left)
+                chunk = qemu_core.read_memory(cur, chunk_size)
+                vmcore.write(chunk)
+                cur  += chunk_size
+                left -= chunk_size
+
+    def create_vmcore(self, filename):
+        vmcore = open(filename, "wb")
+        self.dump_begin(vmcore)
+        self.dump_iterate(vmcore)
+        vmcore.close()
+
+    def invoke(self, args, from_tty):
+        # Unwittingly pressing the Enter key after the command should
+        # not dump the same multi-gig coredump to the same file.
+        self.dont_repeat()
+
+        argv = gdb.string_to_argv(args)
+        if (len(argv) != 1):
+            raise gdb.GdbError("usage: dump-guest-memory FILE")
+
+        self.dump_init()
+        self.create_vmcore(argv[0])
+
+DumpGuestMemory()
commit 2d23d5edb5b23849c668dd729e4da7b2c63b163b
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Nov 6 19:56:58 2013 +0100

    tcg/i386: cleanup useless #ifdef
    
    TCG_TARGET_HAS_movcond_i32 is always defined to 1 in tcg-target.h, so
    remove the corresponding #ifdef #endif sequence, left from a previous
    refactoring.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index db0039a..5d4cf93 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -2026,9 +2026,7 @@ static const TCGTargetOpDef x86_op_defs[] = {
     { INDEX_op_setcond_i32, { "q", "r", "ri" } },
 
     { INDEX_op_deposit_i32, { "Q", "0", "Q" } },
-#if TCG_TARGET_HAS_movcond_i32
     { INDEX_op_movcond_i32, { "r", "r", "ri", "r", "0" } },
-#endif
 
     { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
     { INDEX_op_muls2_i32, { "a", "d", "a", "r" } },
commit 085bb5bb64069a16b843fca840f91cdfb3f40fda
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Nov 6 19:51:21 2013 +0100

    tcg/i386: use movbe instruction in qemu_ldst routines
    
    The movbe instruction has been added on some Intel Atom CPUs and on
    recent Intel Haswell CPUs. It allows to load/store a value and at the
    same time bswap it.
    
    This patch detects the avaibility of this instruction and when available
    use it in the qemu load/store routines in replacement of load/store +
    bswap. Note that for 16-bit unsigned loads, movbe + movzw is basically the
    same as movzw + bswap, so the patch doesn't touch this case.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    [RTH: Reduced the number of conditionals using "movop".]
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 7161fe0..db0039a 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -99,18 +99,31 @@ static const int tcg_target_call_oarg_regs[] = {
 # define TCG_REG_L1 TCG_REG_EDX
 #endif
 
+/* The host compiler should supply <cpuid.h> to enable runtime features
+   detection, as we're not going to go so far as our own inline assembly.
+   If not available, default values will be assumed.  */
+#if defined(CONFIG_CPUID_H)
+#include <cpuid.h>
+#endif
+
 /* For 32-bit, we are going to attempt to determine at runtime whether cmov
-   is available.  However, the host compiler must supply <cpuid.h>, as we're
-   not going to go so far as our own inline assembly.  */
+   is available.  */
 #if TCG_TARGET_REG_BITS == 64
 # define have_cmov 1
 #elif defined(CONFIG_CPUID_H)
-#include <cpuid.h>
 static bool have_cmov;
 #else
 # define have_cmov 0
 #endif
 
+/* If bit_MOVBE is defined in cpuid.h (added in GCC version 4.6), we are
+   going to attempt to determine at runtime whether movbe is available.  */
+#if defined(CONFIG_CPUID_H) && defined(bit_MOVBE)
+static bool have_movbe;
+#else
+# define have_movbe 0
+#endif
+
 static uint8_t *tb_ret_addr;
 
 static void patch_reloc(uint8_t *code_ptr, int type,
@@ -280,6 +293,8 @@ static inline int tcg_target_const_match(tcg_target_long val,
 #define OPC_MOVB_EvIz   (0xc6)
 #define OPC_MOVL_EvIz	(0xc7)
 #define OPC_MOVL_Iv     (0xb8)
+#define OPC_MOVBE_GyMy  (0xf0 | P_EXT38)
+#define OPC_MOVBE_MyGy  (0xf1 | P_EXT38)
 #define OPC_MOVSBL	(0xbe | P_EXT)
 #define OPC_MOVSWL	(0xbf | P_EXT)
 #define OPC_MOVSLQ	(0x63 | P_REXW)
@@ -1344,7 +1359,14 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
                                    TCGReg base, intptr_t ofs, int seg,
                                    TCGMemOp memop)
 {
-    const TCGMemOp bswap = memop & MO_BSWAP;
+    const TCGMemOp real_bswap = memop & MO_BSWAP;
+    TCGMemOp bswap = real_bswap;
+    int movop = OPC_MOVL_GvEv;
+
+    if (have_movbe && real_bswap) {
+        bswap = 0;
+        movop = OPC_MOVBE_GyMy;
+    }
 
     switch (memop & MO_SSIZE) {
     case MO_UB:
@@ -1355,14 +1377,19 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
         break;
     case MO_UW:
         tcg_out_modrm_offset(s, OPC_MOVZWL + seg, datalo, base, ofs);
-        if (bswap) {
+        if (real_bswap) {
             tcg_out_rolw_8(s, datalo);
         }
         break;
     case MO_SW:
-        if (bswap) {
-            tcg_out_modrm_offset(s, OPC_MOVZWL + seg, datalo, base, ofs);
-            tcg_out_rolw_8(s, datalo);
+        if (real_bswap) {
+            if (have_movbe) {
+                tcg_out_modrm_offset(s, OPC_MOVBE_GyMy + P_DATA16 + seg,
+                                     datalo, base, ofs);
+            } else {
+                tcg_out_modrm_offset(s, OPC_MOVZWL + seg, datalo, base, ofs);
+                tcg_out_rolw_8(s, datalo);
+            }
             tcg_out_modrm(s, OPC_MOVSWL + P_REXW, datalo, datalo);
         } else {
             tcg_out_modrm_offset(s, OPC_MOVSWL + P_REXW + seg,
@@ -1370,16 +1397,18 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
         }
         break;
     case MO_UL:
-        tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg, datalo, base, ofs);
+        tcg_out_modrm_offset(s, movop + seg, datalo, base, ofs);
         if (bswap) {
             tcg_out_bswap32(s, datalo);
         }
         break;
 #if TCG_TARGET_REG_BITS == 64
     case MO_SL:
-        if (bswap) {
-            tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg, datalo, base, ofs);
-            tcg_out_bswap32(s, datalo);
+        if (real_bswap) {
+            tcg_out_modrm_offset(s, movop + seg, datalo, base, ofs);
+            if (bswap) {
+                tcg_out_bswap32(s, datalo);
+            }
             tcg_out_ext32s(s, datalo, datalo);
         } else {
             tcg_out_modrm_offset(s, OPC_MOVSLQ + seg, datalo, base, ofs);
@@ -1388,27 +1417,22 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
 #endif
     case MO_Q:
         if (TCG_TARGET_REG_BITS == 64) {
-            tcg_out_modrm_offset(s, OPC_MOVL_GvEv + P_REXW + seg,
-                                 datalo, base, ofs);
+            tcg_out_modrm_offset(s, movop + P_REXW + seg, datalo, base, ofs);
             if (bswap) {
                 tcg_out_bswap64(s, datalo);
             }
         } else {
-            if (bswap) {
+            if (real_bswap) {
                 int t = datalo;
                 datalo = datahi;
                 datahi = t;
             }
             if (base != datalo) {
-                tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg,
-                                     datalo, base, ofs);
-                tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg,
-                                     datahi, base, ofs + 4);
+                tcg_out_modrm_offset(s, movop + seg, datalo, base, ofs);
+                tcg_out_modrm_offset(s, movop + seg, datahi, base, ofs + 4);
             } else {
-                tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg,
-                                     datahi, base, ofs + 4);
-                tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg,
-                                     datalo, base, ofs);
+                tcg_out_modrm_offset(s, movop + seg, datahi, base, ofs + 4);
+                tcg_out_modrm_offset(s, movop + seg, datalo, base, ofs);
             }
             if (bswap) {
                 tcg_out_bswap32(s, datalo);
@@ -1484,13 +1508,19 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
                                    TCGReg base, intptr_t ofs, int seg,
                                    TCGMemOp memop)
 {
-    const TCGMemOp bswap = memop & MO_BSWAP;
-
     /* ??? Ideally we wouldn't need a scratch register.  For user-only,
        we could perform the bswap twice to restore the original value
        instead of moving to the scratch.  But as it is, the L constraint
        means that TCG_REG_L0 is definitely free here.  */
     const TCGReg scratch = TCG_REG_L0;
+    const TCGMemOp real_bswap = memop & MO_BSWAP;
+    TCGMemOp bswap = real_bswap;
+    int movop = OPC_MOVL_EvGv;
+
+    if (have_movbe && real_bswap) {
+        bswap = 0;
+        movop = OPC_MOVBE_MyGy;
+    }
 
     switch (memop & MO_SIZE) {
     case MO_8:
@@ -1509,8 +1539,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
             tcg_out_rolw_8(s, scratch);
             datalo = scratch;
         }
-        tcg_out_modrm_offset(s, OPC_MOVL_EvGv + P_DATA16 + seg,
-                             datalo, base, ofs);
+        tcg_out_modrm_offset(s, movop + P_DATA16 + seg, datalo, base, ofs);
         break;
     case MO_32:
         if (bswap) {
@@ -1518,7 +1547,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
             tcg_out_bswap32(s, scratch);
             datalo = scratch;
         }
-        tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, datalo, base, ofs);
+        tcg_out_modrm_offset(s, movop + seg, datalo, base, ofs);
         break;
     case MO_64:
         if (TCG_TARGET_REG_BITS == 64) {
@@ -1527,8 +1556,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
                 tcg_out_bswap64(s, scratch);
                 datalo = scratch;
             }
-            tcg_out_modrm_offset(s, OPC_MOVL_EvGv + P_REXW + seg,
-                                 datalo, base, ofs);
+            tcg_out_modrm_offset(s, movop + P_REXW + seg, datalo, base, ofs);
         } else if (bswap) {
             tcg_out_mov(s, TCG_TYPE_I32, scratch, datahi);
             tcg_out_bswap32(s, scratch);
@@ -1537,8 +1565,13 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
             tcg_out_bswap32(s, scratch);
             tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, scratch, base, ofs+4);
         } else {
-            tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, datalo, base, ofs);
-            tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, datahi, base, ofs+4);
+            if (real_bswap) {
+                int t = datalo;
+                datalo = datahi;
+                datahi = t;
+            }
+            tcg_out_modrm_offset(s, movop + seg, datalo, base, ofs);
+            tcg_out_modrm_offset(s, movop + seg, datahi, base, ofs+4);
         }
         break;
     default:
@@ -2165,13 +2198,23 @@ static void tcg_target_qemu_prologue(TCGContext *s)
 
 static void tcg_target_init(TCGContext *s)
 {
-    /* For 32-bit, 99% certainty that we're running on hardware that supports
-       cmov, but we still need to check.  In case cmov is not available, we'll
-       use a small forward branch.  */
-#ifndef have_cmov
+#if !(defined(have_cmov) && defined(have_movbe))
     {
         unsigned a, b, c, d;
-        have_cmov = (__get_cpuid(1, &a, &b, &c, &d) && (d & bit_CMOV));
+        int ret = __get_cpuid(1, &a, &b, &c, &d);
+
+# ifndef have_cmov
+        /* For 32-bit, 99% certainty that we're running on hardware that
+           supports cmov, but we still need to check.  In case cmov is not
+           available, we'll use a small forward branch.  */
+        have_cmov = ret && (d & bit_CMOV);
+# endif
+
+# ifndef have_movbe
+        /* MOVBE is only available on Intel Atom and Haswell CPUs, so we
+           need to probe for it.  */
+        have_movbe = ret && (c & bit_MOVBE);
+# endif
     }
 #endif
 
commit 2a1137753f9618283ac40394a75976d18f608e39
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Nov 6 19:49:08 2013 +0100

    tcg/i386: add support for three-byte opcodes
    
    Add support for three-byte opcodes, starting with the 0x0f 0x38 prefix.
    Use P_EXT38 as the new constant, and shift all other constants so that
    P_EXT and P_EXT38 have neighbouring values.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    [RTH: Changed the name from P_EXT2 to P_EXT38.]
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 753b3a1..7161fe0 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -240,13 +240,14 @@ static inline int tcg_target_const_match(tcg_target_long val,
 #endif
 
 #define P_EXT		0x100		/* 0x0f opcode prefix */
-#define P_DATA16	0x200		/* 0x66 opcode prefix */
+#define P_EXT38         0x200           /* 0x0f 0x38 opcode prefix */
+#define P_DATA16        0x400           /* 0x66 opcode prefix */
 #if TCG_TARGET_REG_BITS == 64
-# define P_ADDR32	0x400		/* 0x67 opcode prefix */
-# define P_REXW		0x800		/* Set REX.W = 1 */
-# define P_REXB_R	0x1000		/* REG field as byte register */
-# define P_REXB_RM	0x2000		/* R/M field as byte register */
-# define P_GS           0x4000          /* gs segment override */
+# define P_ADDR32       0x800           /* 0x67 opcode prefix */
+# define P_REXW         0x1000          /* Set REX.W = 1 */
+# define P_REXB_R       0x2000          /* REG field as byte register */
+# define P_REXB_RM      0x4000          /* R/M field as byte register */
+# define P_GS           0x8000          /* gs segment override */
 #else
 # define P_ADDR32	0
 # define P_REXW		0
@@ -398,9 +399,13 @@ static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
         tcg_out8(s, (uint8_t)(rex | 0x40));
     }
 
-    if (opc & P_EXT) {
+    if (opc & (P_EXT | P_EXT38)) {
         tcg_out8(s, 0x0f);
+        if (opc & P_EXT38) {
+            tcg_out8(s, 0x38);
+        }
     }
+
     tcg_out8(s, opc);
 }
 #else
@@ -409,8 +414,11 @@ static void tcg_out_opc(TCGContext *s, int opc)
     if (opc & P_DATA16) {
         tcg_out8(s, 0x66);
     }
-    if (opc & P_EXT) {
+    if (opc & (P_EXT | P_EXT38)) {
         tcg_out8(s, 0x0f);
+        if (opc & P_EXT38) {
+            tcg_out8(s, 0x38);
+        }
     }
     tcg_out8(s, opc);
 }
commit c9d78213b8bf6e0da9ff30b53c33e93fb0373249
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Nov 6 18:32:23 2013 +0100

    tcg/i386: remove hardcoded P_REXW value
    
    P_REXW is defined has a constant at the beginning of i386/tcg-target.c,
    but the corresponding bit is later used in a harcoded way, which defeat
    the purpose of a constant.
    
    Fix that by using a conditional expression operator instead of a shift.
    On x86 this actually makes the code slightly smaller as GCC does in
    practice (opc >> 8) & 8 instead of (opc & 0x800) >> 8 so the constants
    are smaller to load.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 495b901..753b3a1 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -381,7 +381,7 @@ static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
     }
 
     rex = 0;
-    rex |= (opc & P_REXW) >> 8;		/* REX.W */
+    rex |= (opc & P_REXW) ? 0x8 : 0x0;  /* REX.W */
     rex |= (r & 8) >> 1;		/* REX.R */
     rex |= (x & 8) >> 2;		/* REX.X */
     rex |= (rm & 8) >> 3;		/* REX.B */
commit ba00599cc32626b53ba151c627a763518c76c49f
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Nov 6 18:31:43 2013 +0100

    disas/i386.c: disassemble movbe instruction
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/disas/i386.c b/disas/i386.c
index 47f1f2e..044e02c 100644
--- a/disas/i386.c
+++ b/disas/i386.c
@@ -2632,17 +2632,17 @@ static const struct dis386 prefix_user_table[][4] = {
 
   /* PREGRP87 */
   {
+    { "movbe",	{ Gv, Ev } },
     { "(bad)",	{ XX } },
-    { "(bad)",	{ XX } },
-    { "(bad)",	{ XX } },
+    { "movbe",	{ Gv, Ev } },
     { "crc32",	{ Gdq, { CRC32_Fixup, b_mode } } },
   },
 
   /* PREGRP88 */
   {
+    { "movbe",	{ Ev, Gv } },
     { "(bad)",	{ XX } },
-    { "(bad)",	{ XX } },
-    { "(bad)",	{ XX } },
+    { "movbe",	{ Ev, Gv } },
     { "crc32",	{ Gdq, { CRC32_Fixup, v_mode } } },
   },
 
commit 8d7b5a1da0e06aa7addd7f084d9ec9d433c4bafb
Author: Alexey Kardashevskiy <aik at ozlabs.ru>
Date:   Fri Jan 17 11:12:56 2014 -0700

    vfio: fix mapping of MSIX bar
    
    VFIO virtualizes MSIX table for the guest but not mapping the part of
    a BAR which contains an MSIX table. Since vfio_mmap_bar() mmaps chunks
    before and after the MSIX table, they have to be aligned to the host
    page size which may be TARGET_PAGE_MASK (4K) or 64K in case of PPC64.
    
    This fixes boundaries calculations to use the real host page size.
    
    Without the patch, the chunk before MSIX table may overlap with the MSIX
    table and mmap will fail in the host kernel. The result will be serious
    slowdown as the whole BAR will be emulated by QEMU.
    
    Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index 432547c..8a1f1a1 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -2544,7 +2544,7 @@ static void vfio_map_bar(VFIODevice *vdev, int nr)
      * potentially insert a direct-mapped subregion before and after it.
      */
     if (vdev->msix && vdev->msix->table_bar == nr) {
-        size = vdev->msix->table_offset & TARGET_PAGE_MASK;
+        size = vdev->msix->table_offset & qemu_host_page_mask;
     }
 
     strncat(name, " mmap", sizeof(name) - strlen(name) - 1);
@@ -2556,8 +2556,8 @@ static void vfio_map_bar(VFIODevice *vdev, int nr)
     if (vdev->msix && vdev->msix->table_bar == nr) {
         unsigned start;
 
-        start = TARGET_PAGE_ALIGN(vdev->msix->table_offset +
-                                  (vdev->msix->entries * PCI_MSIX_ENTRY_SIZE));
+        start = HOST_PAGE_ALIGN(vdev->msix->table_offset +
+                                (vdev->msix->entries * PCI_MSIX_ENTRY_SIZE));
 
         size = start < bar->size ? bar->size - start : 0;
         strncat(name, " msix-hi", sizeof(name) - strlen(name) - 1);
commit 47c16ed56aa6bc4037bdb7b61f049097993cd244
Author: Alexey Kardashevskiy <aik at ozlabs.ru>
Date:   Fri Jan 17 11:12:07 2014 -0700

    kvm: initialize qemu_host_page_size
    
    There is a HOST_PAGE_ALIGN macro which makes sense for KVM accelerator
    but it uses qemu_host_page_size/qemu_host_page_mask which initialized
    for TCG only.
    
    This moves qemu_host_page_size/qemu_host_page_mask initialization from
    TCG's page_init() and adds a call for it from kvm_init().
    
    Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index ea90b64..3b03cbf 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -81,6 +81,7 @@ void cpu_gen_init(void);
 int cpu_gen_code(CPUArchState *env, struct TranslationBlock *tb,
                  int *gen_code_size_ptr);
 bool cpu_restore_state(CPUArchState *env, uintptr_t searched_pc);
+void page_size_init(void);
 
 void QEMU_NORETURN cpu_resume_from_signal(CPUArchState *env1, void *puc);
 void QEMU_NORETURN cpu_io_recompile(CPUArchState *env, uintptr_t retaddr);
diff --git a/kvm-all.c b/kvm-all.c
index 0bfb060..edf2365 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1360,6 +1360,7 @@ int kvm_init(void)
      * page size for the system though.
      */
     assert(TARGET_PAGE_SIZE <= getpagesize());
+    page_size_init();
 
 #ifdef KVM_CAP_SET_GUEST_DEBUG
     QTAILQ_INIT(&s->kvm_sw_breakpoints);
diff --git a/translate-all.c b/translate-all.c
index 105c25a..543e1ff 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -289,17 +289,15 @@ static inline void map_exec(void *addr, long size)
 }
 #endif
 
-static void page_init(void)
+void page_size_init(void)
 {
     /* NOTE: we can always suppose that qemu_host_page_size >=
        TARGET_PAGE_SIZE */
 #ifdef _WIN32
-    {
-        SYSTEM_INFO system_info;
+    SYSTEM_INFO system_info;
 
-        GetSystemInfo(&system_info);
-        qemu_real_host_page_size = system_info.dwPageSize;
-    }
+    GetSystemInfo(&system_info);
+    qemu_real_host_page_size = system_info.dwPageSize;
 #else
     qemu_real_host_page_size = getpagesize();
 #endif
@@ -310,7 +308,11 @@ static void page_init(void)
         qemu_host_page_size = TARGET_PAGE_SIZE;
     }
     qemu_host_page_mask = ~(qemu_host_page_size - 1);
+}
 
+static void page_init(void)
+{
+    page_size_init();
 #if defined(CONFIG_BSD) && defined(CONFIG_USER_ONLY)
     {
 #ifdef HAVE_KINFO_GETVMMAP
commit 794798e36eda77802ce7cc7d7d6b1c65751e8a76
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Fri Jan 10 15:56:33 2014 +0000

    xen_pt: Fix passthrough of device with ROM.
    
    QEMU does not need and should not allocate memory for the ROM of a
    passthrough PCI device. So this patch initialize the particular region
    like any other PCI BAR of a passthrough device.
    
    When a guest will access the ROM, Xen will take care of the IO, QEMU
    will not be involved in it.
    
    Xen set a limit of memory available for each guest, allocating memory
    for a ROM can hit this limit.
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Reported-and-Tested-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>

diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
index eee4354..be4220b 100644
--- a/hw/xen/xen_pt.c
+++ b/hw/xen/xen_pt.c
@@ -440,8 +440,8 @@ static int xen_pt_register_regions(XenPCIPassthroughState *s)
 
         s->bases[PCI_ROM_SLOT].access.maddr = d->rom.base_addr;
 
-        memory_region_init_rom_device(&s->rom, OBJECT(s), NULL, NULL,
-                                      "xen-pci-pt-rom", d->rom.size);
+        memory_region_init_io(&s->rom, OBJECT(s), &ops, &s->dev,
+                              "xen-pci-pt-rom", d->rom.size);
         pci_register_bar(&s->dev, PCI_ROM_SLOT, PCI_BASE_ADDRESS_MEM_PREFETCH,
                          &s->rom);
 
commit fc33b9004c49f21f8188df5c4cd079a9a3d08de8
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Fri Jan 10 15:52:54 2014 +0000

    xen_pt: Fix debug output.
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>

diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
index d58cb61..eee4354 100644
--- a/hw/xen/xen_pt.c
+++ b/hw/xen/xen_pt.c
@@ -420,8 +420,8 @@ static int xen_pt_register_regions(XenPCIPassthroughState *s)
                               "xen-pci-pt-bar", r->size);
         pci_register_bar(&s->dev, i, type, &s->bar[i]);
 
-        XEN_PT_LOG(&s->dev, "IO region %i registered (size=0x%lx"PRIx64
-                   " base_addr=0x%lx"PRIx64" type: %#x)\n",
+        XEN_PT_LOG(&s->dev, "IO region %i registered (size=0x%08"PRIx64
+                   " base_addr=0x%08"PRIx64" type: %#x)\n",
                    i, r->size, r->base_addr, type);
     }
 
commit 0193c62c94643a837832f2b5ccc133434ee740cb
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Fri Jan 17 15:28:18 2014 +0000

    xenfb: map framebuffer read-only and handle unmap errors
    
    The framebuffer is needlessly mapped (PROT_READ | PROT_WRITE), map it
    PROT_READ instead.
    
    The framebuffer is unmapped by replacing the framebuffer pages with
    anonymous shared memory, calling mmap. Check for return errors and print
    a warning.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index f0333a0..cb9d456 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -495,7 +495,7 @@ static int xenfb_map_fb(struct XenFB *xenfb)
     munmap(map, n_fbdirs * XC_PAGE_SIZE);
 
     xenfb->pixels = xc_map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
-					 PROT_READ | PROT_WRITE, fbmfns, xenfb->fbpages);
+            PROT_READ, fbmfns, xenfb->fbpages);
     if (xenfb->pixels == NULL)
 	goto out;
 
@@ -903,6 +903,11 @@ static void fb_disconnect(struct XenDevice *xendev)
     fb->pixels = mmap(fb->pixels, fb->fbpages * XC_PAGE_SIZE,
                       PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON,
                       -1, 0);
+    if (fb->pixels == MAP_FAILED) {
+        xen_be_printf(xendev, 0,
+                "Couldn't replace the framebuffer with anonymous memory errno=%d\n",
+                errno);
+    }
     common_unbind(&fb->c);
     fb->feature_update = 0;
     fb->bug_trigger    = 0;
commit 87ca1f77b1c406137fe36ab73b2dc91fb75f8d0a
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Jan 16 09:22:07 2014 -0700

    vfio-pci: Fail initfn on DMA mapping errors
    
    The vfio-pci initfn will currently succeed even if DMA mappings fail.
    A typical reason for failure is if the user does not have sufficient
    privilege to lock all the memory for the guest.  In this case, the
    device gets attached, but can only access a portion of guest memory
    and is extremely unlikely to work.
    
    DMA mappings are done via a MemoryListener, which provides no direct
    error return path.  We therefore stuff the errno into our container
    structure and check for error after registration completes.  We can
    also test for mapping errors during runtime, but our only option for
    resolution at that point is to kill the guest with a hw_error.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index d304213..432547c 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -135,12 +135,18 @@ enum {
 
 struct VFIOGroup;
 
+typedef struct VFIOType1 {
+    MemoryListener listener;
+    int error;
+    bool initialized;
+} VFIOType1;
+
 typedef struct VFIOContainer {
     int fd; /* /dev/vfio/vfio, empowered by the attached groups */
     struct {
         /* enable abstraction to support various iommu backends */
         union {
-            MemoryListener listener; /* Used by type1 iommu */
+            VFIOType1 type1;
         };
         void (*release)(struct VFIOContainer *);
     } iommu_data;
@@ -2170,7 +2176,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
                                      MemoryRegionSection *section)
 {
     VFIOContainer *container = container_of(listener, VFIOContainer,
-                                            iommu_data.listener);
+                                            iommu_data.type1.listener);
     hwaddr iova, end;
     void *vaddr;
     int ret;
@@ -2212,6 +2218,19 @@ static void vfio_listener_region_add(MemoryListener *listener,
         error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", "
                      "0x%"HWADDR_PRIx", %p) = %d (%m)",
                      container, iova, end - iova, vaddr, ret);
+
+        /*
+         * On the initfn path, store the first error in the container so we
+         * can gracefully fail.  Runtime, there's not much we can do other
+         * than throw a hardware error.
+         */
+        if (!container->iommu_data.type1.initialized) {
+            if (!container->iommu_data.type1.error) {
+                container->iommu_data.type1.error = ret;
+            }
+        } else {
+            hw_error("vfio: DMA mapping failed, unable to continue\n");
+        }
     }
 }
 
@@ -2219,7 +2238,7 @@ static void vfio_listener_region_del(MemoryListener *listener,
                                      MemoryRegionSection *section)
 {
     VFIOContainer *container = container_of(listener, VFIOContainer,
-                                            iommu_data.listener);
+                                            iommu_data.type1.listener);
     hwaddr iova, end;
     int ret;
 
@@ -2264,7 +2283,7 @@ static MemoryListener vfio_memory_listener = {
 
 static void vfio_listener_release(VFIOContainer *container)
 {
-    memory_listener_unregister(&container->iommu_data.listener);
+    memory_listener_unregister(&container->iommu_data.type1.listener);
 }
 
 /*
@@ -3236,10 +3255,23 @@ static int vfio_connect_container(VFIOGroup *group)
             return -errno;
         }
 
-        container->iommu_data.listener = vfio_memory_listener;
+        container->iommu_data.type1.listener = vfio_memory_listener;
         container->iommu_data.release = vfio_listener_release;
 
-        memory_listener_register(&container->iommu_data.listener, &address_space_memory);
+        memory_listener_register(&container->iommu_data.type1.listener,
+                                 &address_space_memory);
+
+        if (container->iommu_data.type1.error) {
+            ret = container->iommu_data.type1.error;
+            vfio_listener_release(container);
+            g_free(container);
+            close(fd);
+            error_report("vfio: memory listener initialization failed for container\n");
+            return ret;
+        }
+
+        container->iommu_data.type1.initialized = true;
+
     } else {
         error_report("vfio: No available IOMMU models");
         g_free(container);
commit d3a2fd9b29e43e202315d5e99399b99622469c4a
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Jan 16 09:22:07 2014 -0700

    vfio: Filter out bogus mappings
    
    Since 57271d63 we now see spurious mappings with the upper bits set
    if 64bit PCI BARs are sized while enabled.  The guest writes a mask
    of 0xffffffff to the lower BAR to size it, then restores it, then
    writes the same mask to the upper BAR resulting in a spurious BAR
    mapping into the last 4G of the 64bit address space.  Most
    architectures do not support or make use of the full 64bits address
    space for PCI BARs, so we filter out mappings with the high bit set.
    Long term, we probably need to think about vfio telling us the
    address width limitations of the IOMMU.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index 30b1a78..d304213 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -2156,7 +2156,14 @@ static int vfio_dma_map(VFIOContainer *container, hwaddr iova,
 
 static bool vfio_listener_skipped_section(MemoryRegionSection *section)
 {
-    return !memory_region_is_ram(section->mr);
+    return !memory_region_is_ram(section->mr) ||
+           /*
+            * Sizing an enabled 64-bit BAR can cause spurious mappings to
+            * addresses in the upper part of the 64-bit address space.  These
+            * are never accessed by the CPU and beyond the address width of
+            * some IOMMU hardware.  TODO: VFIO should tell us the IOMMU width.
+            */
+           section->offset_within_address_space & (1ULL << 63);
 }
 
 static void vfio_listener_region_add(MemoryListener *listener,
commit 2c02d1ad48ad44cf00522df7d8de9138689fac85
Author: Kewei Yu <keweihk at gmail.com>
Date:   Tue Dec 31 18:36:08 2013 +0800

    vl: Add a blank space between the variable and '='
    
    Signed-off-by: Kewei Yu <keweihk at gmail.com>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/vl.c b/vl.c
index 7f4fe0d..2b47866 100644
--- a/vl.c
+++ b/vl.c
@@ -2925,7 +2925,7 @@ int main(int argc, char **argv, char **envp)
 
     bdrv_init_with_whitelist();
 
-    autostart= 1;
+    autostart = 1;
 
     /* first pass of option parsing */
     optind = 1;
commit 3babcc8704f593473ccd0f66d6e39c949c672477
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Dec 28 08:31:11 2013 +0100

    pc-bios: Remove execute flag from BIOS files
    
    BIOS files are not directly executable, so they don't need this flag.
    All other BIOS files don't use the execute flag.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/pc-bios/kvmvapic.bin b/pc-bios/kvmvapic.bin
old mode 100755
new mode 100644
diff --git a/pc-bios/multiboot.bin b/pc-bios/multiboot.bin
old mode 100755
new mode 100644
diff --git a/pc-bios/sgabios.bin b/pc-bios/sgabios.bin
old mode 100755
new mode 100644
commit a39ca6a124267dcfc6bc5276fff9c4b02e5c2215
Author: Pavel Zbitskiy <pavel.zbitskiy at gmail.com>
Date:   Sat Jan 11 13:34:11 2014 +0400

    linux-user: fixed recvfrom() addrlen
    
    addrlen parameter of recvfrom() of type socklen_t* was read into
    variable of type socklen_t, that caused zeroing out of upper 4 bytes
    when running s390x on top of x86_64. This patch changes addrlen type
    to abi_ulong.
    
    Signed-off-by: Pavel Zbitskiy <pavel.zbitskiy at gmail.com>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index a9ce6ba..bc0ac98 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2340,7 +2340,7 @@ static abi_long do_socketcall(int num, abi_ulong vptr)
             size_t len;
             abi_ulong flags;
             abi_ulong addr;
-            socklen_t addrlen;
+            abi_ulong addrlen;
 
             if (get_user_ual(sockfd, vptr)
                 || get_user_ual(msg, vptr + n)
commit fe54b24930f94bdfbc3d38eccd7adedf35f2f26f
Author: Pavel Zbitskiy <pavel.zbitskiy at gmail.com>
Date:   Sat Jan 11 13:34:10 2014 +0400

    linux-user: fixed getsockopt() optlen
    
    optlen parameter of getsockopt() of type socklen_t* was read into
    variable of type socklen_t, that caused zeroing out of upper 4 bytes
    when running s390x on top of x86_64. This patch changes optlen type
    to abi_ulong.
    
    Signed-off-by: Pavel Zbitskiy <pavel.zbitskiy at gmail.com>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 0ac05b8..a9ce6ba 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2406,7 +2406,7 @@ static abi_long do_socketcall(int num, abi_ulong vptr)
             abi_ulong level;
             abi_ulong optname;
             abi_ulong optval;
-            socklen_t optlen;
+            abi_ulong optlen;
 
             if (get_user_ual(sockfd, vptr)
                 || get_user_ual(level, vptr + n)
commit 19a894ba777fa45c6f89ae007570311384204a69
Author: Pavel Zbitskiy <pavel.zbitskiy at gmail.com>
Date:   Sat Jan 11 13:34:09 2014 +0400

    linux-user: fixed s390x clone() argument order
    
    It was broken by 4ce6243dc6216e35b5b691078ffa856463bfa8db,
    where TARGET_CLONE_BACKWARDS was specified instead of
    TARGET_CLONE_BACKWARDS2.
    
    Signed-off-by: Pavel Zbitskiy <pavel.zbitskiy at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/linux-user/s390x/syscall.h b/linux-user/s390x/syscall.h
index ea8c304..e5ce30b 100644
--- a/linux-user/s390x/syscall.h
+++ b/linux-user/s390x/syscall.h
@@ -22,4 +22,4 @@ struct target_pt_regs {
 
 #define UNAME_MACHINE "s390x"
 
-#define TARGET_CLONE_BACKWARDS
+#define TARGET_CLONE_BACKWARDS2
commit 850484a295a856474978d9338b8c17eb8e00f549
Author: David du Colombier <0intro at gmail.com>
Date:   Wed Dec 25 15:17:43 2013 +0100

    ide: cmd_exec_dev_diagnostic() always set error register to 0x01
    
    This notably fix IDE CD probing on the Plan 9 operating system,
    which rely on the error register set by the Execute Device
    Diagnostic command to detect drive configurations.
    
    Thanks to Rémi Pommarel for reporting this issue.
    
    Signed-off-by: David du Colombier <0intro at gmail.com>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index e1f4c33..7783d58 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1321,6 +1321,7 @@ static bool cmd_exec_dev_diagnostic(IDEState *s, uint8_t cmd)
         s->status = 0; /* ATAPI spec (v6) section 9.10 defines packet
                         * devices to return a clear status register
                         * with READY_STAT *not* set. */
+        s->error = 0x01;
     } else {
         s->status = READY_STAT | SEEK_STAT;
         /* The bits of the error register are not as usual for this command!
commit e6baf6130ef26f32a45e0282bd4720913a1ff472
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Thu Jan 9 09:58:16 2014 -0500

    virtio-balloon: don't hardcode config size value
    
    Use sizeof(struct virtio_balloon_config) instead.
    
    Signed-off-by: Luiz capitulino <lcapitulino at redhat.com>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index d9754db..a470a0b 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -263,7 +263,7 @@ static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
     config.num_pages = cpu_to_le32(dev->num_pages);
     config.actual = cpu_to_le32(dev->actual);
 
-    memcpy(config_data, &config, 8);
+    memcpy(config_data, &config, sizeof(struct virtio_balloon_config));
 }
 
 static void virtio_balloon_set_config(VirtIODevice *vdev,
@@ -272,7 +272,7 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,
     VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
     struct virtio_balloon_config config;
     uint32_t oldactual = dev->actual;
-    memcpy(&config, config_data, 8);
+    memcpy(&config, config_data, sizeof(struct virtio_balloon_config));
     dev->actual = le32_to_cpu(config.actual);
     if (dev->actual != oldactual) {
         qemu_balloon_changed(ram_size -
@@ -343,7 +343,8 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
     VirtIOBalloon *s = VIRTIO_BALLOON(dev);
     int ret;
 
-    virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON, 8);
+    virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON,
+                sizeof(struct virtio_balloon_config));
 
     ret = qemu_add_balloon_handler(virtio_balloon_to_target,
                                    virtio_balloon_stat, s);
commit fb3ecb7ea40c44d15091143c4336993e7165fc4f
Author: Stefan Weil <sw at weilnetz.de>
Date:   Tue Jan 14 07:00:28 2014 +0100

    exec: Exclude non portable function for MinGW
    
    cpu_physical_memory_set_dirty_lebitmap calls getpageaddr and ffsl which are
    unavailable for MinGW. As the function is unused for MinGW, it can simply
    be excluded from compilation.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index 33c8acc..481a447 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -79,6 +79,7 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
     xen_modified_memory(start, length);
 }
 
+#if !defined(_WIN32)
 static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap,
                                                           ram_addr_t start,
                                                           ram_addr_t pages)
@@ -127,6 +128,7 @@ static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap,
         }
     }
 }
+#endif /* not _WIN32 */
 
 static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start,
                                                          ram_addr_t length,
commit bf2eaf718e2fcc5cc975326495bf03de7305bbe4
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Mon Dec 9 21:33:34 2013 -0200

    Add bios-256k.bin to BLOBS on Makefile
    
    The default machine-type (pc-i440fx-2.0) now requires bios-256k.bin, but
    "make install" isn't installing it, so qemu-system-x86_64 won't run out
    of the box. Add it to BLOBS so it gets installed.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Gerd Hoffmann <kraxel at redhat.com>
    Tested-by: William Dauchy <william at gandi.net>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/Makefile b/Makefile
index bdff4e4..807054b 100644
--- a/Makefile
+++ b/Makefile
@@ -290,7 +290,7 @@ common  de-ch  es     fo  fr-ca  hu     ja  mk  nl-be      pt  sl     tr \
 bepo    cz
 
 ifdef INSTALL_BLOBS
-BLOBS=bios.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \
+BLOBS=bios.bin bios-256k.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \
 vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \
 acpi-dsdt.aml q35-acpi-dsdt.aml \
 ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc QEMU,tcx.bin \
commit dc9fc1cac59e46102f2e046ac3233d8ad4535497
Author: Namhyung Kim <namhyung at gmail.com>
Date:   Tue Jan 7 09:04:25 2014 +0900

    Fix typo of tiemr in timer.h
    
    Signed-off-by: Namhyung Kim <namhyung at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 5afcffc..7f9a074 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -405,7 +405,7 @@ int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg);
  * timer_init:
  * @ts: the timer to be initialised
  * @timer_list: the timer list to attach the timer to
- * @scale: the scale value for the tiemr
+ * @scale: the scale value for the timer
  * @cb: the callback to be called when the timer expires
  * @opaque: the opaque pointer to be passed to the callback
  *
@@ -422,7 +422,7 @@ void timer_init(QEMUTimer *ts,
 /**
  * timer_new_tl:
  * @timer_list: the timer list to attach the timer to
- * @scale: the scale value for the tiemr
+ * @scale: the scale value for the timer
  * @cb: the callback to be called when the timer expires
  * @opaque: the opaque pointer to be passed to the callback
  *
@@ -447,7 +447,7 @@ static inline QEMUTimer *timer_new_tl(QEMUTimerList *timer_list,
 /**
  * timer_new:
  * @type: the clock type to use
- * @scale: the scale value for the tiemr
+ * @scale: the scale value for the timer
  * @cb: the callback to be called when the timer expires
  * @opaque: the opaque pointer to be passed to the callback
  *
commit 7af6f46c6199549f0e02a2176d0f3ec2ec405e99
Author: Namhyung Kim <namhyung at gmail.com>
Date:   Tue Jan 7 21:53:51 2014 +0900

    docs: Fix typo in QMP WAKEUP example
    
    Cc: qemu-trivial at nongnu.org
    Signed-off-by: Namhyung Kim <namhyung at gmail.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/docs/qmp/qmp-events.txt b/docs/qmp/qmp-events.txt
index 6b87e97..a378c87 100644
--- a/docs/qmp/qmp-events.txt
+++ b/docs/qmp/qmp-events.txt
@@ -479,7 +479,7 @@ Data: None.
 
 Example:
 
-{ "event": "WATCHDOG",
+{ "event": "WAKEUP",
      "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
 
 WATCHDOG
commit e638073c569e801ce9def2016a84f955cbbca779
Author: Bandan Das <bsd at redhat.com>
Date:   Wed Jan 15 10:11:52 2014 -0700

    vfio: Do not reattempt a failed rom read
    
    During lazy rom loading, if rom read fails, and the
    guest attempts a read again, vfio will again attempt it.
    Add a boolean to prevent this. There could be a case where
    a failed rom read might succeed the next time because of
    a device reset or such, but it's best to exclude unpredictable
    behavior
    
    Signed-off-by: Bandan Das <bsd at redhat.com>
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index ef615fc..30b1a78 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -191,6 +191,7 @@ typedef struct VFIODevice {
     bool has_flr;
     bool has_pm_reset;
     bool needs_reset;
+    bool rom_read_failed;
 } VFIODevice;
 
 typedef struct VFIOGroup {
@@ -1125,6 +1126,7 @@ static void vfio_pci_load_rom(VFIODevice *vdev)
     vdev->rom_offset = reg_info.offset;
 
     if (!vdev->rom_size) {
+        vdev->rom_read_failed = true;
         error_report("vfio-pci: Cannot read device rom at "
                     "%04x:%02x:%02x.%x\n",
                     vdev->host.domain, vdev->host.bus, vdev->host.slot,
@@ -1163,6 +1165,9 @@ static uint64_t vfio_rom_read(void *opaque, hwaddr addr, unsigned size)
     /* Load the ROM lazily when the guest tries to read it */
     if (unlikely(!vdev->rom)) {
         vfio_pci_load_rom(vdev);
+        if (unlikely(!vdev->rom && !vdev->rom_read_failed)) {
+            vfio_pci_load_rom(vdev);
+        }
     }
 
     memcpy(&val, vdev->rom + addr,
@@ -1230,6 +1235,7 @@ static void vfio_pci_size_rom(VFIODevice *vdev)
                      PCI_BASE_ADDRESS_SPACE_MEMORY, &vdev->pdev.rom);
 
     vdev->pdev.has_rom = true;
+    vdev->rom_read_failed = false;
 }
 
 static void vfio_vga_write(void *opaque, hwaddr addr,
commit d20b43dfea1587b561aae17e4fa0f7407779d253
Author: Bandan Das <bsd at redhat.com>
Date:   Wed Jan 15 10:11:06 2014 -0700

    vfio: warn if host device rom can't be read
    
    If the device rom can't be read, report an error to the
    user. This alerts the user that the device has a bad
    state that is causing rom read failure or option rom
    loading has been disabled from the device boot menu
    (among other reasons).
    
    Signed-off-by: Bandan Das <bsd at redhat.com>
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index ec9f41b..ef615fc 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -1125,6 +1125,13 @@ static void vfio_pci_load_rom(VFIODevice *vdev)
     vdev->rom_offset = reg_info.offset;
 
     if (!vdev->rom_size) {
+        error_report("vfio-pci: Cannot read device rom at "
+                    "%04x:%02x:%02x.%x\n",
+                    vdev->host.domain, vdev->host.bus, vdev->host.slot,
+                    vdev->host.function);
+        error_printf("Device option ROM contents are probably invalid "
+                    "(check dmesg).\nSkip option ROM probe with rombar=0, "
+                    "or load from file with romfile=\n");
         return;
     }
 
commit 7c4228b4771acddcb8815079bc116007cec8a1ff
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Wed Jan 15 10:07:26 2014 -0700

    vfio: Destroy memory regions
    
    Somehow this has been lurking for a while; we remove our subregions
    from the base BAR and VGA region mappings, but we don't destroy them,
    creating a leak and more serious problems when we try to migrate after
    removing these devices.  Add the trivial bit of final cleanup to
    remove these entirely.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index 9aecaa8..ec9f41b 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -1968,6 +1968,7 @@ static void vfio_vga_quirk_teardown(VFIODevice *vdev)
         while (!QLIST_EMPTY(&vdev->vga.region[i].quirks)) {
             VFIOQuirk *quirk = QLIST_FIRST(&vdev->vga.region[i].quirks);
             memory_region_del_subregion(&vdev->vga.region[i].mem, &quirk->mem);
+            memory_region_destroy(&quirk->mem);
             QLIST_REMOVE(quirk, next);
             g_free(quirk);
         }
@@ -1990,6 +1991,7 @@ static void vfio_bar_quirk_teardown(VFIODevice *vdev, int nr)
     while (!QLIST_EMPTY(&bar->quirks)) {
         VFIOQuirk *quirk = QLIST_FIRST(&bar->quirks);
         memory_region_del_subregion(&bar->mem, &quirk->mem);
+        memory_region_destroy(&quirk->mem);
         QLIST_REMOVE(quirk, next);
         g_free(quirk);
     }
@@ -2412,10 +2414,12 @@ static void vfio_unmap_bar(VFIODevice *vdev, int nr)
 
     memory_region_del_subregion(&bar->mem, &bar->mmap_mem);
     munmap(bar->mmap, memory_region_size(&bar->mmap_mem));
+    memory_region_destroy(&bar->mmap_mem);
 
     if (vdev->msix && vdev->msix->table_bar == nr) {
         memory_region_del_subregion(&bar->mem, &vdev->msix->mmap_mem);
         munmap(vdev->msix->mmap, memory_region_size(&vdev->msix->mmap_mem));
+        memory_region_destroy(&vdev->msix->mmap_mem);
     }
 
     memory_region_destroy(&bar->mem);


More information about the Spice-commits mailing list