summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure34
-rw-r--r--default-configs/alpha-softmmu.mak1
-rw-r--r--default-configs/mips-softmmu.mak2
-rw-r--r--default-configs/mips64-softmmu.mak2
-rw-r--r--default-configs/mips64el-softmmu.mak2
-rw-r--r--default-configs/mipsel-softmmu.mak2
-rw-r--r--default-configs/ppc-softmmu.mak1
-rw-r--r--default-configs/ppc64-softmmu.mak7
-rw-r--r--default-configs/ppcemb-softmmu.mak1
-rw-r--r--default-configs/sh4-softmmu.mak9
-rw-r--r--default-configs/sh4eb-softmmu.mak9
-rw-r--r--default-configs/sparc64-softmmu.mak1
-rw-r--r--exec.c4
-rw-r--r--hw/isa/Makefile.objs1
-rw-r--r--hw/isa/isa_mmio.c81
-rw-r--r--hw/mips/gt64xxx_pci.c3
-rw-r--r--hw/mips/mips_fulong2e.c3
-rw-r--r--hw/mips/mips_jazz.c8
-rw-r--r--hw/mips/mips_malta.c3
-rw-r--r--hw/mips/mips_mipssim.c8
-rw-r--r--hw/mips/mips_r4k.c6
-rw-r--r--hw/misc/pc-testdev.c28
-rw-r--r--hw/pci-host/apb.c101
-rw-r--r--hw/pci-host/bonito.c25
-rw-r--r--hw/ppc/mac_newworld.c5
-rw-r--r--hw/ppc/mac_oldworld.c5
-rw-r--r--hw/ppc/ppc440_bamboo.c5
-rw-r--r--hw/ppc/prep.c2
-rw-r--r--hw/ppc/spapr_pci.c41
-rw-r--r--hw/sh4/sh_pci.c42
-rw-r--r--hw/sparc64/sun4u.c6
-rw-r--r--include/exec/cpu-all.h8
-rw-r--r--include/exec/gdbstub.h2
-rw-r--r--include/hw/isa/isa.h3
-rw-r--r--ioport.c1
-rw-r--r--linux-user/arm/syscall.h2
-rw-r--r--linux-user/cris/syscall.h2
-rw-r--r--linux-user/i386/syscall.h2
-rw-r--r--linux-user/i386/target_cpu.h19
-rw-r--r--linux-user/m68k/target_cpu.h6
-rw-r--r--linux-user/main.c93
-rw-r--r--linux-user/microblaze/syscall.h2
-rw-r--r--linux-user/mips/syscall.h2
-rw-r--r--linux-user/mips64/syscall.h2
-rw-r--r--linux-user/mmap.c11
-rw-r--r--linux-user/openrisc/target_cpu.h9
-rw-r--r--linux-user/ppc/syscall.h2
-rw-r--r--linux-user/qemu.h20
-rw-r--r--linux-user/s390x/syscall.h2
-rw-r--r--linux-user/sparc/syscall.h7
-rw-r--r--linux-user/sparc/target_cpu.h16
-rw-r--r--linux-user/sparc64/syscall.h7
-rw-r--r--linux-user/syscall.c88
-rw-r--r--linux-user/syscall_defs.h54
-rw-r--r--memory.c101
-rw-r--r--po/Makefile33
-rw-r--r--tests/Makefile14
-rw-r--r--tests/endianness-test.c316
-rw-r--r--translate-all.c10
-rw-r--r--user-exec.c4
60 files changed, 782 insertions, 504 deletions
diff --git a/configure b/configure
index 877a8213f3..3d83e168bc 100755
--- a/configure
+++ b/configure
@@ -155,7 +155,6 @@ curl=""
 curses=""
 docs=""
 fdt=""
-nptl=""
 pixman=""
 sdl=""
 virtfs=""
@@ -856,10 +855,6 @@ for opt do
   ;;
   --enable-fdt) fdt="yes"
   ;;
-  --disable-nptl) nptl="no"
-  ;;
-  --enable-nptl) nptl="yes"
-  ;;
   --enable-mixemu) mixemu="yes"
   ;;
   --disable-linux-aio) linux_aio="no"
@@ -1103,8 +1098,6 @@ echo "  --enable-kvm             enable KVM acceleration support"
 echo "  --disable-rdma           disable RDMA-based migration support"
 echo "  --enable-rdma            enable RDMA-based migration support"
 echo "  --enable-tcg-interpreter enable TCG with bytecode interpreter (TCI)"
-echo "  --disable-nptl           disable usermode NPTL support"
-echo "  --enable-nptl            enable usermode NPTL support"
 echo "  --enable-system          enable all system emulation targets"
 echo "  --disable-system         disable all system emulation targets"
 echo "  --enable-user            enable supported user emulation targets"
@@ -1439,7 +1432,7 @@ fi
 ##########################################
 # NPTL probe
 
-if test "$nptl" != "no" ; then
+if test "$linux_user" = "yes"; then
   cat > $TMPC <<EOF
 #include <sched.h>
 #include <linux/futex.h>
@@ -1450,14 +1443,8 @@ int main(void) {
   return 0;
 }
 EOF
-
-  if compile_object ; then
-    nptl=yes
-  else
-    if test "$nptl" = "yes" ; then
-      feature_not_found "nptl"
-    fi
-    nptl=no
+  if ! compile_object ; then
+    feature_not_found "nptl"
   fi
 fi
 
@@ -3581,7 +3568,6 @@ echo "bluez  support    $bluez"
 echo "Documentation     $docs"
 [ ! -z "$uname_release" ] && \
 echo "uname -r          $uname_release"
-echo "NPTL support      $nptl"
 echo "GUEST_BASE        $guest_base"
 echo "PIE               $pie"
 echo "vde support       $vde"
@@ -4216,7 +4202,6 @@ mkdir -p $target_dir
 echo "# Automatically generated by configure - do not modify" > $config_target_mak
 
 bflt="no"
-target_nptl="no"
 interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_name/g"`
 gdb_xml_files=""
 
@@ -4231,16 +4216,13 @@ case "$target_name" in
     TARGET_BASE_ARCH=i386
   ;;
   alpha)
-    target_nptl="yes"
   ;;
   arm|armeb)
     TARGET_ARCH=arm
     bflt="yes"
-    target_nptl="yes"
     gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
   ;;
   cris)
-    target_nptl="yes"
   ;;
   lm32)
   ;;
@@ -4251,12 +4233,10 @@ case "$target_name" in
   microblaze|microblazeel)
     TARGET_ARCH=microblaze
     bflt="yes"
-    target_nptl="yes"
   ;;
   mips|mipsel)
     TARGET_ARCH=mips
     echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak
-    target_nptl="yes"
   ;;
   mipsn32|mipsn32el)
     TARGET_ARCH=mips64
@@ -4277,13 +4257,11 @@ case "$target_name" in
   ;;
   ppc)
     gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
-    target_nptl="yes"
   ;;
   ppcemb)
     TARGET_BASE_ARCH=ppc
     TARGET_ABI_DIR=ppc
     gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
-    target_nptl="yes"
   ;;
   ppc64)
     TARGET_BASE_ARCH=ppc
@@ -4300,7 +4278,6 @@ case "$target_name" in
   sh4|sh4eb)
     TARGET_ARCH=sh4
     bflt="yes"
-    target_nptl="yes"
   ;;
   sparc)
   ;;
@@ -4314,7 +4291,6 @@ case "$target_name" in
     echo "TARGET_ABI32=y" >> $config_target_mak
   ;;
   s390x)
-    target_nptl="yes"
   ;;
   unicore32)
   ;;
@@ -4396,10 +4372,6 @@ fi
 if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then
   echo "TARGET_HAS_BFLT=y" >> $config_target_mak
 fi
-if test "$target_user_only" = "yes" \
-        -a "$nptl" = "yes" -a "$target_nptl" = "yes"; then
-  echo "CONFIG_USE_NPTL=y" >> $config_target_mak
-fi
 if test "$target_user_only" = "yes" -a "$guest_base" = "yes"; then
   echo "CONFIG_USE_GUEST_BASE=y" >> $config_target_mak
 fi
diff --git a/default-configs/alpha-softmmu.mak b/default-configs/alpha-softmmu.mak
index 18e5337a77..bc07600f96 100644
--- a/default-configs/alpha-softmmu.mak
+++ b/default-configs/alpha-softmmu.mak
@@ -14,3 +14,4 @@ CONFIG_VMWARE_VGA=y
 CONFIG_IDE_CMD646=y
 CONFIG_I8259=y
 CONFIG_MC146818RTC=y
+CONFIG_ISA_TESTDEV=y
diff --git a/default-configs/mips-softmmu.mak b/default-configs/mips-softmmu.mak
index b443702b87..926709ae52 100644
--- a/default-configs/mips-softmmu.mak
+++ b/default-configs/mips-softmmu.mak
@@ -3,7 +3,6 @@
 include pci.mak
 include sound.mak
 include usb.mak
-CONFIG_ISA_MMIO=y
 CONFIG_ESP=y
 CONFIG_VGA=y
 CONFIG_VGA_PCI=y
@@ -34,3 +33,4 @@ CONFIG_I8259=y
 CONFIG_JAZZ_LED=y
 CONFIG_MC146818RTC=y
 CONFIG_VT82C686=y
+CONFIG_ISA_TESTDEV=y
diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak
index d63895792b..0ef3f09c77 100644
--- a/default-configs/mips64-softmmu.mak
+++ b/default-configs/mips64-softmmu.mak
@@ -3,7 +3,6 @@
 include pci.mak
 include sound.mak
 include usb.mak
-CONFIG_ISA_MMIO=y
 CONFIG_ESP=y
 CONFIG_VGA=y
 CONFIG_VGA_PCI=y
@@ -34,3 +33,4 @@ CONFIG_I8259=y
 CONFIG_JAZZ_LED=y
 CONFIG_MC146818RTC=y
 CONFIG_VT82C686=y
+CONFIG_ISA_TESTDEV=y
diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak
index c9be3f49ca..60893182b3 100644
--- a/default-configs/mips64el-softmmu.mak
+++ b/default-configs/mips64el-softmmu.mak
@@ -3,7 +3,6 @@
 include pci.mak
 include sound.mak
 include usb.mak
-CONFIG_ISA_MMIO=y
 CONFIG_ESP=y
 CONFIG_VGA=y
 CONFIG_VGA_PCI=y
@@ -36,3 +35,4 @@ CONFIG_I8259=y
 CONFIG_JAZZ_LED=y
 CONFIG_MC146818RTC=y
 CONFIG_VT82C686=y
+CONFIG_ISA_TESTDEV=y
diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/mipsel-softmmu.mak
index 4f4a449408..cd59e2479a 100644
--- a/default-configs/mipsel-softmmu.mak
+++ b/default-configs/mipsel-softmmu.mak
@@ -3,7 +3,6 @@
 include pci.mak
 include sound.mak
 include usb.mak
-CONFIG_ISA_MMIO=y
 CONFIG_ESP=y
 CONFIG_VGA=y
 CONFIG_VGA_PCI=y
@@ -34,3 +33,4 @@ CONFIG_I8259=y
 CONFIG_JAZZ_LED=y
 CONFIG_MC146818RTC=y
 CONFIG_VT82C686=y
+CONFIG_ISA_TESTDEV=y
diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index 73e4cc5f63..eac0b28fb9 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -46,3 +46,4 @@ CONFIG_E500=y
 CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
 # For PReP
 CONFIG_MC146818RTC=y
+CONFIG_ISA_TESTDEV=y
diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index 6d1933bbf9..7831c2bf57 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -48,4 +48,11 @@ CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
 # For pSeries
 CONFIG_XICS=$(CONFIG_PSERIES)
 # For PReP
+CONFIG_I82378=y
+CONFIG_I8259=y
+CONFIG_I8254=y
+CONFIG_PCSPK=y
+CONFIG_I82374=y
+CONFIG_I8257=y
 CONFIG_MC146818RTC=y
