summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--MAINTAINERS8
-rw-r--r--audio/audio.c2
-rw-r--r--audio/paaudio.c8
-rwxr-xr-xconfigure32
-rw-r--r--default-configs/arm-softmmu.mak1
-rw-r--r--device_tree.c4
-rw-r--r--exec.c59
-rw-r--r--fpu/softfloat.c38
-rw-r--r--hmp-commands.hx4
-rw-r--r--hw/arm/Makefile.objs2
-rw-r--r--hw/arm/boot.c32
-rw-r--r--hw/arm/integratorcp.c13
-rw-r--r--hw/arm/virt.c452
-rw-r--r--hw/audio/adlib.c4
-rw-r--r--hw/audio/intel-hda.c1
-rw-r--r--hw/char/cadence_uart.c4
-rw-r--r--hw/cpu/a9mpcore.c44
-rw-r--r--hw/display/qxl-render.c1
-rw-r--r--hw/display/vmware_vga.c1
-rw-r--r--hw/i386/acpi-build.c5
-rw-r--r--hw/i386/pc_piix.c16
-rw-r--r--hw/i386/pc_q35.c13
-rw-r--r--hw/misc/vfio.c133
-rw-r--r--hw/net/cadence_gem.c278
-rw-r--r--hw/net/virtio-net.c37
-rw-r--r--hw/nvram/eeprom93xx.c62
-rw-r--r--hw/ppc/mac.h1
-rw-r--r--hw/ppc/ppc.c6
-rw-r--r--hw/ppc/ppc405_uc.c2
-rw-r--r--hw/ppc/ppc_booke.c4
-rw-r--r--hw/scsi/scsi-bus.c10
-rw-r--r--hw/timer/Makefile.objs1
-rw-r--r--hw/timer/a9gtimer.c369
-rw-r--r--hw/timer/m48t59.c4
-rw-r--r--hw/usb/bus.c18
-rw-r--r--hw/usb/core.c22
-rw-r--r--hw/usb/desc.c12
-rw-r--r--hw/usb/desc.h11
-rw-r--r--hw/usb/dev-hid.c2
-rw-r--r--hw/usb/dev-uas.c156
-rw-r--r--hw/usb/hcd-ehci.c19
-rw-r--r--hw/usb/hcd-ehci.h1
-rw-r--r--hw/usb/hcd-xhci.c138
-rw-r--r--hw/xen/xen_pt.c3
-rw-r--r--hw/xen/xen_pvdevice.c6
-rw-r--r--include/elf.h73
-rw-r--r--include/fpu/softfloat.h4
-rw-r--r--include/hw/arm/arm.h7
-rw-r--r--include/hw/char/serial.h4
-rw-r--r--include/hw/cpu/a9mpcore.h4
-rw-r--r--include/hw/pci/pci_ids.h1
-rw-r--r--include/hw/ppc/ppc.h4
-rw-r--r--include/hw/scsi/scsi.h4
-rw-r--r--include/hw/timer/a9gtimer.h97
-rw-r--r--include/hw/usb.h32
-rw-r--r--include/qemu/cache-utils.h4
-rw-r--r--include/qemu/osdep.h25
-rw-r--r--include/ui/console.h1
-rw-r--r--kvm-all.c30
-rw-r--r--libcacard/cac.c1
-rw-r--r--libcacard/vcard_emul_nss.c1
-rw-r--r--libcacard/vscclient.c4
-rw-r--r--linux-headers/asm-arm/kvm.h3
-rw-r--r--linux-headers/asm-powerpc/epapr_hcalls.h4
-rw-r--r--linux-headers/asm-powerpc/kvm.h86
-rw-r--r--linux-headers/asm-x86/hyperv.h19
-rw-r--r--linux-headers/asm-x86/kvm.h6
-rw-r--r--linux-headers/linux/kvm.h11
-rw-r--r--linux-user/aarch64/target_structs.h58
-rw-r--r--linux-user/alpha/target_structs.h48
-rw-r--r--linux-user/arm/target_structs.h52
-rw-r--r--linux-user/cris/target_structs.h58
-rw-r--r--linux-user/flatload.c2
-rw-r--r--linux-user/i386/target_structs.h58
-rw-r--r--linux-user/m68k/target_structs.h58
-rw-r--r--linux-user/main.c35
-rw-r--r--linux-user/microblaze/target_structs.h58
-rw-r--r--linux-user/mips/target_structs.h48
-rw-r--r--linux-user/mips64/target_cpu.h18
-rw-r--r--linux-user/mips64/target_structs.h2
-rw-r--r--linux-user/openrisc/target_structs.h58
-rw-r--r--linux-user/ppc/target_structs.h60
-rw-r--r--linux-user/qemu.h1
-rw-r--r--linux-user/s390x/target_structs.h63
-rw-r--r--linux-user/sh4/target_structs.h58
-rw-r--r--linux-user/sparc/target_structs.h63
-rw-r--r--linux-user/sparc64/target_structs.h58
-rw-r--r--linux-user/syscall.c254
-rw-r--r--linux-user/syscall_defs.h25
-rw-r--r--linux-user/unicore32/target_structs.h58
-rw-r--r--linux-user/x86_64/target_structs.h58
-rw-r--r--net/Makefile.objs1
-rw-r--r--net/clients.h5
-rw-r--r--net/net.c32
-rw-r--r--net/netmap.c435
-rw-r--r--pc-bios/acpi-dsdt.amlbin4407 -> 4407 bytes
-rw-r--r--pc-bios/bios-256k.binbin0 -> 262144 bytes
-rw-r--r--pc-bios/bios.binbin131072 -> 131072 bytes
-rw-r--r--pc-bios/q35-acpi-dsdt.amlbin7344 -> 7344 bytes
-rw-r--r--pc-bios/vgabios-cirrus.binbin35840 -> 36864 bytes
-rw-r--r--pc-bios/vgabios-qxl.binbin40448 -> 37376 bytes
-rw-r--r--pc-bios/vgabios-stdvga.binbin40448 -> 37376 bytes
-rw-r--r--pc-bios/vgabios-vmware.binbin40448 -> 37376 bytes
-rw-r--r--pc-bios/vgabios.binbin40448 -> 36864 bytes
-rw-r--r--qapi-schema.json24
-rw-r--r--qemu-options.hx11
-rw-r--r--qemu-seccomp.c1
-rw-r--r--qobject/qerror.c4
-rw-r--r--roms/Makefile9
-rw-r--r--roms/config.seabios1
-rw-r--r--roms/config.seabios-128k6
-rw-r--r--roms/config.seabios-256k3
m---------roms/seabios0
-rw-r--r--target-alpha/cpu-qom.h2
-rw-r--r--target-arm/cpu-qom.h11
-rw-r--r--target-arm/cpu.c59
-rw-r--r--target-arm/cpu.h13
-rw-r--r--target-arm/helper.c33
-rw-r--r--target-arm/helper.h5
-rw-r--r--target-arm/kvm-consts.h64
-rw-r--r--target-arm/kvm.c243
-rw-r--r--target-arm/kvm_arm.h55
-rw-r--r--target-arm/translate.c302
-rw-r--r--target-cris/translate.c29
-rw-r--r--target-i386/cpu.c6
-rw-r--r--target-microblaze/translate.c139
-rw-r--r--target-mips/cpu.h2
-rw-r--r--target-mips/dsp_helper.c30
-rw-r--r--target-mips/translate.c7
-rw-r--r--target-openrisc/cpu.h2
-rw-r--r--target-sh4/cpu.h6
-rw-r--r--target-sparc/cpu.h2
-rw-r--r--tcg/arm/tcg-target.c14
-rw-r--r--tcg/ppc64/tcg-target.c11
-rw-r--r--tcg/s390/tcg-target.c95
-rw-r--r--tcg/tcg.c32
-rw-r--r--tcg/tcg.h11
-rw-r--r--trace-events23
-rw-r--r--ui/console.c14
-rw-r--r--ui/gtk.c19
-rw-r--r--ui/input.c2
-rw-r--r--util/Makefile.objs1
-rw-r--r--util/cache-utils.c51
-rw-r--r--util/getauxval.c74
-rw-r--r--vl.c14
-rw-r--r--xen-all.c4
147 files changed, 4751 insertions, 872 deletions
diff --git a/.gitignore b/.gitignore
index 5584b5fcb0..1c9d63d651 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@ config-all-devices.*
 config-all-disas.*
 config-host.*
 config-target.*
+config.status
 trace/generated-tracers.h
 trace/generated-tracers.c
 trace/generated-tracers-dtrace.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 3e61ac839c..7eed206101 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -710,6 +710,14 @@ S: Maintained
 F: net/
 T: git git://github.com/stefanha/qemu.git net
 
+Netmap network backend
+M: Luigi Rizzo <rizzo@iet.unipi.it>
+M: Giuseppe Lettieri <g.lettieri@iet.unipi.it>
+M: Vincenzo Maffione <v.maffione@gmail.com>
+W: http://info.iet.unipi.it/~luigi/netmap/
+S: Maintained
+F: net/netmap.c
+
 Network Block Device (NBD)
 M: Paolo Bonzini <pbonzini@redhat.com>
 S: Odd Fixes
diff --git a/audio/audio.c b/audio/audio.c
index b3db67979d..fc775110af 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -95,7 +95,7 @@ static struct {
         }
     },
 
-    .period = { .hertz = 250 },
+    .period = { .hertz = 100 },
     .plive = 0,
     .log_to_monitor = 0,
     .try_poll_in = 1,
diff --git a/audio/paaudio.c b/audio/paaudio.c
index 8b69778ad9..90ff24500b 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -547,11 +547,11 @@ static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as)
     ss.rate = as->freq;
 
     /*
-     * qemu audio tick runs at 250 Hz (by default), so processing
-     * data chunks worth 4 ms of sound should be a good fit.
+     * qemu audio tick runs at 100 Hz (by default), so processing
+     * data chunks worth 10 ms of sound should be a good fit.
      */
-    ba.tlength = pa_usec_to_bytes (4 * 1000, &ss);
-    ba.minreq = pa_usec_to_bytes (2 * 1000, &ss);
+    ba.tlength = pa_usec_to_bytes (10 * 1000, &ss);
+    ba.minreq = pa_usec_to_bytes (5 * 1000, &ss);
     ba.maxlength = -1;
     ba.prebuf = -1;
 
diff --git a/configure b/configure
index 8144d9fc67..edfea9591c 100755
--- a/configure
+++ b/configure
@@ -169,6 +169,7 @@ curl=""
 curses=""
 docs=""
 fdt=""
+netmap="no"
 pixman=""
 sdl=""
 virtfs=""
@@ -488,6 +489,7 @@ FreeBSD)
   audio_possible_drivers="oss sdl esd pa"
   # needed for kinfo_getvmmap(3) in libutil.h
   LIBS="-lutil $LIBS"
+  netmap=""  # enable netmap autodetect
 ;;
 DragonFly)
   bsd="yes"
@@ -797,6 +799,10 @@ for opt do
   ;;
   --enable-vde) vde="yes"
   ;;
+  --disable-netmap) netmap="no"
+  ;;
+  --enable-netmap) netmap="yes"
+  ;;
   --disable-xen) xen="no"
   ;;
   --enable-xen) xen="yes"
@@ -1182,6 +1188,8 @@ echo "  --disable-uuid           disable uuid support"
 echo "  --enable-uuid            enable uuid support"
 echo "  --disable-vde            disable support for vde network"
 echo "  --enable-vde             enable support for vde network"
+echo "  --disable-netmap         disable support for netmap network"
+echo "  --enable-netmap          enable support for netmap network"
 echo "  --disable-linux-aio      disable Linux AIO support"
 echo "  --enable-linux-aio       enable Linux AIO support"
 echo "  --disable-cap-ng         disable libcap-ng support"
@@ -2095,6 +2103,26 @@ EOF
 fi
 
 ##########################################
+# netmap headers probe
+if test "$netmap" != "no" ; then
+  cat > $TMPC << EOF
+#include <inttypes.h>
+#include <net/if.h>
+#include <net/netmap.h>
+#include <net/netmap_user.h>
+int main(void) { return 0; }
+EOF
+  if compile_prog "" "" ; then
+    netmap=yes
+  else
+    if test "$netmap" = "yes" ; then
+      feature_not_found "netmap"
+    fi
+    netmap=no
+  fi
+fi
+
+##########################################
 # libcap-ng library probe
 if test "$cap_ng" != "no" ; then
   cap_libs="-lcap-ng"
@@ -3751,6 +3779,7 @@ echo "uname -r          $uname_release"
 echo "GUEST_BASE        $guest_base"
 echo "PIE               $pie"
 echo "vde support       $vde"
+echo "netmap support    $netmap"
 echo "Linux AIO support $linux_aio"
 echo "ATTR/XATTR support $attr"
 echo "Install blobs     $blobs"
@@ -3888,6 +3917,9 @@ fi
 if test "$vde" = "yes" ; then
   echo "CONFIG_VDE=y" >> $config_host_mak
 fi
+if test "$netmap" = "yes" ; then
+  echo "CONFIG_NETMAP=y" >> $config_host_mak
+fi
 if test "$cap_ng" = "yes" ; then
   echo "CONFIG_LIBCAP=y" >> $config_host_mak
 fi
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index a555eefed5..e48f102af6 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -41,6 +41,7 @@ CONFIG_ARM_GIC=y
 CONFIG_ARM_GIC_KVM=$(CONFIG_KVM)
 CONFIG_ARM_TIMER=y
 CONFIG_ARM_MPTIMER=y
+CONFIG_A9_GTIMER=y
 CONFIG_PL011=y
 CONFIG_PL022=y
 CONFIG_PL031=y
diff --git a/device_tree.c b/device_tree.c
index ffec99ae29..391da8c45e 100644
--- a/device_tree.c
+++ b/device_tree.c
@@ -41,6 +41,10 @@ void *create_device_tree(int *sizep)
     if (ret < 0) {
         goto fail;
     }
+    ret = fdt_finish_reservemap(fdt);
+    if (ret < 0) {
+        goto fail;
+    }
     ret = fdt_begin_node(fdt, "");
     if (ret < 0) {
         goto fail;
diff --git a/exec.c b/exec.c
index 95c4356c65..f4b9ef25f5 100644
--- a/exec.c
+++ b/exec.c
@@ -904,6 +904,13 @@ static long gethugepagesize(const char *path)
     return fs.f_bsize;
 }
 
+static sigjmp_buf sigjump;
+
+static void sigbus_handler(int signal)
+{
+    siglongjmp(sigjump, 1);
+}
+
 static void *file_ram_alloc(RAMBlock *block,
                             ram_addr_t memory,
                             const char *path)
@@ -913,9 +920,6 @@ static void *file_ram_alloc(RAMBlock *block,
     char *c;
     void *area;
     int fd;
-#ifdef MAP_POPULATE
-    int flags;
-#endif
     unsigned long hpagesize;
 
     hpagesize = gethugepagesize(path);
@@ -963,21 +967,52 @@ static void *file_ram_alloc(RAMBlock *block,
     if (ftruncate(fd, memory))
         perror("ftruncate");
 
-#ifdef MAP_POPULATE
-    /* NB: MAP_POPULATE won't exhaustively alloc all phys pages in the case
-     * MAP_PRIVATE is requested.  For mem_prealloc we mmap as MAP_SHARED
-     * to sidestep this quirk.
-     */
-    flags = mem_prealloc ? MAP_POPULATE | MAP_SHARED : MAP_PRIVATE;
-    area = mmap(0, memory, PROT_READ | PROT_WRITE, flags, fd, 0);
-#else
     area = mmap(0, memory, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
-#endif
     if (area == MAP_FAILED) {
         perror("file_ram_alloc: can't mmap RAM pages");
         close(fd);
         return (NULL);
     }
+
+    if (mem_prealloc) {
+        int ret, i;
+        struct sigaction act, oldact;
+        sigset_t set, oldset;
+
+        memset(&act, 0, sizeof(act));
+        act.sa_handler = &sigbus_handler;
+        act.sa_flags = 0;
+
+        ret = sigaction(SIGBUS, &act, &oldact);
+        if (ret) {
+            perror("file_ram_alloc: failed to install signal handler");
+            exit(1);
+        }
+
+        /* unblock SIGBUS */
+        sigemptyset(&set);
+        sigaddset(&set, SIGBUS);
+        pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
+
+        if (sigsetjmp(sigjump, 1)) {
+            fprintf(stderr, "file_ram_alloc: failed to preallocate pages\n");
+            exit(1);
+        }
+
+        /* MAP_POPULATE silently ignores failures */
+        for (i = 0; i < (memory/hpagesize)-1; i++) {
+            memset(area + (hpagesize*i), 0, 1);
+        }
+
+        ret = sigaction(SIGBUS, &oldact, NULL);
+        if (ret) {
+            perror("file_ram_alloc: failed to reinstall signal handler");
+            exit(1);
+        }
+
+        pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+    }
+
     block->fd = fd;
     return area;
 }
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 7ba51b6f3c..dbda61bc8e 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6705,10 +6705,17 @@ int float128_compare_quiet( float128 a, float128 b STATUS_PARAM )
 /* min() and max() functions. These can't be implemented as
  * 'compare and pick one input' because that would mishandle
  * NaNs and +0 vs -0.
+ *
+ * minnum() and maxnum() functions. These are similar to the min()
+ * and max() functions but if one of the arguments is a QNaN and
+ * the other is numerical then the numerical argument is returned.
+ * minnum() and maxnum correspond to the IEEE 754-2008 minNum()
+ * and maxNum() operations. min() and max() are the typical min/max
+ * semantics provided by many CPUs which predate that specification.
  */
-#define MINMAX(s, nan_exp)                                              \
+#define MINMAX(s)                                                       \
 INLINE float ## s float ## s ## _minmax(float ## s a, float ## s b,     \
-                                        int ismin STATUS_PARAM )        \
+                                        int ismin, int isieee STATUS_PARAM) \
 {                                                                       \
     flag aSign, bSign;                                                  \
     uint ## s ## _t av, bv;                                             \
@@ -6716,6 +6723,15 @@ INLINE float ## s float ## s ## _minmax(float ## s a, float ## s b,     \
     b = float ## s ## _squash_input_denormal(b STATUS_VAR);             \
     if (float ## s ## _is_any_nan(a) ||                                 \
         float ## s ## _is_any_nan(b)) {                                 \
+        if (isieee) {                                                   \
+            if (float ## s ## _is_quiet_nan(a) &&                       \
+                !float ## s ##_is_any_nan(b)) {                         \
+                return b;                                               \
+            } else if (float ## s ## _is_quiet_nan(b) &&                \
+                       !float ## s ## _is_any_nan(a)) {                 \
+                return a;                                               \
+            }                                                           \
+        }                                                               \
         return propagateFloat ## s ## NaN(a, b STATUS_VAR);             \
     }                                                                   \
     aSign = extractFloat ## s ## Sign(a);                               \
@@ -6739,16 +6755,26 @@ INLINE float ## s float ## s ## _minmax(float ## s a, float ## s b,     \
                                                                         \
 float ## s float ## s ## _min(float ## s a, float ## s b STATUS_PARAM)  \
 {                                                                       \
-    return float ## s ## _minmax(a, b, 1 STATUS_VAR);                   \
+    return float ## s ## _minmax(a, b, 1, 0 STATUS_VAR);                \
 }                                                                       \
                                                                         \
 float ## s float ## s ## _max(float ## s a, float ## s b STATUS_PARAM)  \
 {                                                                       \
-    return float ## s ## _minmax(a, b, 0 STATUS_VAR);                   \
+    return float ## s ## _minmax(a, b, 0, 0 STATUS_VAR);                \
+}                                                                       \
+                                                                        \
+float ## s float ## s ## _minnum(float ## s a, float ## s b STATUS_PARAM) \
+{                                                                       \
+    return float ## s ## _minmax(a, b, 1, 1 STATUS_VAR);                \
+}                                                                       \
+                                                                        \
+float ## s float ## s ## _maxnum(float ## s a, float ## s b STATUS_PARAM) \
+{                                                                       \
+    return float ## s ## _minmax(a, b, 0, 1 STATUS_VAR);                \
 }
 
-MINMAX(32, 0xff)
-MINMAX(64, 0x7ff)
+MINMAX(32)
+MINMAX(64)
 
 
 /* Multiply A by 2 raised to the power N.  */
diff --git a/hmp-commands.hx b/hmp-commands.hx
index caae5ad9e9..ebe8e78bb9 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1190,7 +1190,7 @@ ETEXI
     {
         .name       = "host_net_add",
         .args_type  = "device:s,opts:s?",
-        .params     = "tap|user|socket|vde|dump [options]",
+        .params     = "tap|user|socket|vde|netmap|dump [options]",
         .help       = "add host VLAN client",
         .mhandler.cmd = net_host_device_add,
     },
@@ -1218,7 +1218,7 @@ ETEXI
     {
         .name       = "netdev_add",
         .args_type  = "netdev:O",
-        .params     = "[user|tap|socket|hubport],id=str[,prop=value][,...]",
+        .params     = "[user|tap|socket|hubport|netmap],id=str[,prop=value][,...]",
         .help       = "add host network device",
         .mhandler.cmd = hmp_netdev_add,
     },
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 3671b42738..78b56149b6 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -1,7 +1,7 @@
 obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
 obj-y += integratorcp.o kzm.o mainstone.o musicpal.o nseries.o
 obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
-obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
+obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o
 
 obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
 obj-y += omap1.o omap2.o strongarm.o
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 583ec7992e..55d552f3a8 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -228,23 +228,31 @@ static void set_kernel_args_old(const struct arm_boot_info *info)
 static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
 {
     void *fdt = NULL;
-    char *filename;
     int size, rc;
     uint32_t acells, scells;
 
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, binfo->dtb_filename);
-    if (!filename) {
-        fprintf(stderr, "Couldn't open dtb file %s\n", binfo->dtb_filename);
-        goto fail;
-    }
+    if (binfo->dtb_filename) {
+        char *filename;
+        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, binfo->dtb_filename);
+        if (!filename) {
+            fprintf(stderr, "Couldn't open dtb file %s\n", binfo->dtb_filename);
+            goto fail;
+        }
 
-    fdt = load_device_tree(filename, &size);
-    if (!fdt) {
-        fprintf(stderr, "Couldn't open dtb file %s\n", filename);
+        fdt = load_device_tree(filename, &size);
+        if (!fdt) {
+            fprintf(stderr, "Couldn't open dtb file %s\n", filename);
+            g_free(filename);
+            goto fail;
+        }
         g_free(filename);
-        goto fail;
+    } else if (binfo->get_dtb) {
+        fdt = binfo->get_dtb(binfo, &size);
+        if (!fdt) {
+            fprintf(stderr, "Board was unable to create a dtb blob\n");
+            goto fail;
+        }
     }
-    g_free(filename);
 
     acells = qemu_devtree_getprop_cell(fdt, "/", "#address-cells");
     scells = qemu_devtree_getprop_cell(fdt, "/", "#size-cells");
@@ -438,7 +446,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) {
+        if (info->dtb_filename || info->get_dtb) {
             /* 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.
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
index c44b2a499c..a759689b44 100644
--- a/hw/arm/integratorcp.c
+++ b/hw/arm/integratorcp.c
@@ -36,6 +36,7 @@ typedef struct IntegratorCMState {
     uint32_t cm_init;
     uint32_t cm_flags;
     uint32_t cm_nvflags;
+    uint32_t cm_refcnt_offset;
     uint32_t int_level;
     uint32_t irq_enabled;
     uint32_t fiq_enabled;
@@ -82,9 +83,13 @@ static uint64_t integratorcm_read(void *opaque, hwaddr offset,
         return s->cm_sdram;
     case 9: /* CM_INIT */
         return s->cm_init;
-    case 10: /* CM_REFCT */
-        /* ??? High frequency timer.  */
-        hw_error("integratorcm_read: CM_REFCT");
+    case 10: /* CM_REFCNT */
+        /* This register, CM_REFCNT, provides a 32-bit count value.
+         * The count increments at the fixed reference clock frequency of 24MHz
+         * and can be used as a real-time counter.
+         */
+        return (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24,
+                                  1000) - s->cm_refcnt_offset;
     case 12: /* CM_FLAGS */
         return s->cm_flags;
     case 14: /* CM_NVFLAGS */
@@ -257,6 +262,8 @@ static int integratorcm_init(SysBusDevice *dev)
     }
     memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
     s->cm_init = 0x00000112;
+    s->cm_refcnt_offset = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24,
+                                   1000);
     memory_region_init_ram(&s->flash, OBJECT(s), "integrator.flash", 0x100000);
     vmstate_register_ram_global(&s->flash);
 
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
new file mode 100644
index 0000000000..9531b5a574
--- /dev/null
+++ b/hw/arm/virt.c
@@ -0,0 +1,452 @@
+/*
+ * ARM mach-virt emulation
+ *
+ * Copyright (c) 2013 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Emulate a virtual board which works by passing Linux all the information
+ * it needs about what devices are present via the device tree.
+ * There are some restrictions about what we can do here:
+ *  + we can only present devices whose Linux drivers will work based
+ *    purely on the device tree with no platform data at all
+ *  + we want to present a very stripped-down minimalist platform,
+ *    both because this reduces the security attack surface from the guest
+ *    and also because it reduces our exposure to being broken when
+ *    the kernel updates its device tree bindings and requires further
+ *    information in a device binding that we aren't providing.
+ * This is essentially the same approach kvmtool uses.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/arm/arm.h"
+#include "hw/arm/primecell.h"
+#include "hw/devices.h"
+#include "net/net.h"
+#include "sysemu/device_tree.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
+#include "hw/boards.h"
+#include "exec/address-spaces.h"
+#include "qemu/bitops.h"
+#include "qemu/error-report.h"
+
+#define NUM_VIRTIO_TRANSPORTS 32
+
+/* Number of external interrupt lines to configure the GIC with */
+#define NUM_IRQS 128
+
+#define GIC_FDT_IRQ_TYPE_SPI 0
+#define GIC_FDT_IRQ_TYPE_PPI 1
+
+#define GIC_FDT_IRQ_FLAGS_EDGE_LO_HI 1
+#define GIC_FDT_IRQ_FLAGS_EDGE_HI_LO 2
+#define GIC_FDT_IRQ_FLAGS_LEVEL_HI 4
+#define GIC_FDT_IRQ_FLAGS_LEVEL_LO 8
+
+#define GIC_FDT_IRQ_PPI_CPU_START 8
+#define GIC_FDT_IRQ_PPI_CPU_WIDTH 8
+
+enum {
+    VIRT_FLASH,
+    VIRT_MEM,
+    VIRT_CPUPERIPHS,
+    VIRT_GIC_DIST,
+    VIRT_GIC_CPU,
+    VIRT_UART,
+    VIRT_MMIO,
+};
+
+typedef struct MemMapEntry {
+    hwaddr base;
+    hwaddr size;
+} MemMapEntry;
+
+typedef struct VirtBoardInfo {
+    struct arm_boot_info bootinfo;
+    const char *cpu_model;
+    const char *qdevname;
+    const char *gic_compatible;
+    const MemMapEntry *memmap;
+    const int *irqmap;
+    int smp_cpus;
+    void *fdt;
+    int fdt_size;
+    uint32_t clock_phandle;
+} VirtBoardInfo;
+
+/* Addresses and sizes of our components.
+ * 0..128MB is space for a flash device so we can run bootrom code such as UEFI.
+ * 128MB..256MB is used for miscellaneous device I/O.
+ * 256MB..1GB is reserved for possible future PCI support (ie where the
+ * PCI memory window will go if we add a PCI host controller).
+ * 1GB and up is RAM (which may happily spill over into the
+ * high memory region beyond 4GB).
+ * This represents a compromise between how much RAM can be given to
+ * a 32 bit VM and leaving space for expansion and in particular for PCI.
+ */
+static const MemMapEntry a15memmap[] = {
+    /* Space up to 0x8000000 is reserved for a boot ROM */
+    [VIRT_FLASH] = { 0, 0x8000000 },
+    [VIRT_CPUPERIPHS] = { 0x8000000, 0x8000 },
+    /* GIC distributor and CPU interfaces sit inside the CPU peripheral space */
+    [VIRT_GIC_DIST] = { 0x8001000, 0x1000 },
+    [VIRT_GIC_CPU] = { 0x8002000, 0x1000 },
+    [VIRT_UART] = { 0x9000000, 0x1000 },
+    [VIRT_MMIO] = { 0xa000000, 0x200 },
+    /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
+    /* 0x10000000 .. 0x40000000 reserved for PCI */
+    [VIRT_MEM] = { 0x40000000, 30ULL * 1024 * 1024 * 1024 },
+};
+
+static const int a15irqmap[] = {
+    [VIRT_UART] = 1,
+    [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */
+};
+
+static VirtBoardInfo machines[] = {
+    {
+        .cpu_model = "cortex-a15",
+        .qdevname = "a15mpcore_priv",
+        .gic_compatible = "arm,cortex-a15-gic",
+        .memmap = a15memmap,
+        .irqmap = a15irqmap,
+    },
+    {
+        .cpu_model = "host",
+        /* We use the A15 private peripheral model to get a V2 GIC */
+        .qdevname = "a15mpcore_priv",
+        .gic_compatible = "arm,cortex-a15-gic",
+        .memmap = a15memmap,
+        .irqmap = a15irqmap,
+    },
+};
+
+static VirtBoardInfo *find_machine_info(const char *cpu)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(machines); i++) {
+        if (strcmp(cpu, machines[i].cpu_model) == 0) {
+            return &machines[i];
+        }
+    }
+    return NULL;
+}
+
+static void create_fdt(VirtBoardInfo *vbi)
+{
+    void *fdt = create_device_tree(&vbi->fdt_size);
+
+    if (!fdt) {
+        error_report("create_device_tree() failed");
+        exit(1);
+    }
+
+    vbi->fdt = fdt;
+
+    /* Header */
+    qemu_devtree_setprop_string(fdt, "/", "compatible", "linux,dummy-virt");
+    qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 0x2);
+    qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 0x2);
+
+    /*
+     * /chosen and /memory nodes must exist for load_dtb
+     * to fill in necessary properties later
+     */
+    qemu_devtree_add_subnode(fdt, "/chosen");
+    qemu_devtree_add_subnode(fdt, "/memory");
+    qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory");
+
+    /* Clock node, for the benefit of the UART. The kernel device tree
+     * binding documentation claims the PL011 node clock properties are
+     * optional but in practice if you omit them the kernel refuses to
+     * probe for the device.
+     */
+    vbi->clock_phandle = qemu_devtree_alloc_phandle(fdt);
+    qemu_devtree_add_subnode(fdt, "/apb-pclk");
+    qemu_devtree_setprop_string(fdt, "/apb-pclk", "compatible", "fixed-clock");
+    qemu_devtree_setprop_cell(fdt, "/apb-pclk", "#clock-cells", 0x0);
+    qemu_devtree_setprop_cell(fdt, "/apb-pclk", "clock-frequency", 24000000);
+    qemu_devtree_setprop_string(fdt, "/apb-pclk", "clock-output-names",
+                                "clk24mhz");
+    qemu_devtree_setprop_cell(fdt, "/apb-pclk", "phandle", vbi->clock_phandle);
+
+    /* No PSCI for TCG yet */
+    if (kvm_enabled()) {
+        qemu_devtree_add_subnode(fdt, "/psci");
+        qemu_devtree_setprop_string(fdt, "/psci", "compatible", "arm,psci");
+        qemu_devtree_setprop_string(fdt, "/psci", "method", "hvc");
+        qemu_devtree_setprop_cell(fdt, "/psci", "cpu_suspend",
+                                  PSCI_FN_CPU_SUSPEND);
+        qemu_devtree_setprop_cell(fdt, "/psci", "cpu_off", PSCI_FN_CPU_OFF);
+        qemu_devtree_setprop_cell(fdt, "/psci", "cpu_on", PSCI_FN_CPU_ON);
+        qemu_devtree_setprop_cell(fdt, "/psci", "migrate", PSCI_FN_MIGRATE);
+    }
+}
+
+static void fdt_add_timer_nodes(const VirtBoardInfo *vbi)
+{
+    /* Note that on A15 h/w these interrupts are level-triggered,
+     * but for the GIC implementation provided by both QEMU and KVM
+     * they are edge-triggered.
+     */
+    uint32_t irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI;
+
+    irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
+                         GIC_FDT_IRQ_PPI_CPU_WIDTH, (1 << vbi->smp_cpus) - 1);
+
+    qemu_devtree_add_subnode(vbi->fdt, "/timer");
+    qemu_devtree_setprop_string(vbi->fdt, "/timer",
+                                "compatible", "arm,armv7-timer");
+    qemu_devtree_setprop_cells(vbi->fdt, "/timer", "interrupts",
+                               GIC_FDT_IRQ_TYPE_PPI, 13, irqflags,
+                               GIC_FDT_IRQ_TYPE_PPI, 14, irqflags,
+                               GIC_FDT_IRQ_TYPE_PPI, 11, irqflags,
+                               GIC_FDT_IRQ_TYPE_PPI, 10, irqflags);
+}
+
+static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
+{
+    int cpu;
+
+    qemu_devtree_add_subnode(vbi->fdt, "/cpus");
+    qemu_devtree_setprop_cell(vbi->fdt, "/cpus", "#address-cells", 0x1);
+    qemu_devtree_setprop_cell(vbi->fdt, "/cpus", "#size-cells", 0x0);
+
+    for (cpu = vbi->smp_cpus - 1; cpu >= 0; cpu--) {
+        char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
+        ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
+
+        qemu_devtree_add_subnode(vbi->fdt, nodename);
+        qemu_devtree_setprop_string(vbi->fdt, nodename, "device_type", "cpu");
+        qemu_devtree_setprop_string(vbi->fdt, nodename, "compatible",
+                                    armcpu->dtb_compatible);
+
+        if (vbi->smp_cpus > 1) {
+            qemu_devtree_setprop_string(vbi->fdt, nodename,
+                                        "enable-method", "psci");
+        }
+
+        qemu_devtree_setprop_cell(vbi->fdt, nodename, "reg", cpu);
+        g_free(nodename);
+    }
+}
+
+static void fdt_add_gic_node(const VirtBoardInfo *vbi)
+{
+    uint32_t gic_phandle;
+
+    gic_phandle = qemu_devtree_alloc_phandle(vbi->fdt);
+    qemu_devtree_setprop_cell(vbi->fdt, "/", "interrupt-parent", gic_phandle);
+
+    qemu_devtree_add_subnode(vbi->fdt, "/intc");
+    qemu_devtree_setprop_string(vbi->fdt, "/intc", "compatible",
+                                vbi->gic_compatible);
+    qemu_devtree_setprop_cell(vbi->fdt, "/intc", "#interrupt-cells", 3);
+    qemu_devtree_setprop(vbi->fdt, "/intc", "interrupt-controller", NULL, 0);
+    qemu_devtree_setprop_sized_cells(vbi->fdt, "/intc", "reg",
+                                     2, vbi->memmap[VIRT_GIC_DIST].base,
+                                     2, vbi->memmap[VIRT_GIC_DIST].size,
+                                     2, vbi->memmap[VIRT_GIC_CPU].base,
+                                     2, vbi->memmap[VIRT_GIC_CPU].size);
+    qemu_devtree_setprop_cell(vbi->fdt, "/intc", "phandle", gic_phandle);
+}
+
+static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
+{
+    char *nodename;
+    hwaddr base = vbi->memmap[VIRT_UART].base;
+    hwaddr size = vbi->memmap[VIRT_UART].size;
+    int irq = vbi->irqmap[VIRT_UART];
+    const char compat[] = "arm,pl011\0arm,primecell";
+    const char clocknames[] = "uartclk\0apb_pclk";
+
+    sysbus_create_simple("pl011", base, pic[irq]);
+
+    nodename = g_strdup_printf("/pl011@%" PRIx64, base);
+    qemu_devtree_add_subnode(vbi->fdt, nodename);
+    /* Note that we can't use setprop_string because of the embedded NUL */
+    qemu_devtree_setprop(vbi->fdt, nodename, "compatible",
+                         compat, sizeof(compat));
+    qemu_devtree_setprop_sized_cells(vbi->fdt, nodename, "reg",
+                                     2, base, 2, size);
+    qemu_devtree_setprop_cells(vbi->fdt, nodename, "interrupts",
+                               GIC_FDT_IRQ_TYPE_SPI, irq,
+                               GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
+    qemu_devtree_setprop_cells(vbi->fdt, nodename, "clocks",
+                               vbi->clock_phandle, vbi->clock_phandle);
+    qemu_devtree_setprop(vbi->fdt, nodename, "clock-names",
+                         clocknames, sizeof(clocknames));
+    g_free(nodename);
+}
+
+static void create_virtio_devices(const VirtBoardInfo *vbi, qemu_irq *pic)
+{
+    int i;
+    hwaddr size = vbi->memmap[VIRT_MMIO].size;
+
+    /* Note that we have to create the transports in forwards order
+     * so that command line devices are inserted lowest address first,
+     * and then add dtb nodes in reverse order so that they appear in
+     * the finished device tree lowest address first.
+     */
+    for (i = 0; i < NUM_VIRTIO_TRANSPORTS; i++) {
+        int irq = vbi->irqmap[VIRT_MMIO] + i;
+        hwaddr base = vbi->memmap[VIRT_MMIO].base + i * size;
+
+        sysbus_create_simple("virtio-mmio", base, pic[irq]);
+    }
+
+    for (i = NUM_VIRTIO_TRANSPORTS - 1; i >= 0; i--) {
+        char *nodename;
+        int irq = vbi->irqmap[VIRT_MMIO] + i;
+        hwaddr base = vbi->memmap[VIRT_MMIO].base + i * size;
+
+        nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
+        qemu_devtree_add_subnode(vbi->fdt, nodename);
+        qemu_devtree_setprop_string(vbi->fdt, nodename,
+                                    "compatible", "virtio,mmio");
+        qemu_devtree_setprop_sized_cells(vbi->fdt, nodename, "reg",
+                                         2, base, 2, size);
+        qemu_devtree_setprop_cells(vbi->fdt, nodename, "interrupts",
+                                   GIC_FDT_IRQ_TYPE_SPI, irq,
+                                   GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
+        g_free(nodename);
+    }
+}
+
+static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
+{
+    const VirtBoardInfo *board = (const VirtBoardInfo *)binfo;
+
+    *fdt_size = board->fdt_size;
+    return board->fdt;
+}
+
+static void machvirt_init(QEMUMachineInitArgs *args)
+{
+    qemu_irq pic[NUM_IRQS];
+    MemoryRegion *sysmem = get_system_memory();
+    int n;
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    const char *cpu_model = args->cpu_model;
+    VirtBoardInfo *vbi;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a15";
+    }
+
+    vbi = find_machine_info(cpu_model);
+
+    if (!vbi) {
+        error_report("mach-virt: CPU %s not supported", cpu_model);
+        exit(1);
+    }
+
+    vbi->smp_cpus = smp_cpus;
+
+    /*
+     * Only supported method of starting secondary CPUs is PSCI and
+     * PSCI is not yet supported with TCG, so limit smp_cpus to 1
+     * if we're not using KVM.
+     */
+    if (!kvm_enabled() && smp_cpus > 1) {
+        error_report("mach-virt: must enable KVM to use multiple CPUs");
+        exit(1);
+    }
+
+    if (args->ram_size > vbi->memmap[VIRT_MEM].size) {
+        error_report("mach-virt: cannot model more than 30GB RAM");
+        exit(1);
+    }
+
+    create_fdt(vbi);
+    fdt_add_timer_nodes(vbi);
+
+    for (n = 0; n < smp_cpus; n++) {
+        ObjectClass *oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model);
+        Object *cpuobj;
+
+        if (!oc) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        cpuobj = object_new(object_class_get_name(oc));
+
+        /* Secondary CPUs start in PSCI powered-down state */
+        if (n > 0) {
+            object_property_set_bool(cpuobj, true, "start-powered-off", NULL);
+        }
+        object_property_set_bool(cpuobj, true, "realized", NULL);
+    }
+    fdt_add_cpu_nodes(vbi);
+
+    memory_region_init_ram(ram, NULL, "mach-virt.ram", args->ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(sysmem, vbi->memmap[VIRT_MEM].base, ram);
+
+    dev = qdev_create(NULL, vbi->qdevname);
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    /* Note that the num-irq property counts both internal and external
+     * interrupts; there are always 32 of the former (mandated by GIC spec).
+     */
+    qdev_prop_set_uint32(dev, "num-irq", NUM_IRQS + 32);
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, vbi->memmap[VIRT_CPUPERIPHS].base);
+    fdt_add_gic_node(vbi);
+    for (n = 0; n < smp_cpus; n++) {
+        DeviceState *cpudev = DEVICE(qemu_get_cpu(n));
+
+        sysbus_connect_irq(busdev, n, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
+    }
+
+    for (n = 0; n < NUM_IRQS; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    create_uart(vbi, pic);
+
+    /* Create mmio transports, so the user can create virtio backends
+     * (which will be automatically plugged in to the transports). If
+     * no backend is created the transport will just sit harmlessly idle.
+     */
+    create_virtio_devices(vbi, pic);
+
+    vbi->bootinfo.ram_size = args->ram_size;
+    vbi->bootinfo.kernel_filename = args->kernel_filename;
+    vbi->bootinfo.kernel_cmdline = args->kernel_cmdline;
+    vbi->bootinfo.initrd_filename = args->initrd_filename;
+    vbi->bootinfo.nb_cpus = smp_cpus;
+    vbi->bootinfo.board_id = -1;
+    vbi->bootinfo.loader_start = vbi->memmap[VIRT_MEM].base;
+    vbi->bootinfo.get_dtb = machvirt_dtb;
+    arm_load_kernel(ARM_CPU(first_cpu), &vbi->bootinfo);
+}
+
+static QEMUMachine machvirt_a15_machine = {
+    .name = "virt",
+    .desc = "ARM Virtual Machine",
+    .init = machvirt_init,
+    .max_cpus = 4,
+};
+
+static void machvirt_machine_init(void)
+{
+    qemu_register_machine(&machvirt_a15_machine);
+}
+
+machine_init(machvirt_machine_init);
diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c
index bd8e9d9815..e88d2dd845 100644
--- a/hw/audio/adlib.c
+++ b/hw/audio/adlib.c
@@ -347,8 +347,8 @@ static void adlib_realizefn (DeviceState *dev, Error **errp)
     s->samples = AUD_get_buffer_size_out (s->voice) >> SHIFT;
     s->mixbuf = g_malloc0 (s->samples << SHIFT);
 
-    adlib_portio_list[1].offset = s->port;
-    adlib_portio_list[2].offset = s->port + 8;
+    adlib_portio_list[0].offset = s->port;
+    adlib_portio_list[1].offset = s->port + 8;
     portio_list_init (port_list, OBJECT(s), adlib_portio_list, s, "adlib");
     portio_list_add (port_list, isa_address_space_io(&s->parent_obj), 0);
 }
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
index 4327264394..6ab8c245d3 100644
--- a/hw/audio/intel-hda.c
+++ b/hw/audio/intel-hda.c
@@ -444,6 +444,7 @@ static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output,
         }
     }
     if (d->dp_lbase & 0x01) {
+        s = st - d->st;
         addr = intel_hda_addr(d->dp_lbase & ~0x01, d->dp_ubase);
         stl_le_pci_dma(&d->pci, addr + 8*s, st->lpib);
     }
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index f8ccbdd13a..f18db53bca 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -120,8 +120,8 @@ typedef struct {
     uint64_t char_tx_time;
     CharDriverState *chr;
     qemu_irq irq;
-    struct QEMUTimer *fifo_trigger_handle;
-    struct QEMUTimer *tx_time_handle;
+    QEMUTimer *fifo_trigger_handle;
+    QEMUTimer *tx_time_handle;
 } UartState;
 
 static void uart_update_status(UartState *s)
diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c
index 918a7d1291..c09358c6e7 100644
--- a/hw/cpu/a9mpcore.c
+++ b/hw/cpu/a9mpcore.c
@@ -24,11 +24,14 @@ static void a9mp_priv_initfn(Object *obj)
     memory_region_init(&s->container, obj, "a9mp-priv-container", 0x2000);
     sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->container);
 
+    object_initialize(&s->scu, sizeof(s->scu), TYPE_A9_SCU);
+    qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default());
+
     object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
     qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
 
-    object_initialize(&s->scu, sizeof(s->scu), TYPE_A9_SCU);
-    qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default());
+    object_initialize(&s->gtimer, sizeof(s->gtimer), TYPE_A9_GTIMER);
+    qdev_set_parent_bus(DEVICE(&s->gtimer), sysbus_get_default());
 
     object_initialize(&s->mptimer, sizeof(s->mptimer), TYPE_ARM_MPTIMER);
     qdev_set_parent_bus(DEVICE(&s->mptimer), sysbus_get_default());
@@ -41,11 +44,21 @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp)
 {
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     A9MPPrivState *s = A9MPCORE_PRIV(dev);
-    DeviceState *gicdev, *scudev, *mptimerdev, *wdtdev;
-    SysBusDevice *timerbusdev, *wdtbusdev, *gicbusdev, *scubusdev;
+    DeviceState *scudev, *gicdev, *gtimerdev, *mptimerdev, *wdtdev;
+    SysBusDevice *scubusdev, *gicbusdev, *gtimerbusdev, *mptimerbusdev,
+                 *wdtbusdev;
     Error *err = NULL;
     int i;
 
+    scudev = DEVICE(&s->scu);
+    qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu);
+    object_property_set_bool(OBJECT(&s->scu), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    scubusdev = SYS_BUS_DEVICE(&s->scu);
+
     gicdev = DEVICE(&s->gic);
     qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
     qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
@@ -62,14 +75,14 @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp)
     /* Pass through inbound GPIO lines to the GIC */
     qdev_init_gpio_in(dev, a9mp_priv_set_irq, s->num_irq - 32);
 
-    scudev = DEVICE(&s->scu);
-    qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu);
-    object_property_set_bool(OBJECT(&s->scu), true, "realized", &err);
+    gtimerdev = DEVICE(&s->gtimer);
+    qdev_prop_set_uint32(gtimerdev, "num-cpu", s->num_cpu);
+    object_property_set_bool(OBJECT(&s->gtimer), true, "realized", &err);
     if (err != NULL) {
         error_propagate(errp, err);
         return;
     }
-    scubusdev = SYS_BUS_DEVICE(&s->scu);
+    gtimerbusdev = SYS_BUS_DEVICE(&s->gtimer);
 
     mptimerdev = DEVICE(&s->mptimer);
     qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu);
@@ -78,7 +91,7 @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp)
         error_propagate(errp, err);
         return;
     }
-    timerbusdev = SYS_BUS_DEVICE(&s->mptimer);
+    mptimerbusdev = SYS_BUS_DEVICE(&s->mptimer);
 
     wdtdev = DEVICE(&s->wdt);
     qdev_prop_set_uint32(wdtdev, "num-cpu", s->num_cpu);
@@ -97,30 +110,33 @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp)
      *  0x0600-0x06ff -- private timers and watchdogs
      *  0x0700-0x0fff -- nothing
      *  0x1000-0x1fff -- GIC Distributor
-     *
-     * We should implement the global timer but don't currently do so.
      */
     memory_region_add_subregion(&s->container, 0,
                                 sysbus_mmio_get_region(scubusdev, 0));
     /* GIC CPU interface */
     memory_region_add_subregion(&s->container, 0x100,
                                 sysbus_mmio_get_region(gicbusdev, 1));
+    memory_region_add_subregion(&s->container, 0x200,
+                                sysbus_mmio_get_region(gtimerbusdev, 0));
     /* Note that the A9 exposes only the "timer/watchdog for this core"
      * memory region, not the "timer/watchdog for core X" ones 11MPcore has.
      */
     memory_region_add_subregion(&s->container, 0x600,
-                                sysbus_mmio_get_region(timerbusdev, 0));
+                                sysbus_mmio_get_region(mptimerbusdev, 0));
     memory_region_add_subregion(&s->container, 0x620,
                                 sysbus_mmio_get_region(wdtbusdev, 0));
     memory_region_add_subregion(&s->container, 0x1000,
                                 sysbus_mmio_get_region(gicbusdev, 0));
 
     /* Wire up the interrupt from each watchdog and timer.
-     * For each core the timer is PPI 29 and the watchdog PPI 30.
+     * For each core the global timer is PPI 27, the private
+     * timer is PPI 29 and the watchdog PPI 30.
      */
     for (i = 0; i < s->num_cpu; i++) {
         int ppibase = (s->num_irq - 32) + i * 32;
-        sysbus_connect_irq(timerbusdev, i,
+        sysbus_connect_irq(gtimerbusdev, i,
+                           qdev_get_gpio_in(gicdev, ppibase + 27));
+        sysbus_connect_irq(mptimerbusdev, i,
                            qdev_get_gpio_in(gicdev, ppibase + 29));
         sysbus_connect_irq(wdtbusdev, i,
                            qdev_get_gpio_in(gicdev, ppibase + 30));
diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c
index d34b0c4170..84f1367716 100644
--- a/hw/display/qxl-render.c
+++ b/hw/display/qxl-render.c
@@ -20,6 +20,7 @@
  */
 
 #include "qxl.h"
+#include "trace.h"
 
 static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
 {
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index a6a8cdc2e1..aba292ccde 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -23,6 +23,7 @@
  */
 #include "hw/hw.h"
 #include "hw/loader.h"
+#include "trace.h"
 #include "ui/console.h"
 #include "hw/pci/pci.h"
 
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 1f22fb60a4..befc39f253 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -285,7 +285,8 @@ static inline void build_append_array(GArray *array, GArray *val)
     g_array_append_vals(array, val->data, val->len);
 }
 
-static void build_append_nameseg(GArray *array, const char *format, ...)
+static void GCC_FMT_ATTR(2, 3)
+build_append_nameseg(GArray *array, const char *format, ...)
 {
     /* It would be nicer to use g_string_vprintf but it's only there in 2.22 */
     char s[] = "XXXX";
@@ -630,7 +631,7 @@ build_append_notify(GArray *device, const char *name,
     GArray *method = build_alloc_array();
     uint8_t op = 0x14; /* MethodOp */
 
-    build_append_nameseg(method, name);
+    build_append_nameseg(method, "%s", name);
     build_append_byte(method, 0x02); /* MethodFlags: ArgCount */
     for (i = skip; i < count; i++) {
         GArray *target = build_alloc_array();
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 2111f0192c..ab562853b8 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -339,13 +339,24 @@ static void pc_xen_hvm_init(QEMUMachineInitArgs *args)
     .desc = "Standard PC (i440FX + PIIX, 1996)", \
     .hot_add_cpu = pc_hot_add_cpu
 
+#define PC_I440FX_2_0_MACHINE_OPTIONS                           \
+    PC_I440FX_MACHINE_OPTIONS,                                  \
+    .default_machine_opts = "firmware=bios-256k.bin"
+
+static QEMUMachine pc_i440fx_machine_v2_0 = {
+    PC_I440FX_2_0_MACHINE_OPTIONS,
+    .name = "pc-i440fx-2.0",
+    .alias = "pc",
+    .init = pc_init_pci,
+    .is_default = 1,
+};
+
 #define PC_I440FX_1_7_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
+
 static QEMUMachine pc_i440fx_machine_v1_7 = {
     PC_I440FX_1_7_MACHINE_OPTIONS,
     .name = "pc-i440fx-1.7",
-    .alias = "pc",
     .init = pc_init_pci,
-    .is_default = 1,
 };
 
 #define PC_I440FX_1_6_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
@@ -747,6 +758,7 @@ static QEMUMachine xenfv_machine = {
 
 static void pc_machine_init(void)
 {
+    qemu_register_machine(&pc_i440fx_machine_v2_0);
     qemu_register_machine(&pc_i440fx_machine_v1_7);
     qemu_register_machine(&pc_i440fx_machine_v1_6);
     qemu_register_machine(&pc_i440fx_machine_v1_5);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 600fc02ebe..97aa84264c 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -259,12 +259,22 @@ static void pc_q35_init_1_4(QEMUMachineInitArgs *args)
     .desc = "Standard PC (Q35 + ICH9, 2009)", \
     .hot_add_cpu = pc_hot_add_cpu
 
+#define PC_Q35_2_0_MACHINE_OPTIONS                      \
+    PC_Q35_MACHINE_OPTIONS,                             \
+    .default_machine_opts = "firmware=bios-256k.bin"
+
+static QEMUMachine pc_q35_machine_v2_0 = {
+    PC_Q35_2_0_MACHINE_OPTIONS,
+    .name = "pc-q35-2.0",
+    .alias = "q35",
+    .init = pc_q35_init,
+};
+
 #define PC_Q35_1_7_MACHINE_OPTIONS PC_Q35_MACHINE_OPTIONS
 
 static QEMUMachine pc_q35_machine_v1_7 = {
     PC_Q35_1_7_MACHINE_OPTIONS,
     .name = "pc-q35-1.7",
-    .alias = "q35",
     .init = pc_q35_init,
 };
 
@@ -306,6 +316,7 @@ static QEMUMachine pc_q35_machine_v1_4 = {
 
 static void pc_q35_machine_init(void)
 {
+    qemu_register_machine(&pc_q35_machine_v2_0);
     qemu_register_machine(&pc_q35_machine_v1_7);
     qemu_register_machine(&pc_q35_machine_v1_6);
     qemu_register_machine(&pc_q35_machine_v1_5);
diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index f7f8a19ee8..9aecaa82bc 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -52,6 +52,8 @@
 /* Extra debugging, trap acceleration paths for more logging */
 #define VFIO_ALLOW_MMAP 1
 #define VFIO_ALLOW_KVM_INTX 1
+#define VFIO_ALLOW_KVM_MSI 1
+#define VFIO_ALLOW_KVM_MSIX 1
 
 struct VFIODevice;
 
@@ -208,6 +210,17 @@ static QLIST_HEAD(, VFIOContainer)
 static QLIST_HEAD(, VFIOGroup)
     group_list = QLIST_HEAD_INITIALIZER(group_list);
 
+#ifdef CONFIG_KVM
+/*
+ * We have a single VFIO pseudo device per KVM VM.  Once created it lives
+ * for the life of the VM.  Closing the file descriptor only drops our
+ * reference to it and the device's reference to kvm.  Therefore once
+ * initialized, this file descriptor is only released on QEMU exit and
+ * we'll re-use it should another vfio device be attached before then.
+ */
+static int vfio_kvm_device_fd = -1;
+#endif
+
 static void vfio_disable_interrupts(VFIODevice *vdev);
 static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len);
 static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
@@ -579,9 +592,21 @@ static void vfio_msi_interrupt(void *opaque)
         return;
     }
 
-    DPRINTF("%s(%04x:%02x:%02x.%x) vector %d\n", __func__,
+#ifdef VFIO_DEBUG
+    MSIMessage msg;
+
+    if (vdev->interrupt == VFIO_INT_MSIX) {
+        msg = msi_get_message(&vdev->pdev, nr);
+    } else if (vdev->interrupt == VFIO_INT_MSI) {
+        msg = msix_get_message(&vdev->pdev, nr);
+    } else {
+        abort();
+    }
+
+    DPRINTF("%s(%04x:%02x:%02x.%x) vector %d 0x%"PRIx64"/0x%x\n", __func__,
             vdev->host.domain, vdev->host.bus, vdev->host.slot,
-            vdev->host.function, nr);
+            vdev->host.function, nr, msg.address, msg.data);
+#endif
 
     if (vdev->interrupt == VFIO_INT_MSIX) {
         msix_notify(&vdev->pdev, nr);
@@ -649,7 +674,8 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
      * Attempt to enable route through KVM irqchip,
      * default to userspace handling if unavailable.
      */
-    vector->virq = msg ? kvm_irqchip_add_msi_route(kvm_state, *msg) : -1;
+    vector->virq = msg && VFIO_ALLOW_KVM_MSIX ?
+                   kvm_irqchip_add_msi_route(kvm_state, *msg) : -1;
     if (vector->virq < 0 ||
         kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interrupt,
                                        NULL, vector->virq) < 0) {
@@ -816,7 +842,8 @@ retry:
          * Attempt to enable route through KVM irqchip,
          * default to userspace handling if unavailable.
          */
-        vector->virq = kvm_irqchip_add_msi_route(kvm_state, vector->msg);
+        vector->virq = VFIO_ALLOW_KVM_MSI ?
+                       kvm_irqchip_add_msi_route(kvm_state, vector->msg) : -1;
         if (vector->virq < 0 ||
             kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interrupt,
                                            NULL, vector->virq) < 0) {
@@ -878,8 +905,20 @@ static void vfio_disable_msi_common(VFIODevice *vdev)
 
 static void vfio_disable_msix(VFIODevice *vdev)
 {
+    int i;
+
     msix_unset_vector_notifiers(&vdev->pdev);
 
+    /*
+     * MSI-X will only release vectors if MSI-X is still enabled on the
+     * device, check through the rest and release it ourselves if necessary.
+     */
+    for (i = 0; i < vdev->nr_vectors; i++) {
+        if (vdev->msi_vectors[i].use) {
+            vfio_msix_vector_release(&vdev->pdev, i);
+        }
+    }
+
     if (vdev->nr_vectors) {
         vfio_disable_irqindex(vdev, VFIO_PCI_MSIX_IRQ_INDEX);
     }
@@ -1800,6 +1839,34 @@ static void vfio_probe_nvidia_bar5_window_quirk(VFIODevice *vdev, int nr)
             vdev->host.function);
 }
 
+static void vfio_nvidia_88000_quirk_write(void *opaque, hwaddr addr,
+                                          uint64_t data, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    PCIDevice *pdev = &vdev->pdev;
+    hwaddr base = quirk->data.address_match & TARGET_PAGE_MASK;
+
+    vfio_generic_quirk_write(opaque, addr, data, size);
+
+    /*
+     * Nvidia seems to acknowledge MSI interrupts by writing 0xff to the
+     * MSI capability ID register.  Both the ID and next register are
+     * read-only, so we allow writes covering either of those to real hw.
+     * NB - only fixed for the 0x88000 MMIO window.
+     */
+    if ((pdev->cap_present & QEMU_PCI_CAP_MSI) &&
+        vfio_range_contained(addr, size, pdev->msi_cap, PCI_MSI_FLAGS)) {
+        vfio_bar_write(&vdev->bars[quirk->data.bar], addr + base, data, size);
+    }
+}
+
+static const MemoryRegionOps vfio_nvidia_88000_quirk = {
+    .read = vfio_generic_quirk_read,
+    .write = vfio_nvidia_88000_quirk_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 /*
  * Finally, BAR0 itself.  We want to redirect any accesses to either
  * 0x1800 or 0x88000 through the PCI config space access functions.
@@ -1826,7 +1893,7 @@ static void vfio_probe_nvidia_bar0_88000_quirk(VFIODevice *vdev, int nr)
     quirk->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1;
     quirk->data.bar = nr;
 
-    memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_generic_quirk,
+    memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_88000_quirk,
                           quirk, "vfio-nvidia-bar0-88000-quirk",
                           TARGET_PAGE_ALIGN(quirk->data.address_mask + 1));
     memory_region_add_subregion_overlap(&vdev->bars[nr].mem,
@@ -3041,6 +3108,59 @@ static void vfio_pci_reset_handler(void *opaque)
     }
 }
 
+static void vfio_kvm_device_add_group(VFIOGroup *group)
+{
+#ifdef CONFIG_KVM
+    struct kvm_device_attr attr = {
+        .group = KVM_DEV_VFIO_GROUP,
+        .attr = KVM_DEV_VFIO_GROUP_ADD,
+        .addr = (uint64_t)(unsigned long)&group->fd,
+    };
+
+    if (!kvm_enabled()) {
+        return;
+    }
+
+    if (vfio_kvm_device_fd < 0) {
+        struct kvm_create_device cd = {
+            .type = KVM_DEV_TYPE_VFIO,
+        };
+
+        if (kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd)) {
+            DPRINTF("KVM_CREATE_DEVICE: %m\n");
+            return;
+        }
+
+        vfio_kvm_device_fd = cd.fd;
+    }
+
+    if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) {
+        error_report("Failed to add group %d to KVM VFIO device: %m",
+                     group->groupid);
+    }
+#endif
+}
+
+static void vfio_kvm_device_del_group(VFIOGroup *group)
+{
+#ifdef CONFIG_KVM
+    struct kvm_device_attr attr = {
+        .group = KVM_DEV_VFIO_GROUP,
+        .attr = KVM_DEV_VFIO_GROUP_DEL,
+        .addr = (uint64_t)(unsigned long)&group->fd,
+    };
+
+    if (vfio_kvm_device_fd < 0) {
+        return;
+    }
+
+    if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) {
+        error_report("Failed to remove group %d to KVM VFIO device: %m",
+                     group->groupid);
+    }
+#endif
+}
+
 static int vfio_connect_container(VFIOGroup *group)
 {
     VFIOContainer *container;
@@ -3189,6 +3309,8 @@ static VFIOGroup *vfio_get_group(int groupid)
 
     QLIST_INSERT_HEAD(&group_list, group, next);
 
+    vfio_kvm_device_add_group(group);
+
     return group;
 }
 
@@ -3198,6 +3320,7 @@ static void vfio_put_group(VFIOGroup *group)
         return;
     }
 
+    vfio_kvm_device_del_group(group);
     vfio_disconnect_container(group);
     QLIST_REMOVE(group, next);
     DPRINTF("vfio_put_group: close group->fd\n");
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index 4a355bbbef..92dc2f21fa 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -222,8 +222,13 @@
 #define PHY_REG_INT_ST_ENERGY   0x0010
 
 /***********************************************************************/
-#define GEM_RX_REJECT  1
-#define GEM_RX_ACCEPT  0
+#define GEM_RX_REJECT                   (-1)
+#define GEM_RX_PROMISCUOUS_ACCEPT       (-2)
+#define GEM_RX_BROADCAST_ACCEPT         (-3)
+#define GEM_RX_MULTICAST_HASH_ACCEPT    (-4)
+#define GEM_RX_UNICAST_HASH_ACCEPT      (-5)
+
+#define GEM_RX_SAR_ACCEPT               0
 
 /***********************************************************************/
 
@@ -236,6 +241,13 @@
 #define DESC_0_RX_WRAP 0x00000002
 #define DESC_0_RX_OWNERSHIP 0x00000001
 
+#define R_DESC_1_RX_SAR_SHIFT           25
+#define R_DESC_1_RX_SAR_LENGTH          2
+#define R_DESC_1_RX_SAR_MATCH           (1 << 27)
+#define R_DESC_1_RX_UNICAST_HASH        (1 << 29)
+#define R_DESC_1_RX_MULTICAST_HASH      (1 << 30)
+#define R_DESC_1_RX_BROADCAST           (1 << 31)
+
 #define DESC_1_RX_SOF 0x00004000
 #define DESC_1_RX_EOF 0x00008000
 
@@ -315,6 +327,28 @@ static inline void rx_desc_set_length(unsigned *desc, unsigned len)
     desc[1] |= len;
 }
 
+static inline void rx_desc_set_broadcast(unsigned *desc)
+{
+    desc[1] |= R_DESC_1_RX_BROADCAST;
+}
+
+static inline void rx_desc_set_unicast_hash(unsigned *desc)
+{
+    desc[1] |= R_DESC_1_RX_UNICAST_HASH;
+}
+
+static inline void rx_desc_set_multicast_hash(unsigned *desc)
+{
+    desc[1] |= R_DESC_1_RX_MULTICAST_HASH;
+}
+
+static inline void rx_desc_set_sar(unsigned *desc, int sar_idx)
+{
+    desc[1] = deposit32(desc[1], R_DESC_1_RX_SAR_SHIFT, R_DESC_1_RX_SAR_LENGTH,
+                        sar_idx);
+    desc[1] |= R_DESC_1_RX_SAR_MATCH;
+}
+
 #define TYPE_CADENCE_GEM "cadence_gem"
 #define GEM(obj) OBJECT_CHECK(GemState, (obj), TYPE_CADENCE_GEM)
 
@@ -346,6 +380,11 @@ typedef struct GemState {
     uint32_t rx_desc_addr;
     uint32_t tx_desc_addr;
 
+    uint8_t can_rx_state; /* Debug only */
+
+    unsigned rx_desc[2];
+
+    bool sar_active[4];
 } GemState;
 
 /* The broadcast MAC address: 0xFFFFFFFFFFFF */
@@ -415,13 +454,28 @@ static int gem_can_receive(NetClientState *nc)
 
     s = qemu_get_nic_opaque(nc);
 
-    DB_PRINT("\n");
-
     /* Do nothing if receive is not enabled. */
     if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_RXENA)) {
+        if (s->can_rx_state != 1) {
+            s->can_rx_state = 1;
+            DB_PRINT("can't receive - no enable\n");
+        }
         return 0;
     }
 
+    if (rx_desc_get_ownership(s->rx_desc) == 1) {
+        if (s->can_rx_state != 2) {
+            s->can_rx_state = 2;
+            DB_PRINT("can't receive - busy buffer descriptor 0x%x\n",
+                     s->rx_desc_addr);
+        }
+        return 0;
+    }
+
+    if (s->can_rx_state != 0) {
+        s->can_rx_state = 0;
+        DB_PRINT("can receive 0x%x\n", s->rx_desc_addr);
+    }
     return 1;
 }
 
@@ -527,7 +581,10 @@ static unsigned calc_mac_hash(const uint8_t *mac)
  * Accept or reject this destination address?
  * Returns:
  * GEM_RX_REJECT: reject
- * GEM_RX_ACCEPT: accept
+ * >= 0: Specific address accept (which matched SAR is returned)
+ * others for various other modes of accept:
+ * GEM_RM_PROMISCUOUS_ACCEPT, GEM_RX_BROADCAST_ACCEPT,
+ * GEM_RX_MULTICAST_HASH_ACCEPT or GEM_RX_UNICAST_HASH_ACCEPT
  */
 static int gem_mac_address_filter(GemState *s, const uint8_t *packet)
 {
@@ -536,7 +593,7 @@ static int gem_mac_address_filter(GemState *s, const uint8_t *packet)
 
     /* Promiscuous mode? */
     if (s->regs[GEM_NWCFG] & GEM_NWCFG_PROMISC) {
-        return GEM_RX_ACCEPT;
+        return GEM_RX_PROMISCUOUS_ACCEPT;
     }
 
     if (!memcmp(packet, broadcast_addr, 6)) {
@@ -544,7 +601,7 @@ static int gem_mac_address_filter(GemState *s, const uint8_t *packet)
         if (s->regs[GEM_NWCFG] & GEM_NWCFG_BCAST_REJ) {
             return GEM_RX_REJECT;
         }
-        return GEM_RX_ACCEPT;
+        return GEM_RX_BROADCAST_ACCEPT;
     }
 
     /* Accept packets -w- hash match? */
@@ -555,53 +612,67 @@ static int gem_mac_address_filter(GemState *s, const uint8_t *packet)
         hash_index = calc_mac_hash(packet);
         if (hash_index < 32) {
             if (s->regs[GEM_HASHLO] & (1<<hash_index)) {
-                return GEM_RX_ACCEPT;
+                return packet[0] == 0x01 ? GEM_RX_MULTICAST_HASH_ACCEPT :
+                                           GEM_RX_UNICAST_HASH_ACCEPT;
             }
         } else {
             hash_index -= 32;
             if (s->regs[GEM_HASHHI] & (1<<hash_index)) {
-                return GEM_RX_ACCEPT;
+                return packet[0] == 0x01 ? GEM_RX_MULTICAST_HASH_ACCEPT :
+                                           GEM_RX_UNICAST_HASH_ACCEPT;
             }
         }
     }
 
     /* Check all 4 specific addresses */
     gem_spaddr = (uint8_t *)&(s->regs[GEM_SPADDR1LO]);
-    for (i = 0; i < 4; i++) {
-        if (!memcmp(packet, gem_spaddr, 6)) {
-            return GEM_RX_ACCEPT;
+    for (i = 3; i >= 0; i--) {
+        if (s->sar_active[i] && !memcmp(packet, gem_spaddr + 8 * i, 6)) {
+            return GEM_RX_SAR_ACCEPT + i;
         }
-
-        gem_spaddr += 8;
     }
 
     /* No address match; reject the packet */
     return GEM_RX_REJECT;
 }
 
+static void gem_get_rx_desc(GemState *s)
+{
+    DB_PRINT("read descriptor 0x%x\n", (unsigned)s->rx_desc_addr);
+    /* read current descriptor */
+    cpu_physical_memory_read(s->rx_desc_addr,
+                             (uint8_t *)s->rx_desc, sizeof(s->rx_desc));
+
+    /* Descriptor owned by software ? */
+    if (rx_desc_get_ownership(s->rx_desc) == 1) {
+        DB_PRINT("descriptor 0x%x owned by sw.\n",
+                 (unsigned)s->rx_desc_addr);
+        s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_NOBUF;
+        s->regs[GEM_ISR] |= GEM_INT_RXUSED & ~(s->regs[GEM_IMR]);
+        /* Handle interrupt consequences */
+        gem_update_int_status(s);
+    }
+}
+
 /*
  * gem_receive:
  * Fit a packet handed to us by QEMU into the receive descriptor ring.
  */
 static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
 {
-    unsigned    desc[2];
-    hwaddr packet_desc_addr, last_desc_addr;
     GemState *s;
     unsigned   rxbufsize, bytes_to_copy;
     unsigned   rxbuf_offset;
     uint8_t    rxbuf[2048];
     uint8_t   *rxbuf_ptr;
+    bool first_desc = true;
+    int maf;
 
     s = qemu_get_nic_opaque(nc);
 
-    /* Do nothing if receive is not enabled. */
-    if (!gem_can_receive(nc)) {
-        return -1;
-    }
-
     /* Is this destination MAC address "for us" ? */
-    if (gem_mac_address_filter(s, buf) == GEM_RX_REJECT) {
+    maf = gem_mac_address_filter(s, buf);
+    if (maf == GEM_RX_REJECT) {
         return -1;
     }
 
@@ -633,6 +704,14 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
                  GEM_DMACFG_RBUFSZ_S) * GEM_DMACFG_RBUFSZ_MUL;
     bytes_to_copy = size;
 
+    /* Pad to minimum length. Assume FCS field is stripped, logic
+     * below will increment it to the real minimum of 64 when
+     * not FCS stripping
+     */
+    if (size < 60) {
+        size = 60;
+    }
+
     /* Strip of FCS field ? (usually yes) */
     if (s->regs[GEM_NWCFG] & GEM_NWCFG_STRIP_FCS) {
         rxbuf_ptr = (void *)buf;
@@ -659,95 +738,71 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
         size += 4;
     }
 
-    /* Pad to minimum length */
-    if (size < 64) {
-        size = 64;
-    }
-
     DB_PRINT("config bufsize: %d packet size: %ld\n", rxbufsize, size);
 
-    packet_desc_addr = s->rx_desc_addr;
-    while (1) {
-        DB_PRINT("read descriptor 0x%x\n", (unsigned)packet_desc_addr);
-        /* read current descriptor */
-        cpu_physical_memory_read(packet_desc_addr,
-                                 (uint8_t *)&desc[0], sizeof(desc));
-
-        /* Descriptor owned by software ? */
-        if (rx_desc_get_ownership(desc) == 1) {
-            DB_PRINT("descriptor 0x%x owned by sw.\n",
-                     (unsigned)packet_desc_addr);
-            s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_NOBUF;
-            s->regs[GEM_ISR] |= GEM_INT_RXUSED & ~(s->regs[GEM_IMR]);
-            /* Handle interrupt consequences */
-            gem_update_int_status(s);
+    while (bytes_to_copy) {
+        /* Do nothing if receive is not enabled. */
+        if (!gem_can_receive(nc)) {
+            assert(!first_desc);
             return -1;
         }
 
         DB_PRINT("copy %d bytes to 0x%x\n", MIN(bytes_to_copy, rxbufsize),
-                rx_desc_get_buffer(desc));
-
-        /*
-         * Let's have QEMU lend a helping hand.
-         */
-        if (rx_desc_get_buffer(desc) == 0) {
-            DB_PRINT("Invalid RX buffer (NULL) for descriptor 0x%x\n",
-                     (unsigned)packet_desc_addr);
-            break;
-        }
+                rx_desc_get_buffer(s->rx_desc));
 
         /* Copy packet data to emulated DMA buffer */
-        cpu_physical_memory_write(rx_desc_get_buffer(desc) + rxbuf_offset,
+        cpu_physical_memory_write(rx_desc_get_buffer(s->rx_desc) + rxbuf_offset,
                                   rxbuf_ptr, MIN(bytes_to_copy, rxbufsize));
-        bytes_to_copy -= MIN(bytes_to_copy, rxbufsize);
         rxbuf_ptr += MIN(bytes_to_copy, rxbufsize);
+        bytes_to_copy -= MIN(bytes_to_copy, rxbufsize);
+
+        /* Update the descriptor.  */
+        if (first_desc) {
+            rx_desc_set_sof(s->rx_desc);
+            first_desc = false;
+        }
         if (bytes_to_copy == 0) {
+            rx_desc_set_eof(s->rx_desc);
+            rx_desc_set_length(s->rx_desc, size);
+        }
+        rx_desc_set_ownership(s->rx_desc);
+
+        switch (maf) {
+        case GEM_RX_PROMISCUOUS_ACCEPT:
+            break;
+        case GEM_RX_BROADCAST_ACCEPT:
+            rx_desc_set_broadcast(s->rx_desc);
+            break;
+        case GEM_RX_UNICAST_HASH_ACCEPT:
+            rx_desc_set_unicast_hash(s->rx_desc);
+            break;
+        case GEM_RX_MULTICAST_HASH_ACCEPT:
+            rx_desc_set_multicast_hash(s->rx_desc);
             break;
+        case GEM_RX_REJECT:
+            abort();
+        default: /* SAR */
+            rx_desc_set_sar(s->rx_desc, maf);
         }
 
+        /* Descriptor write-back.  */
+        cpu_physical_memory_write(s->rx_desc_addr,
+                                  (uint8_t *)s->rx_desc, sizeof(s->rx_desc));
+
         /* Next descriptor */
-        if (rx_desc_get_wrap(desc)) {
-            packet_desc_addr = s->regs[GEM_RXQBASE];
+        if (rx_desc_get_wrap(s->rx_desc)) {
+            DB_PRINT("wrapping RX descriptor list\n");
+            s->rx_desc_addr = s->regs[GEM_RXQBASE];
         } else {
-            packet_desc_addr += 8;
+            DB_PRINT("incrementing RX descriptor list\n");
+            s->rx_desc_addr += 8;
         }
+        gem_get_rx_desc(s);
     }
 
-    DB_PRINT("set length: %ld, EOF on descriptor 0x%x\n", size,
-            (unsigned)packet_desc_addr);
-
-    /* Update last descriptor with EOF and total length */
-    rx_desc_set_eof(desc);
-    rx_desc_set_length(desc, size);
-    cpu_physical_memory_write(packet_desc_addr,
-                              (uint8_t *)&desc[0], sizeof(desc));
-
-    /* Advance RX packet descriptor Q */
-    last_desc_addr = packet_desc_addr;
-    packet_desc_addr = s->rx_desc_addr;
-    s->rx_desc_addr = last_desc_addr;
-    if (rx_desc_get_wrap(desc)) {
-        s->rx_desc_addr = s->regs[GEM_RXQBASE];
-        DB_PRINT("wrapping RX descriptor list\n");
-    } else {
-        DB_PRINT("incrementing RX descriptor list\n");
-        s->rx_desc_addr += 8;
-    }
-
-    DB_PRINT("set SOF, OWN on descriptor 0x%08x\n", (unsigned)packet_desc_addr);
-
     /* Count it */
     gem_receive_updatestats(s, buf, size);
 
-    /* Update first descriptor (which could also be the last) */
-    /* read descriptor */
-    cpu_physical_memory_read(packet_desc_addr,
-                             (uint8_t *)&desc[0], sizeof(desc));
-    rx_desc_set_sof(desc);
-    rx_desc_set_ownership(desc);
-    cpu_physical_memory_write(packet_desc_addr,
-                              (uint8_t *)&desc[0], sizeof(desc));
-
     s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_FRMRCVD;
     s->regs[GEM_ISR] |= GEM_INT_RXCMPL & ~(s->regs[GEM_IMR]);
 
@@ -893,7 +948,7 @@ static void gem_transmit(GemState *s)
             gem_transmit_updatestats(s, tx_packet, total_bytes);
 
             /* Send the packet somewhere */
-            if (s->phy_loop) {
+            if (s->phy_loop || (s->regs[GEM_NWCTRL] & GEM_NWCTRL_LOCALLOOP)) {
                 gem_receive(qemu_get_queue(s->nic), tx_packet, total_bytes);
             } else {
                 qemu_send_packet(qemu_get_queue(s->nic), tx_packet,
@@ -949,6 +1004,7 @@ static void gem_phy_reset(GemState *s)
 
 static void gem_reset(DeviceState *d)
 {
+    int i;
     GemState *s = GEM(d);
 
     DB_PRINT("\n");
@@ -968,6 +1024,10 @@ static void gem_reset(DeviceState *d)
     s->regs[GEM_DESCONF5] = 0x002f2145;
     s->regs[GEM_DESCONF6] = 0x00000200;
 
+    for (i = 0; i < 4; i++) {
+        s->sar_active[i] = false;
+    }
+
     gem_phy_reset(s);
 
     gem_update_int_status(s);
@@ -1069,19 +1129,21 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
 
     /* Squash bits which are read only in write value */
     val &= ~(s->regs_ro[offset]);
-    /* Preserve (only) bits which are read only in register */
-    readonly = s->regs[offset];
-    readonly &= s->regs_ro[offset];
-
-    /* Squash bits which are write 1 to clear */
-    val &= ~(s->regs_w1c[offset] & val);
+    /* Preserve (only) bits which are read only and wtc in register */
+    readonly = s->regs[offset] & (s->regs_ro[offset] | s->regs_w1c[offset]);
 
     /* Copy register write to backing store */
-    s->regs[offset] = val | readonly;
+    s->regs[offset] = (val & ~s->regs_w1c[offset]) | readonly;
+
+    /* do w1c */
+    s->regs[offset] &= ~(s->regs_w1c[offset] & val);
 
     /* Handle register write side effects */
     switch (offset) {
     case GEM_NWCTRL:
+        if (val & GEM_NWCTRL_RXENA) {
+            gem_get_rx_desc(s);
+        }
         if (val & GEM_NWCTRL_TXSTART) {
             gem_transmit(s);
         }
@@ -1089,7 +1151,7 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
             /* Reset to start of Q when transmit disabled. */
             s->tx_desc_addr = s->regs[GEM_TXQBASE];
         }
-        if (val & GEM_NWCTRL_RXENA) {
+        if (gem_can_receive(qemu_get_queue(s->nic))) {
             qemu_flush_queued_packets(qemu_get_queue(s->nic));
         }
         break;
@@ -1114,6 +1176,18 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
         s->regs[GEM_IMR] |= val;
         gem_update_int_status(s);
         break;
+    case GEM_SPADDR1LO:
+    case GEM_SPADDR2LO:
+    case GEM_SPADDR3LO:
+    case GEM_SPADDR4LO:
+        s->sar_active[(offset - GEM_SPADDR1LO) / 2] = false;
+        break;
+    case GEM_SPADDR1HI:
+    case GEM_SPADDR2HI:
+    case GEM_SPADDR3HI:
+    case GEM_SPADDR4HI:
+        s->sar_active[(offset - GEM_SPADDR1HI) / 2] = true;
+        break;
     case GEM_PHYMNTNC:
         if (val & GEM_PHYMNTNC_OP_W) {
             uint32_t phy_addr, reg_num;
@@ -1181,15 +1255,17 @@ static int gem_init(SysBusDevice *sbd)
 
 static const VMStateDescription vmstate_cadence_gem = {
     .name = "cadence_gem",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
+    .version_id = 2,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 2,
     .fields      = (VMStateField[]) {
         VMSTATE_UINT32_ARRAY(regs, GemState, GEM_MAXREG),
         VMSTATE_UINT16_ARRAY(phy_regs, GemState, 32),
         VMSTATE_UINT8(phy_loop, GemState),
         VMSTATE_UINT32(rx_desc_addr, GemState),
         VMSTATE_UINT32(tx_desc_addr, GemState),
+        VMSTATE_BOOL_ARRAY(sar_active, GemState, 4),
+        VMSTATE_END_OF_LIST(),
     }
 };
 
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index b75c753305..d312b9c83c 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -610,11 +610,11 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
         return VIRTIO_NET_ERR;
     }
 
-    n->mac_table.in_use = 0;
-    n->mac_table.first_multi = 0;
-    n->mac_table.uni_overflow = 0;
-    n->mac_table.multi_overflow = 0;
-    memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
+    int in_use = 0;
+    int first_multi = 0;
+    uint8_t uni_overflow = 0;
+    uint8_t multi_overflow = 0;
+    uint8_t *macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN);
 
     s = iov_to_buf(iov, iov_cnt, 0, &mac_data.entries,
                    sizeof(mac_data.entries));
@@ -629,19 +629,19 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
     }
 
     if (mac_data.entries <= MAC_TABLE_ENTRIES) {
-        s = iov_to_buf(iov, iov_cnt, 0, n->mac_table.macs,
+        s = iov_to_buf(iov, iov_cnt, 0, macs,
                        mac_data.entries * ETH_ALEN);
         if (s != mac_data.entries * ETH_ALEN) {
             goto error;
         }
-        n->mac_table.in_use += mac_data.entries;
+        in_use += mac_data.entries;
     } else {
-        n->mac_table.uni_overflow = 1;
+        uni_overflow = 1;
     }
 
     iov_discard_front(&iov, &iov_cnt, mac_data.entries * ETH_ALEN);
 
-    n->mac_table.first_multi = n->mac_table.in_use;
+    first_multi = in_use;
 
     s = iov_to_buf(iov, iov_cnt, 0, &mac_data.entries,
                    sizeof(mac_data.entries));
@@ -656,24 +656,29 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
         goto error;
     }
 
-    if (n->mac_table.in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {
-        s = iov_to_buf(iov, iov_cnt, 0,
-                       &n->mac_table.macs[n->mac_table.in_use * ETH_ALEN],
+    if (in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {
+        s = iov_to_buf(iov, iov_cnt, 0, &macs[in_use * ETH_ALEN],
                        mac_data.entries * ETH_ALEN);
         if (s != mac_data.entries * ETH_ALEN) {
             goto error;
         }
-        n->mac_table.in_use += mac_data.entries;
+        in_use += mac_data.entries;
     } else {
-        n->mac_table.multi_overflow = 1;
+        multi_overflow = 1;
     }
 
+    n->mac_table.in_use = in_use;
+    n->mac_table.first_multi = first_multi;
+    n->mac_table.uni_overflow = uni_overflow;
+    n->mac_table.multi_overflow = multi_overflow;
+    memcpy(n->mac_table.macs, macs, MAC_TABLE_ENTRIES * ETH_ALEN);
+    g_free(macs);
     rxfilter_notify(nc);
 
     return VIRTIO_NET_OK;
 
 error:
-    rxfilter_notify(nc);
+    g_free(macs);
     return VIRTIO_NET_ERR;
 }
 
@@ -1428,7 +1433,7 @@ static NetClientInfo net_virtio_info = {
     .size = sizeof(NICState),
     .can_receive = virtio_net_can_receive,
     .receive = virtio_net_receive,
-        .cleanup = virtio_net_cleanup,
+    .cleanup = virtio_net_cleanup,
     .link_status_changed = virtio_net_set_link_status,
     .query_rx_filter = virtio_net_query_rxfilter,
 };
diff --git a/hw/nvram/eeprom93xx.c b/hw/nvram/eeprom93xx.c
index 08f4df586c..a98f924b81 100644
--- a/hw/nvram/eeprom93xx.c
+++ b/hw/nvram/eeprom93xx.c
@@ -126,7 +126,7 @@ static const VMStateDescription vmstate_eeprom = {
     .version_id = EEPROM_VERSION,
     .minimum_version_id = OLD_EEPROM_VERSION,
     .minimum_version_id_old = OLD_EEPROM_VERSION,
-    .fields      = (VMStateField []) {
+    .fields      = (VMStateField[]) {
         VMSTATE_UINT8(tick, eeprom_t),
         VMSTATE_UINT8(address, eeprom_t),
         VMSTATE_UINT8(command, eeprom_t),
@@ -157,13 +157,13 @@ void eeprom93xx_write(eeprom_t *eeprom, int eecs, int eesk, int eedi)
     logout("CS=%u SK=%u DI=%u DO=%u, tick = %u\n",
            eecs, eesk, eedi, eedo, tick);
 
-    if (! eeprom->eecs && eecs) {
+    if (!eeprom->eecs && eecs) {
         /* Start chip select cycle. */
         logout("Cycle start, waiting for 1st start bit (0)\n");
         tick = 0;
         command = 0x0;
         address = 0x0;
-    } else if (eeprom->eecs && ! eecs) {
+    } else if (eeprom->eecs && !eecs) {
         /* End chip select cycle. This triggers write / erase. */
         if (eeprom->writable) {
             uint8_t subcommand = address >> (eeprom->addrbits - 2);
@@ -189,7 +189,7 @@ void eeprom93xx_write(eeprom_t *eeprom, int eecs, int eesk, int eedi)
         }
         /* Output DO is tristate, read results in 1. */
         eedo = 1;
-    } else if (eecs && ! eeprom->eesk && eesk) {
+    } else if (eecs && !eeprom->eesk && eesk) {
         /* Raising edge of clock shifts data in. */
         if (tick == 0) {
             /* Wait for 1st start bit. */
@@ -230,20 +230,20 @@ void eeprom93xx_write(eeprom_t *eeprom, int eecs, int eesk, int eedi)
                 if (command == 0) {
                     /* Command code in upper 2 bits of address. */
                     switch (address >> (eeprom->addrbits - 2)) {
-                        case 0:
-                            logout("write disable command\n");
-                            eeprom->writable = 0;
-                            break;
-                        case 1:
-                            logout("write all command\n");
-                            break;
-                        case 2:
-                            logout("erase all command\n");
-                            break;
-                        case 3:
-                            logout("write enable command\n");
-                            eeprom->writable = 1;
-                            break;
+                    case 0:
+                        logout("write disable command\n");
+                        eeprom->writable = 0;
+                        break;
+                    case 1:
+                        logout("write all command\n");
+                        break;
+                    case 2:
+                        logout("erase all command\n");
+                        break;
+                    case 3:
+                        logout("write enable command\n");
+                        eeprom->writable = 1;
+                        break;
                     }
                 } else {
                     /* Read, write or erase word. */
@@ -276,7 +276,7 @@ uint16_t eeprom93xx_read(eeprom_t *eeprom)
 {
     /* Return status of pin DO (0 or 1). */
     logout("CS=%u DO=%u\n", eeprom->eecs, eeprom->eedo);
-    return (eeprom->eedo);
+    return eeprom->eedo;
 }
 
 #if 0
@@ -296,18 +296,18 @@ eeprom_t *eeprom93xx_new(DeviceState *dev, uint16_t nwords)
     uint8_t addrbits;
 
     switch (nwords) {
-        case 16:
-        case 64:
-            addrbits = 6;
-            break;
-        case 128:
-        case 256:
-            addrbits = 8;
-            break;
-        default:
-            assert(!"Unsupported EEPROM size, fallback to 64 words!");
-            nwords = 64;
-            addrbits = 6;
+    case 16:
+    case 64:
+        addrbits = 6;
+        break;
+    case 128:
+    case 256:
+        addrbits = 8;
+        break;
+    default:
+        assert(!"Unsupported EEPROM size, fallback to 64 words!");
+        nwords = 64;
+        addrbits = 6;
     }
 
     eeprom = (eeprom_t *)g_malloc0(sizeof(*eeprom) + nwords * 2);
diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h
index 1e578dd59d..c1faf9ce27 100644
--- a/hw/ppc/mac.h
+++ b/hw/ppc/mac.h
@@ -34,7 +34,6 @@
 #define MAX_CPUS 1
 
 #define BIOS_SIZE     (1024 * 1024)
-#define BIOS_FILENAME "ppc_rom.bin"
 #define NVRAM_SIZE        0x2000
 #define PROM_FILENAME    "openbios-ppc"
 #define PROM_ADDR         0xfff00000
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index bf2d3d4b35..114be64480 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -684,7 +684,7 @@ static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
 }
 
 static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
-                                 struct QEMUTimer *timer,
+                                 QEMUTimer *timer,
                                  void (*raise_excp)(PowerPCCPU *),
                                  uint32_t decr, uint32_t value,
                                  int is_excp)
@@ -856,9 +856,9 @@ typedef struct ppc40x_timer_t ppc40x_timer_t;
 struct ppc40x_timer_t {
     uint64_t pit_reload;  /* PIT auto-reload value        */
     uint64_t fit_next;    /* Tick for next FIT interrupt  */
-    struct QEMUTimer *fit_timer;
+    QEMUTimer *fit_timer;
     uint64_t wdt_next;    /* Tick for next WDT interrupt  */
-    struct QEMUTimer *wdt_timer;
+    QEMUTimer *wdt_timer;
 
     /* 405 have the PIT, 440 have a DECR.  */
     unsigned int decr_excp;
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 6d6a7f1203..8109f92200 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1234,7 +1234,7 @@ struct ppc4xx_gpt_t {
     MemoryRegion iomem;
     int64_t tb_offset;
     uint32_t tb_freq;
-    struct QEMUTimer *timer;
+    QEMUTimer *timer;
     qemu_irq irqs[5];
     uint32_t oe;
     uint32_t ol;
diff --git a/hw/ppc/ppc_booke.c b/hw/ppc/ppc_booke.c
index b421620708..d8399602d6 100644
--- a/hw/ppc/ppc_booke.c
+++ b/hw/ppc/ppc_booke.c
@@ -64,10 +64,10 @@ typedef struct booke_timer_t booke_timer_t;
 struct booke_timer_t {
 
     uint64_t fit_next;
-    struct QEMUTimer *fit_timer;
+    QEMUTimer *fit_timer;
 
     uint64_t wdt_next;
-    struct QEMUTimer *wdt_timer;
+    QEMUTimer *wdt_timer;
 
     uint32_t flags;
 };
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 2d6ce4d6bb..3496c0bbd8 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -1305,6 +1305,11 @@ const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED = {
     .key = ILLEGAL_REQUEST, .asc = 0x53, .ascq = 0x02
 };
 
+/* Illegal request, Invalid Transfer Tag */
+const struct SCSISense sense_code_INVALID_TAG = {
+    .key = ILLEGAL_REQUEST, .asc = 0x4b, .ascq = 0x01
+};
+
 /* Command aborted, I/O process terminated */
 const struct SCSISense sense_code_IO_ERROR = {
     .key = ABORTED_COMMAND, .asc = 0x00, .ascq = 0x06
@@ -1320,6 +1325,11 @@ const struct SCSISense sense_code_LUN_FAILURE = {
     .key = ABORTED_COMMAND, .asc = 0x3e, .ascq = 0x01
 };
 
+/* Command aborted, Overlapped Commands Attempted */
+const struct SCSISense sense_code_OVERLAPPED_COMMANDS = {
+    .key = ABORTED_COMMAND, .asc = 0x4e, .ascq = 0x00
+};
+
 /* Unit attention, Capacity data has changed */
 const struct SCSISense sense_code_CAPACITY_CHANGED = {
     .key = UNIT_ATTENTION, .asc = 0x2a, .ascq = 0x09
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
index eca590570e..3ae091c95e 100644
--- a/hw/timer/Makefile.objs
+++ b/hw/timer/Makefile.objs
@@ -1,5 +1,6 @@
 common-obj-$(CONFIG_ARM_TIMER) += arm_timer.o
 common-obj-$(CONFIG_ARM_MPTIMER) += arm_mptimer.o
+common-obj-$(CONFIG_A9_GTIMER) += a9gtimer.o
 common-obj-$(CONFIG_CADENCE) += cadence_ttc.o
 common-obj-$(CONFIG_DS1338) += ds1338.o
 common-obj-$(CONFIG_HPET) += hpet.o
diff --git a/hw/timer/a9gtimer.c b/hw/timer/a9gtimer.c
new file mode 100644
index 0000000000..a0656d58a1
--- /dev/null
+++ b/hw/timer/a9gtimer.c
@@ -0,0 +1,369 @@
+/*
+ * Global peripheral timer block for ARM A9MP
+ *
+ * (C) 2013 Xilinx Inc.
+ *
+ * Written by François LEGAL
+ * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/timer/a9gtimer.h"
+#include "qemu/timer.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+
+#ifndef A9_GTIMER_ERR_DEBUG
+#define A9_GTIMER_ERR_DEBUG 0
+#endif
+
+#define DB_PRINT_L(level, ...) do { \
+    if (A9_GTIMER_ERR_DEBUG > (level)) { \
+        fprintf(stderr,  ": %s: ", __func__); \
+        fprintf(stderr, ## __VA_ARGS__); \
+    } \
+} while (0);
+
+#define DB_PRINT(...) DB_PRINT_L(0, ## __VA_ARGS__)
+
+static inline int a9_gtimer_get_current_cpu(A9GTimerState *s)
+{
+    if (current_cpu->cpu_index >= s->num_cpu) {
+        hw_error("a9gtimer: num-cpu %d but this cpu is %d!\n",
+                 s->num_cpu, current_cpu->cpu_index);
+    }
+    return current_cpu->cpu_index;
+}
+
+static inline uint64_t a9_gtimer_get_conv(A9GTimerState *s)
+{
+    uint64_t prescale = extract32(s->control, R_CONTROL_PRESCALER_SHIFT,
+                                  R_CONTROL_PRESCALER_LEN);
+
+    return (prescale + 1) * 10;
+}
+
+static A9GTimerUpdate a9_gtimer_get_update(A9GTimerState *s)
+{
+    A9GTimerUpdate ret;
+
+    ret.now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+    ret.new = s->ref_counter +
+              (ret.now - s->cpu_ref_time) / a9_gtimer_get_conv(s);
+    return ret;
+}
+
+static void a9_gtimer_update(A9GTimerState *s, bool sync)
+{
+
+    A9GTimerUpdate update = a9_gtimer_get_update(s);
+    int i;
+    int64_t next_cdiff = 0;
+
+    for (i = 0; i < s->num_cpu; ++i) {
+        A9GTimerPerCPU *gtb = &s->per_cpu[i];
+        int64_t cdiff = 0;
+
+        if ((s->control & R_CONTROL_TIMER_ENABLE) &&
+                (gtb->control & R_CONTROL_COMP_ENABLE)) {
+            /* R2p0+, where the compare function is >= */
+            while (gtb->compare < update.new) {
+                DB_PRINT("Compare event happened for CPU %d\n", i);
+                gtb->status = 1;
+                if (gtb->control & R_CONTROL_AUTO_INCREMENT) {
+                    DB_PRINT("Auto incrementing timer compare by %" PRId32 "\n",
+                             gtb->inc);
+                    gtb->compare += gtb->inc;
+                } else {
+                    break;
+                }
+            }
+            cdiff = (int64_t)gtb->compare - (int64_t)update.new + 1;
+            if (cdiff > 0 && (cdiff < next_cdiff || !next_cdiff)) {
+                next_cdiff = cdiff;
+            }
+        }
+
+        qemu_set_irq(gtb->irq,
+                     gtb->status && (gtb->control & R_CONTROL_IRQ_ENABLE));
+    }
+
+    timer_del(s->timer);
+    if (next_cdiff) {
+        DB_PRINT("scheduling qemu_timer to fire again in %"
+                 PRIx64 " cycles\n", next_cdiff);
+        timer_mod(s->timer, update.now + next_cdiff * a9_gtimer_get_conv(s));
+    }
+
+    if (s->control & R_CONTROL_TIMER_ENABLE) {
+        s->counter = update.new;
+    }
+
+    if (sync) {
+        s->cpu_ref_time = update.now;
+        s->ref_counter = s->counter;
+    }
+}
+
+static void a9_gtimer_update_no_sync(void *opaque)
+{
+    A9GTimerState *s = A9_GTIMER(opaque);
+
+    return a9_gtimer_update(s, false);
+}
+
+static uint64_t a9_gtimer_read(void *opaque, hwaddr addr, unsigned size)
+{
+    A9GTimerPerCPU *gtb = (A9GTimerPerCPU *)opaque;
+    A9GTimerState *s = gtb->parent;
+    A9GTimerUpdate update;
+    uint64_t ret = 0;
+    int shift = 0;
+
+    switch (addr) {
+    case R_COUNTER_HI:
+        shift = 32;
+        /* fallthrough */
+    case R_COUNTER_LO:
+        update = a9_gtimer_get_update(s);
+        ret = extract64(update.new, shift, 32);
+        break;
+    case R_CONTROL:
+        ret = s->control | gtb->control;
+        break;
+    case R_INTERRUPT_STATUS:
+        ret = gtb->status;
+        break;
+    case R_COMPARATOR_HI:
+        shift = 32;
+        /* fallthrough */
+    case R_COMPARATOR_LO:
+        ret = extract64(gtb->compare, shift, 32);
+        break;
+    case R_AUTO_INCREMENT:
+        ret =  gtb->inc;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "bad a9gtimer register: %x\n",
+                      (unsigned)addr);
+        return 0;
+    }
+
+    DB_PRINT("addr:%#x data:%#08" PRIx64 "\n", (unsigned)addr, ret);
+    return ret;
+}
+
+static void a9_gtimer_write(void *opaque, hwaddr addr, uint64_t value,
+                            unsigned size)
+{
+    A9GTimerPerCPU *gtb = (A9GTimerPerCPU *)opaque;
+    A9GTimerState *s = gtb->parent;
+    int shift = 0;
+
+    DB_PRINT("addr:%#x data:%#08" PRIx64 "\n", (unsigned)addr, value);
+
+    switch (addr) {
+    case R_COUNTER_HI:
+        shift = 32;
+        /* fallthrough */
+    case R_COUNTER_LO:
+        /*
+         * Keep it simple - ARM docco explicitly says to disable timer before
+         * modding it, so dont bother trying to do all the difficult on the fly
+         * timer modifications - (if they even work in real hardware??).
+         */
+        if (s->control & R_CONTROL_TIMER_ENABLE) {
+            qemu_log_mask(LOG_GUEST_ERROR, "Cannot mod running ARM gtimer\n");
+            return;
+        }
+        s->counter = deposit64(s->counter, shift, 32, value);
+        return;
+    case R_CONTROL:
+        a9_gtimer_update(s, (value ^ s->control) & R_CONTROL_NEEDS_SYNC);
+        gtb->control = value & R_CONTROL_BANKED;
+        s->control = value & ~R_CONTROL_BANKED;
+        break;
+    case R_INTERRUPT_STATUS:
+        a9_gtimer_update(s, false);
+        gtb->status &= ~value;
+        break;
+    case R_COMPARATOR_HI:
+        shift = 32;
+        /* fallthrough */
+    case R_COMPARATOR_LO:
+        a9_gtimer_update(s, false);
+        gtb->compare = deposit64(gtb->compare, shift, 32, value);
+        break;
+    case R_AUTO_INCREMENT:
+        gtb->inc = value;
+        return;
+    default:
+        return;
+    }
+
+    a9_gtimer_update(s, false);
+}
+
+/* Wrapper functions to implement the "read global timer for
+ * the current CPU" memory regions.
+ */
+static uint64_t a9_gtimer_this_read(void *opaque, hwaddr addr,
+                                    unsigned size)
+{
+    A9GTimerState *s = A9_GTIMER(opaque);
+    int id = a9_gtimer_get_current_cpu(s);
+
+    /* no \n so concatenates with message from read fn */
+    DB_PRINT("CPU:%d:", id);
+
+    return a9_gtimer_read(&s->per_cpu[id], addr, size);
+}
+
+static void a9_gtimer_this_write(void *opaque, hwaddr addr,
+                                 uint64_t value, unsigned size)
+{
+    A9GTimerState *s = A9_GTIMER(opaque);
+    int id = a9_gtimer_get_current_cpu(s);
+
+    /* no \n so concatenates with message from write fn */
+    DB_PRINT("CPU:%d:", id);
+
+    a9_gtimer_write(&s->per_cpu[id], addr, value, size);
+}
+
+static const MemoryRegionOps a9_gtimer_this_ops = {
+    .read = a9_gtimer_this_read,
+    .write = a9_gtimer_this_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const MemoryRegionOps a9_gtimer_ops = {
+    .read = a9_gtimer_read,
+    .write = a9_gtimer_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void a9_gtimer_reset(DeviceState *dev)
+{
+    A9GTimerState *s = A9_GTIMER(dev);
+    int i;
+
+    s->counter = 0;
+    s->control = 0;
+
+    for (i = 0; i < s->num_cpu; i++) {
+        A9GTimerPerCPU *gtb = &s->per_cpu[i];
+
+        gtb->control = 0;
+        gtb->status = 0;
+        gtb->compare = 0;
+        gtb->inc = 0;
+    }
+    a9_gtimer_update(s, false);
+}
+
+static void a9_gtimer_realize(DeviceState *dev, Error **errp)
+{
+    A9GTimerState *s = A9_GTIMER(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    int i;
+
+    if (s->num_cpu < 1 || s->num_cpu > A9_GTIMER_MAX_CPUS) {
+        error_setg(errp, "%s: num-cpu must be between 1 and %d\n",
+                   __func__, A9_GTIMER_MAX_CPUS);
+        return;
+    }
+
+    memory_region_init_io(&s->iomem, OBJECT(dev), &a9_gtimer_this_ops, s,
+                          "a9gtimer shared", 0x20);
+    sysbus_init_mmio(sbd, &s->iomem);
+    s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, a9_gtimer_update_no_sync, s);
+
+    for (i = 0; i < s->num_cpu; i++) {
+        A9GTimerPerCPU *gtb = &s->per_cpu[i];
+
+        gtb->parent = s;
+        sysbus_init_irq(sbd, &gtb->irq);
+        memory_region_init_io(&gtb->iomem, OBJECT(dev), &a9_gtimer_ops, gtb,
+                              "a9gtimer per cpu", 0x20);
+        sysbus_init_mmio(sbd, &gtb->iomem);
+    }
+}
+
+static const VMStateDescription vmstate_a9_gtimer_per_cpu = {
+    .name = "arm.cortex-a9-global-timer.percpu",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(control, A9GTimerPerCPU),
+        VMSTATE_UINT64(compare, A9GTimerPerCPU),
+        VMSTATE_UINT32(status, A9GTimerPerCPU),
+        VMSTATE_UINT32(inc, A9GTimerPerCPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_a9_gtimer = {
+    .name = "arm.cortex-a9-global-timer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_TIMER(timer, A9GTimerState),
+        VMSTATE_UINT64(counter, A9GTimerState),
+        VMSTATE_UINT64(ref_counter, A9GTimerState),
+        VMSTATE_UINT64(cpu_ref_time, A9GTimerState),
+        VMSTATE_STRUCT_VARRAY_UINT32(per_cpu, A9GTimerState, num_cpu,
+                                     1, vmstate_a9_gtimer_per_cpu,
+                                     A9GTimerPerCPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property a9_gtimer_properties[] = {
+    DEFINE_PROP_UINT32("num-cpu", A9GTimerState, num_cpu, 0),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void a9_gtimer_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = a9_gtimer_realize;
+    dc->vmsd = &vmstate_a9_gtimer;
+    dc->reset = a9_gtimer_reset;
+    dc->props = a9_gtimer_properties;
+}
+
+static const TypeInfo a9_gtimer_info = {
+    .name          = TYPE_A9_GTIMER,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(A9GTimerState),
+    .class_init    = a9_gtimer_class_init,
+};
+
+static void a9_gtimer_register_types(void)
+{
+    type_register_static(&a9_gtimer_info);
+}
+
+type_init(a9_gtimer_register_types)
diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c
index d3d78ec5a8..be0592b53d 100644
--- a/hw/timer/m48t59.c
+++ b/hw/timer/m48t59.c
@@ -61,8 +61,8 @@ struct M48t59State {
     time_t   stop_time;
     /* Alarm & watchdog */
     struct tm alarm;
-    struct QEMUTimer *alrm_timer;
-    struct QEMUTimer *wd_timer;
+    QEMUTimer *alrm_timer;
+    QEMUTimer *wd_timer;
     /* NVRAM storage */
     uint8_t *buffer;
     /* Model parameters */
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index ca329bef29..09848c6320 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -203,6 +203,24 @@ void usb_device_ep_stopped(USBDevice *dev, USBEndpoint *ep)
     }
 }
 
+int usb_device_alloc_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps,
+                             int streams)
+{
+    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+    if (klass->alloc_streams) {
+        return klass->alloc_streams(dev, eps, nr_eps, streams);
+    }
+    return 0;
+}
+
+void usb_device_free_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps)
+{
+    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+    if (klass->free_streams) {
+        klass->free_streams(dev, eps, nr_eps);
+    }
+}
+
 static int usb_qdev_init(DeviceState *qdev)
 {
     USBDevice *dev = USB_DEVICE(qdev);
diff --git a/hw/usb/core.c b/hw/usb/core.c
index cf59a1abcf..67ba7d6018 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -623,6 +623,7 @@ void usb_ep_reset(USBDevice *dev)
     dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL;
     dev->ep_ctl.ifnum = 0;
     dev->ep_ctl.max_packet_size = 64;
+    dev->ep_ctl.max_streams = 0;
     dev->ep_ctl.dev = dev;
     dev->ep_ctl.pipeline = false;
     for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
@@ -636,6 +637,8 @@ void usb_ep_reset(USBDevice *dev)
         dev->ep_out[ep].ifnum = USB_INTERFACE_INVALID;
         dev->ep_in[ep].max_packet_size = 0;
         dev->ep_out[ep].max_packet_size = 0;
+        dev->ep_in[ep].max_streams = 0;
+        dev->ep_out[ep].max_streams = 0;
         dev->ep_in[ep].dev = dev;
         dev->ep_out[ep].dev = dev;
         dev->ep_in[ep].pipeline = false;
@@ -764,6 +767,25 @@ int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep)
     return uep->max_packet_size;
 }
 
+void usb_ep_set_max_streams(USBDevice *dev, int pid, int ep, uint8_t raw)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    int MaxStreams;
+
+    MaxStreams = raw & 0x1f;
+    if (MaxStreams) {
+        uep->max_streams = 1 << MaxStreams;
+    } else {
+        uep->max_streams = 0;
+    }
+}
+
+int usb_ep_get_max_streams(USBDevice *dev, int pid, int ep)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    return uep->max_streams;
+}
+
 void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled)
 {
     struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
diff --git a/hw/usb/desc.c b/hw/usb/desc.c
index bf6c522682..f18a043500 100644
--- a/hw/usb/desc.c
+++ b/hw/usb/desc.c
@@ -6,16 +6,6 @@
 
 /* ------------------------------------------------------------------ */
 
-static uint8_t usb_lo(uint16_t val)
-{
-    return val & 0xff;
-}
-
-static uint8_t usb_hi(uint16_t val)
-{
-    return (val >> 8) & 0xff;
-}
-
 int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
                     uint8_t *dest, size_t len)
 {
@@ -385,6 +375,8 @@ static void usb_desc_ep_init(USBDevice *dev)
             usb_ep_set_ifnum(dev, pid, ep, iface->bInterfaceNumber);
             usb_ep_set_max_packet_size(dev, pid, ep,
                                        iface->eps[e].wMaxPacketSize);
+            usb_ep_set_max_streams(dev, pid, ep,
+                                   iface->eps[e].bmAttributes_super);
         }
     }
 }
diff --git a/hw/usb/desc.h b/hw/usb/desc.h
index ddd3e7485c..81327b0e74 100644
--- a/hw/usb/desc.h
+++ b/hw/usb/desc.h
@@ -194,6 +194,17 @@ struct USBDesc {
 
 #define USB_DESC_FLAG_SUPER (1 << 1)
 
+/* little helpers */
+static inline uint8_t usb_lo(uint16_t val)
+{
+    return val & 0xff;
+}
+
+static inline uint8_t usb_hi(uint16_t val)
+{
+    return (val >> 8) & 0xff;
+}
+
 /* generate usb packages from structs */
 int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
                     uint8_t *dest, size_t len);
diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c
index 59567200ae..5e667f0199 100644
--- a/hw/usb/dev-hid.c
+++ b/hw/usb/dev-hid.c
@@ -236,7 +236,7 @@ static const USBDescDevice desc_device_tablet2 = {
             .bNumInterfaces        = 1,
             .bConfigurationValue   = 1,
             .iConfiguration        = STR_CONFIG_TABLET,
-            .bmAttributes          = 0x80,
+            .bmAttributes          = 0xa0,
             .bMaxPower             = 50,
             .nif = 1,
             .ifs = &desc_iface_tablet2,
diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index 70ed2d1dbd..997b715952 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -55,7 +55,7 @@ typedef struct {
     uint8_t    id;
     uint8_t    reserved;
     uint16_t   tag;
-} QEMU_PACKED  uas_ui_header;
+} QEMU_PACKED  uas_iu_header;
 
 typedef struct {
     uint8_t    prio_taskattr;   /* 6:3 priority, 2:0 task attribute   */
@@ -65,7 +65,7 @@ typedef struct {
     uint64_t   lun;
     uint8_t    cdb[16];
     uint8_t    add_cdb[];
-} QEMU_PACKED  uas_ui_command;
+} QEMU_PACKED  uas_iu_command;
 
 typedef struct {
     uint16_t   status_qualifier;
@@ -73,29 +73,29 @@ typedef struct {
     uint8_t    reserved[7];
     uint16_t   sense_length;
     uint8_t    sense_data[18];
-} QEMU_PACKED  uas_ui_sense;
+} QEMU_PACKED  uas_iu_sense;
 
 typedef struct {
-    uint16_t   add_response_info;
+    uint8_t    add_response_info[3];
     uint8_t    response_code;
-} QEMU_PACKED  uas_ui_response;
+} QEMU_PACKED  uas_iu_response;
 
 typedef struct {
     uint8_t    function;
     uint8_t    reserved;
     uint16_t   task_tag;
     uint64_t   lun;
-} QEMU_PACKED  uas_ui_task_mgmt;
+} QEMU_PACKED  uas_iu_task_mgmt;
 
 typedef struct {
-    uas_ui_header  hdr;
+    uas_iu_header  hdr;
     union {
-        uas_ui_command   command;
-        uas_ui_sense     sense;
-        uas_ui_task_mgmt task;
-        uas_ui_response  response;
+        uas_iu_command   command;
+        uas_iu_sense     sense;
+        uas_iu_task_mgmt task;
+        uas_iu_response  response;
     };
-} QEMU_PACKED  uas_ui;
+} QEMU_PACKED  uas_iu;
 
 /* --------------------------------------------------------------------- */
 
@@ -122,8 +122,8 @@ struct UASDevice {
     UASRequest                *dataout2;
 
     /* usb 3.0 only */
-    USBPacket                 *data3[UAS_MAX_STREAMS];
-    USBPacket                 *status3[UAS_MAX_STREAMS];
+    USBPacket                 *data3[UAS_MAX_STREAMS + 1];
+    USBPacket                 *status3[UAS_MAX_STREAMS + 1];
 };
 
 struct UASRequest {
@@ -145,7 +145,7 @@ struct UASRequest {
 
 struct UASStatus {
     uint32_t                  stream;
-    uas_ui                    status;
+    uas_iu                    status;
     uint32_t                  length;
     QTAILQ_ENTRY(UASStatus)   next;
 };
@@ -338,7 +338,7 @@ static UASStatus *usb_uas_alloc_status(UASDevice *uas, uint8_t id, uint16_t tag)
 
     st->status.hdr.id = id;
     st->status.hdr.tag = cpu_to_be16(tag);
-    st->length = sizeof(uas_ui_header);
+    st->length = sizeof(uas_iu_header);
     if (uas_using_streams(uas)) {
         st->stream = tag;
     }
@@ -392,15 +392,13 @@ static void usb_uas_queue_status(UASDevice *uas, UASStatus *st, int length)
     }
 }
 
-static void usb_uas_queue_response(UASDevice *uas, uint16_t tag,
-                                   uint8_t code, uint16_t add_info)
+static void usb_uas_queue_response(UASDevice *uas, uint16_t tag, uint8_t code)
 {
     UASStatus *st = usb_uas_alloc_status(uas, UAS_UI_RESPONSE, tag);
 
     trace_usb_uas_response(uas->dev.addr, tag, code);
     st->status.response.response_code = code;
-    st->status.response.add_response_info = cpu_to_be16(add_info);
-    usb_uas_queue_status(uas, st, sizeof(uas_ui_response));
+    usb_uas_queue_status(uas, st, sizeof(uas_iu_response));
 }
 
 static void usb_uas_queue_sense(UASRequest *req, uint8_t status)
@@ -416,10 +414,28 @@ static void usb_uas_queue_sense(UASRequest *req, uint8_t status)
                                   sizeof(st->status.sense.sense_data));
         st->status.sense.sense_length = cpu_to_be16(slen);
     }
-    len = sizeof(uas_ui_sense) - sizeof(st->status.sense.sense_data) + slen;
+    len = sizeof(uas_iu_sense) - sizeof(st->status.sense.sense_data) + slen;
     usb_uas_queue_status(req->uas, st, len);
 }
 
+static void usb_uas_queue_fake_sense(UASDevice *uas, uint16_t tag,
+                                     struct SCSISense sense)
+{
+    UASStatus *st = usb_uas_alloc_status(uas, UAS_UI_SENSE, tag);
+    int len, slen = 0;
+
+    st->status.sense.status = CHECK_CONDITION;
+    st->status.sense.status_qualifier = cpu_to_be16(0);
+    st->status.sense.sense_data[0] = 0x70;
+    st->status.sense.sense_data[2] = sense.key;
+    st->status.sense.sense_data[7] = 10;
+    st->status.sense.sense_data[12] = sense.asc;
+    st->status.sense.sense_data[13] = sense.ascq;
+    slen = 18;
+    len = sizeof(uas_iu_sense) - sizeof(st->status.sense.sense_data) + slen;
+    usb_uas_queue_status(uas, st, len);
+}
+
 static void usb_uas_queue_read_ready(UASRequest *req)
 {
     UASStatus *st = usb_uas_alloc_status(req->uas, UAS_UI_READ_READY,
@@ -518,14 +534,14 @@ static void usb_uas_start_next_transfer(UASDevice *uas)
     }
 }
 
-static UASRequest *usb_uas_alloc_request(UASDevice *uas, uas_ui *ui)
+static UASRequest *usb_uas_alloc_request(UASDevice *uas, uas_iu *iu)
 {
     UASRequest *req;
 
     req = g_new0(UASRequest, 1);
     req->uas = uas;
-    req->tag = be16_to_cpu(ui->hdr.tag);
-    req->lun = be64_to_cpu(ui->command.lun);
+    req->tag = be16_to_cpu(iu->hdr.tag);
+    req->lun = be64_to_cpu(iu->command.lun);
     req->dev = usb_uas_get_dev(req->uas, req->lun);
     return req;
 }
@@ -648,7 +664,7 @@ static void usb_uas_cancel_io(USBDevice *dev, USBPacket *p)
         return;
     }
     if (uas_using_streams(uas)) {
-        for (i = 0; i < UAS_MAX_STREAMS; i++) {
+        for (i = 0; i <= UAS_MAX_STREAMS; i++) {
             if (uas->status3[i] == p) {
                 uas->status3[i] = NULL;
                 return;
@@ -668,16 +684,20 @@ static void usb_uas_cancel_io(USBDevice *dev, USBPacket *p)
     assert(!"canceled usb packet not found");
 }
 
-static void usb_uas_command(UASDevice *uas, uas_ui *ui)
+static void usb_uas_command(UASDevice *uas, uas_iu *iu)
 {
     UASRequest *req;
     uint32_t len;
+    uint16_t tag = be16_to_cpu(iu->hdr.tag);
 
-    req = usb_uas_find_request(uas, be16_to_cpu(ui->hdr.tag));
+    if (uas_using_streams(uas) && tag > UAS_MAX_STREAMS) {
+        goto invalid_tag;
+    }
+    req = usb_uas_find_request(uas, tag);
     if (req) {
         goto overlapped_tag;
     }
-    req = usb_uas_alloc_request(uas, ui);
+    req = usb_uas_alloc_request(uas, iu);
     if (req->dev == NULL) {
         goto bad_target;
     }
@@ -694,7 +714,7 @@ static void usb_uas_command(UASDevice *uas, uas_ui *ui)
 
     req->req = scsi_req_new(req->dev, req->tag,
                             usb_uas_get_lun(req->lun),
-                            ui->command.cdb, req);
+                            iu->command.cdb, req);
     if (uas->requestlog) {
         scsi_req_print(req->req);
     }
@@ -705,105 +725,97 @@ static void usb_uas_command(UASDevice *uas, uas_ui *ui)
     }
     return;
 
+invalid_tag:
+    usb_uas_queue_fake_sense(uas, tag, sense_code_INVALID_TAG);
+    return;
+
 overlapped_tag:
-    usb_uas_queue_response(uas, req->tag, UAS_RC_OVERLAPPED_TAG, 0);
+    usb_uas_queue_fake_sense(uas, tag, sense_code_OVERLAPPED_COMMANDS);
     return;
 
 bad_target:
-    /*
-     * FIXME: Seems to upset linux, is this wrong?
-     * NOTE: Happens only with no scsi devices at the bus, not sure
-     *       this is a valid UAS setup in the first place.
-     */
-    usb_uas_queue_response(uas, req->tag, UAS_RC_INVALID_INFO_UNIT, 0);
+    usb_uas_queue_fake_sense(uas, tag, sense_code_LUN_NOT_SUPPORTED);
     g_free(req);
 }
 
-static void usb_uas_task(UASDevice *uas, uas_ui *ui)
+static void usb_uas_task(UASDevice *uas, uas_iu *iu)
 {
-    uint16_t tag = be16_to_cpu(ui->hdr.tag);
-    uint64_t lun64 = be64_to_cpu(ui->task.lun);
+    uint16_t tag = be16_to_cpu(iu->hdr.tag);
+    uint64_t lun64 = be64_to_cpu(iu->task.lun);
     SCSIDevice *dev = usb_uas_get_dev(uas, lun64);
     int lun = usb_uas_get_lun(lun64);
     UASRequest *req;
     uint16_t task_tag;
 
-    req = usb_uas_find_request(uas, be16_to_cpu(ui->hdr.tag));
+    if (uas_using_streams(uas) && tag > UAS_MAX_STREAMS) {
+        goto invalid_tag;
+    }
+    req = usb_uas_find_request(uas, be16_to_cpu(iu->hdr.tag));
     if (req) {
         goto overlapped_tag;
     }
+    if (dev == NULL) {
+        goto incorrect_lun;
+    }
 
-    switch (ui->task.function) {
+    switch (iu->task.function) {
     case UAS_TMF_ABORT_TASK:
-        task_tag = be16_to_cpu(ui->task.task_tag);
+        task_tag = be16_to_cpu(iu->task.task_tag);
         trace_usb_uas_tmf_abort_task(uas->dev.addr, tag, task_tag);
-        if (dev == NULL) {
-            goto bad_target;
-        }
-        if (dev->lun != lun) {
-            goto incorrect_lun;
-        }
         req = usb_uas_find_request(uas, task_tag);
         if (req && req->dev == dev) {
             scsi_req_cancel(req->req);
         }
-        usb_uas_queue_response(uas, tag, UAS_RC_TMF_COMPLETE, 0);
+        usb_uas_queue_response(uas, tag, UAS_RC_TMF_COMPLETE);
         break;
 
     case UAS_TMF_LOGICAL_UNIT_RESET:
         trace_usb_uas_tmf_logical_unit_reset(uas->dev.addr, tag, lun);
-        if (dev == NULL) {
-            goto bad_target;
-        }
-        if (dev->lun != lun) {
-            goto incorrect_lun;
-        }
         qdev_reset_all(&dev->qdev);
-        usb_uas_queue_response(uas, tag, UAS_RC_TMF_COMPLETE, 0);
+        usb_uas_queue_response(uas, tag, UAS_RC_TMF_COMPLETE);
         break;
 
     default:
-        trace_usb_uas_tmf_unsupported(uas->dev.addr, tag, ui->task.function);
-        usb_uas_queue_response(uas, tag, UAS_RC_TMF_NOT_SUPPORTED, 0);
+        trace_usb_uas_tmf_unsupported(uas->dev.addr, tag, iu->task.function);
+        usb_uas_queue_response(uas, tag, UAS_RC_TMF_NOT_SUPPORTED);
         break;
     }
     return;
 
-overlapped_tag:
-    usb_uas_queue_response(uas, req->tag, UAS_RC_OVERLAPPED_TAG, 0);
+invalid_tag:
+    usb_uas_queue_response(uas, tag, UAS_RC_INVALID_INFO_UNIT);
     return;
 
-bad_target:
-    /* FIXME: correct?  [see long comment in usb_uas_command()] */
-    usb_uas_queue_response(uas, tag, UAS_RC_INVALID_INFO_UNIT, 0);
+overlapped_tag:
+    usb_uas_queue_response(uas, req->tag, UAS_RC_OVERLAPPED_TAG);
     return;
 
 incorrect_lun:
-    usb_uas_queue_response(uas, tag, UAS_RC_INCORRECT_LUN, 0);
+    usb_uas_queue_response(uas, tag, UAS_RC_INCORRECT_LUN);
 }
 
 static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
 {
     UASDevice *uas = DO_UPCAST(UASDevice, dev, dev);
-    uas_ui ui;
+    uas_iu iu;
     UASStatus *st;
     UASRequest *req;
     int length;
 
     switch (p->ep->nr) {
     case UAS_PIPE_ID_COMMAND:
-        length = MIN(sizeof(ui), p->iov.size);
-        usb_packet_copy(p, &ui, length);
-        switch (ui.hdr.id) {
+        length = MIN(sizeof(iu), p->iov.size);
+        usb_packet_copy(p, &iu, length);
+        switch (iu.hdr.id) {
         case UAS_UI_COMMAND:
-            usb_uas_command(uas, &ui);
+            usb_uas_command(uas, &iu);
             break;
         case UAS_UI_TASK_MGMT:
-            usb_uas_task(uas, &ui);
+            usb_uas_task(uas, &iu);
             break;
         default:
-            fprintf(stderr, "%s: unknown command ui: id 0x%x\n",
-                    __func__, ui.hdr.id);
+            fprintf(stderr, "%s: unknown command iu: id 0x%x\n",
+                    __func__, iu.hdr.id);
             p->status = USB_RET_STALL;
             break;
         }
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 22bdbf4a7d..355bbd6bed 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -28,6 +28,7 @@
  */
 
 #include "hw/usb/hcd-ehci.h"
+#include "trace.h"
 
 /* Capability Registers Base Address - section 2.2 */
 #define CAPLENGTH        0x0000  /* 1-byte, 0x0001 reserved */
@@ -826,9 +827,9 @@ static void ehci_child_detach(USBPort *port, USBDevice *child)
 static void ehci_wakeup(USBPort *port)
 {
     EHCIState *s = port->opaque;
-    uint32_t portsc = s->portsc[port->index];
+    uint32_t *portsc = &s->portsc[port->index];
 
-    if (portsc & PORTSC_POWNER) {
+    if (*portsc & PORTSC_POWNER) {
         USBPort *companion = s->companion_ports[port->index];
         if (companion->ops->wakeup) {
             companion->ops->wakeup(companion);
@@ -836,6 +837,12 @@ static void ehci_wakeup(USBPort *port)
         return;
     }
 
+    if (*portsc & PORTSC_SUSPEND) {
+        trace_usb_ehci_port_wakeup(port->index);
+        *portsc |= PORTSC_FPRES;
+        ehci_raise_irq(s, USBSTS_PCD);
+    }
+
     qemu_bh_schedule(s->async_bh);
 }
 
@@ -1067,6 +1074,14 @@ static void ehci_port_write(void *ptr, hwaddr addr,
         }
     }
 
+    if ((val & PORTSC_SUSPEND) && !(*portsc & PORTSC_SUSPEND)) {
+        trace_usb_ehci_port_suspend(port);
+    }
+    if (!(val & PORTSC_FPRES) && (*portsc & PORTSC_FPRES)) {
+        trace_usb_ehci_port_resume(port);
+        val &= ~PORTSC_SUSPEND;
+    }
+
     *portsc &= ~PORTSC_RO_MASK;
     *portsc |= val;
     trace_usb_ehci_portsc_change(addr + s->portscbase, addr >> 2, *portsc, old);
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
index 065c9fa741..1ad4b96cce 100644
--- a/hw/usb/hcd-ehci.h
+++ b/hw/usb/hcd-ehci.h
@@ -21,7 +21,6 @@
 #include "qemu/timer.h"
 #include "hw/usb.h"
 #include "monitor/monitor.h"
-#include "trace.h"
 #include "sysemu/dma.h"
 #include "sysemu/sysemu.h"
 #include "hw/pci/pci.h"
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 835f65ed81..bafe08590b 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -1150,6 +1150,111 @@ static void xhci_free_streams(XHCIEPContext *epctx)
     epctx->nr_pstreams = 0;
 }
 
+static int xhci_epmask_to_eps_with_streams(XHCIState *xhci,
+                                           unsigned int slotid,
+                                           uint32_t epmask,
+                                           XHCIEPContext **epctxs,
+                                           USBEndpoint **eps)
+{
+    XHCISlot *slot;
+    XHCIEPContext *epctx;
+    USBEndpoint *ep;
+    int i, j;
+
+    assert(slotid >= 1 && slotid <= xhci->numslots);
+
+    slot = &xhci->slots[slotid - 1];
+
+    for (i = 2, j = 0; i <= 31; i++) {
+        if (!(epmask & (1 << i))) {
+            continue;
+        }
+
+        epctx = slot->eps[i - 1];
+        ep = xhci_epid_to_usbep(xhci, slotid, i);
+        if (!epctx || !epctx->nr_pstreams || !ep) {
+            continue;
+        }
+
+        if (epctxs) {
+            epctxs[j] = epctx;
+        }
+        eps[j++] = ep;
+    }
+    return j;
+}
+
+static void xhci_free_device_streams(XHCIState *xhci, unsigned int slotid,
+                                     uint32_t epmask)
+{
+    USBEndpoint *eps[30];
+    int nr_eps;
+
+    nr_eps = xhci_epmask_to_eps_with_streams(xhci, slotid, epmask, NULL, eps);
+    if (nr_eps) {
+        usb_device_free_streams(eps[0]->dev, eps, nr_eps);
+    }
+}
+
+static TRBCCode xhci_alloc_device_streams(XHCIState *xhci, unsigned int slotid,
+                                          uint32_t epmask)
+{
+    XHCIEPContext *epctxs[30];
+    USBEndpoint *eps[30];
+    int i, r, nr_eps, req_nr_streams, dev_max_streams;
+
+    nr_eps = xhci_epmask_to_eps_with_streams(xhci, slotid, epmask, epctxs,
+                                             eps);
+    if (nr_eps == 0) {
+        return CC_SUCCESS;
+    }
+
+    req_nr_streams = epctxs[0]->nr_pstreams;
+    dev_max_streams = eps[0]->max_streams;
+
+    for (i = 1; i < nr_eps; i++) {
+        /*
+         * HdG: I don't expect these to ever trigger, but if they do we need
+         * to come up with another solution, ie group identical endpoints
+         * together and make an usb_device_alloc_streams call per group.
+         */
+        if (epctxs[i]->nr_pstreams != req_nr_streams) {
+            FIXME("guest streams config not identical for all eps");
+            return CC_RESOURCE_ERROR;
+        }
+        if (eps[i]->max_streams != dev_max_streams) {
+            FIXME("device streams config not identical for all eps");
+            return CC_RESOURCE_ERROR;
+        }
+    }
+
+    /*
+     * max-streams in both the device descriptor and in the controller is a
+     * power of 2. But stream id 0 is reserved, so if a device can do up to 4
+     * streams the guest will ask for 5 rounded up to the next power of 2 which
+     * becomes 8. For emulated devices usb_device_alloc_streams is a nop.
+     *
+     * For redirected devices however this is an issue, as there we must ask
+     * the real xhci controller to alloc streams, and the host driver for the
+     * real xhci controller will likely disallow allocating more streams then
+     * the device can handle.
+     *
+     * So we limit the requested nr_streams to the maximum number the device
+     * can handle.
+     */
+    if (req_nr_streams > dev_max_streams) {
+        req_nr_streams = dev_max_streams;
+    }
+
+    r = usb_device_alloc_streams(eps[0]->dev, eps, nr_eps, req_nr_streams);
+    if (r != 0) {
+        fprintf(stderr, "xhci: alloc streams failed\n");
+        return CC_RESOURCE_ERROR;
+    }
+
+    return CC_SUCCESS;
+}
+
 static XHCIStreamContext *xhci_find_stream(XHCIEPContext *epctx,
                                            unsigned int streamid,
                                            uint32_t *cc_error)
@@ -1495,7 +1600,8 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid,
     }
 
     if (!xhci->slots[slotid-1].uport ||
-        !xhci->slots[slotid-1].uport->dev) {
+        !xhci->slots[slotid-1].uport->dev ||
+        !xhci->slots[slotid-1].uport->dev->attached) {
         return CC_USB_TRANSACTION_ERROR;
     }
 
@@ -1982,6 +2088,14 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
         return;
     }
 
+    /* If the device has been detached, but the guest has not noticed this
+       yet the 2 above checks will succeed, but we must NOT continue */
+    if (!xhci->slots[slotid - 1].uport ||
+        !xhci->slots[slotid - 1].uport->dev ||
+        !xhci->slots[slotid - 1].uport->dev->attached) {
+        return;
+    }
+
     if (epctx->retry) {
         XHCITransfer *xfer = epctx->retry;
 
@@ -2206,7 +2320,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
     trace_usb_xhci_slot_address(slotid, uport->path);
 
     dev = uport->dev;
-    if (!dev) {
+    if (!dev || !dev->attached) {
         fprintf(stderr, "xhci: port %s not connected\n", uport->path);
         return CC_USB_TRANSACTION_ERROR;
     }
@@ -2313,6 +2427,8 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
         return CC_CONTEXT_STATE_ERROR;
     }
 
+    xhci_free_device_streams(xhci, slotid, ictl_ctx[0] | ictl_ctx[1]);
+
     for (i = 2; i <= 31; i++) {
         if (ictl_ctx[0] & (1<<i)) {
             xhci_disable_ep(xhci, slotid, i);
@@ -2334,6 +2450,16 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
         }
     }
 
+    res = xhci_alloc_device_streams(xhci, slotid, ictl_ctx[1]);
+    if (res != CC_SUCCESS) {
+        for (i = 2; i <= 31; i++) {
+            if (ictl_ctx[1] & (1 << i)) {
+                xhci_disable_ep(xhci, slotid, i);
+            }
+        }
+        return res;
+    }
+
     slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
     slot_ctx[3] |= SLOT_CONFIGURED << SLOT_STATE_SHIFT;
     slot_ctx[0] &= ~(SLOT_CONTEXT_ENTRIES_MASK << SLOT_CONTEXT_ENTRIES_SHIFT);
@@ -3016,6 +3142,14 @@ static void xhci_oper_write(void *ptr, hwaddr reg,
         } else if (!(val & USBCMD_RS) && (xhci->usbcmd & USBCMD_RS)) {
             xhci_stop(xhci);
         }
+        if (val & USBCMD_CSS) {
+            /* save state */
+            xhci->usbsts &= ~USBSTS_SRE;
+        }
+        if (val & USBCMD_CRS) {
+            /* restore state */
+            xhci->usbsts |= USBSTS_SRE;
+        }
         xhci->usbcmd = val & 0xc0f;
         xhci_mfwrap_update(xhci);
         if (val & USBCMD_HCRST) {
diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
index ca2d460785..d58cb616b1 100644
--- a/hw/xen/xen_pt.c
+++ b/hw/xen/xen_pt.c
@@ -570,7 +570,8 @@ static void xen_pt_region_update(XenPCIPassthroughState *s,
     if (args.rc) {
         XEN_PT_WARN(d, "Region: %d (addr: %#"FMT_PCIBUS
                     ", len: %#"FMT_PCIBUS") is overlapped.\n",
-                    bar, sec->offset_within_address_space, sec->size);
+                    bar, sec->offset_within_address_space,
+                    int128_get64(sec->size));
     }
 
     if (d->io_regions[bar].type & PCI_BASE_ADDRESS_SPACE_IO) {
diff --git a/hw/xen/xen_pvdevice.c b/hw/xen/xen_pvdevice.c
index 1132c8934f..c2189473ba 100644
--- a/hw/xen/xen_pvdevice.c
+++ b/hw/xen/xen_pvdevice.c
@@ -74,6 +74,10 @@ static int xen_pv_init(PCIDevice *pci_dev)
     XenPVDevice *d = XEN_PV_DEVICE(pci_dev);
     uint8_t *pci_conf;
 
+    /* device-id property must always be supplied */
+    if (d->device_id == 0xffff)
+	    return -1;
+
     pci_conf = pci_dev->config;
 
     pci_set_word(pci_conf + PCI_VENDOR_ID, d->vendor_id);
@@ -99,7 +103,7 @@ static int xen_pv_init(PCIDevice *pci_dev)
 
 static Property xen_pv_props[] = {
     DEFINE_PROP_UINT16("vendor-id", XenPVDevice, vendor_id, PCI_VENDOR_ID_XEN),
-    DEFINE_PROP_UINT16("device-id", XenPVDevice, device_id, PCI_DEVICE_ID_XEN_PVDEVICE),
+    DEFINE_PROP_UINT16("device-id", XenPVDevice, device_id, 0xffff),
     DEFINE_PROP_UINT8("revision", XenPVDevice, revision, 0x01),
     DEFINE_PROP_UINT32("size", XenPVDevice, size, 0x400000),
     DEFINE_PROP_END_OF_LIST()
diff --git a/include/elf.h b/include/elf.h
index b818091c7b..667af6fc63 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -411,6 +411,65 @@ typedef struct {
 #define R_SPARC_5		44
 #define R_SPARC_6		45
 
+/* Bits present in AT_HWCAP for ARM.  */
+
+#define HWCAP_ARM_SWP           (1 << 0)
+#define HWCAP_ARM_HALF          (1 << 1)
+#define HWCAP_ARM_THUMB         (1 << 2)
+#define HWCAP_ARM_26BIT         (1 << 3)
+#define HWCAP_ARM_FAST_MULT     (1 << 4)
+#define HWCAP_ARM_FPA           (1 << 5)
+#define HWCAP_ARM_VFP           (1 << 6)
+#define HWCAP_ARM_EDSP          (1 << 7)
+#define HWCAP_ARM_JAVA          (1 << 8)
+#define HWCAP_ARM_IWMMXT        (1 << 9)
+#define HWCAP_ARM_CRUNCH        (1 << 10)
+#define HWCAP_ARM_THUMBEE       (1 << 11)
+#define HWCAP_ARM_NEON          (1 << 12)
+#define HWCAP_ARM_VFPv3         (1 << 13)
+#define HWCAP_ARM_VFPv3D16      (1 << 14)       /* also set for VFPv4-D16 */
+#define HWCAP_ARM_TLS           (1 << 15)
+#define HWCAP_ARM_VFPv4         (1 << 16)
+#define HWCAP_ARM_IDIVA         (1 << 17)
+#define HWCAP_ARM_IDIVT         (1 << 18)
+#define HWCAP_IDIV              (HWCAP_IDIVA | HWCAP_IDIVT)
+#define HWCAP_VFPD32            (1 << 19)       /* set if VFP has 32 regs */
+#define HWCAP_LPAE              (1 << 20)
+
+/* Bits present in AT_HWCAP for PowerPC.  */
+
+#define PPC_FEATURE_32                  0x80000000
+#define PPC_FEATURE_64                  0x40000000
+#define PPC_FEATURE_601_INSTR           0x20000000
+#define PPC_FEATURE_HAS_ALTIVEC         0x10000000
+#define PPC_FEATURE_HAS_FPU             0x08000000
+#define PPC_FEATURE_HAS_MMU             0x04000000
+#define PPC_FEATURE_HAS_4xxMAC          0x02000000
+#define PPC_FEATURE_UNIFIED_CACHE       0x01000000
+#define PPC_FEATURE_HAS_SPE             0x00800000
+#define PPC_FEATURE_HAS_EFP_SINGLE      0x00400000
+#define PPC_FEATURE_HAS_EFP_DOUBLE      0x00200000
+#define PPC_FEATURE_NO_TB               0x00100000
+#define PPC_FEATURE_POWER4              0x00080000
+#define PPC_FEATURE_POWER5              0x00040000
+#define PPC_FEATURE_POWER5_PLUS         0x00020000
+#define PPC_FEATURE_CELL                0x00010000
+#define PPC_FEATURE_BOOKE               0x00008000
+#define PPC_FEATURE_SMT                 0x00004000
+#define PPC_FEATURE_ICACHE_SNOOP        0x00002000
+#define PPC_FEATURE_ARCH_2_05           0x00001000
+#define PPC_FEATURE_PA6T                0x00000800
+#define PPC_FEATURE_HAS_DFP             0x00000400
+#define PPC_FEATURE_POWER6_EXT          0x00000200
+#define PPC_FEATURE_ARCH_2_06           0x00000100
+#define PPC_FEATURE_HAS_VSX             0x00000080
+
+#define PPC_FEATURE_PSERIES_PERFMON_COMPAT \
+                                        0x00000040
+
+#define PPC_FEATURE_TRUE_LE             0x00000002
+#define PPC_FEATURE_PPC_LE              0x00000001
+
 /* Bits present in AT_HWCAP, primarily for Sparc32.  */
 
 #define HWCAP_SPARC_FLUSH       1    /* CPU supports flush instruction. */
@@ -420,6 +479,20 @@ typedef struct {
 #define HWCAP_SPARC_V9		16
 #define HWCAP_SPARC_ULTRA3	32
 
+/* Bits present in AT_HWCAP for s390.  */
+
+#define HWCAP_S390_ESAN3        1
+#define HWCAP_S390_ZARCH        2
+#define HWCAP_S390_STFLE        4
+#define HWCAP_S390_MSA          8
+#define HWCAP_S390_LDISP        16
+#define HWCAP_S390_EIMM         32
+#define HWCAP_S390_DFP          64
+#define HWCAP_S390_HPAGE        128
+#define HWCAP_S390_ETF3EH       256
+#define HWCAP_S390_HIGH_GPRS    512
+#define HWCAP_S390_TE           1024
+
 /*
  * 68k ELF relocation types
  */
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index f3927e2419..2365274daa 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -302,6 +302,8 @@ int float32_compare( float32, float32 STATUS_PARAM );
 int float32_compare_quiet( float32, float32 STATUS_PARAM );
 float32 float32_min(float32, float32 STATUS_PARAM);
 float32 float32_max(float32, float32 STATUS_PARAM);
+float32 float32_minnum(float32, float32 STATUS_PARAM);
+float32 float32_maxnum(float32, float32 STATUS_PARAM);
 int float32_is_quiet_nan( float32 );
 int float32_is_signaling_nan( float32 );
 float32 float32_maybe_silence_nan( float32 );
@@ -408,6 +410,8 @@ int float64_compare( float64, float64 STATUS_PARAM );
 int float64_compare_quiet( float64, float64 STATUS_PARAM );
 float64 float64_min(float64, float64 STATUS_PARAM);
 float64 float64_max(float64, float64 STATUS_PARAM);
+float64 float64_minnum(float64, float64 STATUS_PARAM);
+float64 float64_maxnum(float64, float64 STATUS_PARAM);
 int float64_is_quiet_nan( float64 a );
 int float64_is_signaling_nan( float64 );
 float64 float64_maybe_silence_nan( float64 );
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index ecbbba871e..cbbf4ca4cb 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -50,6 +50,13 @@ struct arm_boot_info {
                                  const struct arm_boot_info *info);
     void (*secondary_cpu_reset_hook)(ARMCPU *cpu,
                                      const struct arm_boot_info *info);
+    /* if a board is able to create a dtb without a dtb file then it
+     * sets get_dtb. This will only be used if no dtb file is provided
+     * by the user. On success, sets *size to the length of the created
+     * dtb, and returns a pointer to it. (The caller must free this memory
+     * with g_free() when it has finished with it.) On failure, returns NULL.
+     */
+    void *(*get_dtb)(const struct arm_boot_info *info, int *size);
     /* if a board needs to be able to modify a device tree provided by
      * the user it should implement this hook.
      */
diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h
index 85f58acd51..f431764bf5 100644
--- a/include/hw/char/serial.h
+++ b/include/hw/char/serial.h
@@ -65,13 +65,13 @@ struct SerialState {
     /* Interrupt trigger level for recv_fifo */
     uint8_t recv_fifo_itl;
 
-    struct QEMUTimer *fifo_timeout_timer;
+    QEMUTimer *fifo_timeout_timer;
     int timeout_ipending;           /* timeout interrupt pending state */
 
     uint64_t char_transmit_time;    /* time to transmit a char in ticks */
     int poll_msl;
 
-    struct QEMUTimer *modem_status_poll;
+    QEMUTimer *modem_status_poll;
     MemoryRegion io;
 };
 
diff --git a/include/hw/cpu/a9mpcore.h b/include/hw/cpu/a9mpcore.h
index 010489b98e..5d67ca22c4 100644
--- a/include/hw/cpu/a9mpcore.h
+++ b/include/hw/cpu/a9mpcore.h
@@ -14,6 +14,7 @@
 #include "hw/intc/arm_gic.h"
 #include "hw/misc/a9scu.h"
 #include "hw/timer/arm_mptimer.h"
+#include "hw/timer/a9gtimer.h"
 
 #define TYPE_A9MPCORE_PRIV "a9mpcore_priv"
 #define A9MPCORE_PRIV(obj) \
@@ -28,8 +29,9 @@ typedef struct A9MPPrivState {
     MemoryRegion container;
     uint32_t num_irq;
 
-    GICState gic;
     A9SCUState scu;
+    GICState gic;
+    A9GTimerState gtimer;
     ARMMPTimerState mptimer;
     ARMMPTimerState wdt;
 } A9MPPrivState;
diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h
index 4c0002beca..e597070ab8 100644
--- a/include/hw/pci/pci_ids.h
+++ b/include/hw/pci/pci_ids.h
@@ -146,7 +146,6 @@
 
 #define PCI_VENDOR_ID_XEN                0x5853
 #define PCI_DEVICE_ID_XEN_PLATFORM       0x0001
-#define PCI_DEVICE_ID_XEN_PVDEVICE       0x0002
 
 #define PCI_VENDOR_ID_NEC                0x1033
 #define PCI_DEVICE_ID_NEC_UPD720200      0x0194
diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h
index 132ab97b58..835418aeb0 100644
--- a/include/hw/ppc/ppc.h
+++ b/include/hw/ppc/ppc.h
@@ -24,10 +24,10 @@ struct ppc_tb_t {
     /* Decrementer management */
     uint64_t decr_next;    /* Tick for next decr interrupt    */
     uint32_t decr_freq;    /* decrementer frequency           */
-    struct QEMUTimer *decr_timer;
+    QEMUTimer *decr_timer;
     /* Hypervisor decrementer management */
     uint64_t hdecr_next;    /* Tick for next hdecr interrupt  */
-    struct QEMUTimer *hdecr_timer;
+    QEMUTimer *hdecr_timer;
     uint64_t purr_load;
     uint64_t purr_start;
     void *opaque;
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
index 76f6ac24a7..bf6da3d632 100644
--- a/include/hw/scsi/scsi.h
+++ b/include/hw/scsi/scsi.h
@@ -199,12 +199,16 @@ extern const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED;
 extern const struct SCSISense sense_code_INCOMPATIBLE_FORMAT;
 /* Illegal request, medium removal prevented */
 extern const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED;
+/* Illegal request, Invalid Transfer Tag */
+extern const struct SCSISense sense_code_INVALID_TAG;
 /* Command aborted, I/O process terminated */
 extern const struct SCSISense sense_code_IO_ERROR;
 /* Command aborted, I_T Nexus loss occurred */
 extern const struct SCSISense sense_code_I_T_NEXUS_LOSS;
 /* Command aborted, Logical Unit failure */
 extern const struct SCSISense sense_code_LUN_FAILURE;
+/* Command aborted, Overlapped Commands Attempted */
+extern const struct SCSISense sense_code_OVERLAPPED_COMMANDS;
 /* LUN not ready, Capacity data has changed */
 extern const struct SCSISense sense_code_CAPACITY_CHANGED;
 /* LUN not ready, Medium not present */
diff --git a/include/hw/timer/a9gtimer.h b/include/hw/timer/a9gtimer.h
new file mode 100644
index 0000000000..b88c02a6ef
--- /dev/null
+++ b/include/hw/timer/a9gtimer.h
@@ -0,0 +1,97 @@
+/*
+ * Global peripheral timer block for ARM A9MP
+ *
+ * (C) 2013 Xilinx Inc.
+ *
+ * Written by François LEGAL
+ * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_TIMER_A9_GTIMER_H_H
+#define HW_TIMER_A9_GTIMER_H_H
+
+#include "hw/sysbus.h"
+
+#define A9_GTIMER_MAX_CPUS 4
+
+#define TYPE_A9_GTIMER "arm.cortex-a9-global-timer"
+#define A9_GTIMER(obj) OBJECT_CHECK(A9GTimerState, (obj), TYPE_A9_GTIMER)
+
+#define R_COUNTER_LO                0x00
+#define R_COUNTER_HI                0x04
+
+#define R_CONTROL                   0x08
+#define R_CONTROL_TIMER_ENABLE      (1 << 0)
+#define R_CONTROL_COMP_ENABLE       (1 << 1)
+#define R_CONTROL_IRQ_ENABLE        (1 << 2)
+#define R_CONTROL_AUTO_INCREMENT    (1 << 2)
+#define R_CONTROL_PRESCALER_SHIFT   8
+#define R_CONTROL_PRESCALER_LEN     8
+#define R_CONTROL_PRESCALER_MASK    (((1 << R_CONTROL_PRESCALER_LEN) - 1) << \
+                                     R_CONTROL_PRESCALER_SHIFT)
+
+#define R_CONTROL_BANKED            (R_CONTROL_COMP_ENABLE | \
+                                     R_CONTROL_IRQ_ENABLE | \
+                                     R_CONTROL_AUTO_INCREMENT)
+#define R_CONTROL_NEEDS_SYNC        (R_CONTROL_TIMER_ENABLE | \
+                                     R_CONTROL_PRESCALER_MASK)
+
+#define R_INTERRUPT_STATUS          0x0C
+#define R_COMPARATOR_LO             0x10
+#define R_COMPARATOR_HI             0x14
+#define R_AUTO_INCREMENT            0x18
+
+typedef struct A9GTimerPerCPU A9GTimerPerCPU;
+typedef struct A9GTimerState A9GTimerState;
+
+struct A9GTimerPerCPU {
+    A9GTimerState *parent;
+
+    uint32_t control; /* only per cpu banked bits valid */
+    uint64_t compare;
+    uint32_t status;
+    uint32_t inc;
+
+    MemoryRegion iomem;
+    qemu_irq irq; /* PPI interrupts */
+};
+
+struct A9GTimerState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    MemoryRegion iomem;
+    /* static props */
+    uint32_t num_cpu;
+
+    QEMUTimer *timer;
+
+    uint64_t counter; /* current timer value */
+
+    uint64_t ref_counter;
+    uint64_t cpu_ref_time; /* the cpu time as of last update of ref_counter */
+    uint32_t control; /* only non per cpu banked bits valid */
+
+    A9GTimerPerCPU per_cpu[A9_GTIMER_MAX_CPUS];
+};
+
+typedef struct A9GTimerUpdate {
+    uint64_t now;
+    uint64_t new;
+} A9GTimerUpdate;
+
+#endif /* #ifdef HW_TIMER_A9_GTIMER_H_H */
diff --git a/include/hw/usb.h b/include/hw/usb.h
index a7680d4e8a..2a3ea0c92e 100644
--- a/include/hw/usb.h
+++ b/include/hw/usb.h
@@ -102,17 +102,26 @@
 
 #define DeviceRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
 #define DeviceOutRequest ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
-#define InterfaceRequest \
+#define VendorDeviceRequest ((USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8)
+#define VendorDeviceOutRequest \
+        ((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8)
+
+#define InterfaceRequest                                        \
         ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
 #define InterfaceOutRequest \
         ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
-#define EndpointRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8)
-#define EndpointOutRequest \
-        ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8)
 #define ClassInterfaceRequest \
         ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8)
 #define ClassInterfaceOutRequest \
         ((USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8)
+#define VendorInterfaceRequest \
+        ((USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_INTERFACE)<<8)
+#define VendorInterfaceOutRequest \
+        ((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE)<<8)
+
+#define EndpointRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8)
+#define EndpointOutRequest \
+        ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8)
 
 #define USB_REQ_GET_STATUS		0x00
 #define USB_REQ_CLEAR_FEATURE		0x01
@@ -189,6 +198,7 @@ struct USBEndpoint {
     uint8_t type;
     uint8_t ifnum;
     int max_packet_size;
+    int max_streams;
     bool pipeline;
     bool halted;
     USBDevice *dev;
@@ -314,6 +324,14 @@ typedef struct USBDeviceClass {
      */
     void (*ep_stopped)(USBDevice *dev, USBEndpoint *ep);
 
+    /*
+     * Called by the hcd to alloc / free streams on a bulk endpoint.
+     * Optional may be NULL.
+     */
+    int (*alloc_streams)(USBDevice *dev, USBEndpoint **eps, int nr_eps,
+                         int streams);
+    void (*free_streams)(USBDevice *dev, USBEndpoint **eps, int nr_eps);
+
     const char *product_desc;
     const USBDesc *usb_desc;
 } USBDeviceClass;
@@ -421,6 +439,8 @@ void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum);
 void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep,
                                 uint16_t raw);
 int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep);
+void usb_ep_set_max_streams(USBDevice *dev, int pid, int ep, uint8_t raw);
+int usb_ep_get_max_streams(USBDevice *dev, int pid, int ep);
 void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled);
 void usb_ep_set_halted(USBDevice *dev, int pid, int ep, bool halted);
 USBPacket *usb_ep_find_packet_by_id(USBDevice *dev, int pid, int ep,
@@ -550,6 +570,10 @@ void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep);
 
 void usb_device_ep_stopped(USBDevice *dev, USBEndpoint *ep);
 
+int usb_device_alloc_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps,
+                             int streams);
+void usb_device_free_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps);
+
 const char *usb_device_get_product_desc(USBDevice *dev);
 
 const USBDesc *usb_device_get_usb_desc(USBDevice *dev);
diff --git a/include/qemu/cache-utils.h b/include/qemu/cache-utils.h
index 2c57f78fc1..211245bea0 100644
--- a/include/qemu/cache-utils.h
+++ b/include/qemu/cache-utils.h
@@ -12,7 +12,7 @@ struct qemu_cache_conf {
 
 extern struct qemu_cache_conf qemu_cache_conf;
 
-void qemu_cache_utils_init(char **envp);
+void qemu_cache_utils_init(void);
 
 /* mildly adjusted code from tcg-dyngen.c */
 static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
@@ -38,7 +38,7 @@ static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
 }
 
 #else
-#define qemu_cache_utils_init(envp) do { (void) (envp); } while (0)
+#define qemu_cache_utils_init() do { } while (0)
 #endif
 
 #endif /* QEMU_CACHE_UTILS_H */
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index 26136f16ec..b3e2b6d8ea 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -215,4 +215,29 @@ bool fips_get_state(void);
  */
 char *qemu_get_local_state_pathname(const char *relative_pathname);
 
+/**
+ * qemu_getauxval:
+ * @type: the auxiliary vector key to lookup
+ *
+ * Search the auxiliary vector for @type, returning the value
+ * or 0 if @type is not present.
+ */
+#if defined(CONFIG_GETAUXVAL) || defined(__linux__)
+unsigned long qemu_getauxval(unsigned long type);
+#else
+static inline unsigned long qemu_getauxval(unsigned long type) { return 0; }
+#endif
+
+/**
+ * qemu_init_auxval:
+ * @envp: the third argument to main
+ *
+ * If supported and required, locate the auxiliary vector at program startup.
+ */
+#if defined(CONFIG_GETAUXVAL) || !defined(__linux__)
+static inline void qemu_init_auxval(char **envp) { }
+#else
+void qemu_init_auxval(char **envp);
+#endif
+
 #endif
diff --git a/include/ui/console.h b/include/ui/console.h
index 98edf413a6..4156a876e1 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -6,7 +6,6 @@
 #include "qapi/qmp/qdict.h"
 #include "qemu/notify.h"
 #include "monitor/monitor.h"
-#include "trace.h"
 #include "qapi-types.h"
 #include "qapi/error.h"
 
diff --git a/kvm-all.c b/kvm-all.c
index 4478969ed2..393775459d 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -72,7 +72,8 @@ typedef struct kvm_dirty_log KVMDirtyLog;
 
 struct KVMState
 {
-    KVMSlot slots[32];
+    KVMSlot *slots;
+    int nr_slots;
     int fd;
     int vmfd;
     int coalesced_mmio;
@@ -125,7 +126,7 @@ static KVMSlot *kvm_alloc_slot(KVMState *s)
 {
     int i;
 
-    for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
+    for (i = 0; i < s->nr_slots; i++) {
         if (s->slots[i].memory_size == 0) {
             return &s->slots[i];
         }
@@ -141,7 +142,7 @@ static KVMSlot *kvm_lookup_matching_slot(KVMState *s,
 {
     int i;
 
-    for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
+    for (i = 0; i < s->nr_slots; i++) {
         KVMSlot *mem = &s->slots[i];
 
         if (start_addr == mem->start_addr &&
@@ -163,7 +164,7 @@ static KVMSlot *kvm_lookup_overlapping_slot(KVMState *s,
     KVMSlot *found = NULL;
     int i;
 
-    for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
+    for (i = 0; i < s->nr_slots; i++) {
         KVMSlot *mem = &s->slots[i];
 
         if (mem->memory_size == 0 ||
@@ -185,7 +186,7 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram,
 {
     int i;
 
-    for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
+    for (i = 0; i < s->nr_slots; i++) {
         KVMSlot *mem = &s->slots[i];
 
         if (ram >= mem->ram && ram < mem->ram + mem->memory_size) {
@@ -357,7 +358,7 @@ static int kvm_set_migration_log(int enable)
 
     s->migration_log = enable;
 
-    for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
+    for (i = 0; i < s->nr_slots; i++) {
         mem = &s->slots[i];
 
         if (!mem->memory_size) {
@@ -1383,9 +1384,6 @@ int kvm_init(void)
 #ifdef KVM_CAP_SET_GUEST_DEBUG
     QTAILQ_INIT(&s->kvm_sw_breakpoints);
 #endif
-    for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
-        s->slots[i].slot = i;
-    }
     s->vmfd = -1;
     s->fd = qemu_open("/dev/kvm", O_RDWR);
     if (s->fd == -1) {
@@ -1409,6 +1407,19 @@ int kvm_init(void)
         goto err;
     }
 
+    s->nr_slots = kvm_check_extension(s, KVM_CAP_NR_MEMSLOTS);
+
+    /* If unspecified, use the default value */
+    if (!s->nr_slots) {
+        s->nr_slots = 32;
+    }
+
+    s->slots = g_malloc0(s->nr_slots * sizeof(KVMSlot));
+
+    for (i = 0; i < s->nr_slots; i++) {
+        s->slots[i].slot = i;
+    }
+
     /* check the vcpu limits */
     soft_vcpus_limit = kvm_recommended_vcpus(s);
     hard_vcpus_limit = kvm_max_vcpus(s);
@@ -1527,6 +1538,7 @@ err:
     if (s->fd != -1) {
         close(s->fd);
     }
+    g_free(s->slots);
     g_free(s);
 
     return ret;
diff --git a/libcacard/cac.c b/libcacard/cac.c
index 7a06b5a31b..74ef3e3cec 100644
--- a/libcacard/cac.c
+++ b/libcacard/cac.c
@@ -189,7 +189,6 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
             pki_applet->sign_buffer = sign_buffer;
             pki_applet->sign_buffer_len = size;
             *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
-            ret = VCARD_DONE;
             break;
         case 0x00:
             /* we now have the whole buffer, do the operation, result will be
diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index fb429b1f82..ee2dfaee82 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -934,7 +934,6 @@ vcard_emul_init(const VCardEmulOptions *options)
         vreader = vreader_new(options->vreader[i].vname, vreader_emul,
                               vreader_emul_delete);
         vreader_add_reader(vreader);
-        cert_count = options->vreader[i].cert_count;
 
         vcard_emul_alloc_arrays(&certs, &cert_len, &keys,
                                 options->vreader[i].cert_count);
diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
index a3cb7762b5..f1d46d397a 100644
--- a/libcacard/vscclient.c
+++ b/libcacard/vscclient.c
@@ -407,7 +407,7 @@ do_socket_read(GIOChannel *source,
             }
             break;
         default:
-            g_warn_if_reached();
+            g_assert_not_reached();
             return FALSE;
         }
 
@@ -760,7 +760,7 @@ main(
 
     g_io_channel_unref(channel_stdin);
     g_io_channel_unref(channel_socket);
-    g_byte_array_unref(socket_to_send);
+    g_byte_array_free(socket_to_send, TRUE);
 
     closesocket(sock);
     return 0;
diff --git a/linux-headers/asm-arm/kvm.h b/linux-headers/asm-arm/kvm.h
index c1ee007523..c498b60c05 100644
--- a/linux-headers/asm-arm/kvm.h
+++ b/linux-headers/asm-arm/kvm.h
@@ -63,7 +63,8 @@ struct kvm_regs {
 
 /* Supported Processor Types */
 #define KVM_ARM_TARGET_CORTEX_A15	0
-#define KVM_ARM_NUM_TARGETS		1
+#define KVM_ARM_TARGET_CORTEX_A7	1
+#define KVM_ARM_NUM_TARGETS		2
 
 /* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
 #define KVM_ARM_DEVICE_TYPE_SHIFT	0
diff --git a/linux-headers/asm-powerpc/epapr_hcalls.h b/linux-headers/asm-powerpc/epapr_hcalls.h
index 33b3f89f55..06f724786a 100644
--- a/linux-headers/asm-powerpc/epapr_hcalls.h
+++ b/linux-headers/asm-powerpc/epapr_hcalls.h
@@ -78,7 +78,7 @@
 #define EV_SUCCESS		0
 #define EV_EPERM		1	/* Operation not permitted */
 #define EV_ENOENT		2	/*  Entry Not Found */
-#define EV_EIO			3	/* I/O error occurred */
+#define EV_EIO			3	/* I/O error occured */
 #define EV_EAGAIN		4	/* The operation had insufficient
 					 * resources to complete and should be
 					 * retried
@@ -89,7 +89,7 @@
 #define EV_ENODEV		7	/* No such device */
 #define EV_EINVAL		8	/* An argument supplied to the hcall
 					   was out of range or invalid */
-#define EV_INTERNAL		9	/* An internal error occurred */
+#define EV_INTERNAL		9	/* An internal error occured */
 #define EV_CONFIG		10	/* A configuration error was detected */
 #define EV_INVALID_STATE	11	/* The object is in an invalid state */
 #define EV_UNIMPLEMENTED	12	/* Unimplemented hypercall */
diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index 0fb1a6e9ff..6836ec79a8 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -27,6 +27,7 @@
 #define __KVM_HAVE_PPC_SMT
 #define __KVM_HAVE_IRQCHIP
 #define __KVM_HAVE_IRQ_LINE
+#define __KVM_HAVE_GUEST_DEBUG
 
 struct kvm_regs {
 	__u64 pc;
@@ -269,7 +270,24 @@ struct kvm_fpu {
 	__u64 fpr[32];
 };
 
+/*
+ * Defines for h/w breakpoint, watchpoint (read, write or both) and
+ * software breakpoint.
+ * These are used as "type" in KVM_SET_GUEST_DEBUG ioctl and "status"
+ * for KVM_DEBUG_EXIT.
+ */
+#define KVMPPC_DEBUG_NONE		0x0
+#define KVMPPC_DEBUG_BREAKPOINT		(1UL << 1)
+#define KVMPPC_DEBUG_WATCH_WRITE	(1UL << 2)
+#define KVMPPC_DEBUG_WATCH_READ		(1UL << 3)
 struct kvm_debug_exit_arch {
+	__u64 address;
+	/*
+	 * exiting to userspace because of h/w breakpoint, watchpoint
+	 * (read, write or both) and software breakpoint.
+	 */
+	__u32 status;
+	__u32 reserved;
 };
 
 /* for KVM_SET_GUEST_DEBUG */
@@ -281,10 +299,6 @@ struct kvm_guest_debug_arch {
 		 * Type denotes h/w breakpoint, read watchpoint, write
 		 * watchpoint or watchpoint (both read and write).
 		 */
-#define KVMPPC_DEBUG_NONE		0x0
-#define KVMPPC_DEBUG_BREAKPOINT		(1UL << 1)
-#define KVMPPC_DEBUG_WATCH_WRITE	(1UL << 2)
-#define KVMPPC_DEBUG_WATCH_READ		(1UL << 3)
 		__u32 type;
 		__u32 reserved;
 	} bp[16];
@@ -429,6 +443,11 @@ struct kvm_get_htab_header {
 #define KVM_REG_PPC_MMCR0	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x10)
 #define KVM_REG_PPC_MMCR1	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x11)
 #define KVM_REG_PPC_MMCRA	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x12)
+#define KVM_REG_PPC_MMCR2	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x13)
+#define KVM_REG_PPC_MMCRS	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x14)
+#define KVM_REG_PPC_SIAR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x15)
+#define KVM_REG_PPC_SDAR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x16)
+#define KVM_REG_PPC_SIER	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x17)
 
 #define KVM_REG_PPC_PMC1	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x18)
 #define KVM_REG_PPC_PMC2	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x19)
@@ -499,6 +518,65 @@ struct kvm_get_htab_header {
 #define KVM_REG_PPC_TLB3PS	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9a)
 #define KVM_REG_PPC_EPTCFG	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9b)
 
+/* Timebase offset */
+#define KVM_REG_PPC_TB_OFFSET	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x9c)
+
+/* POWER8 registers */
+#define KVM_REG_PPC_SPMC1	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9d)
+#define KVM_REG_PPC_SPMC2	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9e)
+#define KVM_REG_PPC_IAMR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x9f)
+#define KVM_REG_PPC_TFHAR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa0)
+#define KVM_REG_PPC_TFIAR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa1)
+#define KVM_REG_PPC_TEXASR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa2)
+#define KVM_REG_PPC_FSCR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa3)
+#define KVM_REG_PPC_PSPB	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xa4)
+#define KVM_REG_PPC_EBBHR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa5)
+#define KVM_REG_PPC_EBBRR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa6)
+#define KVM_REG_PPC_BESCR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa7)
+#define KVM_REG_PPC_TAR		(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa8)
+#define KVM_REG_PPC_DPDES	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa9)
+#define KVM_REG_PPC_DAWR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xaa)
+#define KVM_REG_PPC_DAWRX	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xab)
+#define KVM_REG_PPC_CIABR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xac)
+#define KVM_REG_PPC_IC		(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xad)
+#define KVM_REG_PPC_VTB		(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xae)
+#define KVM_REG_PPC_CSIGR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xaf)
+#define KVM_REG_PPC_TACR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb0)
+#define KVM_REG_PPC_TCSCR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb1)
+#define KVM_REG_PPC_PID		(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb2)
+#define KVM_REG_PPC_ACOP	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb3)
+
+#define KVM_REG_PPC_VRSAVE	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb4)
+#define KVM_REG_PPC_LPCR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb5)
+#define KVM_REG_PPC_PPR		(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb6)
+
+/* Architecture compatibility level */
+#define KVM_REG_PPC_ARCH_COMPAT	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb7)
+
+/* Transactional Memory checkpointed state:
+ * This is all GPRs, all VSX regs and a subset of SPRs
+ */
+#define KVM_REG_PPC_TM		(KVM_REG_PPC | 0x80000000)
+/* TM GPRs */
+#define KVM_REG_PPC_TM_GPR0	(KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0)
+#define KVM_REG_PPC_TM_GPR(n)	(KVM_REG_PPC_TM_GPR0 + (n))
+#define KVM_REG_PPC_TM_GPR31	(KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x1f)
+/* TM VSX */
+#define KVM_REG_PPC_TM_VSR0	(KVM_REG_PPC_TM | KVM_REG_SIZE_U128 | 0x20)
+#define KVM_REG_PPC_TM_VSR(n)	(KVM_REG_PPC_TM_VSR0 + (n))
+#define KVM_REG_PPC_TM_VSR63	(KVM_REG_PPC_TM | KVM_REG_SIZE_U128 | 0x5f)
+/* TM SPRS */
+#define KVM_REG_PPC_TM_CR	(KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x60)
+#define KVM_REG_PPC_TM_LR	(KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x61)
+#define KVM_REG_PPC_TM_CTR	(KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x62)
+#define KVM_REG_PPC_TM_FPSCR	(KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x63)
+#define KVM_REG_PPC_TM_AMR	(KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x64)
+#define KVM_REG_PPC_TM_PPR	(KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x65)
+#define KVM_REG_PPC_TM_VRSAVE	(KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x66)
+#define KVM_REG_PPC_TM_VSCR	(KVM_REG_PPC_TM | KVM_REG_SIZE_U32 | 0x67)
+#define KVM_REG_PPC_TM_DSCR	(KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x68)
+#define KVM_REG_PPC_TM_TAR	(KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x69)
+
 /* PPC64 eXternal Interrupt Controller Specification */
 #define KVM_DEV_XICS_GRP_SOURCES	1	/* 64-bit source attributes */
 
diff --git a/linux-headers/asm-x86/hyperv.h b/linux-headers/asm-x86/hyperv.h
index b80420bcd0..b8f1c0176c 100644
--- a/linux-headers/asm-x86/hyperv.h
+++ b/linux-headers/asm-x86/hyperv.h
@@ -27,6 +27,19 @@
 #define HV_X64_MSR_VP_RUNTIME_AVAILABLE		(1 << 0)
 /* Partition Reference Counter (HV_X64_MSR_TIME_REF_COUNT) available*/
 #define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE	(1 << 1)
+
+/*
+ * There is a single feature flag that signifies the presence of the MSR
+ * that can be used to retrieve both the local APIC Timer frequency as
+ * well as the TSC frequency.
+ */
+
+/* Local APIC timer frequency MSR (HV_X64_MSR_APIC_FREQUENCY) is available */
+#define HV_X64_MSR_APIC_FREQUENCY_AVAILABLE (1 << 11)
+
+/* TSC frequency MSR (HV_X64_MSR_TSC_FREQUENCY) is available */
+#define HV_X64_MSR_TSC_FREQUENCY_AVAILABLE (1 << 11)
+
 /*
  * Basic SynIC MSRs (HV_X64_MSR_SCONTROL through HV_X64_MSR_EOM
  * and HV_X64_MSR_SINT0 through HV_X64_MSR_SINT15) available
@@ -136,6 +149,12 @@
 /* MSR used to read the per-partition time reference counter */
 #define HV_X64_MSR_TIME_REF_COUNT		0x40000020
 
+/* MSR used to retrieve the TSC frequency */
+#define HV_X64_MSR_TSC_FREQUENCY		0x40000022
+
+/* MSR used to retrieve the local APIC timer frequency */
+#define HV_X64_MSR_APIC_FREQUENCY		0x40000023
+
 /* Define the virtual APIC registers */
 #define HV_X64_MSR_EOI				0x40000070
 #define HV_X64_MSR_ICR				0x40000071
diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h
index 5d9a3033b3..d3a87780c7 100644
--- a/linux-headers/asm-x86/kvm.h
+++ b/linux-headers/asm-x86/kvm.h
@@ -211,9 +211,9 @@ struct kvm_cpuid_entry2 {
 	__u32 padding[3];
 };
 
-#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX 1
-#define KVM_CPUID_FLAG_STATEFUL_FUNC    2
-#define KVM_CPUID_FLAG_STATE_READ_NEXT  4
+#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX		BIT(0)
+#define KVM_CPUID_FLAG_STATEFUL_FUNC		BIT(1)
+#define KVM_CPUID_FLAG_STATE_READ_NEXT		BIT(2)
 
 /* for KVM_SET_CPUID2 */
 struct kvm_cpuid2 {
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 13e890c53b..5a49671845 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -518,6 +518,10 @@ struct kvm_ppc_smmu_info {
 /* machine type bits, to be used as argument to KVM_CREATE_VM */
 #define KVM_VM_S390_UCONTROL	1
 
+/* on ppc, 0 indicate default, 1 should force HV and 2 PR */
+#define KVM_VM_PPC_HV 1
+#define KVM_VM_PPC_PR 2
+
 #define KVM_S390_SIE_PAGE_OFFSET 1
 
 /*
@@ -541,6 +545,7 @@ struct kvm_ppc_smmu_info {
 #define KVM_TRACE_ENABLE          __KVM_DEPRECATED_MAIN_W_0x06
 #define KVM_TRACE_PAUSE           __KVM_DEPRECATED_MAIN_0x07
 #define KVM_TRACE_DISABLE         __KVM_DEPRECATED_MAIN_0x08
+#define KVM_GET_EMULATED_CPUID	  _IOWR(KVMIO, 0x09, struct kvm_cpuid2)
 
 /*
  * Extension capability list.
@@ -668,6 +673,7 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_IRQ_XICS 92
 #define KVM_CAP_ARM_EL1_32BIT 93
 #define KVM_CAP_SPAPR_MULTITCE 94
+#define KVM_CAP_EXT_EMUL_CPUID 95
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -843,6 +849,10 @@ struct kvm_device_attr {
 #define KVM_DEV_TYPE_FSL_MPIC_20	1
 #define KVM_DEV_TYPE_FSL_MPIC_42	2
 #define KVM_DEV_TYPE_XICS		3
+#define KVM_DEV_TYPE_VFIO		4
+#define  KVM_DEV_VFIO_GROUP			1
+#define   KVM_DEV_VFIO_GROUP_ADD			1
+#define   KVM_DEV_VFIO_GROUP_DEL			2
 
 /*
  * ioctls for VM fds
@@ -1012,6 +1022,7 @@ struct kvm_s390_ucas_mapping {
 /* VM is being stopped by host */
 #define KVM_KVMCLOCK_CTRL	  _IO(KVMIO,   0xad)
 #define KVM_ARM_VCPU_INIT	  _IOW(KVMIO,  0xae, struct kvm_vcpu_init)
+#define KVM_ARM_PREFERRED_TARGET  _IOR(KVMIO,  0xaf, struct kvm_vcpu_init)
 #define KVM_GET_REG_LIST	  _IOWR(KVMIO, 0xb0, struct kvm_reg_list)
 
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU	(1 << 0)
diff --git a/linux-user/aarch64/target_structs.h b/linux-user/aarch64/target_structs.h
new file mode 100644
index 0000000000..21c1f2c074
--- /dev/null
+++ b/linux-user/aarch64/target_structs.h
@@ -0,0 +1,58 @@
+/*
+ * ARM AArch64 specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_STRUCTS_H
+#define TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+    abi_int __key;                      /* Key.  */
+    abi_uint uid;                       /* Owner's user ID.  */
+    abi_uint gid;                       /* Owner's group ID.  */
+    abi_uint cuid;                      /* Creator's user ID.  */
+    abi_uint cgid;                      /* Creator's group ID.  */
+    abi_ushort mode;                    /* Read/write permission.  */
+    abi_ushort __pad1;
+    abi_ushort __seq;                   /* Sequence number.  */
+    abi_ushort __pad2;
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+struct target_shmid_ds {
+    struct target_ipc_perm shm_perm;    /* operation permission struct */
+    abi_long shm_segsz;                 /* size of segment in bytes */
+    abi_ulong shm_atime;                /* time of last shmat() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused1;
+#endif
+    abi_ulong shm_dtime;                /* time of last shmdt() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused2;
+#endif
+    abi_ulong shm_ctime;                /* time of last change by shmctl() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused3;
+#endif
+    abi_int shm_cpid;                   /* pid of creator */
+    abi_int shm_lpid;                   /* pid of last shmop */
+    abi_ulong shm_nattch;               /* number of current attaches */
+    abi_ulong __unused4;
+    abi_ulong __unused5;
+};
+
+#endif
diff --git a/linux-user/alpha/target_structs.h b/linux-user/alpha/target_structs.h
new file mode 100644
index 0000000000..50e7708ffd
--- /dev/null
+++ b/linux-user/alpha/target_structs.h
@@ -0,0 +1,48 @@
+/*
+ * Alpha specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_STRUCTS_H
+#define TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+    abi_int __key;                      /* Key.  */
+    abi_uint uid;                       /* Owner's user ID.  */
+    abi_uint gid;                       /* Owner's group ID.  */
+    abi_uint cuid;                      /* Creator's user ID.  */
+    abi_uint cgid;                      /* Creator's group ID.  */
+    abi_uint mode;                      /* Read/write permission.  */
+    abi_ushort __seq;                   /* Sequence number.  */
+    abi_ushort __pad1;
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+struct target_shmid_ds {
+    struct target_ipc_perm shm_perm;    /* operation permission struct */
+    abi_long shm_segsz;                 /* size of segment in bytes */
+    abi_ulong shm_atime;                /* time of last shmat() */
+    abi_ulong shm_dtime;                /* time of last shmdt() */
+    abi_ulong shm_ctime;                /* time of last change by shmctl() */
+    abi_int shm_cpid;                   /* pid of creator */
+    abi_int shm_lpid;                   /* pid of last shmop */
+    abi_ulong shm_nattch;               /* number of current attaches */
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+#endif
diff --git a/linux-user/arm/target_structs.h b/linux-user/arm/target_structs.h
new file mode 100644
index 0000000000..f3c85d4e1f
--- /dev/null
+++ b/linux-user/arm/target_structs.h
@@ -0,0 +1,52 @@
+/*
+ * ARM specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_STRUCTS_H
+#define TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+    abi_int __key;                      /* Key.  */
+    abi_uint uid;                       /* Owner's user ID.  */
+    abi_uint gid;                       /* Owner's group ID.  */
+    abi_uint cuid;                      /* Creator's user ID.  */
+    abi_uint cgid;                      /* Creator's group ID.  */
+    abi_ushort mode;                    /* Read/write permission.  */
+    abi_ushort __pad1;
+    abi_ushort __seq;                   /* Sequence number.  */
+    abi_ushort __pad2;
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+struct target_shmid_ds {
+    struct target_ipc_perm shm_perm;    /* operation permission struct */
+    abi_long shm_segsz;                 /* size of segment in bytes */
+    abi_ulong shm_atime;                /* time of last shmat() */
+    abi_ulong __unused1;
+    abi_ulong shm_dtime;                /* time of last shmdt() */
+    abi_ulong __unused2;
+    abi_ulong shm_ctime;                /* time of last change by shmctl() */
+    abi_ulong __unused3;
+    abi_int shm_cpid;                   /* pid of creator */
+    abi_int shm_lpid;                   /* pid of last shmop */
+    abi_ulong shm_nattch;               /* number of current attaches */
+    abi_ulong __unused4;
+    abi_ulong __unused5;
+};
+
+#endif
diff --git a/linux-user/cris/target_structs.h b/linux-user/cris/target_structs.h
new file mode 100644
index 0000000000..e4a1ffb3c1
--- /dev/null
+++ b/linux-user/cris/target_structs.h
@@ -0,0 +1,58 @@
+/*
+ * CRIS specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_STRUCTS_H
+#define TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+    abi_int __key;                      /* Key.  */
+    abi_uint uid;                       /* Owner's user ID.  */
+    abi_uint gid;                       /* Owner's group ID.  */
+    abi_uint cuid;                      /* Creator's user ID.  */
+    abi_uint cgid;                      /* Creator's group ID.  */
+    abi_ushort mode;                    /* Read/write permission.  */
+    abi_ushort __pad1;
+    abi_ushort __seq;                   /* Sequence number.  */
+    abi_ushort __pad2;
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+struct target_shmid_ds {
+    struct target_ipc_perm shm_perm;    /* operation permission struct */
+    abi_long shm_segsz;                 /* size of segment in bytes */
+    abi_ulong shm_atime;                /* time of last shmat() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused1;
+#endif
+    abi_ulong shm_dtime;                /* time of last shmdt() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused2;
+#endif
+    abi_ulong shm_ctime;                /* time of last change by shmctl() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused3;
+#endif
+    abi_int shm_cpid;                   /* pid of creator */
+    abi_int shm_lpid;                   /* pid of last shmop */
+    abi_ulong shm_nattch;               /* number of current attaches */
+    abi_ulong __unused4;
+    abi_ulong __unused5;
+};
+
+#endif
diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index 58f679e072..ceb89bb6ea 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -633,7 +633,7 @@ static int load_flat_file(struct linux_binprm * bprm,
             /* Get the pointer's value.  */
             if (get_user_ual(addr, rp))
                 return -EFAULT;
-            addr = flat_get_addr_from_rp(rp, relval, flags, &persistent);
+            addr = flat_get_addr_from_rp(addr, relval, flags, &persistent);
             if (addr != 0) {
                 /*
                  * Do the relocation.  PIC relocs in the data section are
diff --git a/linux-user/i386/target_structs.h b/linux-user/i386/target_structs.h
new file mode 100644
index 0000000000..65f535e16b
--- /dev/null
+++ b/linux-user/i386/target_structs.h
@@ -0,0 +1,58 @@
+/*
+ * i386 specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_STRUCTS_H
+#define TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+    abi_int __key;                      /* Key.  */
+    abi_uint uid;                       /* Owner's user ID.  */
+    abi_uint gid;                       /* Owner's group ID.  */
+    abi_uint cuid;                      /* Creator's user ID.  */
+    abi_uint cgid;                      /* Creator's group ID.  */
+    abi_ushort mode;                    /* Read/write permission.  */
+    abi_ushort __pad1;
+    abi_ushort __seq;                   /* Sequence number.  */
+    abi_ushort __pad2;
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+struct target_shmid_ds {
+    struct target_ipc_perm shm_perm;    /* operation permission struct */
+    abi_long shm_segsz;                 /* size of segment in bytes */
+    abi_ulong shm_atime;                /* time of last shmat() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused1;
+#endif
+    abi_ulong shm_dtime;                /* time of last shmdt() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused2;
+#endif
+    abi_ulong shm_ctime;                /* time of last change by shmctl() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused3;
+#endif
+    abi_int shm_cpid;                   /* pid of creator */
+    abi_int shm_lpid;                   /* pid of last shmop */
+    abi_ulong shm_nattch;               /* number of current attaches */
+    abi_ulong __unused4;
+    abi_ulong __unused5;
+};
+
+#endif
diff --git a/linux-user/m68k/target_structs.h b/linux-user/m68k/target_structs.h
new file mode 100644
index 0000000000..de257c97de
--- /dev/null
+++ b/linux-user/m68k/target_structs.h
@@ -0,0 +1,58 @@
+/*
+ * m68k specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_STRUCTS_H
+#define TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+    abi_int __key;                      /* Key.  */
+    abi_uint uid;                       /* Owner's user ID.  */
+    abi_uint gid;                       /* Owner's group ID.  */
+    abi_uint cuid;                      /* Creator's user ID.  */
+    abi_uint cgid;                      /* Creator's group ID.  */
+    abi_ushort mode;                    /* Read/write permission.  */
+    abi_ushort __pad1;
+    abi_ushort __seq;                   /* Sequence number.  */
+    abi_ushort __pad2;
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+struct target_shmid_ds {
+    struct target_ipc_perm shm_perm;    /* operation permission struct */
+    abi_long shm_segsz;                 /* size of segment in bytes */
+    abi_ulong shm_atime;                /* time of last shmat() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused1;
+#endif
+    abi_ulong shm_dtime;                /* time of last shmdt() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused2;
+#endif
+    abi_ulong shm_ctime;                /* time of last change by shmctl() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused3;
+#endif
+    abi_int shm_cpid;                   /* pid of creator */
+    abi_int shm_lpid;                   /* pid of last shmop */
+    abi_ulong shm_nattch;               /* number of current attaches */
+    abi_ulong __unused4;
+    abi_ulong __unused5;
+};
+
+#endif
diff --git a/linux-user/main.c b/linux-user/main.c
index 6b4ab0930e..54f71fe8f6 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3663,26 +3663,6 @@ static int parse_args(int argc, char **argv)
     return optind;
 }
 
-static int get_execfd(char **envp)
-{
-    typedef struct {
-        long a_type;
-        long a_val;
-    } auxv_t;
-    auxv_t *auxv;
-
-    while (*envp++ != NULL) {
-        ;
-    }
-
-    for (auxv = (auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) {
-        if (auxv->a_type == AT_EXECFD) {
-            return auxv->a_val;
-        }
-    }
-    return -1;
-}
-
 int main(int argc, char **argv, char **envp)
 {
     struct target_pt_regs regs1, *regs = &regs1;
@@ -3701,7 +3681,8 @@ int main(int argc, char **argv, char **envp)
 
     module_call_init(MODULE_INIT_QOM);
 
-    qemu_cache_utils_init(envp);
+    qemu_init_auxval(envp);
+    qemu_cache_utils_init();
 
     if ((envlist = envlist_create()) == NULL) {
         (void) fprintf(stderr, "Unable to allocate envlist\n");
@@ -3875,13 +3856,13 @@ int main(int argc, char **argv, char **envp)
     env->opaque = ts;
     task_settid(ts);
 
-    execfd = get_execfd(envp);
-    if (execfd < 0) {
+    execfd = qemu_getauxval(AT_EXECFD);
+    if (execfd == 0) {
         execfd = open(filename, O_RDONLY);
-    }
-    if (execfd < 0) {
-        printf("Error while loading %s: %s\n", filename, strerror(-execfd));
-        _exit(1);
+        if (execfd < 0) {
+            printf("Error while loading %s: %s\n", filename, strerror(errno));
+            _exit(1);
+        }
     }
 
     ret = loader_exec(execfd, filename, target_argv, target_environ, regs,
diff --git a/linux-user/microblaze/target_structs.h b/linux-user/microblaze/target_structs.h
new file mode 100644
index 0000000000..325e2f6d4d
--- /dev/null
+++ b/linux-user/microblaze/target_structs.h
@@ -0,0 +1,58 @@
+/*
+ * MicroBlaze specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_STRUCTS_H
+#define TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+    abi_int __key;                      /* Key.  */
+    abi_uint uid;                       /* Owner's user ID.  */
+    abi_uint gid;                       /* Owner's group ID.  */
+    abi_uint cuid;                      /* Creator's user ID.  */
+    abi_uint cgid;                      /* Creator's group ID.  */
+    abi_ushort mode;                    /* Read/write permission.  */
+    abi_ushort __pad1;
+    abi_ushort __seq;                   /* Sequence number.  */
+    abi_ushort __pad2;
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+struct target_shmid_ds {
+    struct target_ipc_perm shm_perm;    /* operation permission struct */
+    abi_long shm_segsz;                 /* size of segment in bytes */
+    abi_ulong shm_atime;                /* time of last shmat() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused1;
+#endif
+    abi_ulong shm_dtime;                /* time of last shmdt() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused2;
+#endif
+    abi_ulong shm_ctime;                /* time of last change by shmctl() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused3;
+#endif
+    abi_int shm_cpid;                   /* pid of creator */
+    abi_int shm_lpid;                   /* pid of last shmop */
+    abi_ulong shm_nattch;               /* number of current attaches */
+    abi_ulong __unused4;
+    abi_ulong __unused5;
+};
+
+#endif
diff --git a/linux-user/mips/target_structs.h b/linux-user/mips/target_structs.h
new file mode 100644
index 0000000000..16021e8a94
--- /dev/null
+++ b/linux-user/mips/target_structs.h
@@ -0,0 +1,48 @@
+/*
+ * MIPS specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_STRUCTS_H
+#define TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+    abi_int __key;                      /* Key.  */
+    abi_uint uid;                       /* Owner's user ID.  */
+    abi_uint gid;                       /* Owner's group ID.  */
+    abi_uint cuid;                      /* Creator's user ID.  */
+    abi_uint cgid;                      /* Creator's group ID.  */
+    abi_uint mode;                      /* Read/write permission.  */
+    abi_ushort __seq;                   /* Sequence number.  */
+    abi_ushort __pad1;
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+struct target_shmid_ds {
+    struct target_ipc_perm shm_perm;    /* operation permission struct */
+    abi_long shm_segsz;                 /* size of segment in bytes */
+    abi_ulong shm_atime;                /* time of last shmat() */
+    abi_ulong shm_dtime;                /* time of last shmdt() */
+    abi_ulong shm_ctime;                /* time of last change by shmctl() */
+    abi_int shm_cpid;                   /* pid of creator */
+    abi_int shm_lpid;                   /* pid of last shmop */
+    abi_ulong shm_nattch;               /* number of current attaches */
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+#endif
diff --git a/linux-user/mips64/target_cpu.h b/linux-user/mips64/target_cpu.h
index fa36407c68..f16991b4ef 100644
--- a/linux-user/mips64/target_cpu.h
+++ b/linux-user/mips64/target_cpu.h
@@ -1 +1,19 @@
+/*
+ * MIPS64 specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
 #include "../mips/target_cpu.h"
diff --git a/linux-user/mips64/target_structs.h b/linux-user/mips64/target_structs.h
new file mode 100644
index 0000000000..a4f619e732
--- /dev/null
+++ b/linux-user/mips64/target_structs.h
@@ -0,0 +1,2 @@
+#include "../mips/target_structs.h"
+
diff --git a/linux-user/openrisc/target_structs.h b/linux-user/openrisc/target_structs.h
new file mode 100644
index 0000000000..f4d560f575
--- /dev/null
+++ b/linux-user/openrisc/target_structs.h
@@ -0,0 +1,58 @@
+/*
+ * OpenRISC specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_STRUCTS_H
+#define TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+    abi_int __key;                      /* Key.  */
+    abi_uint uid;                       /* Owner's user ID.  */
+    abi_uint gid;                       /* Owner's group ID.  */
+    abi_uint cuid;                      /* Creator's user ID.  */
+    abi_uint cgid;                      /* Creator's group ID.  */
+    abi_ushort mode;                    /* Read/write permission.  */
+    abi_ushort __pad1;
+    abi_ushort __seq;                   /* Sequence number.  */
+    abi_ushort __pad2;
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+struct target_shmid_ds {
+    struct target_ipc_perm shm_perm;    /* operation permission struct */
+    abi_long shm_segsz;                 /* size of segment in bytes */
+    abi_ulong shm_atime;                /* time of last shmat() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused1;
+#endif
+    abi_ulong shm_dtime;                /* time of last shmdt() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused2;
+#endif
+    abi_ulong shm_ctime;                /* time of last change by shmctl() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused3;
+#endif
+    abi_int shm_cpid;                   /* pid of creator */
+    abi_int shm_lpid;                   /* pid of last shmop */
+    abi_ulong shm_nattch;               /* number of current attaches */
+    abi_ulong __unused4;
+    abi_ulong __unused5;
+};
+
+#endif
diff --git a/linux-user/ppc/target_structs.h b/linux-user/ppc/target_structs.h
new file mode 100644
index 0000000000..2b87613104
--- /dev/null
+++ b/linux-user/ppc/target_structs.h
@@ -0,0 +1,60 @@
+/*
+ * PowerPC specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_STRUCTS_H
+#define TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+    abi_int __key;                      /* Key.  */
+    abi_uint uid;                       /* Owner's user ID.  */
+    abi_uint gid;                       /* Owner's group ID.  */
+    abi_uint cuid;                      /* Creator's user ID.  */
+    abi_uint cgid;                      /* Creator's group ID.  */
+    abi_uint mode;                      /* Read/write permission.  */
+    uint32_t __seq;                     /* Sequence number.  */
+    uint32_t __pad1;
+    uint64_t __unused1;
+    uint64_t __unused2;
+};
+
+struct target_shmid_ds {
+    struct target_ipc_perm shm_perm;    /* operation permission struct */
+#if TARGET_ABI_BITS == 32
+    abi_uint __unused1;
+#endif
+    abi_ulong shm_atime;                /* time of last shmat() */
+#if TARGET_ABI_BITS == 32
+    abi_uint __unused2;
+#endif
+    abi_ulong shm_dtime;                /* time of last shmdt() */
+#if TARGET_ABI_BITS == 32
+    abi_uint __unused3;
+#endif
+    abi_ulong shm_ctime;                /* time of last change by shmctl() */
+#if TARGET_ABI_BITS == 32
+    abi_uint __unused4;
+#endif
+    abi_long shm_segsz;                 /* size of segment in bytes */
+    abi_int shm_cpid;                   /* pid of creator */
+    abi_int shm_lpid;                   /* pid of last shmop */
+    abi_ulong shm_nattch;               /* number of current attaches */
+    abi_ulong __unused5;
+    abi_ulong __unused6;
+};
+
+#endif
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index da64e877c7..e2717e0775 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -452,5 +452,6 @@ static inline void *lock_user_string(abi_ulong guest_addr)
  */
 #include "target_cpu.h"
 #include "target_signal.h"
+#include "target_structs.h"
 
 #endif /* QEMU_H */
diff --git a/linux-user/s390x/target_structs.h b/linux-user/s390x/target_structs.h
new file mode 100644
index 0000000000..6b6f5b5212
--- /dev/null
+++ b/linux-user/s390x/target_structs.h
@@ -0,0 +1,63 @@
+/*
+ * S/390 specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_STRUCTS_H
+#define TARGET_STRUCTS_H
+
+
+struct target_ipc_perm {
+    abi_int __key;                       /* Key.  */
+    abi_uint uid;                        /* Owner's user ID.  */
+    abi_uint gid;                        /* Owner's group ID.  */
+    abi_uint cuid;                       /* Creator's user ID.  */
+    abi_uint cgid;                       /* Creator's group ID.  */
+#if TARGET_ABI_BITS == 64
+    abi_uint mode;                       /* Read/write permission.  */
+#else
+    abi_ushort mode;                     /* Read/write permission.  */
+    abi_ushort __pad1;
+#endif
+    abi_ushort __seq;                    /* Sequence number.  */
+    abi_ushort __pad2;
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+struct target_shmid_ds {
+    struct target_ipc_perm shm_perm;    /* operation permission struct */
+    abi_long shm_segsz;                 /* size of segment in bytes */
+    abi_ulong shm_atime;                /* time of last shmat() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused1;
+#endif
+    abi_ulong shm_dtime;                /* time of last shmdt() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused2;
+#endif
+    abi_ulong shm_ctime;                /* time of last change by shmctl() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused3;
+#endif
+    abi_int shm_cpid;                   /* pid of creator */
+    abi_int shm_lpid;                   /* pid of last shmop */
+    abi_ulong shm_nattch;               /* number of current attaches */
+    abi_ulong __unused4;
+    abi_ulong __unused5;
+};
+
+#endif
diff --git a/linux-user/sh4/target_structs.h b/linux-user/sh4/target_structs.h
new file mode 100644
index 0000000000..32b235e0b3
--- /dev/null
+++ b/linux-user/sh4/target_structs.h
@@ -0,0 +1,58 @@
+/*
+ * SH4 specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_STRUCTS_H
+#define TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+    abi_int __key;                      /* Key.  */
+    abi_uint uid;                       /* Owner's user ID.  */
+    abi_uint gid;                       /* Owner's group ID.  */
+    abi_uint cuid;                      /* Creator's user ID.  */
+    abi_uint cgid;                      /* Creator's group ID.  */
+    abi_ushort mode;                    /* Read/write permission.  */
+    abi_ushort __pad1;
+    abi_ushort __seq;                   /* Sequence number.  */
+    abi_ushort __pad2;
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+struct target_shmid_ds {
+    struct target_ipc_perm shm_perm;    /* operation permission struct */
+    abi_long shm_segsz;                 /* size of segment in bytes */
+    abi_ulong shm_atime;                /* time of last shmat() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused1;
+#endif
+    abi_ulong shm_dtime;                /* time of last shmdt() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused2;
+#endif
+    abi_ulong shm_ctime;                /* time of last change by shmctl() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused3;
+#endif
+    abi_int shm_cpid;                   /* pid of creator */
+    abi_int shm_lpid;                   /* pid of last shmop */
+    abi_ulong shm_nattch;               /* number of current attaches */
+    abi_ulong __unused4;
+    abi_ulong __unused5;
+};
+
+#endif
diff --git a/linux-user/sparc/target_structs.h b/linux-user/sparc/target_structs.h
new file mode 100644
index 0000000000..c139e09a61
--- /dev/null
+++ b/linux-user/sparc/target_structs.h
@@ -0,0 +1,63 @@
+/*
+ * SPARC specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_STRUCTS_H
+#define TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+    abi_int __key;                      /* Key.  */
+    abi_uint uid;                       /* Owner's user ID.  */
+    abi_uint gid;                       /* Owner's group ID.  */
+    abi_uint cuid;                      /* Creator's user ID.  */
+    abi_uint cgid;                      /* Creator's group ID.  */
+#if TARGET_ABI_BITS == 32
+    abi_ushort __pad1;
+    abi_ushort mode;                    /* Read/write permission.  */
+    abi_ushort __pad2;
+#else
+    abi_ushort mode;
+    abi_ushort __pad1;
+#endif
+    abi_ushort __seq;                   /* Sequence number.  */
+    uint64_t __unused1;
+    uint64_t __unused2;
+};
+
+struct target_shmid_ds {
+    struct target_ipc_perm shm_perm;    /* operation permission struct */
+#if TARGET_ABI_BITS == 32
+    abi_uint __pad1;
+#endif
+    abi_ulong shm_atime;                /* time of last shmat() */
+#if TARGET_ABI_BITS == 32
+    abi_uint __pad2;
+#endif
+    abi_ulong shm_dtime;                /* time of last shmdt() */
+#if TARGET_ABI_BITS == 32
+    abi_uint __pad3;
+#endif
+    abi_ulong shm_ctime;                /* time of last change by shmctl() */
+    abi_long shm_segsz;                 /* size of segment in bytes */
+    abi_ulong shm_cpid;                 /* pid of creator */
+    abi_ulong shm_lpid;                 /* pid of last shmop */
+    abi_long shm_nattch;                /* number of current attaches */
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+#endif
diff --git a/linux-user/sparc64/target_structs.h b/linux-user/sparc64/target_structs.h
new file mode 100644
index 0000000000..fc1729007d
--- /dev/null
+++ b/linux-user/sparc64/target_structs.h
@@ -0,0 +1,58 @@
+/*
+ * SPARC64 specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_STRUCTS_H
+#define TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+    abi_int __key;                      /* Key.  */
+    abi_uint uid;                       /* Owner's user ID.  */
+    abi_uint gid;                       /* Owner's group ID.  */
+    abi_uint cuid;                      /* Creator's user ID.  */
+    abi_uint cgid;                      /* Creator's group ID.  */
+    abi_ushort mode;                    /* Read/write permission.  */
+    abi_ushort __pad1;
+    abi_ushort __seq;                   /* Sequence number.  */
+    abi_ushort __pad2;
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+struct target_shmid_ds {
+    struct target_ipc_perm shm_perm;    /* operation permission struct */
+    abi_long shm_segsz;                 /* size of segment in bytes */
+    abi_ulong shm_atime;                /* time of last shmat() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused1;
+#endif
+    abi_ulong shm_dtime;                /* time of last shmdt() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused2;
+#endif
+    abi_ulong shm_ctime;                /* time of last change by shmctl() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused3;
+#endif
+    abi_int shm_cpid;                   /* pid of creator */
+    abi_int shm_lpid;                   /* pid of last shmop */
+    abi_ulong shm_nattch;               /* number of current attaches */
+    abi_ulong __unused4;
+    abi_ulong __unused5;
+};
+
+#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index eaaf00ddd0..efd1453987 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -428,6 +428,25 @@ _syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
           struct host_rlimit64 *, old_limit)
 #endif
 
+
+#if defined(TARGET_NR_timer_create)
+/* Maxiumum of 32 active POSIX timers allowed at any one time. */
+static timer_t g_posix_timers[32] = { 0, } ;
+
+static inline int next_free_host_timer(void)
+{
+    int k ;
+    /* FIXME: Does finding the next free slot require a lock? */
+    for (k = 0; k < ARRAY_SIZE(g_posix_timers); k++) {
+        if (g_posix_timers[k] == 0) {
+            g_posix_timers[k] = (timer_t) 1;
+            return k;
+        }
+    }
+    return -1;
+}
+#endif
+
 /* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
 #ifdef TARGET_ARM
 static inline int regpairs_aligned(void *cpu_env) {
@@ -2417,21 +2436,6 @@ static struct shm_region {
     abi_ulong	size;
 } shm_regions[N_SHM_REGIONS];
 
-struct target_ipc_perm
-{
-    abi_long __key;
-    abi_ulong uid;
-    abi_ulong gid;
-    abi_ulong cuid;
-    abi_ulong cgid;
-    unsigned short int mode;
-    unsigned short int __pad1;
-    unsigned short int __seq;
-    unsigned short int __pad2;
-    abi_ulong __unused1;
-    abi_ulong __unused2;
-};
-
 struct target_semid_ds
 {
   struct target_ipc_perm sem_perm;
@@ -2453,12 +2457,21 @@ static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
     if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
         return -TARGET_EFAULT;
     target_ip = &(target_sd->sem_perm);
-    host_ip->__key = tswapal(target_ip->__key);
-    host_ip->uid = tswapal(target_ip->uid);
-    host_ip->gid = tswapal(target_ip->gid);
-    host_ip->cuid = tswapal(target_ip->cuid);
-    host_ip->cgid = tswapal(target_ip->cgid);
+    host_ip->__key = tswap32(target_ip->__key);
+    host_ip->uid = tswap32(target_ip->uid);
+    host_ip->gid = tswap32(target_ip->gid);
+    host_ip->cuid = tswap32(target_ip->cuid);
+    host_ip->cgid = tswap32(target_ip->cgid);
+#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
+    host_ip->mode = tswap32(target_ip->mode);
+#else
     host_ip->mode = tswap16(target_ip->mode);
+#endif
+#if defined(TARGET_PPC)
+    host_ip->__seq = tswap32(target_ip->__seq);
+#else
+    host_ip->__seq = tswap16(target_ip->__seq);
+#endif
     unlock_user_struct(target_sd, target_addr, 0);
     return 0;
 }
@@ -2472,12 +2485,21 @@ static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
     if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
         return -TARGET_EFAULT;
     target_ip = &(target_sd->sem_perm);
-    target_ip->__key = tswapal(host_ip->__key);
-    target_ip->uid = tswapal(host_ip->uid);
-    target_ip->gid = tswapal(host_ip->gid);
-    target_ip->cuid = tswapal(host_ip->cuid);
-    target_ip->cgid = tswapal(host_ip->cgid);
+    target_ip->__key = tswap32(host_ip->__key);
+    target_ip->uid = tswap32(host_ip->uid);
+    target_ip->gid = tswap32(host_ip->gid);
+    target_ip->cuid = tswap32(host_ip->cuid);
+    target_ip->cgid = tswap32(host_ip->cgid);
+#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
+    target_ip->mode = tswap32(host_ip->mode);
+#else
     target_ip->mode = tswap16(host_ip->mode);
+#endif
+#if defined(TARGET_PPC)
+    target_ip->__seq = tswap32(host_ip->__seq);
+#else
+    target_ip->__seq = tswap16(host_ip->__seq);
+#endif
     unlock_user_struct(target_sd, target_addr, 1);
     return 0;
 }
@@ -2908,29 +2930,6 @@ end:
     return ret;
 }
 
-struct target_shmid_ds
-{
-    struct target_ipc_perm shm_perm;
-    abi_ulong shm_segsz;
-    abi_ulong shm_atime;
-#if TARGET_ABI_BITS == 32
-    abi_ulong __unused1;
-#endif
-    abi_ulong shm_dtime;
-#if TARGET_ABI_BITS == 32
-    abi_ulong __unused2;
-#endif
-    abi_ulong shm_ctime;
-#if TARGET_ABI_BITS == 32
-    abi_ulong __unused3;
-#endif
-    int shm_cpid;
-    int shm_lpid;
-    abi_ulong shm_nattch;
-    unsigned long int __unused4;
-    unsigned long int __unused5;
-};
-
 static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
                                                abi_ulong target_addr)
 {
@@ -3216,7 +3215,7 @@ static abi_long do_ipc(unsigned int call, int first,
 
 	/* IPC_* and SHM_* command values are the same on all linux platforms */
     case IPCOP_shmctl:
-        ret = do_shmctl(first, second, third);
+        ret = do_shmctl(first, second, ptr);
         break;
     default:
 	gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
@@ -4838,6 +4837,45 @@ static inline abi_long host_to_target_timespec(abi_ulong target_addr,
     return 0;
 }
 
+static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec,
+                                                 abi_ulong target_addr)
+{
+    struct target_itimerspec *target_itspec;
+
+    if (!lock_user_struct(VERIFY_READ, target_itspec, target_addr, 1)) {
+        return -TARGET_EFAULT;
+    }
+
+    host_itspec->it_interval.tv_sec =
+                            tswapal(target_itspec->it_interval.tv_sec);
+    host_itspec->it_interval.tv_nsec =
+                            tswapal(target_itspec->it_interval.tv_nsec);
+    host_itspec->it_value.tv_sec = tswapal(target_itspec->it_value.tv_sec);
+    host_itspec->it_value.tv_nsec = tswapal(target_itspec->it_value.tv_nsec);
+
+    unlock_user_struct(target_itspec, target_addr, 1);
+    return 0;
+}
+
+static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
+                                               struct itimerspec *host_its)
+{
+    struct target_itimerspec *target_itspec;
+
+    if (!lock_user_struct(VERIFY_WRITE, target_itspec, target_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+
+    target_itspec->it_interval.tv_sec = tswapal(host_its->it_interval.tv_sec);
+    target_itspec->it_interval.tv_nsec = tswapal(host_its->it_interval.tv_nsec);
+
+    target_itspec->it_value.tv_sec = tswapal(host_its->it_value.tv_sec);
+    target_itspec->it_value.tv_nsec = tswapal(host_its->it_value.tv_nsec);
+
+    unlock_user_struct(target_itspec, target_addr, 0);
+    return 0;
+}
+
 #if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
 static inline abi_long host_to_target_stat64(void *cpu_env,
                                              abi_ulong target_addr,
@@ -9195,6 +9233,124 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
     }
 #endif
+
+#ifdef TARGET_NR_timer_create
+    case TARGET_NR_timer_create:
+    {
+        /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
+
+        struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
+        struct target_sigevent *ptarget_sevp;
+        struct target_timer_t *ptarget_timer;
+
+        int clkid = arg1;
+        int timer_index = next_free_host_timer();
+
+        if (timer_index < 0) {
+            ret = -TARGET_EAGAIN;
+        } else {
+            timer_t *phtimer = g_posix_timers  + timer_index;
+
+            if (arg2) {
+                if (!lock_user_struct(VERIFY_READ, ptarget_sevp, arg2, 1)) {
+                    goto efault;
+                }
+
+                host_sevp.sigev_signo = tswap32(ptarget_sevp->sigev_signo);
+                host_sevp.sigev_notify = tswap32(ptarget_sevp->sigev_notify);
+
+                phost_sevp = &host_sevp;
+            }
+
+            ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
+            if (ret) {
+                phtimer = NULL;
+            } else {
+                if (!lock_user_struct(VERIFY_WRITE, ptarget_timer, arg3, 1)) {
+                    goto efault;
+                }
+                ptarget_timer->ptr = tswap32(0xcafe0000 | timer_index);
+                unlock_user_struct(ptarget_timer, arg3, 1);
+            }
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_settime
+    case TARGET_NR_timer_settime:
+    {
+        /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
+         * struct itimerspec * old_value */
+        arg1 &= 0xffff;
+        if (arg3 == 0 || arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t htimer = g_posix_timers[arg1];
+            struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
+
+            target_to_host_itimerspec(&hspec_new, arg3);
+            ret = get_errno(
+                          timer_settime(htimer, arg2, &hspec_new, &hspec_old));
+            host_to_target_itimerspec(arg2, &hspec_old);
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_gettime
+    case TARGET_NR_timer_gettime:
+    {
+        /* args: timer_t timerid, struct itimerspec *curr_value */
+        arg1 &= 0xffff;
+        if (!arg2) {
+            return -TARGET_EFAULT;
+        } else if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t htimer = g_posix_timers[arg1];
+            struct itimerspec hspec;
+            ret = get_errno(timer_gettime(htimer, &hspec));
+
+            if (host_to_target_itimerspec(arg2, &hspec)) {
+                ret = -TARGET_EFAULT;
+            }
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_getoverrun
+    case TARGET_NR_timer_getoverrun:
+    {
+        /* args: timer_t timerid */
+        arg1 &= 0xffff;
+        if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t htimer = g_posix_timers[arg1];
+            ret = get_errno(timer_getoverrun(htimer));
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_delete
+    case TARGET_NR_timer_delete:
+    {
+        /* args: timer_t timerid */
+        arg1 &= 0xffff;
+        if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t htimer = g_posix_timers[arg1];
+            ret = get_errno(timer_delete(htimer));
+            g_posix_timers[arg1] = 0;
+        }
+        break;
+    }
+#endif
+
     default:
     unimplemented:
         gemu_log("qemu: Unsupported syscall: %d\n", num);
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index fe540f6563..cf08db5a23 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -168,6 +168,11 @@ struct target_itimerval {
     struct target_timeval it_value;
 };
 
+struct target_itimerspec {
+    struct target_timespec it_interval;
+    struct target_timespec it_value;
+};
+
 typedef abi_long target_clock_t;
 
 #define TARGET_HZ 100
@@ -2527,3 +2532,23 @@ struct target_ucred {
 };
 
 #endif
+
+
+struct target_timer_t {
+    abi_ulong ptr;
+};
+
+struct target_sigevent {
+    target_sigval_t sigev_value;
+    int32_t sigev_signo;
+    int32_t sigev_notify;
+    union {
+        int32_t _pad[ARRAY_SIZE(((struct sigevent *)0)->_sigev_un._pad)];
+        int32_t _tid;
+
+        struct {
+            void (*_function)(sigval_t);
+            void *_attribute;
+        } _sigev_thread;
+    } _sigev_un;
+};
diff --git a/linux-user/unicore32/target_structs.h b/linux-user/unicore32/target_structs.h
new file mode 100644
index 0000000000..789369503b
--- /dev/null
+++ b/linux-user/unicore32/target_structs.h
@@ -0,0 +1,58 @@
+/*
+ * UniCore32 specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_STRUCTS_H
+#define TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+    abi_int __key;                      /* Key.  */
+    abi_uint uid;                       /* Owner's user ID.  */
+    abi_uint gid;                       /* Owner's group ID.  */
+    abi_uint cuid;                      /* Creator's user ID.  */
+    abi_uint cgid;                      /* Creator's group ID.  */
+    abi_ushort mode;                    /* Read/write permission.  */
+    abi_ushort __pad1;
+    abi_ushort __seq;                   /* Sequence number.  */
+    abi_ushort __pad2;
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+struct target_shmid_ds {
+    struct target_ipc_perm shm_perm;    /* operation permission struct */
+    abi_long shm_segsz;                 /* size of segment in bytes */
+    abi_ulong shm_atime;                /* time of last shmat() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused1;
+#endif
+    abi_ulong shm_dtime;                /* time of last shmdt() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused2;
+#endif
+    abi_ulong shm_ctime;                /* time of last change by shmctl() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused3;
+#endif
+    abi_int shm_cpid;                   /* pid of creator */
+    abi_int shm_lpid;                   /* pid of last shmop */
+    abi_ulong shm_nattch;               /* number of current attaches */
+    abi_ulong __unused4;
+    abi_ulong __unused5;
+};
+
+#endif
diff --git a/linux-user/x86_64/target_structs.h b/linux-user/x86_64/target_structs.h
new file mode 100644
index 0000000000..d934056149
--- /dev/null
+++ b/linux-user/x86_64/target_structs.h
@@ -0,0 +1,58 @@
+/*
+ * X86-64 specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_STRUCTS_H
+#define TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+    abi_int __key;                      /* Key.  */
+    abi_uint uid;                       /* Owner's user ID.  */
+    abi_uint gid;                       /* Owner's group ID.  */
+    abi_uint cuid;                      /* Creator's user ID.  */
+    abi_uint cgid;                      /* Creator's group ID.  */
+    abi_ushort mode;                    /* Read/write permission.  */
+    abi_ushort __pad1;
+    abi_ushort __seq;                   /* Sequence number.  */
+    abi_ushort __pad2;
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+struct target_shmid_ds {
+    struct target_ipc_perm shm_perm;    /* operation permission struct */
+    abi_long shm_segsz;                 /* size of segment in bytes */
+    abi_ulong shm_atime;                /* time of last shmat() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused1;
+#endif
+    abi_ulong shm_dtime;                /* time of last shmdt() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused2;
+#endif
+    abi_ulong shm_ctime;                /* time of last change by shmctl() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused3;
+#endif
+    abi_int shm_cpid;                   /* pid of creator */
+    abi_int shm_lpid;                   /* pid of last shmop */
+    abi_ulong shm_nattch;               /* number of current attaches */
+    abi_ulong __unused4;
+    abi_ulong __unused5;
+};
+
+#endif
diff --git a/net/Makefile.objs b/net/Makefile.objs
index 4854a14fe4..c25fe6920c 100644
--- a/net/Makefile.objs
+++ b/net/Makefile.objs
@@ -11,3 +11,4 @@ common-obj-$(CONFIG_AIX) += tap-aix.o
 common-obj-$(CONFIG_HAIKU) += tap-haiku.o
 common-obj-$(CONFIG_SLIRP) += slirp.o
 common-obj-$(CONFIG_VDE) += vde.o
+common-obj-$(CONFIG_NETMAP) += netmap.o
diff --git a/net/clients.h b/net/clients.h
index 77932942bd..7322ff5f33 100644
--- a/net/clients.h
+++ b/net/clients.h
@@ -52,4 +52,9 @@ int net_init_vde(const NetClientOptions *opts, const char *name,
                  NetClientState *peer);
 #endif
 
+#ifdef CONFIG_NETMAP
+int net_init_netmap(const NetClientOptions *opts, const char *name,
+                    NetClientState *peer);
+#endif
+
 #endif /* QEMU_NET_CLIENTS_H */
diff --git a/net/net.c b/net/net.c
index 0a88e68253..9db88cc0ee 100644
--- a/net/net.c
+++ b/net/net.c
@@ -726,6 +726,9 @@ static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])(
 #ifdef CONFIG_VDE
         [NET_CLIENT_OPTIONS_KIND_VDE]       = net_init_vde,
 #endif
+#ifdef CONFIG_NETMAP
+        [NET_CLIENT_OPTIONS_KIND_NETMAP]    = net_init_netmap,
+#endif
         [NET_CLIENT_OPTIONS_KIND_DUMP]      = net_init_dump,
 #ifdef CONFIG_NET_BRIDGE
         [NET_CLIENT_OPTIONS_KIND_BRIDGE]    = net_init_bridge,
@@ -757,6 +760,9 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp)
 #ifdef CONFIG_VDE
         case NET_CLIENT_OPTIONS_KIND_VDE:
 #endif
+#ifdef CONFIG_NETMAP
+        case NET_CLIENT_OPTIONS_KIND_NETMAP:
+#endif
 #ifdef CONFIG_NET_BRIDGE
         case NET_CLIENT_OPTIONS_KIND_BRIDGE:
 #endif
@@ -1065,15 +1071,23 @@ void qmp_set_link(const char *name, bool up, Error **errp)
         nc->info->link_status_changed(nc);
     }
 
-    /* Notify peer. Don't update peer link status: this makes it possible to
-     * disconnect from host network without notifying the guest.
-     * FIXME: is disconnected link status change operation useful?
-     *
-     * Current behaviour is compatible with qemu vlans where there could be
-     * multiple clients that can still communicate with each other in
-     * disconnected mode. For now maintain this compatibility. */
-    if (nc->peer && nc->peer->info->link_status_changed) {
-        nc->peer->info->link_status_changed(nc->peer);
+    if (nc->peer) {
+        /* Change peer link only if the peer is NIC and then notify peer.
+         * If the peer is a HUBPORT or a backend, we do not change the
+         * link status.
+         *
+         * This behavior is compatible with qemu vlans where there could be
+         * multiple clients that can still communicate with each other in
+         * disconnected mode. For now maintain this compatibility.
+         */
+        if (nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
+            for (i = 0; i < queues; i++) {
+                ncs[i]->peer->link_down = !up;
+            }
+        }
+        if (nc->peer->info->link_status_changed) {
+            nc->peer->info->link_status_changed(nc->peer);
+        }
     }
 }
 
diff --git a/net/netmap.c b/net/netmap.c
new file mode 100644
index 0000000000..0ccc4976b5
--- /dev/null
+++ b/net/netmap.c
@@ -0,0 +1,435 @@
+/*
+ * netmap access for qemu
+ *
+ * Copyright (c) 2012-2013 Luigi Rizzo
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <sys/mman.h>
+#include <stdint.h>
+#include <net/netmap.h>
+#include <net/netmap_user.h>
+
+#include "net/net.h"
+#include "clients.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+#include "qemu/iov.h"
+
+/* Private netmap device info. */
+typedef struct NetmapPriv {
+    int                 fd;
+    size_t              memsize;
+    void                *mem;
+    struct netmap_if    *nifp;
+    struct netmap_ring  *rx;
+    struct netmap_ring  *tx;
+    char                fdname[PATH_MAX];        /* Normally "/dev/netmap". */
+    char                ifname[IFNAMSIZ];
+} NetmapPriv;
+
+typedef struct NetmapState {
+    NetClientState      nc;
+    NetmapPriv          me;
+    bool                read_poll;
+    bool                write_poll;
+    struct iovec        iov[IOV_MAX];
+} NetmapState;
+
+#define D(format, ...)                                          \
+    do {                                                        \
+        struct timeval __xxts;                                  \
+        gettimeofday(&__xxts, NULL);                            \
+        printf("%03d.%06d %s [%d] " format "\n",                \
+                (int)__xxts.tv_sec % 1000, (int)__xxts.tv_usec, \
+                __func__, __LINE__, ##__VA_ARGS__);         \
+    } while (0)
+
+/* Rate limited version of "D", lps indicates how many per second */
+#define RD(lps, format, ...)                                    \
+    do {                                                        \
+        static int t0, __cnt;                                   \
+        struct timeval __xxts;                                  \
+        gettimeofday(&__xxts, NULL);                            \
+        if (t0 != __xxts.tv_sec) {                              \
+            t0 = __xxts.tv_sec;                                 \
+            __cnt = 0;                                          \
+        }                                                       \
+        if (__cnt++ < lps) {                                    \
+            D(format, ##__VA_ARGS__);                           \
+        }                                                       \
+    } while (0)
+
+
+#ifndef __FreeBSD__
+#define pkt_copy bcopy
+#else
+/* A fast copy routine only for multiples of 64 bytes, non overlapped. */
+static inline void
+pkt_copy(const void *_src, void *_dst, int l)
+{
+    const uint64_t *src = _src;
+    uint64_t *dst = _dst;
+    if (unlikely(l >= 1024)) {
+        bcopy(src, dst, l);
+        return;
+    }
+    for (; l > 0; l -= 64) {
+        *dst++ = *src++;
+        *dst++ = *src++;
+        *dst++ = *src++;
+        *dst++ = *src++;
+        *dst++ = *src++;
+        *dst++ = *src++;
+        *dst++ = *src++;
+        *dst++ = *src++;
+    }
+}
+#endif /* __FreeBSD__ */
+
+/*
+ * Open a netmap device. We assume there is only one queue
+ * (which is the case for the VALE bridge).
+ */
+static int netmap_open(NetmapPriv *me)
+{
+    int fd;
+    int err;
+    size_t l;
+    struct nmreq req;
+
+    me->fd = fd = open(me->fdname, O_RDWR);
+    if (fd < 0) {
+        error_report("Unable to open netmap device '%s' (%s)",
+                        me->fdname, strerror(errno));
+        return -1;
+    }
+    memset(&req, 0, sizeof(req));
+    pstrcpy(req.nr_name, sizeof(req.nr_name), me->ifname);
+    req.nr_ringid = NETMAP_NO_TX_POLL;
+    req.nr_version = NETMAP_API;
+    err = ioctl(fd, NIOCREGIF, &req);
+    if (err) {
+        error_report("Unable to register %s: %s", me->ifname, strerror(errno));
+        goto error;
+    }
+    l = me->memsize = req.nr_memsize;
+
+    me->mem = mmap(0, l, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
+    if (me->mem == MAP_FAILED) {
+        error_report("Unable to mmap netmap shared memory: %s",
+                        strerror(errno));
+        me->mem = NULL;
+        goto error;
+    }
+
+    me->nifp = NETMAP_IF(me->mem, req.nr_offset);
+    me->tx = NETMAP_TXRING(me->nifp, 0);
+    me->rx = NETMAP_RXRING(me->nifp, 0);
+    return 0;
+
+error:
+    close(me->fd);
+    return -1;
+}
+
+/* Tell the event-loop if the netmap backend can send packets
+   to the frontend. */
+static int netmap_can_send(void *opaque)
+{
+    NetmapState *s = opaque;
+
+    return qemu_can_send_packet(&s->nc);
+}
+
+static void netmap_send(void *opaque);
+static void netmap_writable(void *opaque);
+
+/* Set the event-loop handlers for the netmap backend. */
+static void netmap_update_fd_handler(NetmapState *s)
+{
+    qemu_set_fd_handler2(s->me.fd,
+                         s->read_poll  ? netmap_can_send : NULL,
+                         s->read_poll  ? netmap_send     : NULL,
+                         s->write_poll ? netmap_writable : NULL,
+                         s);
+}
+
+/* Update the read handler. */
+static void netmap_read_poll(NetmapState *s, bool enable)
+{
+    if (s->read_poll != enable) { /* Do nothing if not changed. */
+        s->read_poll = enable;
+        netmap_update_fd_handler(s);
+    }
+}
+
+/* Update the write handler. */
+static void netmap_write_poll(NetmapState *s, bool enable)
+{
+    if (s->write_poll != enable) {
+        s->write_poll = enable;
+        netmap_update_fd_handler(s);
+    }
+}
+
+static void netmap_poll(NetClientState *nc, bool enable)
+{
+    NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
+
+    if (s->read_poll != enable || s->write_poll != enable) {
+        s->read_poll = enable;
+        s->read_poll = enable;
+        netmap_update_fd_handler(s);
+    }
+}
+
+/*
+ * The fd_write() callback, invoked if the fd is marked as
+ * writable after a poll. Unregister the handler and flush any
+ * buffered packets.
+ */
+static void netmap_writable(void *opaque)
+{
+    NetmapState *s = opaque;
+
+    netmap_write_poll(s, false);
+    qemu_flush_queued_packets(&s->nc);
+}
+
+static ssize_t netmap_receive(NetClientState *nc,
+      const uint8_t *buf, size_t size)
+{
+    NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
+    struct netmap_ring *ring = s->me.tx;
+    uint32_t i;
+    uint32_t idx;
+    uint8_t *dst;
+
+    if (unlikely(!ring)) {
+        /* Drop. */
+        return size;
+    }
+
+    if (unlikely(size > ring->nr_buf_size)) {
+        RD(5, "[netmap_receive] drop packet of size %d > %d\n",
+                                    (int)size, ring->nr_buf_size);
+        return size;
+    }
+
+    if (ring->avail == 0) {
+        /* No available slots in the netmap TX ring. */
+        netmap_write_poll(s, true);
+        return 0;
+    }
+
+    i = ring->cur;
+    idx = ring->slot[i].buf_idx;
+    dst = (uint8_t *)NETMAP_BUF(ring, idx);
+
+    ring->slot[i].len = size;
+    ring->slot[i].flags = 0;
+    pkt_copy(buf, dst, size);
+    ring->cur = NETMAP_RING_NEXT(ring, i);
+    ring->avail--;
+    ioctl(s->me.fd, NIOCTXSYNC, NULL);
+
+    return size;
+}
+
+static ssize_t netmap_receive_iov(NetClientState *nc,
+                    const struct iovec *iov, int iovcnt)
+{
+    NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
+    struct netmap_ring *ring = s->me.tx;
+    uint32_t last;
+    uint32_t idx;
+    uint8_t *dst;
+    int j;
+    uint32_t i;
+    uint32_t avail;
+
+    if (unlikely(!ring)) {
+        /* Drop the packet. */
+        return iov_size(iov, iovcnt);
+    }
+
+    i = ring->cur;
+    avail = ring->avail;
+
+    if (avail < iovcnt) {
+        /* Not enough netmap slots. */
+        netmap_write_poll(s, true);
+        return 0;
+    }
+
+    for (j = 0; j < iovcnt; j++) {
+        int iov_frag_size = iov[j].iov_len;
+        int offset = 0;
+        int nm_frag_size;
+
+        /* Split each iovec fragment over more netmap slots, if
+           necessary. */
+        while (iov_frag_size) {
+            nm_frag_size = MIN(iov_frag_size, ring->nr_buf_size);
+
+            if (unlikely(avail == 0)) {
+                /* We run out of netmap slots while splitting the
+                   iovec fragments. */
+                netmap_write_poll(s, true);
+                return 0;
+            }
+
+            idx = ring->slot[i].buf_idx;
+            dst = (uint8_t *)NETMAP_BUF(ring, idx);
+
+            ring->slot[i].len = nm_frag_size;
+            ring->slot[i].flags = NS_MOREFRAG;
+            pkt_copy(iov[j].iov_base + offset, dst, nm_frag_size);
+
+            last = i;
+            i = NETMAP_RING_NEXT(ring, i);
+            avail--;
+
+            offset += nm_frag_size;
+            iov_frag_size -= nm_frag_size;
+        }
+    }
+    /* The last slot must not have NS_MOREFRAG set. */
+    ring->slot[last].flags &= ~NS_MOREFRAG;
+
+    /* Now update ring->cur and ring->avail. */
+    ring->cur = i;
+    ring->avail = avail;
+
+    ioctl(s->me.fd, NIOCTXSYNC, NULL);
+
+    return iov_size(iov, iovcnt);
+}
+
+/* Complete a previous send (backend --> guest) and enable the
+   fd_read callback. */
+static void netmap_send_completed(NetClientState *nc, ssize_t len)
+{
+    NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
+
+    netmap_read_poll(s, true);
+}
+
+static void netmap_send(void *opaque)
+{
+    NetmapState *s = opaque;
+    struct netmap_ring *ring = s->me.rx;
+
+    /* Keep sending while there are available packets into the netmap
+       RX ring and the forwarding path towards the peer is open. */
+    while (ring->avail > 0 && qemu_can_send_packet(&s->nc)) {
+        uint32_t i;
+        uint32_t idx;
+        bool morefrag;
+        int iovcnt = 0;
+        int iovsize;
+
+        do {
+            i = ring->cur;
+            idx = ring->slot[i].buf_idx;
+            morefrag = (ring->slot[i].flags & NS_MOREFRAG);
+            s->iov[iovcnt].iov_base = (u_char *)NETMAP_BUF(ring, idx);
+            s->iov[iovcnt].iov_len = ring->slot[i].len;
+            iovcnt++;
+
+            ring->cur = NETMAP_RING_NEXT(ring, i);
+            ring->avail--;
+        } while (ring->avail && morefrag);
+
+        if (unlikely(!ring->avail && morefrag)) {
+            RD(5, "[netmap_send] ran out of slots, with a pending"
+                   "incomplete packet\n");
+        }
+
+        iovsize = qemu_sendv_packet_async(&s->nc, s->iov, iovcnt,
+                                            netmap_send_completed);
+
+        if (iovsize == 0) {
+            /* The peer does not receive anymore. Packet is queued, stop
+             * reading from the backend until netmap_send_completed()
+             */
+            netmap_read_poll(s, false);
+            break;
+        }
+    }
+}
+
+/* Flush and close. */
+static void netmap_cleanup(NetClientState *nc)
+{
+    NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
+
+    qemu_purge_queued_packets(nc);
+
+    netmap_poll(nc, false);
+    munmap(s->me.mem, s->me.memsize);
+    close(s->me.fd);
+
+    s->me.fd = -1;
+}
+
+
+/* NetClientInfo methods */
+static NetClientInfo net_netmap_info = {
+    .type = NET_CLIENT_OPTIONS_KIND_NETMAP,
+    .size = sizeof(NetmapState),
+    .receive = netmap_receive,
+    .receive_iov = netmap_receive_iov,
+    .poll = netmap_poll,
+    .cleanup = netmap_cleanup,
+};
+
+/* The exported init function
+ *
+ * ... -net netmap,ifname="..."
+ */
+int net_init_netmap(const NetClientOptions *opts,
+        const char *name, NetClientState *peer)
+{
+    const NetdevNetmapOptions *netmap_opts = opts->netmap;
+    NetClientState *nc;
+    NetmapPriv me;
+    NetmapState *s;
+
+    pstrcpy(me.fdname, sizeof(me.fdname),
+        netmap_opts->has_devname ? netmap_opts->devname : "/dev/netmap");
+    /* Set default name for the port if not supplied. */
+    pstrcpy(me.ifname, sizeof(me.ifname), netmap_opts->ifname);
+    if (netmap_open(&me)) {
+        return -1;
+    }
+    /* Create the object. */
+    nc = qemu_new_net_client(&net_netmap_info, peer, "netmap", name);
+    s = DO_UPCAST(NetmapState, nc, nc);
+    s->me = me;
+    netmap_read_poll(s, true); /* Initially only poll for reads. */
+
+    return 0;
+}
+
diff --git a/pc-bios/acpi-dsdt.aml b/pc-bios/acpi-dsdt.aml
index 528372b41e..cfd16d756e 100644
--- a/pc-bios/acpi-dsdt.aml
+++ b/pc-bios/acpi-dsdt.aml
Binary files differdiff --git a/pc-bios/bios-256k.bin b/pc-bios/bios-256k.bin
new file mode 100644
index 0000000000..68017e59ce
--- /dev/null
+++ b/pc-bios/bios-256k.bin
Binary files differdiff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index 697440c26c..4f4383b06a 100644
--- a/pc-bios/bios.bin
+++ b/pc-bios/bios.bin
Binary files differdiff --git a/pc-bios/q35-acpi-dsdt.aml b/pc-bios/q35-acpi-dsdt.aml
index 4d23746ebf..d71b3a328c 100644
--- a/pc-bios/q35-acpi-dsdt.aml
+++ b/pc-bios/q35-acpi-dsdt.aml
Binary files differdiff --git a/pc-bios/vgabios-cirrus.bin b/pc-bios/vgabios-cirrus.bin
index 424dd0c70c..36b197d190 100644
--- a/pc-bios/vgabios-cirrus.bin
+++ b/pc-bios/vgabios-cirrus.bin
Binary files differdiff --git a/pc-bios/vgabios-qxl.bin b/pc-bios/vgabios-qxl.bin
index 3156c6e3f1..aaa3b10c7c 100644
--- a/pc-bios/vgabios-qxl.bin
+++ b/pc-bios/vgabios-qxl.bin
Binary files differdiff --git a/pc-bios/vgabios-stdvga.bin b/pc-bios/vgabios-stdvga.bin
index 5123c5fd07..d329e240f9 100644
--- a/pc-bios/vgabios-stdvga.bin
+++ b/pc-bios/vgabios-stdvga.bin
Binary files differdiff --git a/pc-bios/vgabios-vmware.bin b/pc-bios/vgabios-vmware.bin
index 5e8c06b228..31d56a94d0 100644
--- a/pc-bios/vgabios-vmware.bin
+++ b/pc-bios/vgabios-vmware.bin
Binary files differdiff --git a/pc-bios/vgabios.bin b/pc-bios/vgabios.bin
index 892a2b5374..b87f74de7c 100644
--- a/pc-bios/vgabios.bin
+++ b/pc-bios/vgabios.bin
Binary files differdiff --git a/qapi-schema.json b/qapi-schema.json
index 8630eb50ea..d6f8615942 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3009,6 +3009,27 @@
     'hubid':     'int32' } }
 
 ##
+# @NetdevNetmapOptions
+#
+# Connect a client to a netmap-enabled NIC or to a VALE switch port
+#
+# @ifname: Either the name of an existing network interface supported by
+#          netmap, or the name of a VALE port (created on the fly).
+#          A VALE port name is in the form 'valeXXX:YYY', where XXX and
+#          YYY are non-negative integers. XXX identifies a switch and
+#          YYY identifies a port of the switch. VALE ports having the
+#          same XXX are therefore connected to the same switch.
+#
+# @devname: #optional path of the netmap device (default: '/dev/netmap').
+#
+# Since 1.8
+##
+{ 'type': 'NetdevNetmapOptions',
+  'data': {
+    'ifname':     'str',
+    '*devname':    'str' } }
+
+##
 # @NetClientOptions
 #
 # A discriminated record of network device traits.
@@ -3025,7 +3046,8 @@
     'vde':      'NetdevVdeOptions',
     'dump':     'NetdevDumpOptions',
     'bridge':   'NetdevBridgeOptions',
-    'hubport':  'NetdevHubPortOptions' } }
+    'hubport':  'NetdevHubPortOptions',
+    'netmap':   'NetdevNetmapOptions' } }
 
 ##
 # @NetLegacy
diff --git a/qemu-options.hx b/qemu-options.hx
index 7f12f02e04..bcfe9eaa3e 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -228,7 +228,6 @@ STEXI
 Allocate guest RAM from a temporarily created file in @var{path}.
 ETEXI
 
-#ifdef MAP_POPULATE
 DEF("mem-prealloc", 0, QEMU_OPTION_mem_prealloc,
     "-mem-prealloc   preallocate guest memory (use with -mem-path)\n",
     QEMU_ARCH_ALL)
@@ -237,7 +236,6 @@ STEXI
 @findex -mem-prealloc
 Preallocate memory when using -mem-path.
 ETEXI
-#endif
 
 DEF("k", HAS_ARG, QEMU_OPTION_k,
     "-k language     use keyboard layout (for example 'fr' for French)\n",
@@ -1409,6 +1407,12 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
     "                Use group 'groupname' and mode 'octalmode' to change default\n"
     "                ownership and permissions for communication port.\n"
 #endif
+#ifdef CONFIG_NETMAP
+    "-net netmap,ifname=name[,devname=nmname]\n"
+    "                attach to the existing netmap-enabled network interface 'name', or to a\n"
+    "                VALE port (created on the fly) called 'name' ('nmname' is name of the \n"
+    "                netmap device, defaults to '/dev/netmap')\n"
+#endif
     "-net dump[,vlan=n][,file=f][,len=n]\n"
     "                dump traffic on vlan 'n' to file 'f' (max n bytes per packet)\n"
     "-net none       use it alone to have zero network devices. If no -net option\n"
@@ -1423,6 +1427,9 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
 #ifdef CONFIG_VDE
     "vde|"
 #endif
+#ifdef CONFIG_NETMAP
+    "netmap|"
+#endif
     "socket|"
     "hubport],id=str[,option][,option][,...]\n", QEMU_ARCH_ALL)
 STEXI
diff --git a/qemu-seccomp.c b/qemu-seccomp.c
index 69cee443af..cf07869599 100644
--- a/qemu-seccomp.c
+++ b/qemu-seccomp.c
@@ -114,6 +114,7 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
     { SCMP_SYS(write), 244 },
     { SCMP_SYS(fcntl), 243 },
     { SCMP_SYS(tgkill), 242 },
+    { SCMP_SYS(kill), 242 },
     { SCMP_SYS(rt_sigaction), 242 },
     { SCMP_SYS(pipe2), 242 },
     { SCMP_SYS(munmap), 242 },
diff --git a/qobject/qerror.c b/qobject/qerror.c
index 3aee1cf6a6..fc8331aa67 100644
--- a/qobject/qerror.c
+++ b/qobject/qerror.c
@@ -42,8 +42,8 @@ static QError *qerror_new(void)
  *
  * Return strong reference.
  */
-static QError *qerror_from_info(ErrorClass err_class, const char *fmt,
-                                va_list *va)
+static QError * GCC_FMT_ATTR(2, 0)
+qerror_from_info(ErrorClass err_class, const char *fmt, va_list *va)
 {
     QError *qerr;
 
diff --git a/roms/Makefile b/roms/Makefile
index 10d5a65d61..1e04669af4 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -56,9 +56,10 @@ default:
 	@echo "                    the EfiRom utility from edk2 / tianocore)"
 	@echo "  slof           -- update slof.bin"
 
-bios: build-seabios-config-seabios
-	cp seabios/builds/seabios/bios.bin ../pc-bios/bios.bin
-	cp seabios/builds/seabios/*dsdt.aml ../pc-bios/
+bios: build-seabios-config-seabios-128k build-seabios-config-seabios-256k
+	cp seabios/builds/seabios-128k/bios.bin ../pc-bios/bios.bin
+	cp seabios/builds/seabios-256k/bios.bin ../pc-bios/bios-256k.bin
+	cp seabios/builds/seabios-256k/src/fw/*dsdt.aml ../pc-bios/
 
 seavgabios: $(patsubst %,seavgabios-%,$(vgabios_variants))
 
@@ -72,9 +73,11 @@ build-seabios-config-%: config.%
 	mkdir -p seabios/builds/$*
 	cp $< seabios/builds/$*/.config
 	$(MAKE) $(MAKEFLAGS) -C seabios \
+		CROSS_COMPILE=$(x86_64_cross_prefix) \
 		KCONFIG_CONFIG=$(CURDIR)/seabios/builds/$*/.config \
 		OUT=$(CURDIR)/seabios/builds/$*/ oldnoconfig
 	$(MAKE) $(MAKEFLAGS) -C seabios \
+		CROSS_COMPILE=$(x86_64_cross_prefix) \
 		KCONFIG_CONFIG=$(CURDIR)/seabios/builds/$*/.config \
 		OUT=$(CURDIR)/seabios/builds/$*/ all
 
diff --git a/roms/config.seabios b/roms/config.seabios
deleted file mode 100644
index c373b87a98..0000000000
--- a/roms/config.seabios
+++ /dev/null
@@ -1 +0,0 @@
-# empty, default config works for us
diff --git a/roms/config.seabios-128k b/roms/config.seabios-128k
new file mode 100644
index 0000000000..41f83816fc
--- /dev/null
+++ b/roms/config.seabios-128k
@@ -0,0 +1,6 @@
+# for qemu machine types 1.7 + older
+# need to turn off features (xhci) to make it fit into 128k
+CONFIG_QEMU=y
+CONFIG_ROM_SIZE=128
+CONFIG_XEN=n
+CONFIG_USB_XHCI=n
diff --git a/roms/config.seabios-256k b/roms/config.seabios-256k
new file mode 100644
index 0000000000..65e5015c2f
--- /dev/null
+++ b/roms/config.seabios-256k
@@ -0,0 +1,3 @@
+# for qemu machine types 2.0 + newer
+CONFIG_QEMU=y
+CONFIG_ROM_SIZE=256
diff --git a/roms/seabios b/roms/seabios
-Subproject ece025f5980bae88fa677bc9c0d24d2e580e205
+Subproject 31b8b4eea9d9ad58a73b22a6060d3ac1c419c26
diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h
index 2ebc9bcacb..198f1b13a3 100644
--- a/target-alpha/cpu-qom.h
+++ b/target-alpha/cpu-qom.h
@@ -62,7 +62,7 @@ typedef struct AlphaCPU {
     CPUAlphaState env;
 
     /* This alarm doesn't exist in real hardware; we wish it did.  */
-    struct QEMUTimer *alarm_timer;
+    QEMUTimer *alarm_timer;
 } AlphaCPU;
 
 static inline AlphaCPU *alpha_env_get_cpu(CPUAlphaState *env)
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index b55306a3c3..f32178a9db 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -91,6 +91,17 @@ typedef struct ARMCPU {
     /* GPIO outputs for generic timer */
     qemu_irq gt_timer_outputs[NUM_GTIMERS];
 
+    /* 'compatible' string for this CPU for Linux device trees */
+    const char *dtb_compatible;
+
+    /* Should CPU start in PSCI powered-off state? */
+    bool start_powered_off;
+
+    /* [QEMU_]KVM_ARM_TARGET_* constant for this CPU, or
+     * QEMU_KVM_ARM_TARGET_NONE if the kernel doesn't support this CPU type.
+     */
+    uint32_t kvm_target;
+
     /* The instance init functions for implementation-specific subclasses
      * set these fields to specify the implementation-dependent values of
      * various constant registers and reset values of non-constant
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index d40f2a7a4f..0635e78ec2 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -20,6 +20,7 @@
 
 #include "cpu.h"
 #include "qemu-common.h"
+#include "hw/qdev-properties.h"
 #if !defined(CONFIG_USER_ONLY)
 #include "hw/loader.h"
 #endif
@@ -217,6 +218,13 @@ static void arm_cpu_initfn(Object *obj)
                        ARRAY_SIZE(cpu->gt_timer_outputs));
 #endif
 
+    /* DTB consumers generally don't in fact care what the 'compatible'
+     * string is, so always provide some string and trust that a hypothetical
+     * picky DTB consumer will also provide a helpful error message.
+     */
+    cpu->dtb_compatible = "qemu,unknown";
+    cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
+
     if (tcg_enabled() && !inited) {
         inited = true;
         arm_translate_init();
@@ -318,6 +326,8 @@ static ObjectClass *arm_cpu_class_by_name(const char *cpu_model)
 static void arm926_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "arm,arm926";
     set_feature(&cpu->env, ARM_FEATURE_V5);
     set_feature(&cpu->env, ARM_FEATURE_VFP);
     set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
@@ -331,6 +341,8 @@ static void arm926_initfn(Object *obj)
 static void arm946_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "arm,arm946";
     set_feature(&cpu->env, ARM_FEATURE_V5);
     set_feature(&cpu->env, ARM_FEATURE_MPU);
     set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
@@ -342,6 +354,8 @@ static void arm946_initfn(Object *obj)
 static void arm1026_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "arm,arm1026";
     set_feature(&cpu->env, ARM_FEATURE_V5);
     set_feature(&cpu->env, ARM_FEATURE_VFP);
     set_feature(&cpu->env, ARM_FEATURE_AUXCR);
@@ -374,6 +388,8 @@ static void arm1136_r2_initfn(Object *obj)
      * for 1136_r2 (in particular r0p2 does not actually implement most
      * of the ID registers).
      */
+
+    cpu->dtb_compatible = "arm,arm1136";
     set_feature(&cpu->env, ARM_FEATURE_V6);
     set_feature(&cpu->env, ARM_FEATURE_VFP);
     set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
@@ -403,6 +419,8 @@ static void arm1136_r2_initfn(Object *obj)
 static void arm1136_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "arm,arm1136";
     set_feature(&cpu->env, ARM_FEATURE_V6K);
     set_feature(&cpu->env, ARM_FEATURE_V6);
     set_feature(&cpu->env, ARM_FEATURE_VFP);
@@ -433,6 +451,8 @@ static void arm1136_initfn(Object *obj)
 static void arm1176_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "arm,arm1176";
     set_feature(&cpu->env, ARM_FEATURE_V6K);
     set_feature(&cpu->env, ARM_FEATURE_VFP);
     set_feature(&cpu->env, ARM_FEATURE_VAPA);
@@ -463,6 +483,8 @@ static void arm1176_initfn(Object *obj)
 static void arm11mpcore_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "arm,arm11mpcore";
     set_feature(&cpu->env, ARM_FEATURE_V6K);
     set_feature(&cpu->env, ARM_FEATURE_VFP);
     set_feature(&cpu->env, ARM_FEATURE_VAPA);
@@ -516,6 +538,8 @@ static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
 static void cortex_a8_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "arm,cortex-a8";
     set_feature(&cpu->env, ARM_FEATURE_V7);
     set_feature(&cpu->env, ARM_FEATURE_VFP3);
     set_feature(&cpu->env, ARM_FEATURE_NEON);
@@ -580,6 +604,8 @@ static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
 static void cortex_a9_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "arm,cortex-a9";
     set_feature(&cpu->env, ARM_FEATURE_V7);
     set_feature(&cpu->env, ARM_FEATURE_VFP3);
     set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
@@ -649,6 +675,8 @@ static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
 static void cortex_a15_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "arm,cortex-a15";
     set_feature(&cpu->env, ARM_FEATURE_V7);
     set_feature(&cpu->env, ARM_FEATURE_VFP4);
     set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
@@ -658,6 +686,7 @@ static void cortex_a15_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
     set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
     set_feature(&cpu->env, ARM_FEATURE_LPAE);
+    cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15;
     cpu->midr = 0x412fc0f1;
     cpu->reset_fpsid = 0x410430f0;
     cpu->mvfr0 = 0x10110222;
@@ -697,6 +726,8 @@ static void ti925t_initfn(Object *obj)
 static void sa1100_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "intel,sa1100";
     set_feature(&cpu->env, ARM_FEATURE_STRONGARM);
     set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
     cpu->midr = 0x4401A11B;
@@ -715,6 +746,8 @@ static void sa1110_initfn(Object *obj)
 static void pxa250_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "marvell,xscale";
     set_feature(&cpu->env, ARM_FEATURE_V5);
     set_feature(&cpu->env, ARM_FEATURE_XSCALE);
     cpu->midr = 0x69052100;
@@ -725,6 +758,8 @@ static void pxa250_initfn(Object *obj)
 static void pxa255_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "marvell,xscale";
     set_feature(&cpu->env, ARM_FEATURE_V5);
     set_feature(&cpu->env, ARM_FEATURE_XSCALE);
     cpu->midr = 0x69052d00;
@@ -735,6 +770,8 @@ static void pxa255_initfn(Object *obj)
 static void pxa260_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "marvell,xscale";
     set_feature(&cpu->env, ARM_FEATURE_V5);
     set_feature(&cpu->env, ARM_FEATURE_XSCALE);
     cpu->midr = 0x69052903;
@@ -745,6 +782,8 @@ static void pxa260_initfn(Object *obj)
 static void pxa261_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "marvell,xscale";
     set_feature(&cpu->env, ARM_FEATURE_V5);
     set_feature(&cpu->env, ARM_FEATURE_XSCALE);
     cpu->midr = 0x69052d05;
@@ -755,6 +794,8 @@ static void pxa261_initfn(Object *obj)
 static void pxa262_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "marvell,xscale";
     set_feature(&cpu->env, ARM_FEATURE_V5);
     set_feature(&cpu->env, ARM_FEATURE_XSCALE);
     cpu->midr = 0x69052d06;
@@ -765,6 +806,8 @@ static void pxa262_initfn(Object *obj)
 static void pxa270a0_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "marvell,xscale";
     set_feature(&cpu->env, ARM_FEATURE_V5);
     set_feature(&cpu->env, ARM_FEATURE_XSCALE);
     set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
@@ -776,6 +819,8 @@ static void pxa270a0_initfn(Object *obj)
 static void pxa270a1_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "marvell,xscale";
     set_feature(&cpu->env, ARM_FEATURE_V5);
     set_feature(&cpu->env, ARM_FEATURE_XSCALE);
     set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
@@ -787,6 +832,8 @@ static void pxa270a1_initfn(Object *obj)
 static void pxa270b0_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "marvell,xscale";
     set_feature(&cpu->env, ARM_FEATURE_V5);
     set_feature(&cpu->env, ARM_FEATURE_XSCALE);
     set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
@@ -798,6 +845,8 @@ static void pxa270b0_initfn(Object *obj)
 static void pxa270b1_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "marvell,xscale";
     set_feature(&cpu->env, ARM_FEATURE_V5);
     set_feature(&cpu->env, ARM_FEATURE_XSCALE);
     set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
@@ -809,6 +858,8 @@ static void pxa270b1_initfn(Object *obj)
 static void pxa270c0_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "marvell,xscale";
     set_feature(&cpu->env, ARM_FEATURE_V5);
     set_feature(&cpu->env, ARM_FEATURE_XSCALE);
     set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
@@ -820,6 +871,8 @@ static void pxa270c0_initfn(Object *obj)
 static void pxa270c5_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "marvell,xscale";
     set_feature(&cpu->env, ARM_FEATURE_V5);
     set_feature(&cpu->env, ARM_FEATURE_XSCALE);
     set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
@@ -894,6 +947,11 @@ static const ARMCPUInfo arm_cpus[] = {
 #endif
 };
 
+static Property arm_cpu_properties[] = {
+    DEFINE_PROP_BOOL("start-powered-off", ARMCPU, start_powered_off, false),
+    DEFINE_PROP_END_OF_LIST()
+};
+
 static void arm_cpu_class_init(ObjectClass *oc, void *data)
 {
     ARMCPUClass *acc = ARM_CPU_CLASS(oc);
@@ -902,6 +960,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
 
     acc->parent_realize = dc->realize;
     dc->realize = arm_cpu_realizefn;
+    dc->props = arm_cpu_properties;
 
     acc->parent_reset = cc->reset;
     cc->reset = arm_cpu_reset;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 9f110f15b6..c3f007fc53 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -21,6 +21,8 @@
 
 #include "config.h"
 
+#include "kvm-consts.h"
+
 #if defined(TARGET_AARCH64)
   /* AArch64 definitions */
 #  define TARGET_LONG_BITS 64
@@ -497,17 +499,6 @@ void armv7m_nvic_complete_irq(void *opaque, int irq);
     (((cp) << 16) | ((is64) << 15) | ((crn) << 11) |    \
      ((crm) << 7) | ((opc1) << 3) | (opc2))
 
-/* Note that these must line up with the KVM/ARM register
- * ID field definitions (kvm.c will check this, but we
- * can't just use the KVM defines here as the kvm headers
- * are unavailable to non-KVM-specific files)
- */
-#define CP_REG_SIZE_SHIFT 52
-#define CP_REG_SIZE_MASK       0x00f0000000000000ULL
-#define CP_REG_SIZE_U32        0x0020000000000000ULL
-#define CP_REG_SIZE_U64        0x0030000000000000ULL
-#define CP_REG_ARM             0x4000000000000000ULL
-
 /* Convert a full 64 bit KVM register ID to the truncated 32 bit
  * version used as a key for the coprocessor register hashtable
  */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 3445813465..5e5e5aad2b 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1173,7 +1173,7 @@ static int vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
 {
     int maskshift = extract32(value, 0, 3);
 
-    if (arm_feature(env, ARM_FEATURE_LPAE)) {
+    if (arm_feature(env, ARM_FEATURE_LPAE) && (value & (1 << 31))) {
         value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
     } else {
         value &= 7;
@@ -1842,6 +1842,12 @@ void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf)
     (*cpu_fprintf)(f, "Available CPUs:\n");
     g_slist_foreach(list, arm_cpu_list_entry, &s);
     g_slist_free(list);
+#ifdef CONFIG_KVM
+    /* The 'host' CPU type is dynamically registered only if KVM is
+     * enabled, so we have to special-case it here:
+     */
+    (*cpu_fprintf)(f, "  host (only available in KVM mode)\n");
+#endif
 }
 
 static void arm_cpu_add_definition(gpointer data, gpointer user_data)
@@ -4079,3 +4085,28 @@ float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
     float_status *fpst = fpstp;
     return float64_muladd(a, b, c, 0, fpst);
 }
+
+/* ARMv8 VMAXNM/VMINNM */
+float32 VFP_HELPER(maxnm, s)(float32 a, float32 b, void *fpstp)
+{
+    float_status *fpst = fpstp;
+    return float32_maxnum(a, b, fpst);
+}
+
+float64 VFP_HELPER(maxnm, d)(float64 a, float64 b, void *fpstp)
+{
+    float_status *fpst = fpstp;
+    return float64_maxnum(a, b, fpst);
+}
+
+float32 VFP_HELPER(minnm, s)(float32 a, float32 b, void *fpstp)
+{
+    float_status *fpst = fpstp;
+    return float32_minnum(a, b, fpst);
+}
+
+float64 VFP_HELPER(minnm, d)(float64 a, float64 b, void *fpstp)
+{
+    float_status *fpst = fpstp;
+    return float64_minnum(a, b, fpst);
+}
diff --git a/target-arm/helper.h b/target-arm/helper.h
index cac9564f5f..d459a39e46 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -132,6 +132,11 @@ DEF_HELPER_2(neon_fcvt_f32_to_f16, i32, f32, env)
 DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr)
 DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
 
+DEF_HELPER_3(vfp_maxnmd, f64, f64, f64, ptr)
+DEF_HELPER_3(vfp_maxnms, f32, f32, f32, ptr)
+DEF_HELPER_3(vfp_minnmd, f64, f64, f64, ptr)
+DEF_HELPER_3(vfp_minnms, f32, f32, f32, ptr)
+
 DEF_HELPER_3(recps_f32, f32, f32, f32, env)
 DEF_HELPER_3(rsqrts_f32, f32, f32, f32, env)
 DEF_HELPER_2(recpe_f32, f32, f32, env)
diff --git a/target-arm/kvm-consts.h b/target-arm/kvm-consts.h
new file mode 100644
index 0000000000..2bba0bd198
--- /dev/null
+++ b/target-arm/kvm-consts.h
@@ -0,0 +1,64 @@
+/*
+ * KVM ARM ABI constant definitions
+ *
+ * Copyright (c) 2013 Linaro Limited
+ *
+ * Provide versions of KVM constant defines that can be used even
+ * when CONFIG_KVM is not set and we don't have access to the
+ * KVM headers. If CONFIG_KVM is set, we do a compile-time check
+ * that we haven't got out of sync somehow.
+ *
+ * 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 ARM_KVM_CONSTS_H
+#define ARM_KVM_CONSTS_H
+
+#ifdef CONFIG_KVM
+#include "qemu/compiler.h"
+#include <linux/kvm.h>
+
+#define MISMATCH_CHECK(X, Y) QEMU_BUILD_BUG_ON(X != Y)
+
+#else
+#define MISMATCH_CHECK(X, Y)
+#endif
+
+#define CP_REG_SIZE_SHIFT 52
+#define CP_REG_SIZE_MASK       0x00f0000000000000ULL
+#define CP_REG_SIZE_U32        0x0020000000000000ULL
+#define CP_REG_SIZE_U64        0x0030000000000000ULL
+#define CP_REG_ARM             0x4000000000000000ULL
+
+MISMATCH_CHECK(CP_REG_SIZE_SHIFT, KVM_REG_SIZE_SHIFT)
+MISMATCH_CHECK(CP_REG_SIZE_MASK, KVM_REG_SIZE_MASK)
+MISMATCH_CHECK(CP_REG_SIZE_U32, KVM_REG_SIZE_U32)
+MISMATCH_CHECK(CP_REG_SIZE_U64, KVM_REG_SIZE_U64)
+MISMATCH_CHECK(CP_REG_ARM, KVM_REG_ARM)
+
+#define PSCI_FN_BASE 0x95c1ba5e
+#define PSCI_FN(n) (PSCI_FN_BASE + (n))
+#define PSCI_FN_CPU_SUSPEND PSCI_FN(0)
+#define PSCI_FN_CPU_OFF PSCI_FN(1)
+#define PSCI_FN_CPU_ON PSCI_FN(2)
+#define PSCI_FN_MIGRATE PSCI_FN(3)
+
+MISMATCH_CHECK(PSCI_FN_CPU_SUSPEND, KVM_PSCI_FN_CPU_SUSPEND)
+MISMATCH_CHECK(PSCI_FN_CPU_OFF, KVM_PSCI_FN_CPU_OFF)
+MISMATCH_CHECK(PSCI_FN_CPU_ON, KVM_PSCI_FN_CPU_ON)
+MISMATCH_CHECK(PSCI_FN_MIGRATE, KVM_PSCI_FN_MIGRATE)
+
+#define QEMU_KVM_ARM_TARGET_CORTEX_A15 0
+
+/* There's no kernel define for this: sentinel value which
+ * matches no KVM target value for either 64 or 32 bit
+ */
+#define QEMU_KVM_ARM_TARGET_NONE UINT_MAX
+
+#ifndef TARGET_AARCH64
+MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A15, KVM_ARM_TARGET_CORTEX_A15)
+#endif
+
+#undef MISMATCH_CHECK
+
+#endif
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index 6e5cd36fae..f865dac871 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -23,25 +23,240 @@
 #include "cpu.h"
 #include "hw/arm/arm.h"
 
-/* Check that cpu.h's idea of coprocessor fields matches KVM's */
-#if (CP_REG_SIZE_SHIFT != KVM_REG_SIZE_SHIFT) || \
-    (CP_REG_SIZE_MASK != KVM_REG_SIZE_MASK) ||   \
-    (CP_REG_SIZE_U32 != KVM_REG_SIZE_U32) || \
-    (CP_REG_SIZE_U64 != KVM_REG_SIZE_U64) || \
-    (CP_REG_ARM != KVM_REG_ARM)
-#error mismatch between cpu.h and KVM header definitions
-#endif
-
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
     KVM_CAP_LAST_INFO
 };
 
+bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
+                                      int *fdarray,
+                                      struct kvm_vcpu_init *init)
+{
+    int ret, kvmfd = -1, vmfd = -1, cpufd = -1;
+
+    kvmfd = qemu_open("/dev/kvm", O_RDWR);
+    if (kvmfd < 0) {
+        goto err;
+    }
+    vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0);
+    if (vmfd < 0) {
+        goto err;
+    }
+    cpufd = ioctl(vmfd, KVM_CREATE_VCPU, 0);
+    if (cpufd < 0) {
+        goto err;
+    }
+
+    ret = ioctl(vmfd, KVM_ARM_PREFERRED_TARGET, init);
+    if (ret >= 0) {
+        ret = ioctl(cpufd, KVM_ARM_VCPU_INIT, init);
+        if (ret < 0) {
+            goto err;
+        }
+    } else {
+        /* Old kernel which doesn't know about the
+         * PREFERRED_TARGET ioctl: we know it will only support
+         * creating one kind of guest CPU which is its preferred
+         * CPU type.
+         */
+        while (*cpus_to_try != QEMU_KVM_ARM_TARGET_NONE) {
+            init->target = *cpus_to_try++;
+            memset(init->features, 0, sizeof(init->features));
+            ret = ioctl(cpufd, KVM_ARM_VCPU_INIT, init);
+            if (ret >= 0) {
+                break;
+            }
+        }
+        if (ret < 0) {
+            goto err;
+        }
+    }
+
+    fdarray[0] = kvmfd;
+    fdarray[1] = vmfd;
+    fdarray[2] = cpufd;
+
+    return true;
+
+err:
+    if (cpufd >= 0) {
+        close(cpufd);
+    }
+    if (vmfd >= 0) {
+        close(vmfd);
+    }
+    if (kvmfd >= 0) {
+        close(kvmfd);
+    }
+
+    return false;
+}
+
+void kvm_arm_destroy_scratch_host_vcpu(int *fdarray)
+{
+    int i;
+
+    for (i = 2; i >= 0; i--) {
+        close(fdarray[i]);
+    }
+}
+
+static inline void set_feature(uint64_t *features, int feature)
+{
+    *features |= 1ULL << feature;
+}
+
+bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
+{
+    /* Identify the feature bits corresponding to the host CPU, and
+     * fill out the ARMHostCPUClass fields accordingly. To do this
+     * we have to create a scratch VM, create a single CPU inside it,
+     * and then query that CPU for the relevant ID registers.
+     */
+    int i, ret, fdarray[3];
+    uint32_t midr, id_pfr0, id_isar0, mvfr1;
+    uint64_t features = 0;
+    /* Old kernels may not know about the PREFERRED_TARGET ioctl: however
+     * we know these will only support creating one kind of guest CPU,
+     * which is its preferred CPU type.
+     */
+    static const uint32_t cpus_to_try[] = {
+        QEMU_KVM_ARM_TARGET_CORTEX_A15,
+        QEMU_KVM_ARM_TARGET_NONE
+    };
+    struct kvm_vcpu_init init;
+    struct kvm_one_reg idregs[] = {
+        {
+            .id = KVM_REG_ARM | KVM_REG_SIZE_U32
+            | ENCODE_CP_REG(15, 0, 0, 0, 0, 0),
+            .addr = (uintptr_t)&midr,
+        },
+        {
+            .id = KVM_REG_ARM | KVM_REG_SIZE_U32
+            | ENCODE_CP_REG(15, 0, 0, 1, 0, 0),
+            .addr = (uintptr_t)&id_pfr0,
+        },
+        {
+            .id = KVM_REG_ARM | KVM_REG_SIZE_U32
+            | ENCODE_CP_REG(15, 0, 0, 2, 0, 0),
+            .addr = (uintptr_t)&id_isar0,
+        },
+        {
+            .id = KVM_REG_ARM | KVM_REG_SIZE_U32
+            | KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR1,
+            .addr = (uintptr_t)&mvfr1,
+        },
+    };
+
+    if (!kvm_arm_create_scratch_host_vcpu(cpus_to_try, fdarray, &init)) {
+        return false;
+    }
+
+    ahcc->target = init.target;
+
+    /* This is not strictly blessed by the device tree binding docs yet,
+     * but in practice the kernel does not care about this string so
+     * there is no point maintaining an KVM_ARM_TARGET_* -> string table.
+     */
+    ahcc->dtb_compatible = "arm,arm-v7";
+
+    for (i = 0; i < ARRAY_SIZE(idregs); i++) {
+        ret = ioctl(fdarray[2], KVM_GET_ONE_REG, &idregs[i]);
+        if (ret) {
+            break;
+        }
+    }
+
+    kvm_arm_destroy_scratch_host_vcpu(fdarray);
+
+    if (ret) {
+        return false;
+    }
+
+    /* Now we've retrieved all the register information we can
+     * set the feature bits based on the ID register fields.
+     * We can assume any KVM supporting CPU is at least a v7
+     * with VFPv3, LPAE and the generic timers; this in turn implies
+     * most of the other feature bits, but a few must be tested.
+     */
+    set_feature(&features, ARM_FEATURE_V7);
+    set_feature(&features, ARM_FEATURE_VFP3);
+    set_feature(&features, ARM_FEATURE_LPAE);
+    set_feature(&features, ARM_FEATURE_GENERIC_TIMER);
+
+    switch (extract32(id_isar0, 24, 4)) {
+    case 1:
+        set_feature(&features, ARM_FEATURE_THUMB_DIV);
+        break;
+    case 2:
+        set_feature(&features, ARM_FEATURE_ARM_DIV);
+        set_feature(&features, ARM_FEATURE_THUMB_DIV);
+        break;
+    default:
+        break;
+    }
+
+    if (extract32(id_pfr0, 12, 4) == 1) {
+        set_feature(&features, ARM_FEATURE_THUMB2EE);
+    }
+    if (extract32(mvfr1, 20, 4) == 1) {
+        set_feature(&features, ARM_FEATURE_VFP_FP16);
+    }
+    if (extract32(mvfr1, 12, 4) == 1) {
+        set_feature(&features, ARM_FEATURE_NEON);
+    }
+    if (extract32(mvfr1, 28, 4) == 1) {
+        /* FMAC support implies VFPv4 */
+        set_feature(&features, ARM_FEATURE_VFP4);
+    }
+
+    ahcc->features = features;
+
+    return true;
+}
+
+static void kvm_arm_host_cpu_class_init(ObjectClass *oc, void *data)
+{
+    ARMHostCPUClass *ahcc = ARM_HOST_CPU_CLASS(oc);
+
+    /* All we really need to set up for the 'host' CPU
+     * is the feature bits -- we rely on the fact that the
+     * various ID register values in ARMCPU are only used for
+     * TCG CPUs.
+     */
+    if (!kvm_arm_get_host_cpu_features(ahcc)) {
+        fprintf(stderr, "Failed to retrieve host CPU features!\n");
+        abort();
+    }
+}
+
+static void kvm_arm_host_cpu_initfn(Object *obj)
+{
+    ARMHostCPUClass *ahcc = ARM_HOST_CPU_GET_CLASS(obj);
+    ARMCPU *cpu = ARM_CPU(obj);
+    CPUARMState *env = &cpu->env;
+
+    cpu->kvm_target = ahcc->target;
+    cpu->dtb_compatible = ahcc->dtb_compatible;
+    env->features = ahcc->features;
+}
+
+static const TypeInfo host_arm_cpu_type_info = {
+    .name = TYPE_ARM_HOST_CPU,
+    .parent = TYPE_ARM_CPU,
+    .instance_init = kvm_arm_host_cpu_initfn,
+    .class_init = kvm_arm_host_cpu_class_init,
+    .class_size = sizeof(ARMHostCPUClass),
+};
+
 int kvm_arch_init(KVMState *s)
 {
     /* For ARM interrupt delivery is always asynchronous,
      * whether we are using an in-kernel VGIC or not.
      */
     kvm_async_interrupts_allowed = true;
+
+    type_register_static(&host_arm_cpu_type_info);
+
     return 0;
 }
 
@@ -86,8 +301,16 @@ int kvm_arch_init_vcpu(CPUState *cs)
     struct kvm_reg_list *rlp;
     ARMCPU *cpu = ARM_CPU(cs);
 
-    init.target = KVM_ARM_TARGET_CORTEX_A15;
+    if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE) {
+        fprintf(stderr, "KVM is not supported for this guest CPU type\n");
+        return -EINVAL;
+    }
+
+    init.target = cpu->kvm_target;
     memset(init.features, 0, sizeof(init.features));
+    if (cpu->start_powered_off) {
+        init.features[0] = 1 << KVM_ARM_VCPU_POWER_OFF;
+    }
     ret = kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_INIT, &init);
     if (ret) {
         return ret;
diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h
index 5d14887e66..cd3d13ca2d 100644
--- a/target-arm/kvm_arm.h
+++ b/target-arm/kvm_arm.h
@@ -62,4 +62,59 @@ bool write_list_to_kvmstate(ARMCPU *cpu);
  */
 bool write_kvmstate_to_list(ARMCPU *cpu);
 
+#ifdef CONFIG_KVM
+/**
+ * kvm_arm_create_scratch_host_vcpu:
+ * @cpus_to_try: array of QEMU_KVM_ARM_TARGET_* values (terminated with
+ * QEMU_KVM_ARM_TARGET_NONE) to try as fallback if the kernel does not
+ * know the PREFERRED_TARGET ioctl
+ * @fdarray: filled in with kvmfd, vmfd, cpufd file descriptors in that order
+ * @init: filled in with the necessary values for creating a host vcpu
+ *
+ * Create a scratch vcpu in its own VM of the type preferred by the host
+ * kernel (as would be used for '-cpu host'), for purposes of probing it
+ * for capabilities.
+ *
+ * Returns: true on success (and fdarray and init are filled in),
+ * false on failure (and fdarray and init are not valid).
+ */
+bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
+                                      int *fdarray,
+                                      struct kvm_vcpu_init *init);
+
+/**
+ * kvm_arm_destroy_scratch_host_vcpu:
+ * @fdarray: array of fds as set up by kvm_arm_create_scratch_host_vcpu
+ *
+ * Tear down the scratch vcpu created by kvm_arm_create_scratch_host_vcpu.
+ */
+void kvm_arm_destroy_scratch_host_vcpu(int *fdarray);
+
+#define TYPE_ARM_HOST_CPU "host-" TYPE_ARM_CPU
+#define ARM_HOST_CPU_CLASS(klass) \
+    OBJECT_CLASS_CHECK(ARMHostCPUClass, (klass), TYPE_ARM_HOST_CPU)
+#define ARM_HOST_CPU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(ARMHostCPUClass, (obj), TYPE_ARM_HOST_CPU)
+
+typedef struct ARMHostCPUClass {
+    /*< private >*/
+    ARMCPUClass parent_class;
+    /*< public >*/
+
+    uint64_t features;
+    uint32_t target;
+    const char *dtb_compatible;
+} ARMHostCPUClass;
+
+/**
+ * kvm_arm_get_host_cpu_features:
+ * @ahcc: ARMHostCPUClass to fill in
+ *
+ * Probe the capabilities of the host kernel's preferred CPU and fill
+ * in the ARMHostCPUClass struct accordingly.
+ */
+bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc);
+
+#endif
+
 #endif
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 5f003e785e..8c479ff9a8 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -825,63 +825,57 @@ static inline void store_reg_from_load(CPUARMState *env, DisasContext *s,
  * extended if we're a 64 bit core) and  data is also
  * 32 bits unless specifically doing a 64 bit access.
  * These functions work like tcg_gen_qemu_{ld,st}* except
- * that their arguments are TCGv_i32 rather than TCGv.
+ * that the address argument is TCGv_i32 rather than TCGv.
  */
 #if TARGET_LONG_BITS == 32
 
-#define DO_GEN_LD(OP)                                                    \
-static inline void gen_aa32_##OP(TCGv_i32 val, TCGv_i32 addr, int index) \
+#define DO_GEN_LD(SUFF, OPC)                                             \
+static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
 {                                                                        \
-    tcg_gen_qemu_##OP(val, addr, index);                                 \
+    tcg_gen_qemu_ld_i32(val, addr, index, OPC);                          \
 }
 
-#define DO_GEN_ST(OP)                                                    \
-static inline void gen_aa32_##OP(TCGv_i32 val, TCGv_i32 addr, int index) \
+#define DO_GEN_ST(SUFF, OPC)                                             \
+static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
 {                                                                        \
-    tcg_gen_qemu_##OP(val, addr, index);                                 \
+    tcg_gen_qemu_st_i32(val, addr, index, OPC);                          \
 }
 
 static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
 {
-    tcg_gen_qemu_ld64(val, addr, index);
+    tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
 }
 
 static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
 {
-    tcg_gen_qemu_st64(val, addr, index);
+    tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
 }
 
 #else
 
-#define DO_GEN_LD(OP)                                                    \
-static inline void gen_aa32_##OP(TCGv_i32 val, TCGv_i32 addr, int index) \
+#define DO_GEN_LD(SUFF, OPC)                                             \
+static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
 {                                                                        \
     TCGv addr64 = tcg_temp_new();                                        \
-    TCGv val64 = tcg_temp_new();                                         \
     tcg_gen_extu_i32_i64(addr64, addr);                                  \
-    tcg_gen_qemu_##OP(val64, addr64, index);                             \
+    tcg_gen_qemu_ld_i32(val, addr64, index, OPC);                        \
     tcg_temp_free(addr64);                                               \
-    tcg_gen_trunc_i64_i32(val, val64);                                   \
-    tcg_temp_free(val64);                                                \
 }
 
-#define DO_GEN_ST(OP)                                                    \
-static inline void gen_aa32_##OP(TCGv_i32 val, TCGv_i32 addr, int index) \
+#define DO_GEN_ST(SUFF, OPC)                                             \
+static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
 {                                                                        \
     TCGv addr64 = tcg_temp_new();                                        \
-    TCGv val64 = tcg_temp_new();                                         \
     tcg_gen_extu_i32_i64(addr64, addr);                                  \
-    tcg_gen_extu_i32_i64(val64, val);                                    \
-    tcg_gen_qemu_##OP(val64, addr64, index);                             \
+    tcg_gen_qemu_st_i32(val, addr64, index, OPC);                        \
     tcg_temp_free(addr64);                                               \
-    tcg_temp_free(val64);                                                \
 }
 
 static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
 {
     TCGv addr64 = tcg_temp_new();
     tcg_gen_extu_i32_i64(addr64, addr);
-    tcg_gen_qemu_ld64(val, addr64, index);
+    tcg_gen_qemu_ld_i64(val, addr64, index, MO_TEQ);
     tcg_temp_free(addr64);
 }
 
@@ -889,20 +883,20 @@ static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
 {
     TCGv addr64 = tcg_temp_new();
     tcg_gen_extu_i32_i64(addr64, addr);
-    tcg_gen_qemu_st64(val, addr64, index);
+    tcg_gen_qemu_st_i64(val, addr64, index, MO_TEQ);
     tcg_temp_free(addr64);
 }
 
 #endif
 
-DO_GEN_LD(ld8s)
-DO_GEN_LD(ld8u)
-DO_GEN_LD(ld16s)
-DO_GEN_LD(ld16u)
-DO_GEN_LD(ld32u)
-DO_GEN_ST(st8)
-DO_GEN_ST(st16)
-DO_GEN_ST(st32)
+DO_GEN_LD(8s, MO_SB)
+DO_GEN_LD(8u, MO_UB)
+DO_GEN_LD(16s, MO_TESW)
+DO_GEN_LD(16u, MO_TEUW)
+DO_GEN_LD(32u, MO_TEUL)
+DO_GEN_ST(8, MO_UB)
+DO_GEN_ST(16, MO_TEUW)
+DO_GEN_ST(32, MO_TEUL)
 
 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
 {
@@ -2614,6 +2608,189 @@ static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
     return tmp;
 }
 
+static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
+                       uint32_t dp)
+{
+    uint32_t cc = extract32(insn, 20, 2);
+
+    if (dp) {
+        TCGv_i64 frn, frm, dest;
+        TCGv_i64 tmp, zero, zf, nf, vf;
+
+        zero = tcg_const_i64(0);
+
+        frn = tcg_temp_new_i64();
+        frm = tcg_temp_new_i64();
+        dest = tcg_temp_new_i64();
+
+        zf = tcg_temp_new_i64();
+        nf = tcg_temp_new_i64();
+        vf = tcg_temp_new_i64();
+
+        tcg_gen_extu_i32_i64(zf, cpu_ZF);
+        tcg_gen_ext_i32_i64(nf, cpu_NF);
+        tcg_gen_ext_i32_i64(vf, cpu_VF);
+
+        tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
+        tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
+        switch (cc) {
+        case 0: /* eq: Z */
+            tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
+                                frn, frm);
+            break;
+        case 1: /* vs: V */
+            tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
+                                frn, frm);
+            break;
+        case 2: /* ge: N == V -> N ^ V == 0 */
+            tmp = tcg_temp_new_i64();
+            tcg_gen_xor_i64(tmp, vf, nf);
+            tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
+                                frn, frm);
+            tcg_temp_free_i64(tmp);
+            break;
+        case 3: /* gt: !Z && N == V */
+            tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
+                                frn, frm);
+            tmp = tcg_temp_new_i64();
+            tcg_gen_xor_i64(tmp, vf, nf);
+            tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
+                                dest, frm);
+            tcg_temp_free_i64(tmp);
+            break;
+        }
+        tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
+        tcg_temp_free_i64(frn);
+        tcg_temp_free_i64(frm);
+        tcg_temp_free_i64(dest);
+
+        tcg_temp_free_i64(zf);
+        tcg_temp_free_i64(nf);
+        tcg_temp_free_i64(vf);
+
+        tcg_temp_free_i64(zero);
+    } else {
+        TCGv_i32 frn, frm, dest;
+        TCGv_i32 tmp, zero;
+
+        zero = tcg_const_i32(0);
+
+        frn = tcg_temp_new_i32();
+        frm = tcg_temp_new_i32();
+        dest = tcg_temp_new_i32();
+        tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
+        tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
+        switch (cc) {
+        case 0: /* eq: Z */
+            tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
+                                frn, frm);
+            break;
+        case 1: /* vs: V */
+            tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
+                                frn, frm);
+            break;
+        case 2: /* ge: N == V -> N ^ V == 0 */
+            tmp = tcg_temp_new_i32();
+            tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
+            tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
+                                frn, frm);
+            tcg_temp_free_i32(tmp);
+            break;
+        case 3: /* gt: !Z && N == V */
+            tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
+                                frn, frm);
+            tmp = tcg_temp_new_i32();
+            tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
+            tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
+                                dest, frm);
+            tcg_temp_free_i32(tmp);
+            break;
+        }
+        tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
+        tcg_temp_free_i32(frn);
+        tcg_temp_free_i32(frm);
+        tcg_temp_free_i32(dest);
+
+        tcg_temp_free_i32(zero);
+    }
+
+    return 0;
+}
+
+static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
+                            uint32_t rm, uint32_t dp)
+{
+    uint32_t vmin = extract32(insn, 6, 1);
+    TCGv_ptr fpst = get_fpstatus_ptr(0);
+
+    if (dp) {
+        TCGv_i64 frn, frm, dest;
+
+        frn = tcg_temp_new_i64();
+        frm = tcg_temp_new_i64();
+        dest = tcg_temp_new_i64();
+
+        tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
+        tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
+        if (vmin) {
+            gen_helper_vfp_minnmd(dest, frn, frm, fpst);
+        } else {
+            gen_helper_vfp_maxnmd(dest, frn, frm, fpst);
+        }
+        tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
+        tcg_temp_free_i64(frn);
+        tcg_temp_free_i64(frm);
+        tcg_temp_free_i64(dest);
+    } else {
+        TCGv_i32 frn, frm, dest;
+
+        frn = tcg_temp_new_i32();
+        frm = tcg_temp_new_i32();
+        dest = tcg_temp_new_i32();
+
+        tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
+        tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
+        if (vmin) {
+            gen_helper_vfp_minnms(dest, frn, frm, fpst);
+        } else {
+            gen_helper_vfp_maxnms(dest, frn, frm, fpst);
+        }
+        tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
+        tcg_temp_free_i32(frn);
+        tcg_temp_free_i32(frm);
+        tcg_temp_free_i32(dest);
+    }
+
+    tcg_temp_free_ptr(fpst);
+    return 0;
+}
+
+static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
+{
+    uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
+
+    if (!arm_feature(env, ARM_FEATURE_V8)) {
+        return 1;
+    }
+
+    if (dp) {
+        VFP_DREG_D(rd, insn);
+        VFP_DREG_N(rn, insn);
+        VFP_DREG_M(rm, insn);
+    } else {
+        rd = VFP_SREG_D(insn);
+        rn = VFP_SREG_N(insn);
+        rm = VFP_SREG_M(insn);
+    }
+
+    if ((insn & 0x0f800e50) == 0x0e000a00) {
+        return handle_vsel(insn, rd, rn, rm, dp);
+    } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
+        return handle_vminmaxnm(insn, rd, rn, rm, dp);
+    }
+    return 1;
+}
+
 /* Disassemble a VFP instruction.  Returns nonzero if an error occurred
    (ie. an undefined instruction).  */
 static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
@@ -2636,6 +2813,14 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
             && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
             return 1;
     }
+
+    if (extract32(insn, 28, 4) == 0xf) {
+        /* Encodings with T=1 (Thumb) or unconditional (ARM):
+         * only used in v8 and above.
+         */
+        return disas_vfp_v8_insn(env, s, insn);
+    }
+
     dp = ((insn & 0xf00) == 0xb00);
     switch ((insn >> 24) & 0xf) {
     case 0xe:
@@ -4362,7 +4547,7 @@ static void gen_neon_narrow_op(int op, int u, int size,
 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
-#define NEON_3R_VRECPS_VRSQRTS 31 /* float VRECPS, VRSQRTS */
+#define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
 
 static const uint8_t neon_3r_sizes[] = {
     [NEON_3R_VHADD] = 0x7,
@@ -4395,7 +4580,7 @@ static const uint8_t neon_3r_sizes[] = {
     [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
     [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
     [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
-    [NEON_3R_VRECPS_VRSQRTS] = 0x5, /* size bit 1 encodes op */
+    [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
 };
 
 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
@@ -4656,8 +4841,9 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
                 return 1;
             }
             break;
-        case NEON_3R_VRECPS_VRSQRTS:
-            if (u) {
+        case NEON_3R_FLOAT_MISC:
+            /* VMAXNM/VMINNM in ARMv8 */
+            if (u && !arm_feature(env, ARM_FEATURE_V8)) {
                 return 1;
             }
             break;
@@ -4946,11 +5132,23 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
             tcg_temp_free_ptr(fpstatus);
             break;
         }
-        case NEON_3R_VRECPS_VRSQRTS:
-            if (size == 0)
-                gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
-            else
-                gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
+        case NEON_3R_FLOAT_MISC:
+            if (u) {
+                /* VMAXNM/VMINNM */
+                TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+                if (size == 0) {
+                    gen_helper_vfp_maxnms(tmp, tmp, tmp2, fpstatus);
+                } else {
+                    gen_helper_vfp_minnms(tmp, tmp, tmp2, fpstatus);
+                }
+                tcg_temp_free_ptr(fpstatus);
+            } else {
+                if (size == 0) {
+                    gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
+                } else {
+                    gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
+              }
+            }
             break;
         case NEON_3R_VFM:
         {
@@ -6296,9 +6494,6 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
 	    return disas_dsp_insn(env, s, insn);
 	}
 	return 1;
-    case 10:
-    case 11:
-	return disas_vfp_insn (env, s, insn);
     default:
         break;
     }
@@ -6753,6 +6948,13 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
                 goto illegal_op;
             return;
         }
+        if ((insn & 0x0f000e10) == 0x0e000a00) {
+            /* VFP.  */
+            if (disas_vfp_insn(env, s, insn)) {
+                goto illegal_op;
+            }
+            return;
+        }
         if (((insn & 0x0f30f000) == 0x0510f000) ||
             ((insn & 0x0f30f010) == 0x0710f000)) {
             if ((insn & (1 << 22)) == 0) {
@@ -8033,9 +8235,15 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
         case 0xc:
         case 0xd:
         case 0xe:
-            /* Coprocessor.  */
-            if (disas_coproc_insn(env, s, insn))
+            if (((insn >> 8) & 0xe) == 10) {
+                /* VFP.  */
+                if (disas_vfp_insn(env, s, insn)) {
+                    goto illegal_op;
+                }
+            } else if (disas_coproc_insn(env, s, insn)) {
+                /* Coprocessor.  */
                 goto illegal_op;
+            }
             break;
         case 0xf:
             /* swi */
@@ -8765,6 +8973,10 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
             insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
             if (disas_neon_data_insn(env, s, insn))
                 goto illegal_op;
+        } else if (((insn >> 8) & 0xe) == 10) {
+            if (disas_vfp_insn(env, s, insn)) {
+                goto illegal_op;
+            }
         } else {
             if (insn & (1 << 28))
                 goto illegal_op;
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 5faa44c1ea..f990d591c7 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -1133,7 +1133,7 @@ static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr)
         cris_store_direct_jmp(dc);
     }
 
-    tcg_gen_qemu_ld64(dst, addr, mem_index);
+    tcg_gen_qemu_ld_i64(dst, addr, mem_index, MO_TEQ);
 }
 
 static void gen_load(DisasContext *dc, TCGv dst, TCGv addr, 
@@ -1147,23 +1147,8 @@ static void gen_load(DisasContext *dc, TCGv dst, TCGv addr,
         cris_store_direct_jmp(dc);
     }
 
-    if (size == 1) {
-        if (sign) {
-            tcg_gen_qemu_ld8s(dst, addr, mem_index);
-        } else {
-            tcg_gen_qemu_ld8u(dst, addr, mem_index);
-        }
-    } else if (size == 2) {
-        if (sign) {
-            tcg_gen_qemu_ld16s(dst, addr, mem_index);
-        } else {
-            tcg_gen_qemu_ld16u(dst, addr, mem_index);
-        }
-    } else if (size == 4) {
-        tcg_gen_qemu_ld32u(dst, addr, mem_index);
-    } else {
-        abort();
-    }
+    tcg_gen_qemu_ld_tl(dst, addr, mem_index,
+                       MO_TE + ctz32(size) + (sign ? MO_SIGN : 0));
 }
 
 static void gen_store (DisasContext *dc, TCGv addr, TCGv val,
@@ -1187,13 +1172,7 @@ static void gen_store (DisasContext *dc, TCGv addr, TCGv val,
         return;
     }
 
-    if (size == 1) {
-        tcg_gen_qemu_st8(val, addr, mem_index);
-    } else if (size == 2) {
-        tcg_gen_qemu_st16(val, addr, mem_index);
-    } else {
-        tcg_gen_qemu_st32(val, addr, mem_index);
-    }
+    tcg_gen_qemu_st_tl(val, addr, mem_index, MO_TE + ctz32(size));
 
     if (dc->flagx_known && dc->flags_x) {
         cris_evaluate_flags(dc);
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 47af9a8816..bb98f6defc 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -335,7 +335,7 @@ typedef struct ExtSaveArea {
 
 static const ExtSaveArea ext_save_areas[] = {
     [2] = { .feature = FEAT_1_ECX, .bits = CPUID_EXT_AVX,
-            .offset = 0x100, .size = 0x240 },
+            .offset = 0x240, .size = 0x100 },
 };
 
 const char *get_register_name_32(unsigned int reg)
@@ -2227,8 +2227,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
             const ExtSaveArea *esa = &ext_save_areas[count];
             if ((env->features[esa->feature] & esa->bits) == esa->bits &&
                 (kvm_mask & (1 << count)) != 0) {
-                *eax = esa->offset;
-                *ebx = esa->size;
+                *eax = esa->size;
+                *ebx = esa->offset;
             }
         }
         break;
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 9edcb67e66..270138c6d2 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -864,26 +864,6 @@ static void dec_imm(DisasContext *dc)
     dc->clear_imm = 0;
 }
 
-static inline void gen_load(DisasContext *dc, TCGv dst, TCGv addr,
-                            unsigned int size, bool exclusive)
-{
-    int mem_index = cpu_mmu_index(dc->env);
-
-    if (size == 1) {
-        tcg_gen_qemu_ld8u(dst, addr, mem_index);
-    } else if (size == 2) {
-        tcg_gen_qemu_ld16u(dst, addr, mem_index);
-    } else if (size == 4) {
-        tcg_gen_qemu_ld32u(dst, addr, mem_index);
-    } else
-        cpu_abort(dc->env, "Incorrect load size %d\n", size);
-
-    if (exclusive) {
-        tcg_gen_mov_tl(env_res_addr, addr);
-        tcg_gen_mov_tl(env_res_val, dst);
-    }
-}
-
 static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
 {
     unsigned int extimm = dc->tb_flags & IMM_FLAG;
@@ -935,35 +915,22 @@ static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
     return t;
 }
 
-static inline void dec_byteswap(DisasContext *dc, TCGv dst, TCGv src, int size)
-{
-    if (size == 4) {
-        tcg_gen_bswap32_tl(dst, src);
-    } else if (size == 2) {
-        TCGv t = tcg_temp_new();
-
-        /* bswap16 assumes the high bits are zero.  */
-        tcg_gen_andi_tl(t, src, 0xffff);
-        tcg_gen_bswap16_tl(dst, t);
-        tcg_temp_free(t);
-    } else {
-        /* Ignore.
-        cpu_abort(dc->env, "Invalid ldst byteswap size %d\n", size);
-        */
-    }
-}
-
 static void dec_load(DisasContext *dc)
 {
-    TCGv t, *addr;
+    TCGv t, v, *addr;
     unsigned int size, rev = 0, ex = 0;
+    TCGMemOp mop;
 
-    size = 1 << (dc->opcode & 3);
-
+    mop = dc->opcode & 3;
+    size = 1 << mop;
     if (!dc->type_b) {
         rev = (dc->ir >> 9) & 1;
         ex = (dc->ir >> 10) & 1;
     }
+    mop |= MO_TE;
+    if (rev) {
+        mop ^= MO_BSWAP;
+    }
 
     if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
           && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
@@ -1044,40 +1011,30 @@ static void dec_load(DisasContext *dc)
     sync_jmpstate(dc);
 
     /* Verify alignment if needed.  */
-    if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
-        TCGv v = tcg_temp_new();
-
-        /*
-         * Microblaze gives MMU faults priority over faults due to
-         * unaligned addresses. That's why we speculatively do the load
-         * into v. If the load succeeds, we verify alignment of the
-         * address and if that succeeds we write into the destination reg.
-         */
-        gen_load(dc, v, *addr, size, ex);
+    /*
+     * Microblaze gives MMU faults priority over faults due to
+     * unaligned addresses. That's why we speculatively do the load
+     * into v. If the load succeeds, we verify alignment of the
+     * address and if that succeeds we write into the destination reg.
+     */
+    v = tcg_temp_new();
+    tcg_gen_qemu_ld_tl(v, *addr, cpu_mmu_index(dc->env), mop);
 
+    if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
         tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
         gen_helper_memalign(cpu_env, *addr, tcg_const_tl(dc->rd),
                             tcg_const_tl(0), tcg_const_tl(size - 1));
-        if (dc->rd) {
-            if (rev) {
-                dec_byteswap(dc, cpu_R[dc->rd], v, size);
-            } else {
-                tcg_gen_mov_tl(cpu_R[dc->rd], v);
-            }
-        }
-        tcg_temp_free(v);
-    } else {
-        if (dc->rd) {
-            gen_load(dc, cpu_R[dc->rd], *addr, size, ex);
-            if (rev) {
-                dec_byteswap(dc, cpu_R[dc->rd], cpu_R[dc->rd], size);
-            }
-        } else {
-            /* We are loading into r0, no need to reverse.  */
-            gen_load(dc, env_imm, *addr, size, ex);
-        }
     }
 
+    if (ex) {
+        tcg_gen_mov_tl(env_res_addr, *addr);
+        tcg_gen_mov_tl(env_res_val, v);
+    }
+    if (dc->rd) {
+        tcg_gen_mov_tl(cpu_R[dc->rd], v);
+    }
+    tcg_temp_free(v);
+
     if (ex) { /* lwx */
         /* no support for for AXI exclusive so always clear C */
         write_carryi(dc, 0);
@@ -1087,32 +1044,23 @@ static void dec_load(DisasContext *dc)
         tcg_temp_free(t);
 }
 
-static void gen_store(DisasContext *dc, TCGv addr, TCGv val,
-                      unsigned int size)
-{
-    int mem_index = cpu_mmu_index(dc->env);
-
-    if (size == 1)
-        tcg_gen_qemu_st8(val, addr, mem_index);
-    else if (size == 2) {
-        tcg_gen_qemu_st16(val, addr, mem_index);
-    } else if (size == 4) {
-        tcg_gen_qemu_st32(val, addr, mem_index);
-    } else
-        cpu_abort(dc->env, "Incorrect store size %d\n", size);
-}
-
 static void dec_store(DisasContext *dc)
 {
     TCGv t, *addr, swx_addr;
     int swx_skip = 0;
     unsigned int size, rev = 0, ex = 0;
+    TCGMemOp mop;
 
-    size = 1 << (dc->opcode & 3);
+    mop = dc->opcode & 3;
+    size = 1 << mop;
     if (!dc->type_b) {
         rev = (dc->ir >> 9) & 1;
         ex = (dc->ir >> 10) & 1;
     }
+    mop |= MO_TE;
+    if (rev) {
+        mop ^= MO_BSWAP;
+    }
 
     if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
           && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
@@ -1148,7 +1096,7 @@ static void dec_store(DisasContext *dc)
            this compare and the following write to be atomic. For user
            emulation we need to add atomicity between threads.  */
         tval = tcg_temp_new();
-        gen_load(dc, tval, swx_addr, 4, false);
+        tcg_gen_qemu_ld_tl(tval, swx_addr, cpu_mmu_index(dc->env), MO_TEUL);
         tcg_gen_brcond_tl(TCG_COND_NE, env_res_val, tval, swx_skip);
         write_carryi(dc, 0);
         tcg_temp_free(tval);
@@ -1197,25 +1145,8 @@ static void dec_store(DisasContext *dc)
                 cpu_abort(dc->env, "Invalid reverse size\n");
                 break;
         }
-
-        if (size != 1) {
-            TCGv bs_data = tcg_temp_new();
-            dec_byteswap(dc, bs_data, cpu_R[dc->rd], size);
-            gen_store(dc, *addr, bs_data, size);
-            tcg_temp_free(bs_data);
-        } else {
-            gen_store(dc, *addr, cpu_R[dc->rd], size);
-        }
-    } else {
-        if (rev) {
-            TCGv bs_data = tcg_temp_new();
-            dec_byteswap(dc, bs_data, cpu_R[dc->rd], size);
-            gen_store(dc, *addr, bs_data, size);
-            tcg_temp_free(bs_data);
-        } else {
-            gen_store(dc, *addr, cpu_R[dc->rd], size);
-        }
     }
+    tcg_gen_qemu_st_tl(cpu_R[dc->rd], *addr, cpu_mmu_index(dc->env), mop);
 
     /* Verify alignment if needed.  */
     if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index a29c82faf1..9caf4474b9 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -476,7 +476,7 @@ struct CPUMIPSState {
 
     const mips_def_t *cpu_model;
     void *irq[8];
-    struct QEMUTimer *timer; /* Internal timer */
+    QEMUTimer *timer; /* Internal timer */
 };
 
 #include "cpu-qom.h"
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index b088a25017..a2f46d9637 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -1088,12 +1088,11 @@ static inline int32_t mipsdsp_cmpu_lt(uint32_t a, uint32_t b)
 target_ulong helper_##name(target_ulong rt, CPUMIPSState *env)             \
 {                                                                          \
     DSP32Value dt;                                                         \
-    unsigned int i, n;                                                     \
+    unsigned int i;                                                     \
                                                                            \
-    n = sizeof(DSP32Value) / sizeof(dt.element[0]);                        \
     dt.sw[0] = rt;                                                         \
                                                                            \
-    for (i = 0; i < n; i++) {                                              \
+    for (i = 0; i < ARRAY_SIZE(dt.element); i++) {                         \
         dt.element[i] = mipsdsp_##func(dt.element[i], env);                \
     }                                                                      \
                                                                            \
@@ -1109,12 +1108,11 @@ MIPSDSP32_UNOP_ENV(absq_s_w, sat_abs32, sw)
 target_ulong helper_##name(target_ulong rt, CPUMIPSState *env)             \
 {                                                                          \
     DSP64Value dt;                                                         \
-    unsigned int i, n;                                                     \
+    unsigned int i;                                                        \
                                                                            \
-    n = sizeof(DSP64Value) / sizeof(dt.element[0]);                        \
     dt.sl[0] = rt;                                                         \
                                                                            \
-    for (i = 0; i < n; i++) {                                              \
+    for (i = 0; i < ARRAY_SIZE(dt.element); i++) {                         \
         dt.element[i] = mipsdsp_##func(dt.element[i], env);                \
     }                                                                      \
                                                                            \
@@ -1130,13 +1128,12 @@ MIPSDSP64_UNOP_ENV(absq_s_pw, sat_abs32, sw)
 target_ulong helper_##name(target_ulong rs, target_ulong rt)               \
 {                                                                          \
     DSP32Value ds, dt;                                                     \
-    unsigned int i, n;                                                     \
+    unsigned int i;                                                        \
                                                                            \
-    n = sizeof(DSP32Value) / sizeof(ds.element[0]);                        \
     ds.sw[0] = rs;                                                         \
     dt.sw[0] = rt;                                                         \
                                                                            \
-    for (i = 0; i < n; i++) {                                              \
+    for (i = 0; i < ARRAY_SIZE(ds.element); i++) {                         \
         ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]);      \
     }                                                                      \
                                                                            \
@@ -1159,13 +1156,12 @@ target_ulong helper_##name(target_ulong rs, target_ulong rt,               \
                            CPUMIPSState *env)                              \
 {                                                                          \
     DSP32Value ds, dt;                                                     \
-    unsigned int i, n;                                                     \
+    unsigned int i;                                                        \
                                                                            \
-    n = sizeof(DSP32Value) / sizeof(ds.element[0]);                        \
     ds.sw[0] = rs;                                                         \
     dt.sw[0] = rt;                                                         \
                                                                            \
-    for (i = 0 ; i < n ; i++) {                                            \
+    for (i = 0 ; i < ARRAY_SIZE(ds.element); i++) {                        \
         ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \
     }                                                                      \
                                                                            \
@@ -1192,13 +1188,12 @@ MIPSDSP32_BINOP_ENV(subu_s_qb, satu8_sub, ub);
 target_ulong helper_##name(target_ulong rs, target_ulong rt)               \
 {                                                                          \
     DSP64Value ds, dt;                                                     \
-    unsigned int i, n;                                                     \
+    unsigned int i;                                                        \
                                                                            \
-    n = sizeof(DSP64Value) / sizeof(ds.element[0]);                        \
     ds.sl[0] = rs;                                                         \
     dt.sl[0] = rt;                                                         \
                                                                            \
-    for (i = 0 ; i < n ; i++) {                                            \
+    for (i = 0 ; i < ARRAY_SIZE(ds.element); i++) {                        \
         ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]);      \
     }                                                                      \
                                                                            \
@@ -1215,13 +1210,12 @@ target_ulong helper_##name(target_ulong rs, target_ulong rt,               \
                            CPUMIPSState *env)                              \
 {                                                                          \
     DSP64Value ds, dt;                                                     \
-    unsigned int i, n;                                                     \
+    unsigned int i;                                                        \
                                                                            \
-    n = sizeof(DSP64Value) / sizeof(ds.element[0]);                        \
     ds.sl[0] = rs;                                                         \
     dt.sl[0] = rt;                                                         \
                                                                            \
-    for (i = 0 ; i < n ; i++) {                                            \
+    for (i = 0 ; i < ARRAY_SIZE(ds.element); i++) {                        \
         ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \
     }                                                                      \
                                                                            \
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 67f326b205..e30273438a 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15983,10 +15983,13 @@ void cpu_state_reset(CPUMIPSState *env)
     if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
         env->CP0_Status |= (1 << CP0St_MX);
     }
-    /* Enable 64-bit FPU if the target cpu supports it.  */
-    if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
+# if defined(TARGET_MIPS64)
+    /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
+    if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
+        (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
         env->CP0_Status |= (1 << CP0St_FR);
     }
+# endif
 #else
     if (env->hflags & MIPS_HFLAG_BMASK) {
         /* If the exception was raised from a delay slot,
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 0f9efdf6de..51d6afd153 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -307,7 +307,7 @@ typedef struct CPUOpenRISCState {
 #ifndef CONFIG_USER_ONLY
     CPUOpenRISCTLBContext * tlb;
 
-    struct QEMUTimer *timer;
+    QEMUTimer *timer;
     uint32_t ttmr;          /* Timer tick mode register */
     uint32_t ttcr;          /* Timer tick count register */
 
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 276d2955c3..c181ddacf5 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -157,9 +157,6 @@ typedef struct CPUSH4State {
     /* float point status register */
     float_status fp_status;
 
-    /* The features that we should emulate. See sh_features above.  */
-    uint32_t features;
-
     /* Those belong to the specific unit (SH7750) but are handled here */
     uint32_t mmucr;		/* MMU control register */
     uint32_t pteh;		/* page table entry high register */
@@ -180,6 +177,9 @@ typedef struct CPUSH4State {
 
     int id;			/* CPU model */
 
+    /* The features that we should emulate. See sh_features above.  */
+    uint32_t features;
+
     void *intc_handle;
     int in_sleep;		/* SR_BL ignored during sleep */
     memory_content *movcal_backup;
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 41194ec06b..c519063ba9 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -370,7 +370,7 @@ struct CPUTimer
     uint32_t    disabled;
     uint64_t    disabled_mask;
     int64_t     clock_offset;
-    struct QEMUTimer  *qtimer;
+    QEMUTimer  *qtimer;
 };
 
 typedef struct CPUTimer CPUTimer;
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index e93a4a237b..82658a170c 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -22,6 +22,7 @@
  * THE SOFTWARE.
  */
 
+#include "elf.h"
 #include "tcg-be-ldst.h"
 
 /* The __ARM_ARCH define is provided by gcc 4.8.  Construct it otherwise.  */
@@ -58,9 +59,6 @@ static int arm_arch = __ARM_ARCH;
 #ifndef use_idiv_instructions
 bool use_idiv_instructions;
 #endif
-#ifdef CONFIG_GETAUXVAL
-# include <sys/auxv.h>
-#endif
 
 #ifndef NDEBUG
 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
@@ -2036,22 +2034,20 @@ static const TCGTargetOpDef arm_op_defs[] = {
 
 static void tcg_target_init(TCGContext *s)
 {
-#if defined(CONFIG_GETAUXVAL)
     /* Only probe for the platform and capabilities if we havn't already
        determined maximum values at compile time.  */
-# if !defined(use_idiv_instructions)
+#ifndef use_idiv_instructions
     {
-        unsigned long hwcap = getauxval(AT_HWCAP);
+        unsigned long hwcap = qemu_getauxval(AT_HWCAP);
         use_idiv_instructions = (hwcap & HWCAP_ARM_IDIVA) != 0;
     }
-# endif
+#endif
     if (__ARM_ARCH < 7) {
-        const char *pl = (const char *)getauxval(AT_PLATFORM);
+        const char *pl = (const char *)qemu_getauxval(AT_PLATFORM);
         if (pl != NULL && pl[0] == 'v' && pl[1] >= '4' && pl[1] <= '9') {
             arm_arch = pl[1] - '0';
         }
     }
-#endif /* GETAUXVAL */
 
     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
     tcg_regset_set32(tcg_target_call_clobber_regs, 0,
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 6109d862db..06e440f9bc 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -45,15 +45,10 @@ static uint8_t *tb_ret_addr;
 #define GUEST_BASE 0
 #endif
 
-#ifdef CONFIG_GETAUXVAL
-#include <sys/auxv.h>
+#include "elf.h"
 static bool have_isa_2_06;
 #define HAVE_ISA_2_06  have_isa_2_06
 #define HAVE_ISEL      have_isa_2_06
-#else
-#define HAVE_ISA_2_06  0
-#define HAVE_ISEL      0
-#endif
 
 #ifdef CONFIG_USE_GUEST_BASE
 #define TCG_GUEST_BASE_REG 30
@@ -2132,12 +2127,10 @@ static const TCGTargetOpDef ppc_op_defs[] = {
 
 static void tcg_target_init(TCGContext *s)
 {
-#ifdef CONFIG_GETAUXVAL
-    unsigned long hwcap = getauxval(AT_HWCAP);
+    unsigned long hwcap = qemu_getauxval(AT_HWCAP);
     if (hwcap & PPC_FEATURE_ARCH_2_06) {
         have_isa_2_06 = true;
     }
-#endif
 
     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 0a4f3be0e9..248726e82f 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -31,6 +31,8 @@
 #error "unsupported code generation mode"
 #endif
 
+#include "elf.h"
+
 /* ??? The translation blocks produced by TCG are generally small enough to
    be entirely reachable with a 16-bit displacement.  Leaving the option for
    a 32-bit displacement here Just In Case.  */
@@ -2233,91 +2235,18 @@ static void sigill_handler(int sig)
 
 static void query_facilities(void)
 {
-    struct sigaction sa_old, sa_new;
-    register int r0 __asm__("0");
-    register void *r1 __asm__("1");
-    int fail;
-
-    memset(&sa_new, 0, sizeof(sa_new));
-    sa_new.sa_handler = sigill_handler;
-    sigaction(SIGILL, &sa_new, &sa_old);
-
-    /* First, try STORE FACILITY LIST EXTENDED.  If this is present, then
-       we need not do any more probing.  Unfortunately, this itself is an
-       extension and the original STORE FACILITY LIST instruction is
-       kernel-only, storing its results at absolute address 200.  */
-    /* stfle 0(%r1) */
-    r1 = &facilities;
-    asm volatile(".word 0xb2b0,0x1000"
-                 : "=r"(r0) : "0"(0), "r"(r1) : "memory", "cc");
-
-    if (got_sigill) {
-        /* STORE FACILITY EXTENDED is not available.  Probe for one of each
-           kind of instruction that we're interested in.  */
-        /* ??? Possibly some of these are in practice never present unless
-           the store-facility-extended facility is also present.  But since
-           that isn't documented it's just better to probe for each.  */
-
-        /* Test for z/Architecture.  Required even in 31-bit mode.  */
-        got_sigill = 0;
-        /* agr %r0,%r0 */
-        asm volatile(".word 0xb908,0x0000" : "=r"(r0) : : "cc");
-        if (!got_sigill) {
-            facilities |= FACILITY_ZARCH_ACTIVE;
-        }
-
-        /* Test for long displacement.  */
-        got_sigill = 0;
-        /* ly %r0,0(%r1) */
-        r1 = &facilities;
-        asm volatile(".word 0xe300,0x1000,0x0058"
-                     : "=r"(r0) : "r"(r1) : "cc");
-        if (!got_sigill) {
-            facilities |= FACILITY_LONG_DISP;
-        }
-
-        /* Test for extended immediates.  */
-        got_sigill = 0;
-        /* afi %r0,0 */
-        asm volatile(".word 0xc209,0x0000,0x0000" : : : "cc");
-        if (!got_sigill) {
-            facilities |= FACILITY_EXT_IMM;
-        }
-
-        /* Test for general-instructions-extension.  */
-        got_sigill = 0;
-        /* msfi %r0,1 */
-        asm volatile(".word 0xc201,0x0000,0x0001");
-        if (!got_sigill) {
-            facilities |= FACILITY_GEN_INST_EXT;
-        }
-    }
-
-    sigaction(SIGILL, &sa_old, NULL);
+    unsigned long hwcap = qemu_getauxval(AT_HWCAP);
 
-    /* The translator currently uses these extensions unconditionally.
-       Pruning this back to the base ESA/390 architecture doesn't seem
-       worthwhile, since even the KVM target requires z/Arch.  */
-    fail = 0;
-    if ((facilities & FACILITY_ZARCH_ACTIVE) == 0) {
-        fprintf(stderr, "TCG: z/Arch facility is required.\n");
-        fprintf(stderr, "TCG: Boot with a 64-bit enabled kernel.\n");
-        fail = 1;
-    }
-    if ((facilities & FACILITY_LONG_DISP) == 0) {
-        fprintf(stderr, "TCG: long-displacement facility is required.\n");
-        fail = 1;
-    }
+    /* Is STORE FACILITY LIST EXTENDED available?  Honestly, I believe this
+       is present on all 64-bit systems, but let's check for it anyway.  */
+    if (hwcap & HWCAP_S390_STFLE) {
+        register int r0 __asm__("0");
+        register void *r1 __asm__("1");
 
-    /* So far there's just enough support for 31-bit mode to let the
-       compile succeed.  This is good enough to run QEMU with KVM.  */
-    if (sizeof(void *) != 8) {
-        fprintf(stderr, "TCG: 31-bit mode is not supported.\n");
-        fail = 1;
-    }
-
-    if (fail) {
-        exit(-1);
+        /* stfle 0(%r1) */
+        r1 = &facilities;
+        asm volatile(".word 0xb2b0,0x1000"
+                     : "=r"(r0) : "0"(0), "r"(r1) : "memory", "cc");
     }
 }
 
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 66d3f3de80..712438ced8 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -357,11 +357,12 @@ void tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size)
 
 void tcg_func_start(TCGContext *s)
 {
-    int i;
     tcg_pool_reset(s);
     s->nb_temps = s->nb_globals;
-    for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
-        s->first_free_temp[i] = -1;
+
+    /* No temps have been previously allocated for size or locality.  */
+    memset(s->free_temps, 0, sizeof(s->free_temps));
+
     s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
     s->nb_labels = 0;
     s->current_frame_offset = s->frame_start;
@@ -503,16 +504,15 @@ static inline int tcg_temp_new_internal(TCGType type, int temp_local)
     TCGTemp *ts;
     int idx, k;
 
-    k = type;
-    if (temp_local)
-        k += TCG_TYPE_COUNT;
-    idx = s->first_free_temp[k];
-    if (idx != -1) {
-        /* There is already an available temp with the
-           right type */
+    k = type + (temp_local ? TCG_TYPE_COUNT : 0);
+    idx = find_first_bit(s->free_temps[k].l, TCG_MAX_TEMPS);
+    if (idx < TCG_MAX_TEMPS) {
+        /* There is already an available temp with the right type.  */
+        clear_bit(idx, s->free_temps[k].l);
+
         ts = &s->temps[idx];
-        s->first_free_temp[k] = ts->next_free_temp;
         ts->temp_allocated = 1;
+        assert(ts->base_type == type);
         assert(ts->temp_local == temp_local);
     } else {
         idx = s->nb_temps;
@@ -568,7 +568,7 @@ TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
     return MAKE_TCGV_I64(idx);
 }
 
-static inline void tcg_temp_free_internal(int idx)
+static void tcg_temp_free_internal(int idx)
 {
     TCGContext *s = &tcg_ctx;
     TCGTemp *ts;
@@ -585,11 +585,9 @@ static inline void tcg_temp_free_internal(int idx)
     ts = &s->temps[idx];
     assert(ts->temp_allocated != 0);
     ts->temp_allocated = 0;
-    k = ts->base_type;
-    if (ts->temp_local)
-        k += TCG_TYPE_COUNT;
-    ts->next_free_temp = s->first_free_temp[k];
-    s->first_free_temp[k] = idx;
+
+    k = ts->type + (ts->temp_local ? TCG_TYPE_COUNT : 0);
+    set_bit(idx, s->free_temps[k].l);
 }
 
 void tcg_temp_free_i32(TCGv_i32 arg)
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 0d9bd293b5..c72af6cfb7 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -26,7 +26,7 @@
 #define TCG_H
 
 #include "qemu-common.h"
-
+#include "qemu/bitops.h"
 #include "tcg-target.h"
 
 /* Default target word size to pointer size.  */
@@ -436,13 +436,15 @@ typedef struct TCGTemp {
                                   basic blocks. Otherwise, it is not
                                   preserved across basic blocks. */
     unsigned int temp_allocated:1; /* never used for code gen */
-    /* index of next free temp of same base type, -1 if end */
-    int next_free_temp;
     const char *name;
 } TCGTemp;
 
 typedef struct TCGContext TCGContext;
 
+typedef struct TCGTempSet {
+    unsigned long l[BITS_TO_LONGS(TCG_MAX_TEMPS)];
+} TCGTempSet;
+
 struct TCGContext {
     uint8_t *pool_cur, *pool_end;
     TCGPool *pool_first, *pool_current, *pool_first_large;
@@ -450,8 +452,6 @@ struct TCGContext {
     int nb_labels;
     int nb_globals;
     int nb_temps;
-    /* index of free temps, -1 if none */
-    int first_free_temp[TCG_TYPE_COUNT * 2]; 
 
     /* goto_tb support */
     uint8_t *code_buf;
@@ -477,6 +477,7 @@ struct TCGContext {
 
     uint8_t *code_ptr;
     TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */
+    TCGTempSet free_temps[TCG_TYPE_COUNT * 2];
 
     GHashTable *helpers;
 
diff --git a/trace-events b/trace-events
index e32d00cefb..9f4456a82e 100644
--- a/trace-events
+++ b/trace-events
@@ -311,6 +311,9 @@ usb_ehci_sitd(uint32_t addr, uint32_t nxt, uint32_t active) "ITD @ %08x: next %0
 usb_ehci_port_attach(uint32_t port, const char *owner, const char *device) "attach port #%d, owner %s, device %s"
 usb_ehci_port_detach(uint32_t port, const char *owner) "detach port #%d, owner %s"
 usb_ehci_port_reset(uint32_t port, int enable) "reset port #%d - %d"
+usb_ehci_port_suspend(uint32_t port) "port #%d"
+usb_ehci_port_wakeup(uint32_t port) "port #%d"
+usb_ehci_port_resume(uint32_t port) "port #%d"
 usb_ehci_queue_action(void *q, const char *action) "q %p: %s"
 usb_ehci_packet_action(void *q, void *p, const char *action) "q %p p %p: %s"
 usb_ehci_irq(uint32_t level, uint32_t frindex, uint32_t sts, uint32_t mask) "level %d, frindex 0x%04x, sts 0x%x, mask 0x%x"
@@ -429,45 +432,32 @@ usb_uas_tmf_abort_task(int addr, uint16_t tag, uint16_t task_tag) "dev %d, tag 0
 usb_uas_tmf_logical_unit_reset(int addr, uint16_t tag, int lun) "dev %d, tag 0x%x, lun %d"
 usb_uas_tmf_unsupported(int addr, uint16_t tag, uint32_t function) "dev %d, tag 0x%x, function 0x%x"
 
-# hw/usb/host-linux.c
 # hw/usb/host-libusb.c
 usb_host_open_started(int bus, int addr) "dev %d:%d"
 usb_host_open_success(int bus, int addr) "dev %d:%d"
 usb_host_open_failure(int bus, int addr) "dev %d:%d"
-usb_host_disconnect(int bus, int addr) "dev %d:%d"
 usb_host_close(int bus, int addr) "dev %d:%d"
 usb_host_attach_kernel(int bus, int addr, int interface) "dev %d:%d, if %d"
 usb_host_detach_kernel(int bus, int addr, int interface) "dev %d:%d, if %d"
 usb_host_set_address(int bus, int addr, int config) "dev %d:%d, address %d"
 usb_host_set_config(int bus, int addr, int config) "dev %d:%d, config %d"
 usb_host_set_interface(int bus, int addr, int interface, int alt) "dev %d:%d, interface %d, alt %d"
-usb_host_claim_interfaces(int bus, int addr, int config, int nif) "dev %d:%d, config %d, nif %d"
 usb_host_claim_interface(int bus, int addr, int config, int interface) "dev %d:%d, config %d, if %d"
-usb_host_release_interfaces(int bus, int addr) "dev %d:%d"
 usb_host_release_interface(int bus, int addr, int interface) "dev %d:%d, if %d"
 usb_host_req_control(int bus, int addr, void *p, int req, int value, int index) "dev %d:%d, packet %p, req 0x%x, value %d, index %d"
 usb_host_req_data(int bus, int addr, void *p, int in, int ep, int size) "dev %d:%d, packet %p, in %d, ep %d, size %d"
 usb_host_req_complete(int bus, int addr, void *p, int status, int length) "dev %d:%d, packet %p, status %d, length %d"
 usb_host_req_emulated(int bus, int addr, void *p, int status) "dev %d:%d, packet %p, status %d"
 usb_host_req_canceled(int bus, int addr, void *p) "dev %d:%d, packet %p"
-usb_host_urb_submit(int bus, int addr, void *aurb, int length, int more) "dev %d:%d, aurb %p, length %d, more %d"
-usb_host_urb_complete(int bus, int addr, void *aurb, int status, int length, int more) "dev %d:%d, aurb %p, status %d, length %d, more %d"
-usb_host_urb_canceled(int bus, int addr, void *aurb) "dev %d:%d, aurb %p"
-usb_host_ep_set_halt(int bus, int addr, int ep) "dev %d:%d, ep %d"
-usb_host_ep_clear_halt(int bus, int addr, int ep) "dev %d:%d, ep %d"
 usb_host_iso_start(int bus, int addr, int ep) "dev %d:%d, ep %d"
 usb_host_iso_stop(int bus, int addr, int ep) "dev %d:%d, ep %d"
 usb_host_iso_out_of_bufs(int bus, int addr, int ep) "dev %d:%d, ep %d"
-usb_host_iso_many_urbs(int bus, int addr, int count) "dev %d:%d, count %d"
 usb_host_reset(int bus, int addr) "dev %d:%d"
 usb_host_auto_scan_enabled(void)
 usb_host_auto_scan_disabled(void)
-usb_host_claim_port(int bus, int hub, int port) "bus %d, hub addr %d, port %d"
-usb_host_parse_device(int bus, int addr, int vendor, int product) "dev %d:%d, id %04x:%04x"
 usb_host_parse_config(int bus, int addr, int value, int active) "dev %d:%d, value %d, active %d"
 usb_host_parse_interface(int bus, int addr, int num, int alt, int active) "dev %d:%d, num %d, alt %d, active %d"
 usb_host_parse_endpoint(int bus, int addr, int ep, const char *dir, const char *type, int active) "dev %d:%d, ep %d, %s, %s, active %d"
-usb_host_parse_unknown(int bus, int addr, int len, int type) "dev %d:%d, len %d, type %d"
 usb_host_parse_error(int bus, int addr, const char *errmsg) "dev %d:%d, msg %s"
 
 # hw/scsi/scsi-bus.c
@@ -1012,6 +1002,8 @@ dma_map_wait(void *dbs) "dbs=%p"
 
 # ui/console.c
 console_gfx_new(void) ""
+console_putchar_csi(int esc_param0, int esc_param1, int ch, int nb_esc_params) "escape sequence CSI%d;%d%c, %d parameters"
+console_putchar_unhandled(int ch) "unhandled escape character '%c'"
 console_txt_new(int w, int h) "%dx%d"
 console_select(int nr) "%d"
 console_refresh(int interval) "interval %d ms"
@@ -1022,6 +1014,11 @@ displaychangelistener_register(void *dcl, const char *name) "%p [ %s ]"
 displaychangelistener_unregister(void *dcl, const char *name) "%p [ %s ]"
 ppm_save(const char *filename, void *display_surface) "%s surface=%p"
 
+# ui/gtk.c
+gd_switch(int width, int height) "width=%d, height=%d"
+gd_update(int x, int y, int w, int h) "x=%d, y=%d, w=%d, h=%d"
+gd_key_event(int gdk_keycode, int qemu_keycode, const char *action) "translated GDK keycode %d to QEMU keycode %d (%s)"
+
 # hw/display/vmware_vga.c
 vmware_value_read(uint32_t index, uint32_t value) "index %d, value 0x%x"
 vmware_value_write(uint32_t index, uint32_t value) "index %d, value 0x%x"
diff --git a/ui/console.c b/ui/console.c
index 199ba69101..502e1600ab 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -27,8 +27,8 @@
 #include "qemu/timer.h"
 #include "qmp-commands.h"
 #include "sysemu/char.h"
+#include "trace.h"
 
-//#define DEBUG_CONSOLE
 #define DEFAULT_BACKSCROLL 512
 #define MAX_CONSOLES 12
 #define CONSOLE_CURSOR_PERIOD 500
@@ -161,7 +161,7 @@ struct QemuConsole {
 };
 
 struct DisplayState {
-    struct QEMUTimer *gui_timer;
+    QEMUTimer *gui_timer;
     uint64_t last_update;
     uint64_t update_interval;
     bool refreshing;
@@ -866,10 +866,8 @@ static void console_putchar(QemuConsole *s, int ch)
                 s->nb_esc_params++;
             if (ch == ';')
                 break;
-#ifdef DEBUG_CONSOLE
-            fprintf(stderr, "escape sequence CSI%d;%d%c, %d parameters\n",
-                    s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params);
-#endif
+            trace_console_putchar_csi(s->esc_params[0], s->esc_params[1],
+                                      ch, s->nb_esc_params);
             s->state = TTY_STATE_NORM;
             switch(ch) {
             case 'A':
@@ -983,9 +981,7 @@ static void console_putchar(QemuConsole *s, int ch)
                 s->y = s->y_saved;
                 break;
             default:
-#ifdef DEBUG_CONSOLE
-                fprintf(stderr, "unhandled escape character '%c'\n", ch);
-#endif
+                trace_console_putchar_unhandled(ch);
                 break;
             }
             break;
diff --git a/ui/gtk.c b/ui/gtk.c
index b5f4f0bd40..6316f5ba00 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -53,6 +53,7 @@
 #include <vte/vte.h>
 #include <math.h>
 
+#include "trace.h"
 #include "ui/console.h"
 #include "sysemu/sysemu.h"
 #include "qmp-commands.h"
@@ -60,14 +61,6 @@
 #include "keymaps.h"
 #include "sysemu/char.h"
 
-//#define DEBUG_GTK
-
-#ifdef DEBUG_GTK
-#define DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
-#else
-#define DPRINTF(fmt, ...) do { } while (0)
-#endif
-
 #define MAX_VCS 10
 
 
@@ -302,7 +295,7 @@ static void gd_update(DisplayChangeListener *dcl,
     int fbw, fbh;
     int ww, wh;
 
-    DPRINTF("update(x=%d, y=%d, w=%d, h=%d)\n", x, y, w, h);
+    trace_gd_update(x, y, w, h);
 
     if (s->convert) {
         pixman_image_composite(PIXMAN_OP_SRC, s->ds->image, NULL, s->convert,
@@ -396,8 +389,7 @@ static void gd_switch(DisplayChangeListener *dcl,
     GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
     bool resized = true;
 
-    DPRINTF("resize(width=%d, height=%d)\n",
-            surface_width(surface), surface_height(surface));
+    trace_gd_switch(surface_width(surface), surface_height(surface));
 
     if (s->surface) {
         cairo_surface_destroy(s->surface);
@@ -732,9 +724,8 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
         qemu_keycode = 0;
     }
 
-    DPRINTF("translated GDK keycode %d to QEMU keycode %d (%s)\n",
-            gdk_keycode, qemu_keycode,
-            (key->type == GDK_KEY_PRESS) ? "down" : "up");
+    trace_gd_key_event(gdk_keycode, qemu_keycode,
+                       (key->type == GDK_KEY_PRESS) ? "down" : "up");
 
     for (i = 0; i < ARRAY_SIZE(modifier_keycode); i++) {
         if (qemu_keycode == modifier_keycode[i]) {
diff --git a/ui/input.c b/ui/input.c
index 10d8c056f1..1c70f60e0d 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -414,7 +414,7 @@ void kbd_put_keycode(int keycode)
     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
         return;
     }
-    if (entry) {
+    if (entry && entry->put_kbd) {
         entry->put_kbd(entry->opaque, keycode);
     }
 }
diff --git a/util/Makefile.objs b/util/Makefile.objs
index 2bb13a2a59..af3e5cb157 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -12,3 +12,4 @@ util-obj-y += qemu-option.o qemu-progress.o
 util-obj-y += hexdump.o
 util-obj-y += crc32c.o
 util-obj-y += throttle.o
+util-obj-y += getauxval.o
diff --git a/util/cache-utils.c b/util/cache-utils.c
index b94013a8cb..047003008b 100644
--- a/util/cache-utils.c
+++ b/util/cache-utils.c
@@ -1,3 +1,4 @@
+#include "qemu-common.h"
 #include "qemu/cache-utils.h"
 
 #if defined(_ARCH_PPC)
@@ -9,31 +10,33 @@ struct qemu_cache_conf qemu_cache_conf = {
 #if defined _AIX
 #include <sys/systemcfg.h>
 
-static void ppc_init_cacheline_sizes(void)
+void qemu_cache_utils_init(void)
 {
     qemu_cache_conf.icache_bsize = _system_configuration.icache_line;
     qemu_cache_conf.dcache_bsize = _system_configuration.dcache_line;
 }
 
 #elif defined __linux__
+#include "qemu/osdep.h"
+#include "elf.h"
 
-#define QEMU_AT_NULL        0
-#define QEMU_AT_DCACHEBSIZE 19
-#define QEMU_AT_ICACHEBSIZE 20
-
-static void ppc_init_cacheline_sizes(char **envp)
+void qemu_cache_utils_init(void)
 {
-    unsigned long *auxv;
-
-    while (*envp++);
+    unsigned long dsize = qemu_getauxval(AT_DCACHEBSIZE);
+    unsigned long isize = qemu_getauxval(AT_ICACHEBSIZE);
 
-    for (auxv = (unsigned long *) envp; *auxv != QEMU_AT_NULL; auxv += 2) {
-        switch (*auxv) {
-        case QEMU_AT_DCACHEBSIZE: qemu_cache_conf.dcache_bsize = auxv[1]; break;
-        case QEMU_AT_ICACHEBSIZE: qemu_cache_conf.icache_bsize = auxv[1]; break;
-        default: break;
+    if (dsize == 0 || isize == 0) {
+        if (dsize == 0) {
+            fprintf(stderr, "getauxval AT_DCACHEBSIZE failed\n");
+        }
+        if (isize == 0) {
+            fprintf(stderr, "getauxval AT_ICACHEBSIZE failed\n");
         }
+        exit(1);
+
     }
+    qemu_cache_conf.dcache_bsize = dsize;
+    qemu_cache_conf.icache_bsize = isize;
 }
 
 #elif defined __APPLE__
@@ -41,7 +44,7 @@ static void ppc_init_cacheline_sizes(char **envp)
 #include <sys/types.h>
 #include <sys/sysctl.h>
 
-static void ppc_init_cacheline_sizes(void)
+void qemu_cache_utils_init(void)
 {
     size_t len;
     unsigned cacheline;
@@ -55,9 +58,8 @@ static void ppc_init_cacheline_sizes(void)
         qemu_cache_conf.icache_bsize = cacheline;
     }
 }
-#endif
 
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -65,7 +67,7 @@ static void ppc_init_cacheline_sizes(void)
 #include <sys/types.h>
 #include <sys/sysctl.h>
 
-static void ppc_init_cacheline_sizes(void)
+void qemu_cache_utils_init(void)
 {
     size_t len = 4;
     unsigned cacheline;
@@ -81,17 +83,4 @@ static void ppc_init_cacheline_sizes(void)
 }
 #endif
 
-#ifdef __linux__
-void qemu_cache_utils_init(char **envp)
-{
-    ppc_init_cacheline_sizes(envp);
-}
-#else
-void qemu_cache_utils_init(char **envp)
-{
-    (void) envp;
-    ppc_init_cacheline_sizes();
-}
-#endif
-
 #endif /* _ARCH_PPC */
diff --git a/util/getauxval.c b/util/getauxval.c
new file mode 100644
index 0000000000..476c883b32
--- /dev/null
+++ b/util/getauxval.c
@@ -0,0 +1,74 @@
+/*
+ * QEMU access to the auxiliary vector
+ *
+ * Copyright (C) 2013 Red Hat, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu-common.h"
+#include "qemu/osdep.h"
+
+#ifdef CONFIG_GETAUXVAL
+/* Don't inline this in qemu/osdep.h, because pulling in <sys/auxv.h> for
+   the system declaration of getauxval pulls in the system <elf.h>, which
+   conflicts with qemu's version.  */
+
+#include <sys/auxv.h>
+
+unsigned long qemu_getauxval(unsigned long key)
+{
+    return getauxval(key);
+}
+#elif defined(__linux__)
+#include "elf.h"
+
+/* Our elf.h doesn't contain Elf32_auxv_t and Elf64_auxv_t, which is ok because
+   that just makes it easier to define it properly for the host here.  */
+typedef struct {
+    unsigned long a_type;
+    unsigned long a_val;
+} ElfW_auxv_t;
+
+static const ElfW_auxv_t *auxv;
+
+void qemu_init_auxval(char **envp)
+{
+    /* The auxiliary vector is located just beyond the initial environment.  */
+    while (*envp++ != NULL) {
+        continue;
+    }
+    auxv = (const ElfW_auxv_t *)envp;
+}
+
+unsigned long qemu_getauxval(unsigned long type)
+{
+    /* If we were able to find the auxiliary vector, use it.  */
+    if (auxv) {
+        const ElfW_auxv_t *a;
+        for (a = auxv; a->a_type != 0; a++) {
+            if (a->a_type == type) {
+                return a->a_val;
+            }
+        }
+    }
+
+    return 0;
+}
+#endif
diff --git a/vl.c b/vl.c
index 8d5d874e68..b0399de25f 100644
--- a/vl.c
+++ b/vl.c
@@ -188,9 +188,7 @@ static int display_remote;
 const char* keyboard_layout = NULL;
 ram_addr_t ram_size;
 const char *mem_path = NULL;
-#ifdef MAP_POPULATE
 int mem_prealloc = 0; /* force preallocation of physical target memory */
-#endif
 int nb_nics;
 NICInfo nd_table[MAX_NICS];
 int autostart;
@@ -428,6 +426,10 @@ static QemuOptsList qemu_machine_opts = {
             .name = "usb",
             .type = QEMU_OPT_BOOL,
             .help = "Set on/off to enable/disable usb",
+        },{
+            .name = "firmware",
+            .type = QEMU_OPT_STRING,
+            .help = "firmware image",
         },
         { /* End of list */ }
     },
@@ -2894,7 +2896,8 @@ int main(int argc, char **argv, char **envp)
     init_clocks();
     rtc_clock = QEMU_CLOCK_HOST;
 
-    qemu_cache_utils_init(envp);
+    qemu_init_auxval(envp);
+    qemu_cache_utils_init();
 
     QLIST_INIT (&vm_change_state_head);
     os_setup_early_signal_handling();
@@ -3206,11 +3209,9 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_mempath:
                 mem_path = optarg;
                 break;
-#ifdef MAP_POPULATE
             case QEMU_OPTION_mem_prealloc:
                 mem_prealloc = 1;
                 break;
-#endif
             case QEMU_OPTION_d:
                 log_mask = optarg;
                 break;
@@ -3229,7 +3230,7 @@ int main(int argc, char **argv, char **envp)
                 }
                 break;
             case QEMU_OPTION_bios:
-                bios_name = optarg;
+                qemu_opts_set(qemu_find_opts("machine"), 0, "firmware", optarg);
                 break;
             case QEMU_OPTION_singlestep:
                 singlestep = 1;
@@ -4050,6 +4051,7 @@ int main(int argc, char **argv, char **envp)
     kernel_filename = qemu_opt_get(machine_opts, "kernel");
     initrd_filename = qemu_opt_get(machine_opts, "initrd");
     kernel_cmdline = qemu_opt_get(machine_opts, "append");
+    bios_name = qemu_opt_get(machine_opts, "firmware");
 
     boot_order = machine->default_boot_order;
     opts = qemu_opts_find(qemu_find_opts("boot-opts"), NULL);
diff --git a/xen-all.c b/xen-all.c
index 9a27899ca1..4a594bdd9b 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -369,8 +369,8 @@ static int xen_remove_from_physmap(XenIOState *state,
     phys_offset = physmap->phys_offset;
     size = physmap->size;
 
-    DPRINTF("unmapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx", from ",
-            "%"HWADDR_PRIx"\n", phys_offset, phys_offset + size, start_addr);
+    DPRINTF("unmapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx", at "
+            "%"HWADDR_PRIx"\n", start_addr, start_addr + size, phys_offset);
 
     size >>= TARGET_PAGE_BITS;
     start_addr >>= TARGET_PAGE_BITS;