+CONFIG_ISA_TESTDEV=y
diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
index e3b5e50360..86080a7574 100644
--- a/default-configs/ppcemb-softmmu.mak
+++ b/default-configs/ppcemb-softmmu.mak
@@ -41,3 +41,4 @@ CONFIG_E500=y
 CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
 # For PReP
 CONFIG_MC146818RTC=y
+CONFIG_ISA_TESTDEV=y
diff --git a/default-configs/sh4-softmmu.mak b/default-configs/sh4-softmmu.mak
index f6bf62d1c2..8e00390d4f 100644
--- a/default-configs/sh4-softmmu.mak
+++ b/default-configs/sh4-softmmu.mak
@@ -5,7 +5,14 @@ include usb.mak
 CONFIG_SERIAL=y
 CONFIG_PTIMER=y
 CONFIG_PFLASH_CFI02=y
-CONFIG_ISA_MMIO=y
 CONFIG_SH4=y
 CONFIG_IDE_MMIO=y
 CONFIG_SM501=y
+CONFIG_ISA_TESTDEV=y
+CONFIG_I82378=y
+CONFIG_I8259=y
+CONFIG_I8254=y
+CONFIG_PCSPK=y
+CONFIG_I82374=y
+CONFIG_I8257=y
+CONFIG_MC146818RTC=y
diff --git a/default-configs/sh4eb-softmmu.mak b/default-configs/sh4eb-softmmu.mak
index c1d513d099..efdd05842f 100644
--- a/default-configs/sh4eb-softmmu.mak
+++ b/default-configs/sh4eb-softmmu.mak
@@ -5,7 +5,14 @@ include usb.mak
 CONFIG_SERIAL=y
 CONFIG_PTIMER=y
 CONFIG_PFLASH_CFI02=y
-CONFIG_ISA_MMIO=y
 CONFIG_SH4=y
 CONFIG_IDE_MMIO=y
 CONFIG_SM501=y
+CONFIG_ISA_TESTDEV=y
+CONFIG_I82378=y
+CONFIG_I8259=y
+CONFIG_I8254=y
+CONFIG_PCSPK=y
+CONFIG_I82374=y
+CONFIG_I8257=y
+CONFIG_MC146818RTC=y
diff --git a/default-configs/sparc64-softmmu.mak b/default-configs/sparc64-softmmu.mak
index 9b08ee8a20..299c97b715 100644
--- a/default-configs/sparc64-softmmu.mak
+++ b/default-configs/sparc64-softmmu.mak
@@ -15,3 +15,4 @@ CONFIG_IDE_ISA=y
 CONFIG_IDE_CMD646=y
 CONFIG_PCI_APB=y
 CONFIG_MC146818RTC=y
+CONFIG_ISA_TESTDEV=y
diff --git a/exec.c b/exec.c
index 7997002f14..3ba9525bd3 100644
--- a/exec.c
+++ b/exec.c
@@ -646,6 +646,10 @@ CPUArchState *cpu_copy(CPUArchState *env)
     CPUWatchpoint *wp;
 #endif
 
+    /* Reset non arch specific state */
+    cpu_reset(ENV_GET_CPU(new_env));
+
+    /* Copy arch specific state into the new CPU */
     memcpy(new_env, env, sizeof(CPUArchState));
 
     /* Clone all break/watchpoints.
diff --git a/hw/isa/Makefile.objs b/hw/isa/Makefile.objs
index 193746a73e..9164556a4d 100644
--- a/hw/isa/Makefile.objs
+++ b/hw/isa/Makefile.objs
@@ -1,7 +1,6 @@
 common-obj-y += isa-bus.o
 common-obj-$(CONFIG_APM) += apm.o
 common-obj-$(CONFIG_I82378) += i82378.o
-common-obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
 common-obj-$(CONFIG_PC87312) += pc87312.o
 common-obj-$(CONFIG_PIIX4) += piix4.o
 common-obj-$(CONFIG_VT82C686) += vt82c686.o
diff --git a/hw/isa/isa_mmio.c b/hw/isa/isa_mmio.c
deleted file mode 100644
index 00ae8ebc2e..0000000000
--- a/hw/isa/isa_mmio.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Memory mapped access to ISA IO space.
- *
- * Copyright (c) 2006 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "hw/hw.h"
-#include "hw/isa/isa.h"
-#include "exec/address-spaces.h"
-
-static void isa_mmio_writeb (void *opaque, hwaddr addr,
-                                  uint32_t val)
-{
-    cpu_outb(addr & IOPORTS_MASK, val);
-}
-
-static void isa_mmio_writew(void *opaque, hwaddr addr,
-                               uint32_t val)
-{
-    cpu_outw(addr & IOPORTS_MASK, val);
-}
-
-static void isa_mmio_writel(void *opaque, hwaddr addr,
-                               uint32_t val)
-{
-    cpu_outl(addr & IOPORTS_MASK, val);
-}
-
-static uint32_t isa_mmio_readb (void *opaque, hwaddr addr)
-{
-    return cpu_inb(addr & IOPORTS_MASK);
-}
-
-static uint32_t isa_mmio_readw(void *opaque, hwaddr addr)
-{
-    return cpu_inw(addr & IOPORTS_MASK);
-}
-
-static uint32_t isa_mmio_readl(void *opaque, hwaddr addr)
-{
-    return cpu_inl(addr & IOPORTS_MASK);
-}
-
-static const MemoryRegionOps isa_mmio_ops = {
-    .old_mmio = {
-        .write = { isa_mmio_writeb, isa_mmio_writew, isa_mmio_writel },
-        .read = { isa_mmio_readb, isa_mmio_readw, isa_mmio_readl, },
-    },
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-void isa_mmio_setup(MemoryRegion *mr, hwaddr size)
-{
-    memory_region_init_io(mr, NULL, &isa_mmio_ops, NULL, "isa-mmio", size);
-}
-
-void isa_mmio_init(hwaddr base, hwaddr size)
-{
-    MemoryRegion *mr = g_malloc(sizeof(*mr));
-
-    isa_mmio_setup(mr, size);
-    memory_region_add_subregion(get_system_memory(), base, mr);
-}
diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c
index 5843417567..3da2e67098 100644
--- a/hw/mips/gt64xxx_pci.c
+++ b/hw/mips/gt64xxx_pci.c
@@ -304,7 +304,8 @@ static void gt64120_pci_mapping(GT64120State *s)
       s->PCI0IO_length = ((s->regs[GT_PCI0IOHD] + 1) - (s->regs[GT_PCI0IOLD] & 0x7f)) << 21;
       isa_mem_base = s->PCI0IO_start;
       if (s->PCI0IO_length) {
-          isa_mmio_setup(&s->PCI0IO_mem, s->PCI0IO_length);
+          memory_region_init_alias(&s->PCI0IO_mem, OBJECT(s), "isa_mmio",
+                                   get_system_io(), 0, s->PCI0IO_length);
           memory_region_add_subregion(get_system_memory(), s->PCI0IO_start,
                                       &s->PCI0IO_mem);
       }
diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c
index 9e305d2878..a7e9dcf4bf 100644
--- a/hw/mips/mips_fulong2e.c
+++ b/hw/mips/mips_fulong2e.c
@@ -333,8 +333,7 @@ static void mips_fulong2e_init(QEMUMachineInitArgs *args)
         }
 
         if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
-            fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n", bios_name);
-            exit(1);
+            fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n", bios_name);
         }
     }
 
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
index 31e138b056..d6e0860a83 100644
--- a/hw/mips/mips_jazz.c
+++ b/hw/mips/mips_jazz.c
@@ -119,6 +119,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
     qemu_irq *rc4030, *i8259;
     rc4030_dma *dmas;
     void* rc4030_opaque;
+    MemoryRegion *isa = g_new(MemoryRegion, 1);
     MemoryRegion *rtc = g_new(MemoryRegion, 1);
     MemoryRegion *i8042 = g_new(MemoryRegion, 1);
     MemoryRegion *dma_dummy = g_new(MemoryRegion, 1);
@@ -176,9 +177,8 @@ static void mips_jazz_init(MemoryRegion *address_space,
         bios_size = -1;
     }
     if (bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) {
-        fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n",
+        fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
                 bios_name);
-        exit(1);
     }
 
     /* Init CPU internal devices */
@@ -201,7 +201,9 @@ static void mips_jazz_init(MemoryRegion *address_space,
     pcspk_init(isa_bus, pit);
 
     /* ISA IO space at 0x90000000 */
-    isa_mmio_init(0x90000000, 0x01000000);
+    memory_region_init_alias(isa, NULL, "isa_mmio",
+                             get_system_io(), 0, 0x01000000);
+    memory_region_add_subregion(address_space, 0x90000000, isa);
     isa_mem_base = 0x11000000;
 
     /* Video card */
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index de87241e9c..dad58c0ed2 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -908,9 +908,8 @@ void mips_malta_init(QEMUMachineInitArgs *args)
             }
             if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
                 fprintf(stderr,
-                        "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
+                        "qemu: Warning, could not load MIPS bios '%s', and no -kernel argument was specified\n",
                         bios_name);
-                exit(1);
             }
         }
         /* In little endian mode the 32bit words in the bios are swapped,
diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c
index a10cf13a92..e8802c128e 100644
--- a/hw/mips/mips_mipssim.c
+++ b/hw/mips/mips_mipssim.c
@@ -140,6 +140,7 @@ mips_mipssim_init(QEMUMachineInitArgs *args)
     const char *initrd_filename = args->initrd_filename;
     char *filename;
     MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *isa = g_new(MemoryRegion, 1);
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     MemoryRegion *bios = g_new(MemoryRegion, 1);
     MIPSCPU *cpu;
@@ -191,9 +192,8 @@ mips_mipssim_init(QEMUMachineInitArgs *args)
     if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
         /* Bail out if we have neither a kernel image nor boot vector code. */
         fprintf(stderr,
-                "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
+                "qemu: Warning, could not load MIPS bios '%s', and no -kernel argument was specified\n",
                 filename);
-        exit(1);
     } else {
         /* We have a boot vector start address. */
         env->active_tc.PC = (target_long)(int32_t)0xbfc00000;
@@ -212,7 +212,9 @@ mips_mipssim_init(QEMUMachineInitArgs *args)
     cpu_mips_clock_init(env);
 
     /* Register 64 KB of ISA IO space at 0x1fd00000. */
-    isa_mmio_init(0x1fd00000, 0x00010000);
+    memory_region_init_alias(isa, NULL, "isa_mmio",
+                             get_system_io(), 0, 0x00010000);
+    memory_region_add_subregion(get_system_memory(), 0x1fd00000, isa);
 
     /* A single 16450 sits at offset 0x3f8. It is attached to
        MIPS CPU INT2, which is interrupt 4. */
diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c
index 22beb0a67c..4bc2e3fa7a 100644
--- a/hw/mips/mips_r4k.c
+++ b/hw/mips/mips_r4k.c
@@ -164,6 +164,7 @@ void mips_r4k_init(QEMUMachineInitArgs *args)
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     MemoryRegion *bios;
     MemoryRegion *iomem = g_new(MemoryRegion, 1);
+    MemoryRegion *isa = g_new(MemoryRegion, 1);
     int bios_size;
     MIPSCPU *cpu;
     CPUMIPSState *env;
@@ -273,7 +274,10 @@ void mips_r4k_init(QEMUMachineInitArgs *args)
     rtc_init(isa_bus, 2000, NULL);
 
     /* Register 64 KB of ISA IO space at 0x14000000 */
-    isa_mmio_init(0x14000000, 0x00010000);
+    memory_region_init_alias(isa, NULL, "isa_mmio",
+                             get_system_io(), 0, 0x00010000);
+    memory_region_add_subregion(get_system_memory(), 0x14000000, isa);
+
     isa_mem_base = 0x10000000;
 
     pit = pit_init(isa_bus, 0x40, 0, NULL);
diff --git a/hw/misc/pc-testdev.c b/hw/misc/pc-testdev.c
index 699a16ffbe..5867c70069 100644
--- a/hw/misc/pc-testdev.c
+++ b/hw/misc/pc-testdev.c
@@ -49,6 +49,7 @@ typedef struct PCTestdev {
     ISADevice parent_obj;
 
     MemoryRegion ioport;
+    MemoryRegion ioport_byte;
     MemoryRegion flush;
     MemoryRegion irq;
     MemoryRegion iomem;
@@ -80,13 +81,20 @@ static void test_ioport_write(void *opaque, hwaddr addr, uint64_t data,
                               unsigned len)
 {
     PCTestdev *dev = opaque;
-    dev->ioport_data = data;
+    int bits = len * 8;
+    int start_bit = (addr & 3) * 8;
+    uint32_t mask = ((uint32_t)-1 >> (32 - bits)) << start_bit;
+    dev->ioport_data &= ~mask;
+    dev->ioport_data |= data << start_bit;
 }
 
 static uint64_t test_ioport_read(void *opaque, hwaddr addr, unsigned len)
 {
     PCTestdev *dev = opaque;
-    return dev->ioport_data;
+    int bits = len * 8;
+    int start_bit = (addr & 3) * 8;
+    uint32_t mask = ((uint32_t)-1 >> (32 - bits)) << start_bit;
+    return (dev->ioport_data & mask) >> start_bit;
 }
 
 static const MemoryRegionOps test_ioport_ops = {
@@ -95,6 +103,16 @@ static const MemoryRegionOps test_ioport_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
+static const MemoryRegionOps test_ioport_byte_ops = {
+    .read = test_ioport_read,
+    .write = test_ioport_write,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 4,
+    .impl.min_access_size = 1,
+    .impl.max_access_size = 1,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 static void test_flush_page(void *opaque, hwaddr addr, uint64_t data,
                             unsigned len)
 {
@@ -122,7 +140,6 @@ static uint64_t test_iomem_read(void *opaque, hwaddr addr, unsigned len)
     PCTestdev *dev = opaque;
     uint64_t ret = 0;
     memcpy(&ret, &dev->iomem_buf[addr], len);
-    ret = le64_to_cpu(ret);
 
     return ret;
 }
@@ -131,7 +148,6 @@ static void test_iomem_write(void *opaque, hwaddr addr, uint64_t val,
                              unsigned len)
 {
     PCTestdev *dev = opaque;
-    val = cpu_to_le64(val);
     memcpy(&dev->iomem_buf[addr], &val, len);
     dev->iomem_buf[addr] = val;
 }
@@ -151,6 +167,9 @@ static void testdev_realizefn(DeviceState *d, Error **errp)
 
     memory_region_init_io(&dev->ioport, OBJECT(dev), &test_ioport_ops, dev,
                           "pc-testdev-ioport", 4);
+    memory_region_init_io(&dev->ioport_byte, OBJECT(dev),
+                          &test_ioport_byte_ops, dev,
+                          "pc-testdev-ioport-byte", 4);
     memory_region_init_io(&dev->flush, OBJECT(dev), &test_flush_ops, dev,
                           "pc-testdev-flush-page", 4);
     memory_region_init_io(&dev->irq, OBJECT(dev), &test_irq_ops, dev,
@@ -160,6 +179,7 @@ static void testdev_realizefn(DeviceState *d, Error **errp)
 
     memory_region_add_subregion(io,  0xe0,       &dev->ioport);
     memory_region_add_subregion(io,  0xe4,       &dev->flush);
+    memory_region_add_subregion(io,  0xe8,       &dev->ioport_byte);
     memory_region_add_subregion(io,  0x2000,     &dev->irq);
     memory_region_add_subregion(mem, 0xff000000, &dev->iomem);
 }
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 06ace085b5..3756ce9a4b 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -70,9 +70,14 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
 #define MAX_IVEC 0x40
 #define NO_IRQ_REQUEST (MAX_IVEC + 1)
 
+#define TYPE_APB "pbm"
+
+#define APB_DEVICE(obj) \
+    OBJECT_CHECK(APBState, (obj), TYPE_APB)
+
 typedef struct APBState {
-    SysBusDevice busdev;
-    PCIBus      *bus;
+    PCIHostState parent_obj;
+
     MemoryRegion apb_config;
     MemoryRegion pci_config;
     MemoryRegion pci_mmio;
@@ -284,10 +289,11 @@ static void apb_pci_config_write(void *opaque, hwaddr addr,
                                  uint64_t val, unsigned size)
 {
     APBState *s = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(s);
 
     val = qemu_bswap_len(val, size);
     APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
-    pci_data_write(s->bus, addr, val, size);
+    pci_data_write(phb->bus, addr, val, size);
 }
 
 static uint64_t apb_pci_config_read(void *opaque, hwaddr addr,
@@ -295,63 +301,14 @@ static uint64_t apb_pci_config_read(void *opaque, hwaddr addr,
 {
     uint32_t ret;
     APBState *s = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(s);
 
-    ret = pci_data_read(s->bus, addr, size);
+    ret = pci_data_read(phb->bus, addr, size);
     ret = qemu_bswap_len(ret, size);
     APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, ret);
     return ret;
 }
 
-static void pci_apb_iowriteb (void *opaque, hwaddr addr,
-                                  uint32_t val)
-{
-    cpu_outb(addr & IOPORTS_MASK, val);
-}
-
-static void pci_apb_iowritew (void *opaque, hwaddr addr,
-                                  uint32_t val)
-{
-    cpu_outw(addr & IOPORTS_MASK, bswap16(val));
-}
-
-static void pci_apb_iowritel (void *opaque, hwaddr addr,
-                                uint32_t val)
-{
-    cpu_outl(addr & IOPORTS_MASK, bswap32(val));
-}
-
-static uint32_t pci_apb_ioreadb (void *opaque, hwaddr addr)
-{
-    uint32_t val;
-
-    val = cpu_inb(addr & IOPORTS_MASK);
-    return val;
-}
-
-static uint32_t pci_apb_ioreadw (void *opaque, hwaddr addr)
-{
-    uint32_t val;
-
-    val = bswap16(cpu_inw(addr & IOPORTS_MASK));
-    return val;
-}
-
-static uint32_t pci_apb_ioreadl (void *opaque, hwaddr addr)
-{
-    uint32_t val;
-
-    val = bswap32(cpu_inl(addr & IOPORTS_MASK));
-    return val;
-}
-
-static const MemoryRegionOps pci_ioport_ops = {
-    .old_mmio = {
-        .read = { pci_apb_ioreadb, pci_apb_ioreadw, pci_apb_ioreadl },
-        .write = { pci_apb_iowriteb, pci_apb_iowritew, pci_apb_iowritel, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
 /* The APB host has an IRQ line for each IRQ line of each slot.  */
 static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
 {
@@ -431,12 +388,13 @@ PCIBus *pci_apb_init(hwaddr special_base,
 {
     DeviceState *dev;
     SysBusDevice *s;
+    PCIHostState *phb;
     APBState *d;
     PCIDevice *pci_dev;
     PCIBridge *br;
 
     /* Ultrasparc PBM main bus */
-    dev = qdev_create(NULL, "pbm");
+    dev = qdev_create(NULL, TYPE_APB);
     qdev_init_nofail(dev);
     s = SYS_BUS_DEVICE(dev);
     /* apb_config */
@@ -445,24 +403,25 @@ PCIBus *pci_apb_init(hwaddr special_base,
     sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
     /* pci_ioport */
     sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
-    d = FROM_SYSBUS(APBState, s);
+    d = APB_DEVICE(dev);
 
     memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL);
     memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);
 
-    d->bus = pci_register_bus(&d->busdev.qdev, "pci",
-                              pci_apb_set_irq, pci_pbm_map_irq, d,
-                              &d->pci_mmio,
-                              get_system_io(),
-                              0, 32, TYPE_PCI_BUS);
+    phb = PCI_HOST_BRIDGE(dev);
+    phb->bus = pci_register_bus(DEVICE(phb), "pci",
+                                pci_apb_set_irq, pci_pbm_map_irq, d,
+                                &d->pci_mmio,
+                                get_system_io(),
+                                0, 32, TYPE_PCI_BUS);
 
     *pbm_irqs = d->pbm_irqs;
     d->ivec_irqs = ivec_irqs;
 
-    pci_create_simple(d->bus, 0, "pbm-pci");
+    pci_create_simple(phb->bus, 0, "pbm-pci");
 
     /* APB secondary busses */
-    pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true,
+    pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true,
                                    "pbm-bridge");
     br = DO_UPCAST(PCIBridge, dev, pci_dev);
     pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
@@ -470,7 +429,7 @@ PCIBus *pci_apb_init(hwaddr special_base,
     qdev_init_nofail(&pci_dev->qdev);
     *bus2 = pci_bridge_get_sec_bus(br);
 
-    pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true,
+    pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true,
                                    "pbm-bridge");
     br = DO_UPCAST(PCIBridge, dev, pci_dev);
     pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
@@ -478,13 +437,13 @@ PCIBus *pci_apb_init(hwaddr special_base,
     qdev_init_nofail(&pci_dev->qdev);
     *bus3 = pci_bridge_get_sec_bus(br);
 
-    return d->bus;
+    return phb->bus;
 }
 
 static void pci_pbm_reset(DeviceState *d)
 {
     unsigned int i;
-    APBState *s = container_of(d, APBState, busdev.qdev);
+    APBState *s = APB_DEVICE(d);
 
     for (i = 0; i < 8; i++) {
         s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
@@ -513,7 +472,7 @@ static int pci_pbm_init_device(SysBusDevice *dev)
     APBState *s;
     unsigned int i;
 
-    s = FROM_SYSBUS(APBState, dev);
+    s = APB_DEVICE(dev);
     for (i = 0; i < 8; i++) {
         s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
     }
@@ -536,8 +495,8 @@ static int pci_pbm_init_device(SysBusDevice *dev)
     sysbus_init_mmio(dev, &s->pci_config);
 
     /* pci_ioport */
-    memory_region_init_io(&s->pci_ioport, OBJECT(s), &pci_ioport_ops, s,
-                          "apb-pci-ioport", 0x10000);
+    memory_region_init_alias(&s->pci_ioport, OBJECT(s), "apb-pci-ioport",
+                             get_system_io(), 0, 0x10000);
     /* at region 2 */
     sysbus_init_mmio(dev, &s->pci_ioport);
 
@@ -581,8 +540,8 @@ static void pbm_host_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo pbm_host_info = {
-    .name          = "pbm",
-    .parent        = TYPE_SYS_BUS_DEVICE,
+    .name          = TYPE_APB,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(APBState),
     .class_init    = pbm_host_class_init,
 };
diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c
index 592d6666bc..5086d42c13 100644
--- a/hw/pci-host/bonito.c
+++ b/hw/pci-host/bonito.c
@@ -210,14 +210,8 @@ typedef struct PCIBonitoState
     MemoryRegion iomem;
     MemoryRegion iomem_ldma;
     MemoryRegion iomem_cop;
-
-    hwaddr bonito_pciio_start;
-    hwaddr bonito_pciio_length;
-    int bonito_pciio_handle;
-
-    hwaddr bonito_localio_start;
-    hwaddr bonito_localio_length;
-    int bonito_localio_handle;
+    MemoryRegion bonito_pciio;
+    MemoryRegion bonito_localio;
 
 } PCIBonitoState;
 
@@ -750,15 +744,16 @@ static int bonito_initfn(PCIDevice *dev)
     sysbus_mmio_map(sysbus, 4, 0xbfe00300);
 
     /* Map PCI IO Space  0x1fd0 0000 - 0x1fd1 0000 */
-    s->bonito_pciio_start = BONITO_PCIIO_BASE;
-    s->bonito_pciio_length = BONITO_PCIIO_SIZE;
-    isa_mem_base = s->bonito_pciio_start;
-    isa_mmio_init(s->bonito_pciio_start, s->bonito_pciio_length);
+    memory_region_init_alias(&s->bonito_pciio, OBJECT(s), "isa_mmio",
+                             get_system_io(), 0, BONITO_PCIIO_SIZE);
+    sysbus_init_mmio(sysbus, &s->bonito_pciio);
+    sysbus_mmio_map(sysbus, 5, BONITO_PCIIO_BASE);
 
     /* add pci local io mapping */
-    s->bonito_localio_start = BONITO_DEV_BASE;
-    s->bonito_localio_length = BONITO_DEV_SIZE;
-    isa_mmio_init(s->bonito_localio_start, s->bonito_localio_length);
+    memory_region_init_alias(&s->bonito_localio, OBJECT(s), "isa_mmio",
+                             get_system_io(), 0, BONITO_DEV_SIZE);
+    sysbus_init_mmio(sysbus, &s->bonito_localio);
+    sysbus_mmio_map(sysbus, 6, BONITO_DEV_BASE);
 
     /* set the default value of north bridge pci config */
     pci_set_word(dev->config + PCI_COMMAND, 0x0000);
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index fe803480a7..7ef806ef7f 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -152,6 +152,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args)
     CPUPPCState *env = NULL;
     char *filename;
     qemu_irq *pic, **openpic_irqs;
+    MemoryRegion *isa = g_new(MemoryRegion, 1);
     MemoryRegion *unin_memory = g_new(MemoryRegion, 1);
     MemoryRegion *unin2_memory = g_new(MemoryRegion, 1);
     int linux_boot, i, j, k;
@@ -288,7 +289,9 @@ static void ppc_core99_init(QEMUMachineInitArgs *args)
     }
 
     /* Register 8 MB of ISA IO space */
-    isa_mmio_init(0xf2000000, 0x00800000);
+    memory_region_init_alias(isa, NULL, "isa_mmio",
+                             get_system_io(), 0, 0x00800000);
+    memory_region_add_subregion(get_system_memory(), 0xf2000000, isa);
 
     /* UniN init: XXX should be a real device */
     memory_region_init_io(unin_memory, NULL, &unin_ops, token, "unin", 0x1000);
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 8b8c6b93a5..42bb9d55c8 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -87,6 +87,7 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args)
     int linux_boot, i;
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     MemoryRegion *bios = g_new(MemoryRegion, 1);
+    MemoryRegion *isa = g_new(MemoryRegion, 1);
     uint32_t kernel_base, initrd_base, cmdline_base = 0;
     int32_t kernel_size, initrd_size;
     PCIBus *pci_bus;
@@ -225,7 +226,9 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args)
     }
 
     /* Register 2 MB of ISA IO space */
-    isa_mmio_init(0xfe000000, 0x00200000);
+    memory_region_init_alias(isa, NULL, "isa_mmio",
+                             get_system_io(), 0, 0x00200000);
+    memory_region_add_subregion(sysmem, 0xfe000000, isa);
 
     /* XXX: we register only 1 output pin for heathrow PIC */
     heathrow_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index 5b039abb38..369ab9e26e 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -164,6 +164,7 @@ static void bamboo_init(QEMUMachineInitArgs *args)
     const char *initrd_filename = args->initrd_filename;
     unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
     MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *isa = g_new(MemoryRegion, 1);
     MemoryRegion *ram_memories
         = g_malloc(PPC440EP_SDRAM_NR_BANKS * sizeof(*ram_memories));
     hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS];
@@ -225,7 +226,9 @@ static void bamboo_init(QEMUMachineInitArgs *args)
         exit(1);
     }
 
-    isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN);
+    memory_region_init_alias(isa, NULL, "isa_mmio",
+                             get_system_io(), 0, PPC440EP_PCI_IOLEN);
+    memory_region_add_subregion(get_system_memory(), PPC440EP_PCI_IO, isa);
 
     if (serial_hds[0] != NULL) {
         serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 19f2442482..7e04b1ac84 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -410,7 +410,7 @@ static const MemoryRegionOps PPC_prep_io_ops = {
         .read = { PPC_prep_io_readb, PPC_prep_io_readw, PPC_prep_io_readl },
         .write = { PPC_prep_io_writeb, PPC_prep_io_writew, PPC_prep_io_writel },
     },
-    .endianness = DEVICE_LITTLE_ENDIAN,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 #define NVRAM_SIZE        0x2000
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 318bc9d6ef..c880a757c8 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -440,43 +440,6 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level)
     qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level);
 }
 
-static uint64_t spapr_io_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    switch (size) {
-    case 1:
-        return cpu_inb(addr);
-    case 2:
-        return cpu_inw(addr);
-    case 4:
-        return cpu_inl(addr);
-    }
-    g_assert_not_reached();
-}
-
-static void spapr_io_write(void *opaque, hwaddr addr,
-                           uint64_t data, unsigned size)
-{
-    switch (size) {
-    case 1:
-        cpu_outb(addr, data);
-        return;
-    case 2:
-        cpu_outw(addr, data);
-        return;
-    case 4:
-        cpu_outl(addr, data);
-        return;
-    }
-    g_assert_not_reached();
-}
-
-static const MemoryRegionOps spapr_io_ops = {
-    .endianness = DEVICE_LITTLE_ENDIAN,
-    .read = spapr_io_read,
-    .write = spapr_io_write
-};
-
 /*
  * MSI/MSIX memory region implementation.
  * The handler handles both MSI and MSIX.
@@ -605,8 +568,8 @@ static int spapr_phb_init(SysBusDevice *s)
     memory_region_add_subregion(get_system_io(), 0, &sphb->iospace);
 
     sprintf(namebuf, "%s.io-alias", sphb->dtbusname);
-    memory_region_init_io(&sphb->iowindow, OBJECT(sphb), &spapr_io_ops, sphb,
-                          namebuf, SPAPR_PCI_IO_WIN_SIZE);
+    memory_region_init_alias(&sphb->iowindow, OBJECT(sphb), namebuf,
+                             get_system_io(), 0, SPAPR_PCI_IO_WIN_SIZE);
     memory_region_add_subregion(get_system_memory(), sphb->io_win_addr,
                                 &sphb->iowindow);
 
diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c
index c33a72f80f..e81176a11e 100644
--- a/hw/sh4/sh_pci.c
+++ b/hw/sh4/sh_pci.c
@@ -28,9 +28,14 @@
 #include "qemu/bswap.h"
 #include "exec/address-spaces.h"
 
+#define TYPE_SH_PCI_HOST_BRIDGE "sh_pci"
+
+#define SH_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(SHPCIState, (obj), TYPE_SH_PCI_HOST_BRIDGE)
+
 typedef struct SHPCIState {
-    SysBusDevice busdev;
-    PCIBus *bus;
+    PCIHostState parent_obj;
+
     PCIDevice *dev;
     qemu_irq irq[4];
     MemoryRegion memconfig_p4;
@@ -45,6 +50,8 @@ static void sh_pci_reg_write (void *p, hwaddr addr, uint64_t val,
                               unsigned size)
 {
     SHPCIState *pcic = p;
+    PCIHostState *phb = PCI_HOST_BRIDGE(pcic);
+
     switch(addr) {
     case 0 ... 0xfc:
         cpu_to_le32w((uint32_t*)(pcic->dev->config + addr), val);
@@ -64,7 +71,7 @@ static void sh_pci_reg_write (void *p, hwaddr addr, uint64_t val,
         }
         break;
     case 0x220:
-        pci_data_write(pcic->bus, pcic->par, val, 4);
+        pci_data_write(phb->bus, pcic->par, val, 4);
         break;
     }
 }
@@ -73,6 +80,8 @@ static uint64_t sh_pci_reg_read (void *p, hwaddr addr,
                                  unsigned size)
 {
     SHPCIState *pcic = p;
+    PCIHostState *phb = PCI_HOST_BRIDGE(pcic);
+
     switch(addr) {
     case 0 ... 0xfc:
         return le32_to_cpup((uint32_t*)(pcic->dev->config + addr));
@@ -83,7 +92,7 @@ static uint64_t sh_pci_reg_read (void *p, hwaddr addr,
     case 0x1c8:
         return pcic->iobr;
     case 0x220:
-        return pci_data_read(pcic->bus, pcic->par, 4);
+        return pci_data_read(phb->bus, pcic->par, 4);
     }
     return 0;
 }
@@ -112,30 +121,33 @@ static void sh_pci_set_irq(void *opaque, int irq_num, int level)
 
 static int sh_pci_device_init(SysBusDevice *dev)
 {
+    PCIHostState *phb;
     SHPCIState *s;
     int i;
 
-    s = FROM_SYSBUS(SHPCIState, dev);
+    s = SH_PCI_HOST_BRIDGE(dev);
+    phb = PCI_HOST_BRIDGE(s);
     for (i = 0; i < 4; i++) {
         sysbus_init_irq(dev, &s->irq[i]);
     }
-    s->bus = pci_register_bus(&s->busdev.qdev, "pci",
-                              sh_pci_set_irq, sh_pci_map_irq,
-                              s->irq,
-                              get_system_memory(),
-                              get_system_io(),
-                              PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
+    phb->bus = pci_register_bus(DEVICE(dev), "pci",
+                                sh_pci_set_irq, sh_pci_map_irq,
+                                s->irq,
+                                get_system_memory(),
+                                get_system_io(),
+                                PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
     memory_region_init_io(&s->memconfig_p4, OBJECT(s), &sh_pci_reg_ops, s,
                           "sh_pci", 0x224);
     memory_region_init_alias(&s->memconfig_a7, OBJECT(s), "sh_pci.2",
                              &s->memconfig_p4, 0, 0x224);
-    isa_mmio_setup(&s->isa, 0x40000);
+    memory_region_init_alias(&s->isa, OBJECT(s), "sh_pci.isa",
+                             get_system_io(), 0, 0x40000);
     sysbus_init_mmio(dev, &s->memconfig_p4);
     sysbus_init_mmio(dev, &s->memconfig_a7);
     s->iobr = 0xfe240000;
     memory_region_add_subregion(get_system_memory(), s->iobr, &s->isa);
 
-    s->dev = pci_create_simple(s->bus, PCI_DEVFN(0, 0), "sh_pci_host");
+    s->dev = pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "sh_pci_host");
     return 0;
 }
 
@@ -171,8 +183,8 @@ static void sh_pci_device_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo sh_pci_device_info = {
-    .name          = "sh_pci",
-    .parent        = TYPE_SYS_BUS_DEVICE,
+    .name          = TYPE_SH_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(SHPCIState),
     .class_init    = sh_pci_device_class_init,
 };
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 564c1959ee..34a5e7331c 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -605,9 +605,11 @@ pci_ebus_init1(PCIDevice *pci_dev)
     pci_dev->config[0x09] = 0x00; // programming i/f
     pci_dev->config[0x0D] = 0x0a; // latency_timer
 
-    isa_mmio_setup(&s->bar0, 0x1000000);
+    memory_region_init_alias(&s->bar0, OBJECT(s), "bar0", get_system_io(),
+                             0, 0x1000000);
     pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0);
-    isa_mmio_setup(&s->bar1, 0x800000);
+    memory_region_init_alias(&s->bar1, OBJECT(s), "bar1", get_system_io(),
+                             0, 0x800000);
     pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar1);
     return 0;
 }
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index f2800ec682..a407b50f4a 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -210,11 +210,15 @@ extern unsigned long reserved_va;
 })
 #endif
 
-#define h2g(x) ({ \
+#define h2g_nocheck(x) ({ \
     unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \
+    (abi_ulong)__ret; \
+})
+
+#define h2g(x) ({ \
     /* Check if given address fits target address space */ \
     assert(h2g_valid(x)); \
-    (abi_ulong)__ret; \
+    h2g_nocheck(x); \
 })
 
 #define saddr(x) g2h(x)
diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index 1bd00aea23..7ea1ad7f9c 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -32,7 +32,7 @@ void gdb_register_coprocessor(CPUState *cpu,
 
 static inline int cpu_index(CPUState *cpu)
 {
-#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USE_NPTL)
+#if defined(CONFIG_USER_ONLY)
     return cpu->host_tid;
 #else
     return cpu->cpu_index + 1;
diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h
index e1bf96ca69..495bcf3a08 100644
--- a/include/hw/isa/isa.h
+++ b/include/hw/isa/isa.h
@@ -92,9 +92,6 @@ static inline ISABus *isa_bus_from_device(ISADevice *d)
 
 extern hwaddr isa_mem_base;
 
-void isa_mmio_setup(MemoryRegion *mr, hwaddr size);
-void isa_mmio_init(hwaddr base, hwaddr size);
-
 /* dma.c */
 int DMA_get_channel_mode (int nchan);
 int DMA_read_memory (int nchan, void *buf, int pos, int size);
diff --git a/ioport.c b/ioport.c
index 89b17d69f4..79b7f1ae38 100644
--- a/ioport.c
+++ b/ioport.c
@@ -183,6 +183,7 @@ static void portio_write(void *opaque, hwaddr addr, uint64_t data,
 static const MemoryRegionOps portio_ops = {
     .read = portio_read,
     .write = portio_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
     .valid.unaligned = true,
     .impl.unaligned = true,
 };
diff --git a/linux-user/arm/syscall.h b/linux-user/arm/syscall.h
index 003d424701..73f29314f6 100644
--- a/linux-user/arm/syscall.h
+++ b/linux-user/arm/syscall.h
@@ -40,3 +40,5 @@ struct target_pt_regs {
 #else
 #define UNAME_MACHINE "armv5tel"
 #endif
+
+#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/cris/syscall.h b/linux-user/cris/syscall.h
index 50e50b4f3f..832ee64bd8 100644
--- a/linux-user/cris/syscall.h
+++ b/linux-user/cris/syscall.h
@@ -38,4 +38,6 @@ struct target_pt_regs {
         unsigned long eda;
 };
 
+#define TARGET_CLONE_BACKWARDS2
+
 #endif
diff --git a/linux-user/i386/syscall.h b/linux-user/i386/syscall.h
index 266e2c4c83..12b8c3b672 100644
--- a/linux-user/i386/syscall.h
+++ b/linux-user/i386/syscall.h
@@ -144,3 +144,5 @@ struct target_vm86plus_struct {
 };
 
 #define UNAME_MACHINE "i686"
+
+#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/i386/target_cpu.h b/linux-user/i386/target_cpu.h
index abcac79d25..58f86454d6 100644
--- a/linux-user/i386/target_cpu.h
+++ b/linux-user/i386/target_cpu.h
@@ -28,6 +28,21 @@ static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp)
     env->regs[R_EAX] = 0;
 }
 
-/* TODO: need to implement cpu_set_tls() */
+#if defined(TARGET_ABI32)
+abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr);
 
-#endif
+static inline void cpu_set_tls(CPUX86State *env, target_ulong newtls)
+{
+    do_set_thread_area(env, newtls);
+    cpu_x86_load_seg(env, R_GS, env->segs[R_GS].selector);
+}
+#else
+abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr);
+
+static inline void cpu_set_tls(CPUX86State *env, target_ulong newtls)
+{
+    do_arch_prctl(env, TARGET_ARCH_SET_FS, newtls);
+}
+#endif /* defined(TARGET_ABI32) */
+
+#endif /* !defined(TARGET_CPU_H) */
diff --git a/linux-user/m68k/target_cpu.h b/linux-user/m68k/target_cpu.h
index 8a2a305a0b..cad9c90dd0 100644
--- a/linux-user/m68k/target_cpu.h
+++ b/linux-user/m68k/target_cpu.h
@@ -29,6 +29,10 @@ static inline void cpu_clone_regs(CPUM68KState *env, target_ulong newsp)
     env->dregs[0] = 0;
 }
 
-/* TODO: need to implement cpu_set_tls() */
+static inline void cpu_set_tls(CPUM68KState *env, target_ulong newtls)
+{
+    TaskState *ts = env->opaque;
+    ts->tp_value = newtls;
+}
 
 #endif
diff --git a/linux-user/main.c b/linux-user/main.c
index f6a3aad9e5..5dc09471e4 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -92,7 +92,6 @@ int cpu_get_pic_interrupt(CPUX86State *env)
 }
 #endif
 
-#if defined(CONFIG_USE_NPTL)
 /***********************************************************/
 /* Helper routines for implementing atomic operations.  */
 
@@ -207,43 +206,6 @@ void cpu_list_unlock(void)
 {
     pthread_mutex_unlock(&cpu_list_mutex);
 }
-#else /* if !CONFIG_USE_NPTL */
-/* These are no-ops because we are not threadsafe.  */
-static inline void cpu_exec_start(CPUState *cpu)
-{
-}
-
-static inline void cpu_exec_end(CPUState *cpu)
-{
-}
-
-static inline void start_exclusive(void)
-{
-}
-
-static inline void end_exclusive(void)
-{
-}
-
-void fork_start(void)
-{
-}
-
-void fork_end(int child)
-{
-    if (child) {
-        gdbserver_fork((CPUArchState *)thread_cpu->env_ptr);
-    }
-}
-
-void cpu_list_lock(void)
-{
-}
-
-void cpu_list_unlock(void)
-{
-}
-#endif
 
 
 #ifdef TARGET_I386
@@ -2349,7 +2311,31 @@ done_syscall:
                 abi_ulong trap_instr;
                 unsigned int code;
 
-                ret = get_user_ual(trap_instr, env->active_tc.PC);
+                if (env->hflags & MIPS_HFLAG_M16) {
+                    if (env->insn_flags & ASE_MICROMIPS) {
+                        /* microMIPS mode */
+                        abi_ulong instr[2];
+
+                        ret = get_user_u16(instr[0], env->active_tc.PC) ||
+                              get_user_u16(instr[1], env->active_tc.PC + 2);
+
+                        trap_instr = (instr[0] << 16) | instr[1];
+                    } else {
+                        /* MIPS16e mode */
+                        ret = get_user_u16(trap_instr, env->active_tc.PC);
+                        if (ret != 0) {
+                            goto error;
+                        }
+                        code = (trap_instr >> 6) & 0x3f;
+                        if (do_break(env, &info, code) != 0) {
+                            goto error;
+                        }
+                        break;
+                    }
+                } else {
+                    ret = get_user_ual(trap_instr, env->active_tc.PC);
+                }
+
                 if (ret != 0) {
                     goto error;
                 }
@@ -2373,14 +2359,30 @@ done_syscall:
                 abi_ulong trap_instr;
                 unsigned int code = 0;
 
-                ret = get_user_ual(trap_instr, env->active_tc.PC);
+                if (env->hflags & MIPS_HFLAG_M16) {
+                    /* microMIPS mode */
+                    abi_ulong instr[2];
+
+                    ret = get_user_u16(instr[0], env->active_tc.PC) ||
+                          get_user_u16(instr[1], env->active_tc.PC + 2);
+
+                    trap_instr = (instr[0] << 16) | instr[1];
+                } else {
+                    ret = get_user_ual(trap_instr, env->active_tc.PC);
+                }
+
                 if (ret != 0) {
                     goto error;
                 }
 
                 /* The immediate versions don't provide a code.  */
                 if (!(trap_instr & 0xFC000000)) {
-                    code = ((trap_instr >> 6) & ((1 << 10) - 1));
+                    if (env->hflags & MIPS_HFLAG_M16) {
+                        /* microMIPS mode */
+                        code = ((trap_instr >> 12) & ((1 << 4) - 1));
+                    } else {
+                        code = ((trap_instr >> 6) & ((1 << 10) - 1));
+                    }
                 }
 
                 if (do_break(env, &info, code) != 0) {
@@ -3157,12 +3159,7 @@ THREAD CPUState *thread_cpu;
 void task_settid(TaskState *ts)
 {
     if (ts->ts_tid == 0) {
-#ifdef CONFIG_USE_NPTL
         ts->ts_tid = (pid_t)syscall(SYS_gettid);
-#else
-        /* when no threads are used, tid becomes pid */
-        ts->ts_tid = getpid();
-#endif
     }
 }
 
@@ -3640,9 +3637,7 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
     cpu = ENV_GET_CPU(env);
-#if defined(TARGET_SPARC) || defined(TARGET_PPC)
-    cpu_reset(cpu);
-#endif
+    cpu_reset(ENV_GET_CPU(env));
 
     thread_cpu = cpu;
 
diff --git a/linux-user/microblaze/syscall.h b/linux-user/microblaze/syscall.h
index c3e5c55b3d..d550989d5e 100644
--- a/linux-user/microblaze/syscall.h
+++ b/linux-user/microblaze/syscall.h
@@ -48,4 +48,6 @@ struct target_pt_regs {
         uint32_t kernel_mode;
 };
 
+#define TARGET_CLONE_BACKWARDS
+
 #endif
diff --git a/linux-user/mips/syscall.h b/linux-user/mips/syscall.h
index 3deb862cc4..9d437d918b 100644
--- a/linux-user/mips/syscall.h
+++ b/linux-user/mips/syscall.h
@@ -225,3 +225,5 @@ struct target_pt_regs {
 #define TARGET_QEMU_ESIGRETURN 255
 
 #define UNAME_MACHINE "mips"
+
+#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/mips64/syscall.h b/linux-user/mips64/syscall.h
index cd707df32f..1710f766e2 100644
--- a/linux-user/mips64/syscall.h
+++ b/linux-user/mips64/syscall.h
@@ -222,3 +222,5 @@ struct target_pt_regs {
 #define TARGET_QEMU_ESIGRETURN 255
 
 #define UNAME_MACHINE "mips64"
+
+#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index de2219768d..a249f0ceb6 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -33,7 +33,6 @@
 
 //#define DEBUG_MMAP
 
-#if defined(CONFIG_USE_NPTL)
 static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
 static __thread int mmap_lock_count;
 
@@ -66,16 +65,6 @@ void mmap_fork_end(int child)
     else
         pthread_mutex_unlock(&mmap_mutex);
 }
-#else
-/* We aren't threadsafe to start with, so no need to worry about locking.  */
-void mmap_lock(void)
-{
-}
-
-void mmap_unlock(void)
-{
-}
-#endif
 
 /* NOTE: all the constants are the HOST ones, but addresses are target. */
 int target_mprotect(abi_ulong start, abi_ulong len, int prot)
diff --git a/linux-user/openrisc/target_cpu.h b/linux-user/openrisc/target_cpu.h
index 501fb81162..32a46ac840 100644
--- a/linux-user/openrisc/target_cpu.h
+++ b/linux-user/openrisc/target_cpu.h
@@ -25,9 +25,14 @@ static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp)
     if (newsp) {
         env->gpr[1] = newsp;
     }
-    env->gpr[2] = 0;
+    env->gpr[11] = 0;
 }
 
-/* TODO: need to implement cpu_set_tls() */
+static inline void cpu_set_tls(CPUOpenRISCState *env, target_ulong newtls)
+{
+    /* Linux kernel 3.10 does not pay any attention to CLONE_SETTLS
+     * in copy_thread(), so QEMU need not do so either.
+     */
+}
 
 #endif
diff --git a/linux-user/ppc/syscall.h b/linux-user/ppc/syscall.h
index 481047b2dd..ba36acbc33 100644
--- a/linux-user/ppc/syscall.h
+++ b/linux-user/ppc/syscall.h
@@ -62,3 +62,5 @@ struct target_revectored_struct {
 #else
 #define UNAME_MACHINE "ppc"
 #endif
+
+#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 6569608b64..4a16e8fe1d 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -16,16 +16,10 @@
 #include "exec/user/thunk.h"
 #include "syscall_defs.h"
 #include "syscall.h"
-#include "target_cpu.h"
-#include "target_signal.h"
 #include "exec/gdbstub.h"
 #include "qemu/queue.h"
 
-#if defined(CONFIG_USE_NPTL)
 #define THREAD __thread
-#else
-#define THREAD
-#endif
 
 /* This struct is used to hold certain information about the image.
  * Basically, it replicates in user space what would be certain
@@ -118,11 +112,10 @@ typedef struct TaskState {
     uint32_t v86flags;
     uint32_t v86mask;
 #endif
-#ifdef CONFIG_USE_NPTL
     abi_ulong child_tidptr;
-#endif
 #ifdef TARGET_M68K
     int sim_syscalls;
+    abi_ulong tp_value;
 #endif
 #if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
     /* Extra fields for semihosted binaries.  */
@@ -269,10 +262,8 @@ void mmap_unlock(void);
 abi_ulong mmap_find_vma(abi_ulong, abi_ulong);
 void cpu_list_lock(void);
 void cpu_list_unlock(void);
-#if defined(CONFIG_USE_NPTL)
 void mmap_fork_start(void);
 void mmap_fork_end(int child);
-#endif
 
 /* main.c */
 extern unsigned long guest_stack_size;
@@ -450,8 +441,13 @@ static inline void *lock_user_string(abi_ulong guest_addr)
 #define unlock_user_struct(host_ptr, guest_addr, copy)		\
     unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0)
 
-#if defined(CONFIG_USE_NPTL)
 #include <pthread.h>
-#endif
+
+/* Include target-specific struct and function definitions;
+ * they may need access to the target-independent structures
+ * above, so include them last.
+ */
+#include "target_cpu.h"
+#include "target_signal.h"
 
 #endif /* QEMU_H */
diff --git a/linux-user/s390x/syscall.h b/linux-user/s390x/syscall.h
index e4603b79c3..ea8c304840 100644
--- a/linux-user/s390x/syscall.h
+++ b/linux-user/s390x/syscall.h
@@ -21,3 +21,5 @@ struct target_pt_regs {
 };
 
 #define UNAME_MACHINE "s390x"
+
+#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/sparc/syscall.h b/linux-user/sparc/syscall.h
index 5a9bb7e546..4cd64bf41d 100644
--- a/linux-user/sparc/syscall.h
+++ b/linux-user/sparc/syscall.h
@@ -7,3 +7,10 @@ struct target_pt_regs {
 };
 
 #define UNAME_MACHINE "sun4"
+
+/* SPARC kernels don't define this in their Kconfig, but they have the
+ * same ABI as if they did, implemented by sparc-specific code which fishes
+ * directly in the u_regs() struct for half the parameters in sparc_do_fork()
+ * and copy_thread().
+ */
+#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/sparc/target_cpu.h b/linux-user/sparc/target_cpu.h
index 5a620a2bb7..4944d465a2 100644
--- a/linux-user/sparc/target_cpu.h
+++ b/linux-user/sparc/target_cpu.h
@@ -25,12 +25,20 @@ static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp)
     if (newsp) {
         env->regwptr[22] = newsp;
     }
+    /* syscall return for clone child: 0, and clear CF since
+     * this counts as a success return value.
+     */
     env->regwptr[0] = 0;
-    /* FIXME: Do we also need to clear CF?  */
-    /* XXXXX */
-    printf("HELPME: %s:%d\n", __FILE__, __LINE__);
+#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
+    env->xcc &= ~PSR_CARRY;
+#else
+    env->psr &= ~PSR_CARRY;
+#endif
 }
 
-/* TODO: need to implement cpu_set_tls() */
+static inline void cpu_set_tls(CPUSPARCState *env, target_ulong newtls)
+{
+    env->gregs[7] = newtls;
+}
 
 #endif
diff --git a/linux-user/sparc64/syscall.h b/linux-user/sparc64/syscall.h
index 81a816de94..e60bf311c0 100644
--- a/linux-user/sparc64/syscall.h
+++ b/linux-user/sparc64/syscall.h
@@ -8,3 +8,10 @@ struct target_pt_regs {
 };
 
 #define UNAME_MACHINE "sun4u"
+
+/* SPARC kernels don't define this in their Kconfig, but they have the
+ * same ABI as if they did, implemented by sparc-specific code which fishes
+ * directly in the u_regs() struct for half the parameters in sparc_do_fork()
+ * and copy_thread().
+ */
+#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 00a0390ea9..3f6db4b0d1 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -111,13 +111,8 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
 
 #include "qemu.h"
 
-#if defined(CONFIG_USE_NPTL)
 #define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
     CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
-#else
-/* XXX: Hardcode the above values.  */
-#define CLONE_NPTL_FLAGS2 0
-#endif
 
 //#define DEBUG
 
@@ -234,12 +229,10 @@ _syscall1(int,exit_group,int,error_code)
 #if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
 _syscall1(int,set_tid_address,int *,tidptr)
 #endif
-#if defined(CONFIG_USE_NPTL)
 #if defined(TARGET_NR_futex) && defined(__NR_futex)
 _syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
           const struct timespec *,timeout,int *,uaddr2,int,val3)
 #endif
-#endif
 #define __NR_sys_sched_getaffinity __NR_sched_getaffinity
 _syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
           unsigned long *, user_mask_ptr);
@@ -1039,6 +1032,9 @@ static abi_long do_pipe(void *cpu_env, abi_ulong pipedes,
 #elif defined(TARGET_SH4)
         ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
         return host_pipe[0];
+#elif defined(TARGET_SPARC)
+        ((CPUSPARCState*)cpu_env)->regwptr[1] = host_pipe[1];
+        return host_pipe[0];
 #endif
     }
 
@@ -4055,7 +4051,7 @@ static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
 }
 
 #if defined(TARGET_I386) && defined(TARGET_ABI32)
-static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
+abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
 {
     uint64_t *gdt_table = g2h(env->gdt.base);
     struct target_modify_ldt_ldt_s ldt_info;
@@ -4189,7 +4185,7 @@ static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
 #endif /* TARGET_I386 && TARGET_ABI32 */
 
 #ifndef TARGET_ABI32
-static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
+abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
 {
     abi_long ret = 0;
     abi_ulong val;
@@ -4227,7 +4223,6 @@ static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
 
 #define NEW_STACK_SIZE 0x40000
 
-#if defined(CONFIG_USE_NPTL)
 
 static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
 typedef struct {
@@ -4272,16 +4267,6 @@ static void *clone_func(void *arg)
     /* never exits */
     return NULL;
 }
-#else
-
-static int clone_func(void *arg)
-{
-    CPUArchState *env = arg;
-    cpu_loop(env);
-    /* never exits */
-    return 0;
-}
-#endif
 
 /* do_fork() Must return host values and target errnos (unlike most
    do_*() functions). */
@@ -4292,12 +4277,8 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
     int ret;
     TaskState *ts;
     CPUArchState *new_env;
-#if defined(CONFIG_USE_NPTL)
     unsigned int nptl_flags;
     sigset_t sigmask;
-#else
-    uint8_t *new_stack;
-#endif
 
     /* Emulate vfork() with fork() */
     if (flags & CLONE_VFORK)
@@ -4305,23 +4286,18 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
 
     if (flags & CLONE_VM) {
         TaskState *parent_ts = (TaskState *)env->opaque;
-#if defined(CONFIG_USE_NPTL)
         new_thread_info info;
         pthread_attr_t attr;
-#endif
+
         ts = g_malloc0(sizeof(TaskState));
         init_task_state(ts);
         /* we create a new CPU instance. */
         new_env = cpu_copy(env);
-#if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
-        cpu_reset(ENV_GET_CPU(new_env));
-#endif
         /* Init regs that differ from the parent.  */
         cpu_clone_regs(new_env, newsp);
         new_env->opaque = ts;
         ts->bprm = parent_ts->bprm;
         ts->info = parent_ts->info;
-#if defined(CONFIG_USE_NPTL)
         nptl_flags = flags;
         flags &= ~CLONE_NPTL_FLAGS2;
 
@@ -4371,17 +4347,6 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
         pthread_cond_destroy(&info.cond);
         pthread_mutex_destroy(&info.mutex);
         pthread_mutex_unlock(&clone_lock);
-#else
-        if (flags & CLONE_NPTL_FLAGS2)
-            return -EINVAL;
-        /* This is probably going to die very quickly, but do it anyway.  */
-        new_stack = g_malloc0 (NEW_STACK_SIZE);
-#ifdef __ia64__
-        ret = __clone2(clone_func, new_stack, NEW_STACK_SIZE, flags, new_env);
-#else
-	ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
-#endif
-#endif
     } else {
         /* if no CLONE_VM, we consider it is a fork */
         if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
@@ -4392,7 +4357,6 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
             /* Child Process.  */
             cpu_clone_regs(env, newsp);
             fork_end(1);
-#if defined(CONFIG_USE_NPTL)
             /* There is a race condition here.  The parent process could
                theoretically read the TID in the child process before the child
                tid is set.  This would require using either ptrace
@@ -4408,7 +4372,6 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
                 cpu_set_tls (env, newtls);
             if (flags & CLONE_CHILD_CLEARTID)
                 ts->child_tidptr = child_tidptr;
-#endif
         } else {
             fork_end(0);
         }
@@ -4834,7 +4797,6 @@ static inline abi_long host_to_target_stat64(void *cpu_env,
 }
 #endif
 
-#if defined(CONFIG_USE_NPTL)
 /* ??? Using host futex calls even when target atomic operations
    are not really atomic probably breaks things.  However implementing
    futexes locally would make futexes shared between multiple processes
@@ -4886,7 +4848,6 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
         return -TARGET_ENOSYS;
     }
 }
-#endif
 
 /* Map host to target signal numbers for the wait family of syscalls.
    Assume all other status bits are the same.  */
@@ -5132,9 +5093,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                     abi_long arg5, abi_long arg6, abi_long arg7,
                     abi_long arg8)
 {
-#ifdef CONFIG_USE_NPTL
     CPUState *cpu = ENV_GET_CPU(cpu_env);
-#endif
     abi_long ret;
     struct stat st;
     struct statfs stfs;
@@ -5148,7 +5107,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 
     switch(num) {
     case TARGET_NR_exit:
-#ifdef CONFIG_USE_NPTL
         /* In old applications this may be used to implement _exit(2).
            However in threaded applictions it is used for thread termination,
            and _exit_group is used for application termination.
@@ -5186,7 +5144,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             g_free(ts);
             pthread_exit(NULL);
         }
-#endif
 #ifdef TARGET_GPROF
         _mcleanup();
 #endif
@@ -6956,16 +6913,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         ret = get_errno(fsync(arg1));
         break;
     case TARGET_NR_clone:
-#if defined(TARGET_SH4) || defined(TARGET_ALPHA)
-        ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
-#elif defined(TARGET_CRIS)
-        ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
-#elif defined(TARGET_MICROBLAZE)
+        /* Linux manages to have three different orderings for its
+         * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
+         * match the kernel's CONFIG_CLONE_* settings.
+         * Microblaze is further special in that it uses a sixth
+         * implicit argument to clone for the TLS pointer.
+         */
+#if defined(TARGET_MICROBLAZE)
         ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
-#elif defined(TARGET_S390X)
+#elif defined(TARGET_CLONE_BACKWARDS)
+        ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
+#elif defined(TARGET_CLONE_BACKWARDS2)
         ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
 #else
-        ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
+        ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
 #endif
         break;
 #ifdef __NR_exit_group
@@ -8558,6 +8519,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #elif defined(TARGET_I386) && defined(TARGET_ABI32)
       ret = do_set_thread_area(cpu_env, arg1);
       break;
+#elif defined(TARGET_M68K)
+      {
+          TaskState *ts = ((CPUArchState *)cpu_env)->opaque;
+          ts->tp_value = arg1;
+          break;
+      }
 #else
       goto unimplemented_nowarn;
 #endif
@@ -8566,6 +8533,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     case TARGET_NR_get_thread_area:
 #if defined(TARGET_I386) && defined(TARGET_ABI32)
         ret = do_get_thread_area(cpu_env, arg1);
+        break;
+#elif defined(TARGET_M68K)
+        {
+            TaskState *ts = ((CPUArchState *)cpu_env)->opaque;
+            ret = ts->tp_value;
+            break;
+        }
 #else
         goto unimplemented_nowarn;
 #endif
@@ -8670,11 +8644,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         }
 	break;
 #endif
-#if defined(CONFIG_USE_NPTL)
     case TARGET_NR_futex:
         ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
         break;
-#endif
 #if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
     case TARGET_NR_inotify_init:
         ret = get_errno(sys_inotify_init());
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 92c01a9603..086fbfffe7 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -1138,8 +1138,7 @@ struct target_winsize {
 #endif
 
 #if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) \
-    || defined(TARGET_CRIS) || defined(TARGET_UNICORE32) \
-    || defined(TARGET_OPENRISC)
+    || defined(TARGET_CRIS) || defined(TARGET_UNICORE32)
 struct target_stat {
 	unsigned short st_dev;
 	unsigned short __pad1;
@@ -1837,29 +1836,55 @@ struct target_stat {
     abi_ulong  __unused[3];
 };
 #elif defined(TARGET_OPENRISC)
+
+/* These are the asm-generic versions of the stat and stat64 structures */
+
 struct target_stat {
     abi_ulong st_dev;
     abi_ulong st_ino;
-    abi_ulong st_nlink;
-
     unsigned int st_mode;
+    unsigned int st_nlink;
     unsigned int st_uid;
     unsigned int st_gid;
-    unsigned int __pad0;
     abi_ulong st_rdev;
+    abi_ulong __pad1;
     abi_long st_size;
-    abi_long st_blksize;
-    abi_long st_blocks;    /* Number 512-byte blocks allocated. */
-
-    abi_ulong target_st_atime;
+    int st_blksize;
+    int __pad2;
+    abi_long st_blocks;
+    abi_long target_st_atime;
     abi_ulong target_st_atime_nsec;
-    abi_ulong target_st_mtime;
+    abi_long target_st_mtime;
     abi_ulong target_st_mtime_nsec;
-    abi_ulong target_st_ctime;
+    abi_long target_st_ctime;
     abi_ulong target_st_ctime_nsec;
+    unsigned int __unused4;
+    unsigned int __unused5;
+};
 
-    abi_long __unused[3];
+struct target_stat64 {
+    uint64_t st_dev;
+    uint64_t st_ino;
+    unsigned int st_mode;
+    unsigned int st_nlink;
+    unsigned int st_uid;
+    unsigned int st_gid;
+    uint64_t st_rdev;
+    uint64_t __pad1;
+    int64_t st_size;
+    int st_blksize;
+    int __pad2;
+    int64_t st_blocks;
+    int target_st_atime;
+    unsigned int target_st_atime_nsec;
+    int target_st_mtime;
+    unsigned int target_st_mtime_nsec;
+    int target_st_ctime;
+    unsigned int target_st_ctime_nsec;
+    unsigned int __unused4;
+    unsigned int __unused5;
 };
+
 #else
 #error unsupported CPU
 #endif
@@ -2434,8 +2459,11 @@ typedef union target_epoll_data {
 
 struct target_epoll_event {
     uint32_t events;
+#ifdef TARGET_ARM
+    uint32_t __pad;
+#endif
     target_epoll_data_t data;
-};
+} QEMU_PACKED;
 #endif
 struct target_rlimit64 {
     uint64_t rlim_cur;
diff --git a/memory.c b/memory.c
index 01846c9768..1494e955d4 100644
--- a/memory.c
+++ b/memory.c
@@ -339,28 +339,65 @@ static void flatview_simplify(FlatView *view)
     }
 }
 
-static void memory_region_oldmmio_read_accessor(void *opaque,
+static bool memory_region_big_endian(MemoryRegion *mr)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+    return mr->ops->endianness != DEVICE_LITTLE_ENDIAN;
+#else
+    return mr->ops->endianness == DEVICE_BIG_ENDIAN;
+#endif
+}
+
+static bool memory_region_wrong_endianness(MemoryRegion *mr)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+    return mr->ops->endianness == DEVICE_LITTLE_ENDIAN;
+#else
+    return mr->ops->endianness == DEVICE_BIG_ENDIAN;
+#endif
+}
+
+static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size)
+{
+    if (memory_region_wrong_endianness(mr)) {
+        switch (size) {
+        case 1:
+            break;
+        case 2:
+            *data = bswap16(*data);
+            break;
+        case 4:
+            *data = bswap32(*data);
+            break;
+        case 8:
+            *data = bswap64(*data);
+            break;
+        default:
+            abort();
+        }
+    }
+}
+
+static void memory_region_oldmmio_read_accessor(MemoryRegion *mr,
                                                 hwaddr addr,
                                                 uint64_t *value,
                                                 unsigned size,
                                                 unsigned shift,
                                                 uint64_t mask)
 {
-    MemoryRegion *mr = opaque;
     uint64_t tmp;
 
     tmp = mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr);
     *value |= (tmp & mask) << shift;
 }
 
-static void memory_region_read_accessor(void *opaque,
+static void memory_region_read_accessor(MemoryRegion *mr,
                                         hwaddr addr,
                                         uint64_t *value,
                                         unsigned size,
                                         unsigned shift,
                                         uint64_t mask)
 {
-    MemoryRegion *mr = opaque;
     uint64_t tmp;
 
     if (mr->flush_coalesced_mmio) {
@@ -370,28 +407,26 @@ static void memory_region_read_accessor(void *opaque,
     *value |= (tmp & mask) << shift;
 }
 
-static void memory_region_oldmmio_write_accessor(void *opaque,
+static void memory_region_oldmmio_write_accessor(MemoryRegion *mr,
                                                  hwaddr addr,
                                                  uint64_t *value,
                                                  unsigned size,
                                                  unsigned shift,
                                                  uint64_t mask)
 {
-    MemoryRegion *mr = opaque;
     uint64_t tmp;
 
     tmp = (*value >> shift) & mask;
     mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, tmp);
 }
 
-static void memory_region_write_accessor(void *opaque,
+static void memory_region_write_accessor(MemoryRegion *mr,
                                          hwaddr addr,
                                          uint64_t *value,
                                          unsigned size,
                                          unsigned shift,
                                          uint64_t mask)
 {
-    MemoryRegion *mr = opaque;
     uint64_t tmp;
 
     if (mr->flush_coalesced_mmio) {
@@ -406,13 +441,13 @@ static void access_with_adjusted_size(hwaddr addr,
                                       unsigned size,
                                       unsigned access_size_min,
                                       unsigned access_size_max,
-                                      void (*access)(void *opaque,
+                                      void (*access)(MemoryRegion *mr,
                                                      hwaddr addr,
                                                      uint64_t *value,
                                                      unsigned size,
                                                      unsigned shift,
                                                      uint64_t mask),
-                                      void *opaque)
+                                      MemoryRegion *mr)
 {
     uint64_t access_mask;
     unsigned access_size;
@@ -428,13 +463,15 @@ static void access_with_adjusted_size(hwaddr addr,
     /* FIXME: support unaligned access? */
     access_size = MAX(MIN(size, access_size_max), access_size_min);
     access_mask = -1ULL >> (64 - access_size * 8);
-    for (i = 0; i < size; i += access_size) {
-#ifdef TARGET_WORDS_BIGENDIAN
-        access(opaque, addr + i, value, access_size,
-               (size - access_size - i) * 8, access_mask);
-#else
-        access(opaque, addr + i, value, access_size, i * 8, access_mask);
-#endif
+    if (memory_region_big_endian(mr)) {
+        for (i = 0; i < size; i += access_size) {
+            access(mr, addr + i, value, access_size,
+                   (size - access_size - i) * 8, access_mask);
+        }
+    } else {
+        for (i = 0; i < size; i += access_size) {
+            access(mr, addr + i, value, access_size, i * 8, access_mask);
+        }
     }
 }
 
@@ -786,15 +823,6 @@ static void memory_region_destructor_rom_device(MemoryRegion *mr)
     qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK);
 }
 
-static bool memory_region_wrong_endianness(MemoryRegion *mr)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
-    return mr->ops->endianness == DEVICE_LITTLE_ENDIAN;
-#else
-    return mr->ops->endianness == DEVICE_BIG_ENDIAN;
-#endif
-}
-
 void memory_region_init(MemoryRegion *mr,
                         Object *owner,
                         const char *name,
@@ -921,27 +949,6 @@ static uint64_t memory_region_dispatch_read1(MemoryRegion *mr,
     return data;
 }
 
-static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size)
-{
-    if (memory_region_wrong_endianness(mr)) {
-        switch (size) {
-        case 1:
-            break;
-        case 2:
-            *data = bswap16(*data);
-            break;
-        case 4:
-            *data = bswap32(*data);
-            break;
-        case 8:
-            *data = bswap64(*data);
-            break;
-        default:
-            abort();
-        }
-    }
-}
-
 static bool memory_region_dispatch_read(MemoryRegion *mr,
                                         hwaddr addr,
                                         uint64_t *pval,
diff --git a/po/Makefile b/po/Makefile
index 60ccd7d3bb..705166e2d3 100644
--- a/po/Makefile
+++ b/po/Makefile
@@ -1,20 +1,23 @@
 # This makefile is very special as it's meant to build as part of the build
 # process and also within the source tree to update the translation files.
 
-VERSION=$(shell cat ../VERSION)
-SRCS=$(filter-out messages.po,$(wildcard *.po))
-OBJS=$(patsubst %.po,%.mo,$(SRCS))
-
+# Set SRC_PATH for in-tree builds without configuration.
 SRC_PATH=..
 
 -include ../config-host.mak
+include $(SRC_PATH)/rules.mak
+
+PO_PATH=$(SRC_PATH)/po
+
+VERSION=$(shell cat $(SRC_PATH)/VERSION)
+SRCS=$(filter-out $(PO_PATH)/messages.po,$(wildcard $(PO_PATH)/*.po))
+OBJS=$(patsubst $(PO_PATH)/%.po,%.mo,$(SRCS))
 
-vpath %.po $(SRC_PATH)/po
+vpath %.po $(PO_PATH)
 
 all:
-	@echo Use 'make update' to update translation files
-	@echo or us 'make build' or 'make install' to build and install
-	@echo the translation files
+	@echo "Use 'make update' to update translation files or use 'make build'"
+	@echo "or 'make install' to build and install the translation files."
 
 update: $(SRCS)
 
@@ -31,12 +34,16 @@ install: $(OBJS)
 	done
 
 %.mo: %.po
-	@msgfmt -o $@ $(SRC_PATH)/po/`basename $@ .mo`.po
+	$(call quiet-command, msgfmt -o $@ $<, "  GEN   $@")
 
-messages.po: $(SRC_PATH)/ui/gtk.c
-	@xgettext -o $@ --foreign-user --package-name=QEMU --package-version=$(VERSION) --msgid-bugs-address=qemu-devel@nongnu.org -k_ -C $<
+$(PO_PATH)/messages.po: $(SRC_PATH)/ui/gtk.c
+	$(call quiet-command, cd $(SRC_PATH) && \
+	 (xgettext -o - --from-code=UTF-8 --foreign-user \
+	    --package-name=QEMU --package-version=$(VERSION) \
+	    --msgid-bugs-address=qemu-devel@nongnu.org -k_ -C ui/gtk.c | \
+	  sed -e s/CHARSET/UTF-8/) >$@, "  GEN   $@")
 
-%.po: messages.po
-	@msgmerge $@ $< > $@.bak && mv $@.bak $@
+$(PO_PATH)/%.po: $(PO_PATH)/messages.po
+	$(call quiet-command, msgmerge -q $@ $< > $@.bak && mv $@.bak $@, "  GEN   $@")
 
 .PHONY: clean all
diff --git a/tests/Makefile b/tests/Makefile
index 6c34eec1d2..cdbb79e111 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -53,7 +53,8 @@ check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 
 # All QTests for now are POSIX-only, but the dependencies are
 # really in libqtest, not in the testcases themselves.
-check-qtest-i386-y = tests/fdc-test$(EXESUF)
+check-qtest-i386-y = tests/endianness-test$(EXESUF)
+check-qtest-i386-y += tests/fdc-test$(EXESUF)
 gcov-files-i386-y = hw/fdc.c
 check-qtest-i386-y += tests/ide-test$(EXESUF)
 check-qtest-i386-y += tests/hd-geo-test$(EXESUF)
@@ -65,8 +66,16 @@ check-qtest-i386-y += tests/fw_cfg-test$(EXESUF)
 check-qtest-x86_64-y = $(check-qtest-i386-y)
 gcov-files-i386-y += i386-softmmu/hw/mc146818rtc.c
 gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
+check-qtest-mips-y = tests/endianness-test$(EXESUF)
+check-qtest-mips64-y = tests/endianness-test$(EXESUF)
+check-qtest-mips64el-y = tests/endianness-test$(EXESUF)
+check-qtest-ppc-y = tests/endianness-test$(EXESUF)
+check-qtest-ppc64-y = tests/endianness-test$(EXESUF)
+check-qtest-sh4-y = tests/endianness-test$(EXESUF)
+check-qtest-sh4eb-y = tests/endianness-test$(EXESUF)
+check-qtest-sparc64-y = tests/endianness-test$(EXESUF)
 #check-qtest-sparc-y = tests/m48t59-test$(EXESUF)
-#check-qtest-sparc64-y = tests/m48t59-test$(EXESUF)
+#check-qtest-sparc64-y += tests/m48t59-test$(EXESUF)
 gcov-files-sparc-y += hw/m48t59.c
 gcov-files-sparc64-y += hw/m48t59.c
 check-qtest-arm-y = tests/tmp105-test$(EXESUF)
@@ -136,6 +145,7 @@ libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o
 
 tests/rtc-test$(EXESUF): tests/rtc-test.o
 tests/m48t59-test$(EXESUF): tests/m48t59-test.o
+tests/endianness-test$(EXESUF): tests/endianness-test.o
 tests/fdc-test$(EXESUF): tests/fdc-test.o
 tests/ide-test$(EXESUF): tests/ide-test.o $(libqos-pc-obj-y)
 tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
diff --git a/tests/endianness-test.c b/tests/endianness-test.c
new file mode 100644
index 0000000000..feb32a8503
--- /dev/null
+++ b/tests/endianness-test.c
@@ -0,0 +1,316 @@
+/*
+ * QTest testcase for ISA endianness
+ *
+ * Copyright Red Hat, Inc. 2012
+ *
+ * Authors:
+ *  Paolo Bonzini <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+#include "libqtest.h"
+
+#include <glib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "qemu/bswap.h"
+
+typedef struct TestCase TestCase;
+struct TestCase {
+    const char *arch;
+    const char *machine;
+    uint64_t isa_base;
+    bool bswap;
+    const char *superio;
+};
+
+static const TestCase test_cases[] = {
+    { "i386", "pc", -1 },
+    { "mips", "magnum", 0x90000000, .bswap = true },
+    { "mips", "pica61", 0x90000000, .bswap = true },
+    { "mips", "mips", 0x14000000, .bswap = true },
+    { "mips", "malta", 0x10000000, .bswap = true },
+    { "mips64", "magnum", 0x90000000, .bswap = true },
+    { "mips64", "pica61", 0x90000000, .bswap = true },
+    { "mips64", "mips", 0x14000000, .bswap = true },
+    { "mips64", "malta", 0x10000000, .bswap = true },
+    { "mips64el", "fulong2e", 0x1fd00000 },
+    { "ppc", "g3beige", 0xfe000000, .bswap = true, .superio = "i82378" },
+    { "ppc", "prep", 0x80000000, .bswap = true },
+    { "ppc", "bamboo", 0xe8000000, .bswap = true, .superio = "i82378" },
+    { "ppc64", "mac99", 0xf2000000, .bswap = true, .superio = "i82378" },
+    { "ppc64", "pseries", 0x10080000000, .bswap = true, .superio = "i82378" },
+    { "sh4", "r2d", 0xfe240000, .superio = "i82378" },
+    { "sh4eb", "r2d", 0xfe240000, .bswap = true, .superio = "i82378" },
+    { "sparc64", "sun4u", 0x1fe02000000LL, .bswap = true },
+    { "x86_64", "pc", -1 },
+    {}
+};
+
+static uint8_t isa_inb(const TestCase *test, uint16_t addr)
+{
+    uint8_t value;
+    if (test->isa_base == -1) {
+        value = inb(addr);
+    } else {
+        value = readb(test->isa_base + addr);
+    }
+    return value;
+}
+
+static uint16_t isa_inw(const TestCase *test, uint16_t addr)
+{
+    uint16_t value;
+    if (test->isa_base == -1) {
+        value = inw(addr);
+    } else {
+        value = readw(test->isa_base + addr);
+    }
+    return test->bswap ? bswap16(value) : value;
+}
+
+static uint32_t isa_inl(const TestCase *test, uint16_t addr)
+{
+    uint32_t value;
+    if (test->isa_base == -1) {
+        value = inl(addr);
+    } else {
+        value = readl(test->isa_base + addr);
+    }
+    return test->bswap ? bswap32(value) : value;
+}
+
+static void isa_outb(const TestCase *test, uint16_t addr, uint8_t value)
+{
+    if (test->isa_base == -1) {
+        outb(addr, value);
+    } else {
+        writeb(test->isa_base + addr, value);
+    }
+}
+
+static void isa_outw(const TestCase *test, uint16_t addr, uint16_t value)
+{
+    value = test->bswap ? bswap16(value) : value;
+    if (test->isa_base == -1) {
+        outw(addr, value);
+    } else {
+        writew(test->isa_base + addr, value);
+    }
+}
+
+static void isa_outl(const TestCase *test, uint16_t addr, uint32_t value)
+{
+    value = test->bswap ? bswap32(value) : value;
+    if (test->isa_base == -1) {
+        outl(addr, value);
+    } else {
+        writel(test->isa_base + addr, value);
+    }
+}
+
+
+static void test_endianness(gconstpointer data)
+{
+    const TestCase *test = data;
+    char *args;
+
+    args = g_strdup_printf("-display none -M %s%s%s -device pc-testdev",
+                           test->machine,
+                           test->superio ? " -device " : "",
+                           test->superio ?: "");
+    qtest_start(args);
+    isa_outl(test, 0xe0, 0x87654321);
+    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654321);
+    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
+    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
+    g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87);
+    g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x65);
+    g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x43);
+    g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x21);
+
+    isa_outw(test, 0xe2, 0x8866);
+    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x88664321);
+    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8866);
+    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
+    g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x88);
+    g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x66);
+    g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x43);
+    g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x21);
+
+    isa_outw(test, 0xe0, 0x4422);
+    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x88664422);
+    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8866);
+    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4422);
+    g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x88);
+    g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x66);
+    g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x44);
+    g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x22);
+
+    isa_outb(test, 0xe3, 0x87);
+    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87664422);
+    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8766);
+    g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87);
+    g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x66);
+    g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x44);
+    g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x22);
+
+    isa_outb(test, 0xe2, 0x65);
+    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654422);
+    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
+    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4422);
+    g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87);
+    g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x65);
+    g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x44);
+    g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x22);
+
+    isa_outb(test, 0xe1, 0x43);
+    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654322);
+    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
+    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4322);
+    g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87);
+    g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x65);
+    g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x43);
+    g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x22);
+
+    isa_outb(test, 0xe0, 0x21);
+    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654321);
+    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
+    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
+    g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87);
+    g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x65);
+    g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x43);
+    g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x21);
+    qtest_quit(global_qtest);
+    g_free(args);
+}
+
+static void test_endianness_split(gconstpointer data)
+{
+    const TestCase *test = data;
+    char *args;
+
+    args = g_strdup_printf("-display none -M %s%s%s -device pc-testdev",
+                           test->machine,
+                           test->superio ? " -device " : "",
+                           test->superio ?: "");
+    qtest_start(args);
+    isa_outl(test, 0xe8, 0x87654321);
+    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654321);
+    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
+    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
+
+    isa_outw(test, 0xea, 0x8866);
+    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x88664321);
+    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8866);
+    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
+
+    isa_outw(test, 0xe8, 0x4422);
+    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x88664422);
+    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8866);
+    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4422);
+
+    isa_outb(test, 0xeb, 0x87);
+    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87664422);
+    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8766);
+
+    isa_outb(test, 0xea, 0x65);
+    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654422);
+    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
+    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4422);
+
+    isa_outb(test, 0xe9, 0x43);
+    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654322);
+    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
+    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4322);
+
+    isa_outb(test, 0xe8, 0x21);
+    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654321);
+    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
+    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
+    qtest_quit(global_qtest);
+    g_free(args);
+}
+
+static void test_endianness_combine(gconstpointer data)
+{
+    const TestCase *test = data;
+    char *args;
+
+    args = g_strdup_printf("-display none -M %s%s%s -device pc-testdev",
+                           test->machine,
+                           test->superio ? " -device " : "",
+                           test->superio ?: "");
+    qtest_start(args);
+    isa_outl(test, 0xe0, 0x87654321);
+    g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87654321);
+    g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8765);
+    g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4321);
+
+    isa_outw(test, 0xe2, 0x8866);
+    g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x88664321);
+    g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8866);
+    g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4321);
+
+    isa_outw(test, 0xe0, 0x4422);
+    g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x88664422);
+    g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8866);
+    g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4422);
+
+    isa_outb(test, 0xe3, 0x87);
+    g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87664422);
+    g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8766);
+
+    isa_outb(test, 0xe2, 0x65);
+    g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87654422);
+    g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8765);
+    g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4422);
+
+    isa_outb(test, 0xe1, 0x43);
+    g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87654322);
+    g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8765);
+    g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4322);
+
+    isa_outb(test, 0xe0, 0x21);
+    g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87654321);
+    g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8765);
+    g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4321);
+    qtest_quit(global_qtest);
+    g_free(args);
+}
+
+int main(int argc, char **argv)
+{
+    const char *arch = qtest_get_arch();
+    int ret;
+    int i;
+
+    g_test_init(&argc, &argv, NULL);
+
+    for (i = 0; test_cases[i].arch; i++) {
+        gchar *path;
+        if (strcmp(test_cases[i].arch, arch) != 0) {
+            continue;
+        }
+        path = g_strdup_printf("/%s/endianness/%s",
+                               arch, test_cases[i].machine);
+        g_test_add_data_func(path, &test_cases[i], test_endianness);
+
+        path = g_strdup_printf("/%s/endianness/split/%s",
+                               arch, test_cases[i].machine);
+        g_test_add_data_func(path, &test_cases[i], test_endianness_split);
+
+        path = g_strdup_printf("/%s/endianness/combine/%s",
+                               arch, test_cases[i].machine);
+        g_test_add_data_func(path, &test_cases[i], test_endianness_combine);
+    }
+
+    ret = g_test_run();
+
+    return ret;
+}
diff --git a/translate-all.c b/translate-all.c
index e8683d2c66..3b5fc7c901 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1148,7 +1148,8 @@ void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len)
 
 #if !defined(CONFIG_SOFTMMU)
 static void tb_invalidate_phys_page(tb_page_addr_t addr,
-                                    uintptr_t pc, void *puc)
+                                    uintptr_t pc, void *puc,
+                                    bool locked)
 {
     TranslationBlock *tb;
     PageDesc *p;
@@ -1206,6 +1207,9 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr,
            itself */
         cpu->current_tb = NULL;
         tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
+        if (locked) {
+            mmap_unlock();
+        }
         cpu_resume_from_signal(env, puc);
     }
 #endif
@@ -1723,7 +1727,7 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
         if (!(p->flags & PAGE_WRITE) &&
             (flags & PAGE_WRITE) &&
             p->first_tb) {
-            tb_invalidate_phys_page(addr, 0, NULL);
+            tb_invalidate_phys_page(addr, 0, NULL, false);
         }
         p->flags = flags;
     }
@@ -1818,7 +1822,7 @@ int page_unprotect(target_ulong address, uintptr_t pc, void *puc)
 
             /* and since the content will be modified, we must invalidate
                the corresponding translated code. */
-            tb_invalidate_phys_page(addr, pc, puc);
+            tb_invalidate_phys_page(addr, pc, puc, true);
 #ifdef DEBUG_TB_CHECK
             tb_invalidate_check(addr);
 #endif
diff --git a/user-exec.c b/user-exec.c
index d45ca8e877..82bfa66ce3 100644
--- a/user-exec.c
+++ b/user-exec.c
@@ -95,6 +95,10 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
         return 1;
     }
 
+    /* Convert forcefully to guest address space, invalid addresses
+       are still valid segv ones */
+    address = h2g_nocheck(address);
+
     env = current_cpu->env_ptr;
     /* see if it is an MMU fault */
     ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX);