Merge remote-tracking branch 'riku/linux-user-for-upstream' into staging

# By Andreas Schwab (2) and others
# Via Riku Voipio
* riku/linux-user-for-upstream:
  linux-user: Do not ignore mmap failure from host
  linux-user: improve target_to_host_sock_type conversion
  user-exec.c: Set is_write correctly in the ARM cpu_signal_handler()
  linux-user: Fix sys_utimensat (would not compile on old glibc)
  linux-user: fix signal number range check
  linux-user: add SIOCADDRT/SIOCDELRT support
  linux-user: handle /proc/$$ like /proc/self

Message-id: cover.1373051589.git.riku.voipio@linaro.org
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
diff --git a/MAINTAINERS b/MAINTAINERS
index ad9c860..93ad19d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -104,6 +104,12 @@
 S: Maintained
 F: target-moxie/
 
+OpenRISC
+M: Jia Liu <proljc@gmail.com>
+S: Maintained
+F: target-openrisc/
+F: hw/openrisc/
+
 PowerPC
 M: Alexander Graf <agraf@suse.de>
 L: qemu-ppc@nongnu.org
@@ -155,7 +161,7 @@
 
 Overall
 M: Gleb Natapov <gleb@redhat.com>
-M: Marcelo Tosatti <mtosatti@redhat.com>
+M: Paolo Bonzini <pbonzini@redhat.com>
 L: kvm@vger.kernel.org
 S: Supported
 F: kvm-*
@@ -303,11 +309,7 @@
 M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
 S: Maintained
 F: hw/cris/axis_dev88.c
-
-etraxfs
-M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
-S: Maintained
-F: hw/cris/etraxfs.c
+F: hw/*/etraxfs_*.c
 
 LM32 Machines
 -------------
@@ -343,7 +345,7 @@
 petalogix_s3adsp1800
 M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
 S: Maintained
-F: hw/microblaze/petalogix_s3adsp1800.c
+F: hw/microblaze/petalogix_s3adsp1800_mmu.c
 
 petalogix_ml605
 M: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
@@ -372,6 +374,13 @@
 S: Maintained
 F: hw/mips/mips_r4k.c
 
+OpenRISC Machines
+-----------------
+or1k-sim
+M: Jia Liu <proljc@gmail.com>
+S: Maintained
+F: hw/openrisc/openrisc_sim.c
+
 PowerPC Machines
 ----------------
 405
@@ -407,8 +416,8 @@
 L: qemu-ppc@nongnu.org
 S: Maintained
 F: hw/ppc/mac_newworld.c
-F: hw/pci/devices/host-uninorth.c
-F: hw/pci/devices/host-dec.[hc]
+F: hw/pci-host/uninorth.c
+F: hw/pci-bridge/dec.[hc]
 F: hw/misc/macio/
 
 Old World
@@ -416,7 +425,7 @@
 L: qemu-ppc@nongnu.org
 S: Maintained
 F: hw/ppc/mac_oldworld.c
-F: hw/pci/devices/host-grackle.c
+F: hw/pci-host/grackle.c
 F: hw/misc/macio/
 
 PReP
@@ -424,7 +433,7 @@
 L: qemu-ppc@nongnu.org
 S: Odd Fixes
 F: hw/ppc/prep.c
-F: hw/pci/devices/host-prep.[hc]
+F: hw/pci-host/prep.[hc]
 F: hw/isa/pc87312.[hc]
 
 sPAPR
@@ -441,19 +450,19 @@
 M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
 L: qemu-ppc@nongnu.org
 S: Odd Fixes
-F: hw/pci/virtex_ml507.c
+F: hw/ppc/virtex_ml507.c
 
 SH4 Machines
 ------------
 R2D
 M: Magnus Damm <magnus.damm@gmail.com>
 S: Maintained
-F: hw/sh/r2d.c
+F: hw/sh4/r2d.c
 
 Shix
 M: Magnus Damm <magnus.damm@gmail.com>
 S: Orphan
-F: hw/sh/shix.c
+F: hw/sh4/shix.c
 
 SPARC Machines
 --------------
@@ -478,7 +487,7 @@
 S390 Virtio
 M: Alexander Graf <agraf@suse.de>
 S: Maintained
-F: hw/s390/s390-*.c
+F: hw/s390x/s390-*.c
 
 S390 Virtio-ccw
 M: Cornelia Huck <cornelia.huck@de.ibm.com>
@@ -547,7 +556,7 @@
 M: Scott Wood <scottwood@freescale.com>
 L: qemu-ppc@nongnu.org
 S: Supported
-F: hw/ppc/e500_*
+F: hw/ppc/e500*
 
 SCSI
 M: Paolo Bonzini <pbonzini@redhat.com>
@@ -575,7 +584,7 @@
 VFIO
 M: Alex Williamson <alex.williamson@redhat.com>
 S: Supported
-F: hw/pci/vfio.c
+F: hw/misc/vfio.c
 
 vhost
 M: Michael S. Tsirkin <mst@redhat.com>
@@ -649,7 +658,7 @@
 M: Andreas Färber <afaerber@suse.de>
 S: Supported
 F: qom/cpu.c
-F: include/qemu/cpu.h
+F: include/qom/cpu.h
 F: target-i386/cpu.c
 
 ICC Bus
@@ -662,7 +671,7 @@
 M: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
 M: Alexander Graf <agraf@suse.de>
 S: Maintained
-F: device-tree.[ch]
+F: device_tree.[ch]
 
 GDB stub
 M: qemu-devel@nongnu.org
@@ -673,7 +682,7 @@
 SPICE
 M: Gerd Hoffmann <kraxel@redhat.com>
 S: Supported
-F: ui/qemu-spice.h
+F: include/ui/qemu-spice.h
 F: ui/spice-*.c
 F: audio/spiceaudio.c
 F: hw/display/qxl*
@@ -772,6 +781,7 @@
 -------------------------
 Common code
 M: qemu-devel@nongnu.org
+M: Richard Henderson <rth@twiddle.net>
 S: Maintained
 F: tcg/
 
diff --git a/block.c b/block.c
index 6c493ad..183fec8 100644
--- a/block.c
+++ b/block.c
@@ -1358,11 +1358,12 @@
 
 void bdrv_close(BlockDriverState *bs)
 {
-    bdrv_flush(bs);
     if (bs->job) {
         block_job_cancel_sync(bs->job);
     }
-    bdrv_drain_all();
+    bdrv_drain_all(); /* complete I/O */
+    bdrv_flush(bs);
+    bdrv_drain_all(); /* in case flush left pending I/O */
     notifier_list_notify(&bs->close_notifiers, bs);
 
     if (bs->drv) {
diff --git a/block/curl.c b/block/curl.c
index 6af8cb7..82d39ff 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -81,6 +81,7 @@
     CURLState states[CURL_NUM_STATES];
     char *url;
     size_t readahead_size;
+    bool accept_range;
 } BDRVCURLState;
 
 static void curl_clean_state(CURLState *s);
@@ -110,14 +111,15 @@
     return 0;
 }
 
-static size_t curl_size_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
+static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
 {
-    CURLState *s = ((CURLState*)opaque);
+    BDRVCURLState *s = opaque;
     size_t realsize = size * nmemb;
-    size_t fsize;
+    const char *accept_line = "Accept-Ranges: bytes";
 
-    if(sscanf(ptr, "Content-Length: %zd", &fsize) == 1) {
-        s->s->len = fsize;
+    if (realsize >= strlen(accept_line)
+        && strncmp((char *)ptr, accept_line, strlen(accept_line)) == 0) {
+        s->accept_range = true;
     }
 
     return realsize;
@@ -447,8 +449,11 @@
 
     // Get file size
 
+    s->accept_range = false;
     curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1);
-    curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, (void *)curl_size_cb);
+    curl_easy_setopt(state->curl, CURLOPT_HEADERFUNCTION,
+                     curl_header_cb);
+    curl_easy_setopt(state->curl, CURLOPT_HEADERDATA, s);
     if (curl_easy_perform(state->curl))
         goto out;
     curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d);
@@ -456,6 +461,13 @@
         s->len = (size_t)d;
     else if(!s->len)
         goto out;
+    if ((!strncasecmp(s->url, "http://", strlen("http://"))
+        || !strncasecmp(s->url, "https://", strlen("https://")))
+        && !s->accept_range) {
+        pstrcpy(state->errmsg, CURL_ERROR_SIZE,
+                "Server does not support 'range' (byte ranges).");
+        goto out;
+    }
     DPRINTF("CURL: Size = %zd\n", s->len);
 
     curl_clean_state(state);
diff --git a/block/vmdk.c b/block/vmdk.c
index a28fb5e..3756333 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1724,6 +1724,23 @@
     return ret;
 }
 
+static int vmdk_has_zero_init(BlockDriverState *bs)
+{
+    int i;
+    BDRVVmdkState *s = bs->opaque;
+
+    /* If has a flat extent and its underlying storage doesn't have zero init,
+     * return 0. */
+    for (i = 0; i < s->num_extents; i++) {
+        if (s->extents[i].flat) {
+            if (!bdrv_has_zero_init(s->extents[i].file)) {
+                return 0;
+            }
+        }
+    }
+    return 1;
+}
+
 static QEMUOptionParameter vmdk_create_options[] = {
     {
         .name = BLOCK_OPT_SIZE,
@@ -1762,21 +1779,22 @@
 };
 
 static BlockDriver bdrv_vmdk = {
-    .format_name    = "vmdk",
-    .instance_size  = sizeof(BDRVVmdkState),
-    .bdrv_probe     = vmdk_probe,
-    .bdrv_open      = vmdk_open,
-    .bdrv_reopen_prepare = vmdk_reopen_prepare,
-    .bdrv_read      = vmdk_co_read,
-    .bdrv_write     = vmdk_co_write,
-    .bdrv_co_write_zeroes = vmdk_co_write_zeroes,
-    .bdrv_close     = vmdk_close,
-    .bdrv_create    = vmdk_create,
-    .bdrv_co_flush_to_disk  = vmdk_co_flush,
-    .bdrv_co_is_allocated   = vmdk_co_is_allocated,
-    .bdrv_get_allocated_file_size  = vmdk_get_allocated_file_size,
+    .format_name                  = "vmdk",
+    .instance_size                = sizeof(BDRVVmdkState),
+    .bdrv_probe                   = vmdk_probe,
+    .bdrv_open                    = vmdk_open,
+    .bdrv_reopen_prepare          = vmdk_reopen_prepare,
+    .bdrv_read                    = vmdk_co_read,
+    .bdrv_write                   = vmdk_co_write,
+    .bdrv_co_write_zeroes         = vmdk_co_write_zeroes,
+    .bdrv_close                   = vmdk_close,
+    .bdrv_create                  = vmdk_create,
+    .bdrv_co_flush_to_disk        = vmdk_co_flush,
+    .bdrv_co_is_allocated         = vmdk_co_is_allocated,
+    .bdrv_get_allocated_file_size = vmdk_get_allocated_file_size,
+    .bdrv_has_zero_init           = vmdk_has_zero_init,
 
-    .create_options = vmdk_create_options,
+    .create_options               = vmdk_create_options,
 };
 
 static void bdrv_vmdk_init(void)
diff --git a/configure b/configure
index 0e0adde..cb0f870 100755
--- a/configure
+++ b/configure
@@ -3445,6 +3445,36 @@
   roms="$roms s390-ccw"
 fi
 
+# Probe for the need for relocating the user-only binary.
+if test "$pie" = "no" ; then
+  textseg_addr=
+  case "$cpu" in
+    arm | hppa | i386 | m68k | ppc | ppc64 | s390* | sparc | sparc64 | x86_64)
+      textseg_addr=0x60000000
+      ;;
+    mips)
+      textseg_addr=0x400000
+      ;;
+  esac
+  if [ -n "$textseg_addr" ]; then
+    cat > $TMPC <<EOF
+    int main(void) { return 0; }
+EOF
+    textseg_ldflags="-Wl,-Ttext-segment=$textseg_addr"
+    if ! compile_prog "" "$textseg_ldflags"; then
+      # In case ld does not support -Ttext-segment, edit the default linker
+      # script via sed to set the .text start addr.  This is needed on FreeBSD
+      # at least.
+      $ld --verbose | sed \
+        -e '1,/==================================================/d' \
+        -e '/==================================================/,$d' \
+        -e "s/[.] = [0-9a-fx]* [+] SIZEOF_HEADERS/. = $textseg_addr + SIZEOF_HEADERS/" \
+        -e "s/__executable_start = [0-9a-fx]*/__executable_start = $textseg_addr/" > config-host.ld
+      textseg_ldflags="-Wl,-T../config-host.ld"
+    fi
+  fi
+fi
+
 # add pixman flags after all config tests are done
 QEMU_CFLAGS="$QEMU_CFLAGS $pixman_cflags $fdt_cflags"
 libs_softmmu="$libs_softmmu $pixman_libs"
@@ -4073,9 +4103,6 @@
   echo "GCOV=$gcov_tool" >> $config_host_mak
 fi
 
-# generate list of library paths for linker script
-$ld --verbose -v 2> /dev/null | grep SEARCH_DIR > config-host.ld
-
 # use included Linux headers
 if test "$linux" = "yes" ; then
   mkdir -p linux-headers
@@ -4438,21 +4465,8 @@
   fi
 fi
 
-if test "$ARCH" = "tci"; then
-  linker_script=""
-else
-  linker_script="-Wl,-T../config-host.ld -Wl,-T,\$(SRC_PATH)/ldscripts/\$(ARCH).ld"
-fi
-
 if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then
-  case "$ARCH" in
-  alpha | s390x | aarch64)
-    # The default placement of the application is fine.
-    ;;
-  *)
-    ldflags="$linker_script $ldflags"
-    ;;
-  esac
+  ldflags="$ldflags $textseg_ldflags"
 fi
 
 echo "LDFLAGS+=$ldflags" >> $config_target_mak
diff --git a/cputlb.c b/cputlb.c
index 80b2a94..828007c 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -158,6 +158,17 @@
     }
 }
 
+static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
+{
+    ram_addr_t ram_addr;
+
+    if (qemu_ram_addr_from_host(ptr, &ram_addr) == NULL) {
+        fprintf(stderr, "Bad ram pointer %p\n", ptr);
+        abort();
+    }
+    return ram_addr;
+}
+
 static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
 {
     ram_addr_t ram_addr;
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 03deca2..4a0fc9c 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -28,11 +28,10 @@
 CONFIG_I8259=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_TPM_TIS=$(CONFIG_TPM)
-CONFIG_PCI_HOTPLUG=y
+CONFIG_PCI_HOTPLUG_OLD=y
 CONFIG_MC146818RTC=y
 CONFIG_PAM=y
 CONFIG_PCI_PIIX=y
-CONFIG_PCI_HOTPLUG=y
 CONFIG_WDT_IB700=y
 CONFIG_PC_SYSFW=y
 CONFIG_XEN_I386=$(CONFIG_XEN)
diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index cb279cb..5a72b5f 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -45,7 +45,5 @@
 CONFIG_PSERIES=y
 CONFIG_E500=y
 CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
-# For pSeries
-CONFIG_PCI_HOTPLUG=y
 # For PReP
 CONFIG_MC146818RTC=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 599b630..10bb0c6 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -28,11 +28,10 @@
 CONFIG_I8259=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_TPM_TIS=$(CONFIG_TPM)
-CONFIG_PCI_HOTPLUG=y
+CONFIG_PCI_HOTPLUG_OLD=y
 CONFIG_MC146818RTC=y
 CONFIG_PAM=y
 CONFIG_PCI_PIIX=y
-CONFIG_PCI_HOTPLUG=y
 CONFIG_WDT_IB700=y
 CONFIG_PC_SYSFW=y
 CONFIG_XEN_I386=$(CONFIG_XEN)
diff --git a/device_tree.c b/device_tree.c
index 69be9da..10cf3d0 100644
--- a/device_tree.c
+++ b/device_tree.c
@@ -21,6 +21,7 @@
 #include "config.h"
 #include "qemu-common.h"
 #include "sysemu/device_tree.h"
+#include "sysemu/sysemu.h"
 #include "hw/loader.h"
 #include "qemu/option.h"
 #include "qemu/config-file.h"
@@ -239,15 +240,8 @@
      * which phandle id to start allocting phandles.
      */
     if (!phandle) {
-        QemuOpts *machine_opts;
-        machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-        if (machine_opts) {
-            const char *phandle_start;
-            phandle_start = qemu_opt_get(machine_opts, "phandle_start");
-            if (phandle_start) {
-                phandle = strtoul(phandle_start, NULL, 0);
-            }
-        }
+        phandle = qemu_opt_get_number(qemu_get_machine_opts(),
+                                      "phandle_start", 0);
     }
 
     if (!phandle) {
@@ -307,15 +301,10 @@
 
 void qemu_devtree_dumpdtb(void *fdt, int size)
 {
-    QemuOpts *machine_opts;
+    const char *dumpdtb = qemu_opt_get(qemu_get_machine_opts(), "dumpdtb");
 
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        const char *dumpdtb = qemu_opt_get(machine_opts, "dumpdtb");
-        if (dumpdtb) {
-            /* Dump the dtb to a file and quit */
-            exit(g_file_set_contents(dumpdtb, fdt, size, NULL) ? 0 : 1);
-        }
+    if (dumpdtb) {
+        /* Dump the dtb to a file and quit */
+        exit(g_file_set_contents(dumpdtb, fdt, size, NULL) ? 0 : 1);
     }
-
 }
diff --git a/dma-helpers.c b/dma-helpers.c
index 5afba47..499550f 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -34,13 +34,16 @@
     return error;
 }
 
-void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint, AddressSpace *as)
+void qemu_sglist_init(QEMUSGList *qsg, DeviceState *dev, int alloc_hint,
+                      AddressSpace *as)
 {
     qsg->sg = g_malloc(alloc_hint * sizeof(ScatterGatherEntry));
     qsg->nsg = 0;
     qsg->nalloc = alloc_hint;
     qsg->size = 0;
     qsg->as = as;
+    qsg->dev = dev;
+    object_ref(OBJECT(dev));
 }
 
 void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len)
@@ -57,6 +60,7 @@
 
 void qemu_sglist_destroy(QEMUSGList *qsg)
 {
+    object_unref(OBJECT(qsg->dev));
     g_free(qsg->sg);
     memset(qsg, 0, sizeof(*qsg));
 }
diff --git a/docs/atomics.txt b/docs/atomics.txt
new file mode 100644
index 0000000..6f2997b
--- /dev/null
+++ b/docs/atomics.txt
@@ -0,0 +1,352 @@
+CPUs perform independent memory operations effectively in random order.
+but this can be a problem for CPU-CPU interaction (including interactions
+between QEMU and the guest).  Multi-threaded programs use various tools
+to instruct the compiler and the CPU to restrict the order to something
+that is consistent with the expectations of the programmer.
+
+The most basic tool is locking.  Mutexes, condition variables and
+semaphores are used in QEMU, and should be the default approach to
+synchronization.  Anything else is considerably harder, but it's
+also justified more often than one would like.  The two tools that
+are provided by qemu/atomic.h are memory barriers and atomic operations.
+
+Macros defined by qemu/atomic.h fall in three camps:
+
+- compiler barriers: barrier();
+
+- weak atomic access and manual memory barriers: atomic_read(),
+  atomic_set(), smp_rmb(), smp_wmb(), smp_mb(), smp_read_barrier_depends();
+
+- sequentially consistent atomic access: everything else.
+
+
+COMPILER MEMORY BARRIER
+=======================
+
+barrier() prevents the compiler from moving the memory accesses either
+side of it to the other side.  The compiler barrier has no direct effect
+on the CPU, which may then reorder things however it wishes.
+
+barrier() is mostly used within qemu/atomic.h itself.  On some
+architectures, CPU guarantees are strong enough that blocking compiler
+optimizations already ensures the correct order of execution.  In this
+case, qemu/atomic.h will reduce stronger memory barriers to simple
+compiler barriers.
+
+Still, barrier() can be useful when writing code that can be interrupted
+by signal handlers.
+
+
+SEQUENTIALLY CONSISTENT ATOMIC ACCESS
+=====================================
+
+Most of the operations in the qemu/atomic.h header ensure *sequential
+consistency*, where "the result of any execution is the same as if the
+operations of all the processors were executed in some sequential order,
+and the operations of each individual processor appear in this sequence
+in the order specified by its program".
+
+qemu/atomic.h provides the following set of atomic read-modify-write
+operations:
+
+    void atomic_inc(ptr)
+    void atomic_dec(ptr)
+    void atomic_add(ptr, val)
+    void atomic_sub(ptr, val)
+    void atomic_and(ptr, val)
+    void atomic_or(ptr, val)
+
+    typeof(*ptr) atomic_fetch_inc(ptr)
+    typeof(*ptr) atomic_fetch_dec(ptr)
+    typeof(*ptr) atomic_fetch_add(ptr, val)
+    typeof(*ptr) atomic_fetch_sub(ptr, val)
+    typeof(*ptr) atomic_fetch_and(ptr, val)
+    typeof(*ptr) atomic_fetch_or(ptr, val)
+    typeof(*ptr) atomic_xchg(ptr, val
+    typeof(*ptr) atomic_cmpxchg(ptr, old, new)
+
+all of which return the old value of *ptr.  These operations are
+polymorphic; they operate on any type that is as wide as an int.
+
+Sequentially consistent loads and stores can be done using:
+
+    atomic_fetch_add(ptr, 0) for loads
+    atomic_xchg(ptr, val) for stores
+
+However, they are quite expensive on some platforms, notably POWER and
+ARM.  Therefore, qemu/atomic.h provides two primitives with slightly
+weaker constraints:
+
+    typeof(*ptr) atomic_mb_read(ptr)
+    void         atomic_mb_set(ptr, val)
+
+The semantics of these primitives map to Java volatile variables,
+and are strongly related to memory barriers as used in the Linux
+kernel (see below).
+
+As long as you use atomic_mb_read and atomic_mb_set, accesses cannot
+be reordered with each other, and it is also not possible to reorder
+"normal" accesses around them.
+
+However, and this is the important difference between
+atomic_mb_read/atomic_mb_set and sequential consistency, it is important
+for both threads to access the same volatile variable.  It is not the
+case that everything visible to thread A when it writes volatile field f
+becomes visible to thread B after it reads volatile field g. The store
+and load have to "match" (i.e., be performed on the same volatile
+field) to achieve the right semantics.
+
+
+These operations operate on any type that is as wide as an int or smaller.
+
+
+WEAK ATOMIC ACCESS AND MANUAL MEMORY BARRIERS
+=============================================
+
+Compared to sequentially consistent atomic access, programming with
+weaker consistency models can be considerably more complicated.
+In general, if the algorithm you are writing includes both writes
+and reads on the same side, it is generally simpler to use sequentially
+consistent primitives.
+
+When using this model, variables are accessed with atomic_read() and
+atomic_set(), and restrictions to the ordering of accesses is enforced
+using the smp_rmb(), smp_wmb(), smp_mb() and smp_read_barrier_depends()
+memory barriers.
+
+atomic_read() and atomic_set() prevents the compiler from using
+optimizations that might otherwise optimize accesses out of existence
+on the one hand, or that might create unsolicited accesses on the other.
+In general this should not have any effect, because the same compiler
+barriers are already implied by memory barriers.  However, it is useful
+to do so, because it tells readers which variables are shared with
+other threads, and which are local to the current thread or protected
+by other, more mundane means.
+
+Memory barriers control the order of references to shared memory.
+They come in four kinds:
+
+- smp_rmb() guarantees that all the LOAD operations specified before
+  the barrier will appear to happen before all the LOAD operations
+  specified after the barrier with respect to the other components of
+  the system.
+
+  In other words, smp_rmb() puts a partial ordering on loads, but is not
+  required to have any effect on stores.
+
+- smp_wmb() guarantees that all the STORE operations specified before
+  the barrier will appear to happen before all the STORE operations
+  specified after the barrier with respect to the other components of
+  the system.
+
+  In other words, smp_wmb() puts a partial ordering on stores, but is not
+  required to have any effect on loads.
+
+- smp_mb() guarantees that all the LOAD and STORE operations specified
+  before the barrier will appear to happen before all the LOAD and
+  STORE operations specified after the barrier with respect to the other
+  components of the system.
+
+  smp_mb() puts a partial ordering on both loads and stores.  It is
+  stronger than both a read and a write memory barrier; it implies both
+  smp_rmb() and smp_wmb(), but it also prevents STOREs coming before the
+  barrier from overtaking LOADs coming after the barrier and vice versa.
+
+- smp_read_barrier_depends() is a weaker kind of read barrier.  On
+  most processors, whenever two loads are performed such that the
+  second depends on the result of the first (e.g., the first load
+  retrieves the address to which the second load will be directed),
+  the processor will guarantee that the first LOAD will appear to happen
+  before the second with respect to the other components of the system.
+  However, this is not always true---for example, it was not true on
+  Alpha processors.  Whenever this kind of access happens to shared
+  memory (that is not protected by a lock), a read barrier is needed,
+  and smp_read_barrier_depends() can be used instead of smp_rmb().
+
+  Note that the first load really has to have a _data_ dependency and not
+  a control dependency.  If the address for the second load is dependent
+  on the first load, but the dependency is through a conditional rather
+  than actually loading the address itself, then it's a _control_
+  dependency and a full read barrier or better is required.
+
+
+This is the set of barriers that is required *between* two atomic_read()
+and atomic_set() operations to achieve sequential consistency:
+
+                    |               2nd operation             |
+                    |-----------------------------------------|
+     1st operation  | (after last) | atomic_read | atomic_set |
+     ---------------+--------------+-------------+------------|
+     (before first) |              | none        | smp_wmb()  |
+     ---------------+--------------+-------------+------------|
+     atomic_read    | smp_rmb()    | smp_rmb()*  | **         |
+     ---------------+--------------+-------------+------------|
+     atomic_set     | none         | smp_mb()*** | smp_wmb()  |
+     ---------------+--------------+-------------+------------|
+
+       * Or smp_read_barrier_depends().
+
+      ** This requires a load-store barrier.  How to achieve this varies
+         depending on the machine, but in practice smp_rmb()+smp_wmb()
+         should have the desired effect.  For example, on PowerPC the
+         lwsync instruction is a combined load-load, load-store and
+         store-store barrier.
+
+     *** This requires a store-load barrier.  On most machines, the only
+         way to achieve this is a full barrier.
+
+
+You can see that the two possible definitions of atomic_mb_read()
+and atomic_mb_set() are the following:
+
+    1) atomic_mb_read(p)   = atomic_read(p); smp_rmb()
+       atomic_mb_set(p, v) = smp_wmb(); atomic_set(p, v); smp_mb()
+
+    2) atomic_mb_read(p)   = smp_mb() atomic_read(p); smp_rmb()
+       atomic_mb_set(p, v) = smp_wmb(); atomic_set(p, v);
+
+Usually the former is used, because smp_mb() is expensive and a program
+normally has more reads than writes.  Therefore it makes more sense to
+make atomic_mb_set() the more expensive operation.
+
+There are two common cases in which atomic_mb_read and atomic_mb_set
+generate too many memory barriers, and thus it can be useful to manually
+place barriers instead:
+
+- when a data structure has one thread that is always a writer
+  and one thread that is always a reader, manual placement of
+  memory barriers makes the write side faster.  Furthermore,
+  correctness is easy to check for in this case using the "pairing"
+  trick that is explained below:
+
+     thread 1                                thread 1
+     -------------------------               ------------------------
+     (other writes)
+                                             smp_wmb()
+     atomic_mb_set(&a, x)                    atomic_set(&a, x)
+                                             smp_wmb()
+     atomic_mb_set(&b, y)                    atomic_set(&b, y)
+
+                                       =>
+     thread 2                                thread 2
+     -------------------------               ------------------------
+     y = atomic_mb_read(&b)                  y = atomic_read(&b)
+                                             smp_rmb()
+     x = atomic_mb_read(&a)                  x = atomic_read(&a)
+                                             smp_rmb()
+
+- sometimes, a thread is accessing many variables that are otherwise
+  unrelated to each other (for example because, apart from the current
+  thread, exactly one other thread will read or write each of these
+  variables).  In this case, it is possible to "hoist" the implicit
+  barriers provided by atomic_mb_read() and atomic_mb_set() outside
+  a loop.  For example, the above definition atomic_mb_read() gives
+  the following transformation:
+
+     n = 0;                                  n = 0;
+     for (i = 0; i < 10; i++)          =>    for (i = 0; i < 10; i++)
+       n += atomic_mb_read(&a[i]);             n += atomic_read(&a[i]);
+                                             smp_rmb();
+
+  Similarly, atomic_mb_set() can be transformed as follows:
+  smp_mb():
+
+                                             smp_wmb();
+     for (i = 0; i < 10; i++)          =>    for (i = 0; i < 10; i++)
+       atomic_mb_set(&a[i], false);            atomic_set(&a[i], false);
+                                             smp_mb();
+
+
+The two tricks can be combined.  In this case, splitting a loop in
+two lets you hoist the barriers out of the loops _and_ eliminate the
+expensive smp_mb():
+
+                                             smp_wmb();
+     for (i = 0; i < 10; i++) {        =>    for (i = 0; i < 10; i++)
+       atomic_mb_set(&a[i], false);            atomic_set(&a[i], false);
+       atomic_mb_set(&b[i], false);          smb_wmb();
+     }                                       for (i = 0; i < 10; i++)
+                                               atomic_set(&a[i], false);
+                                             smp_mb();
+
+  The other thread can still use atomic_mb_read()/atomic_mb_set()
+
+
+Memory barrier pairing
+----------------------
+
+A useful rule of thumb is that memory barriers should always, or almost
+always, be paired with another barrier.  In the case of QEMU, however,
+note that the other barrier may actually be in a driver that runs in
+the guest!
+
+For the purposes of pairing, smp_read_barrier_depends() and smp_rmb()
+both count as read barriers.  A read barriers shall pair with a write
+barrier or a full barrier; a write barrier shall pair with a read
+barrier or a full barrier.  A full barrier can pair with anything.
+For example:
+
+        thread 1             thread 2
+        ===============      ===============
+        a = 1;
+        smp_wmb();
+        b = 2;               x = b;
+                             smp_rmb();
+                             y = a;
+
+Note that the "writing" thread are accessing the variables in the
+opposite order as the "reading" thread.  This is expected: stores
+before the write barrier will normally match the loads after the
+read barrier, and vice versa.  The same is true for more than 2
+access and for data dependency barriers:
+
+        thread 1             thread 2
+        ===============      ===============
+        b[2] = 1;
+        smp_wmb();
+        x->i = 2;
+        smp_wmb();
+        a = x;               x = a;
+                             smp_read_barrier_depends();
+                             y = x->i;
+                             smp_read_barrier_depends();
+                             z = b[y];
+
+smp_wmb() also pairs with atomic_mb_read(), and smp_rmb() also pairs
+with atomic_mb_set().
+
+
+COMPARISON WITH LINUX KERNEL MEMORY BARRIERS
+============================================
+
+Here is a list of differences between Linux kernel atomic operations
+and memory barriers, and the equivalents in QEMU:
+
+- atomic operations in Linux are always on a 32-bit int type and
+  use a boxed atomic_t type; atomic operations in QEMU are polymorphic
+  and use normal C types.
+
+- atomic_read and atomic_set in Linux give no guarantee at all;
+  atomic_read and atomic_set in QEMU include a compiler barrier
+  (similar to the ACCESS_ONCE macro in Linux).
+
+- most atomic read-modify-write operations in Linux return void;
+  in QEMU, all of them return the old value of the variable.
+
+- different atomic read-modify-write operations in Linux imply
+  a different set of memory barriers; in QEMU, all of them enforce
+  sequential consistency, which means they imply full memory barriers
+  before and after the operation.
+
+- Linux does not have an equivalent of atomic_mb_read() and
+  atomic_mb_set().  In particular, note that set_mb() is a little
+  weaker than atomic_mb_set().
+
+
+SOURCES
+=======
+
+* Documentation/memory-barriers.txt from the Linux kernel
+
+* "The JSR-133 Cookbook for Compiler Writers", available at
+  http://g.oswego.edu/dl/jmm/cookbook.html
diff --git a/exec.c b/exec.c
index c49806c..e150935 100644
--- a/exec.c
+++ b/exec.c
@@ -31,6 +31,7 @@
 #include "hw/qdev.h"
 #include "qemu/osdep.h"
 #include "sysemu/kvm.h"
+#include "sysemu/sysemu.h"
 #include "hw/xen/xen.h"
 #include "qemu/timer.h"
 #include "qemu/config-file.h"
@@ -53,7 +54,6 @@
 //#define DEBUG_SUBPAGE
 
 #if !defined(CONFIG_USER_ONLY)
-int phys_ram_fd;
 static int in_migration;
 
 RAMList ram_list = { .blocks = QTAILQ_HEAD_INITIALIZER(ram_list.blocks) };
@@ -88,12 +88,15 @@
     uint16_t ptr : 15;
 };
 
+typedef PhysPageEntry Node[L2_SIZE];
+
 struct AddressSpaceDispatch {
     /* This is a multi-level map on the physical address space.
      * The bottom level has pointers to MemoryRegionSections.
      */
     PhysPageEntry phys_map;
-    MemoryListener listener;
+    Node *nodes;
+    MemoryRegionSection *sections;
     AddressSpace *as;
 };
 
@@ -105,16 +108,22 @@
     uint16_t sub_section[TARGET_PAGE_SIZE];
 } subpage_t;
 
-static MemoryRegionSection *phys_sections;
-static unsigned phys_sections_nb, phys_sections_nb_alloc;
-static uint16_t phys_section_unassigned;
-static uint16_t phys_section_notdirty;
-static uint16_t phys_section_rom;
-static uint16_t phys_section_watch;
+#define PHYS_SECTION_UNASSIGNED 0
+#define PHYS_SECTION_NOTDIRTY 1
+#define PHYS_SECTION_ROM 2
+#define PHYS_SECTION_WATCH 3
 
-/* Simple allocator for PhysPageEntry nodes */
-static PhysPageEntry (*phys_map_nodes)[L2_SIZE];
-static unsigned phys_map_nodes_nb, phys_map_nodes_nb_alloc;
+typedef struct PhysPageMap {
+    unsigned sections_nb;
+    unsigned sections_nb_alloc;
+    unsigned nodes_nb;
+    unsigned nodes_nb_alloc;
+    Node *nodes;
+    MemoryRegionSection *sections;
+} PhysPageMap;
+
+static PhysPageMap *prev_map;
+static PhysPageMap next_map;
 
 #define PHYS_MAP_NODE_NIL (((uint16_t)~0) >> 1)
 
@@ -129,13 +138,13 @@
 
 static void phys_map_node_reserve(unsigned nodes)
 {
-    if (phys_map_nodes_nb + nodes > phys_map_nodes_nb_alloc) {
-        typedef PhysPageEntry Node[L2_SIZE];
-        phys_map_nodes_nb_alloc = MAX(phys_map_nodes_nb_alloc * 2, 16);
-        phys_map_nodes_nb_alloc = MAX(phys_map_nodes_nb_alloc,
-                                      phys_map_nodes_nb + nodes);
-        phys_map_nodes = g_renew(Node, phys_map_nodes,
-                                 phys_map_nodes_nb_alloc);
+    if (next_map.nodes_nb + nodes > next_map.nodes_nb_alloc) {
+        next_map.nodes_nb_alloc = MAX(next_map.nodes_nb_alloc * 2,
+                                            16);
+        next_map.nodes_nb_alloc = MAX(next_map.nodes_nb_alloc,
+                                      next_map.nodes_nb + nodes);
+        next_map.nodes = g_renew(Node, next_map.nodes,
+                                 next_map.nodes_nb_alloc);
     }
 }
 
@@ -144,22 +153,16 @@
     unsigned i;
     uint16_t ret;
 
-    ret = phys_map_nodes_nb++;
+    ret = next_map.nodes_nb++;
     assert(ret != PHYS_MAP_NODE_NIL);
-    assert(ret != phys_map_nodes_nb_alloc);
+    assert(ret != next_map.nodes_nb_alloc);
     for (i = 0; i < L2_SIZE; ++i) {
-        phys_map_nodes[ret][i].is_leaf = 0;
-        phys_map_nodes[ret][i].ptr = PHYS_MAP_NODE_NIL;
+        next_map.nodes[ret][i].is_leaf = 0;
+        next_map.nodes[ret][i].ptr = PHYS_MAP_NODE_NIL;
     }
     return ret;
 }
 
-static void phys_map_nodes_reset(void)
-{
-    phys_map_nodes_nb = 0;
-}
-
-
 static void phys_page_set_level(PhysPageEntry *lp, hwaddr *index,
                                 hwaddr *nb, uint16_t leaf,
                                 int level)
@@ -170,15 +173,15 @@
 
     if (!lp->is_leaf && lp->ptr == PHYS_MAP_NODE_NIL) {
         lp->ptr = phys_map_node_alloc();
-        p = phys_map_nodes[lp->ptr];
+        p = next_map.nodes[lp->ptr];
         if (level == 0) {
             for (i = 0; i < L2_SIZE; i++) {
                 p[i].is_leaf = 1;
-                p[i].ptr = phys_section_unassigned;
+                p[i].ptr = PHYS_SECTION_UNASSIGNED;
             }
         }
     } else {
-        p = phys_map_nodes[lp->ptr];
+        p = next_map.nodes[lp->ptr];
     }
     lp = &p[(*index >> (level * L2_BITS)) & (L2_SIZE - 1)];
 
@@ -205,20 +208,20 @@
     phys_page_set_level(&d->phys_map, &index, &nb, leaf, P_L2_LEVELS - 1);
 }
 
-static MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index)
+static MemoryRegionSection *phys_page_find(PhysPageEntry lp, hwaddr index,
+                                           Node *nodes, MemoryRegionSection *sections)
 {
-    PhysPageEntry lp = d->phys_map;
     PhysPageEntry *p;
     int i;
 
     for (i = P_L2_LEVELS - 1; i >= 0 && !lp.is_leaf; i--) {
         if (lp.ptr == PHYS_MAP_NODE_NIL) {
-            return &phys_sections[phys_section_unassigned];
+            return &sections[PHYS_SECTION_UNASSIGNED];
         }
-        p = phys_map_nodes[lp.ptr];
+        p = nodes[lp.ptr];
         lp = p[(index >> (i * L2_BITS)) & (L2_SIZE - 1)];
     }
-    return &phys_sections[lp.ptr];
+    return &sections[lp.ptr];
 }
 
 bool memory_region_is_unassigned(MemoryRegion *mr)
@@ -227,29 +230,30 @@
         && mr != &io_mem_watch;
 }
 
-static MemoryRegionSection *address_space_lookup_region(AddressSpace *as,
+static MemoryRegionSection *address_space_lookup_region(AddressSpaceDispatch *d,
                                                         hwaddr addr,
                                                         bool resolve_subpage)
 {
     MemoryRegionSection *section;
     subpage_t *subpage;
 
-    section = phys_page_find(as->dispatch, addr >> TARGET_PAGE_BITS);
+    section = phys_page_find(d->phys_map, addr >> TARGET_PAGE_BITS,
+                             d->nodes, d->sections);
     if (resolve_subpage && section->mr->subpage) {
         subpage = container_of(section->mr, subpage_t, iomem);
-        section = &phys_sections[subpage->sub_section[SUBPAGE_IDX(addr)]];
+        section = &d->sections[subpage->sub_section[SUBPAGE_IDX(addr)]];
     }
     return section;
 }
 
 static MemoryRegionSection *
-address_space_translate_internal(AddressSpace *as, hwaddr addr, hwaddr *xlat,
+address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *xlat,
                                  hwaddr *plen, bool resolve_subpage)
 {
     MemoryRegionSection *section;
     Int128 diff;
 
-    section = address_space_lookup_region(as, addr, resolve_subpage);
+    section = address_space_lookup_region(d, addr, resolve_subpage);
     /* Compute offset within MemoryRegionSection */
     addr -= section->offset_within_address_space;
 
@@ -271,7 +275,7 @@
     hwaddr len = *plen;
 
     for (;;) {
-        section = address_space_translate_internal(as, addr, &addr, plen, true);
+        section = address_space_translate_internal(as->dispatch, addr, &addr, plen, true);
         mr = section->mr;
 
         if (!mr->iommu_ops) {
@@ -300,7 +304,7 @@
                                   hwaddr *plen)
 {
     MemoryRegionSection *section;
-    section = address_space_translate_internal(as, addr, xlat, plen, false);
+    section = address_space_translate_internal(as->dispatch, addr, xlat, plen, false);
 
     assert(!section->mr->iommu_ops);
     return section;
@@ -723,12 +727,12 @@
         iotlb = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
             + xlat;
         if (!section->readonly) {
-            iotlb |= phys_section_notdirty;
+            iotlb |= PHYS_SECTION_NOTDIRTY;
         } else {
-            iotlb |= phys_section_rom;
+            iotlb |= PHYS_SECTION_ROM;
         }
     } else {
-        iotlb = section - phys_sections;
+        iotlb = section - address_space_memory.dispatch->sections;
         iotlb += xlat;
     }
 
@@ -738,7 +742,7 @@
         if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
             /* Avoid trapping reads of pages with a write breakpoint. */
             if ((prot & PAGE_WRITE) || (wp->flags & BP_MEM_READ)) {
-                iotlb = phys_section_watch + paddr;
+                iotlb = PHYS_SECTION_WATCH + paddr;
                 *address |= TLB_MMIO;
                 break;
             }
@@ -754,10 +758,29 @@
 static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
                              uint16_t section);
 static subpage_t *subpage_init(AddressSpace *as, hwaddr base);
-static void destroy_page_desc(uint16_t section_index)
+
+static uint16_t phys_section_add(MemoryRegionSection *section)
 {
-    MemoryRegionSection *section = &phys_sections[section_index];
-    MemoryRegion *mr = section->mr;
+    /* The physical section number is ORed with a page-aligned
+     * pointer to produce the iotlb entries.  Thus it should
+     * never overflow into the page-aligned value.
+     */
+    assert(next_map.sections_nb < TARGET_PAGE_SIZE);
+
+    if (next_map.sections_nb == next_map.sections_nb_alloc) {
+        next_map.sections_nb_alloc = MAX(next_map.sections_nb_alloc * 2,
+                                         16);
+        next_map.sections = g_renew(MemoryRegionSection, next_map.sections,
+                                    next_map.sections_nb_alloc);
+    }
+    next_map.sections[next_map.sections_nb] = *section;
+    memory_region_ref(section->mr);
+    return next_map.sections_nb++;
+}
+
+static void phys_section_destroy(MemoryRegion *mr)
+{
+    memory_region_unref(mr);
 
     if (mr->subpage) {
         subpage_t *subpage = container_of(mr, subpage_t, iomem);
@@ -766,53 +789,15 @@
     }
 }
 
-static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level)
+static void phys_sections_free(PhysPageMap *map)
 {
-    unsigned i;
-    PhysPageEntry *p;
-
-    if (lp->ptr == PHYS_MAP_NODE_NIL) {
-        return;
+    while (map->sections_nb > 0) {
+        MemoryRegionSection *section = &map->sections[--map->sections_nb];
+        phys_section_destroy(section->mr);
     }
-
-    p = phys_map_nodes[lp->ptr];
-    for (i = 0; i < L2_SIZE; ++i) {
-        if (!p[i].is_leaf) {
-            destroy_l2_mapping(&p[i], level - 1);
-        } else {
-            destroy_page_desc(p[i].ptr);
-        }
-    }
-    lp->is_leaf = 0;
-    lp->ptr = PHYS_MAP_NODE_NIL;
-}
-
-static void destroy_all_mappings(AddressSpaceDispatch *d)
-{
-    destroy_l2_mapping(&d->phys_map, P_L2_LEVELS - 1);
-    phys_map_nodes_reset();
-}
-
-static uint16_t phys_section_add(MemoryRegionSection *section)
-{
-    /* The physical section number is ORed with a page-aligned
-     * pointer to produce the iotlb entries.  Thus it should
-     * never overflow into the page-aligned value.
-     */
-    assert(phys_sections_nb < TARGET_PAGE_SIZE);
-
-    if (phys_sections_nb == phys_sections_nb_alloc) {
-        phys_sections_nb_alloc = MAX(phys_sections_nb_alloc * 2, 16);
-        phys_sections = g_renew(MemoryRegionSection, phys_sections,
-                                phys_sections_nb_alloc);
-    }
-    phys_sections[phys_sections_nb] = *section;
-    return phys_sections_nb++;
-}
-
-static void phys_sections_clear(void)
-{
-    phys_sections_nb = 0;
+    g_free(map->sections);
+    g_free(map->nodes);
+    g_free(map);
 }
 
 static void register_subpage(AddressSpaceDispatch *d, MemoryRegionSection *section)
@@ -820,7 +805,8 @@
     subpage_t *subpage;
     hwaddr base = section->offset_within_address_space
         & TARGET_PAGE_MASK;
-    MemoryRegionSection *existing = phys_page_find(d, base >> TARGET_PAGE_BITS);
+    MemoryRegionSection *existing = phys_page_find(d->phys_map, base >> TARGET_PAGE_BITS,
+                                                   next_map.nodes, next_map.sections);
     MemoryRegionSection subsection = {
         .offset_within_address_space = base,
         .size = int128_make64(TARGET_PAGE_SIZE),
@@ -857,7 +843,8 @@
 
 static void mem_add(MemoryListener *listener, MemoryRegionSection *section)
 {
-    AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener);
+    AddressSpace *as = container_of(listener, AddressSpace, dispatch_listener);
+    AddressSpaceDispatch *d = as->next_dispatch;
     MemoryRegionSection now = *section, remain = *section;
     Int128 page_size = int128_make64(TARGET_PAGE_SIZE);
 
@@ -1057,12 +1044,10 @@
 static void qemu_ram_setup_dump(void *addr, ram_addr_t size)
 {
     int ret;
-    QemuOpts *machine_opts;
 
     /* Use MADV_DONTDUMP, if user doesn't want the guest memory in the core */
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts &&
-        !qemu_opt_get_bool(machine_opts, "dump-guest-core", true)) {
+    if (!qemu_opt_get_bool(qemu_get_machine_opts(),
+                           "dump-guest-core", true)) {
         ret = qemu_madvise(addr, size, QEMU_MADV_DONTDUMP);
         if (ret) {
             perror("qemu_madvise");
@@ -1109,10 +1094,7 @@
 
 static int memory_try_enable_merging(void *addr, size_t len)
 {
-    QemuOpts *opts;
-
-    opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (opts && !qemu_opt_get_bool(opts, "mem-merge", true)) {
+    if (!qemu_opt_get_bool(qemu_get_machine_opts(), "mem-merge", true)) {
         /* disabled by the user */
         return 0;
     }
@@ -1316,15 +1298,7 @@
 }
 #endif /* !_WIN32 */
 
-/* Return a host pointer to ram allocated with qemu_ram_alloc.
-   With the exception of the softmmu code in this file, this should
-   only be used for local memory (e.g. video ram) that the device owns,
-   and knows it isn't going to access beyond the end of the block.
-
-   It should not be used for general purpose DMA.
-   Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
- */
-void *qemu_get_ram_ptr(ram_addr_t addr)
+static RAMBlock *qemu_get_ram_block(ram_addr_t addr)
 {
     RAMBlock *block;
 
@@ -1344,6 +1318,21 @@
 
 found:
     ram_list.mru_block = block;
+    return block;
+}
+
+/* Return a host pointer to ram allocated with qemu_ram_alloc.
+   With the exception of the softmmu code in this file, this should
+   only be used for local memory (e.g. video ram) that the device owns,
+   and knows it isn't going to access beyond the end of the block.
+
+   It should not be used for general purpose DMA.
+   Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
+ */
+void *qemu_get_ram_ptr(ram_addr_t addr)
+{
+    RAMBlock *block = qemu_get_ram_block(addr);
+
     if (xen_enabled()) {
         /* We need to check if the requested address is in the RAM
          * because we don't want to map the entire memory in QEMU.
@@ -1418,14 +1407,21 @@
     }
 }
 
-int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
+/* Some of the softmmu routines need to translate from a host pointer
+   (typically a TLB entry) back to a ram offset.  */
+MemoryRegion *qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
 {
     RAMBlock *block;
     uint8_t *host = ptr;
 
     if (xen_enabled()) {
         *ram_addr = xen_ram_addr_from_mapcache(ptr);
-        return 0;
+        return qemu_get_ram_block(*ram_addr)->mr;
+    }
+
+    block = ram_list.mru_block;
+    if (block && block->host && host - block->host < block->length) {
+        goto found;
     }
 
     QTAILQ_FOREACH(block, &ram_list.blocks, next) {
@@ -1434,25 +1430,15 @@
             continue;
         }
         if (host - block->host < block->length) {
-            *ram_addr = block->offset + (host - block->host);
-            return 0;
+            goto found;
         }
     }
 
-    return -1;
-}
+    return NULL;
 
-/* Some of the softmmu routines need to translate from a host pointer
-   (typically a TLB entry) back to a ram offset.  */
-ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
-{
-    ram_addr_t ram_addr;
-
-    if (qemu_ram_addr_from_host(ptr, &ram_addr)) {
-        fprintf(stderr, "Bad ram pointer %p\n", ptr);
-        abort();
-    }
-    return ram_addr;
+found:
+    *ram_addr = block->offset + (host - block->host);
+    return block->mr;
 }
 
 static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
@@ -1673,14 +1659,14 @@
 
     mmio->as = as;
     mmio->base = base;
-    memory_region_init_io(&mmio->iomem, &subpage_ops, mmio,
+    memory_region_init_io(&mmio->iomem, NULL, &subpage_ops, mmio,
                           "subpage", TARGET_PAGE_SIZE);
     mmio->iomem.subpage = true;
 #if defined(DEBUG_SUBPAGE)
     printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
            mmio, base, TARGET_PAGE_SIZE, subpage_memory);
 #endif
-    subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, phys_section_unassigned);
+    subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, PHYS_SECTION_UNASSIGNED);
 
     return mmio;
 }
@@ -1699,35 +1685,67 @@
 
 MemoryRegion *iotlb_to_region(hwaddr index)
 {
-    return phys_sections[index & ~TARGET_PAGE_MASK].mr;
+    return address_space_memory.dispatch->sections[index & ~TARGET_PAGE_MASK].mr;
 }
 
 static void io_mem_init(void)
 {
-    memory_region_init_io(&io_mem_rom, &unassigned_mem_ops, NULL, "rom", UINT64_MAX);
-    memory_region_init_io(&io_mem_unassigned, &unassigned_mem_ops, NULL,
+    memory_region_init_io(&io_mem_rom, NULL, &unassigned_mem_ops, NULL, "rom", UINT64_MAX);
+    memory_region_init_io(&io_mem_unassigned, NULL, &unassigned_mem_ops, NULL,
                           "unassigned", UINT64_MAX);
-    memory_region_init_io(&io_mem_notdirty, &notdirty_mem_ops, NULL,
+    memory_region_init_io(&io_mem_notdirty, NULL, &notdirty_mem_ops, NULL,
                           "notdirty", UINT64_MAX);
-    memory_region_init_io(&io_mem_watch, &watch_mem_ops, NULL,
+    memory_region_init_io(&io_mem_watch, NULL, &watch_mem_ops, NULL,
                           "watch", UINT64_MAX);
 }
 
 static void mem_begin(MemoryListener *listener)
 {
-    AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener);
+    AddressSpace *as = container_of(listener, AddressSpace, dispatch_listener);
+    AddressSpaceDispatch *d = g_new(AddressSpaceDispatch, 1);
 
-    destroy_all_mappings(d);
-    d->phys_map.ptr = PHYS_MAP_NODE_NIL;
+    d->phys_map  = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .is_leaf = 0 };
+    d->as = as;
+    as->next_dispatch = d;
+}
+
+static void mem_commit(MemoryListener *listener)
+{
+    AddressSpace *as = container_of(listener, AddressSpace, dispatch_listener);
+    AddressSpaceDispatch *cur = as->dispatch;
+    AddressSpaceDispatch *next = as->next_dispatch;
+
+    next->nodes = next_map.nodes;
+    next->sections = next_map.sections;
+
+    as->dispatch = next;
+    g_free(cur);
 }
 
 static void core_begin(MemoryListener *listener)
 {
-    phys_sections_clear();
-    phys_section_unassigned = dummy_section(&io_mem_unassigned);
-    phys_section_notdirty = dummy_section(&io_mem_notdirty);
-    phys_section_rom = dummy_section(&io_mem_rom);
-    phys_section_watch = dummy_section(&io_mem_watch);
+    uint16_t n;
+
+    prev_map = g_new(PhysPageMap, 1);
+    *prev_map = next_map;
+
+    memset(&next_map, 0, sizeof(next_map));
+    n = dummy_section(&io_mem_unassigned);
+    assert(n == PHYS_SECTION_UNASSIGNED);
+    n = dummy_section(&io_mem_notdirty);
+    assert(n == PHYS_SECTION_NOTDIRTY);
+    n = dummy_section(&io_mem_rom);
+    assert(n == PHYS_SECTION_ROM);
+    n = dummy_section(&io_mem_watch);
+    assert(n == PHYS_SECTION_WATCH);
+}
+
+/* This listener's commit run after the other AddressSpaceDispatch listeners'.
+ * All AddressSpaceDispatch instances have switched to the next map.
+ */
+static void core_commit(MemoryListener *listener)
+{
+    phys_sections_free(prev_map);
 }
 
 static void tcg_commit(MemoryListener *listener)
@@ -1752,65 +1770,36 @@
     cpu_physical_memory_set_dirty_tracking(0);
 }
 
-static void io_region_add(MemoryListener *listener,
-                          MemoryRegionSection *section)
-{
-    MemoryRegionIORange *mrio = g_new(MemoryRegionIORange, 1);
-
-    mrio->mr = section->mr;
-    mrio->offset = section->offset_within_region;
-    iorange_init(&mrio->iorange, &memory_region_iorange_ops,
-                 section->offset_within_address_space,
-                 int128_get64(section->size));
-    ioport_register(&mrio->iorange);
-}
-
-static void io_region_del(MemoryListener *listener,
-                          MemoryRegionSection *section)
-{
-    isa_unassign_ioport(section->offset_within_address_space,
-                        int128_get64(section->size));
-}
-
 static MemoryListener core_memory_listener = {
     .begin = core_begin,
+    .commit = core_commit,
     .log_global_start = core_log_global_start,
     .log_global_stop = core_log_global_stop,
     .priority = 1,
 };
 
-static MemoryListener io_memory_listener = {
-    .region_add = io_region_add,
-    .region_del = io_region_del,
-    .priority = 0,
-};
-
 static MemoryListener tcg_memory_listener = {
     .commit = tcg_commit,
 };
 
 void address_space_init_dispatch(AddressSpace *as)
 {
-    AddressSpaceDispatch *d = g_new(AddressSpaceDispatch, 1);
-
-    d->phys_map  = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .is_leaf = 0 };
-    d->listener = (MemoryListener) {
+    as->dispatch = NULL;
+    as->dispatch_listener = (MemoryListener) {
         .begin = mem_begin,
+        .commit = mem_commit,
         .region_add = mem_add,
         .region_nop = mem_add,
         .priority = 0,
     };
-    d->as = as;
-    as->dispatch = d;
-    memory_listener_register(&d->listener, as);
+    memory_listener_register(&as->dispatch_listener, as);
 }
 
 void address_space_destroy_dispatch(AddressSpace *as)
 {
     AddressSpaceDispatch *d = as->dispatch;
 
-    memory_listener_unregister(&d->listener);
-    destroy_l2_mapping(&d->phys_map, P_L2_LEVELS - 1);
+    memory_listener_unregister(&as->dispatch_listener);
     g_free(d);
     as->dispatch = NULL;
 }
@@ -1818,15 +1807,14 @@
 static void memory_map_init(void)
 {
     system_memory = g_malloc(sizeof(*system_memory));
-    memory_region_init(system_memory, "system", INT64_MAX);
+    memory_region_init(system_memory, NULL, "system", INT64_MAX);
     address_space_init(&address_space_memory, system_memory, "memory");
 
     system_io = g_malloc(sizeof(*system_io));
-    memory_region_init(system_io, "io", 65536);
+    memory_region_init(system_io, NULL, "io", 65536);
     address_space_init(&address_space_io, system_io, "I/O");
 
     memory_listener_register(&core_memory_listener, &address_space_memory);
-    memory_listener_register(&io_memory_listener, &address_space_io);
     memory_listener_register(&tcg_memory_listener, &address_space_memory);
 }
 
@@ -2039,6 +2027,7 @@
 }
 
 typedef struct {
+    MemoryRegion *mr;
     void *buffer;
     hwaddr addr;
     hwaddr len;
@@ -2118,47 +2107,56 @@
                         bool is_write)
 {
     hwaddr len = *plen;
-    hwaddr todo = 0;
-    hwaddr l, xlat;
-    MemoryRegion *mr;
-    ram_addr_t raddr = RAM_ADDR_MAX;
-    ram_addr_t rlen;
-    void *ret;
+    hwaddr done = 0;
+    hwaddr l, xlat, base;
+    MemoryRegion *mr, *this_mr;
+    ram_addr_t raddr;
 
-    while (len > 0) {
-        l = len;
-        mr = address_space_translate(as, addr, &xlat, &l, is_write);
+    if (len == 0) {
+        return NULL;
+    }
 
-        if (!memory_access_is_direct(mr, is_write)) {
-            if (todo || bounce.buffer) {
-                break;
-            }
-            bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
-            bounce.addr = addr;
-            bounce.len = l;
-            if (!is_write) {
-                address_space_read(as, addr, bounce.buffer, l);
-            }
-
-            *plen = l;
-            return bounce.buffer;
+    l = len;
+    mr = address_space_translate(as, addr, &xlat, &l, is_write);
+    if (!memory_access_is_direct(mr, is_write)) {
+        if (bounce.buffer) {
+            return NULL;
         }
-        if (!todo) {
-            raddr = memory_region_get_ram_addr(mr) + xlat;
-        } else {
-            if (memory_region_get_ram_addr(mr) + xlat != raddr + todo) {
-                break;
-            }
+        bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
+        bounce.addr = addr;
+        bounce.len = l;
+
+        memory_region_ref(mr);
+        bounce.mr = mr;
+        if (!is_write) {
+            address_space_read(as, addr, bounce.buffer, l);
         }
 
+        *plen = l;
+        return bounce.buffer;
+    }
+
+    base = xlat;
+    raddr = memory_region_get_ram_addr(mr);
+
+    for (;;) {
         len -= l;
         addr += l;
-        todo += l;
+        done += l;
+        if (len == 0) {
+            break;
+        }
+
+        l = len;
+        this_mr = address_space_translate(as, addr, &xlat, &l, is_write);
+        if (this_mr != mr || xlat != base + done) {
+            break;
+        }
     }
-    rlen = todo;
-    ret = qemu_ram_ptr_length(raddr, &rlen);
-    *plen = rlen;
-    return ret;
+
+    memory_region_ref(mr);
+    *plen = done;
+    return qemu_ram_ptr_length(raddr + base, plen);
 }
 
 /* Unmaps a memory region previously mapped by address_space_map().
@@ -2169,8 +2167,12 @@
                          int is_write, hwaddr access_len)
 {
     if (buffer != bounce.buffer) {
+        MemoryRegion *mr;
+        ram_addr_t addr1;
+
+        mr = qemu_ram_addr_from_host(buffer, &addr1);
+        assert(mr != NULL);
         if (is_write) {
-            ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer);
             while (access_len) {
                 unsigned l;
                 l = TARGET_PAGE_SIZE;
@@ -2184,6 +2186,7 @@
         if (xen_enabled()) {
             xen_invalidate_map_cache_entry(buffer);
         }
+        memory_region_unref(mr);
         return;
     }
     if (is_write) {
@@ -2191,6 +2194,7 @@
     }
     qemu_vfree(bounce.buffer);
     bounce.buffer = NULL;
+    memory_region_unref(bounce.mr);
     cpu_notify_map_clients();
 }
 
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
index 6eaf36d..ccfec13 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -76,6 +76,8 @@
 
     if (fsle->fse.ops->parse_opts) {
         if (fsle->fse.ops->parse_opts(opts, &fsle->fse)) {
+            g_free(fsle->fse.fsdev_id);
+            g_free(fsle);
             return -1;
         }
     }
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 915b0d1..d1cdcfb 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1077,7 +1077,7 @@
 Add drive to PCI storage controller.
 ETEXI
 
-#if defined(TARGET_I386)
+#if defined(CONFIG_PCI_HOTPLUG_OLD)
     {
         .name       = "pci_add",
         .args_type  = "pci_addr:s,type:s,opts:s?",
@@ -1093,7 +1093,7 @@
 Hot-add PCI device.
 ETEXI
 
-#if defined(TARGET_I386)
+#if defined(CONFIG_PCI_HOTPLUG_OLD)
     {
         .name       = "pci_del",
         .args_type  = "pci_addr:s",
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index dc6f4e4..35e2af4 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -68,14 +68,14 @@
         fprintf(stderr, "Virtio-9p device couldn't find fsdev with the "
                 "id = %s\n",
                 s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL");
-        return -1;
+        goto out;
     }
 
     if (!s->fsconf.tag) {
         /* we haven't specified a mount_tag */
         fprintf(stderr, "fsdev with id %s needs mount_tag arguments\n",
                 s->fsconf.fsdev_id);
-        return -1;
+        goto out;
     }
 
     s->ctx.export_flags = fse->export_flags;
@@ -85,10 +85,10 @@
     if (len > MAX_TAG_LEN - 1) {
         fprintf(stderr, "mount tag '%s' (%d bytes) is longer than "
                 "maximum (%d bytes)", s->fsconf.tag, len, MAX_TAG_LEN - 1);
-        return -1;
+        goto out;
     }
 
-    s->tag = strdup(s->fsconf.tag);
+    s->tag = g_strdup(s->fsconf.tag);
     s->ctx.uid = -1;
 
     s->ops = fse->ops;
@@ -99,11 +99,11 @@
     if (s->ops->init(&s->ctx) < 0) {
         fprintf(stderr, "Virtio-9p Failed to initialize fs-driver with id:%s"
                 " and export path:%s\n", s->fsconf.fsdev_id, s->ctx.fs_root);
-        return -1;
+        goto out;
     }
     if (v9fs_init_worker_threads() < 0) {
         fprintf(stderr, "worker thread initialization failed\n");
-        return -1;
+        goto out;
     }
 
     /*
@@ -115,18 +115,26 @@
     if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) {
         fprintf(stderr,
                 "error in converting name to path %s", strerror(errno));
-        return -1;
+        goto out;
     }
     if (s->ops->lstat(&s->ctx, &path, &stat)) {
         fprintf(stderr, "share path %s does not exist\n", fse->path);
-        return -1;
+        goto out;
     } else if (!S_ISDIR(stat.st_mode)) {
         fprintf(stderr, "share path %s is not a directory\n", fse->path);
-        return -1;
+        goto out;
     }
     v9fs_path_free(&path);
 
     return 0;
+out:
+    g_free(s->ctx.fs_root);
+    g_free(s->tag);
+    virtio_cleanup(vdev);
+    v9fs_path_free(&path);
+
+    return -1;
+
 }
 
 /* virtio-9p device */
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index 42eeace..b07feda 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -419,7 +419,8 @@
                        MemoryRegion *parent)
 {
     ar->pm1.evt.update_sci = update_sci;
-    memory_region_init_io(&ar->pm1.evt.io, &acpi_pm_evt_ops, ar, "acpi-evt", 4);
+    memory_region_init_io(&ar->pm1.evt.io, memory_region_owner(parent),
+                          &acpi_pm_evt_ops, ar, "acpi-evt", 4);
     memory_region_add_subregion(parent, 0, &ar->pm1.evt.io);
 }
 
@@ -481,7 +482,8 @@
 {
     ar->tmr.update_sci = update_sci;
     ar->tmr.timer = qemu_new_timer_ns(vm_clock, acpi_pm_tmr_timer, ar);
-    memory_region_init_io(&ar->tmr.io, &acpi_pm_tmr_ops, ar, "acpi-tmr", 4);
+    memory_region_init_io(&ar->tmr.io, memory_region_owner(parent),
+                          &acpi_pm_tmr_ops, ar, "acpi-tmr", 4);
     memory_region_add_subregion(parent, 8, &ar->tmr.io);
 }
 
@@ -552,7 +554,8 @@
     ar->pm1.cnt.s4_val = s4_val;
     ar->wakeup.notify = acpi_notify_wakeup;
     qemu_register_wakeup_notifier(&ar->wakeup);
-    memory_region_init_io(&ar->pm1.cnt.io, &acpi_pm_cnt_ops, ar, "acpi-cnt", 2);
+    memory_region_init_io(&ar->pm1.cnt.io, memory_region_owner(parent),
+                          &acpi_pm_cnt_ops, ar, "acpi-cnt", 2);
     memory_region_add_subregion(parent, 4, &ar->pm1.cnt.io);
 }
 
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 4a17f32..3fb443d 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -205,7 +205,7 @@
 void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
                   qemu_irq sci_irq)
 {
-    memory_region_init(&pm->io, "ich9-pm", ICH9_PMIO_SIZE);
+    memory_region_init(&pm->io, OBJECT(lpc_pci), "ich9-pm", ICH9_PMIO_SIZE);
     memory_region_set_enabled(&pm->io, false);
     memory_region_add_subregion(pci_address_space_io(lpc_pci),
                                 0, &pm->io);
@@ -215,12 +215,12 @@
     acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io, 2);
 
     acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
-    memory_region_init_io(&pm->io_gpe, &ich9_gpe_ops, pm, "apci-gpe0",
-                          ICH9_PMIO_GPE0_LEN);
+    memory_region_init_io(&pm->io_gpe, OBJECT(lpc_pci), &ich9_gpe_ops, pm,
+                          "apci-gpe0", ICH9_PMIO_GPE0_LEN);
     memory_region_add_subregion(&pm->io, ICH9_PMIO_GPE0_STS, &pm->io_gpe);
 
-    memory_region_init_io(&pm->io_smi, &ich9_smi_ops, pm, "apci-smi",
-                          8);
+    memory_region_init_io(&pm->io_smi, OBJECT(lpc_pci), &ich9_smi_ops, pm,
+                          "apci-smi", 8);
     memory_region_add_subregion(&pm->io, ICH9_PMIO_SMI_EN, &pm->io_smi);
 
     pm->irq = sci_irq;
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 756df3b..948ea87 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -383,14 +383,15 @@
 static void piix4_pm_machine_ready(Notifier *n, void *opaque)
 {
     PIIX4PMState *s = container_of(n, PIIX4PMState, machine_ready);
+    MemoryRegion *io_as = pci_address_space_io(&s->dev);
     uint8_t *pci_conf;
 
     pci_conf = s->dev.config;
-    pci_conf[0x5f] = (isa_is_ioport_assigned(0x378) ? 0x80 : 0) | 0x10;
+    pci_conf[0x5f] = 0x10 |
+        (memory_region_present(io_as, 0x378) ? 0x80 : 0);
     pci_conf[0x63] = 0x60;
-    pci_conf[0x67] = (isa_is_ioport_assigned(0x3f8) ? 0x08 : 0) |
-	(isa_is_ioport_assigned(0x2f8) ? 0x90 : 0);
-
+    pci_conf[0x67] = (memory_region_present(io_as, 0x3f8) ? 0x08 : 0) |
+        (memory_region_present(io_as, 0x2f8) ? 0x90 : 0);
 }
 
 static int piix4_pm_initfn(PCIDevice *dev)
@@ -423,7 +424,7 @@
     memory_region_add_subregion(pci_address_space_io(dev),
                                 s->smb_io_base, &s->smb.io);
 
-    memory_region_init(&s->io, "piix4-pm", 64);
+    memory_region_init(&s->io, OBJECT(s), "piix4-pm", 64);
     memory_region_set_enabled(&s->io, false);
     memory_region_add_subregion(pci_address_space_io(dev),
                                 0, &s->io);
@@ -670,19 +671,19 @@
 static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
                                            PCIBus *bus, PIIX4PMState *s)
 {
-    memory_region_init_io(&s->io_gpe, &piix4_gpe_ops, s, "apci-gpe0",
-                          GPE_LEN);
+    memory_region_init_io(&s->io_gpe, OBJECT(s), &piix4_gpe_ops, s,
+                          "acpi-gpe0", GPE_LEN);
     memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe);
 
-    memory_region_init_io(&s->io_pci, &piix4_pci_ops, s, "apci-pci-hotplug",
-                          PCI_HOTPLUG_SIZE);
+    memory_region_init_io(&s->io_pci, OBJECT(s), &piix4_pci_ops, s,
+                          "acpi-pci-hotplug", PCI_HOTPLUG_SIZE);
     memory_region_add_subregion(parent, PCI_HOTPLUG_ADDR,
                                 &s->io_pci);
     pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
 
     qemu_for_each_cpu(piix4_init_cpu_status, &s->gpe_cpu);
-    memory_region_init_io(&s->io_cpu, &cpu_hotplug_ops, s, "apci-cpu-hotplug",
-                          PIIX4_PROC_LEN);
+    memory_region_init_io(&s->io_cpu, OBJECT(s), &cpu_hotplug_ops, s,
+                          "acpi-cpu-hotplug", PIIX4_PROC_LEN);
     memory_region_add_subregion(parent, PIIX4_PROC_BASE, &s->io_cpu);
     s->cpu_added_notifier.notify = piix4_cpu_added_req;
     qemu_register_cpu_added_notifier(&s->cpu_added_notifier);
diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
index 8695efb..8dad08f 100644
--- a/hw/alpha/dp264.c
+++ b/hw/alpha/dp264.c
@@ -89,7 +89,7 @@
 
     /* Network setup.  e1000 is good enough, failing Tulip support.  */
     for (i = 0; i < nb_nics; i++) {
-        pci_nic_init_nofail(&nd_table[i], "e1000", NULL);
+        pci_nic_init_nofail(&nd_table[i], pci_bus, "e1000", NULL);
     }
 
     /* IDE disk setup.  */
diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
index 207dcad..63cc2cb 100644
--- a/hw/alpha/typhoon.c
+++ b/hw/alpha/typhoon.c
@@ -741,7 +741,7 @@
 
     /* Main memory region, 0x00.0000.0000.  Real hardware supports 32GB,
        but the address space hole reserved at this point is 8TB.  */
-    memory_region_init_ram(&s->ram_region, "ram", ram_size);
+    memory_region_init_ram(&s->ram_region, OBJECT(s), "ram", ram_size);
     vmstate_register_ram_global(&s->ram_region);
     memory_region_add_subregion(addr_space, 0, &s->ram_region);
 
@@ -750,22 +750,25 @@
        the flash ROM.  I'm not sure that we need to implement it at all.  */
 
     /* Pchip0 CSRs, 0x801.8000.0000, 256MB.  */
-    memory_region_init_io(&s->pchip.region, &pchip_ops, s, "pchip0", 256*MB);
+    memory_region_init_io(&s->pchip.region, OBJECT(s), &pchip_ops, s, "pchip0",
+                          256*MB);
     memory_region_add_subregion(addr_space, 0x80180000000ULL,
                                 &s->pchip.region);
 
     /* Cchip CSRs, 0x801.A000.0000, 256MB.  */
-    memory_region_init_io(&s->cchip.region, &cchip_ops, s, "cchip0", 256*MB);
+    memory_region_init_io(&s->cchip.region, OBJECT(s), &cchip_ops, s, "cchip0",
+                          256*MB);
     memory_region_add_subregion(addr_space, 0x801a0000000ULL,
                                 &s->cchip.region);
 
     /* Dchip CSRs, 0x801.B000.0000, 256MB.  */
-    memory_region_init_io(&s->dchip_region, &dchip_ops, s, "dchip0", 256*MB);
+    memory_region_init_io(&s->dchip_region, OBJECT(s), &dchip_ops, s, "dchip0",
+                          256*MB);
     memory_region_add_subregion(addr_space, 0x801b0000000ULL,
                                 &s->dchip_region);
 
     /* Pchip0 PCI memory, 0x800.0000.0000, 4GB.  */
-    memory_region_init(&s->pchip.reg_mem, "pci0-mem", 4*GB);
+    memory_region_init(&s->pchip.reg_mem, OBJECT(s), "pci0-mem", 4*GB);
     memory_region_add_subregion(addr_space, 0x80000000000ULL,
                                 &s->pchip.reg_mem);
 
@@ -773,8 +776,8 @@
     /* ??? Ideally we drop the "system" i/o space on the floor and give the
        PCI subsystem the full address space reserved by the chipset.
        We can't do that until the MEM and IO paths in memory.c are unified.  */
-    memory_region_init_io(&s->pchip.reg_io, &alpha_pci_bw_io_ops, NULL,
-                          "pci0-io", 32*MB);
+    memory_region_init_io(&s->pchip.reg_io, OBJECT(s), &alpha_pci_bw_io_ops,
+                          NULL, "pci0-io", 32*MB);
     memory_region_add_subregion(addr_space, 0x801fc000000ULL,
                                 &s->pchip.reg_io);
 
@@ -784,13 +787,13 @@
     phb->bus = b;
 
     /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB.  */
-    memory_region_init_io(&s->pchip.reg_iack, &alpha_pci_iack_ops, b,
+    memory_region_init_io(&s->pchip.reg_iack, OBJECT(s), &alpha_pci_iack_ops, b,
                           "pci0-iack", 64*MB);
     memory_region_add_subregion(addr_space, 0x801f8000000ULL,
                                 &s->pchip.reg_iack);
 
     /* Pchip0 PCI configuration, 0x801.FE00.0000, 16MB.  */
-    memory_region_init_io(&s->pchip.reg_conf, &alpha_pci_conf1_ops, b,
+    memory_region_init_io(&s->pchip.reg_conf, OBJECT(s), &alpha_pci_conf1_ops, b,
                           "pci0-conf", 16*MB);
     memory_region_add_subregion(addr_space, 0x801fe000000ULL,
                                 &s->pchip.reg_conf);
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index 93422bc..5b22e84 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -124,8 +124,8 @@
 {
     BitBandState *s = FROM_SYSBUS(BitBandState, dev);
 
-    memory_region_init_io(&s->iomem, &bitband_ops, &s->base, "bitband",
-                          0x02000000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &bitband_ops, &s->base,
+                          "bitband", 0x02000000);
     sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
@@ -203,11 +203,11 @@
 #endif
 
     /* Flash programming is done via the SCU, so pretend it is ROM.  */
-    memory_region_init_ram(flash, "armv7m.flash", flash_size);
+    memory_region_init_ram(flash, NULL, "armv7m.flash", flash_size);
     vmstate_register_ram_global(flash);
     memory_region_set_readonly(flash, true);
     memory_region_add_subregion(address_space_mem, 0, flash);
-    memory_region_init_ram(sram, "armv7m.sram", sram_size);
+    memory_region_init_ram(sram, NULL, "armv7m.sram", sram_size);
     vmstate_register_ram_global(sram);
     memory_region_add_subregion(address_space_mem, 0x20000000, sram);
     armv7m_bitband_init();
@@ -247,7 +247,7 @@
     /* Hack to map an additional page of ram at the top of the address
        space.  This stops qemu complaining about executing code outside RAM
        when returning from an exception.  */
-    memory_region_init_ram(hack, "armv7m.hack", 0x1000);
+    memory_region_init_ram(hack, NULL, "armv7m.hack", 0x1000);
     vmstate_register_ram_global(hack);
     memory_region_add_subregion(address_space_mem, 0xfffff000, hack);
 
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 7c0090f..3e8741e 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -359,7 +359,6 @@
     uint64_t elf_entry;
     hwaddr entry;
     int big_endian;
-    QemuOpts *machine_opts;
 
     /* Load the kernel.  */
     if (!info->kernel_filename) {
@@ -367,12 +366,7 @@
         exit(1);
     }
 
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        info->dtb_filename = qemu_opt_get(machine_opts, "dtb");
-    } else {
-        info->dtb_filename = NULL;
-    }
+    info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
 
     if (!info->secondary_cpu_reset_hook) {
         info->secondary_cpu_reset_hook = default_reset_secondary;
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
index 8186f14..216b9b7 100644
--- a/hw/arm/exynos4210.c
+++ b/hw/arm/exynos4210.c
@@ -241,20 +241,20 @@
     /*** Memory ***/
 
     /* Chip-ID and OMR */
-    memory_region_init_io(&s->chipid_mem, &exynos4210_chipid_and_omr_ops,
+    memory_region_init_io(&s->chipid_mem, NULL, &exynos4210_chipid_and_omr_ops,
         NULL, "exynos4210.chipid", sizeof(chipid_and_omr));
     memory_region_add_subregion(system_mem, EXYNOS4210_CHIPID_ADDR,
                                 &s->chipid_mem);
 
     /* Internal ROM */
-    memory_region_init_ram(&s->irom_mem, "exynos4210.irom",
+    memory_region_init_ram(&s->irom_mem, NULL, "exynos4210.irom",
                            EXYNOS4210_IROM_SIZE);
     vmstate_register_ram_global(&s->irom_mem);
     memory_region_set_readonly(&s->irom_mem, true);
     memory_region_add_subregion(system_mem, EXYNOS4210_IROM_BASE_ADDR,
                                 &s->irom_mem);
     /* mirror of iROM */
-    memory_region_init_alias(&s->irom_alias_mem, "exynos4210.irom_alias",
+    memory_region_init_alias(&s->irom_alias_mem, NULL, "exynos4210.irom_alias",
                              &s->irom_mem,
                              0,
                              EXYNOS4210_IROM_SIZE);
@@ -263,7 +263,7 @@
                                 &s->irom_alias_mem);
 
     /* Internal RAM */
-    memory_region_init_ram(&s->iram_mem, "exynos4210.iram",
+    memory_region_init_ram(&s->iram_mem, NULL, "exynos4210.iram",
                            EXYNOS4210_IRAM_SIZE);
     vmstate_register_ram_global(&s->iram_mem);
     memory_region_add_subregion(system_mem, EXYNOS4210_IRAM_BASE_ADDR,
@@ -272,14 +272,14 @@
     /* DRAM */
     mem_size = ram_size;
     if (mem_size > EXYNOS4210_DRAM_MAX_SIZE) {
-        memory_region_init_ram(&s->dram1_mem, "exynos4210.dram1",
+        memory_region_init_ram(&s->dram1_mem, NULL, "exynos4210.dram1",
                 mem_size - EXYNOS4210_DRAM_MAX_SIZE);
         vmstate_register_ram_global(&s->dram1_mem);
         memory_region_add_subregion(system_mem, EXYNOS4210_DRAM1_BASE_ADDR,
                 &s->dram1_mem);
         mem_size = EXYNOS4210_DRAM_MAX_SIZE;
     }
-    memory_region_init_ram(&s->dram0_mem, "exynos4210.dram0", mem_size);
+    memory_region_init_ram(&s->dram0_mem, NULL, "exynos4210.dram0", mem_size);
     vmstate_register_ram_global(&s->dram0_mem);
     memory_region_add_subregion(system_mem, EXYNOS4210_DRAM0_BASE_ADDR,
             &s->dram0_mem);
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
index 4405dbd..de6c98a 100644
--- a/hw/arm/highbank.c
+++ b/hw/arm/highbank.c
@@ -149,8 +149,8 @@
     HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, dev);
 
     s->iomem = g_new(MemoryRegion, 1);
-    memory_region_init_io(s->iomem, &hb_mem_ops, s->regs, "highbank_regs",
-                          0x1000);
+    memory_region_init_io(s->iomem, OBJECT(s), &hb_mem_ops, s->regs,
+                          "highbank_regs", 0x1000);
     sysbus_init_mmio(dev, s->iomem);
 
     return 0;
@@ -227,12 +227,12 @@
 
     sysmem = get_system_memory();
     dram = g_new(MemoryRegion, 1);
-    memory_region_init_ram(dram, "highbank.dram", ram_size);
+    memory_region_init_ram(dram, NULL, "highbank.dram", ram_size);
     /* SDRAM at address zero.  */
     memory_region_add_subregion(sysmem, 0, dram);
 
     sysram = g_new(MemoryRegion, 1);
-    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
+    memory_region_init_ram(sysram, NULL, "highbank.sysram", 0x8000);
     memory_region_add_subregion(sysmem, 0xfff88000, sysram);
     if (bios_name != NULL) {
         sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
index cca2971..249a430 100644
--- a/hw/arm/integratorcp.c
+++ b/hw/arm/integratorcp.c
@@ -249,10 +249,10 @@
     }
     memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
     s->cm_init = 0x00000112;
-    memory_region_init_ram(&s->flash, "integrator.flash", 0x100000);
+    memory_region_init_ram(&s->flash, OBJECT(s), "integrator.flash", 0x100000);
     vmstate_register_ram_global(&s->flash);
 
-    memory_region_init_io(&s->iomem, &integratorcm_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &integratorcm_ops, s,
                           "integratorcm", 0x00800000);
     sysbus_init_mmio(dev, &s->iomem);
 
@@ -374,7 +374,8 @@
     qdev_init_gpio_in(&dev->qdev, icp_pic_set_irq, 32);
     sysbus_init_irq(dev, &s->parent_irq);
     sysbus_init_irq(dev, &s->parent_fiq);
-    memory_region_init_io(&s->iomem, &icp_pic_ops, s, "icp-pic", 0x00800000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &icp_pic_ops, s,
+                          "icp-pic", 0x00800000);
     sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
@@ -424,7 +425,7 @@
     MemoryRegion *io;
 
     io = (MemoryRegion *)g_malloc0(sizeof(MemoryRegion));
-    memory_region_init_io(io, &icp_control_ops, NULL,
+    memory_region_init_io(io, NULL, &icp_control_ops, NULL,
                           "control", 0x00800000);
     memory_region_add_subregion(get_system_memory(), base, io);
     /* ??? Save/restore.  */
@@ -463,14 +464,14 @@
         exit(1);
     }
 
-    memory_region_init_ram(ram, "integrator.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "integrator.ram", ram_size);
     vmstate_register_ram_global(ram);
     /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
     /* ??? RAM should repeat to fill physical memory space.  */
     /* SDRAM at address zero*/
     memory_region_add_subregion(address_space_mem, 0, ram);
     /* And again at address 0x80000000 */
-    memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size);
+    memory_region_init_alias(ram_alias, NULL, "ram.alias", ram, 0, ram_size);
     memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
 
     dev = qdev_create(NULL, "integrator_core");
diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c
index cf90f5d..bd6c05c 100644
--- a/hw/arm/kzm.c
+++ b/hw/arm/kzm.c
@@ -98,14 +98,14 @@
 
     /* On a real system, the first 16k is a `secure boot rom' */
 
-    memory_region_init_ram(ram, "kzm.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "kzm.ram", ram_size);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space_mem, KZM_RAMADDRESS, ram);
 
-    memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size);
+    memory_region_init_alias(ram_alias, NULL, "ram.alias", ram, 0, ram_size);
     memory_region_add_subregion(address_space_mem, 0x88000000, ram_alias);
 
-    memory_region_init_ram(sram, "kzm.sram", 0x4000);
+    memory_region_init_ram(sram, NULL, "kzm.sram", 0x4000);
     memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram);
 
     cpu_pic = arm_pic_init_cpu(cpu);
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
index 260e314..8e5fc26 100644
--- a/hw/arm/mainstone.c
+++ b/hw/arm/mainstone.c
@@ -113,7 +113,7 @@
 
     /* Setup CPU & memory */
     mpu = pxa270_init(address_space_mem, mainstone_binfo.ram_size, cpu_model);
-    memory_region_init_ram(rom, "mainstone.rom", MAINSTONE_ROM);
+    memory_region_init_ram(rom, NULL, "mainstone.rom", MAINSTONE_ROM);
     vmstate_register_ram_global(rom);
     memory_region_set_readonly(rom, true);
     memory_region_add_subregion(address_space_mem, 0, rom);
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index fbaf2be..b06d442 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -389,8 +389,8 @@
     sysbus_init_irq(dev, &s->irq);
     s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf,
                           object_get_typename(OBJECT(dev)), dev->qdev.id, s);
-    memory_region_init_io(&s->iomem, &mv88w8618_eth_ops, s, "mv88w8618-eth",
-                          MP_ETH_SIZE);
+    memory_region_init_io(&s->iomem, OBJECT(s), &mv88w8618_eth_ops, s,
+                          "mv88w8618-eth", MP_ETH_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
@@ -612,7 +612,7 @@
 
     s->brightness = 7;
 
-    memory_region_init_io(&s->iomem, &musicpal_lcd_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &musicpal_lcd_ops, s,
                           "musicpal-lcd", MP_LCD_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
 
@@ -740,7 +740,7 @@
 
     qdev_init_gpio_in(&dev->qdev, mv88w8618_pic_set_irq, 32);
     sysbus_init_irq(dev, &s->parent_irq);
-    memory_region_init_io(&s->iomem, &mv88w8618_pic_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &mv88w8618_pic_ops, s,
                           "musicpal-pic", MP_PIC_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
     return 0;
@@ -905,7 +905,7 @@
         mv88w8618_timer_init(dev, &s->timer[i], 1000000);
     }
 
-    memory_region_init_io(&s->iomem, &mv88w8618_pit_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &mv88w8618_pit_ops, s,
                           "musicpal-pit", MP_PIT_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
     return 0;
@@ -999,7 +999,7 @@
     mv88w8618_flashcfg_state *s = FROM_SYSBUS(mv88w8618_flashcfg_state, dev);
 
     s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
-    memory_region_init_io(&s->iomem, &mv88w8618_flashcfg_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &mv88w8618_flashcfg_ops, s,
                           "musicpal-flashcfg", MP_FLASHCFG_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
     return 0;
@@ -1074,7 +1074,7 @@
     SysBusDevice *sd = SYS_BUS_DEVICE(obj);
     MusicPalMiscState *s = MUSICPAL_MISC(obj);
 
-    memory_region_init_io(&s->iomem, &musicpal_misc_ops, NULL,
+    memory_region_init_io(&s->iomem, OBJECT(s), &musicpal_misc_ops, NULL,
                           "musicpal-misc", MP_MISC_SIZE);
     sysbus_init_mmio(sd, &s->iomem);
 }
@@ -1121,7 +1121,7 @@
 {
     MemoryRegion *iomem = g_new(MemoryRegion, 1);
 
-    memory_region_init_io(iomem, &mv88w8618_wlan_ops, NULL,
+    memory_region_init_io(iomem, OBJECT(dev), &mv88w8618_wlan_ops, NULL,
                           "musicpal-wlan", MP_WLAN_SIZE);
     sysbus_init_mmio(dev, iomem);
     return 0;
@@ -1327,7 +1327,7 @@
 
     sysbus_init_irq(dev, &s->irq);
 
-    memory_region_init_io(&s->iomem, &musicpal_gpio_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &musicpal_gpio_ops, s,
                           "musicpal-gpio", MP_GPIO_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
 
@@ -1484,7 +1484,7 @@
 {
     musicpal_key_state *s = FROM_SYSBUS(musicpal_key_state, dev);
 
-    memory_region_init(&s->iomem, "dummy", 0);
+    memory_region_init(&s->iomem, OBJECT(s), "dummy", 0);
     sysbus_init_mmio(dev, &s->iomem);
 
     s->kbd_extended = 0;
@@ -1564,11 +1564,11 @@
     cpu_pic = arm_pic_init_cpu(cpu);
 
     /* For now we use a fixed - the original - RAM size */
-    memory_region_init_ram(ram, "musicpal.ram", MP_RAM_DEFAULT_SIZE);
+    memory_region_init_ram(ram, NULL, "musicpal.ram", MP_RAM_DEFAULT_SIZE);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space_mem, 0, ram);
 
-    memory_region_init_ram(sram, "musicpal.sram", MP_SRAM_SIZE);
+    memory_region_init_ram(sram, NULL, "musicpal.sram", MP_SRAM_SIZE);
     vmstate_register_ram_global(sram);
     memory_region_add_subregion(address_space_mem, MP_SRAM_BASE, sram);
 
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
index c06c642..19be5fc 100644
--- a/hw/arm/omap1.c
+++ b/hw/arm/omap1.c
@@ -264,7 +264,7 @@
     omap_mpu_timer_reset(s);
     omap_timer_clk_setup(s);
 
-    memory_region_init_io(&s->iomem, &omap_mpu_timer_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &omap_mpu_timer_ops, s,
                           "omap-mpu-timer", 0x100);
 
     memory_region_add_subregion(system_memory, base, &s->iomem);
@@ -392,7 +392,7 @@
     omap_wd_timer_reset(s);
     omap_timer_clk_setup(&s->timer);
 
-    memory_region_init_io(&s->iomem, &omap_wd_timer_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &omap_wd_timer_ops, s,
                           "omap-wd-timer", 0x100);
     memory_region_add_subregion(memory, base, &s->iomem);
 
@@ -498,7 +498,7 @@
     omap_os_timer_reset(s);
     omap_timer_clk_setup(&s->timer);
 
-    memory_region_init_io(&s->iomem, &omap_os_timer_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &omap_os_timer_ops, s,
                           "omap-os-timer", 0x800);
     memory_region_add_subregion(memory, base, &s->iomem);
 
@@ -731,7 +731,7 @@
                 hwaddr base,
                 struct omap_mpu_state_s *mpu)
 {
-    memory_region_init_io(&mpu->ulpd_pm_iomem, &omap_ulpd_pm_ops, mpu,
+    memory_region_init_io(&mpu->ulpd_pm_iomem, NULL, &omap_ulpd_pm_ops, mpu,
                           "omap-ulpd-pm", 0x800);
     memory_region_add_subregion(system_memory, base, &mpu->ulpd_pm_iomem);
     omap_ulpd_pm_reset(mpu);
@@ -949,7 +949,7 @@
                 hwaddr base,
                 struct omap_mpu_state_s *mpu)
 {
-    memory_region_init_io(&mpu->pin_cfg_iomem, &omap_pin_cfg_ops, mpu,
+    memory_region_init_io(&mpu->pin_cfg_iomem, NULL, &omap_pin_cfg_ops, mpu,
                           "omap-pin-cfg", 0x800);
     memory_region_add_subregion(system_memory, base, &mpu->pin_cfg_iomem);
     omap_pin_cfg_reset(mpu);
@@ -1021,16 +1021,16 @@
 
 static void omap_id_init(MemoryRegion *memory, struct omap_mpu_state_s *mpu)
 {
-    memory_region_init_io(&mpu->id_iomem, &omap_id_ops, mpu,
+    memory_region_init_io(&mpu->id_iomem, NULL, &omap_id_ops, mpu,
                           "omap-id", 0x100000000ULL);
-    memory_region_init_alias(&mpu->id_iomem_e18, "omap-id-e18", &mpu->id_iomem,
+    memory_region_init_alias(&mpu->id_iomem_e18, NULL, "omap-id-e18", &mpu->id_iomem,
                              0xfffe1800, 0x800);
     memory_region_add_subregion(memory, 0xfffe1800, &mpu->id_iomem_e18);
-    memory_region_init_alias(&mpu->id_iomem_ed4, "omap-id-ed4", &mpu->id_iomem,
+    memory_region_init_alias(&mpu->id_iomem_ed4, NULL, "omap-id-ed4", &mpu->id_iomem,
                              0xfffed400, 0x100);
     memory_region_add_subregion(memory, 0xfffed400, &mpu->id_iomem_ed4);
     if (!cpu_is_omap15xx(mpu)) {
-        memory_region_init_alias(&mpu->id_iomem_ed4, "omap-id-e20",
+        memory_region_init_alias(&mpu->id_iomem_ed4, NULL, "omap-id-e20",
                                  &mpu->id_iomem, 0xfffe2000, 0x800);
         memory_region_add_subregion(memory, 0xfffe2000, &mpu->id_iomem_e20);
     }
@@ -1115,7 +1115,7 @@
 static void omap_mpui_init(MemoryRegion *memory, hwaddr base,
                 struct omap_mpu_state_s *mpu)
 {
-    memory_region_init_io(&mpu->mpui_iomem, &omap_mpui_ops, mpu,
+    memory_region_init_io(&mpu->mpui_iomem, NULL, &omap_mpui_ops, mpu,
                           "omap-mpui", 0x100);
     memory_region_add_subregion(memory, base, &mpu->mpui_iomem);
 
@@ -1227,7 +1227,7 @@
     s->abort = abort_irq;
     omap_tipb_bridge_reset(s);
 
-    memory_region_init_io(&s->iomem, &omap_tipb_bridge_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &omap_tipb_bridge_ops, s,
                           "omap-tipb-bridge", 0x100);
     memory_region_add_subregion(memory, base, &s->iomem);
 
@@ -1336,7 +1336,7 @@
 static void omap_tcmi_init(MemoryRegion *memory, hwaddr base,
                 struct omap_mpu_state_s *mpu)
 {
-    memory_region_init_io(&mpu->tcmi_iomem, &omap_tcmi_ops, mpu,
+    memory_region_init_io(&mpu->tcmi_iomem, NULL, &omap_tcmi_ops, mpu,
                           "omap-tcmi", 0x100);
     memory_region_add_subregion(memory, base, &mpu->tcmi_iomem);
     omap_tcmi_reset(mpu);
@@ -1418,7 +1418,7 @@
                            hwaddr base, omap_clk clk)
 {
     struct dpll_ctl_s *s = g_malloc0(sizeof(*s));
-    memory_region_init_io(&s->iomem, &omap_dpll_ops, s, "omap-dpll", 0x100);
+    memory_region_init_io(&s->iomem, NULL, &omap_dpll_ops, s, "omap-dpll", 0x100);
 
     s->dpll = clk;
     omap_dpll_reset(s);
@@ -1831,9 +1831,9 @@
 static void omap_clkm_init(MemoryRegion *memory, hwaddr mpu_base,
                 hwaddr dsp_base, struct omap_mpu_state_s *s)
 {
-    memory_region_init_io(&s->clkm_iomem, &omap_clkm_ops, s,
+    memory_region_init_io(&s->clkm_iomem, NULL, &omap_clkm_ops, s,
                           "omap-clkm", 0x100);
-    memory_region_init_io(&s->clkdsp_iomem, &omap_clkdsp_ops, s,
+    memory_region_init_io(&s->clkdsp_iomem, NULL, &omap_clkdsp_ops, s,
                           "omap-clkdsp", 0x1000);
 
     s->clkm.arm_idlect1 = 0x03ff;
@@ -2090,7 +2090,7 @@
     s->in = qemu_allocate_irqs(omap_mpuio_set, s, 16);
     omap_mpuio_reset(s);
 
-    memory_region_init_io(&s->iomem, &omap_mpuio_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &omap_mpuio_ops, s,
                           "omap-mpuio", 0x800);
     memory_region_add_subregion(memory, base, &s->iomem);
 
@@ -2281,7 +2281,7 @@
     s->txdrq = dma;
     omap_uwire_reset(s);
 
-    memory_region_init_io(&s->iomem, &omap_uwire_ops, s, "omap-uwire", 0x800);
+    memory_region_init_io(&s->iomem, NULL, &omap_uwire_ops, s, "omap-uwire", 0x800);
     memory_region_add_subregion(system_memory, base, &s->iomem);
 
     return s;
@@ -2393,7 +2393,7 @@
 
     omap_pwl_reset(s);
 
-    memory_region_init_io(&s->iomem, &omap_pwl_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &omap_pwl_ops, s,
                           "omap-pwl", 0x800);
     memory_region_add_subregion(system_memory, base, &s->iomem);
 
@@ -2500,7 +2500,7 @@
     s->clk = clk;
     omap_pwt_reset(s);
 
-    memory_region_init_io(&s->iomem, &omap_pwt_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &omap_pwt_ops, s,
                           "omap-pwt", 0x800);
     memory_region_add_subregion(system_memory, base, &s->iomem);
     return s;
@@ -2919,7 +2919,7 @@
 
     omap_rtc_reset(s);
 
-    memory_region_init_io(&s->iomem, &omap_rtc_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &omap_rtc_ops, s,
                           "omap-rtc", 0x800);
     memory_region_add_subregion(system_memory, base, &s->iomem);
 
@@ -3452,7 +3452,7 @@
     s->source_timer = qemu_new_timer_ns(vm_clock, omap_mcbsp_source_tick, s);
     omap_mcbsp_reset(s);
 
-    memory_region_init_io(&s->iomem, &omap_mcbsp_ops, s, "omap-mcbsp", 0x800);
+    memory_region_init_io(&s->iomem, NULL, &omap_mcbsp_ops, s, "omap-mcbsp", 0x800);
     memory_region_add_subregion(system_memory, base, &s->iomem);
 
     return s;
@@ -3627,7 +3627,7 @@
 
     omap_lpg_reset(s);
 
-    memory_region_init_io(&s->iomem, &omap_lpg_ops, s, "omap-lpg", 0x800);
+    memory_region_init_io(&s->iomem, NULL, &omap_lpg_ops, s, "omap-lpg", 0x800);
     memory_region_add_subregion(system_memory, base, &s->iomem);
 
     omap_clk_adduser(clk, qemu_allocate_irqs(omap_lpg_clk_update, s, 1)[0]);
@@ -3666,7 +3666,7 @@
 static void omap_setup_mpui_io(MemoryRegion *system_memory,
                                struct omap_mpu_state_s *mpu)
 {
-    memory_region_init_io(&mpu->mpui_io_iomem, &omap_mpui_io_ops, mpu,
+    memory_region_init_io(&mpu->mpui_io_iomem, NULL, &omap_mpui_io_ops, mpu,
                           "omap-mpui-io", 0x7fff);
     memory_region_add_subregion(system_memory, OMAP_MPUI_BASE,
                                 &mpu->mpui_io_iomem);
@@ -3747,7 +3747,7 @@
 
     for (; map->phys_dsp; map ++) {
         io = g_new(MemoryRegion, 1);
-        memory_region_init_alias(io, map->name,
+        memory_region_init_alias(io, NULL, map->name,
                                  system_memory, map->phys_mpu, map->size);
         memory_region_add_subregion(system_memory, map->phys_dsp, io);
     }
@@ -3851,10 +3851,10 @@
     omap_clk_init(s);
 
     /* Memory-mapped stuff */
-    memory_region_init_ram(&s->emiff_ram, "omap1.dram", s->sdram_size);
+    memory_region_init_ram(&s->emiff_ram, NULL, "omap1.dram", s->sdram_size);
     vmstate_register_ram_global(&s->emiff_ram);
     memory_region_add_subregion(system_memory, OMAP_EMIFF_BASE, &s->emiff_ram);
-    memory_region_init_ram(&s->imif_ram, "omap1.sram", s->sram_size);
+    memory_region_init_ram(&s->imif_ram, NULL, "omap1.sram", s->sram_size);
     vmstate_register_ram_global(&s->imif_ram);
     memory_region_add_subregion(system_memory, OMAP_IMIF_BASE, &s->imif_ram);
 
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
index 2ff4371..ec9610b 100644
--- a/hw/arm/omap2.c
+++ b/hw/arm/omap2.c
@@ -603,7 +603,7 @@
 
     AUD_register_card("OMAP EAC", &s->codec.card);
 
-    memory_region_init_io(&s->iomem, &omap_eac_ops, s, "omap.eac",
+    memory_region_init_io(&s->iomem, NULL, &omap_eac_ops, s, "omap.eac",
                           omap_l4_region_size(ta, 0));
     omap_l4_attach(ta, 0, &s->iomem);
 
@@ -791,11 +791,11 @@
 
     s->chr = chr ?: qemu_chr_new("null", "null", NULL);
 
-    memory_region_init_io(&s->iomem, &omap_sti_ops, s, "omap.sti",
+    memory_region_init_io(&s->iomem, NULL, &omap_sti_ops, s, "omap.sti",
                           omap_l4_region_size(ta, 0));
     omap_l4_attach(ta, 0, &s->iomem);
 
-    memory_region_init_io(&s->iomem_fifo, &omap_sti_fifo_ops, s,
+    memory_region_init_io(&s->iomem_fifo, NULL, &omap_sti_fifo_ops, s,
                           "omap.sti.fifo", 0x10000);
     memory_region_add_subregion(sysmem, channel_base, &s->iomem_fifo);
 
@@ -1809,9 +1809,9 @@
     s->mpu = mpu;
     omap_prcm_coldreset(s);
 
-    memory_region_init_io(&s->iomem0, &omap_prcm_ops, s, "omap.pcrm0",
+    memory_region_init_io(&s->iomem0, NULL, &omap_prcm_ops, s, "omap.pcrm0",
                           omap_l4_region_size(ta, 0));
-    memory_region_init_io(&s->iomem1, &omap_prcm_ops, s, "omap.pcrm1",
+    memory_region_init_io(&s->iomem1, NULL, &omap_prcm_ops, s, "omap.pcrm1",
                           omap_l4_region_size(ta, 1));
     omap_l4_attach(ta, 0, &s->iomem0);
     omap_l4_attach(ta, 1, &s->iomem1);
@@ -2185,7 +2185,7 @@
     s->mpu = mpu;
     omap_sysctl_reset(s);
 
-    memory_region_init_io(&s->iomem, &omap_sysctl_ops, s, "omap.sysctl",
+    memory_region_init_io(&s->iomem, NULL, &omap_sysctl_ops, s, "omap.sysctl",
                           omap_l4_region_size(ta, 0));
     omap_l4_attach(ta, 0, &s->iomem);
 
@@ -2267,10 +2267,10 @@
     omap_clk_init(s);
 
     /* Memory-mapped stuff */
-    memory_region_init_ram(&s->sdram, "omap2.dram", s->sdram_size);
+    memory_region_init_ram(&s->sdram, NULL, "omap2.dram", s->sdram_size);
     vmstate_register_ram_global(&s->sdram);
     memory_region_add_subregion(sysmem, OMAP2_Q2_BASE, &s->sdram);
-    memory_region_init_ram(&s->sram, "omap2.sram", s->sram_size);
+    memory_region_init_ram(&s->sram, NULL, "omap2.sram", s->sram_size);
     vmstate_register_ram_global(&s->sram);
     memory_region_add_subregion(sysmem, OMAP2_SRAM_BASE, &s->sram);
 
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
index e421ece..05b0353 100644
--- a/hw/arm/omap_sx1.c
+++ b/hw/arm/omap_sx1.c
@@ -120,23 +120,23 @@
     mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, args->cpu_model);
 
     /* External Flash (EMIFS) */
-    memory_region_init_ram(flash, "omap_sx1.flash0-0", flash_size);
+    memory_region_init_ram(flash, NULL, "omap_sx1.flash0-0", flash_size);
     vmstate_register_ram_global(flash);
     memory_region_set_readonly(flash, true);
     memory_region_add_subregion(address_space, OMAP_CS0_BASE, flash);
 
-    memory_region_init_io(&cs[0], &static_ops, &cs0val,
+    memory_region_init_io(&cs[0], NULL, &static_ops, &cs0val,
                           "sx1.cs0", OMAP_CS0_SIZE - flash_size);
     memory_region_add_subregion(address_space,
                                 OMAP_CS0_BASE + flash_size, &cs[0]);
 
 
-    memory_region_init_io(&cs[2], &static_ops, &cs2val,
+    memory_region_init_io(&cs[2], NULL, &static_ops, &cs2val,
                           "sx1.cs2", OMAP_CS2_SIZE);
     memory_region_add_subregion(address_space,
                                 OMAP_CS2_BASE, &cs[2]);
 
-    memory_region_init_io(&cs[3], &static_ops, &cs3val,
+    memory_region_init_io(&cs[3], NULL, &static_ops, &cs3val,
                           "sx1.cs3", OMAP_CS3_SIZE);
     memory_region_add_subregion(address_space,
                                 OMAP_CS2_BASE, &cs[3]);
@@ -162,12 +162,12 @@
 
     if ((version == 1) &&
             (dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
-        memory_region_init_ram(flash_1, "omap_sx1.flash1-0", flash1_size);
+        memory_region_init_ram(flash_1, NULL, "omap_sx1.flash1-0", flash1_size);
         vmstate_register_ram_global(flash_1);
         memory_region_set_readonly(flash_1, true);
         memory_region_add_subregion(address_space, OMAP_CS1_BASE, flash_1);
 
-        memory_region_init_io(&cs[1], &static_ops, &cs1val,
+        memory_region_init_io(&cs[1], NULL, &static_ops, &cs1val,
                               "sx1.cs1", OMAP_CS1_SIZE - flash1_size);
         memory_region_add_subregion(address_space,
                                 OMAP_CS1_BASE + flash1_size, &cs[1]);
@@ -182,7 +182,7 @@
         }
         fl_idx++;
     } else {
-        memory_region_init_io(&cs[1], &static_ops, &cs1val,
+        memory_region_init_io(&cs[1], NULL, &static_ops, &cs1val,
                               "sx1.cs1", OMAP_CS1_SIZE);
         memory_region_add_subregion(address_space,
                                 OMAP_CS1_BASE, &cs[1]);
diff --git a/hw/arm/palm.c b/hw/arm/palm.c
index b13d810..cdc3c3a 100644
--- a/hw/arm/palm.c
+++ b/hw/arm/palm.c
@@ -211,22 +211,22 @@
     mpu = omap310_mpu_init(address_space_mem, sdram_size, cpu_model);
 
     /* External Flash (EMIFS) */
-    memory_region_init_ram(flash, "palmte.flash", flash_size);
+    memory_region_init_ram(flash, NULL, "palmte.flash", flash_size);
     vmstate_register_ram_global(flash);
     memory_region_set_readonly(flash, true);
     memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE, flash);
 
-    memory_region_init_io(&cs[0], &static_ops, &cs0val, "palmte-cs0",
+    memory_region_init_io(&cs[0], NULL, &static_ops, &cs0val, "palmte-cs0",
                           OMAP_CS0_SIZE - flash_size);
     memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE + flash_size,
                                 &cs[0]);
-    memory_region_init_io(&cs[1], &static_ops, &cs1val, "palmte-cs1",
+    memory_region_init_io(&cs[1], NULL, &static_ops, &cs1val, "palmte-cs1",
                           OMAP_CS1_SIZE);
     memory_region_add_subregion(address_space_mem, OMAP_CS1_BASE, &cs[1]);
-    memory_region_init_io(&cs[2], &static_ops, &cs2val, "palmte-cs2",
+    memory_region_init_io(&cs[2], NULL, &static_ops, &cs2val, "palmte-cs2",
                           OMAP_CS2_SIZE);
     memory_region_add_subregion(address_space_mem, OMAP_CS2_BASE, &cs[2]);
-    memory_region_init_io(&cs[3], &static_ops, &cs3val, "palmte-cs3",
+    memory_region_init_io(&cs[3], NULL, &static_ops, &cs3val, "palmte-cs3",
                           OMAP_CS3_SIZE);
     memory_region_add_subregion(address_space_mem, OMAP_CS3_BASE, &cs[3]);
 
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 24b03a0..5a22654 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -764,7 +764,8 @@
 
     sysbus_init_irq(dev, &s->irq);
 
-    memory_region_init_io(&s->iomem, &pxa2xx_ssp_ops, s, "pxa2xx-ssp", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_ssp_ops, s,
+                          "pxa2xx-ssp", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     register_savevm(&dev->qdev, "pxa2xx_ssp", -1, 0,
                     pxa2xx_ssp_save, pxa2xx_ssp_load, s);
@@ -1131,7 +1132,8 @@
 
     sysbus_init_irq(dev, &s->rtc_irq);
 
-    memory_region_init_io(&s->iomem, &pxa2xx_rtc_ops, s, "pxa2xx-rtc", 0x10000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_rtc_ops, s,
+                          "pxa2xx-rtc", 0x10000);
     sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
@@ -1481,8 +1483,8 @@
 
     s->bus = i2c_init_bus(&dev->qdev, "i2c");
 
-    memory_region_init_io(&s->iomem, &pxa2xx_i2c_ops, s,
-                          "pxa2xx-i2x", s->region_size);
+    memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_i2c_ops, s,
+                          "pxa2xx-i2c", s->region_size);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
@@ -1720,7 +1722,7 @@
 
     pxa2xx_i2s_reset(s);
 
-    memory_region_init_io(&s->iomem, &pxa2xx_i2s_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &pxa2xx_i2s_ops, s,
                           "pxa2xx-i2s", 0x100000);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
@@ -1978,7 +1980,7 @@
 
     pxa2xx_fir_reset(s);
 
-    memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000);
+    memory_region_init_io(&s->iomem, NULL, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
     if (chr) {
@@ -2027,10 +2029,10 @@
     s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
 
     /* SDRAM & Internal Memory Storage */
-    memory_region_init_ram(&s->sdram, "pxa270.sdram", sdram_size);
+    memory_region_init_ram(&s->sdram, NULL, "pxa270.sdram", sdram_size);
     vmstate_register_ram_global(&s->sdram);
     memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram);
-    memory_region_init_ram(&s->internal, "pxa270.internal", 0x40000);
+    memory_region_init_ram(&s->internal, NULL, "pxa270.internal", 0x40000);
     vmstate_register_ram_global(&s->internal);
     memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
                                 &s->internal);
@@ -2083,7 +2085,7 @@
     s->cm_base = 0x41300000;
     s->cm_regs[CCCR >> 2] = 0x02000210;	/* 416.0 MHz */
     s->clkcfg = 0x00000009;		/* Turbo mode active */
-    memory_region_init_io(&s->cm_iomem, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000);
+    memory_region_init_io(&s->cm_iomem, NULL, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000);
     memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
     vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
 
@@ -2093,12 +2095,12 @@
     s->mm_regs[MDMRS >> 2] = 0x00020002;
     s->mm_regs[MDREFR >> 2] = 0x03ca4000;
     s->mm_regs[MECR >> 2] = 0x00000001;	/* Two PC Card sockets */
-    memory_region_init_io(&s->mm_iomem, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000);
+    memory_region_init_io(&s->mm_iomem, NULL, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000);
     memory_region_add_subregion(address_space, s->mm_base, &s->mm_iomem);
     vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
 
     s->pm_base = 0x40f00000;
-    memory_region_init_io(&s->pm_iomem, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100);
+    memory_region_init_io(&s->pm_iomem, NULL, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100);
     memory_region_add_subregion(address_space, s->pm_base, &s->pm_iomem);
     vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
 
@@ -2158,10 +2160,10 @@
     s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
 
     /* SDRAM & Internal Memory Storage */
-    memory_region_init_ram(&s->sdram, "pxa255.sdram", sdram_size);
+    memory_region_init_ram(&s->sdram, NULL, "pxa255.sdram", sdram_size);
     vmstate_register_ram_global(&s->sdram);
     memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram);
-    memory_region_init_ram(&s->internal, "pxa255.internal",
+    memory_region_init_ram(&s->internal, NULL, "pxa255.internal",
                            PXA2XX_INTERNAL_SIZE);
     vmstate_register_ram_global(&s->internal);
     memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
@@ -2214,7 +2216,7 @@
     s->cm_base = 0x41300000;
     s->cm_regs[CCCR >> 2] = 0x02000210;	/* 416.0 MHz */
     s->clkcfg = 0x00000009;		/* Turbo mode active */
-    memory_region_init_io(&s->cm_iomem, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000);
+    memory_region_init_io(&s->cm_iomem, NULL, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000);
     memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
     vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
 
@@ -2224,12 +2226,12 @@
     s->mm_regs[MDMRS >> 2] = 0x00020002;
     s->mm_regs[MDREFR >> 2] = 0x03ca4000;
     s->mm_regs[MECR >> 2] = 0x00000001;	/* Two PC Card sockets */
-    memory_region_init_io(&s->mm_iomem, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000);
+    memory_region_init_io(&s->mm_iomem, NULL, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000);
     memory_region_add_subregion(address_space, s->mm_base, &s->mm_iomem);
     vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
 
     s->pm_base = 0x40f00000;
-    memory_region_init_io(&s->pm_iomem, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100);
+    memory_region_init_io(&s->pm_iomem, NULL, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100);
     memory_region_add_subregion(address_space, s->pm_base, &s->pm_iomem);
     vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
 
diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c
index fa31575..f8c3ee0 100644
--- a/hw/arm/pxa2xx_gpio.c
+++ b/hw/arm/pxa2xx_gpio.c
@@ -283,7 +283,7 @@
     qdev_init_gpio_in(&dev->qdev, pxa2xx_gpio_set, s->lines);
     qdev_init_gpio_out(&dev->qdev, s->handler, s->lines);
 
-    memory_region_init_io(&s->iomem, &pxa_gpio_ops, s, "pxa2xx-gpio", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &pxa_gpio_ops, s, "pxa2xx-gpio", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq0);
     sysbus_init_irq(dev, &s->irq1);
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
index 835d07c..8929b6d 100644
--- a/hw/arm/pxa2xx_pic.c
+++ b/hw/arm/pxa2xx_pic.c
@@ -278,7 +278,7 @@
     qdev_init_gpio_in(dev, pxa2xx_pic_set_irq, PXA2XX_PIC_SRCS);
 
     /* Enable IC memory-mapped registers access.  */
-    memory_region_init_io(&s->iomem, &pxa2xx_pic_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_pic_ops, s,
                           "pxa2xx-pic", 0x00100000);
     sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
index d6f47bf..b596256 100644
--- a/hw/arm/realview.c
+++ b/hw/arm/realview.c
@@ -59,7 +59,7 @@
     qemu_irq *irqp;
     qemu_irq pic[64];
     qemu_irq mmc_irq[2];
-    PCIBus *pci_bus;
+    PCIBus *pci_bus = NULL;
     NICInfo *nd;
     i2c_bus *i2c;
     int n;
@@ -114,18 +114,18 @@
         /* Core tile RAM.  */
         low_ram_size = ram_size - 0x20000000;
         ram_size = 0x20000000;
-        memory_region_init_ram(ram_lo, "realview.lowmem", low_ram_size);
+        memory_region_init_ram(ram_lo, NULL, "realview.lowmem", low_ram_size);
         vmstate_register_ram_global(ram_lo);
         memory_region_add_subregion(sysmem, 0x20000000, ram_lo);
     }
 
-    memory_region_init_ram(ram_hi, "realview.highmem", ram_size);
+    memory_region_init_ram(ram_hi, NULL, "realview.highmem", ram_size);
     vmstate_register_ram_global(ram_hi);
     low_ram_size = ram_size;
     if (low_ram_size > 0x10000000)
       low_ram_size = 0x10000000;
     /* SDRAM at address zero.  */
-    memory_region_init_alias(ram_alias, "realview.alias",
+    memory_region_init_alias(ram_alias, NULL, "realview.alias",
                              ram_hi, 0, low_ram_size);
     memory_region_add_subregion(sysmem, 0, ram_alias);
     if (is_pb) {
@@ -250,7 +250,9 @@
             }
             done_nic = 1;
         } else {
-            pci_nic_init_nofail(nd, "rtl8139", NULL);
+            if (pci_bus) {
+                pci_nic_init_nofail(nd, pci_bus, "rtl8139", NULL);
+            }
         }
     }
 
@@ -318,7 +320,7 @@
        startup code.  I guess this works on real hardware because the
        BootROM happens to be in ROM/flash or in memory that isn't clobbered
        until after Linux boots the secondary CPUs.  */
-    memory_region_init_ram(ram_hack, "realview.hack", 0x1000);
+    memory_region_init_ram(ram_hack, NULL, "realview.hack", 0x1000);
     vmstate_register_ram_global(ram_hack);
     memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack);
 
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index b5ed109..593b75e 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -169,7 +169,7 @@
     nand = drive_get(IF_MTD, 0, 0);
     s->nand = nand_init(nand ? nand->bdrv : NULL, s->manf_id, s->chip_id);
 
-    memory_region_init_io(&s->iomem, &sl_ops, s, "sl", 0x40);
+    memory_region_init_io(&s->iomem, OBJECT(s), &sl_ops, s, "sl", 0x40);
     sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
@@ -896,7 +896,7 @@
 
     sl_flash_register(mpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
 
-    memory_region_init_ram(rom, "spitz.rom", SPITZ_ROM);
+    memory_region_init_ram(rom, NULL, "spitz.rom", SPITZ_ROM);
     vmstate_register_ram_global(rom);
     memory_region_set_readonly(rom, true);
     memory_region_add_subregion(address_space_mem, 0, rom);
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
index 2b61e3c..a2b6b17 100644
--- a/hw/arm/stellaris.c
+++ b/hw/arm/stellaris.c
@@ -307,7 +307,7 @@
     sysbus_init_irq(dev, &s->irq);
     qdev_init_gpio_out(&dev->qdev, &s->trigger, 1);
 
-    memory_region_init_io(&s->iomem, &gptm_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &gptm_ops, s,
                           "gptm", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
 
@@ -669,7 +669,7 @@
     s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16);
     s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16);
 
-    memory_region_init_io(&s->iomem, &ssys_ops, s, "ssys", 0x00001000);
+    memory_region_init_io(&s->iomem, NULL, &ssys_ops, s, "ssys", 0x00001000);
     memory_region_add_subregion(get_system_memory(), base, &s->iomem);
     ssys_reset(s);
     vmstate_register(NULL, -1, &vmstate_stellaris_sys, s);
@@ -862,7 +862,7 @@
     bus = i2c_init_bus(&dev->qdev, "i2c");
     s->bus = bus;
 
-    memory_region_init_io(&s->iomem, &stellaris_i2c_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &stellaris_i2c_ops, s,
                           "i2c", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     /* ??? For now we only implement the master interface.  */
@@ -1145,7 +1145,7 @@
         sysbus_init_irq(dev, &s->irq[n]);
     }
 
-    memory_region_init_io(&s->iomem, &stellaris_adc_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &stellaris_adc_ops, s,
                           "adc", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     stellaris_adc_reset(s);
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
index 4d49306..feaaf45 100644
--- a/hw/arm/strongarm.c
+++ b/hw/arm/strongarm.c
@@ -173,7 +173,8 @@
     StrongARMPICState *s = FROM_SYSBUS(StrongARMPICState, dev);
 
     qdev_init_gpio_in(&dev->qdev, strongarm_pic_set_irq, SA_PIC_SRCS);
-    memory_region_init_io(&s->iomem, &strongarm_pic_ops, s, "pic", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_pic_ops, s,
+                          "pic", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     sysbus_init_irq(dev, &s->fiq);
@@ -383,7 +384,8 @@
     sysbus_init_irq(dev, &s->rtc_irq);
     sysbus_init_irq(dev, &s->rtc_hz_irq);
 
-    memory_region_init_io(&s->iomem, &strongarm_rtc_ops, s, "rtc", 0x10000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_rtc_ops, s,
+                          "rtc", 0x10000);
     sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
@@ -637,7 +639,8 @@
     qdev_init_gpio_in(&dev->qdev, strongarm_gpio_set, 28);
     qdev_init_gpio_out(&dev->qdev, s->handler, 28);
 
-    memory_region_init_io(&s->iomem, &strongarm_gpio_ops, s, "gpio", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_gpio_ops, s,
+                          "gpio", 0x1000);
 
     sysbus_init_mmio(dev, &s->iomem);
     for (i = 0; i < 11; i++) {
@@ -808,7 +811,8 @@
     qdev_init_gpio_in(&dev->qdev, strongarm_ppc_set, 22);
     qdev_init_gpio_out(&dev->qdev, s->handler, 22);
 
-    memory_region_init_io(&s->iomem, &strongarm_ppc_ops, s, "ppc", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_ppc_ops, s,
+                          "ppc", 0x1000);
 
     sysbus_init_mmio(dev, &s->iomem);
 
@@ -1204,7 +1208,8 @@
 {
     StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev);
 
-    memory_region_init_io(&s->iomem, &strongarm_uart_ops, s, "uart", 0x10000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_uart_ops, s,
+                          "uart", 0x10000);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
@@ -1496,7 +1501,8 @@
 
     sysbus_init_irq(dev, &s->irq);
 
-    memory_region_init_io(&s->iomem, &strongarm_ssp_ops, s, "ssp", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_ssp_ops, s,
+                          "ssp", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
 
     s->bus = ssi_create_bus(&dev->qdev, "ssi");
@@ -1571,7 +1577,7 @@
         exit(1);
     }
 
-    memory_region_init_ram(&s->sdram, "strongarm.sdram", sdram_size);
+    memory_region_init_ram(&s->sdram, NULL, "strongarm.sdram", sdram_size);
     vmstate_register_ram_global(&s->sdram);
     memory_region_add_subregion(sysmem, SA_SDCS0, &s->sdram);
 
diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
index 47818a5..47d1f4f 100644
--- a/hw/arm/tosa.c
+++ b/hw/arm/tosa.c
@@ -222,7 +222,7 @@
 
     mpu = pxa255_init(address_space_mem, tosa_binfo.ram_size);
 
-    memory_region_init_ram(rom, "tosa.rom", TOSA_ROM);
+    memory_region_init_ram(rom, NULL, "tosa.rom", TOSA_ROM);
     vmstate_register_ram_global(rom);
     memory_region_set_readonly(rom, true);
     memory_region_add_subregion(address_space_mem, 0, rom);
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
index 753757e..725f60f 100644
--- a/hw/arm/versatilepb.c
+++ b/hw/arm/versatilepb.c
@@ -154,7 +154,8 @@
         sysbus_init_irq(dev, &s->parent[i]);
     }
     s->irq = 31;
-    memory_region_init_io(&s->iomem, &vpb_sic_ops, s, "vpb-sic", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &vpb_sic_ops, s,
+                          "vpb-sic", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
@@ -193,7 +194,7 @@
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    memory_region_init_ram(ram, "versatile.ram", args->ram_size);
+    memory_region_init_ram(ram, NULL, "versatile.ram", args->ram_size);
     vmstate_register_ram_global(ram);
     /* ??? RAM should repeat to fill physical memory space.  */
     /* SDRAM at address zero.  */
@@ -244,7 +245,7 @@
             smc91c111_init(nd, 0x10010000, sic[25]);
             done_smc = 1;
         } else {
-            pci_nic_init_nofail(nd, "rtl8139", NULL);
+            pci_nic_init_nofail(nd, pci_bus, "rtl8139", NULL);
         }
     }
     if (usb_enabled(false)) {
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index a077c62..710413e 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -196,7 +196,7 @@
         exit(1);
     }
 
-    memory_region_init_ram(ram, "vexpress.highmem", ram_size);
+    memory_region_init_ram(ram, NULL, "vexpress.highmem", ram_size);
     vmstate_register_ram_global(ram);
     low_ram_size = ram_size;
     if (low_ram_size > 0x4000000) {
@@ -206,7 +206,7 @@
      * address space should in theory be remappable to various
      * things including ROM or RAM; we always map the RAM there.
      */
-    memory_region_init_alias(lowram, "vexpress.lowmem", ram, 0, low_ram_size);
+    memory_region_init_alias(lowram, NULL, "vexpress.lowmem", ram, 0, low_ram_size);
     memory_region_add_subregion(sysmem, 0x0, lowram);
     memory_region_add_subregion(sysmem, 0x60000000, ram);
 
@@ -323,7 +323,7 @@
         }
     }
 
-    memory_region_init_ram(ram, "vexpress.highmem", ram_size);
+    memory_region_init_ram(ram, NULL, "vexpress.highmem", ram_size);
     vmstate_register_ram_global(ram);
     /* RAM is from 0x80000000 upwards; there is no low-memory alias for it. */
     memory_region_add_subregion(sysmem, 0x80000000, ram);
@@ -357,7 +357,7 @@
     /* 0x2b060000: SP805 watchdog: not modelled */
     /* 0x2b0a0000: PL341 dynamic memory controller: not modelled */
     /* 0x2e000000: system SRAM */
-    memory_region_init_ram(sram, "vexpress.a15sram", 0x10000);
+    memory_region_init_ram(sram, NULL, "vexpress.a15sram", 0x10000);
     vmstate_register_ram_global(sram);
     memory_region_add_subregion(sysmem, 0x2e000000, sram);
 
@@ -491,12 +491,12 @@
     }
 
     sram_size = 0x2000000;
-    memory_region_init_ram(sram, "vexpress.sram", sram_size);
+    memory_region_init_ram(sram, NULL, "vexpress.sram", sram_size);
     vmstate_register_ram_global(sram);
     memory_region_add_subregion(sysmem, map[VE_SRAM], sram);
 
     vram_size = 0x800000;
-    memory_region_init_ram(vram, "vexpress.vram", vram_size);
+    memory_region_init_ram(vram, NULL, "vexpress.vram", vram_size);
     vmstate_register_ram_global(vram);
     memory_region_add_subregion(sysmem, map[VE_VIDEORAM], vram);
 
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 4602a6f..0dc0871 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -132,12 +132,12 @@
     }
 
     /* DDR remapped to address zero.  */
-    memory_region_init_ram(ext_ram, "zynq.ext_ram", ram_size);
+    memory_region_init_ram(ext_ram, NULL, "zynq.ext_ram", ram_size);
     vmstate_register_ram_global(ext_ram);
     memory_region_add_subregion(address_space_mem, 0, ext_ram);
 
     /* 256K of on-chip memory */
-    memory_region_init_ram(ocm_ram, "zynq.ocm_ram", 256 << 10);
+    memory_region_init_ram(ocm_ram, NULL, "zynq.ocm_ram", 256 << 10);
     vmstate_register_ram_global(ocm_ram);
     memory_region_add_subregion(address_space_mem, 0xFFFC0000, ocm_ram);
 
diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c
index baf138b..365b2f1 100644
--- a/hw/audio/ac97.c
+++ b/hw/audio/ac97.c
@@ -1378,8 +1378,10 @@
     c[PCI_INTERRUPT_LINE] = 0x00;      /* intr_ln interrupt line rw */
     c[PCI_INTERRUPT_PIN] = 0x01;      /* intr_pn interrupt pin ro */
 
-    memory_region_init_io (&s->io_nam, &ac97_io_nam_ops, s, "ac97-nam", 1024);
-    memory_region_init_io (&s->io_nabm, &ac97_io_nabm_ops, s, "ac97-nabm", 256);
+    memory_region_init_io (&s->io_nam, OBJECT(s), &ac97_io_nam_ops, s,
+                           "ac97-nam", 1024);
+    memory_region_init_io (&s->io_nabm, OBJECT(s), &ac97_io_nabm_ops, s,
+                           "ac97-nabm", 256);
     pci_register_bar (&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nam);
     pci_register_bar (&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nabm);
     qemu_register_reset (ac97_on_reset, s);
diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c
index 6a7d377..f72e6ee 100644
--- a/hw/audio/adlib.c
+++ b/hw/audio/adlib.c
@@ -283,9 +283,17 @@
     AUD_remove_card (&s->card);
 }
 
+static MemoryRegionPortio adlib_portio_list[] = {
+    { 0x388, 4, 1, .read = adlib_read, .write = adlib_write, },
+    { 0, 4, 1, .read = adlib_read, .write = adlib_write, },
+    { 0, 2, 1, .read = adlib_read, .write = adlib_write, },
+    PORTIO_END_OF_LIST(),
+};
+
 static void adlib_realizefn (DeviceState *dev, Error **errp)
 {
     AdlibState *s = ADLIB(dev);
+    PortioList *port_list = g_new(PortioList, 1);
     struct audsettings as;
 
     if (glob_adlib) {
@@ -339,14 +347,10 @@
     s->samples = AUD_get_buffer_size_out (s->voice) >> SHIFT;
     s->mixbuf = g_malloc0 (s->samples << SHIFT);
 
-    register_ioport_read (0x388, 4, 1, adlib_read, s);
-    register_ioport_write (0x388, 4, 1, adlib_write, s);
-
-    register_ioport_read (s->port, 4, 1, adlib_read, s);
-    register_ioport_write (s->port, 4, 1, adlib_write, s);
-
-    register_ioport_read (s->port + 8, 2, 1, adlib_read, s);
-    register_ioport_write (s->port + 8, 2, 1, adlib_write, s);
+    adlib_portio_list[1].offset = s->port;
+    adlib_portio_list[2].offset = s->port + 8;
+    portio_list_init (port_list, OBJECT(s), adlib_portio_list, s, "adlib");
+    portio_list_add (port_list, isa_address_space_io(&s->parent_obj), 0);
 }
 
 static Property adlib_properties[] = {
diff --git a/hw/audio/cs4231.c b/hw/audio/cs4231.c
index 2975336..fabe9e6 100644
--- a/hw/audio/cs4231.c
+++ b/hw/audio/cs4231.c
@@ -144,7 +144,8 @@
 {
     CSState *s = FROM_SYSBUS(CSState, dev);
 
-    memory_region_init_io(&s->iomem, &cs_mem_ops, s, "cs4321", CS_SIZE);
+    memory_region_init_io(&s->iomem, OBJECT(s), &cs_mem_ops, s, "cs4321",
+                          CS_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c
index 605dad4..7365c3c 100644
--- a/hw/audio/cs4231a.c
+++ b/hw/audio/cs4231a.c
@@ -648,7 +648,8 @@
 {
     CSState *s = CS4231A (obj);
 
-    memory_region_init_io (&s->ioports, &cs_ioport_ops, s, "cs4231a", 4);
+    memory_region_init_io (&s->ioports, OBJECT(s), &cs_ioport_ops, s,
+                           "cs4231a", 4);
 }
 
 static void cs4231a_realizefn (DeviceState *dev, Error **errp)
diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c
index c1cd169..f2c40da 100644
--- a/hw/audio/es1370.c
+++ b/hw/audio/es1370.c
@@ -1035,7 +1035,7 @@
     c[PCI_MIN_GNT] = 0x0c;
     c[PCI_MAX_LAT] = 0x80;
 
-    memory_region_init_io (&s->io, &es1370_io_ops, s, "es1370", 256);
+    memory_region_init_io (&s->io, OBJECT(s), &es1370_io_ops, s, "es1370", 256);
     pci_register_bar (&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
     qemu_register_reset (es1370_on_reset, s);
 
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
index 3ac90d5..58984dc 100644
--- a/hw/audio/intel-hda.c
+++ b/hw/audio/intel-hda.c
@@ -1135,7 +1135,7 @@
     /* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */
     conf[0x40] = 0x01;
 
-    memory_region_init_io(&d->mmio, &intel_hda_mmio_ops, d,
+    memory_region_init_io(&d->mmio, OBJECT(d), &intel_hda_mmio_ops, d,
                           "intel-hda", 0x4000);
     pci_register_bar(&d->pci, 0, 0, &d->mmio);
     if (d->msi) {
diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c
index c5d88a7..b40ea43 100644
--- a/hw/audio/marvell_88w8618.c
+++ b/hw/audio/marvell_88w8618.c
@@ -244,7 +244,7 @@
 
     wm8750_data_req_set(s->wm, mv88w8618_audio_callback, s);
 
-    memory_region_init_io(&s->iomem, &mv88w8618_audio_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &mv88w8618_audio_ops, s,
                           "audio", MP_AUDIO_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
 
diff --git a/hw/audio/milkymist-ac97.c b/hw/audio/milkymist-ac97.c
index e08e9dc..133de4e 100644
--- a/hw/audio/milkymist-ac97.c
+++ b/hw/audio/milkymist-ac97.c
@@ -300,7 +300,7 @@
     s->voice_out = AUD_open_out(&s->card, s->voice_out,
             "mm_ac97.out", s, ac97_out_cb, &as);
 
-    memory_region_init_io(&s->regs_region, &ac97_mmio_ops, s,
+    memory_region_init_io(&s->regs_region, OBJECT(s), &ac97_mmio_ops, s,
             "milkymist-ac97", R_MAX * 4);
     sysbus_init_mmio(dev, &s->regs_region);
 
diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c
index 5dde0e7..7ad59a1 100644
--- a/hw/audio/pcspk.c
+++ b/hw/audio/pcspk.c
@@ -167,7 +167,7 @@
 {
     PCSpkState *s = PC_SPEAKER(obj);
 
-    memory_region_init_io(&s->ioport, &pcspk_io_ops, s, "elcr", 1);
+    memory_region_init_io(&s->ioport, OBJECT(s), &pcspk_io_ops, s, "elcr", 1);
 }
 
 static void pcspk_realizefn(DeviceState *dev, Error **errp)
diff --git a/hw/audio/pl041.c b/hw/audio/pl041.c
index 653ab4f..7d331b9 100644
--- a/hw/audio/pl041.c
+++ b/hw/audio/pl041.c
@@ -543,7 +543,7 @@
     }
 
     /* Connect the device to the sysbus */
-    memory_region_init_io(&s->iomem, &pl041_ops, s, "pl041", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &pl041_ops, s, "pl041", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index 930f191..cdc00e5 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -2149,7 +2149,8 @@
     FDCtrl *fdctrl = &sys->state;
     int ret;
 
-    memory_region_init_io(&fdctrl->iomem, &fdctrl_mem_ops, fdctrl, "fdc", 0x08);
+    memory_region_init_io(&fdctrl->iomem, OBJECT(sys), &fdctrl_mem_ops, fdctrl,
+                          "fdc", 0x08);
     sysbus_init_mmio(dev, &fdctrl->iomem);
     sysbus_init_irq(dev, &fdctrl->irq);
     qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1);
@@ -2165,8 +2166,8 @@
 {
     FDCtrl *fdctrl = &(FROM_SYSBUS(FDCtrlSysBus, dev)->state);
 
-    memory_region_init_io(&fdctrl->iomem, &fdctrl_mem_strict_ops, fdctrl,
-                          "fdctrl", 0x08);
+    memory_region_init_io(&fdctrl->iomem, OBJECT(dev), &fdctrl_mem_strict_ops,
+                          fdctrl, "fdctrl", 0x08);
     sysbus_init_mmio(dev, &fdctrl->iomem);
     sysbus_init_irq(dev, &fdctrl->irq);
     qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1);
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 58b0d91..f15f04a 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -777,7 +777,8 @@
     n->sq = g_malloc0(sizeof(*n->sq)*n->num_queues);
     n->cq = g_malloc0(sizeof(*n->cq)*n->num_queues);
 
-    memory_region_init_io(&n->iomem, &nvme_mmio_ops, n, "nvme", n->reg_size);
+    memory_region_init_io(&n->iomem, OBJECT(n), &nvme_mmio_ops, n,
+                          "nvme", n->reg_size);
     pci_register_bar(&n->parent_obj, 0,
         PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64,
         &n->iomem);
diff --git a/hw/block/onenand.c b/hw/block/onenand.c
index 8b511a7..2776f64 100644
--- a/hw/block/onenand.c
+++ b/hw/block/onenand.c
@@ -113,9 +113,10 @@
     /* XXX: We should use IO_MEM_ROMD but we broke it earlier...
      * Both 0x0000 ... 0x01ff and 0x8000 ... 0x800f can be used to
      * write boot commands.  Also take note of the BWPS bit.  */
-    memory_region_init(&s->container, "onenand", 0x10000 << s->shift);
+    memory_region_init(&s->container, OBJECT(s), "onenand",
+                       0x10000 << s->shift);
     memory_region_add_subregion(&s->container, 0, &s->iomem);
-    memory_region_init_alias(&s->mapped_ram, "onenand-mapped-ram",
+    memory_region_init_alias(&s->mapped_ram, OBJECT(s), "onenand-mapped-ram",
                              &s->ram, 0x0200 << s->shift,
                              0xbe00 << s->shift);
     memory_region_add_subregion_overlap(&s->container,
@@ -768,7 +769,7 @@
     s->blockwp = g_malloc(s->blocks);
     s->density_mask = (s->id.dev & 0x08)
         ? (1 << (6 + ((s->id.dev >> 4) & 7))) : 0;
-    memory_region_init_io(&s->iomem, &onenand_ops, s, "onenand",
+    memory_region_init_io(&s->iomem, OBJECT(s), &onenand_ops, s, "onenand",
                           0x10000 << s->shift);
     if (!s->bdrv) {
         s->image = memset(g_malloc(size + (size >> 5)),
@@ -782,7 +783,8 @@
     }
     s->otp = memset(g_malloc((64 + 2) << PAGE_SHIFT),
                     0xff, (64 + 2) << PAGE_SHIFT);
-    memory_region_init_ram(&s->ram, "onenand.ram", 0xc000 << s->shift);
+    memory_region_init_ram(&s->ram, OBJECT(s), "onenand.ram",
+                           0xc000 << s->shift);
     vmstate_register_ram_global(&s->ram);
     ram = memory_region_get_ram_ptr(&s->ram);
     s->boot[0] = ram + (0x0000 << s->shift);
diff --git a/hw/block/pc_sysfw.c b/hw/block/pc_sysfw.c
index 412d1b0..0669410 100644
--- a/hw/block/pc_sysfw.c
+++ b/hw/block/pc_sysfw.c
@@ -59,7 +59,7 @@
         isa_bios_size = 128 * 1024;
     }
     isa_bios = g_malloc(sizeof(*isa_bios));
-    memory_region_init_ram(isa_bios, "isa-bios", isa_bios_size);
+    memory_region_init_ram(isa_bios, NULL, "isa-bios", isa_bios_size);
     vmstate_register_ram_global(isa_bios);
     memory_region_add_subregion_overlap(rom_memory,
                                         0x100000 - isa_bios_size,
@@ -162,7 +162,7 @@
         goto bios_error;
     }
     bios = g_malloc(sizeof(*bios));
-    memory_region_init_ram(bios, "pc.bios", bios_size);
+    memory_region_init_ram(bios, NULL, "pc.bios", bios_size);
     vmstate_register_ram_global(bios);
     if (!isapc_ram_fw) {
         memory_region_set_readonly(bios, true);
@@ -183,7 +183,7 @@
         isa_bios_size = 128 * 1024;
     }
     isa_bios = g_malloc(sizeof(*isa_bios));
-    memory_region_init_alias(isa_bios, "isa-bios", bios,
+    memory_region_init_alias(isa_bios, NULL, "isa-bios", bios,
                              bios_size - isa_bios_size, isa_bios_size);
     memory_region_add_subregion_overlap(rom_memory,
                                         0x100000 - isa_bios_size,
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 63d7c99..6898a25 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -579,7 +579,8 @@
 #endif
 
     memory_region_init_rom_device(
-        &pfl->mem, pfl->be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl,
+        &pfl->mem, OBJECT(dev),
+        pfl->be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl,
         pfl->name, total_len);
     vmstate_register_ram(&pfl->mem, DEVICE(pfl));
     pfl->storage = memory_region_get_ram_ptr(&pfl->mem);
diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
index 5f25246..d6cd3da 100644
--- a/hw/block/pflash_cfi02.c
+++ b/hw/block/pflash_cfi02.c
@@ -100,11 +100,11 @@
     unsigned i;
     hwaddr size = memory_region_size(&pfl->orig_mem);
 
-    memory_region_init(&pfl->mem, "pflash", pfl->mappings * size);
+    memory_region_init(&pfl->mem, OBJECT(pfl), "pflash", pfl->mappings * size);
     pfl->mem_mappings = g_new(MemoryRegion, pfl->mappings);
     for (i = 0; i < pfl->mappings; ++i) {
-        memory_region_init_alias(&pfl->mem_mappings[i], "pflash-alias",
-                                 &pfl->orig_mem, 0, size);
+        memory_region_init_alias(&pfl->mem_mappings[i], OBJECT(pfl),
+                                 "pflash-alias", &pfl->orig_mem, 0, size);
         memory_region_add_subregion(&pfl->mem, i * size, &pfl->mem_mappings[i]);
     }
 }
@@ -600,7 +600,7 @@
         return NULL;
 #endif
 
-    memory_region_init_rom_device(&pfl->orig_mem, pfl->be ?
+    memory_region_init_rom_device(&pfl->orig_mem, OBJECT(pfl), pfl->be ?
                                   &pflash_cfi02_ops_be : &pflash_cfi02_ops_le,
                                   pfl, pfl->name, chip_len);
     vmstate_register_ram(&pfl->orig_mem, DEVICE(pfl));
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index 205e125..131370a 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -442,7 +442,7 @@
 {
     UartState *s = FROM_SYSBUS(UartState, dev);
 
-    memory_region_init_io(&s->iomem, &uart_ops, s, "uart", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &uart_ops, s, "uart", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c
index f254841..03db12f 100644
--- a/hw/char/debugcon.c
+++ b/hw/char/debugcon.c
@@ -103,7 +103,7 @@
         error_propagate(errp, err);
         return;
     }
-    memory_region_init_io(&s->io, &debugcon_ops, s,
+    memory_region_init_io(&s->io, OBJECT(dev), &debugcon_ops, s,
                           TYPE_ISA_DEBUGCON_DEVICE, 1);
     memory_region_add_subregion(isa_address_space_io(d),
                                 isa->iobase, &s->io);
diff --git a/hw/char/escc.c b/hw/char/escc.c
index c2cb07f..4c42198 100644
--- a/hw/char/escc.c
+++ b/hw/char/escc.c
@@ -96,14 +96,14 @@
     uint8_t rx, tx;
 } ChannelState;
 
-struct SerialState {
+typedef struct ESCCState {
     SysBusDevice busdev;
     struct ChannelState chn[2];
     uint32_t it_shift;
     MemoryRegion mmio;
     uint32_t disabled;
     uint32_t frequency;
-};
+} ESCCState;
 
 #define SERIAL_CTRL 0
 #define SERIAL_DATA 1
@@ -309,7 +309,7 @@
 
 static void escc_reset(DeviceState *d)
 {
-    SerialState *s = container_of(d, SerialState, busdev.qdev);
+    ESCCState *s = container_of(d, ESCCState, busdev.qdev);
 
     escc_reset_chn(&s->chn[0]);
     escc_reset_chn(&s->chn[1]);
@@ -466,7 +466,7 @@
 static void escc_mem_write(void *opaque, hwaddr addr,
                            uint64_t val, unsigned size)
 {
-    SerialState *serial = opaque;
+    ESCCState *serial = opaque;
     ChannelState *s;
     uint32_t saddr;
     int newreg, channel;
@@ -568,7 +568,7 @@
 static uint64_t escc_mem_read(void *opaque, hwaddr addr,
                               unsigned size)
 {
-    SerialState *serial = opaque;
+    ESCCState *serial = opaque;
     ChannelState *s;
     uint32_t saddr;
     uint32_t ret;
@@ -677,7 +677,7 @@
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
-        VMSTATE_STRUCT_ARRAY(chn, SerialState, 2, 2, vmstate_escc_chn,
+        VMSTATE_STRUCT_ARRAY(chn, ESCCState, 2, 2, vmstate_escc_chn,
                              ChannelState),
         VMSTATE_END_OF_LIST()
     }
@@ -689,7 +689,7 @@
 {
     DeviceState *dev;
     SysBusDevice *s;
-    SerialState *d;
+    ESCCState *d;
 
     dev = qdev_create(NULL, "escc");
     qdev_prop_set_uint32(dev, "disabled", 0);
@@ -707,7 +707,7 @@
         sysbus_mmio_map(s, 0, base);
     }
 
-    d = FROM_SYSBUS(SerialState, s);
+    d = FROM_SYSBUS(ESCCState, s);
     return &d->mmio;
 }
 
@@ -869,7 +869,7 @@
 
 static int escc_init1(SysBusDevice *dev)
 {
-    SerialState *s = FROM_SYSBUS(SerialState, dev);
+    ESCCState *s = FROM_SYSBUS(ESCCState, dev);
     unsigned int i;
 
     s->chn[0].disabled = s->disabled;
@@ -886,7 +886,7 @@
     s->chn[0].otherchn = &s->chn[1];
     s->chn[1].otherchn = &s->chn[0];
 
-    memory_region_init_io(&s->mmio, &escc_mem_ops, s, "escc",
+    memory_region_init_io(&s->mmio, OBJECT(s), &escc_mem_ops, s, "escc",
                           ESCC_SIZE << s->it_shift);
     sysbus_init_mmio(dev, &s->mmio);
 
@@ -902,13 +902,13 @@
 }
 
 static Property escc_properties[] = {
-    DEFINE_PROP_UINT32("frequency", SerialState, frequency,   0),
-    DEFINE_PROP_UINT32("it_shift",  SerialState, it_shift,    0),
-    DEFINE_PROP_UINT32("disabled",  SerialState, disabled,    0),
-    DEFINE_PROP_UINT32("chnBtype",  SerialState, chn[0].type, 0),
-    DEFINE_PROP_UINT32("chnAtype",  SerialState, chn[1].type, 0),
-    DEFINE_PROP_CHR("chrB", SerialState, chn[0].chr),
-    DEFINE_PROP_CHR("chrA", SerialState, chn[1].chr),
+    DEFINE_PROP_UINT32("frequency", ESCCState, frequency,   0),
+    DEFINE_PROP_UINT32("it_shift",  ESCCState, it_shift,    0),
+    DEFINE_PROP_UINT32("disabled",  ESCCState, disabled,    0),
+    DEFINE_PROP_UINT32("chnBtype",  ESCCState, chn[0].type, 0),
+    DEFINE_PROP_UINT32("chnAtype",  ESCCState, chn[1].type, 0),
+    DEFINE_PROP_CHR("chrB", ESCCState, chn[0].chr),
+    DEFINE_PROP_CHR("chrA", ESCCState, chn[1].chr),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -926,7 +926,7 @@
 static const TypeInfo escc_info = {
     .name          = "escc",
     .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(SerialState),
+    .instance_size = sizeof(ESCCState),
     .class_init    = escc_class_init,
 };
 
diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c
index 11820f5..d19af00 100644
--- a/hw/char/etraxfs_ser.c
+++ b/hw/char/etraxfs_ser.c
@@ -211,7 +211,8 @@
     struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
 
     sysbus_init_irq(dev, &s->irq);
-    memory_region_init_io(&s->mmio, &ser_ops, s, "etraxfs-serial", R_MAX * 4);
+    memory_region_init_io(&s->mmio, OBJECT(s), &ser_ops, s,
+                          "etraxfs-serial", R_MAX * 4);
     sysbus_init_mmio(dev, &s->mmio);
 
     s->chr = qemu_char_get_next_serial();
diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c
index 5751816..855ce7a 100644
--- a/hw/char/exynos4210_uart.c
+++ b/hw/char/exynos4210_uart.c
@@ -630,8 +630,8 @@
     Exynos4210UartState *s = FROM_SYSBUS(Exynos4210UartState, dev);
 
     /* memory mapping */
-    memory_region_init_io(&s->iomem, &exynos4210_uart_ops, s, "exynos4210.uart",
-                          EXYNOS4210_UART_REGS_MEM_SIZE);
+    memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_uart_ops, s,
+                          "exynos4210.uart", EXYNOS4210_UART_REGS_MEM_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
 
     sysbus_init_irq(dev, &s->irq);
diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c
index a64453f..82e1b95 100644
--- a/hw/char/grlib_apbuart.c
+++ b/hw/char/grlib_apbuart.c
@@ -242,7 +242,7 @@
 
     sysbus_init_irq(dev, &uart->irq);
 
-    memory_region_init_io(&uart->iomem, &grlib_apbuart_ops, uart,
+    memory_region_init_io(&uart->iomem, OBJECT(uart), &grlib_apbuart_ops, uart,
                           "uart", UART_REG_SIZE);
 
     sysbus_init_mmio(dev, &uart->iomem);
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
index 2a2c230..69b9ed2 100644
--- a/hw/char/imx_serial.c
+++ b/hw/char/imx_serial.c
@@ -386,7 +386,8 @@
     IMXSerialState *s = FROM_SYSBUS(IMXSerialState, dev);
 
 
-    memory_region_init_io(&s->iomem, &imx_serial_ops, s, "imx-serial", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &imx_serial_ops, s,
+                          "imx-serial", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c
index 99721ab..37b38ba 100644
--- a/hw/char/lm32_uart.c
+++ b/hw/char/lm32_uart.c
@@ -250,7 +250,8 @@
 
     sysbus_init_irq(dev, &s->irq);
 
-    memory_region_init_io(&s->iomem, &uart_ops, s, "uart", R_MAX * 4);
+    memory_region_init_io(&s->iomem, OBJECT(s), &uart_ops, s,
+                          "uart", R_MAX * 4);
     sysbus_init_mmio(dev, &s->iomem);
 
     s->chr = qemu_char_get_next_serial();
diff --git a/hw/char/mcf_uart.c b/hw/char/mcf_uart.c
index 3ec4705..98fd44e 100644
--- a/hw/char/mcf_uart.c
+++ b/hw/char/mcf_uart.c
@@ -302,6 +302,6 @@
     mcf_uart_state *s;
 
     s = mcf_uart_init(irq, chr);
-    memory_region_init_io(&s->iomem, &mcf_uart_ops, s, "uart", 0x40);
+    memory_region_init_io(&s->iomem, NULL, &mcf_uart_ops, s, "uart", 0x40);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 }
diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c
index cbc7d73..46deab2 100644
--- a/hw/char/milkymist-uart.c
+++ b/hw/char/milkymist-uart.c
@@ -196,7 +196,7 @@
 
     sysbus_init_irq(dev, &s->irq);
 
-    memory_region_init_io(&s->regs_region, &uart_mmio_ops, s,
+    memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s,
             "milkymist-uart", R_MAX * 4);
     sysbus_init_mmio(dev, &s->regs_region);
 
diff --git a/hw/char/omap_uart.c b/hw/char/omap_uart.c
index 5bb36ed..0b91693 100644
--- a/hw/char/omap_uart.c
+++ b/hw/char/omap_uart.c
@@ -168,7 +168,7 @@
     struct omap_uart_s *s = omap_uart_init(base, irq,
                     fclk, iclk, txdma, rxdma, label, chr);
 
-    memory_region_init_io(&s->iomem, &omap_uart_ops, s, "omap.uart", 0x100);
+    memory_region_init_io(&s->iomem, NULL, &omap_uart_ops, s, "omap.uart", 0x100);
 
     s->ta = ta;
 
diff --git a/hw/char/parallel.c b/hw/char/parallel.c
index caa9eb4..ad96ea5 100644
--- a/hw/char/parallel.c
+++ b/hw/char/parallel.c
@@ -587,7 +587,7 @@
     s->it_shift = it_shift;
     qemu_register_reset(parallel_reset, s);
 
-    memory_region_init_io(&s->iomem, &parallel_mm_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &parallel_mm_ops, s,
                           "parallel", 8 << it_shift);
     memory_region_add_subregion(address_space, base, &s->iomem);
     return true;
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 7079ef6..ebec64f 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -265,7 +265,7 @@
 {
     pl011_state *s = FROM_SYSBUS(pl011_state, dev);
 
-    memory_region_init_io(&s->iomem, &pl011_ops, s, "pl011", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &pl011_ops, s, "pl011", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     s->id = id;
diff --git a/hw/char/serial-isa.c b/hw/char/serial-isa.c
index e06a802..cea8212 100644
--- a/hw/char/serial-isa.c
+++ b/hw/char/serial-isa.c
@@ -72,7 +72,7 @@
     serial_realize_core(s, errp);
     qdev_set_legacy_instance_id(dev, isa->iobase, 3);
 
-    memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
+    memory_region_init_io(&s->io, OBJECT(isa), &serial_io_ops, s, "serial", 8);
     isa_register_ioport(isadev, &s->io, isa->iobase);
 }
 
diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c
index 3bec8eb..a17c702 100644
--- a/hw/char/serial-pci.c
+++ b/hw/char/serial-pci.c
@@ -63,7 +63,7 @@
     pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
     s->irq = pci->dev.irq[0];
 
-    memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
+    memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, "serial", 8);
     pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
     return 0;
 }
@@ -102,7 +102,7 @@
     assert(pci->ports <= PCI_SERIAL_MAX_PORTS);
 
     pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
-    memory_region_init(&pci->iobar, "multiserial", 8 * pci->ports);
+    memory_region_init(&pci->iobar, OBJECT(pci), "multiserial", 8 * pci->ports);
     pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->iobar);
     pci->irqs = qemu_allocate_irqs(multi_serial_irq_mux, pci,
                                    pci->ports);
@@ -118,7 +118,8 @@
         }
         s->irq = pci->irqs[i];
         pci->name[i] = g_strdup_printf("uart #%d", i+1);
-        memory_region_init_io(&s->io, &serial_io_ops, s, pci->name[i], 8);
+        memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s,
+                              pci->name[i], 8);
         memory_region_add_subregion(&pci->iobar, 8 * i, &s->io);
     }
     return 0;
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 6382f98..6025592 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -703,7 +703,7 @@
 
     vmstate_register(NULL, base, &vmstate_serial, s);
 
-    memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
+    memory_region_init_io(&s->io, NULL, &serial_io_ops, s, "serial", 8);
     memory_region_add_subregion(system_io, base, &s->io);
 
     return s;
@@ -766,7 +766,7 @@
     }
     vmstate_register(NULL, base, &vmstate_serial, s);
 
-    memory_region_init_io(&s->io, &serial_mm_ops[end], s,
+    memory_region_init_io(&s->io, NULL, &serial_mm_ops[end], s,
                           "serial", 8 << it_shift);
     memory_region_add_subregion(address_space, base, &s->io);
 
diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c
index b328643..6223a55 100644
--- a/hw/char/sh_serial.c
+++ b/hw/char/sh_serial.c
@@ -383,14 +383,14 @@
 
     sh_serial_clear_fifo(s);
 
-    memory_region_init_io(&s->iomem, &sh_serial_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &sh_serial_ops, s,
                           "serial", 0x100000000ULL);
 
-    memory_region_init_alias(&s->iomem_p4, "serial-p4", &s->iomem,
+    memory_region_init_alias(&s->iomem_p4, NULL, "serial-p4", &s->iomem,
                              0, 0x28);
     memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4);
 
-    memory_region_init_alias(&s->iomem_a7, "serial-a7", &s->iomem,
+    memory_region_init_alias(&s->iomem_a7, NULL, "serial-a7", &s->iomem,
                              0, 0x28);
     memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
 
diff --git a/hw/char/tpci200.c b/hw/char/tpci200.c
index 0170602..a199e57 100644
--- a/hw/char/tpci200.c
+++ b/hw/char/tpci200.c
@@ -588,17 +588,17 @@
     pci_set_long(c + 0x48, 0x00024C06);
     pci_set_long(c + 0x4C, 0x00000003);
 
-    memory_region_init_io(&s->mmio, &tpci200_cfg_ops,
+    memory_region_init_io(&s->mmio, OBJECT(s), &tpci200_cfg_ops,
                           s, "tpci200_mmio", 128);
-    memory_region_init_io(&s->io,   &tpci200_cfg_ops,
+    memory_region_init_io(&s->io, OBJECT(s),   &tpci200_cfg_ops,
                           s, "tpci200_io",   128);
-    memory_region_init_io(&s->las0, &tpci200_las0_ops,
+    memory_region_init_io(&s->las0, OBJECT(s), &tpci200_las0_ops,
                           s, "tpci200_las0", 256);
-    memory_region_init_io(&s->las1, &tpci200_las1_ops,
+    memory_region_init_io(&s->las1, OBJECT(s), &tpci200_las1_ops,
                           s, "tpci200_las1", 1024);
-    memory_region_init_io(&s->las2, &tpci200_las2_ops,
+    memory_region_init_io(&s->las2, OBJECT(s), &tpci200_las2_ops,
                           s, "tpci200_las2", 1024*1024*32);
-    memory_region_init_io(&s->las3, &tpci200_las3_ops,
+    memory_region_init_io(&s->las3, OBJECT(s), &tpci200_las3_ops,
                           s, "tpci200_las3", 1024*1024*16);
     pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio);
     pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO,     &s->io);
diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c
index 3f7e989..feca497 100644
--- a/hw/char/xilinx_uartlite.c
+++ b/hw/char/xilinx_uartlite.c
@@ -199,8 +199,8 @@
     sysbus_init_irq(dev, &s->irq);
 
     uart_update_status(s);
-    memory_region_init_io(&s->mmio, &uart_ops, s, "xlnx.xps-uartlite",
-                                                                R_MAX * 4);
+    memory_region_init_io(&s->mmio, OBJECT(s), &uart_ops, s,
+                          "xlnx.xps-uartlite", R_MAX * 4);
     sysbus_init_mmio(dev, &s->mmio);
 
     s->chr = qemu_char_get_next_serial();
diff --git a/hw/core/empty_slot.c b/hw/core/empty_slot.c
index 5234a4d..e624991 100644
--- a/hw/core/empty_slot.c
+++ b/hw/core/empty_slot.c
@@ -70,7 +70,7 @@
 {
     EmptySlot *s = FROM_SYSBUS(EmptySlot, dev);
 
-    memory_region_init_io(&s->iomem, &empty_slot_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &empty_slot_ops, s,
                           "empty-slot", s->size);
     sysbus_init_mmio(dev, &s->iomem);
     return 0;
diff --git a/hw/core/loader.c b/hw/core/loader.c
index d569636..44311ff 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -727,6 +727,7 @@
         addr += rom->romsize;
         section = memory_region_find(get_system_memory(), rom->addr, 1);
         rom->isrom = int128_nz(section.size) && memory_region_is_rom(section.mr);
+        memory_region_unref(section.mr);
     }
     qemu_register_reset(rom_reset, NULL);
     roms_loaded = 1;
diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
index 648656d..967b080 100644
--- a/hw/cpu/a15mpcore.c
+++ b/hw/cpu/a15mpcore.c
@@ -68,7 +68,8 @@
      *  0x5000-0x5fff -- GIC virtual interface control (not modelled)
      *  0x6000-0x7fff -- GIC virtual CPU interface (not modelled)
      */
-    memory_region_init(&s->container, "a15mp-priv-container", 0x8000);
+    memory_region_init(&s->container, OBJECT(s),
+                       "a15mp-priv-container", 0x8000);
     memory_region_add_subregion(&s->container, 0x1000,
                                 sysbus_mmio_get_region(busdev, 0));
     memory_region_add_subregion(&s->container, 0x2000,
diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c
index 0a1a10f..6c00a59 100644
--- a/hw/cpu/a9mpcore.c
+++ b/hw/cpu/a9mpcore.c
@@ -71,7 +71,7 @@
      *
      * We should implement the global timer but don't currently do so.
      */
-    memory_region_init(&s->container, "a9mp-priv-container", 0x2000);
+    memory_region_init(&s->container, OBJECT(s), "a9mp-priv-container", 0x2000);
     memory_region_add_subregion(&s->container, 0,
                                 sysbus_mmio_get_region(scubusdev, 0));
     /* GIC CPU interface */
diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c
index 90dcead..8eeb53e 100644
--- a/hw/cpu/arm11mpcore.c
+++ b/hw/cpu/arm11mpcore.c
@@ -87,8 +87,10 @@
     SysBusDevice *gicbusdev = SYS_BUS_DEVICE(s->gic);
     SysBusDevice *timerbusdev = SYS_BUS_DEVICE(s->mptimer);
     SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(s->wdtimer);
-    memory_region_init(&s->container, "mpcode-priv-container", 0x2000);
-    memory_region_init_io(&s->iomem, &mpcore_scu_ops, s, "mpcore-scu", 0x100);
+    memory_region_init(&s->container, OBJECT(s),
+                       "mpcode-priv-container", 0x2000);
+    memory_region_init_io(&s->iomem, OBJECT(s),
+                          &mpcore_scu_ops, s, "mpcore-scu", 0x100);
     memory_region_add_subregion(&s->container, 0, &s->iomem);
     /* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs
      * at 0x200, 0x300...
diff --git a/hw/cpu/icc_bus.c b/hw/cpu/icc_bus.c
index 73a1dc9..8788144 100644
--- a/hw/cpu/icc_bus.c
+++ b/hw/cpu/icc_bus.c
@@ -95,7 +95,7 @@
     /* Do not change order of registering regions,
      * APIC must be first registered region, board maps it by 0 index
      */
-    memory_region_init(&s->apic_container, "icc-apic-container",
+    memory_region_init(&s->apic_container, obj, "icc-apic-container",
                        APIC_SPACE_SIZE);
     sysbus_init_mmio(sb, &s->apic_container);
     s->icc_bus.apic_address_space = &s->apic_container;
diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c
index 7475671..9104d61 100644
--- a/hw/cris/axis_dev88.c
+++ b/hw/cris/axis_dev88.c
@@ -269,13 +269,13 @@
     env = &cpu->env;
 
     /* allocate RAM */
-    memory_region_init_ram(phys_ram, "axisdev88.ram", ram_size);
+    memory_region_init_ram(phys_ram, NULL, "axisdev88.ram", ram_size);
     vmstate_register_ram_global(phys_ram);
     memory_region_add_subregion(address_space_mem, 0x40000000, phys_ram);
 
     /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the 
        internal memory.  */
-    memory_region_init_ram(phys_intmem, "axisdev88.chipram", INTMEM_SIZE);
+    memory_region_init_ram(phys_intmem, NULL, "axisdev88.chipram", INTMEM_SIZE);
     vmstate_register_ram_global(phys_intmem);
     memory_region_add_subregion(address_space_mem, 0x38000000, phys_intmem);
 
@@ -283,13 +283,13 @@
     nand = drive_get(IF_MTD, 0, 0);
     nand_state.nand = nand_init(nand ? nand->bdrv : NULL,
                                 NAND_MFR_STMICRO, 0x39);
-    memory_region_init_io(&nand_state.iomem, &nand_ops, &nand_state,
+    memory_region_init_io(&nand_state.iomem, NULL, &nand_ops, &nand_state,
                           "nand", 0x05000000);
     memory_region_add_subregion(address_space_mem, 0x10000000,
                                 &nand_state.iomem);
 
     gpio_state.nand = &nand_state;
-    memory_region_init_io(&gpio_state.iomem, &gpio_ops, &gpio_state,
+    memory_region_init_io(&gpio_state.iomem, NULL, &gpio_ops, &gpio_state,
                           "gpio", 0x5c);
     memory_region_add_subregion(address_space_mem, 0x3001a000,
                                 &gpio_state.iomem);
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index 0d9eee8..a440575 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -2805,7 +2805,8 @@
     },
 };
 
-static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci,
+static void cirrus_init_common(CirrusVGAState *s, Object *owner,
+                               int device_id, int is_pci,
                                MemoryRegion *system_memory,
                                MemoryRegion *system_io)
 {
@@ -2840,21 +2841,22 @@
     }
 
     /* Register ioport 0x3b0 - 0x3df */
-    memory_region_init_io(&s->cirrus_vga_io, &cirrus_vga_io_ops, s,
+    memory_region_init_io(&s->cirrus_vga_io, owner, &cirrus_vga_io_ops, s,
                           "cirrus-io", 0x30);
     memory_region_add_subregion(system_io, 0x3b0, &s->cirrus_vga_io);
 
-    memory_region_init(&s->low_mem_container,
+    memory_region_init(&s->low_mem_container, owner,
                        "cirrus-lowmem-container",
                        0x20000);
 
-    memory_region_init_io(&s->low_mem, &cirrus_vga_mem_ops, s,
+    memory_region_init_io(&s->low_mem, owner, &cirrus_vga_mem_ops, s,
                           "cirrus-low-memory", 0x20000);
     memory_region_add_subregion(&s->low_mem_container, 0, &s->low_mem);
     for (i = 0; i < 2; ++i) {
         static const char *names[] = { "vga.bank0", "vga.bank1" };
         MemoryRegion *bank = &s->cirrus_bank[i];
-        memory_region_init_alias(bank, names[i], &s->vga.vram, 0, 0x8000);
+        memory_region_init_alias(bank, owner, names[i], &s->vga.vram,
+                                 0, 0x8000);
         memory_region_set_enabled(bank, false);
         memory_region_add_subregion_overlap(&s->low_mem_container, i * 0x8000,
                                             bank, 1);
@@ -2866,13 +2868,13 @@
     memory_region_set_coalescing(&s->low_mem);
 
     /* I/O handler for LFB */
-    memory_region_init_io(&s->cirrus_linear_io, &cirrus_linear_io_ops, s,
+    memory_region_init_io(&s->cirrus_linear_io, owner, &cirrus_linear_io_ops, s,
                           "cirrus-linear-io", s->vga.vram_size_mb
                                               * 1024 * 1024);
     memory_region_set_flush_coalesced(&s->cirrus_linear_io);
 
     /* I/O handler for LFB */
-    memory_region_init_io(&s->cirrus_linear_bitblt_io,
+    memory_region_init_io(&s->cirrus_linear_bitblt_io, owner,
                           &cirrus_linear_bitblt_io_ops,
                           s,
                           "cirrus-bitblt-mmio",
@@ -2880,7 +2882,7 @@
     memory_region_set_flush_coalesced(&s->cirrus_linear_bitblt_io);
 
     /* I/O handler for memory-mapped I/O */
-    memory_region_init_io(&s->cirrus_mmio_io, &cirrus_mmio_io_ops, s,
+    memory_region_init_io(&s->cirrus_mmio_io, owner, &cirrus_mmio_io_ops, s,
                           "cirrus-mmio", CIRRUS_PNPMMIO_SIZE);
     memory_region_set_flush_coalesced(&s->cirrus_mmio_io);
 
@@ -2912,8 +2914,8 @@
     ISACirrusVGAState *d = ISA_CIRRUS_VGA(dev);
     VGACommonState *s = &d->cirrus_vga.vga;
 
-    vga_common_init(s);
-    cirrus_init_common(&d->cirrus_vga, CIRRUS_ID_CLGD5430, 0,
+    vga_common_init(s, OBJECT(dev));
+    cirrus_init_common(&d->cirrus_vga, OBJECT(dev), CIRRUS_ID_CLGD5430, 0,
                        isa_address_space(isadev),
                        isa_address_space_io(isadev));
     s->con = graphic_console_init(dev, s->hw_ops, s);
@@ -2958,14 +2960,14 @@
      int16_t device_id = pc->device_id;
 
      /* setup VGA */
-     vga_common_init(&s->vga);
-     cirrus_init_common(s, device_id, 1, pci_address_space(dev),
+     vga_common_init(&s->vga, OBJECT(dev));
+     cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev),
                         pci_address_space_io(dev));
      s->vga.con = graphic_console_init(DEVICE(dev), s->vga.hw_ops, &s->vga);
 
      /* setup PCI */
 
-    memory_region_init(&s->pci_bar, "cirrus-pci-bar0", 0x2000000);
+    memory_region_init(&s->pci_bar, OBJECT(dev), "cirrus-pci-bar0", 0x2000000);
 
     /* XXX: add byte swapping apertures */
     memory_region_add_subregion(&s->pci_bar, 0, &s->cirrus_linear_io);
diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c
index 0da00a9..eb168ea 100644
--- a/hw/display/exynos4210_fimd.c
+++ b/hw/display/exynos4210_fimd.c
@@ -1126,6 +1126,11 @@
     /* Total number of bytes of virtual screen used by current window */
     w->fb_len = fb_mapped_len = (w->virtpage_width + w->virtpage_offsize) *
             (w->rightbot_y - w->lefttop_y + 1);
+
+    /* TODO: add .exit and unref the region there.  Not needed yet since sysbus
+     * does not support hot-unplug.
+     */
+    memory_region_unref(w->mem_section.mr);
     w->mem_section = memory_region_find(sysbus_address_space(&s->busdev),
             fb_start_addr, w->fb_len);
     assert(w->mem_section.mr);
@@ -1154,6 +1159,7 @@
     return;
 
 error_return:
+    memory_region_unref(w->mem_section.mr);
     w->mem_section.mr = NULL;
     w->mem_section.size = int128_zero();
     w->host_fb_addr = NULL;
@@ -1902,7 +1908,7 @@
     sysbus_init_irq(dev, &s->irq[1]);
     sysbus_init_irq(dev, &s->irq[2]);
 
-    memory_region_init_io(&s->iomem, &exynos4210_fimd_mmio_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_fimd_mmio_ops, s,
             "exynos4210.fimd", FIMD_REGS_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
     s->console = graphic_console_init(DEVICE(dev), &exynos4210_fimd_ops, s);
diff --git a/hw/display/framebuffer.c b/hw/display/framebuffer.c
index 49c9e59..4546e42 100644
--- a/hw/display/framebuffer.c
+++ b/hw/display/framebuffer.c
@@ -54,11 +54,11 @@
     src_len = src_width * rows;
 
     mem_section = memory_region_find(address_space, base, src_len);
+    mem = mem_section.mr;
     if (int128_get64(mem_section.size) != src_len ||
             !memory_region_is_ram(mem_section.mr)) {
-        return;
+        goto out;
     }
-    mem = mem_section.mr;
     assert(mem);
     assert(mem_section.offset_within_address_space == base);
 
@@ -68,10 +68,10 @@
        but it's not really worth it as dirty flag tracking will probably
        already have failed above.  */
     if (!src_base)
-        return;
+        goto out;
     if (src_len != src_width * rows) {
         cpu_physical_memory_unmap(src_base, src_len, 0, 0);
-        return;
+        goto out;
     }
     src = src_base;
     dest = surface_data(ds);
@@ -102,10 +102,12 @@
     }
     cpu_physical_memory_unmap(src_base, src_len, 0, 0);
     if (first < 0) {
-        return;
+        goto out;
     }
     memory_region_reset_dirty(mem, mem_section.offset_within_region, src_len,
                               DIRTY_MEMORY_VGA);
     *first_row = first;
     *last_row = last;
+out:
+    memory_region_unref(mem);
 }
diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c
index 2a4047e..79a0a50 100644
--- a/hw/display/g364fb.c
+++ b/hw/display/g364fb.c
@@ -486,8 +486,8 @@
 
     s->con = graphic_console_init(dev, &g364fb_ops, s);
 
-    memory_region_init_io(&s->mem_ctrl, &g364fb_ctrl_ops, s, "ctrl", 0x180000);
-    memory_region_init_ram_ptr(&s->mem_vram, "vram",
+    memory_region_init_io(&s->mem_ctrl, NULL, &g364fb_ctrl_ops, s, "ctrl", 0x180000);
+    memory_region_init_ram_ptr(&s->mem_vram, NULL, "vram",
                                s->vram_size, s->vram);
     vmstate_register_ram(&s->mem_vram, dev);
     memory_region_set_coalescing(&s->mem_vram);
diff --git a/hw/display/jazz_led.c b/hw/display/jazz_led.c
index 52035fc..7f82037 100644
--- a/hw/display/jazz_led.c
+++ b/hw/display/jazz_led.c
@@ -264,7 +264,7 @@
 {
     LedState *s = FROM_SYSBUS(LedState, dev);
 
-    memory_region_init_io(&s->iomem, &led_ops, s, "led", 1);
+    memory_region_init_io(&s->iomem, OBJECT(s), &led_ops, s, "led", 1);
     sysbus_init_mmio(dev, &s->iomem);
 
     s->con = graphic_console_init(DEVICE(dev), &jazz_led_ops, s);
diff --git a/hw/display/milkymist-tmu2.c b/hw/display/milkymist-tmu2.c
index b723a04..efda082 100644
--- a/hw/display/milkymist-tmu2.c
+++ b/hw/display/milkymist-tmu2.c
@@ -447,7 +447,7 @@
 
     sysbus_init_irq(dev, &s->irq);
 
-    memory_region_init_io(&s->regs_region, &tmu2_mmio_ops, s,
+    memory_region_init_io(&s->regs_region, OBJECT(s), &tmu2_mmio_ops, s,
             "milkymist-tmu2", R_MAX * 4);
     sysbus_init_mmio(dev, &s->regs_region);
 
diff --git a/hw/display/milkymist-vgafb.c b/hw/display/milkymist-vgafb.c
index 3828296..870b339 100644
--- a/hw/display/milkymist-vgafb.c
+++ b/hw/display/milkymist-vgafb.c
@@ -279,7 +279,7 @@
 {
     MilkymistVgafbState *s = FROM_SYSBUS(typeof(*s), dev);
 
-    memory_region_init_io(&s->regs_region, &vgafb_mmio_ops, s,
+    memory_region_init_io(&s->regs_region, OBJECT(s), &vgafb_mmio_ops, s,
             "milkymist-vgafb", R_MAX * 4);
     sysbus_init_mmio(dev, &s->regs_region);
 
diff --git a/hw/display/omap_dss.c b/hw/display/omap_dss.c
index ea3afce..24ccbcc 100644
--- a/hw/display/omap_dss.c
+++ b/hw/display/omap_dss.c
@@ -1053,15 +1053,15 @@
     s->drq = drq;
     omap_dss_reset(s);
 
-    memory_region_init_io(&s->iomem_diss1, &omap_diss_ops, s, "omap.diss1",
+    memory_region_init_io(&s->iomem_diss1, NULL, &omap_diss_ops, s, "omap.diss1",
                           omap_l4_region_size(ta, 0));
-    memory_region_init_io(&s->iomem_disc1, &omap_disc_ops, s, "omap.disc1",
+    memory_region_init_io(&s->iomem_disc1, NULL, &omap_disc_ops, s, "omap.disc1",
                           omap_l4_region_size(ta, 1));
-    memory_region_init_io(&s->iomem_rfbi1, &omap_rfbi_ops, s, "omap.rfbi1",
+    memory_region_init_io(&s->iomem_rfbi1, NULL, &omap_rfbi_ops, s, "omap.rfbi1",
                           omap_l4_region_size(ta, 2));
-    memory_region_init_io(&s->iomem_venc1, &omap_venc_ops, s, "omap.venc1",
+    memory_region_init_io(&s->iomem_venc1, NULL, &omap_venc_ops, s, "omap.venc1",
                           omap_l4_region_size(ta, 3));
-    memory_region_init_io(&s->iomem_im3, &omap_im3_ops, s,
+    memory_region_init_io(&s->iomem_im3, NULL, &omap_im3_ops, s,
                           "omap.im3", 0x1000);
 
     omap_l4_attach(ta, 0, &s->iomem_diss1);
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
index fb72ebe..c3b9b68 100644
--- a/hw/display/omap_lcdc.c
+++ b/hw/display/omap_lcdc.c
@@ -403,7 +403,7 @@
     s->sysmem = sysmem;
     omap_lcdc_reset(s);
 
-    memory_region_init_io(&s->iomem, &omap_lcdc_ops, s, "omap.lcdc", 0x100);
+    memory_region_init_io(&s->iomem, NULL, &omap_lcdc_ops, s, "omap.lcdc", 0x100);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
     s->con = graphic_console_init(NULL, &omap_ops, s);
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
index f259955..60afcf3 100644
--- a/hw/display/pl110.c
+++ b/hw/display/pl110.c
@@ -453,7 +453,7 @@
 {
     pl110_state *s = FROM_SYSBUS(pl110_state, dev);
 
-    memory_region_init_io(&s->iomem, &pl110_ops, s, "pl110", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &pl110_ops, s, "pl110", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     qdev_init_gpio_in(&s->busdev.qdev, pl110_mux_ctrl_set, 1);
diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c
index 3b68f26..990931a 100644
--- a/hw/display/pxa2xx_lcd.c
+++ b/hw/display/pxa2xx_lcd.c
@@ -1009,7 +1009,7 @@
 
     pxa2xx_lcdc_orientation(s, graphic_rotate);
 
-    memory_region_init_io(&s->iomem, &pxa2xx_lcdc_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &pxa2xx_lcdc_ops, s,
                           "pxa2xx-lcd-controller", 0x00100000);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index 937a402..ddefa06 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -23,6 +23,7 @@
 #include "qemu-common.h"
 #include "qemu/timer.h"
 #include "qemu/queue.h"
+#include "qemu/atomic.h"
 #include "monitor/monitor.h"
 #include "sysemu/sysemu.h"
 #include "trace.h"
@@ -1726,7 +1727,7 @@
         trace_qxl_send_events_vm_stopped(d->id, events);
         return;
     }
-    old_pending = __sync_fetch_and_or(&d->ram->int_pending, le_events);
+    old_pending = atomic_fetch_or(&d->ram->int_pending, le_events);
     if ((old_pending & le_events) == le_events) {
         return;
     }
@@ -1981,18 +1982,20 @@
     pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
 
     qxl->rom_size = qxl_rom_size();
-    memory_region_init_ram(&qxl->rom_bar, "qxl.vrom", qxl->rom_size);
+    memory_region_init_ram(&qxl->rom_bar, OBJECT(qxl), "qxl.vrom",
+                           qxl->rom_size);
     vmstate_register_ram(&qxl->rom_bar, &qxl->pci.qdev);
     init_qxl_rom(qxl);
     init_qxl_ram(qxl);
 
     qxl->guest_surfaces.cmds = g_new0(QXLPHYSICAL, qxl->ssd.num_surfaces);
-    memory_region_init_ram(&qxl->vram_bar, "qxl.vram", qxl->vram_size);
+    memory_region_init_ram(&qxl->vram_bar, OBJECT(qxl), "qxl.vram",
+                           qxl->vram_size);
     vmstate_register_ram(&qxl->vram_bar, &qxl->pci.qdev);
-    memory_region_init_alias(&qxl->vram32_bar, "qxl.vram32", &qxl->vram_bar,
-                             0, qxl->vram32_size);
+    memory_region_init_alias(&qxl->vram32_bar, OBJECT(qxl), "qxl.vram32",
+                             &qxl->vram_bar, 0, qxl->vram32_size);
 
-    memory_region_init_io(&qxl->io_bar, &qxl_io_ops, qxl,
+    memory_region_init_io(&qxl->io_bar, OBJECT(qxl), &qxl_io_ops, qxl,
                           "qxl-ioports", io_size);
     if (qxl->id == 0) {
         vga_dirty_log_start(&qxl->vga);
@@ -2067,9 +2070,11 @@
     qxl->id = 0;
     qxl_init_ramsize(qxl);
     vga->vram_size_mb = qxl->vga.vram_size >> 20;
-    vga_common_init(vga);
-    vga_init(vga, pci_address_space(dev), pci_address_space_io(dev), false);
-    portio_list_init(qxl_vga_port_list, qxl_vga_portio_list, vga, "vga");
+    vga_common_init(vga, OBJECT(dev));
+    vga_init(vga, OBJECT(dev),
+             pci_address_space(dev), pci_address_space_io(dev), false);
+    portio_list_init(qxl_vga_port_list, OBJECT(dev), qxl_vga_portio_list,
+                     vga, "vga");
     portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0);
 
     vga->con = graphic_console_init(DEVICE(dev), &qxl_ops, qxl);
@@ -2093,7 +2098,8 @@
 
     qxl->id = device_id++;
     qxl_init_ramsize(qxl);
-    memory_region_init_ram(&qxl->vga.vram, "qxl.vgavram", qxl->vga.vram_size);
+    memory_region_init_ram(&qxl->vga.vram, OBJECT(dev), "qxl.vgavram",
+                           qxl->vga.vram_size);
     vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev);
     qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram);
     qxl->vga.con = graphic_console_init(DEVICE(dev), &qxl_ops, qxl);
diff --git a/hw/display/sm501.c b/hw/display/sm501.c
index f72e488..c75d6ac 100644
--- a/hw/display/sm501.c
+++ b/hw/display/sm501.c
@@ -1408,23 +1408,23 @@
     s->dc_crt_control = 0x00010000;
 
     /* allocate local memory */
-    memory_region_init_ram(&s->local_mem_region, "sm501.local",
+    memory_region_init_ram(&s->local_mem_region, NULL, "sm501.local",
                            local_mem_bytes);
     vmstate_register_ram_global(&s->local_mem_region);
     s->local_mem = memory_region_get_ram_ptr(&s->local_mem_region);
     memory_region_add_subregion(address_space_mem, base, &s->local_mem_region);
 
     /* map mmio */
-    memory_region_init_io(sm501_system_config, &sm501_system_config_ops, s,
+    memory_region_init_io(sm501_system_config, NULL, &sm501_system_config_ops, s,
                           "sm501-system-config", 0x6c);
     memory_region_add_subregion(address_space_mem, base + MMIO_BASE_OFFSET,
                                 sm501_system_config);
-    memory_region_init_io(sm501_disp_ctrl, &sm501_disp_ctrl_ops, s,
+    memory_region_init_io(sm501_disp_ctrl, NULL, &sm501_disp_ctrl_ops, s,
                           "sm501-disp-ctrl", 0x1000);
     memory_region_add_subregion(address_space_mem,
                                 base + MMIO_BASE_OFFSET + SM501_DC,
                                 sm501_disp_ctrl);
-    memory_region_init_io(sm501_2d_engine, &sm501_2d_engine_ops, s,
+    memory_region_init_io(sm501_2d_engine, NULL, &sm501_2d_engine_ops, s,
                           "sm501-2d-engine", 0x54);
     memory_region_add_subregion(address_space_mem,
                                 base + MMIO_BASE_OFFSET + SM501_2D_ENGINE,
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
index 0cb87bc..3dd9b98 100644
--- a/hw/display/tc6393xb.c
+++ b/hw/display/tc6393xb.c
@@ -578,10 +578,10 @@
     nand = drive_get(IF_MTD, 0, 0);
     s->flash = nand_init(nand ? nand->bdrv : NULL, NAND_MFR_TOSHIBA, 0x76);
 
-    memory_region_init_io(&s->iomem, &tc6393xb_ops, s, "tc6393xb", 0x10000);
+    memory_region_init_io(&s->iomem, NULL, &tc6393xb_ops, s, "tc6393xb", 0x10000);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
-    memory_region_init_ram(&s->vram, "tc6393xb.vram", 0x100000);
+    memory_region_init_ram(&s->vram, NULL, "tc6393xb.vram", 0x100000);
     vmstate_register_ram_global(&s->vram);
     s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
     memory_region_add_subregion(sysmem, base + 0x100000, &s->vram);
diff --git a/hw/display/tcx.c b/hw/display/tcx.c
index 995641c..9fd48b5 100644
--- a/hw/display/tcx.c
+++ b/hw/display/tcx.c
@@ -528,7 +528,7 @@
     int size;
     uint8_t *vram_base;
 
-    memory_region_init_ram(&s->vram_mem, "tcx.vram",
+    memory_region_init_ram(&s->vram_mem, OBJECT(s), "tcx.vram",
                            s->vram_size * (1 + 4 + 4));
     vmstate_register_ram_global(&s->vram_mem);
     vram_base = memory_region_get_ram_ptr(&s->vram_mem);
@@ -536,21 +536,23 @@
     /* 8-bit plane */
     s->vram = vram_base;
     size = s->vram_size;
-    memory_region_init_alias(&s->vram_8bit, "tcx.vram.8bit",
+    memory_region_init_alias(&s->vram_8bit, OBJECT(s), "tcx.vram.8bit",
                              &s->vram_mem, vram_offset, size);
     sysbus_init_mmio(dev, &s->vram_8bit);
     vram_offset += size;
     vram_base += size;
 
     /* DAC */
-    memory_region_init_io(&s->dac, &tcx_dac_ops, s, "tcx.dac", TCX_DAC_NREGS);
+    memory_region_init_io(&s->dac, OBJECT(s), &tcx_dac_ops, s,
+                          "tcx.dac", TCX_DAC_NREGS);
     sysbus_init_mmio(dev, &s->dac);
 
     /* TEC (dummy) */
-    memory_region_init_io(&s->tec, &dummy_ops, s, "tcx.tec", TCX_TEC_NREGS);
+    memory_region_init_io(&s->tec, OBJECT(s), &dummy_ops, s,
+                          "tcx.tec", TCX_TEC_NREGS);
     sysbus_init_mmio(dev, &s->tec);
     /* THC: NetBSD writes here even with 8-bit display: dummy */
-    memory_region_init_io(&s->thc24, &dummy_ops, s, "tcx.thc24",
+    memory_region_init_io(&s->thc24, OBJECT(s), &dummy_ops, s, "tcx.thc24",
                           TCX_THC_NREGS_24);
     sysbus_init_mmio(dev, &s->thc24);
 
@@ -559,7 +561,7 @@
         size = s->vram_size * 4;
         s->vram24 = (uint32_t *)vram_base;
         s->vram24_offset = vram_offset;
-        memory_region_init_alias(&s->vram_24bit, "tcx.vram.24bit",
+        memory_region_init_alias(&s->vram_24bit, OBJECT(s), "tcx.vram.24bit",
                                  &s->vram_mem, vram_offset, size);
         sysbus_init_mmio(dev, &s->vram_24bit);
         vram_offset += size;
@@ -569,14 +571,14 @@
         size = s->vram_size * 4;
         s->cplane = (uint32_t *)vram_base;
         s->cplane_offset = vram_offset;
-        memory_region_init_alias(&s->vram_cplane, "tcx.vram.cplane",
+        memory_region_init_alias(&s->vram_cplane, OBJECT(s), "tcx.vram.cplane",
                                  &s->vram_mem, vram_offset, size);
         sysbus_init_mmio(dev, &s->vram_cplane);
 
         s->con = graphic_console_init(DEVICE(dev), &tcx24_ops, s);
     } else {
         /* THC 8 bit (dummy) */
-        memory_region_init_io(&s->thc8, &dummy_ops, s, "tcx.thc8",
+        memory_region_init_io(&s->thc8, OBJECT(s), &dummy_ops, s, "tcx.thc8",
                               TCX_THC_NREGS_8);
         sysbus_init_mmio(dev, &s->thc8);
 
diff --git a/hw/display/vga-isa-mm.c b/hw/display/vga-isa-mm.c
index ceeb92f..8b514cc 100644
--- a/hw/display/vga-isa-mm.c
+++ b/hw/display/vga-isa-mm.c
@@ -105,13 +105,13 @@
 
     s->it_shift = it_shift;
     s_ioport_ctrl = g_malloc(sizeof(*s_ioport_ctrl));
-    memory_region_init_io(s_ioport_ctrl, &vga_mm_ctrl_ops, s,
+    memory_region_init_io(s_ioport_ctrl, NULL, &vga_mm_ctrl_ops, s,
                           "vga-mm-ctrl", 0x100000);
     memory_region_set_flush_coalesced(s_ioport_ctrl);
 
     vga_io_memory = g_malloc(sizeof(*vga_io_memory));
     /* XXX: endianness? */
-    memory_region_init_io(vga_io_memory, &vga_mem_ops, &s->vga,
+    memory_region_init_io(vga_io_memory, NULL, &vga_mem_ops, &s->vga,
                           "vga-mem", 0x20000);
 
     vmstate_register(NULL, 0, &vmstate_vga_common, s);
@@ -132,11 +132,11 @@
     s = g_malloc0(sizeof(*s));
 
     s->vga.vram_size_mb = VGA_RAM_SIZE >> 20;
-    vga_common_init(&s->vga);
+    vga_common_init(&s->vga, NULL);
     vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space);
 
     s->vga.con = graphic_console_init(NULL, s->vga.hw_ops, s);
 
-    vga_init_vbe(&s->vga, address_space);
+    vga_init_vbe(&s->vga, NULL, address_space);
     return 0;
 }
diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c
index d1691a9..8d560ec 100644
--- a/hw/display/vga-isa.c
+++ b/hw/display/vga-isa.c
@@ -56,9 +56,9 @@
     MemoryRegion *vga_io_memory;
     const MemoryRegionPortio *vga_ports, *vbe_ports;
 
-    vga_common_init(s);
+    vga_common_init(s, OBJECT(dev));
     s->legacy_address_space = isa_address_space(isadev);
-    vga_io_memory = vga_init_io(s, &vga_ports, &vbe_ports);
+    vga_io_memory = vga_init_io(s, OBJECT(dev), &vga_ports, &vbe_ports);
     isa_register_portio_list(isadev, 0x3b0, vga_ports, s, "vga");
     if (vbe_ports) {
         isa_register_portio_list(isadev, 0x1ce, vbe_ports, s, "vbe");
@@ -69,7 +69,7 @@
     memory_region_set_coalescing(vga_io_memory);
     s->con = graphic_console_init(DEVICE(dev), s->hw_ops, s);
 
-    vga_init_vbe(s, isa_address_space(isadev));
+    vga_init_vbe(s, OBJECT(dev), isa_address_space(isadev));
     /* ROM BIOS */
     rom_add_vga(VGABIOS_FILENAME);
 }
diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c
index cea8db7..3e150ab 100644
--- a/hw/display/vga-pci.c
+++ b/hw/display/vga-pci.c
@@ -147,8 +147,9 @@
     VGACommonState *s = &d->vga;
 
     /* vga + console init */
-    vga_common_init(s);
-    vga_init(s, pci_address_space(dev), pci_address_space_io(dev), true);
+    vga_common_init(s, OBJECT(dev));
+    vga_init(s, OBJECT(dev), pci_address_space(dev), pci_address_space_io(dev),
+             true);
 
     s->con = graphic_console_init(DEVICE(dev), s->hw_ops, s);
 
@@ -157,10 +158,10 @@
 
     /* mmio bar for vga register access */
     if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_MMIO)) {
-        memory_region_init(&d->mmio, "vga.mmio", 4096);
-        memory_region_init_io(&d->ioport, &pci_vga_ioport_ops, d,
+        memory_region_init(&d->mmio, NULL, "vga.mmio", 4096);
+        memory_region_init_io(&d->ioport, NULL, &pci_vga_ioport_ops, d,
                               "vga ioports remapped", PCI_VGA_IOPORT_SIZE);
-        memory_region_init_io(&d->bochs, &pci_vga_bochs_ops, d,
+        memory_region_init_io(&d->bochs, NULL, &pci_vga_bochs_ops, d,
                               "bochs dispi interface", PCI_VGA_BOCHS_SIZE);
 
         memory_region_add_subregion(&d->mmio, PCI_VGA_IOPORT_OFFSET,
@@ -172,7 +173,7 @@
 
     if (!dev->rom_bar) {
         /* compatibility with pc-0.13 and older */
-        vga_init_vbe(s, pci_address_space(dev));
+        vga_init_vbe(s, OBJECT(dev), pci_address_space(dev));
     }
 
     return 0;
diff --git a/hw/display/vga.c b/hw/display/vga.c
index 21a108d..06f44a8 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -198,7 +198,8 @@
         }
         base += isa_mem_base;
         region = g_malloc(sizeof(*region));
-        memory_region_init_alias(region, "vga.chain4", &s->vram, offset, size);
+        memory_region_init_alias(region, memory_region_owner(&s->vram),
+                                 "vga.chain4", &s->vram, offset, size);
         memory_region_add_subregion_overlap(s->legacy_address_space, base,
                                             region, 2);
         s->chain4_alias = region;
@@ -2256,7 +2257,7 @@
     .text_update = vga_update_text,
 };
 
-void vga_common_init(VGACommonState *s)
+void vga_common_init(VGACommonState *s, Object *obj)
 {
     int i, j, v, b;
 
@@ -2292,7 +2293,7 @@
     s->vram_size_mb = s->vram_size >> 20;
 
     s->is_vbe_vmstate = 1;
-    memory_region_init_ram(&s->vram, "vga.vram", s->vram_size);
+    memory_region_init_ram(&s->vram, obj, "vga.vram", s->vram_size);
     vmstate_register_ram_global(&s->vram);
     xen_register_framebuffer(&s->vram);
     s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
@@ -2333,7 +2334,7 @@
 };
 
 /* Used by both ISA and PCI */
-MemoryRegion *vga_init_io(VGACommonState *s,
+MemoryRegion *vga_init_io(VGACommonState *s, Object *obj,
                           const MemoryRegionPortio **vga_ports,
                           const MemoryRegionPortio **vbe_ports)
 {
@@ -2343,14 +2344,14 @@
     *vbe_ports = vbe_portio_list;
 
     vga_mem = g_malloc(sizeof(*vga_mem));
-    memory_region_init_io(vga_mem, &vga_mem_ops, s,
+    memory_region_init_io(vga_mem, obj, &vga_mem_ops, s,
                           "vga-lowmem", 0x20000);
     memory_region_set_flush_coalesced(vga_mem);
 
     return vga_mem;
 }
 
-void vga_init(VGACommonState *s, MemoryRegion *address_space,
+void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
               MemoryRegion *address_space_io, bool init_vga_ports)
 {
     MemoryRegion *vga_io_memory;
@@ -2364,28 +2365,28 @@
 
     s->legacy_address_space = address_space;
 
-    vga_io_memory = vga_init_io(s, &vga_ports, &vbe_ports);
+    vga_io_memory = vga_init_io(s, obj, &vga_ports, &vbe_ports);
     memory_region_add_subregion_overlap(address_space,
                                         isa_mem_base + 0x000a0000,
                                         vga_io_memory,
                                         1);
     memory_region_set_coalescing(vga_io_memory);
     if (init_vga_ports) {
-        portio_list_init(vga_port_list, vga_ports, s, "vga");
+        portio_list_init(vga_port_list, obj, vga_ports, s, "vga");
         portio_list_add(vga_port_list, address_space_io, 0x3b0);
     }
     if (vbe_ports) {
-        portio_list_init(vbe_port_list, vbe_ports, s, "vbe");
+        portio_list_init(vbe_port_list, obj, vbe_ports, s, "vbe");
         portio_list_add(vbe_port_list, address_space_io, 0x1ce);
     }
 }
 
-void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory)
+void vga_init_vbe(VGACommonState *s, Object *obj, MemoryRegion *system_memory)
 {
     /* With pc-0.12 and below we map both the PCI BAR and the fixed VBE region,
      * so use an alias to avoid double-mapping the same region.
      */
-    memory_region_init_alias(&s->vram_vbe, "vram.vbe",
+    memory_region_init_alias(&s->vram_vbe, obj, "vram.vbe",
                              &s->vram, 0, memory_region_size(&s->vram));
     /* XXX: use optimized standard vga accesses */
     memory_region_add_subregion(system_memory,
diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h
index 66f9f3c..e641890 100644
--- a/hw/display/vga_int.h
+++ b/hw/display/vga_int.h
@@ -177,10 +177,10 @@
     return (v << 2) | (b << 1) | b;
 }
 
-void vga_common_init(VGACommonState *s);
-void vga_init(VGACommonState *s, MemoryRegion *address_space,
+void vga_common_init(VGACommonState *s, Object *obj);
+void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
               MemoryRegion *address_space_io, bool init_vga_ports);
-MemoryRegion *vga_init_io(VGACommonState *s,
+MemoryRegion *vga_init_io(VGACommonState *s, Object *obj,
                           const MemoryRegionPortio **vga_ports,
                           const MemoryRegionPortio **vbe_ports);
 void vga_common_reset(VGACommonState *s);
@@ -198,7 +198,7 @@
 
 int vga_ioport_invalid(VGACommonState *s, uint32_t addr);
 
-void vga_init_vbe(VGACommonState *s, MemoryRegion *address_space);
+void vga_init_vbe(VGACommonState *s, Object *obj, MemoryRegion *address_space);
 uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr);
 void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val);
 void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val);
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index fd3569d..714908f 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -1194,12 +1194,12 @@
     s->vga.con = graphic_console_init(dev, &vmsvga_ops, s);
 
     s->fifo_size = SVGA_FIFO_SIZE;
-    memory_region_init_ram(&s->fifo_ram, "vmsvga.fifo", s->fifo_size);
+    memory_region_init_ram(&s->fifo_ram, NULL, "vmsvga.fifo", s->fifo_size);
     vmstate_register_ram_global(&s->fifo_ram);
     s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram);
 
-    vga_common_init(&s->vga);
-    vga_init(&s->vga, address_space, io, true);
+    vga_common_init(&s->vga, OBJECT(dev));
+    vga_init(&s->vga, OBJECT(dev), address_space, io, true);
     vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
     s->new_depth = 32;
 }
@@ -1241,6 +1241,10 @@
     .valid = {
         .min_access_size = 4,
         .max_access_size = 4,
+        .unaligned = true,
+    },
+    .impl = {
+        .unaligned = true,
     },
 };
 
@@ -1253,7 +1257,7 @@
     s->card.config[PCI_LATENCY_TIMER] = 0x40;           /* Latency timer */
     s->card.config[PCI_INTERRUPT_LINE] = 0xff;          /* End */
 
-    memory_region_init_io(&s->io_bar, &vmsvga_io_ops, &s->chip,
+    memory_region_init_io(&s->io_bar, NULL, &vmsvga_io_ops, &s->chip,
                           "vmsvga-io", 0x10);
     memory_region_set_flush_coalesced(&s->io_bar);
     pci_register_bar(&s->card, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
@@ -1268,7 +1272,7 @@
 
     if (!dev->rom_bar) {
         /* compatibility with pc-0.13 and older */
-        vga_init_vbe(&s->chip.vga, pci_address_space(dev));
+        vga_init_vbe(&s->chip.vga, OBJECT(dev), pci_address_space(dev));
     }
 
     return 0;
diff --git a/hw/dma/etraxfs_dma.c b/hw/dma/etraxfs_dma.c
index 6a8c222..3599513 100644
--- a/hw/dma/etraxfs_dma.c
+++ b/hw/dma/etraxfs_dma.c
@@ -773,7 +773,7 @@
 	ctrl->nr_channels = nr_channels;
 	ctrl->channels = g_malloc0(sizeof ctrl->channels[0] * nr_channels);
 
-	memory_region_init_io(&ctrl->mmio, &dma_ops, ctrl, "etraxfs-dma",
+	memory_region_init_io(&ctrl->mmio, NULL, &dma_ops, ctrl, "etraxfs-dma",
 			      nr_channels * 0x2000);
 	memory_region_add_subregion(get_system_memory(), base, &ctrl->mmio);
 
diff --git a/hw/dma/i82374.c b/hw/dma/i82374.c
index 6192780..a5b891f 100644
--- a/hw/dma/i82374.c
+++ b/hw/dma/i82374.c
@@ -124,16 +124,24 @@
     },
 };
 
+static const MemoryRegionPortio i82374_portio_list[] = {
+    { 0x0A, 1, 1, .read = i82374_read_isr, },
+    { 0x10, 8, 1, .write = i82374_write_command, },
+    { 0x18, 8, 1, .read = i82374_read_status, },
+    { 0x20, 0x20, 1,
+      .write = i82374_write_descriptor, .read = i82374_read_descriptor, },
+    PORTIO_END_OF_LIST(),
+};
+
 static void i82374_isa_realize(DeviceState *dev, Error **errp)
 {
     ISAi82374State *isa = I82374(dev);
     I82374State *s = &isa->state;
+    PortioList *port_list = g_new(PortioList, 1);
 
-    register_ioport_read(isa->iobase + 0x0A, 1, 1, i82374_read_isr, s);
-    register_ioport_write(isa->iobase + 0x10, 8, 1, i82374_write_command, s);
-    register_ioport_read(isa->iobase + 0x18, 8, 1, i82374_read_status, s);
-    register_ioport_write(isa->iobase + 0x20, 0x20, 1, i82374_write_descriptor, s);
-    register_ioport_read(isa->iobase + 0x20, 0x20, 1, i82374_read_descriptor, s);
+    portio_list_init(port_list, OBJECT(isa), i82374_portio_list, s, "i82374");
+    portio_list_add(port_list, isa_address_space_io(&isa->parent_obj),
+                    isa->iobase);
 
     i82374_realize(s, errp);
 
diff --git a/hw/dma/i8257.c b/hw/dma/i8257.c
index eb60d45..4490372 100644
--- a/hw/dma/i8257.c
+++ b/hw/dma/i8257.c
@@ -523,7 +523,7 @@
     d->dshift = dshift;
     d->cpu_request_exit = cpu_request_exit;
 
-    memory_region_init_io(&d->channel_io, &channel_io_ops, d,
+    memory_region_init_io(&d->channel_io, NULL, &channel_io_ops, d,
                           "dma-chan", 8 << d->dshift);
     memory_region_add_subregion(isa_address_space_io(NULL),
                                 base, &d->channel_io);
@@ -535,7 +535,7 @@
                                  "dma-pageh");
     }
 
-    memory_region_init_io(&d->cont_io, &cont_io_ops, d, "dma-cont",
+    memory_region_init_io(&d->cont_io, NULL, &cont_io_ops, d, "dma-cont",
                           8 << d->dshift);
     memory_region_add_subregion(isa_address_space_io(NULL),
                                 base + (8 << d->dshift), &d->cont_io);
diff --git a/hw/dma/omap_dma.c b/hw/dma/omap_dma.c
index 184fcee..a81ffc4 100644
--- a/hw/dma/omap_dma.c
+++ b/hw/dma/omap_dma.c
@@ -1663,7 +1663,7 @@
     omap_dma_reset(s->dma);
     omap_dma_clk_update(s, 0, 1);
 
-    memory_region_init_io(&s->iomem, &omap_dma_ops, s, "omap.dma", memsize);
+    memory_region_init_io(&s->iomem, NULL, &omap_dma_ops, s, "omap.dma", memsize);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
     mpu->drq = s->dma->drq;
@@ -2085,7 +2085,7 @@
     omap_dma_reset(s->dma);
     omap_dma_clk_update(s, 0, !!s->dma->freq);
 
-    memory_region_init_io(&s->iomem, &omap_dma4_ops, s, "omap.dma4", 0x1000);
+    memory_region_init_io(&s->iomem, NULL, &omap_dma4_ops, s, "omap.dma4", 0x1000);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
     mpu->drq = s->dma->drq;
diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c
index 00b66b4..7937c3e 100644
--- a/hw/dma/pl080.c
+++ b/hw/dma/pl080.c
@@ -359,7 +359,7 @@
 {
     pl080_state *s = FROM_SYSBUS(pl080_state, dev);
 
-    memory_region_init_io(&s->iomem, &pl080_ops, s, "pl080", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &pl080_ops, s, "pl080", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     s->nchannels = nchannels;
diff --git a/hw/dma/pl330.c b/hw/dma/pl330.c
index 044c087..ddcc413 100644
--- a/hw/dma/pl330.c
+++ b/hw/dma/pl330.c
@@ -1528,7 +1528,8 @@
     PL330State *s = PL330(dev);
 
     sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq_abort);
-    memory_region_init_io(&s->iomem, &pl330_ops, s, "dma", PL330_IOMEM_SIZE);
+    memory_region_init_io(&s->iomem, OBJECT(s), &pl330_ops, s,
+                          "dma", PL330_IOMEM_SIZE);
     sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
 
     s->timer = qemu_new_timer_ns(vm_clock, pl330_exec_cycle_timer, s);
diff --git a/hw/dma/puv3_dma.c b/hw/dma/puv3_dma.c
index 32844b5..36004ae 100644
--- a/hw/dma/puv3_dma.c
+++ b/hw/dma/puv3_dma.c
@@ -80,7 +80,7 @@
         s->reg_CFG[i] = 0x0;
     }
 
-    memory_region_init_io(&s->iomem, &puv3_dma_ops, s, "puv3_dma",
+    memory_region_init_io(&s->iomem, OBJECT(s), &puv3_dma_ops, s, "puv3_dma",
             PUV3_REGS_OFFSET);
     sysbus_init_mmio(dev, &s->iomem);
 
diff --git a/hw/dma/pxa2xx_dma.c b/hw/dma/pxa2xx_dma.c
index b60569f..bc7bf4c 100644
--- a/hw/dma/pxa2xx_dma.c
+++ b/hw/dma/pxa2xx_dma.c
@@ -465,7 +465,7 @@
 
     qdev_init_gpio_in(&dev->qdev, pxa2xx_dma_request, PXA2XX_DMA_NUM_REQUESTS);
 
-    memory_region_init_io(&s->iomem, &pxa2xx_dma_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_dma_ops, s,
                           "pxa2xx.dma", 0x00010000);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
index 03f92f1..4ec433f 100644
--- a/hw/dma/rc4030.c
+++ b/hw/dma/rc4030.c
@@ -814,10 +814,10 @@
     register_savevm(NULL, "rc4030", 0, 2, rc4030_save, rc4030_load, s);
     rc4030_reset(s);
 
-    memory_region_init_io(&s->iomem_chipset, &rc4030_ops, s,
+    memory_region_init_io(&s->iomem_chipset, NULL, &rc4030_ops, s,
                           "rc4030.chipset", 0x300);
     memory_region_add_subregion(sysmem, 0x80000000, &s->iomem_chipset);
-    memory_region_init_io(&s->iomem_jazzio, &jazzio_ops, s,
+    memory_region_init_io(&s->iomem_jazzio, NULL, &jazzio_ops, s,
                           "rc4030.jazzio", 0x00001000);
     memory_region_add_subregion(sysmem, 0xf0000000, &s->iomem_jazzio);
 
diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c
index fd21533..be6275f 100644
--- a/hw/dma/sparc32_dma.c
+++ b/hw/dma/sparc32_dma.c
@@ -274,7 +274,8 @@
     sysbus_init_irq(dev, &s->irq);
 
     reg_size = s->is_ledma ? DMA_ETH_SIZE : DMA_SIZE;
-    memory_region_init_io(&s->iomem, &dma_mem_ops, s, "dma", reg_size);
+    memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s,
+                          "dma", reg_size);
     sysbus_init_mmio(dev, &s->iomem);
 
     qdev_init_gpio_in(&dev->qdev, dma_set_irq, 1);
diff --git a/hw/dma/sun4m_iommu.c b/hw/dma/sun4m_iommu.c
index 8312bff..edb93f3 100644
--- a/hw/dma/sun4m_iommu.c
+++ b/hw/dma/sun4m_iommu.c
@@ -349,7 +349,7 @@
 
     sysbus_init_irq(dev, &s->irq);
 
-    memory_region_init_io(&s->iomem, &iommu_mem_ops, s, "iommu",
+    memory_region_init_io(&s->iomem, OBJECT(s), &iommu_mem_ops, s, "iommu",
                           IOMMU_NREGS * sizeof(uint32_t));
     sysbus_init_mmio(dev, &s->iomem);
 
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
index 50054cf..a48e3ba 100644
--- a/hw/dma/xilinx_axidma.c
+++ b/hw/dma/xilinx_axidma.c
@@ -590,7 +590,7 @@
     sysbus_init_irq(sbd, &s->streams[0].irq);
     sysbus_init_irq(sbd, &s->streams[1].irq);
 
-    memory_region_init_io(&s->iomem, &axidma_ops, s,
+    memory_region_init_io(&s->iomem, obj, &axidma_ops, s,
                           "xlnx.axi-dma", R_MAX * 4 * 2);
     sysbus_init_mmio(sbd, &s->iomem);
 }
diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c
index f5eeaea..855afae 100644
--- a/hw/gpio/omap_gpio.c
+++ b/hw/gpio/omap_gpio.c
@@ -677,7 +677,7 @@
     qdev_init_gpio_in(&dev->qdev, omap_gpio_set, 16);
     qdev_init_gpio_out(&dev->qdev, s->omap1.handler, 16);
     sysbus_init_irq(dev, &s->omap1.irq);
-    memory_region_init_io(&s->iomem, &omap_gpio_ops, &s->omap1,
+    memory_region_init_io(&s->iomem, OBJECT(s), &omap_gpio_ops, &s->omap1,
                           "omap.gpio", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     return 0;
@@ -692,7 +692,7 @@
     }
     if (s->mpu_model < omap3430) {
         s->modulecount = (s->mpu_model < omap2430) ? 4 : 5;
-        memory_region_init_io(&s->iomem, &omap2_gpif_top_ops, s,
+        memory_region_init_io(&s->iomem, OBJECT(s), &omap2_gpif_top_ops, s,
                               "omap2.gpio", 0x1000);
         sysbus_init_mmio(dev, &s->iomem);
     } else {
@@ -712,7 +712,7 @@
         sysbus_init_irq(dev, &m->irq[0]); /* mpu irq */
         sysbus_init_irq(dev, &m->irq[1]); /* dsp irq */
         sysbus_init_irq(dev, &m->wkup);
-        memory_region_init_io(&m->iomem, &omap2_gpio_module_ops, m,
+        memory_region_init_io(&m->iomem, OBJECT(s), &omap2_gpio_module_ops, m,
                               "omap.gpio-module", 0x1000);
         sysbus_init_mmio(dev, &m->iomem);
     }
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
index 74bc109..a0bbf08 100644
--- a/hw/gpio/pl061.c
+++ b/hw/gpio/pl061.c
@@ -276,7 +276,7 @@
 {
     pl061_state *s = FROM_SYSBUS(pl061_state, dev);
     s->id = id;
-    memory_region_init_io(&s->iomem, &pl061_ops, s, "pl061", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &pl061_ops, s, "pl061", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     qdev_init_gpio_in(&dev->qdev, pl061_set_irq, 8);
diff --git a/hw/gpio/puv3_gpio.c b/hw/gpio/puv3_gpio.c
index 5bab97e..18671eb 100644
--- a/hw/gpio/puv3_gpio.c
+++ b/hw/gpio/puv3_gpio.c
@@ -112,7 +112,7 @@
     sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW7]);
     sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOHIGH]);
 
-    memory_region_init_io(&s->iomem, &puv3_gpio_ops, s, "puv3_gpio",
+    memory_region_init_io(&s->iomem, OBJECT(s), &puv3_gpio_ops, s, "puv3_gpio",
             PUV3_REGS_OFFSET);
     sysbus_init_mmio(dev, &s->iomem);
 
diff --git a/hw/gpio/zaurus.c b/hw/gpio/zaurus.c
index c6cdef3..c235c3e 100644
--- a/hw/gpio/zaurus.c
+++ b/hw/gpio/zaurus.c
@@ -169,7 +169,7 @@
     s->status = 0x02;
     qdev_init_gpio_out(&s->busdev.qdev, s->handler, 16);
     qdev_init_gpio_in(&s->busdev.qdev, scoop_gpio_set, 16);
-    memory_region_init_io(&s->iomem, &scoop_ops, s, "scoop", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &scoop_ops, s, "scoop", 0x1000);
 
     sysbus_init_mmio(dev, &s->iomem);
 
diff --git a/hw/i2c/bitbang_i2c.c b/hw/i2c/bitbang_i2c.c
index 854b8e1..5f8b972 100644
--- a/hw/i2c/bitbang_i2c.c
+++ b/hw/i2c/bitbang_i2c.c
@@ -209,7 +209,7 @@
     GPIOI2CState *s = FROM_SYSBUS(GPIOI2CState, dev);
     i2c_bus *bus;
 
-    memory_region_init(&s->dummy_iomem, "gpio_i2c", 0);
+    memory_region_init(&s->dummy_iomem, OBJECT(s), "gpio_i2c", 0);
     sysbus_init_mmio(dev, &s->dummy_iomem);
 
     bus = i2c_init_bus(&dev->qdev, "i2c");
diff --git a/hw/i2c/exynos4210_i2c.c b/hw/i2c/exynos4210_i2c.c
index 196f889..52bffa5 100644
--- a/hw/i2c/exynos4210_i2c.c
+++ b/hw/i2c/exynos4210_i2c.c
@@ -301,8 +301,8 @@
 {
     Exynos4210I2CState *s = EXYNOS4_I2C(dev);
 
-    memory_region_init_io(&s->iomem, &exynos4210_i2c_ops, s, TYPE_EXYNOS4_I2C,
-                          EXYNOS4_I2C_MEM_SIZE);
+    memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_i2c_ops, s,
+                          TYPE_EXYNOS4_I2C, EXYNOS4_I2C_MEM_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     s->bus = i2c_init_bus(&dev->qdev, "i2c");
diff --git a/hw/i2c/omap_i2c.c b/hw/i2c/omap_i2c.c
index efb2254..f0eb448 100644
--- a/hw/i2c/omap_i2c.c
+++ b/hw/i2c/omap_i2c.c
@@ -448,7 +448,7 @@
     sysbus_init_irq(dev, &s->irq);
     sysbus_init_irq(dev, &s->drq[0]);
     sysbus_init_irq(dev, &s->drq[1]);
-    memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap.i2c",
+    memory_region_init_io(&s->iomem, OBJECT(s), &omap_i2c_ops, s, "omap.i2c",
                           (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     s->bus = i2c_init_bus(&dev->qdev, NULL);
diff --git a/hw/i2c/pm_smbus.c b/hw/i2c/pm_smbus.c
index 0b5bb89..c98e447 100644
--- a/hw/i2c/pm_smbus.c
+++ b/hw/i2c/pm_smbus.c
@@ -32,6 +32,18 @@
 #define SMBHSTDAT1      0x06
 #define SMBBLKDAT       0x07
 
+#define STS_HOST_BUSY   (1)
+#define STS_INTR        (1<<1)
+#define STS_DEV_ERR     (1<<2)
+#define STS_BUS_ERR     (1<<3)
+#define STS_FAILED      (1<<4)
+#define STS_SMBALERT    (1<<5)
+#define STS_INUSE_STS   (1<<6)
+#define STS_BYTE_DONE   (1<<7)
+/* Signs of successfully transaction end :
+*  ByteDoneStatus = 1 (STS_BYTE_DONE) and INTR = 1 (STS_INTR )
+*/
+
 //#define DEBUG
 
 #ifdef DEBUG
@@ -50,9 +62,14 @@
     i2c_bus *bus = s->smbus;
 
     SMBUS_DPRINTF("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
+    /* Transaction isn't exec if STS_DEV_ERR bit set */
+    if ((s->smb_stat & STS_DEV_ERR) != 0)  {
+            goto error;
+        }
     switch(prot) {
     case 0x0:
         smbus_quick_command(bus, addr, read);
+        s->smb_stat |= STS_BYTE_DONE | STS_INTR;
         break;
     case 0x1:
         if (read) {
@@ -60,6 +77,7 @@
         } else {
             smbus_send_byte(bus, addr, cmd);
         }
+        s->smb_stat |= STS_BYTE_DONE | STS_INTR;
         break;
     case 0x2:
         if (read) {
@@ -67,6 +85,7 @@
         } else {
             smbus_write_byte(bus, addr, cmd, s->smb_data0);
         }
+        s->smb_stat |= STS_BYTE_DONE | STS_INTR;
         break;
     case 0x3:
         if (read) {
@@ -77,6 +96,7 @@
         } else {
             smbus_write_word(bus, addr, cmd, (s->smb_data1 << 8) | s->smb_data0);
         }
+        s->smb_stat |= STS_BYTE_DONE | STS_INTR;
         break;
     case 0x5:
         if (read) {
@@ -84,6 +104,7 @@
         } else {
             smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0);
         }
+        s->smb_stat |= STS_BYTE_DONE | STS_INTR;
         break;
     default:
         goto error;
@@ -91,7 +112,7 @@
     return;
 
   error:
-    s->smb_stat |= 0x04;
+    s->smb_stat |= STS_DEV_ERR;
 }
 
 static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
@@ -102,7 +123,7 @@
     SMBUS_DPRINTF("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
     switch(addr) {
     case SMBHSTSTS:
-        s->smb_stat = 0;
+        s->smb_stat = (~(val & 0xff)) & s->smb_stat;
         s->smb_index = 0;
         break;
     case SMBHSTCNT:
@@ -181,5 +202,6 @@
 void pm_smbus_init(DeviceState *parent, PMSMBus *smb)
 {
     smb->smbus = i2c_init_bus(parent, "i2c");
-    memory_region_init_io(&smb->io, &pm_smbus_ops, smb, "pm-smbus", 64);
+    memory_region_init_io(&smb->io, OBJECT(parent), &pm_smbus_ops, smb,
+                          "pm-smbus", 64);
 }
diff --git a/hw/i2c/versatile_i2c.c b/hw/i2c/versatile_i2c.c
index e09c83d..204dd3d 100644
--- a/hw/i2c/versatile_i2c.c
+++ b/hw/i2c/versatile_i2c.c
@@ -79,7 +79,7 @@
 
     bus = i2c_init_bus(&dev->qdev, "i2c");
     s->bitbang = bitbang_i2c_init(bus);
-    memory_region_init_io(&s->iomem, &versatile_i2c_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &versatile_i2c_ops, s,
                           "versatile_i2c", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     return 0;
diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c
index bd0bdd8..179b806 100644
--- a/hw/i386/kvm/apic.c
+++ b/hw/i386/kvm/apic.c
@@ -173,7 +173,7 @@
 
 static void kvm_apic_init(APICCommonState *s)
 {
-    memory_region_init_io(&s->io_memory, &kvm_apic_io_ops, s, "kvm-apic-msi",
+    memory_region_init_io(&s->io_memory, NULL, &kvm_apic_io_ops, s, "kvm-apic-msi",
                           APIC_SPACE_SIZE);
 
     if (kvm_has_gsi_routing()) {
diff --git a/hw/i386/kvm/i8254.c b/hw/i386/kvm/i8254.c
index 93a3669..c1f4094 100644
--- a/hw/i386/kvm/i8254.c
+++ b/hw/i386/kvm/i8254.c
@@ -288,7 +288,7 @@
         return;
     }
 
-    memory_region_init_reservation(&pit->ioports, "kvm-pit", 4);
+    memory_region_init_reservation(&pit->ioports, NULL, "kvm-pit", 4);
 
     qdev_init_gpio_in(dev, kvm_pit_irq_control, 1);
 
diff --git a/hw/i386/kvm/i8259.c b/hw/i386/kvm/i8259.c
index 1250224..53e3ca8 100644
--- a/hw/i386/kvm/i8259.c
+++ b/hw/i386/kvm/i8259.c
@@ -119,8 +119,8 @@
     PICCommonState *s = PIC_COMMON(dev);
     KVMPICClass *kpc = KVM_PIC_GET_CLASS(dev);
 
-    memory_region_init_reservation(&s->base_io, "kvm-pic", 2);
-    memory_region_init_reservation(&s->elcr_io, "kvm-elcr", 1);
+    memory_region_init_reservation(&s->base_io, NULL, "kvm-pic", 2);
+    memory_region_init_reservation(&s->elcr_io, NULL, "kvm-elcr", 1);
 
     kpc->parent_realize(dev, errp);
 }
diff --git a/hw/i386/kvm/ioapic.c b/hw/i386/kvm/ioapic.c
index abfac3d..688cb5c 100644
--- a/hw/i386/kvm/ioapic.c
+++ b/hw/i386/kvm/ioapic.c
@@ -129,7 +129,7 @@
 
 static void kvm_ioapic_init(IOAPICCommonState *s, int instance_no)
 {
-    memory_region_init_reservation(&s->io_memory, "kvm-ioapic", 0x1000);
+    memory_region_init_reservation(&s->io_memory, NULL, "kvm-ioapic", 0x1000);
 
     qdev_init_gpio_in(&s->busdev.qdev, kvm_ioapic_set_irq, IOAPIC_NUM_PINS);
 }
diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c
index eab2d3e..ff33dc8 100644
--- a/hw/i386/kvm/pci-assign.c
+++ b/hw/i386/kvm/pci-assign.c
@@ -298,8 +298,8 @@
     PCIRegion *real_region = &r_dev->real_device.regions[region_num];
 
     if (e_size > 0) {
-        memory_region_init(&region->container, "assigned-dev-container",
-                           e_size);
+        memory_region_init(&region->container, OBJECT(pci_dev),
+                           "assigned-dev-container", e_size);
         memory_region_add_subregion(&region->container, 0, &region->real_iomem);
 
         /* deal with MSI-X MMIO page */
@@ -329,9 +329,10 @@
     AssignedDevRegion *region = &r_dev->v_addrs[region_num];
 
     region->e_size = size;
-    memory_region_init(&region->container, "assigned-dev-container", size);
-    memory_region_init_io(&region->real_iomem, &assigned_dev_ioport_ops,
-                          r_dev->v_addrs + region_num,
+    memory_region_init(&region->container, OBJECT(pci_dev),
+                       "assigned-dev-container", size);
+    memory_region_init_io(&region->real_iomem, OBJECT(pci_dev),
+                          &assigned_dev_ioport_ops, r_dev->v_addrs + region_num,
                           "assigned-dev-iomem", size);
     memory_region_add_subregion(&region->container, 0, &region->real_iomem);
 }
@@ -479,7 +480,8 @@
                              "due to that.",
                              i, cur_region->base_addr, cur_region->size);
                 memory_region_init_io(&pci_dev->v_addrs[i].real_iomem,
-                                      &slow_bar_ops, &pci_dev->v_addrs[i],
+                                      OBJECT(pci_dev), &slow_bar_ops,
+                                      &pci_dev->v_addrs[i],
                                       "assigned-dev-slow-bar",
                                       cur_region->size);
             } else {
@@ -488,8 +490,8 @@
                 snprintf(name, sizeof(name), "%s.bar%d",
                          object_get_typename(OBJECT(pci_dev)), i);
                 memory_region_init_ram_ptr(&pci_dev->v_addrs[i].real_iomem,
-                                           name, cur_region->size,
-                                           virtbase);
+                                           OBJECT(pci_dev), name,
+                                           cur_region->size, virtbase);
                 vmstate_register_ram(&pci_dev->v_addrs[i].real_iomem,
                                      &pci_dev->dev.qdev);
             }
@@ -1650,8 +1652,8 @@
 
     assigned_dev_msix_reset(dev);
 
-    memory_region_init_io(&dev->mmio, &assigned_dev_msix_mmio_ops, dev,
-                          "assigned-dev-msix", MSIX_PAGE_SIZE);
+    memory_region_init_io(&dev->mmio, OBJECT(dev), &assigned_dev_msix_mmio_ops,
+                          dev, "assigned-dev-msix", MSIX_PAGE_SIZE);
     return 0;
 }
 
@@ -1916,7 +1918,7 @@
 
     snprintf(name, sizeof(name), "%s.rom",
             object_get_typename(OBJECT(dev)));
-    memory_region_init_ram(&dev->dev.rom, name, st.st_size);
+    memory_region_init_ram(&dev->dev.rom, OBJECT(dev), name, st.st_size);
     vmstate_register_ram(&dev->dev.rom, &dev->dev.qdev);
     ptr = memory_region_get_ram_ptr(&dev->dev.rom);
     memset(ptr, 0xff, st.st_size);
diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
index f93629f..9850a85 100644
--- a/hw/i386/kvmvapic.c
+++ b/hw/i386/kvmvapic.c
@@ -601,10 +601,11 @@
     rom_paddr &= TARGET_PAGE_MASK;
     rom_size = TARGET_PAGE_ALIGN(rom_size);
 
-    memory_region_init_alias(&s->rom, "kvmvapic-rom", section.mr, rom_paddr,
-                             rom_size);
+    memory_region_init_alias(&s->rom, OBJECT(s), "kvmvapic-rom", section.mr,
+                             rom_paddr, rom_size);
     memory_region_add_subregion_overlap(as, rom_paddr, &s->rom, 1000);
     s->rom_mapped_writable = true;
+    memory_region_unref(section.mr);
 }
 
 static int vapic_prepare(VAPICROMState *s)
@@ -702,7 +703,7 @@
 {
     VAPICROMState *s = VAPIC(dev);
 
-    memory_region_init_io(&s->io, &vapic_ops, s, "kvmvapic", 2);
+    memory_region_init_io(&s->io, OBJECT(s), &vapic_ops, s, "kvmvapic", 2);
     sysbus_add_io(dev, VAPIC_IO_PORT, &s->io);
     sysbus_init_ioports(dev, VAPIC_IO_PORT, 2);
 
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 78f92e2..e00f9dc 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -525,7 +525,7 @@
 {
     Port92State *s = PORT92(obj);
 
-    memory_region_init_io(&s->io, &port92_ops, s, "port92", 1);
+    memory_region_init_io(&s->io, OBJECT(s), &port92_ops, s, "port92", 1);
 
     s->outport = 0;
 }
@@ -989,6 +989,74 @@
     }
 }
 
+/* pci-info ROM file. Little endian format */
+typedef struct PcRomPciInfo {
+    uint64_t w32_min;
+    uint64_t w32_max;
+    uint64_t w64_min;
+    uint64_t w64_max;
+} PcRomPciInfo;
+
+static void pc_fw_cfg_guest_info(PcGuestInfo *guest_info)
+{
+    PcRomPciInfo *info;
+    if (!guest_info->has_pci_info) {
+        return;
+    }
+
+    info = g_malloc(sizeof *info);
+    info->w32_min = cpu_to_le64(guest_info->pci_info.w32.begin);
+    info->w32_max = cpu_to_le64(guest_info->pci_info.w32.end);
+    info->w64_min = cpu_to_le64(guest_info->pci_info.w64.begin);
+    info->w64_max = cpu_to_le64(guest_info->pci_info.w64.end);
+    /* Pass PCI hole info to guest via a side channel.
+     * Required so guest PCI enumeration does the right thing. */
+    fw_cfg_add_file(guest_info->fw_cfg, "etc/pci-info", info, sizeof *info);
+}
+
+typedef struct PcGuestInfoState {
+    PcGuestInfo info;
+    Notifier machine_done;
+} PcGuestInfoState;
+
+static
+void pc_guest_info_machine_done(Notifier *notifier, void *data)
+{
+    PcGuestInfoState *guest_info_state = container_of(notifier,
+                                                      PcGuestInfoState,
+                                                      machine_done);
+    pc_fw_cfg_guest_info(&guest_info_state->info);
+}
+
+PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
+                                ram_addr_t above_4g_mem_size)
+{
+    PcGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state);
+    PcGuestInfo *guest_info = &guest_info_state->info;
+
+    guest_info->pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS;
+    if (sizeof(hwaddr) == 4) {
+        guest_info->pci_info.w64.begin = 0;
+        guest_info->pci_info.w64.end = 0;
+    } else {
+        /*
+         * BIOS does not set MTRR entries for the 64 bit window, so no need to
+         * align address to power of two.  Align address at 1G, this makes sure
+         * it can be exactly covered with a PAT entry even when using huge
+         * pages.
+         */
+        guest_info->pci_info.w64.begin =
+            ROUND_UP((0x1ULL << 32) + above_4g_mem_size, 0x1ULL << 30);
+        guest_info->pci_info.w64.end = guest_info->pci_info.w64.begin +
+            (0x1ULL << 62);
+        assert(guest_info->pci_info.w64.begin <= guest_info->pci_info.w64.end);
+    }
+
+    guest_info_state->machine_done.notify = pc_guest_info_machine_done;
+    qemu_add_machine_init_done_notifier(&guest_info_state->machine_done);
+    return guest_info;
+}
+
 void pc_acpi_init(const char *default_dsdt)
 {
     char *filename;
@@ -1030,7 +1098,8 @@
                            ram_addr_t below_4g_mem_size,
                            ram_addr_t above_4g_mem_size,
                            MemoryRegion *rom_memory,
-                           MemoryRegion **ram_memory)
+                           MemoryRegion **ram_memory,
+                           PcGuestInfo *guest_info)
 {
     int linux_boot, i;
     MemoryRegion *ram, *option_rom_mr;
@@ -1044,17 +1113,17 @@
      * with older qemus that used qemu_ram_alloc().
      */
     ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, "pc.ram",
+    memory_region_init_ram(ram, NULL, "pc.ram",
                            below_4g_mem_size + above_4g_mem_size);
     vmstate_register_ram_global(ram);
     *ram_memory = ram;
     ram_below_4g = g_malloc(sizeof(*ram_below_4g));
-    memory_region_init_alias(ram_below_4g, "ram-below-4g", ram,
+    memory_region_init_alias(ram_below_4g, NULL, "ram-below-4g", ram,
                              0, below_4g_mem_size);
     memory_region_add_subregion(system_memory, 0, ram_below_4g);
     if (above_4g_mem_size > 0) {
         ram_above_4g = g_malloc(sizeof(*ram_above_4g));
-        memory_region_init_alias(ram_above_4g, "ram-above-4g", ram,
+        memory_region_init_alias(ram_above_4g, NULL, "ram-above-4g", ram,
                                  below_4g_mem_size, above_4g_mem_size);
         memory_region_add_subregion(system_memory, 0x100000000ULL,
                                     ram_above_4g);
@@ -1065,7 +1134,7 @@
     pc_system_firmware_init(rom_memory);
 
     option_rom_mr = g_malloc(sizeof(*option_rom_mr));
-    memory_region_init_ram(option_rom_mr, "pc.rom", PC_ROM_SIZE);
+    memory_region_init_ram(option_rom_mr, NULL, "pc.rom", PC_ROM_SIZE);
     vmstate_register_ram_global(option_rom_mr);
     memory_region_add_subregion_overlap(rom_memory,
                                         PC_ROM_MIN_VGA,
@@ -1082,6 +1151,7 @@
     for (i = 0; i < nb_option_roms; i++) {
         rom_add_option(option_rom[i].name, option_rom[i].bootindex);
     }
+    guest_info->fw_cfg = fw_cfg;
     return fw_cfg;
 }
 
@@ -1150,10 +1220,10 @@
     MemoryRegion *ioport80_io = g_new(MemoryRegion, 1);
     MemoryRegion *ioportF0_io = g_new(MemoryRegion, 1);
 
-    memory_region_init_io(ioport80_io, &ioport80_io_ops, NULL, "ioport80", 1);
+    memory_region_init_io(ioport80_io, NULL, &ioport80_io_ops, NULL, "ioport80", 1);
     memory_region_add_subregion(isa_bus->address_space_io, 0x80, ioport80_io);
 
-    memory_region_init_io(ioportF0_io, &ioportF0_io_ops, NULL, "ioportF0", 1);
+    memory_region_init_io(ioportF0_io, NULL, &ioportF0_io_ops, NULL, "ioportF0", 1);
     memory_region_add_subregion(isa_bus->address_space_io, 0xf0, ioportF0_io);
 
     /*
@@ -1240,7 +1310,7 @@
         if (!pci_bus || (nd->model && strcmp(nd->model, "ne2k_isa") == 0)) {
             pc_init_ne2k_isa(isa_bus, nd);
         } else {
-            pci_nic_init_nofail(nd, "e1000", NULL);
+            pci_nic_init_nofail(nd, pci_bus, "e1000", NULL);
         }
     }
 }
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index fa59a0c..01323a9 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -57,6 +57,7 @@
 static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
 
 static bool has_pvpanic = true;
+static bool has_pci_info = true;
 
 /* PC hardware initialisation */
 static void pc_init1(MemoryRegion *system_memory,
@@ -90,6 +91,7 @@
     MemoryRegion *rom_memory;
     DeviceState *icc_bridge;
     FWCfgState *fw_cfg = NULL;
+    PcGuestInfo *guest_info;
 
     if (xen_enabled() && xen_hvm_init() != 0) {
         fprintf(stderr, "xen hardware virtual machine initialisation failed\n");
@@ -117,19 +119,31 @@
 
     if (pci_enabled) {
         pci_memory = g_new(MemoryRegion, 1);
-        memory_region_init(pci_memory, "pci", INT64_MAX);
+        memory_region_init(pci_memory, NULL, "pci", INT64_MAX);
         rom_memory = pci_memory;
     } else {
         pci_memory = NULL;
         rom_memory = system_memory;
     }
 
+    guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
+    guest_info->has_pci_info = has_pci_info;
+
+    /* Set PCI window size the way seabios has always done it. */
+    /* Power of 2 so bios can cover it with a single MTRR */
+    if (ram_size <= 0x80000000)
+        guest_info->pci_info.w32.begin = 0x80000000;
+    else if (ram_size <= 0xc0000000)
+        guest_info->pci_info.w32.begin = 0xc0000000;
+    else
+        guest_info->pci_info.w32.begin = 0xe0000000;
+
     /* allocate ram and load rom/bios */
     if (!xen_enabled()) {
         fw_cfg = pc_memory_init(system_memory,
                        kernel_filename, kernel_cmdline, initrd_filename,
                        below_4g_mem_size, above_4g_mem_size,
-                       rom_memory, &ram_memory);
+                       rom_memory, &ram_memory, guest_info);
     }
 
     gsi_state = g_malloc0(sizeof(*gsi_state));
@@ -248,36 +262,36 @@
              initrd_filename, cpu_model, 1, 1);
 }
 
+static void pc_init_pci_1_5(QEMUMachineInitArgs *args)
+{
+    has_pci_info = false;
+    pc_init_pci(args);
+}
+
 static void pc_init_pci_1_4(QEMUMachineInitArgs *args)
 {
     has_pvpanic = false;
     x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE);
-    pc_init_pci(args);
+    pc_init_pci_1_5(args);
 }
 
 static void pc_init_pci_1_3(QEMUMachineInitArgs *args)
 {
     enable_compat_apic_id_mode();
-    has_pvpanic = false;
-    pc_init_pci(args);
+    pc_init_pci_1_4(args);
 }
 
 /* PC machine init function for pc-1.1 to pc-1.2 */
 static void pc_init_pci_1_2(QEMUMachineInitArgs *args)
 {
     disable_kvm_pv_eoi();
-    enable_compat_apic_id_mode();
-    has_pvpanic = false;
-    pc_init_pci(args);
+    pc_init_pci_1_3(args);
 }
 
 /* PC machine init function for pc-0.14 to pc-1.0 */
 static void pc_init_pci_1_0(QEMUMachineInitArgs *args)
 {
-    disable_kvm_pv_eoi();
-    enable_compat_apic_id_mode();
-    has_pvpanic = false;
-    pc_init_pci(args);
+    pc_init_pci_1_2(args);
 }
 
 /* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */
@@ -290,6 +304,7 @@
     const char *initrd_filename = args->initrd_filename;
     const char *boot_device = args->boot_device;
     has_pvpanic = false;
+    has_pci_info = false;
     disable_kvm_pv_eoi();
     enable_compat_apic_id_mode();
     pc_init1(get_system_memory(),
@@ -308,6 +323,7 @@
     const char *initrd_filename = args->initrd_filename;
     const char *boot_device = args->boot_device;
     has_pvpanic = false;
+    has_pci_info = false;
     if (cpu_model == NULL)
         cpu_model = "486";
     disable_kvm_pv_eoi();
@@ -326,7 +342,7 @@
 
     pc_init_pci(args);
 
-    bus = pci_find_root_bus(0);
+    bus = pci_find_primary_bus();
     if (bus != NULL) {
         pci_create_simple(bus, -1, "xen-platform");
     }
@@ -347,7 +363,7 @@
 static QEMUMachine pc_i440fx_machine_v1_5 = {
     .name = "pc-i440fx-1.5",
     .desc = "Standard PC (i440FX + PIIX, 1996)",
-    .init = pc_init_pci,
+    .init = pc_init_pci_1_5,
     .hot_add_cpu = pc_hot_add_cpu,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index bb0ce6a..6f10246 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -47,6 +47,7 @@
 #define MAX_SATA_PORTS     6
 
 static bool has_pvpanic = true;
+static bool has_pci_info = true;
 
 /* PC hardware initialisation */
 static void pc_q35_init(QEMUMachineInitArgs *args)
@@ -77,6 +78,7 @@
     ICH9LPCState *ich9_lpc;
     PCIDevice *ahci;
     DeviceState *icc_bridge;
+    PcGuestInfo *guest_info;
 
     icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
     object_property_add_child(qdev_get_machine(), "icc-bridge",
@@ -98,18 +100,21 @@
     /* pci enabled */
     if (pci_enabled) {
         pci_memory = g_new(MemoryRegion, 1);
-        memory_region_init(pci_memory, "pci", INT64_MAX);
+        memory_region_init(pci_memory, NULL, "pci", INT64_MAX);
         rom_memory = pci_memory;
     } else {
         pci_memory = NULL;
         rom_memory = get_system_memory();
     }
 
+    guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
+    guest_info->has_pci_info = has_pci_info;
+
     /* allocate ram and load rom/bios */
     if (!xen_enabled()) {
         pc_memory_init(get_system_memory(), kernel_filename, kernel_cmdline,
                        initrd_filename, below_4g_mem_size, above_4g_mem_size,
-                       rom_memory, &ram_memory);
+                       rom_memory, &ram_memory, guest_info);
     }
 
     /* irq lines */
@@ -131,6 +136,7 @@
     q35_host->mch.address_space_io = get_system_io();
     q35_host->mch.below_4g_mem_size = below_4g_mem_size;
     q35_host->mch.above_4g_mem_size = above_4g_mem_size;
+    q35_host->mch.guest_info = guest_info;
     /* pci */
     qdev_init_nofail(DEVICE(q35_host));
     host_bus = q35_host->host.pci.bus;
@@ -208,11 +214,17 @@
     }
 }
 
+static void pc_q35_init_1_5(QEMUMachineInitArgs *args)
+{
+    has_pci_info = false;
+    pc_q35_init(args);
+}
+
 static void pc_q35_init_1_4(QEMUMachineInitArgs *args)
 {
     has_pvpanic = false;
     x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE);
-    pc_q35_init(args);
+    pc_q35_init_1_5(args);
 }
 
 static QEMUMachine pc_q35_machine_v1_6 = {
@@ -228,7 +240,7 @@
 static QEMUMachine pc_q35_machine_v1_5 = {
     .name = "pc-q35-1.5",
     .desc = "Standard PC (Q35 + ICH9, 2009)",
-    .init = pc_q35_init,
+    .init = pc_q35_init_1_5,
     .hot_add_cpu = pc_hot_add_cpu,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 1adfa0b..97eddec 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -650,6 +650,8 @@
     int off_idx = -1;
     int off_pos = -1;
     int tbl_entry_size;
+    IDEBus *bus = &ad->port;
+    BusState *qbus = BUS(bus);
 
     if (!sglist_alloc_hint) {
         DPRINTF(ad->port_no, "no sg list given by guest: 0x%08x\n", opts);
@@ -691,7 +693,8 @@
             goto out;
         }
 
-        qemu_sglist_init(sglist, (sglist_alloc_hint - off_idx), ad->hba->as);
+        qemu_sglist_init(sglist, qbus->parent, (sglist_alloc_hint - off_idx),
+                         ad->hba->as);
         qemu_sglist_add(sglist, le64_to_cpu(tbl[off_idx].addr + off_pos),
                         le32_to_cpu(tbl[off_idx].flags_size) + 1 - off_pos);
 
@@ -1155,8 +1158,10 @@
     s->dev = g_malloc0(sizeof(AHCIDevice) * ports);
     ahci_reg_init(s);
     /* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
-    memory_region_init_io(&s->mem, &ahci_mem_ops, s, "ahci", AHCI_MEM_BAR_SIZE);
-    memory_region_init_io(&s->idp, &ahci_idp_ops, s, "ahci-idp", 32);
+    memory_region_init_io(&s->mem, OBJECT(qdev), &ahci_mem_ops, s,
+                          "ahci", AHCI_MEM_BAR_SIZE);
+    memory_region_init_io(&s->idp, OBJECT(qdev), &ahci_idp_ops, s,
+                          "ahci-idp", 32);
 
     irqs = qemu_allocate_irqs(ahci_irq_set, s, s->ports);
 
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 9916701..33be386 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -117,8 +117,10 @@
 
     bar->bus = bus;
     bar->pci_dev = d;
-    memory_region_init_io(&bar->cmd, &cmd646_cmd_ops, bar, "cmd646-cmd", 4);
-    memory_region_init_io(&bar->data, &cmd646_data_ops, bar, "cmd646-data", 8);
+    memory_region_init_io(&bar->cmd, OBJECT(d), &cmd646_cmd_ops, bar,
+                          "cmd646-cmd", 4);
+    memory_region_init_io(&bar->data, OBJECT(d), &cmd646_data_ops, bar,
+                          "cmd646-data", 8);
 }
 
 static uint64_t bmdma_read(void *opaque, hwaddr addr,
@@ -203,13 +205,14 @@
     BMDMAState *bm;
     int i;
 
-    memory_region_init(&d->bmdma_bar, "cmd646-bmdma", 16);
+    memory_region_init(&d->bmdma_bar, OBJECT(d), "cmd646-bmdma", 16);
     for(i = 0;i < 2; i++) {
         bm = &d->bmdma[i];
-        memory_region_init_io(&bm->extra_io, &cmd646_bmdma_ops, bm,
+        memory_region_init_io(&bm->extra_io, OBJECT(d), &cmd646_bmdma_ops, bm,
                               "cmd646-bmdma-bus", 4);
         memory_region_add_subregion(&d->bmdma_bar, i * 8, &bm->extra_io);
-        memory_region_init_io(&bm->addr_ioport, &bmdma_addr_ioport_ops, bm,
+        memory_region_init_io(&bm->addr_ioport, OBJECT(d),
+                              &bmdma_addr_ioport_ops, bm,
                               "cmd646-bmdma-ioport", 4);
         memory_region_add_subregion(&d->bmdma_bar, i * 8 + 4, &bm->addr_ioport);
     }
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index a1952b0..4798202 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -70,7 +70,7 @@
 
     s->io_buffer_size = io->len;
 
-    qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1,
+    qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1,
                      &address_space_memory);
     qemu_sglist_add(&s->sg, io->addr, io->len);
     io->addr += io->len;
@@ -127,7 +127,7 @@
     s->io_buffer_index = 0;
     s->io_buffer_size = io->len;
 
-    qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1,
+    qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1,
                      &address_space_memory);
     qemu_sglist_add(&s->sg, io->addr, io->len);
     io->addr += io->len;
@@ -335,7 +335,7 @@
     MACIOIDEState *s = MACIO_IDE(obj);
 
     ide_bus_new(&s->bus, DEVICE(obj), 0, 2);
-    memory_region_init_io(&s->mem, &pmac_ide_ops, s, "pmac-ide", 0x1000);
+    memory_region_init_io(&s->mem, obj, &pmac_ide_ops, s, "pmac-ide", 0x1000);
     sysbus_init_mmio(d, &s->mem);
     sysbus_init_irq(d, &s->irq);
     sysbus_init_irq(d, &s->dma_irq);
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
index e80e7e5..d251ff9 100644
--- a/hw/ide/mmio.c
+++ b/hw/ide/mmio.c
@@ -124,9 +124,9 @@
 
     ide_init2(&s->bus, s->irq);
 
-    memory_region_init_io(&s->iomem1, &mmio_ide_ops, s,
+    memory_region_init_io(&s->iomem1, OBJECT(s), &mmio_ide_ops, s,
                           "ide-mmio.1", 16 << s->shift);
-    memory_region_init_io(&s->iomem2, &mmio_ide_cs_ops, s,
+    memory_region_init_io(&s->iomem2, OBJECT(s), &mmio_ide_cs_ops, s,
                           "ide-mmio.2", 2 << s->shift);
     sysbus_init_mmio(d, &s->iomem1);
     sysbus_init_mmio(d, &s->iomem2);
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index bf2856f..58532fe 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -90,15 +90,15 @@
 {
     int i;
 
-    memory_region_init(&d->bmdma_bar, "piix-bmdma-container", 16);
+    memory_region_init(&d->bmdma_bar, OBJECT(d), "piix-bmdma-container", 16);
     for(i = 0;i < 2; i++) {
         BMDMAState *bm = &d->bmdma[i];
 
-        memory_region_init_io(&bm->extra_io, &piix_bmdma_ops, bm,
+        memory_region_init_io(&bm->extra_io, OBJECT(d), &piix_bmdma_ops, bm,
                               "piix-bmdma", 4);
         memory_region_add_subregion(&d->bmdma_bar, i * 8, &bm->extra_io);
-        memory_region_init_io(&bm->addr_ioport, &bmdma_addr_ioport_ops, bm,
-                              "bmdma", 4);
+        memory_region_init_io(&bm->addr_ioport, OBJECT(d),
+                              &bmdma_addr_ioport_ops, bm, "bmdma", 4);
         memory_region_add_subregion(&d->bmdma_bar, i * 8 + 4, &bm->addr_ioport);
     }
 }
diff --git a/hw/ide/via.c b/hw/ide/via.c
index 5fe053c..5a83191 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -92,15 +92,15 @@
 {
     int i;
 
-    memory_region_init(&d->bmdma_bar, "via-bmdma-container", 16);
+    memory_region_init(&d->bmdma_bar, OBJECT(d), "via-bmdma-container", 16);
     for(i = 0;i < 2; i++) {
         BMDMAState *bm = &d->bmdma[i];
 
-        memory_region_init_io(&bm->extra_io, &via_bmdma_ops, bm,
+        memory_region_init_io(&bm->extra_io, OBJECT(d), &via_bmdma_ops, bm,
                               "via-bmdma", 4);
         memory_region_add_subregion(&d->bmdma_bar, i * 8, &bm->extra_io);
-        memory_region_init_io(&bm->addr_ioport, &bmdma_addr_ioport_ops, bm,
-                              "bmdma", 4);
+        memory_region_init_io(&bm->addr_ioport, OBJECT(d),
+                              &bmdma_addr_ioport_ops, bm, "bmdma", 4);
         memory_region_add_subregion(&d->bmdma_bar, i * 8 + 4, &bm->addr_ioport);
     }
 }
diff --git a/hw/input/milkymist-softusb.c b/hw/input/milkymist-softusb.c
index 3edab4f..942cb79 100644
--- a/hw/input/milkymist-softusb.c
+++ b/hw/input/milkymist-softusb.c
@@ -265,17 +265,17 @@
 
     sysbus_init_irq(dev, &s->irq);
 
-    memory_region_init_io(&s->regs_region, &softusb_mmio_ops, s,
+    memory_region_init_io(&s->regs_region, OBJECT(s), &softusb_mmio_ops, s,
                           "milkymist-softusb", R_MAX * 4);
     sysbus_init_mmio(dev, &s->regs_region);
 
     /* register pmem and dmem */
-    memory_region_init_ram(&s->pmem, "milkymist-softusb.pmem",
+    memory_region_init_ram(&s->pmem, OBJECT(s), "milkymist-softusb.pmem",
                            s->pmem_size);
     vmstate_register_ram_global(&s->pmem);
     s->pmem_ptr = memory_region_get_ram_ptr(&s->pmem);
     sysbus_init_mmio(dev, &s->pmem);
-    memory_region_init_ram(&s->dmem, "milkymist-softusb.dmem",
+    memory_region_init_ram(&s->dmem, OBJECT(s), "milkymist-softusb.dmem",
                            s->dmem_size);
     vmstate_register_ram_global(&s->dmem);
     s->dmem_ptr = memory_region_get_ram_ptr(&s->dmem);
diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c
index fff0a4d..ce86237 100644
--- a/hw/input/pckbd.c
+++ b/hw/input/pckbd.c
@@ -424,7 +424,7 @@
 
     vmstate_register(NULL, 0, &vmstate_kbd, s);
 
-    memory_region_init_io(region, &i8042_mmio_ops, s, "i8042", size);
+    memory_region_init_io(region, NULL, &i8042_mmio_ops, s, "i8042", size);
 
     s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);
     s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);
@@ -494,8 +494,10 @@
     ISAKBDState *isa_s = I8042(obj);
     KBDState *s = &isa_s->kbd;
 
-    memory_region_init_io(isa_s->io + 0, &i8042_data_ops, s, "i8042-data", 1);
-    memory_region_init_io(isa_s->io + 1, &i8042_cmd_ops, s, "i8042-cmd", 1);
+    memory_region_init_io(isa_s->io + 0, obj, &i8042_data_ops, s,
+                          "i8042-data", 1);
+    memory_region_init_io(isa_s->io + 1, obj, &i8042_cmd_ops, s,
+                          "i8042-cmd", 1);
 }
 
 static void i8042_realizefn(DeviceState *dev, Error **errp)
diff --git a/hw/input/pl050.c b/hw/input/pl050.c
index 7dd8a59..2312ffc 100644
--- a/hw/input/pl050.c
+++ b/hw/input/pl050.c
@@ -137,7 +137,7 @@
 {
     pl050_state *s = FROM_SYSBUS(pl050_state, dev);
 
-    memory_region_init_io(&s->iomem, &pl050_ops, s, "pl050", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &pl050_ops, s, "pl050", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     s->is_mouse = is_mouse;
diff --git a/hw/input/pxa2xx_keypad.c b/hw/input/pxa2xx_keypad.c
index 1fd5f20..846d137 100644
--- a/hw/input/pxa2xx_keypad.c
+++ b/hw/input/pxa2xx_keypad.c
@@ -313,7 +313,7 @@
     s = (PXA2xxKeyPadState *) g_malloc0(sizeof(PXA2xxKeyPadState));
     s->irq = irq;
 
-    memory_region_init_io(&s->iomem, &pxa2xx_keypad_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &pxa2xx_keypad_ops, s,
                           "pxa2xx-keypad", 0x00100000);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index 46cb097..5e3b96e 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -873,7 +873,7 @@
 
 static void apic_init(APICCommonState *s)
 {
-    memory_region_init_io(&s->io_memory, &apic_io_ops, s, "apic-msi",
+    memory_region_init_io(&s->io_memory, OBJECT(s), &apic_io_ops, s, "apic-msi",
                           APIC_SPACE_SIZE);
 
     s->timer = qemu_new_timer_ns(vm_clock, apic_timer, s);
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index bae6572..b59df06 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -656,7 +656,8 @@
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }
-    memory_region_init_io(&s->iomem, &gic_dist_ops, s, "gic_dist", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &gic_dist_ops, s,
+                          "gic_dist", 0x1000);
 }
 
 static void arm_gic_realize(DeviceState *dev, Error **errp)
@@ -682,12 +683,12 @@
      * GIC v2 defines a larger memory region (0x1000) so this will need
      * to be extended when we implement A15.
      */
-    memory_region_init_io(&s->cpuiomem[0], &gic_thiscpu_ops, s,
+    memory_region_init_io(&s->cpuiomem[0], OBJECT(s), &gic_thiscpu_ops, s,
                           "gic_cpu", 0x100);
     for (i = 0; i < NUM_CPU(s); i++) {
         s->backref[i] = s;
-        memory_region_init_io(&s->cpuiomem[i+1], &gic_cpu_ops, &s->backref[i],
-                              "gic_cpu", 0x100);
+        memory_region_init_io(&s->cpuiomem[i+1], OBJECT(s), &gic_cpu_ops,
+                              &s->backref[i], "gic_cpu", 0x100);
     }
     /* Distributor */
     sysbus_init_mmio(sbd, &s->iomem);
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index b756456..f713975 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -120,7 +120,8 @@
         sysbus_init_irq(sbd, &s->parent_irq[i]);
     }
     /* Distributor */
-    memory_region_init_reservation(&s->iomem, "kvm-gic_dist", 0x1000);
+    memory_region_init_reservation(&s->iomem, OBJECT(s),
+                                   "kvm-gic_dist", 0x1000);
     sysbus_init_mmio(sbd, &s->iomem);
     kvm_arm_register_device(&s->iomem,
                             (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
@@ -129,7 +130,8 @@
      * provide the "interface for core #N" memory regions, because
      * cores with a VGIC don't have those.
      */
-    memory_region_init_reservation(&s->cpuiomem[0], "kvm-gic_cpu", 0x1000);
+    memory_region_init_reservation(&s->cpuiomem[0], OBJECT(s),
+                                   "kvm-gic_cpu", 0x1000);
     sysbus_init_mmio(sbd, &s->cpuiomem[0]);
     kvm_arm_register_device(&s->cpuiomem[0],
                             (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 25fa43c..2a57f77 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -487,17 +487,18 @@
      * We use overlaying to put the GIC like registers
      * over the top of the system control register region.
      */
-    memory_region_init(&s->container, "nvic", 0x1000);
+    memory_region_init(&s->container, OBJECT(s), "nvic", 0x1000);
     /* The system register region goes at the bottom of the priority
      * stack as it covers the whole page.
      */
-    memory_region_init_io(&s->sysregmem, &nvic_sysreg_ops, s,
+    memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s,
                           "nvic_sysregs", 0x1000);
     memory_region_add_subregion(&s->container, 0, &s->sysregmem);
     /* Alias the GIC region so we can get only the section of it
      * we need, and layer it on top of the system register region.
      */
-    memory_region_init_alias(&s->gic_iomem_alias, "nvic-gic", &s->gic.iomem,
+    memory_region_init_alias(&s->gic_iomem_alias, OBJECT(s),
+                             "nvic-gic", &s->gic.iomem,
                              0x100, 0xc00);
     memory_region_add_subregion_overlap(&s->container, 0x100,
                                         &s->gic_iomem_alias, 1);
diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c
index 635103c..ce3a3f6 100644
--- a/hw/intc/etraxfs_pic.c
+++ b/hw/intc/etraxfs_pic.c
@@ -146,7 +146,8 @@
     sysbus_init_irq(dev, &s->parent_irq);
     sysbus_init_irq(dev, &s->parent_nmi);
 
-    memory_region_init_io(&s->mmio, &pic_ops, s, "etraxfs-pic", R_MAX * 4);
+    memory_region_init_io(&s->mmio, OBJECT(s), &pic_ops, s,
+                          "etraxfs-pic", R_MAX * 4);
     sysbus_init_mmio(dev, &s->mmio);
     return 0;
 }
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
index 6874287..3b40976 100644
--- a/hw/intc/exynos4210_combiner.c
+++ b/hw/intc/exynos4210_combiner.c
@@ -417,7 +417,7 @@
         sysbus_init_irq(dev, &s->output_irq[i]);
     }
 
-    memory_region_init_io(&s->iomem, &exynos4210_combiner_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_combiner_ops, s,
             "exynos4210-combiner", IIC_REGION_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
 
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
index bad6dde..6147f04 100644
--- a/hw/intc/exynos4210_gic.c
+++ b/hw/intc/exynos4210_gic.c
@@ -299,15 +299,15 @@
     qdev_init_gpio_in(&s->busdev.qdev, exynos4210_gic_set_irq,
                       EXYNOS4210_GIC_NIRQ - 32);
 
-    memory_region_init(&s->cpu_container, "exynos4210-cpu-container",
+    memory_region_init(&s->cpu_container, OBJECT(s), "exynos4210-cpu-container",
             EXYNOS4210_EXT_GIC_CPU_REGION_SIZE);
-    memory_region_init(&s->dist_container, "exynos4210-dist-container",
+    memory_region_init(&s->dist_container, OBJECT(s), "exynos4210-dist-container",
             EXYNOS4210_EXT_GIC_DIST_REGION_SIZE);
 
     for (i = 0; i < s->num_cpu; i++) {
         /* Map CPU interface per SMP Core */
         sprintf(cpu_alias_name, "%s%x", cpu_prefix, i);
-        memory_region_init_alias(&s->cpu_alias[i],
+        memory_region_init_alias(&s->cpu_alias[i], OBJECT(s),
                                  cpu_alias_name,
                                  sysbus_mmio_get_region(busdev, 1),
                                  0,
@@ -317,7 +317,7 @@
 
         /* Map Distributor per SMP Core */
         sprintf(dist_alias_name, "%s%x", dist_prefix, i);
-        memory_region_init_alias(&s->dist_alias[i],
+        memory_region_init_alias(&s->dist_alias[i], OBJECT(s),
                                  dist_alias_name,
                                  sysbus_mmio_get_region(busdev, 0),
                                  0,
diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c
index 68dfe6a..181f614 100644
--- a/hw/intc/grlib_irqmp.c
+++ b/hw/intc/grlib_irqmp.c
@@ -344,7 +344,7 @@
         return -1;
     }
 
-    memory_region_init_io(&irqmp->iomem, &grlib_irqmp_ops, irqmp,
+    memory_region_init_io(&irqmp->iomem, OBJECT(dev), &grlib_irqmp_ops, irqmp,
                           "irqmp", IRQMP_REG_SIZE);
 
     irqmp->state = g_malloc0(sizeof *irqmp->state);
diff --git a/hw/intc/heathrow_pic.c b/hw/intc/heathrow_pic.c
index beb9661..9818f24 100644
--- a/hw/intc/heathrow_pic.c
+++ b/hw/intc/heathrow_pic.c
@@ -205,7 +205,7 @@
     s = g_malloc0(sizeof(HeathrowPICS));
     /* only 1 CPU */
     s->irqs = irqs[0];
-    memory_region_init_io(&s->mem, &heathrow_pic_ops, s,
+    memory_region_init_io(&s->mem, NULL, &heathrow_pic_ops, s,
                           "heathrow-pic", 0x1000);
     *pmem = &s->mem;
 
diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c
index 192a0ba..1415bda 100644
--- a/hw/intc/i8259.c
+++ b/hw/intc/i8259.c
@@ -417,8 +417,10 @@
     PICCommonState *s = PIC_COMMON(dev);
     PICClass *pc = PIC_GET_CLASS(dev);
 
-    memory_region_init_io(&s->base_io, &pic_base_ioport_ops, s, "pic", 2);
-    memory_region_init_io(&s->elcr_io, &pic_elcr_ioport_ops, s, "elcr", 1);
+    memory_region_init_io(&s->base_io, OBJECT(s), &pic_base_ioport_ops, s,
+                          "pic", 2);
+    memory_region_init_io(&s->elcr_io, OBJECT(s), &pic_elcr_ioport_ops, s,
+                          "elcr", 1);
 
     qdev_init_gpio_out(dev, s->int_out, ARRAY_SIZE(s->int_out));
     qdev_init_gpio_in(dev, pic_set_irq, 8);
diff --git a/hw/intc/imx_avic.c b/hw/intc/imx_avic.c
index ff45dcd..75c8ffd 100644
--- a/hw/intc/imx_avic.c
+++ b/hw/intc/imx_avic.c
@@ -372,7 +372,8 @@
 {
     IMXAVICState *s = FROM_SYSBUS(IMXAVICState, dev);
 
-    memory_region_init_io(&s->iomem, &imx_avic_ops, s, "imx_avic", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &imx_avic_ops, s,
+                          "imx_avic", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
 
     qdev_init_gpio_in(&dev->qdev, imx_avic_set_irq, IMX_AVIC_NUM_IRQS);
diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c
index c6f09f4..5d064fe 100644
--- a/hw/intc/ioapic.c
+++ b/hw/intc/ioapic.c
@@ -227,7 +227,8 @@
 
 static void ioapic_init(IOAPICCommonState *s, int instance_no)
 {
-    memory_region_init_io(&s->io_memory, &ioapic_io_ops, s, "ioapic", 0x1000);
+    memory_region_init_io(&s->io_memory, OBJECT(s), &ioapic_io_ops, s,
+                          "ioapic", 0x1000);
 
     qdev_init_gpio_in(&s->busdev.qdev, ioapic_set_irq, IOAPIC_NUM_PINS);
 
diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c
index 875eba4..bca8585 100644
--- a/hw/intc/omap_intc.c
+++ b/hw/intc/omap_intc.c
@@ -367,7 +367,7 @@
     sysbus_init_irq(dev, &s->parent_intr[0]);
     sysbus_init_irq(dev, &s->parent_intr[1]);
     qdev_init_gpio_in(&dev->qdev, omap_set_intr, s->nbanks * 32);
-    memory_region_init_io(&s->mmio, &omap_inth_mem_ops, s,
+    memory_region_init_io(&s->mmio, OBJECT(s), &omap_inth_mem_ops, s,
                           "omap-intc", s->size);
     sysbus_init_mmio(dev, &s->mmio);
     return 0;
@@ -609,7 +609,7 @@
     sysbus_init_irq(dev, &s->parent_intr[0]);
     sysbus_init_irq(dev, &s->parent_intr[1]);
     qdev_init_gpio_in(&dev->qdev, omap_set_intr_noedge, s->nbanks * 32);
-    memory_region_init_io(&s->mmio, &omap2_inth_mem_ops, s,
+    memory_region_init_io(&s->mmio, OBJECT(s), &omap2_inth_mem_ops, s,
                           "omap2-intc", 0x1000);
     sysbus_init_mmio(dev, &s->mmio);
     return 0;
diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
index a26c641..937e292 100644
--- a/hw/intc/openpic.c
+++ b/hw/intc/openpic.c
@@ -1516,8 +1516,8 @@
     while (list->name) {
         assert(*count < ARRAY_SIZE(opp->sub_io_mem));
 
-        memory_region_init_io(&opp->sub_io_mem[*count], list->ops, opp,
-                              list->name, list->size);
+        memory_region_init_io(&opp->sub_io_mem[*count], OBJECT(opp), list->ops,
+                              opp, list->name, list->size);
 
         memory_region_add_subregion(&opp->mem, list->start_addr,
                                     &opp->sub_io_mem[*count]);
@@ -1531,7 +1531,7 @@
 {
     OpenPICState *opp = OPENPIC(obj);
 
-    memory_region_init(&opp->mem, "openpic", 0x40000);
+    memory_region_init(&opp->mem, obj, "openpic", 0x40000);
 }
 
 static void openpic_realize(DeviceState *dev, Error **errp)
diff --git a/hw/intc/openpic_kvm.c b/hw/intc/openpic_kvm.c
index 6775879..c7f7b84 100644
--- a/hw/intc/openpic_kvm.c
+++ b/hw/intc/openpic_kvm.c
@@ -155,7 +155,7 @@
 {
     KVMOpenPICState *opp = KVM_OPENPIC(obj);
 
-    memory_region_init_io(&opp->mem, &kvm_openpic_mem_ops, opp,
+    memory_region_init_io(&opp->mem, OBJECT(opp), &kvm_openpic_mem_ops, opp,
                           "kvm-openpic", 0x40000);
 }
 
diff --git a/hw/intc/pl190.c b/hw/intc/pl190.c
index 9610673..fdb29d7 100644
--- a/hw/intc/pl190.c
+++ b/hw/intc/pl190.c
@@ -236,7 +236,7 @@
 {
     pl190_state *s = FROM_SYSBUS(pl190_state, dev);
 
-    memory_region_init_io(&s->iomem, &pl190_ops, s, "pl190", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &pl190_ops, s, "pl190", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     qdev_init_gpio_in(&dev->qdev, pl190_set_irq, 32);
     sysbus_init_irq(dev, &s->irq);
diff --git a/hw/intc/puv3_intc.c b/hw/intc/puv3_intc.c
index 0cd5e9e..44b6651 100644
--- a/hw/intc/puv3_intc.c
+++ b/hw/intc/puv3_intc.c
@@ -106,7 +106,7 @@
     s->reg_ICMR = 0;
     s->reg_ICPR = 0;
 
-    memory_region_init_io(&s->iomem, &puv3_intc_ops, s, "puv3_intc",
+    memory_region_init_io(&s->iomem, OBJECT(s), &puv3_intc_ops, s, "puv3_intc",
             PUV3_REGS_OFFSET);
     sysbus_init_mmio(dev, &s->iomem);
 
diff --git a/hw/intc/realview_gic.c b/hw/intc/realview_gic.c
index 0ec30ca..e122c2c 100644
--- a/hw/intc/realview_gic.c
+++ b/hw/intc/realview_gic.c
@@ -43,7 +43,8 @@
     /* Pass through inbound GPIO lines to the GIC */
     qdev_init_gpio_in(&s->busdev.qdev, realview_gic_set_irq, numirq - 32);
 
-    memory_region_init(&s->container, "realview-gic-container", 0x2000);
+    memory_region_init(&s->container, OBJECT(s),
+                       "realview-gic-container", 0x2000);
     memory_region_add_subregion(&s->container, 0,
                                 sysbus_mmio_get_region(busdev, 1));
     memory_region_add_subregion(&s->container, 0x1000,
diff --git a/hw/intc/sh_intc.c b/hw/intc/sh_intc.c
index 050bfb6..f397950 100644
--- a/hw/intc/sh_intc.c
+++ b/hw/intc/sh_intc.c
@@ -319,11 +319,11 @@
 
 #define SH_INTC_IOMEM_FORMAT "interrupt-controller-%s-%s-%s"
     snprintf(name, sizeof(name), SH_INTC_IOMEM_FORMAT, type, action, "p4");
-    memory_region_init_alias(iomem_p4, name, iomem, INTC_A7(address), 4);
+    memory_region_init_alias(iomem_p4, NULL, name, iomem, INTC_A7(address), 4);
     memory_region_add_subregion(sysmem, P4ADDR(address), iomem_p4);
 
     snprintf(name, sizeof(name), SH_INTC_IOMEM_FORMAT, type, action, "a7");
-    memory_region_init_alias(iomem_a7, name, iomem, INTC_A7(address), 4);
+    memory_region_init_alias(iomem_a7, NULL, name, iomem, INTC_A7(address), 4);
     memory_region_add_subregion(sysmem, A7ADDR(address), iomem_a7);
 #undef SH_INTC_IOMEM_FORMAT
 
@@ -466,7 +466,7 @@
 
     desc->irqs = qemu_allocate_irqs(sh_intc_set_irq, desc, nr_sources);
  
-    memory_region_init_io(&desc->iomem, &sh_intc_ops, desc,
+    memory_region_init_io(&desc->iomem, NULL, &sh_intc_ops, desc,
                           "interrupt-controller", 0x100000000ULL);
 
 #define INT_REG_PARAMS(reg_struct, type, action, j) \
diff --git a/hw/intc/slavio_intctl.c b/hw/intc/slavio_intctl.c
index b367752..b47d0f0 100644
--- a/hw/intc/slavio_intctl.c
+++ b/hw/intc/slavio_intctl.c
@@ -426,7 +426,7 @@
     char slave_name[45];
 
     qdev_init_gpio_in(&dev->qdev, slavio_set_irq_all, 32 + MAX_CPUS);
-    memory_region_init_io(&s->iomem, &slavio_intctlm_mem_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &slavio_intctlm_mem_ops, s,
                           "master-interrupt-controller", INTCTLM_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
 
@@ -436,7 +436,8 @@
         for (j = 0; j < MAX_PILS; j++) {
             sysbus_init_irq(dev, &s->cpu_irqs[i][j]);
         }
-        memory_region_init_io(&s->slaves[i].iomem, &slavio_intctl_mem_ops,
+        memory_region_init_io(&s->slaves[i].iomem, OBJECT(s),
+                              &slavio_intctl_mem_ops,
                               &s->slaves[i], slave_name, INTCTL_SIZE);
         sysbus_init_mmio(dev, &s->slaves[i].iomem);
         s->slaves[i].cpu = i;
diff --git a/hw/intc/xilinx_intc.c b/hw/intc/xilinx_intc.c
index 297f537..25d2057 100644
--- a/hw/intc/xilinx_intc.c
+++ b/hw/intc/xilinx_intc.c
@@ -160,7 +160,8 @@
     qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
     sysbus_init_irq(dev, &p->parent_irq);
 
-    memory_region_init_io(&p->mmio, &pic_ops, p, "xlnx.xps-intc", R_MAX * 4);
+    memory_region_init_io(&p->mmio, OBJECT(p), &pic_ops, p, "xlnx.xps-intc",
+                          R_MAX * 4);
     sysbus_init_mmio(dev, &p->mmio);
     return 0;
 }
diff --git a/hw/isa/apm.c b/hw/isa/apm.c
index 5f21d21..f97e7a0 100644
--- a/hw/isa/apm.c
+++ b/hw/isa/apm.c
@@ -96,7 +96,7 @@
     apm->arg = arg;
 
     /* ioport 0xb2, 0xb3 */
-    memory_region_init_io(&apm->io, &apm_ops, apm, "apm-io", 2);
+    memory_region_init_io(&apm->io, OBJECT(dev), &apm_ops, apm, "apm-io", 2);
     memory_region_add_subregion(pci_address_space_io(dev), APM_CNT_IOPORT,
                                 &apm->io);
 }
diff --git a/hw/isa/i82378.c b/hw/isa/i82378.c
index a24cb98..b25ed04 100644
--- a/hw/isa/i82378.c
+++ b/hw/isa/i82378.c
@@ -221,10 +221,12 @@
 
     pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin 0 */
 
-    memory_region_init_io(&s->io, &i82378_io_ops, s, "i82378-io", 0x00010000);
+    memory_region_init_io(&s->io, OBJECT(pci), &i82378_io_ops, s,
+                          "i82378-io", 0x00010000);
     pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io);
 
-    memory_region_init_io(&s->mem, &i82378_mem_ops, s, "i82378-mem", 0x01000000);
+    memory_region_init_io(&s->mem, OBJECT(pci), &i82378_mem_ops, s,
+                          "i82378-mem", 0x01000000);
     pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem);
 
     /* Make I/O address read only */
diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c
index 136d17e..cfd610c 100644
--- a/hw/isa/isa-bus.c
+++ b/hw/isa/isa-bus.c
@@ -115,7 +115,7 @@
        actually handled e.g. the FDC device.  */
     isa_init_ioport(dev, start);
 
-    portio_list_init(piolist, pio_start, opaque, name);
+    portio_list_init(piolist, OBJECT(dev), pio_start, opaque, name);
     portio_list_add(piolist, isabus->address_space_io, start);
 }
 
diff --git a/hw/isa/isa_mmio.c b/hw/isa/isa_mmio.c
index d4dbf13..00ae8eb 100644
--- a/hw/isa/isa_mmio.c
+++ b/hw/isa/isa_mmio.c
@@ -69,7 +69,7 @@
 
 void isa_mmio_setup(MemoryRegion *mr, hwaddr size)
 {
-    memory_region_init_io(mr, &isa_mmio_ops, NULL, "isa-mmio", size);
+    memory_region_init_io(mr, NULL, &isa_mmio_ops, NULL, "isa-mmio", size);
 }
 
 void isa_mmio_init(hwaddr base, hwaddr size)
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index 667e882..b49be4d 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -477,22 +477,23 @@
 static void ich9_lpc_machine_ready(Notifier *n, void *opaque)
 {
     ICH9LPCState *s = container_of(n, ICH9LPCState, machine_ready);
+    MemoryRegion *io_as = pci_address_space_io(&s->d);
     uint8_t *pci_conf;
 
     pci_conf = s->d.config;
-    if (isa_is_ioport_assigned(0x3f8)) {
+    if (memory_region_present(io_as, 0x3f8)) {
         /* com1 */
         pci_conf[0x82] |= 0x01;
     }
-    if (isa_is_ioport_assigned(0x2f8)) {
+    if (memory_region_present(io_as, 0x2f8)) {
         /* com2 */
         pci_conf[0x82] |= 0x02;
     }
-    if (isa_is_ioport_assigned(0x378)) {
+    if (memory_region_present(io_as, 0x378)) {
         /* lpt */
         pci_conf[0x82] |= 0x04;
     }
-    if (isa_is_ioport_assigned(0x3f0)) {
+    if (memory_region_present(io_as, 0x3f0)) {
         /* floppy */
         pci_conf[0x82] |= 0x08;
     }
@@ -534,7 +535,7 @@
     pci_set_long(d->wmask + ICH9_LPC_PMBASE,
                  ICH9_LPC_PMBASE_BASE_ADDRESS_MASK);
 
-    memory_region_init_io(&lpc->rbca_mem, &rbca_mmio_ops, lpc,
+    memory_region_init_io(&lpc->rbca_mem, OBJECT(d), &rbca_mmio_ops, lpc,
                             "lpc-rbca-mmio", ICH9_CC_SIZE);
 
     lpc->isa_bus = isa_bus;
@@ -545,7 +546,7 @@
     lpc->machine_ready.notify = ich9_lpc_machine_ready;
     qemu_add_machine_init_done_notifier(&lpc->machine_ready);
 
-    memory_region_init_io(&lpc->rst_cnt_mem, &ich9_rst_cnt_ops, lpc,
+    memory_region_init_io(&lpc->rst_cnt_mem, OBJECT(d), &ich9_rst_cnt_ops, lpc,
                           "lpc-reset-control", 1);
     memory_region_add_subregion_overlap(pci_address_space_io(d),
                                         ICH9_RST_CNT_IOPORT, &lpc->rst_cnt_mem,
diff --git a/hw/isa/pc87312.c b/hw/isa/pc87312.c
index cc426df..46a23fb 100644
--- a/hw/isa/pc87312.c
+++ b/hw/isa/pc87312.c
@@ -352,7 +352,7 @@
 {
     PC87312State *s = PC87312(obj);
 
-    memory_region_init_io(&s->io, &pc87312_io_ops, s, "pc87312", 2);
+    memory_region_init_io(&s->io, obj, &pc87312_io_ops, s, "pc87312", 2);
 }
 
 static const VMStateDescription vmstate_pc87312 = {
diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
index 391d90d..2174eaa 100644
--- a/hw/isa/vt82c686.c
+++ b/hw/isa/vt82c686.c
@@ -43,10 +43,12 @@
 
 typedef struct VT82C686BState {
     PCIDevice dev;
+    MemoryRegion superio;
     SuperIOConfig superio_conf;
 } VT82C686BState;
 
-static void superio_ioport_writeb(void *opaque, uint32_t addr, uint32_t data)
+static void superio_ioport_writeb(void *opaque, hwaddr addr, uint64_t data,
+                                  unsigned size)
 {
     int can_write;
     SuperIOConfig *superio_conf = opaque;
@@ -93,7 +95,7 @@
     }
 }
 
-static uint32_t superio_ioport_readb(void *opaque, uint32_t addr)
+static uint64_t superio_ioport_readb(void *opaque, hwaddr addr, unsigned size)
 {
     SuperIOConfig *superio_conf = opaque;
 
@@ -101,6 +103,16 @@
     return (superio_conf->config[superio_conf->index]);
 }
 
+static const MemoryRegionOps superio_ops = {
+    .read = superio_ioport_readb,
+    .write = superio_ioport_writeb,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
 static void vt82c686b_reset(void * opaque)
 {
     PCIDevice *d = opaque;
@@ -140,17 +152,7 @@
 
     pci_default_write_config(d, address, val, len);
     if (address == 0x85) {  /* enable or disable super IO configure */
-        if (val & 0x2) {
-            /* floppy also uses 0x3f0 and 0x3f1.
-             * But we do not emulate flopy,so just set it here. */
-            isa_unassign_ioport(0x3f0, 2);
-            register_ioport_read(0x3f0, 2, 1, superio_ioport_readb,
-                                 &vt686->superio_conf);
-            register_ioport_write(0x3f0, 2, 1, superio_ioport_writeb,
-                                  &vt686->superio_conf);
-        } else {
-            isa_unassign_ioport(0x3f0, 2);
-        }
+        memory_region_set_enabled(&vt686->superio, val & 0x2);
     }
 }
 
@@ -354,7 +356,7 @@
 
     apm_init(dev, &s->apm, NULL, s);
 
-    memory_region_init(&s->io, "vt82c686-pm", 64);
+    memory_region_init(&s->io, OBJECT(dev), "vt82c686-pm", 64);
     memory_region_set_enabled(&s->io, false);
     memory_region_add_subregion(get_system_io(), 0, &s->io);
 
@@ -423,11 +425,13 @@
 /* init the PCI-to-ISA bridge */
 static int vt82c686b_initfn(PCIDevice *d)
 {
+    VT82C686BState *vt82c = DO_UPCAST(VT82C686BState, dev, d);
     uint8_t *pci_conf;
+    ISABus *isa_bus;
     uint8_t *wmask;
     int i;
 
-    isa_bus_new(&d->qdev, pci_address_space_io(d));
+    isa_bus = isa_bus_new(&d->qdev, pci_address_space_io(d));
 
     pci_conf = d->config;
     pci_config_set_prog_interface(pci_conf, 0x0);
@@ -439,6 +443,14 @@
        }
     }
 
+    memory_region_init_io(&vt82c->superio, OBJECT(d), &superio_ops,
+                          &vt82c->superio_conf, "superio", 2);
+    memory_region_set_enabled(&vt82c->superio, false);
+    /* The floppy also uses 0x3f0 and 0x3f1.
+     * But we do not emulate a floppy, so just set it here. */
+    memory_region_add_subregion(isa_bus->address_space_io, 0x3f0,
+                                &vt82c->superio);
+
     qemu_register_reset(vt82c686b_reset, d);
 
     return 0;
diff --git a/hw/lm32/lm32_boards.c b/hw/lm32/lm32_boards.c
index 1ca9498..62003b8 100644
--- a/hw/lm32/lm32_boards.c
+++ b/hw/lm32/lm32_boards.c
@@ -106,7 +106,7 @@
 
     reset_info->flash_base = flash_base;
 
-    memory_region_init_ram(phys_ram, "lm32_evr.sdram", ram_size);
+    memory_region_init_ram(phys_ram, NULL, "lm32_evr.sdram", ram_size);
     vmstate_register_ram_global(phys_ram);
     memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
 
@@ -203,7 +203,7 @@
 
     reset_info->flash_base = flash_base;
 
-    memory_region_init_ram(phys_ram, "lm32_uclinux.sdram", ram_size);
+    memory_region_init_ram(phys_ram, NULL, "lm32_uclinux.sdram", ram_size);
     vmstate_register_ram_global(phys_ram);
     memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
 
diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
index cca9374..7ceedb8 100644
--- a/hw/lm32/milkymist.c
+++ b/hw/lm32/milkymist.c
@@ -112,7 +112,7 @@
 
     cpu_lm32_set_phys_msb_ignore(env, 1);
 
-    memory_region_init_ram(phys_sdram, "milkymist.sdram", sdram_size);
+    memory_region_init_ram(phys_sdram, NULL, "milkymist.sdram", sdram_size);
     vmstate_register_ram_global(phys_sdram);
     memory_region_add_subregion(address_space_mem, sdram_base, phys_sdram);
 
diff --git a/hw/m68k/an5206.c b/hw/m68k/an5206.c
index c4a5626..0c03a87 100644
--- a/hw/m68k/an5206.c
+++ b/hw/m68k/an5206.c
@@ -49,12 +49,12 @@
     env->rambar0 = AN5206_RAMBAR_ADDR | 1;
 
     /* DRAM at address zero */
-    memory_region_init_ram(ram, "an5206.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "an5206.ram", ram_size);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space_mem, 0, ram);
 
     /* Internal SRAM.  */
-    memory_region_init_ram(sram, "an5206.sram", 512);
+    memory_region_init_ram(sram, NULL, "an5206.sram", 512);
     vmstate_register_ram_global(sram);
     memory_region_add_subregion(address_space_mem, AN5206_RAMBAR_ADDR, sram);
 
diff --git a/hw/m68k/dummy_m68k.c b/hw/m68k/dummy_m68k.c
index 544d56b..f4ed7c6 100644
--- a/hw/m68k/dummy_m68k.c
+++ b/hw/m68k/dummy_m68k.c
@@ -40,7 +40,7 @@
     env->vbr = 0;
 
     /* RAM at address zero */
-    memory_region_init_ram(ram, "dummy_m68k.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "dummy_m68k.ram", ram_size);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space_mem, 0, ram);
 
diff --git a/hw/m68k/mcf5206.c b/hw/m68k/mcf5206.c
index bcc619d..1727a46 100644
--- a/hw/m68k/mcf5206.c
+++ b/hw/m68k/mcf5206.c
@@ -532,7 +532,7 @@
 
     s = (m5206_mbar_state *)g_malloc0(sizeof(m5206_mbar_state));
 
-    memory_region_init_io(&s->iomem, &m5206_mbar_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &m5206_mbar_ops, s,
                           "mbar", 0x00001000);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
index 05efde7..9cf000f 100644
--- a/hw/m68k/mcf5208.c
+++ b/hw/m68k/mcf5208.c
@@ -172,14 +172,14 @@
     int i;
 
     /* SDRAMC.  */
-    memory_region_init_io(iomem, &m5208_sys_ops, NULL, "m5208-sys", 0x00004000);
+    memory_region_init_io(iomem, NULL, &m5208_sys_ops, NULL, "m5208-sys", 0x00004000);
     memory_region_add_subregion(address_space, 0xfc0a8000, iomem);
     /* Timers.  */
     for (i = 0; i < 2; i++) {
         s = (m5208_timer_state *)g_malloc0(sizeof(m5208_timer_state));
         bh = qemu_bh_new(m5208_timer_trigger, s);
         s->timer = ptimer_init(bh);
-        memory_region_init_io(&s->iomem, &m5208_timer_ops, s,
+        memory_region_init_io(&s->iomem, NULL, &m5208_timer_ops, s,
                               "m5208-timer", 0x00004000);
         memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i,
                                     &s->iomem);
@@ -217,12 +217,12 @@
     /* TODO: Configure BARs.  */
 
     /* DRAM at 0x40000000 */
-    memory_region_init_ram(ram, "mcf5208.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "mcf5208.ram", ram_size);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space_mem, 0x40000000, ram);
 
     /* Internal SRAM.  */
-    memory_region_init_ram(sram, "mcf5208.sram", 16384);
+    memory_region_init_ram(sram, NULL, "mcf5208.sram", 16384);
     vmstate_register_ram_global(sram);
     memory_region_add_subregion(address_space_mem, 0x80000000, sram);
 
diff --git a/hw/m68k/mcf_intc.c b/hw/m68k/mcf_intc.c
index cfe660d..621423c 100644
--- a/hw/m68k/mcf_intc.c
+++ b/hw/m68k/mcf_intc.c
@@ -147,7 +147,7 @@
     s->cpu = cpu;
     mcf_intc_reset(s);
 
-    memory_region_init_io(&s->iomem, &mcf_intc_ops, s, "mcf", 0x100);
+    memory_region_init_io(&s->iomem, NULL, &mcf_intc_ops, s, "mcf", 0x100);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
     return qemu_allocate_irqs(mcf_intc_set_irq, s, 64);
diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
index 3f1d70e..5b057f7 100644
--- a/hw/microblaze/boot.c
+++ b/hw/microblaze/boot.c
@@ -28,6 +28,7 @@
 #include "qemu/config-file.h"
 #include "qemu-common.h"
 #include "sysemu/device_tree.h"
+#include "sysemu/sysemu.h"
 #include "hw/loader.h"
 #include "elf.h"
 
@@ -93,20 +94,18 @@
                             void (*machine_cpu_reset)(MicroBlazeCPU *))
 {
     QemuOpts *machine_opts;
-    const char *kernel_filename = NULL;
-    const char *kernel_cmdline = NULL;
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *dtb_arg;
 
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        const char *dtb_arg;
-        kernel_filename = qemu_opt_get(machine_opts, "kernel");
-        kernel_cmdline = qemu_opt_get(machine_opts, "append");
-        dtb_arg = qemu_opt_get(machine_opts, "dtb");
-        if (dtb_arg) { /* Preference a -dtb argument */
-            dtb_filename = dtb_arg;
-        } else { /* default to pcbios dtb as passed by machine_init */
-            dtb_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
-        }
+    machine_opts = qemu_get_machine_opts();
+    kernel_filename = qemu_opt_get(machine_opts, "kernel");
+    kernel_cmdline = qemu_opt_get(machine_opts, "append");
+    dtb_arg = qemu_opt_get(machine_opts, "dtb");
+    if (dtb_arg) { /* Preference a -dtb argument */
+        dtb_filename = dtb_arg;
+    } else { /* default to pcbios dtb as passed by machine_init */
+        dtb_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
     }
 
     boot_info.machine_cpu_reset = machine_cpu_reset;
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index 3340468..989da25 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -98,12 +98,12 @@
     env = &cpu->env;
 
     /* Attach emulated BRAM through the LMB.  */
-    memory_region_init_ram(phys_lmb_bram, "petalogix_ml605.lmb_bram",
+    memory_region_init_ram(phys_lmb_bram, NULL, "petalogix_ml605.lmb_bram",
                            LMB_BRAM_SIZE);
     vmstate_register_ram_global(phys_lmb_bram);
     memory_region_add_subregion(address_space_mem, 0x00000000, phys_lmb_bram);
 
-    memory_region_init_ram(phys_ram, "petalogix_ml605.ram", ram_size);
+    memory_region_init_ram(phys_ram, NULL, "petalogix_ml605.ram", ram_size);
     vmstate_register_ram_global(phys_ram);
     memory_region_add_subregion(address_space_mem, ddr_base, phys_ram);
 
diff --git a/hw/microblaze/petalogix_s3adsp1800_mmu.c b/hw/microblaze/petalogix_s3adsp1800_mmu.c
index b3bcd4e..a461494 100644
--- a/hw/microblaze/petalogix_s3adsp1800_mmu.c
+++ b/hw/microblaze/petalogix_s3adsp1800_mmu.c
@@ -80,12 +80,12 @@
     env = &cpu->env;
 
     /* Attach emulated BRAM through the LMB.  */
-    memory_region_init_ram(phys_lmb_bram,
+    memory_region_init_ram(phys_lmb_bram, NULL,
                            "petalogix_s3adsp1800.lmb_bram", LMB_BRAM_SIZE);
     vmstate_register_ram_global(phys_lmb_bram);
     memory_region_add_subregion(sysmem, 0x00000000, phys_lmb_bram);
 
-    memory_region_init_ram(phys_ram, "petalogix_s3adsp1800.ram", ram_size);
+    memory_region_init_ram(phys_ram, NULL, "petalogix_s3adsp1800.ram", ram_size);
     vmstate_register_ram_global(phys_ram);
     memory_region_add_subregion(sysmem, ddr_base, phys_ram);
 
diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c
index 189e865..5843417 100644
--- a/hw/mips/gt64xxx_pci.c
+++ b/hw/mips/gt64xxx_pci.c
@@ -1108,7 +1108,7 @@
                                 get_system_memory(),
                                 get_system_io(),
                                 PCI_DEVFN(18, 0), 4, TYPE_PCI_BUS);
-    memory_region_init_io(&d->ISD_mem, &isd_mem_ops, d, "isd-mem", 0x1000);
+    memory_region_init_io(&d->ISD_mem, OBJECT(dev), &isd_mem_ops, d, "isd-mem", 0x1000);
 
     pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "gt64120_pci");
     return phb->bus;
diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c
index 00c9071..03e44d5 100644
--- a/hw/mips/mips_fulong2e.c
+++ b/hw/mips/mips_fulong2e.c
@@ -231,7 +231,7 @@
 }
 
 /* Network support */
-static void network_init (void)
+static void network_init (PCIBus *pci_bus)
 {
     int i;
 
@@ -244,7 +244,7 @@
             default_devaddr = "07";
         }
 
-        pci_nic_init_nofail(nd, "rtl8139", default_devaddr);
+        pci_nic_init_nofail(nd, pci_bus, "rtl8139", default_devaddr);
     }
 }
 
@@ -300,9 +300,9 @@
     bios_size = 1024 * 1024;
 
     /* allocate RAM */
-    memory_region_init_ram(ram, "fulong2e.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "fulong2e.ram", ram_size);
     vmstate_register_ram_global(ram);
-    memory_region_init_ram(bios, "fulong2e.bios", bios_size);
+    memory_region_init_ram(bios, NULL, "fulong2e.bios", bios_size);
     vmstate_register_ram_global(bios);
     memory_region_set_readonly(bios, true);
 
@@ -393,7 +393,7 @@
     /* Sound card */
     audio_init(pci_bus);
     /* Network card */
-    network_init();
+    network_init(pci_bus);
 }
 
 static QEMUMachine mips_fulong2e_machine = {
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
index 2ad0c0b..3eac63b 100644
--- a/hw/mips/mips_jazz.c
+++ b/hw/mips/mips_jazz.c
@@ -152,14 +152,14 @@
     qemu_register_reset(main_cpu_reset, cpu);
 
     /* allocate RAM */
-    memory_region_init_ram(ram, "mips_jazz.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "mips_jazz.ram", ram_size);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space, 0, ram);
 
-    memory_region_init_ram(bios, "mips_jazz.bios", MAGNUM_BIOS_SIZE);
+    memory_region_init_ram(bios, NULL, "mips_jazz.bios", MAGNUM_BIOS_SIZE);
     vmstate_register_ram_global(bios);
     memory_region_set_readonly(bios, true);
-    memory_region_init_alias(bios2, "mips_jazz.bios", bios,
+    memory_region_init_alias(bios2, NULL, "mips_jazz.bios", bios,
                              0, MAGNUM_BIOS_SIZE);
     memory_region_add_subregion(address_space, 0x1fc00000LL, bios);
     memory_region_add_subregion(address_space, 0xfff00000LL, bios2);
@@ -188,7 +188,7 @@
     /* Chipset */
     rc4030_opaque = rc4030_init(env->irq[6], env->irq[3], &rc4030, &dmas,
                                 address_space);
-    memory_region_init_io(dma_dummy, &dma_dummy_ops, NULL, "dummy_dma", 0x1000);
+    memory_region_init_io(dma_dummy, NULL, &dma_dummy_ops, NULL, "dummy_dma", 0x1000);
     memory_region_add_subregion(address_space, 0x8000d000, dma_dummy);
 
     /* ISA devices */
@@ -216,7 +216,7 @@
         {
             /* Simple ROM, so user doesn't have to provide one */
             MemoryRegion *rom_mr = g_new(MemoryRegion, 1);
-            memory_region_init_ram(rom_mr, "g364fb.rom", 0x80000);
+            memory_region_init_ram(rom_mr, NULL, "g364fb.rom", 0x80000);
             vmstate_register_ram_global(rom_mr);
             memory_region_set_readonly(rom_mr, true);
             uint8_t *rom = memory_region_get_ram_ptr(rom_mr);
@@ -266,7 +266,7 @@
 
     /* Real time clock */
     rtc_init(isa_bus, 1980, NULL);
-    memory_region_init_io(rtc, &rtc_ops, NULL, "rtc", 0x1000);
+    memory_region_init_io(rtc, NULL, &rtc_ops, NULL, "rtc", 0x1000);
     memory_region_add_subregion(address_space, 0x80004000, rtc);
 
     /* Keyboard (i8042) */
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 8a4459d..ceadc72 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -446,11 +446,11 @@
 
     s = (MaltaFPGAState *)g_malloc0(sizeof(MaltaFPGAState));
 
-    memory_region_init_io(&s->iomem, &malta_fpga_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &malta_fpga_ops, s,
                           "malta-fpga", 0x100000);
-    memory_region_init_alias(&s->iomem_lo, "malta-fpga",
+    memory_region_init_alias(&s->iomem_lo, NULL, "malta-fpga",
                              &s->iomem, 0, 0x900);
-    memory_region_init_alias(&s->iomem_hi, "malta-fpga",
+    memory_region_init_alias(&s->iomem_hi, NULL, "malta-fpga",
                              &s->iomem, 0xa00, 0x10000-0xa00);
 
     memory_region_add_subregion(address_space, base, &s->iomem_lo);
@@ -468,7 +468,7 @@
 }
 
 /* Network support */
-static void network_init(void)
+static void network_init(PCIBus *pci_bus)
 {
     int i;
 
@@ -480,7 +480,7 @@
             /* The malta board has a PCNet card using PCI SLOT 11 */
             default_devaddr = "0b";
 
-        pci_nic_init_nofail(nd, "pcnet", default_devaddr);
+        pci_nic_init_nofail(nd, pci_bus, "pcnet", default_devaddr);
     }
 }
 
@@ -853,7 +853,7 @@
                 ((unsigned int)ram_size / (1 << 20)));
         exit(1);
     }
-    memory_region_init_ram(ram, "mips_malta.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "mips_malta.ram", ram_size);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(system_memory, 0, ram);
 
@@ -927,7 +927,7 @@
     }
 
     /* Map the BIOS at a 2nd physical location, as on the real board. */
-    memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
+    memory_region_init_alias(bios_alias, NULL, "bios.1fc", bios, 0, BIOS_SIZE);
     memory_region_add_subregion(system_memory, RESET_ADDRESS, bios_alias);
 
     /* Board ID = 0x420 (Malta Board with CoreLV)
@@ -985,7 +985,7 @@
     fdctrl_init_isa(isa_bus, fd);
 
     /* Network card */
-    network_init();
+    network_init(pci_bus);
 
     /* Optional PCI video card */
     pci_vga_init(pci_bus);
diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c
index d1681ec..a10cf13 100644
--- a/hw/mips/mips_mipssim.c
+++ b/hw/mips/mips_mipssim.c
@@ -168,9 +168,9 @@
     qemu_register_reset(main_cpu_reset, reset_info);
 
     /* Allocate RAM. */
-    memory_region_init_ram(ram, "mips_mipssim.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "mips_mipssim.ram", ram_size);
     vmstate_register_ram_global(ram);
-    memory_region_init_ram(bios, "mips_mipssim.bios", BIOS_SIZE);
+    memory_region_init_ram(bios, NULL, "mips_mipssim.bios", BIOS_SIZE);
     vmstate_register_ram_global(bios);
     memory_region_set_readonly(bios, true);
 
diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c
index 4646ab6..22beb0a 100644
--- a/hw/mips/mips_r4k.c
+++ b/hw/mips/mips_r4k.c
@@ -202,12 +202,12 @@
                 ((unsigned int)ram_size / (1 << 20)));
         exit(1);
     }
-    memory_region_init_ram(ram, "mips_r4k.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "mips_r4k.ram", ram_size);
     vmstate_register_ram_global(ram);
 
     memory_region_add_subregion(address_space_mem, 0, ram);
 
-    memory_region_init_io(iomem, &mips_qemu_ops, NULL, "mips-qemu", 0x10000);
+    memory_region_init_io(iomem, NULL, &mips_qemu_ops, NULL, "mips-qemu", 0x10000);
     memory_region_add_subregion(address_space_mem, 0x1fbf0000, iomem);
 
     /* Try to load a BIOS image. If this fails, we continue regardless,
@@ -229,7 +229,7 @@
 #endif
     if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
         bios = g_new(MemoryRegion, 1);
-        memory_region_init_ram(bios, "mips_r4k.bios", BIOS_SIZE);
+        memory_region_init_ram(bios, NULL, "mips_r4k.bios", BIOS_SIZE);
         vmstate_register_ram_global(bios);
         memory_region_set_readonly(bios, true);
         memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios);
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
index 05897c2..601b573 100644
--- a/hw/misc/a9scu.c
+++ b/hw/misc/a9scu.c
@@ -119,7 +119,8 @@
     A9SCUState *s = A9_SCU(dev);
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 
-    memory_region_init_io(&s->iomem, &a9_scu_ops, s, "a9-scu", 0x100);
+    memory_region_init_io(&s->iomem, OBJECT(dev), &a9_scu_ops, s,
+                          "a9-scu", 0x100);
     sysbus_init_mmio(sbd, &s->iomem);
 }
 
diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c
index 46f4fbd..bfafa51 100644
--- a/hw/misc/applesmc.c
+++ b/hw/misc/applesmc.c
@@ -73,6 +73,8 @@
 struct AppleSMCState {
     ISADevice parent_obj;
 
+    MemoryRegion io_data;
+    MemoryRegion io_cmd;
     uint32_t iobase;
     uint8_t cmd;
     uint8_t status;
@@ -86,7 +88,8 @@
     QLIST_HEAD(, AppleSMCData) data_def;
 };
 
-static void applesmc_io_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void applesmc_io_cmd_write(void *opaque, hwaddr addr, uint64_t val,
+                                  unsigned size)
 {
     AppleSMCState *s = opaque;
 
@@ -115,7 +118,8 @@
     }
 }
 
-static void applesmc_io_data_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void applesmc_io_data_write(void *opaque, hwaddr addr, uint64_t val,
+                                   unsigned size)
 {
     AppleSMCState *s = opaque;
 
@@ -138,7 +142,8 @@
     }
 }
 
-static uint32_t applesmc_io_data_readb(void *opaque, uint32_t addr1)
+static uint64_t applesmc_io_data_read(void *opaque, hwaddr addr1,
+                                      unsigned size)
 {
     AppleSMCState *s = opaque;
     uint8_t retval = 0;
@@ -162,7 +167,7 @@
     return retval;
 }
 
-static uint32_t applesmc_io_cmd_readb(void *opaque, uint32_t addr1)
+static uint64_t applesmc_io_cmd_read(void *opaque, hwaddr addr1, unsigned size)
 {
     AppleSMCState *s = opaque;
 
@@ -201,18 +206,39 @@
     applesmc_add_key(s, "MSSD", 1, "\0x3");
 }
 
+static const MemoryRegionOps applesmc_data_io_ops = {
+    .write = applesmc_io_data_write,
+    .read = applesmc_io_data_read,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
+static const MemoryRegionOps applesmc_cmd_io_ops = {
+    .write = applesmc_io_cmd_write,
+    .read = applesmc_io_cmd_read,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
 static void applesmc_isa_realize(DeviceState *dev, Error **errp)
 {
     AppleSMCState *s = APPLE_SMC(dev);
 
-    register_ioport_read(s->iobase + APPLESMC_DATA_PORT, 4, 1,
-                         applesmc_io_data_readb, s);
-    register_ioport_read(s->iobase + APPLESMC_CMD_PORT, 4, 1,
-                         applesmc_io_cmd_readb, s);
-    register_ioport_write(s->iobase + APPLESMC_DATA_PORT, 4, 1,
-                          applesmc_io_data_writeb, s);
-    register_ioport_write(s->iobase + APPLESMC_CMD_PORT, 4, 1,
-                          applesmc_io_cmd_writeb, s);
+    memory_region_init_io(&s->io_data, OBJECT(s), &applesmc_data_io_ops, s,
+                          "applesmc-data", 4);
+    isa_register_ioport(&s->parent_obj, &s->io_data,
+                        s->iobase + APPLESMC_DATA_PORT);
+
+    memory_region_init_io(&s->io_cmd, OBJECT(s), &applesmc_cmd_io_ops, s,
+                          "applesmc-cmd", 4);
+    isa_register_ioport(&s->parent_obj, &s->io_cmd,
+                        s->iobase + APPLESMC_CMD_PORT);
 
     if (!s->osk || (strlen(s->osk) != 64)) {
         fprintf(stderr, "WARNING: Using AppleSMC with invalid key\n");
diff --git a/hw/misc/arm_l2x0.c b/hw/misc/arm_l2x0.c
index eb4427d..3d6acee 100644
--- a/hw/misc/arm_l2x0.c
+++ b/hw/misc/arm_l2x0.c
@@ -157,7 +157,8 @@
 {
     l2x0_state *s = FROM_SYSBUS(l2x0_state, dev);
 
-    memory_region_init_io(&s->iomem, &l2x0_mem_ops, s, "l2x0_cc", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(dev), &l2x0_mem_ops, s,
+                          "l2x0_cc", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
diff --git a/hw/misc/arm_sysctl.c b/hw/misc/arm_sysctl.c
index c8b55a8..5906ae5 100644
--- a/hw/misc/arm_sysctl.c
+++ b/hw/misc/arm_sysctl.c
@@ -589,7 +589,8 @@
     SysBusDevice *sd = SYS_BUS_DEVICE(obj);
     arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, sd);
 
-    memory_region_init_io(&s->iomem, &arm_sysctl_ops, s, "arm-sysctl", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(dev), &arm_sysctl_ops, s,
+                          "arm-sysctl", 0x1000);
     sysbus_init_mmio(sd, &s->iomem);
     qdev_init_gpio_in(dev, arm_sysctl_gpio_set, 2);
     qdev_init_gpio_out(dev, &s->pl110_mux_ctrl, 1);
diff --git a/hw/misc/debugexit.c b/hw/misc/debugexit.c
index ee254e4..d754cf1 100644
--- a/hw/misc/debugexit.c
+++ b/hw/misc/debugexit.c
@@ -40,7 +40,7 @@
     ISADevice *dev = ISA_DEVICE(d);
     ISADebugExitState *isa = ISA_DEBUG_EXIT_DEVICE(d);
 
-    memory_region_init_io(&isa->io, &debug_exit_ops, isa,
+    memory_region_init_io(&isa->io, OBJECT(dev), &debug_exit_ops, isa,
                           TYPE_ISA_DEBUG_EXIT_DEVICE, isa->iosize);
     memory_region_add_subregion(isa_address_space_io(dev),
                                 isa->iobase, &isa->io);
diff --git a/hw/misc/eccmemctl.c b/hw/misc/eccmemctl.c
index 6f4a407..3de9675 100644
--- a/hw/misc/eccmemctl.c
+++ b/hw/misc/eccmemctl.c
@@ -296,11 +296,11 @@
 
     sysbus_init_irq(dev, &s->irq);
     s->regs[0] = s->version;
-    memory_region_init_io(&s->iomem, &ecc_mem_ops, s, "ecc", ECC_SIZE);
+    memory_region_init_io(&s->iomem, OBJECT(dev), &ecc_mem_ops, s, "ecc", ECC_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
 
     if (s->version == ECC_MCC) { // SS-600MP only
-        memory_region_init_io(&s->iomem_diag, &ecc_diag_mem_ops, s,
+        memory_region_init_io(&s->iomem_diag, OBJECT(dev), &ecc_diag_mem_ops, s,
                               "ecc.diag", ECC_DIAG_SIZE);
         sysbus_init_mmio(dev, &s->iomem_diag);
     }
diff --git a/hw/misc/exynos4210_pmu.c b/hw/misc/exynos4210_pmu.c
index ba5aa8d..28395ba 100644
--- a/hw/misc/exynos4210_pmu.c
+++ b/hw/misc/exynos4210_pmu.c
@@ -458,8 +458,8 @@
     Exynos4210PmuState *s = FROM_SYSBUS(Exynos4210PmuState, dev);
 
     /* memory mapping */
-    memory_region_init_io(&s->iomem, &exynos4210_pmu_ops, s, "exynos4210.pmu",
-                          EXYNOS4210_PMU_REGS_MEM_SIZE);
+    memory_region_init_io(&s->iomem, OBJECT(dev), &exynos4210_pmu_ops, s,
+                          "exynos4210.pmu", EXYNOS4210_PMU_REGS_MEM_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c
index 427ce5c..816d5e8 100644
--- a/hw/misc/imx_ccm.c
+++ b/hw/misc/imx_ccm.c
@@ -281,7 +281,8 @@
 {
     IMXCCMState *s = FROM_SYSBUS(typeof(*s), dev);
 
-    memory_region_init_io(&s->iomem, &imx_ccm_ops, s, "imx_ccm", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(dev), &imx_ccm_ops, s,
+                          "imx_ccm", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 5658f73..3594b84 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -339,7 +339,7 @@
 
     ptr = mmap(0, s->ivshmem_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
 
-    memory_region_init_ram_ptr(&s->ivshmem, "ivshmem.bar2",
+    memory_region_init_ram_ptr(&s->ivshmem, OBJECT(s), "ivshmem.bar2",
                                s->ivshmem_size, ptr);
     vmstate_register_ram(&s->ivshmem, &s->dev.qdev);
     memory_region_add_subregion(&s->bar, 0, &s->ivshmem);
@@ -467,7 +467,7 @@
         /* mmap the region and map into the BAR2 */
         map_ptr = mmap(0, s->ivshmem_size, PROT_READ|PROT_WRITE, MAP_SHARED,
                                                             incoming_fd, 0);
-        memory_region_init_ram_ptr(&s->ivshmem,
+        memory_region_init_ram_ptr(&s->ivshmem, OBJECT(s),
                                    "ivshmem.bar2", s->ivshmem_size, map_ptr);
         vmstate_register_ram(&s->ivshmem, &s->dev.qdev);
 
@@ -685,14 +685,14 @@
 
     s->shm_fd = 0;
 
-    memory_region_init_io(&s->ivshmem_mmio, &ivshmem_mmio_ops, s,
+    memory_region_init_io(&s->ivshmem_mmio, OBJECT(s), &ivshmem_mmio_ops, s,
                           "ivshmem-mmio", IVSHMEM_REG_BAR_SIZE);
 
     /* region for registers*/
     pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY,
                      &s->ivshmem_mmio);
 
-    memory_region_init(&s->bar, "ivshmem-bar2-container", s->ivshmem_size);
+    memory_region_init(&s->bar, OBJECT(s), "ivshmem-bar2-container", s->ivshmem_size);
     s->ivshmem_attr = PCI_BASE_ADDRESS_SPACE_MEMORY |
         PCI_BASE_ADDRESS_MEM_PREFETCH;
     if (s->ivshmem_64bit) {
diff --git a/hw/misc/lm32_sys.c b/hw/misc/lm32_sys.c
index aeaf2b7..060a5bf 100644
--- a/hw/misc/lm32_sys.c
+++ b/hw/misc/lm32_sys.c
@@ -117,7 +117,8 @@
 {
     LM32SysState *s = FROM_SYSBUS(typeof(*s), dev);
 
-    memory_region_init_io(&s->iomem, &sys_ops , s, "sys", R_MAX * 4);
+    memory_region_init_io(&s->iomem, OBJECT(dev), &sys_ops , s,
+                          "sys", R_MAX * 4);
     sysbus_init_mmio(dev, &s->iomem);
 
     /* Note: This device is not created in the board initialization,
diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c
index f797796..c0fd7da 100644
--- a/hw/misc/macio/cuda.c
+++ b/hw/misc/macio/cuda.c
@@ -703,7 +703,7 @@
     CUDAState *s = CUDA(obj);
     int i;
 
-    memory_region_init_io(&s->mem, &cuda_ops, s, "cuda", 0x2000);
+    memory_region_init_io(&s->mem, NULL, &cuda_ops, s, "cuda", 0x2000);
     sysbus_init_mmio(d, &s->mem);
     sysbus_init_irq(d, &s->irq);
 
diff --git a/hw/misc/macio/mac_dbdma.c b/hw/misc/macio/mac_dbdma.c
index 2fc7f87..a1d7862 100644
--- a/hw/misc/macio/mac_dbdma.c
+++ b/hw/misc/macio/mac_dbdma.c
@@ -848,7 +848,7 @@
 
     s = g_malloc0(sizeof(DBDMAState));
 
-    memory_region_init_io(&s->mem, &dbdma_ops, s, "dbdma", 0x1000);
+    memory_region_init_io(&s->mem, NULL, &dbdma_ops, s, "dbdma", 0x1000);
     *dbdma_mem = &s->mem;
     vmstate_register(NULL, -1, &vmstate_dbdma, s);
     qemu_register_reset(dbdma_reset, s);
diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c
index fd4c8e5..76a1cfb 100644
--- a/hw/misc/macio/macio.c
+++ b/hw/misc/macio/macio.c
@@ -104,11 +104,11 @@
         0xF0, 0xE0,
     };
 
-    memory_region_init(escc_legacy, "escc-legacy", 256);
+    memory_region_init(escc_legacy, NULL, "escc-legacy", 256);
     for (i = 0; i < ARRAY_SIZE(maps); i += 2) {
         MemoryRegion *port = g_new(MemoryRegion, 1);
-        memory_region_init_alias(port, "escc-legacy-port", macio_state->escc_mem,
-                                 maps[i+1], 0x2);
+        memory_region_init_alias(port, NULL, "escc-legacy-port",
+                                 macio_state->escc_mem, maps[i+1], 0x2);
         memory_region_add_subregion(escc_legacy, maps[i], port);
     }
 
@@ -269,7 +269,7 @@
     MacIOState *s = MACIO(obj);
     MemoryRegion *dbdma_mem;
 
-    memory_region_init(&s->bar, "macio", 0x80000);
+    memory_region_init(&s->bar, NULL, "macio", 0x80000);
 
     object_initialize(&s->cuda, TYPE_CUDA);
     qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default());
diff --git a/hw/misc/milkymist-hpdmc.c b/hw/misc/milkymist-hpdmc.c
index d922f6f..a498881 100644
--- a/hw/misc/milkymist-hpdmc.c
+++ b/hw/misc/milkymist-hpdmc.c
@@ -127,7 +127,7 @@
 {
     MilkymistHpdmcState *s = FROM_SYSBUS(typeof(*s), dev);
 
-    memory_region_init_io(&s->regs_region, &hpdmc_mmio_ops, s,
+    memory_region_init_io(&s->regs_region, OBJECT(dev), &hpdmc_mmio_ops, s,
             "milkymist-hpdmc", R_MAX * 4);
     sysbus_init_mmio(dev, &s->regs_region);
 
diff --git a/hw/misc/milkymist-pfpu.c b/hw/misc/milkymist-pfpu.c
index fe1b039..2b64ee7 100644
--- a/hw/misc/milkymist-pfpu.c
+++ b/hw/misc/milkymist-pfpu.c
@@ -497,7 +497,7 @@
 
     sysbus_init_irq(dev, &s->irq);
 
-    memory_region_init_io(&s->regs_region, &pfpu_mmio_ops, s,
+    memory_region_init_io(&s->regs_region, OBJECT(dev), &pfpu_mmio_ops, s,
             "milkymist-pfpu", MICROCODE_END * 4);
     sysbus_init_mmio(dev, &s->regs_region);
 
diff --git a/hw/misc/mst_fpga.c b/hw/misc/mst_fpga.c
index 1dd1505..604be5e 100644
--- a/hw/misc/mst_fpga.c
+++ b/hw/misc/mst_fpga.c
@@ -208,7 +208,7 @@
 	/* alloc the external 16 irqs */
 	qdev_init_gpio_in(&dev->qdev, mst_fpga_set_irq, MST_NUM_IRQS);
 
-	memory_region_init_io(&s->iomem, &mst_fpga_ops, s,
+	memory_region_init_io(&s->iomem, OBJECT(s), &mst_fpga_ops, s,
 			    "fpga", 0x00100000);
 	sysbus_init_mmio(dev, &s->iomem);
 	return 0;
diff --git a/hw/misc/omap_gpmc.c b/hw/misc/omap_gpmc.c
index 91adb66..2047274 100644
--- a/hw/misc/omap_gpmc.c
+++ b/hw/misc/omap_gpmc.c
@@ -413,7 +413,7 @@
      * constant), the mask should cause wrapping of the address space, so
      * that the same memory becomes accessible at every <i>size</i> bytes
      * starting from <i>base</i>.  */
-    memory_region_init(&f->container, "omap-gpmc-file", size);
+    memory_region_init(&f->container, NULL, "omap-gpmc-file", size);
     memory_region_add_subregion(&f->container, 0,
                                 omap_gpmc_cs_memregion(s, cs));
     memory_region_add_subregion(get_system_memory(), base,
@@ -826,7 +826,7 @@
     struct omap_gpmc_s *s = (struct omap_gpmc_s *)
             g_malloc0(sizeof(struct omap_gpmc_s));
 
-    memory_region_init_io(&s->iomem, &omap_gpmc_ops, s, "omap-gpmc", 0x1000);
+    memory_region_init_io(&s->iomem, NULL, &omap_gpmc_ops, s, "omap-gpmc", 0x1000);
     memory_region_add_subregion(get_system_memory(), base, &s->iomem);
 
     s->irq = irq;
@@ -843,14 +843,14 @@
      * guest-requested size.
      */
     for (cs = 0; cs < 8; cs++) {
-        memory_region_init_io(&s->cs_file[cs].nandiomem,
+        memory_region_init_io(&s->cs_file[cs].nandiomem, NULL,
                               &omap_nand_ops,
                               &s->cs_file[cs],
                               "omap-nand",
                               256 * 1024 * 1024);
     }
 
-    memory_region_init_io(&s->prefetch.iomem, &omap_prefetch_ops, s,
+    memory_region_init_io(&s->prefetch.iomem, NULL, &omap_prefetch_ops, s,
                           "omap-gpmc-prefetch", 256 * 1024 * 1024);
     return s;
 }
diff --git a/hw/misc/omap_l4.c b/hw/misc/omap_l4.c
index ac8251f..f237250 100644
--- a/hw/misc/omap_l4.c
+++ b/hw/misc/omap_l4.c
@@ -136,7 +136,7 @@
     ta->status = 0x00000000;
     ta->control = 0x00000200;	/* XXX 01000200 for L4TAO */
 
-    memory_region_init_io(&ta->iomem, &omap_l4ta_ops, ta, "omap.l4ta",
+    memory_region_init_io(&ta->iomem, NULL, &omap_l4ta_ops, ta, "omap.l4ta",
                           omap_l4_region_size(ta, info->ta_region));
     omap_l4_attach(ta, info->ta_region, &ta->iomem);
 
diff --git a/hw/misc/omap_sdrc.c b/hw/misc/omap_sdrc.c
index e38b571..ed62caf 100644
--- a/hw/misc/omap_sdrc.c
+++ b/hw/misc/omap_sdrc.c
@@ -161,7 +161,7 @@
 
     omap_sdrc_reset(s);
 
-    memory_region_init_io(&s->iomem, &omap_sdrc_ops, s, "omap.sdrc", 0x1000);
+    memory_region_init_io(&s->iomem, NULL, &omap_sdrc_ops, s, "omap.sdrc", 0x1000);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
     return s;
diff --git a/hw/misc/omap_tap.c b/hw/misc/omap_tap.c
index 99b70d5..9d2b710 100644
--- a/hw/misc/omap_tap.c
+++ b/hw/misc/omap_tap.c
@@ -110,7 +110,7 @@
 void omap_tap_init(struct omap_target_agent_s *ta,
                 struct omap_mpu_state_s *mpu)
 {
-    memory_region_init_io(&mpu->tap_iomem, &omap_tap_ops, mpu, "omap.tap",
+    memory_region_init_io(&mpu->tap_iomem, NULL, &omap_tap_ops, mpu, "omap.tap",
                           omap_l4_region_size(ta, 0));
     omap_l4_attach(ta, 0, &mpu->tap_iomem);
 }
diff --git a/hw/misc/pc-testdev.c b/hw/misc/pc-testdev.c
index e6707d6..699a16f 100644
--- a/hw/misc/pc-testdev.c
+++ b/hw/misc/pc-testdev.c
@@ -149,13 +149,13 @@
     MemoryRegion *mem = isa_address_space(isa);
     MemoryRegion *io = isa_address_space_io(isa);
 
-    memory_region_init_io(&dev->ioport, &test_ioport_ops, dev,
+    memory_region_init_io(&dev->ioport, OBJECT(dev), &test_ioport_ops, dev,
                           "pc-testdev-ioport", 4);
-    memory_region_init_io(&dev->flush, &test_flush_ops, dev,
+    memory_region_init_io(&dev->flush, OBJECT(dev), &test_flush_ops, dev,
                           "pc-testdev-flush-page", 4);
-    memory_region_init_io(&dev->irq, &test_irq_ops, dev,
+    memory_region_init_io(&dev->irq, OBJECT(dev), &test_irq_ops, dev,
                           "pc-testdev-irq-line", 24);
-    memory_region_init_io(&dev->iomem, &test_iomem_ops, dev,
+    memory_region_init_io(&dev->iomem, OBJECT(dev), &test_iomem_ops, dev,
                           "pc-testdev-iomem", IOMEM_LEN);
 
     memory_region_add_subregion(io,  0xe0,       &dev->ioport);
diff --git a/hw/misc/pci-testdev.c b/hw/misc/pci-testdev.c
index 71ce5a3..8b0b73f 100644
--- a/hw/misc/pci-testdev.c
+++ b/hw/misc/pci-testdev.c
@@ -236,9 +236,9 @@
 
     pci_conf[PCI_INTERRUPT_PIN] = 0; /* no interrupt pin */
 
-    memory_region_init_io(&d->mmio, &pci_testdev_mmio_ops, d,
+    memory_region_init_io(&d->mmio, OBJECT(d), &pci_testdev_mmio_ops, d,
                           "pci-testdev-mmio", IOTEST_MEMSIZE * 2);
-    memory_region_init_io(&d->portio, &pci_testdev_pio_ops, d,
+    memory_region_init_io(&d->portio, OBJECT(d), &pci_testdev_pio_ops, d,
                           "pci-testdev-portio", IOTEST_IOSIZE * 2);
     pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
     pci_register_bar(&d->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->portio);
diff --git a/hw/misc/puv3_pm.c b/hw/misc/puv3_pm.c
index 0aacdc2..5592560 100644
--- a/hw/misc/puv3_pm.c
+++ b/hw/misc/puv3_pm.c
@@ -120,7 +120,7 @@
 
     s->reg_PCGR = 0x0;
 
-    memory_region_init_io(&s->iomem, &puv3_pm_ops, s, "puv3_pm",
+    memory_region_init_io(&s->iomem, OBJECT(s), &puv3_pm_ops, s, "puv3_pm",
             PUV3_REGS_OFFSET);
     sysbus_init_mmio(dev, &s->iomem);
 
diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c
index 060099b..7bb49a5 100644
--- a/hw/misc/pvpanic.c
+++ b/hw/misc/pvpanic.c
@@ -90,33 +90,36 @@
 {
     PVPanicState *s = ISA_PVPANIC_DEVICE(obj);
 
-    memory_region_init_io(&s->io, &pvpanic_ops, s, "pvpanic", 1);
+    memory_region_init_io(&s->io, OBJECT(s), &pvpanic_ops, s, "pvpanic", 1);
 }
 
 static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp)
 {
     ISADevice *d = ISA_DEVICE(dev);
     PVPanicState *s = ISA_PVPANIC_DEVICE(dev);
-    static bool port_configured;
-    FWCfgState *fw_cfg;
 
     isa_register_ioport(d, &s->io, s->ioport);
-
-    if (!port_configured) {
-        fw_cfg = fw_cfg_find();
-        if (fw_cfg) {
-            fw_cfg_add_file(fw_cfg, "etc/pvpanic-port",
-                            g_memdup(&s->ioport, sizeof(s->ioport)),
-                            sizeof(s->ioport));
-            port_configured = true;
-        }
-    }
 }
 
-int pvpanic_init(ISABus *bus)
+static void pvpanic_fw_cfg(ISADevice *dev, FWCfgState *fw_cfg)
 {
-    isa_create_simple(bus, TYPE_ISA_PVPANIC_DEVICE);
-    return 0;
+    PVPanicState *s = ISA_PVPANIC_DEVICE(dev);
+    uint16_t *pvpanic_port = g_malloc(sizeof(*pvpanic_port));
+    *pvpanic_port = cpu_to_le16(s->ioport);
+
+    fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port,
+                    sizeof(*pvpanic_port));
+}
+
+void pvpanic_init(ISABus *bus)
+{
+    ISADevice *dev;
+    FWCfgState *fw_cfg = fw_cfg_find();
+    if (!fw_cfg) {
+        return;
+    }
+    dev = isa_create_simple (bus, TYPE_ISA_PVPANIC_DEVICE);
+    pvpanic_fw_cfg(dev, fw_cfg);
 }
 
 static Property pvpanic_isa_properties[] = {
diff --git a/hw/misc/pxa2xx_pcmcia.c b/hw/misc/pxa2xx_pcmcia.c
index 323d458..ef71a2a 100644
--- a/hw/misc/pxa2xx_pcmcia.c
+++ b/hw/misc/pxa2xx_pcmcia.c
@@ -128,7 +128,7 @@
             g_malloc0(sizeof(PXA2xxPCMCIAState));
 
     /* Socket I/O Memory Space */
-    memory_region_init_io(&s->iomem, &pxa2xx_pcmcia_io_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &pxa2xx_pcmcia_io_ops, s,
                           "pxa2xx-pcmcia-io", 0x04000000);
     memory_region_add_subregion(sysmem, base | 0x00000000,
                                 &s->iomem);
@@ -136,13 +136,13 @@
     /* Then next 64 MB is reserved */
 
     /* Socket Attribute Memory Space */
-    memory_region_init_io(&s->attr_iomem, &pxa2xx_pcmcia_attr_ops, s,
+    memory_region_init_io(&s->attr_iomem, NULL, &pxa2xx_pcmcia_attr_ops, s,
                           "pxa2xx-pcmcia-attribute", 0x04000000);
     memory_region_add_subregion(sysmem, base | 0x08000000,
                                 &s->attr_iomem);
 
     /* Socket Common Memory Space */
-    memory_region_init_io(&s->common_iomem, &pxa2xx_pcmcia_common_ops, s,
+    memory_region_init_io(&s->common_iomem, NULL, &pxa2xx_pcmcia_common_ops, s,
                           "pxa2xx-pcmcia-common", 0x04000000);
     memory_region_add_subregion(sysmem, base | 0x0c000000,
                                 &s->common_iomem);
diff --git a/hw/misc/slavio_misc.c b/hw/misc/slavio_misc.c
index a7a9368..d274fb4 100644
--- a/hw/misc/slavio_misc.c
+++ b/hw/misc/slavio_misc.c
@@ -412,7 +412,7 @@
     sysbus_init_irq(dev, &s->cpu_halt);
 
     /* Power management (APC) XXX: not a Slavio device */
-    memory_region_init_io(&s->iomem, &apc_mem_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &apc_mem_ops, s,
                           "apc", MISC_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
     return 0;
@@ -427,39 +427,39 @@
 
     /* 8 bit registers */
     /* Slavio control */
-    memory_region_init_io(&s->cfg_iomem, &slavio_cfg_mem_ops, s,
+    memory_region_init_io(&s->cfg_iomem, OBJECT(s), &slavio_cfg_mem_ops, s,
                           "configuration", MISC_SIZE);
     sysbus_init_mmio(dev, &s->cfg_iomem);
 
     /* Diagnostics */
-    memory_region_init_io(&s->diag_iomem, &slavio_diag_mem_ops, s,
+    memory_region_init_io(&s->diag_iomem, OBJECT(s), &slavio_diag_mem_ops, s,
                           "diagnostic", MISC_SIZE);
     sysbus_init_mmio(dev, &s->diag_iomem);
 
     /* Modem control */
-    memory_region_init_io(&s->mdm_iomem, &slavio_mdm_mem_ops, s,
+    memory_region_init_io(&s->mdm_iomem, OBJECT(s), &slavio_mdm_mem_ops, s,
                           "modem", MISC_SIZE);
     sysbus_init_mmio(dev, &s->mdm_iomem);
 
     /* 16 bit registers */
     /* ss600mp diag LEDs */
-    memory_region_init_io(&s->led_iomem, &slavio_led_mem_ops, s,
+    memory_region_init_io(&s->led_iomem, OBJECT(s), &slavio_led_mem_ops, s,
                           "leds", MISC_SIZE);
     sysbus_init_mmio(dev, &s->led_iomem);
 
     /* 32 bit registers */
     /* System control */
-    memory_region_init_io(&s->sysctrl_iomem, &slavio_sysctrl_mem_ops, s,
+    memory_region_init_io(&s->sysctrl_iomem, OBJECT(s), &slavio_sysctrl_mem_ops, s,
                           "system-control", MISC_SIZE);
     sysbus_init_mmio(dev, &s->sysctrl_iomem);
 
     /* AUX 1 (Misc System Functions) */
-    memory_region_init_io(&s->aux1_iomem, &slavio_aux1_mem_ops, s,
+    memory_region_init_io(&s->aux1_iomem, OBJECT(s), &slavio_aux1_mem_ops, s,
                           "misc-system-functions", MISC_SIZE);
     sysbus_init_mmio(dev, &s->aux1_iomem);
 
     /* AUX 2 (Software Powerdown Control) */
-    memory_region_init_io(&s->aux2_iomem, &slavio_aux2_mem_ops, s,
+    memory_region_init_io(&s->aux2_iomem, OBJECT(s), &slavio_aux2_mem_ops, s,
                           "software-powerdown-control", MISC_SIZE);
     sysbus_init_mmio(dev, &s->aux2_iomem);
 
diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index 52fb036..540c377 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -1154,7 +1154,7 @@
     quirk->vdev = vdev;
     quirk->data = (physbar >> 8) & 0xff;
 
-    memory_region_init_io(&quirk->mem, &vfio_ati_3c3_quirk, quirk,
+    memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_ati_3c3_quirk, quirk,
                           "vfio-ati-3c3-quirk", 1);
     memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, 3,
                                 &quirk->mem);
@@ -1245,7 +1245,7 @@
     quirk = g_malloc0(sizeof(*quirk));
     quirk->vdev = vdev;
 
-    memory_region_init_io(&quirk->mem, &vfio_ati_4010_quirk, quirk,
+    memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_ati_4010_quirk, quirk,
                           "vfio-ati-4010-quirk", 8);
     memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1);
 
@@ -1331,7 +1331,7 @@
     quirk = g_malloc0(sizeof(*quirk));
     quirk->vdev = vdev;
 
-    memory_region_init_io(&quirk->mem, &vfio_ati_f10_quirk, quirk,
+    memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_ati_f10_quirk, quirk,
                           "vfio-ati-f10-quirk", 8);
     memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1);
 
@@ -1451,7 +1451,7 @@
     quirk = g_malloc0(sizeof(*quirk));
     quirk->vdev = vdev;
 
-    memory_region_init_io(&quirk->mem, &vfio_nvidia_3d0_quirk, quirk,
+    memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_3d0_quirk, quirk,
                           "vfio-nvidia-3d0-quirk", 6);
     memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem,
                                 0x10, &quirk->mem);
@@ -1566,7 +1566,7 @@
     quirk = g_malloc0(sizeof(*quirk));
     quirk->vdev = vdev;
 
-    memory_region_init_io(&quirk->mem, &vfio_nvidia_bar5_window_quirk, quirk,
+    memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_bar5_window_quirk, quirk,
                           "vfio-nvidia-bar5-window-quirk", 16);
     memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1);
 
@@ -1644,7 +1644,7 @@
     quirk = g_malloc0(sizeof(*quirk));
     quirk->vdev = vdev;
 
-    memory_region_init_io(&quirk->mem, &vfio_nvidia_bar0_88000_quirk, quirk,
+    memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_bar0_88000_quirk, quirk,
                           "vfio-nvidia-bar0-88000-quirk",
                           TARGET_PAGE_ALIGN(PCIE_CONFIG_SPACE_SIZE));
     memory_region_add_subregion_overlap(&vdev->bars[nr].mem,
@@ -1723,7 +1723,7 @@
     quirk = g_malloc0(sizeof(*quirk));
     quirk->vdev = vdev;
 
-    memory_region_init_io(&quirk->mem, &vfio_nvidia_bar0_1800_quirk, quirk,
+    memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_bar0_1800_quirk, quirk,
                           "vfio-nvidia-bar0-1800-quirk",
                           TARGET_PAGE_ALIGN(PCI_CONFIG_SPACE_SIZE));
     memory_region_add_subregion_overlap(&vdev->bars[nr].mem,
@@ -1969,6 +1969,7 @@
     DPRINTF("region_add %"HWADDR_PRIx" - %"HWADDR_PRIx" [%p]\n",
             iova, end - 1, vaddr);
 
+    memory_region_ref(section->mr);
     ret = vfio_dma_map(container, iova, end - iova, vaddr, section->readonly);
     if (ret) {
         error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", "
@@ -2010,6 +2011,7 @@
             iova, end - 1);
 
     ret = vfio_dma_unmap(container, iova, end - iova);
+    memory_region_unref(section->mr);
     if (ret) {
         error_report("vfio_dma_unmap(%p, 0x%"HWADDR_PRIx", "
                      "0x%"HWADDR_PRIx") = %d (%m)",
@@ -2203,7 +2205,8 @@
     memory_region_destroy(&bar->mem);
 }
 
-static int vfio_mmap_bar(VFIOBAR *bar, MemoryRegion *mem, MemoryRegion *submem,
+static int vfio_mmap_bar(VFIODevice *vdev, VFIOBAR *bar,
+                         MemoryRegion *mem, MemoryRegion *submem,
                          void **map, size_t size, off_t offset,
                          const char *name)
 {
@@ -2228,11 +2231,11 @@
             goto empty_region;
         }
 
-        memory_region_init_ram_ptr(submem, name, size, *map);
+        memory_region_init_ram_ptr(submem, OBJECT(vdev), name, size, *map);
     } else {
 empty_region:
         /* Create a zero sized sub-region to make cleanup easy. */
-        memory_region_init(submem, name, 0);
+        memory_region_init(submem, OBJECT(vdev), name, 0);
     }
 
     memory_region_add_subregion(mem, offset, submem);
@@ -2271,7 +2274,7 @@
            ~PCI_BASE_ADDRESS_IO_MASK : ~PCI_BASE_ADDRESS_MEM_MASK);
 
     /* A "slow" read/write mapping underlies all BARs */
-    memory_region_init_io(&bar->mem, &vfio_bar_ops, bar, name, size);
+    memory_region_init_io(&bar->mem, OBJECT(vdev), &vfio_bar_ops, bar, name, size);
     pci_register_bar(&vdev->pdev, nr, type, &bar->mem);
 
     /*
@@ -2283,7 +2286,7 @@
     }
 
     strncat(name, " mmap", sizeof(name) - strlen(name) - 1);
-    if (vfio_mmap_bar(bar, &bar->mem,
+    if (vfio_mmap_bar(vdev, bar, &bar->mem,
                       &bar->mmap_mem, &bar->mmap, size, 0, name)) {
         error_report("%s unsupported. Performance may be slow", name);
     }
@@ -2297,7 +2300,7 @@
         size = start < bar->size ? bar->size - start : 0;
         strncat(name, " msix-hi", sizeof(name) - strlen(name) - 1);
         /* VFIOMSIXInfo contains another MemoryRegion for this mapping */
-        if (vfio_mmap_bar(bar, &bar->mem, &vdev->msix->mmap_mem,
+        if (vfio_mmap_bar(vdev, bar, &bar->mem, &vdev->msix->mmap_mem,
                           &vdev->msix->mmap, size, start, name)) {
             error_report("%s unsupported. Performance may be slow", name);
         }
@@ -2316,17 +2319,17 @@
 
     if (vdev->has_vga) {
         memory_region_init_io(&vdev->vga.region[QEMU_PCI_VGA_MEM].mem,
-                              &vfio_vga_ops,
+                              OBJECT(vdev), &vfio_vga_ops,
                               &vdev->vga.region[QEMU_PCI_VGA_MEM],
                               "vfio-vga-mmio@0xa0000",
                               QEMU_PCI_VGA_MEM_SIZE);
         memory_region_init_io(&vdev->vga.region[QEMU_PCI_VGA_IO_LO].mem,
-                              &vfio_vga_ops,
+                              OBJECT(vdev), &vfio_vga_ops,
                               &vdev->vga.region[QEMU_PCI_VGA_IO_LO],
                               "vfio-vga-io@0x3b0",
                               QEMU_PCI_VGA_IO_LO_SIZE);
         memory_region_init_io(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem,
-                              &vfio_vga_ops,
+                              OBJECT(vdev), &vfio_vga_ops,
                               &vdev->vga.region[QEMU_PCI_VGA_IO_HI],
                               "vfio-vga-io@0x3c0",
                               QEMU_PCI_VGA_IO_HI_SIZE);
@@ -2588,7 +2591,7 @@
     snprintf(name, sizeof(name), "vfio[%04x:%02x:%02x.%x].rom",
              vdev->host.domain, vdev->host.bus, vdev->host.slot,
              vdev->host.function);
-    memory_region_init_ram(&vdev->pdev.rom, name, size);
+    memory_region_init_ram(&vdev->pdev.rom, OBJECT(vdev), name, size);
     ptr = memory_region_get_ram_ptr(&vdev->pdev.rom);
     memset(ptr, 0xff, size);
 
diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
index 8363dfd..7463776 100644
--- a/hw/misc/vmport.c
+++ b/hw/misc/vmport.c
@@ -43,13 +43,13 @@
     ISADevice parent_obj;
 
     MemoryRegion io;
-    IOPortReadFunc *func[VMPORT_ENTRIES];
+    VMPortReadFunc *func[VMPORT_ENTRIES];
     void *opaque[VMPORT_ENTRIES];
 } VMPortState;
 
 static VMPortState *port_state;
 
-void vmport_register(unsigned char command, IOPortReadFunc *func, void *opaque)
+void vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque)
 {
     if (command >= VMPORT_ENTRIES)
         return;
@@ -142,7 +142,7 @@
     ISADevice *isadev = ISA_DEVICE(dev);
     VMPortState *s = VMPORT(dev);
 
-    memory_region_init_io(&s->io, &vmport_ops, s, "vmport", 1);
+    memory_region_init_io(&s->io, OBJECT(s), &vmport_ops, s, "vmport", 1);
     isa_register_ioport(isadev, &s->io, 0x5658);
 
     port_state = s;
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
index 8418327..fc7a85f 100644
--- a/hw/misc/zynq_slcr.c
+++ b/hw/misc/zynq_slcr.c
@@ -494,7 +494,7 @@
 {
     ZynqSLCRState *s = FROM_SYSBUS(ZynqSLCRState, dev);
 
-    memory_region_init_io(&s->iomem, &slcr_ops, s, "slcr", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &slcr_ops, s, "slcr", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
diff --git a/hw/moxie/moxiesim.c b/hw/moxie/moxiesim.c
index 649f9a7..ef4f3a8 100644
--- a/hw/moxie/moxiesim.c
+++ b/hw/moxie/moxiesim.c
@@ -136,11 +136,11 @@
     qemu_register_reset(main_cpu_reset, cpu);
 
     /* Allocate RAM. */
-    memory_region_init_ram(ram, "moxiesim.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "moxiesim.ram", ram_size);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space_mem, ram_base, ram);
 
-    memory_region_init_ram(rom, "moxie.rom", 128*0x1000);
+    memory_region_init_ram(rom, NULL, "moxie.rom", 128*0x1000);
     vmstate_register_ram_global(rom);
     memory_region_add_subregion(get_system_memory(), 0x1000, rom);
 
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index e177057..ac929cb 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -1163,7 +1163,8 @@
 
     s = FROM_SYSBUS(GemState, dev);
     gem_init_register_masks(s);
-    memory_region_init_io(&s->iomem, &gem_ops, s, "enet", sizeof(s->regs));
+    memory_region_init_io(&s->iomem, OBJECT(s), &gem_ops, s,
+                          "enet", sizeof(s->regs));
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index 2289f08..049aa70 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -908,7 +908,7 @@
     qemu_register_reset(nic_reset, s);
     nic_reset(s);
 
-    memory_region_init_io(&s->mmio, &dp8393x_ops, s,
+    memory_region_init_io(&s->mmio, NULL, &dp8393x_ops, s,
                           "dp8393x", 0x40 << it_shift);
     memory_region_add_subregion(address_space, base, &s->mmio);
 }
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index e6f46f0..5f04f13 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -556,7 +556,7 @@
     uint32_t txd_lower = le32_to_cpu(dp->lower.data);
     uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D);
     unsigned int split_size = txd_lower & 0xffff, bytes, sz, op;
-    unsigned int msh = 0xfffff, hdr = 0;
+    unsigned int msh = 0xfffff;
     uint64_t addr;
     struct e1000_context_desc *xp = (struct e1000_context_desc *)dp;
     struct e1000_tx *tp = &s->tx;
@@ -603,8 +603,7 @@
         
     addr = le64_to_cpu(dp->buffer_addr);
     if (tp->tse && tp->cptse) {
-        hdr = tp->hdr_len;
-        msh = hdr + tp->mss;
+        msh = tp->hdr_len + tp->mss;
         do {
             bytes = split_size;
             if (tp->size + bytes > msh)
@@ -612,14 +611,16 @@
 
             bytes = MIN(sizeof(tp->data) - tp->size, bytes);
             pci_dma_read(&s->dev, addr, tp->data + tp->size, bytes);
-            if ((sz = tp->size + bytes) >= hdr && tp->size < hdr)
-                memmove(tp->header, tp->data, hdr);
+            sz = tp->size + bytes;
+            if (sz >= tp->hdr_len && tp->size < tp->hdr_len) {
+                memmove(tp->header, tp->data, tp->hdr_len);
+            }
             tp->size = sz;
             addr += bytes;
             if (sz == msh) {
                 xmit_seg(s);
-                memmove(tp->data, tp->header, hdr);
-                tp->size = hdr;
+                memmove(tp->data, tp->header, tp->hdr_len);
+                tp->size = tp->hdr_len;
             }
         } while (split_size -= bytes);
     } else if (!tp->tse && tp->cptse) {
@@ -633,8 +634,9 @@
 
     if (!(txd_lower & E1000_TXD_CMD_EOP))
         return;
-    if (!(tp->tse && tp->cptse && tp->size < hdr))
+    if (!(tp->tse && tp->cptse && tp->size < tp->hdr_len)) {
         xmit_seg(s);
+    }
     tp->tso_frames = 0;
     tp->sum_needed = 0;
     tp->vlan_needed = 0;
@@ -1276,13 +1278,13 @@
         E1000_IMC, E1000_TCTL, E1000_TDT, PNPMMIO_SIZE
     };
 
-    memory_region_init_io(&d->mmio, &e1000_mmio_ops, d, "e1000-mmio",
-                          PNPMMIO_SIZE);
+    memory_region_init_io(&d->mmio, OBJECT(d), &e1000_mmio_ops, d,
+                          "e1000-mmio", PNPMMIO_SIZE);
     memory_region_add_coalescing(&d->mmio, 0, excluded_regs[0]);
     for (i = 0; excluded_regs[i] != PNPMMIO_SIZE; i++)
         memory_region_add_coalescing(&d->mmio, excluded_regs[i] + 4,
                                      excluded_regs[i+1] - excluded_regs[i] - 4);
-    memory_region_init_io(&d->io, &e1000_io_ops, d, "e1000-io", IOPORT_SIZE);
+    memory_region_init_io(&d->io, OBJECT(d), &e1000_io_ops, d, "e1000-io", IOPORT_SIZE);
 }
 
 static void
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
index dc99ea6..e0befb2 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -1876,15 +1876,15 @@
     s->eeprom = eeprom93xx_new(&pci_dev->qdev, EEPROM_SIZE);
 
     /* Handler for memory-mapped I/O */
-    memory_region_init_io(&s->mmio_bar, &eepro100_ops, s, "eepro100-mmio",
-                          PCI_MEM_SIZE);
+    memory_region_init_io(&s->mmio_bar, OBJECT(s), &eepro100_ops, s,
+                          "eepro100-mmio", PCI_MEM_SIZE);
     pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->mmio_bar);
-    memory_region_init_io(&s->io_bar, &eepro100_ops, s, "eepro100-io",
-                          PCI_IO_SIZE);
+    memory_region_init_io(&s->io_bar, OBJECT(s), &eepro100_ops, s,
+                          "eepro100-io", PCI_IO_SIZE);
     pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
     /* FIXME: flash aliases to mmio?! */
-    memory_region_init_io(&s->flash_bar, &eepro100_ops, s, "eepro100-flash",
-                          PCI_FLASH_SIZE);
+    memory_region_init_io(&s->flash_bar, OBJECT(s), &eepro100_ops, s,
+                          "eepro100-flash", PCI_FLASH_SIZE);
     pci_register_bar(&s->dev, 2, 0, &s->flash_bar);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c
index 1039913..ab9a215 100644
--- a/hw/net/etraxfs_eth.c
+++ b/hw/net/etraxfs_eth.c
@@ -610,7 +610,8 @@
     s->dma_in->client.opaque = s;
     s->dma_in->client.pull = NULL;
 
-    memory_region_init_io(&s->mmio, &eth_ops, s, "etraxfs-eth", 0x5c);
+    memory_region_init_io(&s->mmio, OBJECT(dev), &eth_ops, s,
+                          "etraxfs-eth", 0x5c);
     sysbus_init_mmio(dev, &s->mmio);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
index 403fb86..3323f48 100644
--- a/hw/net/lan9118.c
+++ b/hw/net/lan9118.c
@@ -1328,7 +1328,8 @@
     const MemoryRegionOps *mem_ops =
             s->mode_16bit ? &lan9118_16bit_mem_ops : &lan9118_mem_ops;
 
-    memory_region_init_io(&s->mmio, mem_ops, s, "lan9118-mmio", 0x100);
+    memory_region_init_io(&s->mmio, OBJECT(dev), mem_ops, s,
+                          "lan9118-mmio", 0x100);
     sysbus_init_mmio(dev, &s->mmio);
     sysbus_init_irq(dev, &s->irq);
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
diff --git a/hw/net/lance.c b/hw/net/lance.c
index 187497c..98bcdfc 100644
--- a/hw/net/lance.c
+++ b/hw/net/lance.c
@@ -117,7 +117,8 @@
     SysBusPCNetState *d = FROM_SYSBUS(SysBusPCNetState, dev);
     PCNetState *s = &d->state;
 
-    memory_region_init_io(&s->mmio, &lance_mem_ops, d, "lance-mmio", 4);
+    memory_region_init_io(&s->mmio, OBJECT(d), &lance_mem_ops, d,
+                          "lance-mmio", 4);
 
     qdev_init_gpio_in(&dev->qdev, parent_lance_reset, 1);
 
diff --git a/hw/net/mcf_fec.c b/hw/net/mcf_fec.c
index 2ef5a0d..4bff3de 100644
--- a/hw/net/mcf_fec.c
+++ b/hw/net/mcf_fec.c
@@ -468,7 +468,7 @@
     s->sysmem = sysmem;
     s->irq = irq;
 
-    memory_region_init_io(&s->iomem, &mcf_fec_ops, s, "fec", 0x400);
+    memory_region_init_io(&s->iomem, NULL, &mcf_fec_ops, s, "fec", 0x400);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
     s->conf.macaddr = nd->macaddr;
diff --git a/hw/net/milkymist-minimac2.c b/hw/net/milkymist-minimac2.c
index 4ef6318..2ef4ac3 100644
--- a/hw/net/milkymist-minimac2.c
+++ b/hw/net/milkymist-minimac2.c
@@ -461,12 +461,12 @@
     sysbus_init_irq(dev, &s->rx_irq);
     sysbus_init_irq(dev, &s->tx_irq);
 
-    memory_region_init_io(&s->regs_region, &minimac2_ops, s,
+    memory_region_init_io(&s->regs_region, OBJECT(dev), &minimac2_ops, s,
                           "milkymist-minimac2", R_MAX * 4);
     sysbus_init_mmio(dev, &s->regs_region);
 
     /* register buffers memory */
-    memory_region_init_ram(&s->buffers, "milkymist-minimac2.buffers",
+    memory_region_init_ram(&s->buffers, OBJECT(dev), "milkymist-minimac2.buffers",
                            buffers_size);
     vmstate_register_ram_global(&s->buffers);
     s->rx0_buf = memory_region_get_ram_ptr(&s->buffers);
diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c
index ac6193a..9080850 100644
--- a/hw/net/mipsnet.c
+++ b/hw/net/mipsnet.c
@@ -235,7 +235,8 @@
 {
     MIPSnetState *s = DO_UPCAST(MIPSnetState, busdev, dev);
 
-    memory_region_init_io(&s->io, &mipsnet_ioport_ops, s, "mipsnet-io", 36);
+    memory_region_init_io(&s->io, OBJECT(dev), &mipsnet_ioport_ops, s,
+                          "mipsnet-io", 36);
     sysbus_init_mmio(dev, &s->io);
     sysbus_init_irq(dev, &s->irq);
 
diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c
index 9232abd..e3c8076 100644
--- a/hw/net/ne2000-isa.c
+++ b/hw/net/ne2000-isa.c
@@ -72,7 +72,7 @@
     ISANE2000State *isa = ISA_NE2000(dev);
     NE2000State *s = &isa->ne2000;
 
-    ne2000_setup_io(s, 0x20);
+    ne2000_setup_io(s, DEVICE(isadev), 0x20);
     isa_register_ioport(isadev, &s->io, isa->iobase);
 
     isa_init_irq(isadev, &s->irq, isa->isairq);
diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c
index 33ee03e..8d43fd9 100644
--- a/hw/net/ne2000.c
+++ b/hw/net/ne2000.c
@@ -699,9 +699,9 @@
 /***********************************************************/
 /* PCI NE2000 definitions */
 
-void ne2000_setup_io(NE2000State *s, unsigned size)
+void ne2000_setup_io(NE2000State *s, DeviceState *dev, unsigned size)
 {
-    memory_region_init_io(&s->io, &ne2000_ops, s, "ne2000", size);
+    memory_region_init_io(&s->io, OBJECT(dev), &ne2000_ops, s, "ne2000", size);
 }
 
 static void ne2000_cleanup(NetClientState *nc)
@@ -729,7 +729,7 @@
     pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin A */
 
     s = &d->ne2000;
-    ne2000_setup_io(s, 0x100);
+    ne2000_setup_io(s, DEVICE(pci_dev), 0x100);
     pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
     s->irq = d->dev.irq[0];
 
diff --git a/hw/net/ne2000.h b/hw/net/ne2000.h
index b31ae03..e500306 100644
--- a/hw/net/ne2000.h
+++ b/hw/net/ne2000.h
@@ -31,7 +31,7 @@
     uint8_t mem[NE2000_MEM_SIZE];
 } NE2000State;
 
-void ne2000_setup_io(NE2000State *s, unsigned size);
+void ne2000_setup_io(NE2000State *s, DeviceState *dev, unsigned size);
 extern const VMStateDescription vmstate_ne2000;
 void ne2000_reset(NE2000State *s);
 int ne2000_can_receive(NetClientState *nc);
diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c
index be64bf2..4637557 100644
--- a/hw/net/opencores_eth.c
+++ b/hw/net/opencores_eth.c
@@ -681,11 +681,11 @@
 {
     OpenEthState *s = DO_UPCAST(OpenEthState, dev, dev);
 
-    memory_region_init_io(&s->reg_io, &open_eth_reg_ops, s,
+    memory_region_init_io(&s->reg_io, OBJECT(dev), &open_eth_reg_ops, s,
             "open_eth.regs", 0x54);
     sysbus_init_mmio(dev, &s->reg_io);
 
-    memory_region_init_io(&s->desc_io, &open_eth_desc_ops, s,
+    memory_region_init_io(&s->desc_io, OBJECT(dev), &open_eth_desc_ops, s,
             "open_eth.desc", 0x400);
     sysbus_init_mmio(dev, &s->desc_io);
 
diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c
index 9df2b87..f4a5aef 100644
--- a/hw/net/pcnet-pci.c
+++ b/hw/net/pcnet-pci.c
@@ -315,10 +315,10 @@
     pci_conf[PCI_MAX_LAT] = 0xff;
 
     /* Handler for memory-mapped I/O */
-    memory_region_init_io(&d->state.mmio, &pcnet_mmio_ops, s, "pcnet-mmio",
-                          PCNET_PNPMMIO_SIZE);
+    memory_region_init_io(&d->state.mmio, OBJECT(d), &pcnet_mmio_ops, s,
+                          "pcnet-mmio", PCNET_PNPMMIO_SIZE);
 
-    memory_region_init_io(&d->io_bar, &pcnet_io_ops, s, "pcnet-io",
+    memory_region_init_io(&d->io_bar, OBJECT(d), &pcnet_io_ops, s, "pcnet-io",
                           PCNET_IOPORT_SIZE);
     pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->io_bar);
 
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
index 7993f9f..a00ff58 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -3486,8 +3486,10 @@
      * list bit in status register, and offset 0xdc seems unused. */
     pci_conf[PCI_CAPABILITY_LIST] = 0xdc;
 
-    memory_region_init_io(&s->bar_io, &rtl8139_io_ops, s, "rtl8139", 0x100);
-    memory_region_init_io(&s->bar_mem, &rtl8139_mmio_ops, s, "rtl8139", 0x100);
+    memory_region_init_io(&s->bar_io, OBJECT(s), &rtl8139_io_ops, s,
+                          "rtl8139", 0x100);
+    memory_region_init_io(&s->bar_mem, OBJECT(s), &rtl8139_mmio_ops, s,
+                          "rtl8139", 0x100);
     pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->bar_io);
     pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar_mem);
 
diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
index c2feae6..c49e37a 100644
--- a/hw/net/smc91c111.c
+++ b/hw/net/smc91c111.c
@@ -747,7 +747,7 @@
 static int smc91c111_init1(SysBusDevice *dev)
 {
     smc91c111_state *s = FROM_SYSBUS(smc91c111_state, dev);
-    memory_region_init_io(&s->mmio, &smc91c111_mem_ops, s,
+    memory_region_init_io(&s->mmio, OBJECT(s), &smc91c111_mem_ops, s,
                           "smc91c111-mmio", 16);
     sysbus_init_mmio(dev, &s->mmio);
     sysbus_init_irq(dev, &s->irq);
diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c
index 59b8456..aac7c76 100644
--- a/hw/net/stellaris_enet.c
+++ b/hw/net/stellaris_enet.c
@@ -405,8 +405,8 @@
 {
     stellaris_enet_state *s = FROM_SYSBUS(stellaris_enet_state, dev);
 
-    memory_region_init_io(&s->mmio, &stellaris_enet_ops, s, "stellaris_enet",
-                          0x1000);
+    memory_region_init_io(&s->mmio, OBJECT(s), &stellaris_enet_ops, s,
+                          "stellaris_enet", 0x1000);
     sysbus_init_mmio(dev, &s->mmio);
     sysbus_init_irq(dev, &s->irq);
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 4c575e5..b39ff08 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -2073,17 +2073,17 @@
 
     VMW_CBPRN("Starting init...");
 
-    memory_region_init_io(&s->bar0, &b0_ops, s,
+    memory_region_init_io(&s->bar0, OBJECT(s), &b0_ops, s,
                           "vmxnet3-b0", VMXNET3_PT_REG_SIZE);
     pci_register_bar(pci_dev, VMXNET3_BAR0_IDX,
                      PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0);
 
-    memory_region_init_io(&s->bar1, &b1_ops, s,
+    memory_region_init_io(&s->bar1, OBJECT(s), &b1_ops, s,
                           "vmxnet3-b1", VMXNET3_VD_REG_SIZE);
     pci_register_bar(pci_dev, VMXNET3_BAR1_IDX,
                      PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar1);
 
-    memory_region_init(&s->msix_bar, "vmxnet3-msix-bar",
+    memory_region_init(&s->msix_bar, OBJECT(s), "vmxnet3-msix-bar",
                        VMXNET3_MSIX_BAR_SIZE);
     pci_register_bar(pci_dev, VMXNET3_MSIX_BAR_IDX,
                      PCI_BASE_ADDRESS_SPACE_MEMORY, &s->msix_bar);
diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c
index 1d9074a..997a5b5 100644
--- a/hw/net/xgmac.c
+++ b/hw/net/xgmac.c
@@ -382,7 +382,8 @@
 {
     struct XgmacState *s = FROM_SYSBUS(typeof(*s), dev);
 
-    memory_region_init_io(&s->iomem, &enet_mem_ops, s, "xgmac", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &enet_mem_ops, s,
+                          "xgmac", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->sbd_irq);
     sysbus_init_irq(dev, &s->pmt_irq);
diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c
index 2ca1511..f173429 100644
--- a/hw/net/xilinx_axienet.c
+++ b/hw/net/xilinx_axienet.c
@@ -1001,7 +1001,7 @@
 
     sysbus_init_irq(sbd, &s->irq);
 
-    memory_region_init_io(&s->iomem, &enet_ops, s, "enet", 0x40000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &enet_ops, s, "enet", 0x40000);
     sysbus_init_mmio(sbd, &s->iomem);
 }
 
diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c
index b2e3523..2afc91a 100644
--- a/hw/net/xilinx_ethlite.c
+++ b/hw/net/xilinx_ethlite.c
@@ -221,8 +221,8 @@
     sysbus_init_irq(dev, &s->irq);
     s->rxbuf = 0;
 
-    memory_region_init_io(&s->mmio, &eth_ops, s, "xlnx.xps-ethernetlite",
-                                                                    R_MAX * 4);
+    memory_region_init_io(&s->mmio, OBJECT(s), &eth_ops, s,
+                          "xlnx.xps-ethernetlite", R_MAX * 4);
     sysbus_init_mmio(dev, &s->mmio);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
diff --git a/hw/nvram/ds1225y.c b/hw/nvram/ds1225y.c
index 488f1d7..fa218ce 100644
--- a/hw/nvram/ds1225y.c
+++ b/hw/nvram/ds1225y.c
@@ -117,7 +117,8 @@
 
     s->contents = g_malloc0(s->chip_size);
 
-    memory_region_init_io(&s->iomem, &nvram_ops, s, "nvram", s->chip_size);
+    memory_region_init_io(&s->iomem, OBJECT(s), &nvram_ops, s,
+                          "nvram", s->chip_size);
     sysbus_init_mmio(dev, &s->iomem);
 
     /* Read current file */
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 3c255ce..e455282 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -526,14 +526,14 @@
 {
     FWCfgState *s = FROM_SYSBUS(FWCfgState, dev);
 
-    memory_region_init_io(&s->ctl_iomem, &fw_cfg_ctl_mem_ops, s,
+    memory_region_init_io(&s->ctl_iomem, OBJECT(s), &fw_cfg_ctl_mem_ops, s,
                           "fwcfg.ctl", FW_CFG_SIZE);
     sysbus_init_mmio(dev, &s->ctl_iomem);
-    memory_region_init_io(&s->data_iomem, &fw_cfg_data_mem_ops, s,
+    memory_region_init_io(&s->data_iomem, OBJECT(s), &fw_cfg_data_mem_ops, s,
                           "fwcfg.data", FW_CFG_DATA_SIZE);
     sysbus_init_mmio(dev, &s->data_iomem);
     /* In case ctl and data overlap: */
-    memory_region_init_io(&s->comb_iomem, &fw_cfg_comb_mem_ops, s,
+    memory_region_init_io(&s->comb_iomem, OBJECT(s), &fw_cfg_comb_mem_ops, s,
                           "fwcfg", FW_CFG_SIZE);
 
     if (s->ctl_iobase + 1 == s->data_iobase) {
diff --git a/hw/nvram/mac_nvram.c b/hw/nvram/mac_nvram.c
index d76a06c..2eb0081 100644
--- a/hw/nvram/mac_nvram.c
+++ b/hw/nvram/mac_nvram.c
@@ -115,8 +115,8 @@
 
     s->data = g_malloc0(s->size);
 
-    memory_region_init_io(&s->mem, &macio_nvram_ops, s, "macio-nvram",
-                          s->size << s->it_shift);
+    memory_region_init_io(&s->mem, OBJECT(s), &macio_nvram_ops, s,
+                          "macio-nvram", s->size << s->it_shift);
     sysbus_init_mmio(d, &s->mem);
 }
 
diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
index 49bab1f..924438b 100644
--- a/hw/openrisc/openrisc_sim.c
+++ b/hw/openrisc/openrisc_sim.c
@@ -115,7 +115,7 @@
     }
 
     ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, "openrisc.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "openrisc.ram", ram_size);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(get_system_memory(), 0, ram);
 
diff --git a/hw/pci-bridge/dec.c b/hw/pci-bridge/dec.c
index cff458b..efc07c4 100644
--- a/hw/pci-bridge/dec.c
+++ b/hw/pci-bridge/dec.c
@@ -98,9 +98,9 @@
 
     phb = PCI_HOST_BRIDGE(dev);
 
-    memory_region_init_io(&phb->conf_mem, &pci_host_conf_le_ops,
+    memory_region_init_io(&phb->conf_mem, OBJECT(dev), &pci_host_conf_le_ops,
                           dev, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&phb->data_mem, &pci_host_data_le_ops,
+    memory_region_init_io(&phb->data_mem, OBJECT(dev), &pci_host_data_le_ops,
                           dev, "pci-data-idx", 0x1000);
     sysbus_init_mmio(dev, &phb->conf_mem);
     sysbus_init_mmio(dev, &phb->data_mem);
diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c
index 971b432..5f11323 100644
--- a/hw/pci-bridge/pci_bridge_dev.c
+++ b/hw/pci-bridge/pci_bridge_dev.c
@@ -46,7 +46,7 @@
     if (err) {
         goto bridge_error;
     }
-    memory_region_init(&bridge_dev->bar, "shpc-bar", shpc_bar_size(dev));
+    memory_region_init(&bridge_dev->bar, OBJECT(dev), "shpc-bar", shpc_bar_size(dev));
     err = shpc_init(dev, &br->sec_bus, &bridge_dev->bar, 0);
     if (err) {
         goto shpc_error;
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index e099655..06ace08 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -447,7 +447,7 @@
     sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
     d = FROM_SYSBUS(APBState, s);
 
-    memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
+    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",
@@ -525,18 +525,18 @@
     s->pci_irq_in = 0ULL;
 
     /* apb_config */
-    memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config",
-                          0x10000);
+    memory_region_init_io(&s->apb_config, OBJECT(s), &apb_config_ops, s,
+                          "apb-config", 0x10000);
     /* at region 0 */
     sysbus_init_mmio(dev, &s->apb_config);
 
-    memory_region_init_io(&s->pci_config, &pci_config_ops, s, "apb-pci-config",
-                          0x1000000);
+    memory_region_init_io(&s->pci_config, OBJECT(s), &pci_config_ops, s,
+                          "apb-pci-config", 0x1000000);
     /* at region 1 */
     sysbus_init_mmio(dev, &s->pci_config);
 
     /* pci_ioport */
-    memory_region_init_io(&s->pci_ioport, &pci_ioport_ops, s,
+    memory_region_init_io(&s->pci_ioport, OBJECT(s), &pci_ioport_ops, s,
                           "apb-pci-ioport", 0x10000);
     /* at region 2 */
     sysbus_init_mmio(dev, &s->pci_ioport);
diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c
index 974150b..592d666 100644
--- a/hw/pci-host/bonito.c
+++ b/hw/pci-host/bonito.c
@@ -722,29 +722,29 @@
     pci_config_set_prog_interface(dev->config, 0x00);
 
     /* set the north bridge register mapping */
-    memory_region_init_io(&s->iomem, &bonito_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &bonito_ops, s,
                           "north-bridge-register", BONITO_INTERNAL_REG_SIZE);
     sysbus_init_mmio(sysbus, &s->iomem);
     sysbus_mmio_map(sysbus, 0, BONITO_INTERNAL_REG_BASE);
 
     /* set the north bridge pci configure  mapping */
-    memory_region_init_io(&phb->conf_mem, &bonito_pciconf_ops, s,
+    memory_region_init_io(&phb->conf_mem, OBJECT(s), &bonito_pciconf_ops, s,
                           "north-bridge-pci-config", BONITO_PCICONFIG_SIZE);
     sysbus_init_mmio(sysbus, &phb->conf_mem);
     sysbus_mmio_map(sysbus, 1, BONITO_PCICONFIG_BASE);
 
     /* set the south bridge pci configure  mapping */
-    memory_region_init_io(&phb->data_mem, &bonito_spciconf_ops, s,
+    memory_region_init_io(&phb->data_mem, OBJECT(s), &bonito_spciconf_ops, s,
                           "south-bridge-pci-config", BONITO_SPCICONFIG_SIZE);
     sysbus_init_mmio(sysbus, &phb->data_mem);
     sysbus_mmio_map(sysbus, 2, BONITO_SPCICONFIG_BASE);
 
-    memory_region_init_io(&s->iomem_ldma, &bonito_ldma_ops, s,
+    memory_region_init_io(&s->iomem_ldma, OBJECT(s), &bonito_ldma_ops, s,
                           "ldma", 0x100);
     sysbus_init_mmio(sysbus, &s->iomem_ldma);
     sysbus_mmio_map(sysbus, 3, 0xbfe00200);
 
-    memory_region_init_io(&s->iomem_cop, &bonito_cop_ops, s,
+    memory_region_init_io(&s->iomem_cop, OBJECT(s), &bonito_cop_ops, s,
                           "cop", 0x100);
     sysbus_init_mmio(sysbus, &s->iomem_cop);
     sysbus_mmio_map(sysbus, 4, 0xbfe00300);
diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c
index 69344d9..4991ec4 100644
--- a/hw/pci-host/grackle.c
+++ b/hw/pci-host/grackle.c
@@ -76,8 +76,8 @@
     phb = PCI_HOST_BRIDGE(dev);
     d = GRACKLE_PCI_HOST_BRIDGE(dev);
 
-    memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
-    memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
+    memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL);
+    memory_region_init_alias(&d->pci_hole, OBJECT(s), "pci-hole", &d->pci_mmio,
                              0x80000000ULL, 0x7e000000ULL);
     memory_region_add_subregion(address_space_mem, 0x80000000ULL,
                                 &d->pci_hole);
@@ -104,9 +104,9 @@
 
     phb = PCI_HOST_BRIDGE(dev);
 
-    memory_region_init_io(&phb->conf_mem, &pci_host_conf_le_ops,
+    memory_region_init_io(&phb->conf_mem, OBJECT(dev), &pci_host_conf_le_ops,
                           dev, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&phb->data_mem, &pci_host_data_le_ops,
+    memory_region_init_io(&phb->data_mem, OBJECT(dev), &pci_host_data_le_ops,
                           dev, "pci-data-idx", 0x1000);
     sysbus_init_mmio(dev, &phb->conf_mem);
     sysbus_init_mmio(dev, &phb->data_mem);
diff --git a/hw/pci-host/pam.c b/hw/pci-host/pam.c
index 7181bd6..ec6be46 100644
--- a/hw/pci-host/pam.c
+++ b/hw/pci-host/pam.c
@@ -26,6 +26,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+
+#include "qom/object.h"
 #include "sysemu/sysemu.h"
 #include "hw/pci-host/pam.h"
 
@@ -49,24 +51,24 @@
     }
 }
 
-void init_pam(MemoryRegion *ram_memory, MemoryRegion *system_memory,
-              MemoryRegion *pci_address_space, PAMMemoryRegion *mem,
-              uint32_t start, uint32_t size)
+void init_pam(DeviceState *dev, MemoryRegion *ram_memory,
+              MemoryRegion *system_memory, MemoryRegion *pci_address_space,
+              PAMMemoryRegion *mem, uint32_t start, uint32_t size)
 {
     int i;
 
     /* RAM */
-    memory_region_init_alias(&mem->alias[3], "pam-ram", ram_memory,
+    memory_region_init_alias(&mem->alias[3], OBJECT(dev), "pam-ram", ram_memory,
                              start, size);
     /* ROM (XXX: not quite correct) */
-    memory_region_init_alias(&mem->alias[1], "pam-rom", ram_memory,
+    memory_region_init_alias(&mem->alias[1], OBJECT(dev), "pam-rom", ram_memory,
                              start, size);
     memory_region_set_readonly(&mem->alias[1], true);
 
     /* XXX: should distinguish read/write cases */
-    memory_region_init_alias(&mem->alias[0], "pam-pci", pci_address_space,
+    memory_region_init_alias(&mem->alias[0], OBJECT(dev), "pam-pci", pci_address_space,
                              start, size);
-    memory_region_init_alias(&mem->alias[2], "pam-pci", pci_address_space,
+    memory_region_init_alias(&mem->alias[2], OBJECT(dev), "pam-pci", pci_address_space,
                              start, size);
 
     for (i = 0; i < 4; ++i) {
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index f9e68c3..870e388 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -201,12 +201,12 @@
 {
     PCIHostState *s = PCI_HOST_BRIDGE(dev);
 
-    memory_region_init_io(&s->conf_mem, &pci_host_conf_le_ops, s,
+    memory_region_init_io(&s->conf_mem, OBJECT(dev), &pci_host_conf_le_ops, s,
                           "pci-conf-idx", 4);
     sysbus_add_io(dev, 0xcf8, &s->conf_mem);
     sysbus_init_ioports(&s->busdev, 0xcf8, 4);
 
-    memory_region_init_io(&s->data_mem, &pci_host_data_le_ops, s,
+    memory_region_init_io(&s->data_mem, OBJECT(dev), &pci_host_data_le_ops, s,
                           "pci-conf-data", 4);
     sysbus_add_io(dev, 0xcfc, &s->data_mem);
     sysbus_init_ioports(&s->busdev, 0xcfc, 4);
@@ -260,25 +260,25 @@
     f->system_memory = address_space_mem;
     f->pci_address_space = pci_address_space;
     f->ram_memory = ram_memory;
-    memory_region_init_alias(&f->pci_hole, "pci-hole", f->pci_address_space,
+    memory_region_init_alias(&f->pci_hole, OBJECT(d), "pci-hole", f->pci_address_space,
                              pci_hole_start, pci_hole_size);
     memory_region_add_subregion(f->system_memory, pci_hole_start, &f->pci_hole);
-    memory_region_init_alias(&f->pci_hole_64bit, "pci-hole64",
+    memory_region_init_alias(&f->pci_hole_64bit, OBJECT(d), "pci-hole64",
                              f->pci_address_space,
                              pci_hole64_start, pci_hole64_size);
     if (pci_hole64_size) {
         memory_region_add_subregion(f->system_memory, pci_hole64_start,
                                     &f->pci_hole_64bit);
     }
-    memory_region_init_alias(&f->smram_region, "smram-region",
+    memory_region_init_alias(&f->smram_region, OBJECT(d), "smram-region",
                              f->pci_address_space, 0xa0000, 0x20000);
     memory_region_add_subregion_overlap(f->system_memory, 0xa0000,
                                         &f->smram_region, 1);
     memory_region_set_enabled(&f->smram_region, false);
-    init_pam(f->ram_memory, f->system_memory, f->pci_address_space,
+    init_pam(dev, f->ram_memory, f->system_memory, f->pci_address_space,
              &f->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE);
     for (i = 0; i < 12; ++i) {
-        init_pam(f->ram_memory, f->system_memory, f->pci_address_space,
+        init_pam(dev, f->ram_memory, f->system_memory, f->pci_address_space,
                  &f->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE,
                  PAM_EXPAN_SIZE);
     }
@@ -549,7 +549,8 @@
 
     isa_bus_new(DEVICE(d), pci_address_space_io(dev));
 
-    memory_region_init_io(&d->rcr_mem, &rcr_ops, d, "piix3-reset-control", 1);
+    memory_region_init_io(&d->rcr_mem, OBJECT(dev), &rcr_ops, d,
+                          "piix3-reset-control", 1);
     memory_region_add_subregion_overlap(pci_address_space_io(dev), RCR_IOPORT,
                                         &d->rcr_mem, 1);
 
@@ -629,11 +630,20 @@
     .class_init    = i440fx_class_init,
 };
 
+static const char *i440fx_pcihost_root_bus_path(PCIHostState *host_bridge,
+                                                PCIBus *rootbus)
+{
+    /* For backwards compat with old device paths */
+    return "0000";
+}
+
 static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+    PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
 
+    hc->root_bus_path = i440fx_pcihost_root_bus_path;
     k->init = i440fx_pcihost_initfn;
     dc->fw_name = "pci";
     dc->no_user = 1;
diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c
index 5e7ad94..646204e 100644
--- a/hw/pci-host/ppce500.c
+++ b/hw/pci-host/ppce500.c
@@ -330,7 +330,7 @@
         (d->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) |
         PCI_HEADER_TYPE_BRIDGE;
 
-    memory_region_init_alias(&b->bar0, "e500-pci-bar0", &ccsr->ccsr_space,
+    memory_region_init_alias(&b->bar0, OBJECT(ccsr), "e500-pci-bar0", &ccsr->ccsr_space,
                              0, int128_get64(ccsr->ccsr_space.size));
     pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &b->bar0);
 
@@ -352,7 +352,7 @@
         sysbus_init_irq(dev, &s->irq[i]);
     }
 
-    memory_region_init(&s->pio, "pci-pio", PCIE500_PCI_IOLEN);
+    memory_region_init(&s->pio, OBJECT(s), "pci-pio", PCIE500_PCI_IOLEN);
 
     b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq,
                          mpc85xx_pci_map_irq, s->irq, address_space_mem,
@@ -361,12 +361,12 @@
 
     pci_create_simple(b, 0, "e500-host-bridge");
 
-    memory_region_init(&s->container, "pci-container", PCIE500_ALL_SIZE);
-    memory_region_init_io(&h->conf_mem, &pci_host_conf_be_ops, h,
+    memory_region_init(&s->container, OBJECT(h), "pci-container", PCIE500_ALL_SIZE);
+    memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_be_ops, h,
                           "pci-conf-idx", 4);
-    memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, h,
+    memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops, h,
                           "pci-conf-data", 4);
-    memory_region_init_io(&s->iomem, &e500_pci_reg_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &e500_pci_reg_ops, s,
                           "pci.reg", PCIE500_REG_SIZE);
     memory_region_add_subregion(&s->container, PCIE500_CFGADDR, &h->conf_mem);
     memory_region_add_subregion(&s->container, PCIE500_CFGDATA, &h->data_mem);
diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
index 6130253..b41d564 100644
--- a/hw/pci-host/prep.c
+++ b/hw/pci-host/prep.c
@@ -125,20 +125,20 @@
 
     pci_bus_irqs(&s->pci_bus, prep_set_irq, prep_map_irq, s->irq, 4);
 
-    memory_region_init_io(&h->conf_mem, &pci_host_conf_be_ops, s,
+    memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_be_ops, s,
                           "pci-conf-idx", 1);
     sysbus_add_io(dev, 0xcf8, &h->conf_mem);
     sysbus_init_ioports(&h->busdev, 0xcf8, 1);
 
-    memory_region_init_io(&h->data_mem, &pci_host_data_be_ops, s,
+    memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_be_ops, s,
                           "pci-conf-data", 1);
     sysbus_add_io(dev, 0xcfc, &h->data_mem);
     sysbus_init_ioports(&h->busdev, 0xcfc, 1);
 
-    memory_region_init_io(&h->mmcfg, &PPC_PCIIO_ops, s, "pciio", 0x00400000);
+    memory_region_init_io(&h->mmcfg, OBJECT(s), &PPC_PCIIO_ops, s, "pciio", 0x00400000);
     memory_region_add_subregion(address_space_mem, 0x80800000, &h->mmcfg);
 
-    memory_region_init_io(&s->intack, &PPC_intack_ops, s, "pci-intack", 1);
+    memory_region_init_io(&s->intack, OBJECT(s), &PPC_intack_ops, s, "pci-intack", 1);
     memory_region_add_subregion(address_space_mem, 0xbffffff0, &s->intack);
 
     /* TODO Remove once realize propagates to child devices. */
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 24df6b5..8c3ee53 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -40,12 +40,12 @@
     PCIHostState *pci = FROM_SYSBUS(PCIHostState, dev);
     Q35PCIHost *s = Q35_HOST_DEVICE(&dev->qdev);
 
-    memory_region_init_io(&pci->conf_mem, &pci_host_conf_le_ops, pci,
+    memory_region_init_io(&pci->conf_mem, OBJECT(pci), &pci_host_conf_le_ops, pci,
                           "pci-conf-idx", 4);
     sysbus_add_io(dev, MCH_HOST_BRIDGE_CONFIG_ADDR, &pci->conf_mem);
     sysbus_init_ioports(&pci->busdev, MCH_HOST_BRIDGE_CONFIG_ADDR, 4);
 
-    memory_region_init_io(&pci->data_mem, &pci_host_data_le_ops, pci,
+    memory_region_init_io(&pci->data_mem, OBJECT(pci), &pci_host_data_le_ops, pci,
                           "pci-conf-data", 4);
     sysbus_add_io(dev, MCH_HOST_BRIDGE_CONFIG_DATA, &pci->data_mem);
     sysbus_init_ioports(&pci->busdev, MCH_HOST_BRIDGE_CONFIG_DATA, 4);
@@ -63,6 +63,13 @@
     return 0;
 }
 
+static const char *q35_host_root_bus_path(PCIHostState *host_bridge,
+                                          PCIBus *rootbus)
+{
+    /* For backwards compat with old device paths */
+    return "0000";
+}
+
 static Property mch_props[] = {
     DEFINE_PROP_UINT64("MCFG", Q35PCIHost, host.base_addr,
                         MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT),
@@ -73,7 +80,9 @@
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+    PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
 
+    hc->root_bus_path = q35_host_root_bus_path;
     k->init = q35_host_init;
     dc->props = mch_props;
     dc->fw_name = "pci";
@@ -244,8 +253,16 @@
     hwaddr pci_hole64_size;
     MCHPCIState *mch = MCH_PCI_DEVICE(d);
 
+    /* Leave enough space for the biggest MCFG BAR */
+    /* TODO: this matches current bios behaviour, but
+     * it's not a power of two, which means an MTRR
+     * can't cover it exactly.
+     */
+    mch->guest_info->pci_info.w32.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT +
+        MCH_HOST_BRIDGE_PCIEXBAR_MAX;
+
     /* setup pci memory regions */
-    memory_region_init_alias(&mch->pci_hole, "pci-hole",
+    memory_region_init_alias(&mch->pci_hole, OBJECT(mch), "pci-hole",
                              mch->pci_address_space,
                              mch->below_4g_mem_size,
                              0x100000000ULL - mch->below_4g_mem_size);
@@ -253,7 +270,7 @@
                                 &mch->pci_hole);
     pci_hole64_size = (sizeof(hwaddr) == 4 ? 0 :
                        ((uint64_t)1 << 62));
-    memory_region_init_alias(&mch->pci_hole_64bit, "pci-hole64",
+    memory_region_init_alias(&mch->pci_hole_64bit, OBJECT(mch), "pci-hole64",
                              mch->pci_address_space,
                              0x100000000ULL + mch->above_4g_mem_size,
                              pci_hole64_size);
@@ -264,15 +281,15 @@
     }
     /* smram */
     cpu_smm_register(&mch_set_smm, mch);
-    memory_region_init_alias(&mch->smram_region, "smram-region",
+    memory_region_init_alias(&mch->smram_region, OBJECT(mch), "smram-region",
                              mch->pci_address_space, 0xa0000, 0x20000);
     memory_region_add_subregion_overlap(mch->system_memory, 0xa0000,
                                         &mch->smram_region, 1);
     memory_region_set_enabled(&mch->smram_region, false);
-    init_pam(mch->ram_memory, mch->system_memory, mch->pci_address_space,
+    init_pam(DEVICE(mch), mch->ram_memory, mch->system_memory, mch->pci_address_space,
              &mch->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE);
     for (i = 0; i < 12; ++i) {
-        init_pam(mch->ram_memory, mch->system_memory, mch->pci_address_space,
+        init_pam(DEVICE(mch), mch->ram_memory, mch->system_memory, mch->pci_address_space,
                  &mch->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE,
                  PAM_EXPAN_SIZE);
     }
diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c
index fff235d..91530cd 100644
--- a/hw/pci-host/uninorth.c
+++ b/hw/pci-host/uninorth.c
@@ -152,9 +152,9 @@
     /* Uninorth main bus */
     h = PCI_HOST_BRIDGE(dev);
 
-    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
+    memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
                           dev, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&h->data_mem, &unin_data_ops, dev,
+    memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, dev,
                           "pci-conf-data", 0x1000);
     sysbus_init_mmio(dev, &h->conf_mem);
     sysbus_init_mmio(dev, &h->data_mem);
@@ -170,9 +170,9 @@
     /* Uninorth U3 AGP bus */
     h = PCI_HOST_BRIDGE(dev);
 
-    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
+    memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
                           dev, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&h->data_mem, &unin_data_ops, dev,
+    memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, dev,
                           "pci-conf-data", 0x1000);
     sysbus_init_mmio(dev, &h->conf_mem);
     sysbus_init_mmio(dev, &h->data_mem);
@@ -187,9 +187,9 @@
     /* Uninorth AGP bus */
     h = PCI_HOST_BRIDGE(dev);
 
-    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
+    memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
                           dev, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&h->data_mem, &pci_host_data_le_ops,
+    memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops,
                           dev, "pci-conf-data", 0x1000);
     sysbus_init_mmio(dev, &h->conf_mem);
     sysbus_init_mmio(dev, &h->data_mem);
@@ -203,9 +203,9 @@
     /* Uninorth internal bus */
     h = PCI_HOST_BRIDGE(dev);
 
-    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
+    memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
                           dev, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&h->data_mem, &pci_host_data_le_ops,
+    memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops,
                           dev, "pci-conf-data", 0x1000);
     sysbus_init_mmio(dev, &h->conf_mem);
     sysbus_init_mmio(dev, &h->data_mem);
@@ -228,8 +228,8 @@
     s = SYS_BUS_DEVICE(dev);
     h = PCI_HOST_BRIDGE(s);
     d = UNI_NORTH_PCI_HOST_BRIDGE(dev);
-    memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
-    memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
+    memory_region_init(&d->pci_mmio, OBJECT(d), "pci-mmio", 0x100000000ULL);
+    memory_region_init_alias(&d->pci_hole, OBJECT(d), "pci-hole", &d->pci_mmio,
                              0x80000000ULL, 0x70000000ULL);
     memory_region_add_subregion(address_space_mem, 0x80000000ULL,
                                 &d->pci_hole);
@@ -294,8 +294,8 @@
     h = PCI_HOST_BRIDGE(dev);
     d = U3_AGP_HOST_BRIDGE(dev);
 
-    memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
-    memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
+    memory_region_init(&d->pci_mmio, OBJECT(d), "pci-mmio", 0x100000000ULL);
+    memory_region_init_alias(&d->pci_hole, OBJECT(d), "pci-hole", &d->pci_mmio,
                              0x80000000ULL, 0x70000000ULL);
     memory_region_add_subregion(address_space_mem, 0x80000000ULL,
                                 &d->pci_hole);
diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c
index 2f996d9..9238d39 100644
--- a/hw/pci-host/versatile.c
+++ b/hw/pci-host/versatile.c
@@ -381,8 +381,8 @@
     PCIHostState *h = PCI_HOST_BRIDGE(obj);
     PCIVPBState *s = PCI_VPB(obj);
 
-    memory_region_init(&s->pci_io_space, "pci_io", 1ULL << 32);
-    memory_region_init(&s->pci_mem_space, "pci_mem", 1ULL << 32);
+    memory_region_init(&s->pci_io_space, OBJECT(s), "pci_io", 1ULL << 32);
+    memory_region_init(&s->pci_mem_space, OBJECT(s), "pci_mem", 1ULL << 32);
 
     pci_bus_new_inplace(&s->pci_bus, DEVICE(obj), "pci",
                         &s->pci_mem_space, &s->pci_io_space,
@@ -424,20 +424,20 @@
      * 3 : PCI IO window
      * 4..6 : PCI memory windows
      */
-    memory_region_init_io(&s->controlregs, &pci_vpb_reg_ops, s, "pci-vpb-regs",
-                          0x1000);
+    memory_region_init_io(&s->controlregs, OBJECT(s), &pci_vpb_reg_ops, s,
+                          "pci-vpb-regs", 0x1000);
     sysbus_init_mmio(sbd, &s->controlregs);
-    memory_region_init_io(&s->mem_config, &pci_vpb_config_ops, s,
+    memory_region_init_io(&s->mem_config, OBJECT(s), &pci_vpb_config_ops, s,
                           "pci-vpb-selfconfig", 0x1000000);
     sysbus_init_mmio(sbd, &s->mem_config);
-    memory_region_init_io(&s->mem_config2, &pci_vpb_config_ops, s,
+    memory_region_init_io(&s->mem_config2, OBJECT(s), &pci_vpb_config_ops, s,
                           "pci-vpb-config", 0x1000000);
     sysbus_init_mmio(sbd, &s->mem_config2);
 
     /* The window into I/O space is always into a fixed base address;
      * its size is the same for both realview and versatile.
      */
-    memory_region_init_alias(&s->pci_io_window, "pci-vbp-io-window",
+    memory_region_init_alias(&s->pci_io_window, OBJECT(s), "pci-vbp-io-window",
                              &s->pci_io_space, 0, 0x100000);
 
     sysbus_init_mmio(sbd, &s->pci_io_space);
@@ -447,7 +447,7 @@
      * offsets are guest controllable via the IMAP registers.
      */
     for (i = 0; i < 3; i++) {
-        memory_region_init_alias(&s->pci_mem_window[i], "pci-vbp-window",
+        memory_region_init_alias(&s->pci_mem_window[i], OBJECT(s), "pci-vbp-window",
                                  &s->pci_mem_space, 0, s->mem_win_size[i]);
         sysbus_init_mmio(sbd, &s->pci_mem_window[i]);
     }
diff --git a/hw/pci/Makefile.objs b/hw/pci/Makefile.objs
index a7fb9d0..720f438 100644
--- a/hw/pci/Makefile.objs
+++ b/hw/pci/Makefile.objs
@@ -8,4 +8,4 @@
 common-obj-$(CONFIG_NO_PCI) += pci-stub.o
 common-obj-$(CONFIG_ALL) += pci-stub.o
 
-obj-$(CONFIG_PCI_HOTPLUG) += pci-hotplug.o
+common-obj-$(CONFIG_PCI_HOTPLUG_OLD) += pci-hotplug-old.o
diff --git a/hw/pci/msix.c b/hw/pci/msix.c
index 6da75ec..3430770 100644
--- a/hw/pci/msix.c
+++ b/hw/pci/msix.c
@@ -280,10 +280,10 @@
 
     msix_mask_all(dev, nentries);
 
-    memory_region_init_io(&dev->msix_table_mmio, &msix_table_mmio_ops, dev,
+    memory_region_init_io(&dev->msix_table_mmio, OBJECT(dev), &msix_table_mmio_ops, dev,
                           "msix-table", table_size);
     memory_region_add_subregion(table_bar, table_offset, &dev->msix_table_mmio);
-    memory_region_init_io(&dev->msix_pba_mmio, &msix_pba_mmio_ops, dev,
+    memory_region_init_io(&dev->msix_pba_mmio, OBJECT(dev), &msix_pba_mmio_ops, dev,
                           "msix-pba", pba_size);
     memory_region_add_subregion(pba_bar, pba_offset, &dev->msix_pba_mmio);
 
@@ -311,7 +311,7 @@
     }
 
     name = g_strdup_printf("%s-msix", dev->name);
-    memory_region_init(&dev->msix_exclusive_bar, name, MSIX_EXCLUSIVE_BAR_SIZE);
+    memory_region_init(&dev->msix_exclusive_bar, OBJECT(dev), name, MSIX_EXCLUSIVE_BAR_SIZE);
     g_free(name);
 
     ret = msix_init(dev, nentries, &dev->msix_exclusive_bar, bar_nr,
diff --git a/hw/pci/pci-hotplug.c b/hw/pci/pci-hotplug-old.c
similarity index 78%
rename from hw/pci/pci-hotplug.c
rename to hw/pci/pci-hotplug-old.c
index 12287d1..8077289 100644
--- a/hw/pci/pci-hotplug.c
+++ b/hw/pci/pci-hotplug-old.c
@@ -1,5 +1,7 @@
 /*
- * QEMU PCI hotplug support
+ * Deprecated PCI hotplug interface support
+ * This covers the old pci_add / pci_del command, whereas the more general
+ * device_add / device_del commands are now preferred.
  *
  * Copyright (c) 2004 Fabrice Bellard
  *
@@ -34,17 +36,43 @@
 #include "sysemu/blockdev.h"
 #include "qapi/error.h"
 
-#if defined(TARGET_I386)
+static int pci_read_devaddr(Monitor *mon, const char *addr,
+                            int *busp, unsigned *slotp)
+{
+    int dom;
+
+    /* strip legacy tag */
+    if (!strncmp(addr, "pci_addr=", 9)) {
+        addr += 9;
+    }
+    if (pci_parse_devaddr(addr, &dom, busp, slotp, NULL)) {
+        monitor_printf(mon, "Invalid pci address\n");
+        return -1;
+    }
+    if (dom != 0) {
+        monitor_printf(mon, "Multiple PCI domains not supported, use device_add\n");
+        return -1;
+    }
+    return 0;
+}
+
 static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
                                        const char *devaddr,
                                        const char *opts_str)
 {
     Error *local_err = NULL;
     QemuOpts *opts;
+    PCIBus *root = pci_find_primary_bus();
     PCIBus *bus;
     int ret, devfn;
 
-    bus = pci_get_bus_devfn(&devfn, devaddr);
+    if (!root) {
+        monitor_printf(mon, "no primary PCI bus (if there are multiple"
+                       " PCI roots, you must use device_add instead)");
+        return NULL;
+    }
+
+    bus = pci_get_bus_devfn(&devfn, root, devaddr);
     if (!bus) {
         monitor_printf(mon, "Invalid PCI device address %s\n", devaddr);
         return NULL;
@@ -71,7 +99,7 @@
         monitor_printf(mon, "Parameter addr not supported\n");
         return NULL;
     }
-    return pci_nic_init(&nd_table[ret], "rtl8139", devaddr);
+    return pci_nic_init(&nd_table[ret], root, "rtl8139", devaddr);
 }
 
 static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
@@ -113,18 +141,23 @@
 
 int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo)
 {
-    int dom, pci_bus;
+    int pci_bus;
     unsigned slot;
+    PCIBus *root = pci_find_primary_bus();
     PCIDevice *dev;
     const char *pci_addr = qdict_get_str(qdict, "pci_addr");
 
     switch (dinfo->type) {
     case IF_SCSI:
-        if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
+        if (!root) {
+            monitor_printf(mon, "no primary PCI bus (if there are multiple"
+                           " PCI roots, you must use device_add instead)");
             goto err;
         }
-        dev = pci_find_device(pci_find_root_bus(dom), pci_bus,
-                              PCI_DEVFN(slot, 0));
+        if (pci_read_devaddr(mon, pci_addr, &pci_bus, &slot)) {
+            goto err;
+        }
+        dev = pci_find_device(root, pci_bus, PCI_DEVFN(slot, 0));
         if (!dev) {
             monitor_printf(mon, "no pci device with address %s\n", pci_addr);
             goto err;
@@ -151,6 +184,7 @@
     DriveInfo *dinfo = NULL;
     int type = -1;
     char buf[128];
+    PCIBus *root = pci_find_primary_bus();
     PCIBus *bus;
     int devfn;
 
@@ -180,7 +214,12 @@
         dinfo = NULL;
     }
 
-    bus = pci_get_bus_devfn(&devfn, devaddr);
+    if (!root) {
+        monitor_printf(mon, "no primary PCI bus (if there are multiple"
+                       " PCI roots, you must use device_add instead)");
+        return NULL;
+    }
+    bus = pci_get_bus_devfn(&devfn, root, devaddr);
     if (!bus) {
         monitor_printf(mon, "Invalid PCI device address %s\n", devaddr);
         return NULL;
@@ -250,27 +289,33 @@
     }
 
     if (dev) {
-        monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n",
-                       pci_find_domain(dev->bus),
+        monitor_printf(mon, "OK root bus %s, bus %d, slot %d, function %d\n",
+                       pci_root_bus_path(dev),
                        pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
                        PCI_FUNC(dev->devfn));
     } else
         monitor_printf(mon, "failed to add %s\n", opts);
 }
-#endif
 
 static int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
 {
+    PCIBus *root = pci_find_primary_bus();
     PCIDevice *d;
-    int dom, bus;
+    int bus;
     unsigned slot;
     Error *local_err = NULL;
 
-    if (pci_read_devaddr(mon, pci_addr, &dom, &bus, &slot)) {
+    if (!root) {
+        monitor_printf(mon, "no primary PCI bus (if there are multiple"
+                       " PCI roots, you must use device_del instead)");
         return -1;
     }
 
-    d = pci_find_device(pci_find_root_bus(dom), bus, PCI_DEVFN(slot, 0));
+    if (pci_read_devaddr(mon, pci_addr, &bus, &slot)) {
+        return -1;
+    }
+
+    d = pci_find_device(root, bus, PCI_DEVFN(slot, 0));
     if (!d) {
         monitor_printf(mon, "slot %d empty\n", slot);
         return -1;
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 61b681a..dcc85ef 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -25,6 +25,7 @@
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_bridge.h"
 #include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_host.h"
 #include "monitor/monitor.h"
 #include "net/net.h"
 #include "sysemu/sysemu.h"
@@ -89,12 +90,7 @@
 static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
 static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
 
-struct PCIHostBus {
-    int domain;
-    struct PCIBus *bus;
-    QLIST_ENTRY(PCIHostBus) next;
-};
-static QLIST_HEAD(, PCIHostBus) host_buses;
+static QLIST_HEAD(, PCIHostState) pci_host_bridges;
 
 static const VMStateDescription vmstate_pcibus = {
     .name = "PCIBUS",
@@ -237,46 +233,54 @@
     return 1;
 }
 
-static void pci_host_bus_register(int domain, PCIBus *bus)
+static void pci_host_bus_register(PCIBus *bus, DeviceState *parent)
 {
-    struct PCIHostBus *host;
-    host = g_malloc0(sizeof(*host));
-    host->domain = domain;
-    host->bus = bus;
-    QLIST_INSERT_HEAD(&host_buses, host, next);
+    PCIHostState *host_bridge = PCI_HOST_BRIDGE(parent);
+
+    QLIST_INSERT_HEAD(&pci_host_bridges, host_bridge, next);
 }
 
-PCIBus *pci_find_root_bus(int domain)
+PCIBus *pci_find_primary_bus(void)
 {
-    struct PCIHostBus *host;
+    PCIBus *primary_bus = NULL;
+    PCIHostState *host;
 
-    QLIST_FOREACH(host, &host_buses, next) {
-        if (host->domain == domain) {
-            return host->bus;
+    QLIST_FOREACH(host, &pci_host_bridges, next) {
+        if (primary_bus) {
+            /* We have multiple root buses, refuse to select a primary */
+            return NULL;
         }
+        primary_bus = host->bus;
     }
 
-    return NULL;
+    return primary_bus;
 }
 
-int pci_find_domain(const PCIBus *bus)
+PCIBus *pci_device_root_bus(const PCIDevice *d)
 {
-    PCIDevice *d;
-    struct PCIHostBus *host;
+    PCIBus *bus = d->bus;
 
-    /* obtain root bus */
     while ((d = bus->parent_dev) != NULL) {
         bus = d->bus;
     }
 
-    QLIST_FOREACH(host, &host_buses, next) {
-        if (host->bus == bus) {
-            return host->domain;
-        }
+    return bus;
+}
+
+const char *pci_root_bus_path(PCIDevice *dev)
+{
+    PCIBus *rootbus = pci_device_root_bus(dev);
+    PCIHostState *host_bridge = PCI_HOST_BRIDGE(rootbus->qbus.parent);
+    PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_GET_CLASS(host_bridge);
+
+    assert(!rootbus->parent_dev);
+    assert(host_bridge->bus == rootbus);
+
+    if (hc->root_bus_path) {
+        return (*hc->root_bus_path)(host_bridge, rootbus);
     }
 
-    abort();    /* should not be reached */
-    return -1;
+    return rootbus->qbus.name;
 }
 
 static void pci_bus_init(PCIBus *bus, DeviceState *parent,
@@ -292,7 +296,8 @@
 
     /* host bridge */
     QLIST_INIT(&bus->child);
-    pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */
+
+    pci_host_bus_register(bus, parent);
 
     vmstate_register(NULL, -1, &vmstate_pcibus, bus);
 }
@@ -522,7 +527,7 @@
  * Parse [[<domain>:]<bus>:]<slot>, return -1 on error if funcp == NULL
  *       [[<domain>:]<bus>:]<slot>.<func>, return -1 on error
  */
-static int pci_parse_devaddr(const char *addr, int *domp, int *busp,
+int pci_parse_devaddr(const char *addr, int *domp, int *busp,
                       unsigned int *slotp, unsigned int *funcp)
 {
     const char *p;
@@ -581,36 +586,34 @@
     return 0;
 }
 
-int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
-                     unsigned *slotp)
-{
-    /* strip legacy tag */
-    if (!strncmp(addr, "pci_addr=", 9)) {
-        addr += 9;
-    }
-    if (pci_parse_devaddr(addr, domp, busp, slotp, NULL)) {
-        monitor_printf(mon, "Invalid pci address\n");
-        return -1;
-    }
-    return 0;
-}
-
-PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
+PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root, const char *devaddr)
 {
     int dom, bus;
     unsigned slot;
 
+    assert(!root->parent_dev);
+
+    if (!root) {
+        fprintf(stderr, "No primary PCI bus\n");
+        return NULL;
+    }
+
     if (!devaddr) {
         *devfnp = -1;
-        return pci_find_bus_nr(pci_find_root_bus(0), 0);
+        return pci_find_bus_nr(root, 0);
     }
 
     if (pci_parse_devaddr(devaddr, &dom, &bus, &slot, NULL) < 0) {
         return NULL;
     }
 
+    if (dom != 0) {
+        fprintf(stderr, "No support for non-zero PCI domains\n");
+        return NULL;
+    }
+
     *devfnp = PCI_DEVFN(slot, 0);
-    return pci_find_bus_nr(pci_find_root_bus(dom), bus);
+    return pci_find_bus_nr(root, bus);
 }
 
 static void pci_init_cmask(PCIDevice *dev)
@@ -811,7 +814,8 @@
         dma_as = &address_space_memory;
     }
 
-    memory_region_init_alias(&pci_dev->bus_master_enable_region, "bus master",
+    memory_region_init_alias(&pci_dev->bus_master_enable_region,
+                             OBJECT(pci_dev), "bus master",
                              dma_as->root, 0, memory_region_size(dma_as->root));
     memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
     address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region,
@@ -1525,11 +1529,11 @@
 PciInfoList *qmp_query_pci(Error **errp)
 {
     PciInfoList *info, *head = NULL, *cur_item = NULL;
-    struct PCIHostBus *host;
+    PCIHostState *host_bridge;
 
-    QLIST_FOREACH(host, &host_buses, next) {
+    QLIST_FOREACH(host_bridge, &pci_host_bridges, next) {
         info = g_malloc0(sizeof(*info));
-        info->value = qmp_query_pci_bus(host->bus, 0);
+        info->value = qmp_query_pci_bus(host_bridge->bus, 0);
 
         /* XXX: waiting for the qapi to support GSList */
         if (!cur_item) {
@@ -1569,7 +1573,8 @@
 
 /* Initialize a PCI NIC.  */
 /* FIXME callers should check for failure, but don't */
-PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
+PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus,
+                        const char *default_model,
                         const char *default_devaddr)
 {
     const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr;
@@ -1583,7 +1588,7 @@
     if (i < 0)
         return NULL;
 
-    bus = pci_get_bus_devfn(&devfn, devaddr);
+    bus = pci_get_bus_devfn(&devfn, rootbus, devaddr);
     if (!bus) {
         error_report("Invalid PCI device address %s for device %s",
                      devaddr, pci_nic_names[i]);
@@ -1598,7 +1603,8 @@
     return pci_dev;
 }
 
-PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model,
+PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
+                               const char *default_model,
                                const char *default_devaddr)
 {
     PCIDevice *res;
@@ -1606,7 +1612,7 @@
     if (qemu_show_nic_models(nd->model, pci_nic_models))
         exit(0);
 
-    res = pci_nic_init(nd, default_model, default_devaddr);
+    res = pci_nic_init(nd, rootbus, default_model, default_devaddr);
     if (!res)
         exit(1);
     return res;
@@ -1945,7 +1951,7 @@
         snprintf(name, sizeof(name), "%s.rom", object_get_typename(OBJECT(pdev)));
     }
     pdev->has_rom = true;
-    memory_region_init_ram(&pdev->rom, name, size);
+    memory_region_init_ram(&pdev->rom, OBJECT(pdev), name, size);
     vmstate_register_ram(&pdev->rom, &pdev->qdev);
     ptr = memory_region_get_ram_ptr(&pdev->rom);
     load_image(path, ptr);
@@ -1997,10 +2003,10 @@
         for (i = offset; i < offset + size; i++) {
             overlapping_cap = pci_find_capability_at_offset(pdev, i);
             if (overlapping_cap) {
-                fprintf(stderr, "ERROR: %04x:%02x:%02x.%x "
+                fprintf(stderr, "ERROR: %s:%02x:%02x.%x "
                         "Attempt to add PCI capability %x at offset "
                         "%x overlaps existing capability %x at offset %x\n",
-                        pci_find_domain(pdev->bus), pci_bus_num(pdev->bus),
+                        pci_root_bus_path(pdev), pci_bus_num(pdev->bus),
                         PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
                         cap_id, offset, overlapping_cap, i);
                 return -EINVAL;
@@ -2134,30 +2140,30 @@
      * domain:Bus:Slot.Func for systems without nested PCI bridges.
      * Slot.Function list specifies the slot and function numbers for all
      * devices on the path from root to the specific device. */
-    char domain[] = "DDDD:00";
+    const char *root_bus_path;
+    int root_bus_len;
     char slot[] = ":SS.F";
-    int domain_len = sizeof domain - 1 /* For '\0' */;
     int slot_len = sizeof slot - 1 /* For '\0' */;
     int path_len;
     char *path, *p;
     int s;
 
+    root_bus_path = pci_root_bus_path(d);
+    root_bus_len = strlen(root_bus_path);
+
     /* Calculate # of slots on path between device and root. */;
     slot_depth = 0;
     for (t = d; t; t = t->bus->parent_dev) {
         ++slot_depth;
     }
 
-    path_len = domain_len + slot_len * slot_depth;
+    path_len = root_bus_len + slot_len * slot_depth;
 
     /* Allocate memory, fill in the terminating null byte. */
     path = g_malloc(path_len + 1 /* For '\0' */);
     path[path_len] = '\0';
 
-    /* First field is the domain. */
-    s = snprintf(domain, sizeof domain, "%04x:00", pci_find_domain(d->bus));
-    assert(s == domain_len);
-    memcpy(path, domain, domain_len);
+    memcpy(path, root_bus_path, root_bus_len);
 
     /* Fill in slot numbers. We walk up from device to root, so need to print
      * them in the reverse order, last to first. */
@@ -2191,11 +2197,11 @@
 
 int pci_qdev_find_device(const char *id, PCIDevice **pdev)
 {
-    struct PCIHostBus *host;
+    PCIHostState *host_bridge;
     int rc = -ENODEV;
 
-    QLIST_FOREACH(host, &host_buses, next) {
-        int tmp = pci_qdev_find_recursive(host->bus, id, pdev);
+    QLIST_FOREACH(host_bridge, &pci_host_bridges, next) {
+        int tmp = pci_qdev_find_recursive(host_bridge->bus, id, pdev);
         if (!tmp) {
             rc = 0;
             break;
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 24be6c5..ecdeab0 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -147,7 +147,7 @@
      * Apparently no way to do this with existing memory APIs. */
     pcibus_t size = enabled && limit >= base ? limit + 1 - base : 0;
 
-    memory_region_init_alias(alias, name, space, base, size);
+    memory_region_init_alias(alias, OBJECT(bridge), name, space, base, size);
     memory_region_add_subregion_overlap(parent_space, base, alias, 1);
 }
 
@@ -156,13 +156,13 @@
 {
     uint16_t brctl = pci_get_word(br->dev.config + PCI_BRIDGE_CONTROL);
 
-    memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_LO],
+    memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_LO], OBJECT(br),
                              "pci_bridge_vga_io_lo", &br->address_space_io,
                              QEMU_PCI_VGA_IO_LO_BASE, QEMU_PCI_VGA_IO_LO_SIZE);
-    memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_HI],
+    memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_HI], OBJECT(br),
                              "pci_bridge_vga_io_hi", &br->address_space_io,
                              QEMU_PCI_VGA_IO_HI_BASE, QEMU_PCI_VGA_IO_HI_SIZE);
-    memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_MEM],
+    memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_MEM], OBJECT(br),
                              "pci_bridge_vga_mem", &br->address_space_mem,
                              QEMU_PCI_VGA_MEM_BASE, QEMU_PCI_VGA_MEM_SIZE);
 
@@ -367,9 +367,9 @@
     sec_bus->parent_dev = dev;
     sec_bus->map_irq = br->map_irq ? br->map_irq : pci_swizzle_map_irq_fn;
     sec_bus->address_space_mem = &br->address_space_mem;
-    memory_region_init(&br->address_space_mem, "pci_bridge_pci", INT64_MAX);
+    memory_region_init(&br->address_space_mem, OBJECT(br), "pci_bridge_pci", INT64_MAX);
     sec_bus->address_space_io = &br->address_space_io;
-    memory_region_init(&br->address_space_io, "pci_bridge_io", 65536);
+    memory_region_init(&br->address_space_io, OBJECT(br), "pci_bridge_io", 65536);
     br->windows = pci_bridge_region_init(br);
     QLIST_INIT(&sec_bus->child);
     QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling);
diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c
index 12254b1..7dd9b25 100644
--- a/hw/pci/pci_host.c
+++ b/hw/pci/pci_host.c
@@ -169,6 +169,7 @@
     .name = TYPE_PCI_HOST_BRIDGE,
     .parent = TYPE_SYS_BUS_DEVICE,
     .abstract = true,
+    .class_size = sizeof(PCIHostBridgeClass),
     .instance_size = sizeof(PCIHostState),
 };
 
diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c
index 1ce72ce..ca762ab 100644
--- a/hw/pci/pcie_aer.c
+++ b/hw/pci/pcie_aer.c
@@ -817,9 +817,9 @@
     qdict = qobject_to_qdict(data);
 
     devfn = (int)qdict_get_int(qdict, "devfn");
-    monitor_printf(mon, "OK id: %s domain: %x, bus: %x devfn: %x.%x\n",
+    monitor_printf(mon, "OK id: %s root bus: %s, bus: %x devfn: %x.%x\n",
                    qdict_get_str(qdict, "id"),
-                   (int) qdict_get_int(qdict, "domain"),
+                   qdict_get_str(qdict, "root_bus"),
                    (int) qdict_get_int(qdict, "bus"),
                    PCI_SLOT(devfn), PCI_FUNC(devfn));
 }
@@ -1020,10 +1020,9 @@
 
     ret = pcie_aer_inject_error(dev, &err);
     *ret_data = qobject_from_jsonf("{'id': %s, "
-                                   "'domain': %d, 'bus': %d, 'devfn': %d, "
+                                   "'root_bus': %s, 'bus': %d, 'devfn': %d, "
                                    "'ret': %d}",
-                                   id,
-                                   pci_find_domain(dev->bus),
+                                   id, pci_root_bus_path(dev),
                                    pci_bus_num(dev->bus), dev->devfn,
                                    ret);
     assert(*ret_data);
diff --git a/hw/pci/pcie_host.c b/hw/pci/pcie_host.c
index b2d942b..b70e5ad 100644
--- a/hw/pci/pcie_host.c
+++ b/hw/pci/pcie_host.c
@@ -130,7 +130,8 @@
     assert(size >= PCIE_MMCFG_SIZE_MIN);
     assert(size <= PCIE_MMCFG_SIZE_MAX);
     e->size = size;
-    memory_region_init_io(&e->mmio, &pcie_mmcfg_ops, e, "pcie-mmcfg", e->size);
+    memory_region_init_io(&e->mmio, OBJECT(e), &pcie_mmcfg_ops, e,
+                          "pcie-mmcfg", e->size);
     e->base_addr = addr;
     memory_region_add_subregion(get_system_memory(), e->base_addr, &e->mmio);
 }
diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
index d35c2ee..eb092fd 100644
--- a/hw/pci/shpc.c
+++ b/hw/pci/shpc.c
@@ -612,8 +612,8 @@
     }
 
     /* TODO: init cmask */
-    memory_region_init_io(&shpc->mmio, &shpc_mmio_ops, d, "shpc-mmio",
-                          SHPC_SIZEOF(d));
+    memory_region_init_io(&shpc->mmio, OBJECT(d), &shpc_mmio_ops,
+                          d, "shpc-mmio", SHPC_SIZEOF(d));
     shpc_cap_update_dword(d);
     memory_region_add_subregion(bar, offset, &shpc->mmio);
     pci_bus_hotplug(sec_bus, shpc_device_hotplug, &d->qdev);
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 38f7990..ee7e49a 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -137,7 +137,6 @@
     uint32_t clock_freq = 400000000;
     uint32_t tb_freq = 400000000;
     int i;
-    const char *toplevel_compat = NULL; /* user override */
     char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus";
     char soc[128];
     char mpic[128];
@@ -158,14 +157,9 @@
             0x0, 0xe1000000,
             0x0, 0x10000,
         };
-    QemuOpts *machine_opts;
-    const char *dtb_file = NULL;
-
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        dtb_file = qemu_opt_get(machine_opts, "dtb");
-        toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
-    }
+    QemuOpts *machine_opts = qemu_get_machine_opts();
+    const char *dtb_file = qemu_opt_get(machine_opts, "dtb");
+    const char *toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
 
     if (dtb_file) {
         char *filename;
@@ -528,7 +522,6 @@
 static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr,
                                    qemu_irq **irqs)
 {
-    QemuOptsList *list;
     qemu_irq *mpic;
     DeviceState *dev = NULL;
     SysBusDevice *s;
@@ -537,15 +530,11 @@
     mpic = g_new(qemu_irq, 256);
 
     if (kvm_enabled()) {
-        bool irqchip_allowed = true, irqchip_required = false;
-
-        list = qemu_find_opts("machine");
-        if (!QTAILQ_EMPTY(&list->head)) {
-            irqchip_allowed = qemu_opt_get_bool(QTAILQ_FIRST(&list->head),
+        QemuOpts *machine_opts = qemu_get_machine_opts();
+        bool irqchip_allowed = qemu_opt_get_bool(machine_opts,
                                                 "kernel_irqchip", true);
-            irqchip_required = qemu_opt_get_bool(QTAILQ_FIRST(&list->head),
-                                                 "kernel_irqchip", false);
-        }
+        bool irqchip_required = qemu_opt_get_bool(machine_opts,
+                                                  "kernel_irqchip", false);
 
         if (irqchip_allowed) {
             dev = ppce500_init_mpic_kvm(params, irqs);
@@ -651,7 +640,7 @@
     params->ram_size = ram_size;
 
     /* Register Memory */
-    memory_region_init_ram(ram, "mpc8544ds.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "mpc8544ds.ram", ram_size);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space_mem, 0, ram);
 
@@ -707,7 +696,7 @@
     if (pci_bus) {
         /* Register network interfaces. */
         for (i = 0; i < nb_nics; i++) {
-            pci_nic_init_nofail(&nd_table[i], "virtio", NULL);
+            pci_nic_init_nofail(&nd_table[i], pci_bus, "virtio", NULL);
         }
     }
 
@@ -783,7 +772,7 @@
     PPCE500CCSRState *ccsr;
 
     ccsr = CCSR(dev);
-    memory_region_init(&ccsr->ccsr_space, "e500-ccsr",
+    memory_region_init(&ccsr->ccsr_space, OBJECT(ccsr), "e500-ccsr",
                        MPC8544_CCSRBAR_SIZE);
     return 0;
 }
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 3badfa3..77a8c2e 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -196,12 +196,12 @@
     }
 
     /* allocate RAM */
-    memory_region_init_ram(ram, "ppc_core99.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "ppc_core99.ram", ram_size);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(get_system_memory(), 0, ram);
 
     /* allocate and load BIOS */
-    memory_region_init_ram(bios, "ppc_core99.bios", BIOS_SIZE);
+    memory_region_init_ram(bios, NULL, "ppc_core99.bios", BIOS_SIZE);
     vmstate_register_ram_global(bios);
     if (bios_name == NULL)
         bios_name = PROM_FILENAME;
@@ -290,10 +290,10 @@
     isa_mmio_init(0xf2000000, 0x00800000);
 
     /* UniN init: XXX should be a real device */
-    memory_region_init_io(unin_memory, &unin_ops, token, "unin", 0x1000);
+    memory_region_init_io(unin_memory, NULL, &unin_ops, token, "unin", 0x1000);
     memory_region_add_subregion(get_system_memory(), 0xf8000000, unin_memory);
 
-    memory_region_init_io(unin2_memory, &unin_ops, token, "unin", 0x1000);
+    memory_region_init_io(unin2_memory, NULL, &unin_ops, token, "unin", 0x1000);
     memory_region_add_subregion(get_system_memory(), 0xf3000000, unin2_memory);
 
     openpic_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
@@ -371,11 +371,11 @@
 
     escc_mem = escc_init(0, pic[0x25], pic[0x24],
                          serial_hds[0], serial_hds[1], ESCC_CLOCK, 4);
-    memory_region_init_alias(escc_bar, "escc-bar",
+    memory_region_init_alias(escc_bar, NULL, "escc-bar",
                              escc_mem, 0, memory_region_size(escc_mem));
 
     for(i = 0; i < nb_nics; i++)
-        pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
+        pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL);
 
     ide_drive_get(hd, MAX_IDE_BUS);
 
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 8faff30..4663ed2 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -126,12 +126,12 @@
         exit(1);
     }
 
-    memory_region_init_ram(ram, "ppc_heathrow.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "ppc_heathrow.ram", ram_size);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(sysmem, 0, ram);
 
     /* allocate and load BIOS */
-    memory_region_init_ram(bios, "ppc_heathrow.bios", BIOS_SIZE);
+    memory_region_init_ram(bios, NULL, "ppc_heathrow.bios", BIOS_SIZE);
     vmstate_register_ram_global(bios);
     if (bios_name == NULL)
         bios_name = PROM_FILENAME;
@@ -255,11 +255,11 @@
 
     escc_mem = escc_init(0, pic[0x0f], pic[0x10], serial_hds[0],
                                serial_hds[1], ESCC_CLOCK, 4);
-    memory_region_init_alias(escc_bar, "escc-bar",
+    memory_region_init_alias(escc_bar, NULL, "escc-bar",
                              escc_mem, 0, memory_region_size(escc_mem));
 
     for(i = 0; i < nb_nics; i++)
-        pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
+        pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL);
 
 
     ide_drive_get(hd, MAX_IDE_BUS);
diff --git a/hw/ppc/mpc8544_guts.c b/hw/ppc/mpc8544_guts.c
index d41f615..2e2f2eb 100644
--- a/hw/ppc/mpc8544_guts.c
+++ b/hw/ppc/mpc8544_guts.c
@@ -119,7 +119,7 @@
     SysBusDevice *d = SYS_BUS_DEVICE(obj);
     GutsState *s = MPC8544_GUTS(obj);
 
-    memory_region_init_io(&s->iomem, &mpc8544_guts_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &mpc8544_guts_ops, s,
                           "mpc8544.guts", MPC8544_GUTS_MMIO_SIZE);
     sysbus_init_mmio(d, &s->iomem);
 }
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index f0c7ee9..f74e5e5 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -164,7 +164,7 @@
     MemoryRegion *fpga_memory = g_new(MemoryRegion, 1);
 
     fpga = g_malloc0(sizeof(ref405ep_fpga_t));
-    memory_region_init_io(fpga_memory, &ref405ep_fpga_ops, fpga,
+    memory_region_init_io(fpga_memory, NULL, &ref405ep_fpga_ops, fpga,
                           "fpga", 0x00000100);
     memory_region_add_subregion(sysmem, base, fpga_memory);
     qemu_register_reset(&ref405ep_fpga_reset, fpga);
@@ -197,11 +197,11 @@
     MemoryRegion *sysmem = get_system_memory();
 
     /* XXX: fix this */
-    memory_region_init_ram(&ram_memories[0], "ef405ep.ram", 0x08000000);
+    memory_region_init_ram(&ram_memories[0], NULL, "ef405ep.ram", 0x08000000);
     vmstate_register_ram_global(&ram_memories[0]);
     ram_bases[0] = 0;
     ram_sizes[0] = 0x08000000;
-    memory_region_init(&ram_memories[1], "ef405ep.ram1", 0);
+    memory_region_init(&ram_memories[1], NULL, "ef405ep.ram1", 0);
     ram_bases[1] = 0x00000000;
     ram_sizes[1] = 0x00000000;
     ram_size = 128 * 1024 * 1024;
@@ -212,7 +212,7 @@
                         33333333, &pic, kernel_filename == NULL ? 0 : 1);
     /* allocate SRAM */
     sram_size = 512 * 1024;
-    memory_region_init_ram(sram, "ef405ep.sram", sram_size);
+    memory_region_init_ram(sram, NULL, "ef405ep.sram", sram_size);
     vmstate_register_ram_global(sram);
     memory_region_add_subregion(sysmem, 0xFFF00000, sram);
     /* allocate and load BIOS */
@@ -244,7 +244,7 @@
         printf("Load BIOS from file\n");
 #endif
         bios = g_new(MemoryRegion, 1);
-        memory_region_init_ram(bios, "ef405ep.bios", BIOS_SIZE);
+        memory_region_init_ram(bios, NULL, "ef405ep.bios", BIOS_SIZE);
         vmstate_register_ram_global(bios);
         if (bios_name == NULL)
             bios_name = BIOS_FILENAME;
@@ -490,7 +490,7 @@
     MemoryRegion *cpld_memory = g_new(MemoryRegion, 1);
 
     cpld = g_malloc0(sizeof(taihu_cpld_t));
-    memory_region_init_io(cpld_memory, &taihu_cpld_ops, cpld, "cpld", 0x100);
+    memory_region_init_io(cpld_memory, NULL, &taihu_cpld_ops, cpld, "cpld", 0x100);
     memory_region_add_subregion(sysmem, base, cpld_memory);
     qemu_register_reset(&taihu_cpld_reset, cpld);
 }
@@ -514,12 +514,12 @@
     DriveInfo *dinfo;
 
     /* RAM is soldered to the board so the size cannot be changed */
-    memory_region_init_ram(&ram_memories[0],
+    memory_region_init_ram(&ram_memories[0], NULL,
                            "taihu_405ep.ram-0", 0x04000000);
     vmstate_register_ram_global(&ram_memories[0]);
     ram_bases[0] = 0;
     ram_sizes[0] = 0x04000000;
-    memory_region_init_ram(&ram_memories[1],
+    memory_region_init_ram(&ram_memories[1], NULL,
                            "taihu_405ep.ram-1", 0x04000000);
     vmstate_register_ram_global(&ram_memories[1]);
     ram_bases[1] = 0x04000000;
@@ -563,7 +563,7 @@
         if (bios_name == NULL)
             bios_name = BIOS_FILENAME;
         bios = g_new(MemoryRegion, 1);
-        memory_region_init_ram(bios, "taihu_405ep.bios", BIOS_SIZE);
+        memory_region_init_ram(bios, NULL, "taihu_405ep.bios", BIOS_SIZE);
         vmstate_register_ram_global(bios);
         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
         if (filename) {
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index c6c909e..290f71a 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -390,7 +390,7 @@
 #ifdef DEBUG_OPBA
     printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
 #endif
-    memory_region_init_io(&opba->io, &opba_ops, opba, "opba", 0x002);
+    memory_region_init_io(&opba->io, NULL, &opba_ops, opba, "opba", 0x002);
     memory_region_add_subregion(get_system_memory(), base, &opba->io);
     qemu_register_reset(ppc4xx_opba_reset, opba);
 }
@@ -812,7 +812,7 @@
 #ifdef DEBUG_GPIO
     printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
 #endif
-    memory_region_init_io(&gpio->io, &ppc405_gpio_ops, gpio, "pgio", 0x038);
+    memory_region_init_io(&gpio->io, NULL, &ppc405_gpio_ops, gpio, "pgio", 0x038);
     memory_region_add_subregion(get_system_memory(), base, &gpio->io);
     qemu_register_reset(&ppc405_gpio_reset, gpio);
 }
@@ -972,9 +972,9 @@
 
     ocm = g_malloc0(sizeof(ppc405_ocm_t));
     /* XXX: Size is 4096 or 0x04000000 */
-    memory_region_init_ram(&ocm->isarc_ram, "ppc405.ocm", 4096);
+    memory_region_init_ram(&ocm->isarc_ram, NULL, "ppc405.ocm", 4096);
     vmstate_register_ram_global(&ocm->isarc_ram);
-    memory_region_init_alias(&ocm->dsarc_ram, "ppc405.dsarc", &ocm->isarc_ram,
+    memory_region_init_alias(&ocm->dsarc_ram, NULL, "ppc405.dsarc", &ocm->isarc_ram,
                              0, 4096);
     qemu_register_reset(&ocm_reset, ocm);
     ppc_dcr_register(env, OCM0_ISARC,
@@ -1222,7 +1222,7 @@
 #ifdef DEBUG_I2C
     printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
 #endif
-    memory_region_init_io(&i2c->iomem, &i2c_ops, i2c, "i2c", 0x011);
+    memory_region_init_io(&i2c->iomem, NULL, &i2c_ops, i2c, "i2c", 0x011);
     memory_region_add_subregion(get_system_memory(), base, &i2c->iomem);
     qemu_register_reset(ppc4xx_i2c_reset, i2c);
 }
@@ -1501,7 +1501,7 @@
 #ifdef DEBUG_GPT
     printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
 #endif
-    memory_region_init_io(&gpt->iomem, &gpt_ops, gpt, "gpt", 0x0d4);
+    memory_region_init_io(&gpt->iomem, NULL, &gpt_ops, gpt, "gpt", 0x0d4);
     memory_region_add_subregion(get_system_memory(), base, &gpt->iomem);
     qemu_register_reset(ppc4xx_gpt_reset, gpt);
 }
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index b0c1c02..5b039ab 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -243,7 +243,7 @@
         for (i = 0; i < nb_nics; i++) {
             /* There are no PCI NICs on the Bamboo board, but there are
              * PCI slots, so we can pick whatever default model we want. */
-            pci_nic_init_nofail(&nd_table[i], "e1000", NULL);
+            pci_nic_init_nofail(&nd_table[i], pcibus, "e1000", NULL);
         }
     }
 
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index d8e3dae..239aada 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -431,7 +431,7 @@
         printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
                __func__, sdram_base(bcr), sdram_size(bcr));
 #endif
-        memory_region_init(&sdram->containers[n], "sdram-containers",
+        memory_region_init(&sdram->containers[n], NULL, "sdram-containers",
                            sdram_size(bcr));
         memory_region_add_subregion(&sdram->containers[n], 0,
                                     &sdram->ram_memories[n]);
@@ -696,7 +696,7 @@
             if (bank_size <= size_left) {
                 char name[32];
                 snprintf(name, sizeof(name), "ppc4xx.sdram%d", i);
-                memory_region_init_ram(&ram_memories[i], name, bank_size);
+                memory_region_init_ram(&ram_memories[i], NULL, name, bank_size);
                 vmstate_register_ram_global(&ram_memories[i]);
                 ram_bases[i] = base;
                 ram_sizes[i] = bank_size;
diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c
index 599539b..d2d6f65 100644
--- a/hw/ppc/ppc4xx_pci.c
+++ b/hw/ppc/ppc4xx_pci.c
@@ -355,12 +355,12 @@
     pci_create_simple(b, 0, "ppc4xx-host-bridge");
 
     /* XXX split into 2 memory regions, one for config space, one for regs */
-    memory_region_init(&s->container, "pci-container", PCI_ALL_SIZE);
-    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, h,
+    memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE);
+    memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops, h,
                           "pci-conf-idx", 4);
-    memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, h,
+    memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops, h,
                           "pci-conf-data", 4);
-    memory_region_init_io(&s->iomem, &pci_reg_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s,
                           "pci.reg", PCI_REG_SIZE);
     memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem);
     memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem);
diff --git a/hw/ppc/ppce500_spin.c b/hw/ppc/ppce500_spin.c
index ea65414..11b7de2 100644
--- a/hw/ppc/ppce500_spin.c
+++ b/hw/ppc/ppce500_spin.c
@@ -191,8 +191,8 @@
 
     s = FROM_SYSBUS(SpinState, SYS_BUS_DEVICE(dev));
 
-    memory_region_init_io(&s->iomem, &spin_rw_ops, s, "e500 spin pv device",
-                          sizeof(SpinInfo) * MAX_CPUS);
+    memory_region_init_io(&s->iomem, OBJECT(s), &spin_rw_ops, s,
+                          "e500 spin pv device", sizeof(SpinInfo) * MAX_CPUS);
     sysbus_init_mmio(dev, &s->iomem);
 
     qemu_register_reset(spin_reset, s);
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 90828f2..7b2559d 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -434,6 +434,16 @@
     cpu->env.nip = 0xfffffffc;
 }
 
+static const MemoryRegionPortio prep_portio_list[] = {
+    /* System control ports */
+    { 0x0092, 1, 1, .read = PREP_io_800_readb, .write = PREP_io_800_writeb, },
+    { 0x0800, 0x52, 1,
+      .read = PREP_io_800_readb, .write = PREP_io_800_writeb, },
+    /* Special port to get debug messages from Open-Firmware */
+    { 0x0F00, 4, 1, .write = PPC_debug_write, },
+    PORTIO_END_OF_LIST(),
+};
+
 /* PowerPC PREP hardware initialisation */
 static void ppc_prep_init(QEMUMachineInitArgs *args)
 {
@@ -450,6 +460,7 @@
     nvram_t nvram;
     M48t59State *m48t59;
     MemoryRegion *PPC_io_memory = g_new(MemoryRegion, 1);
+    PortioList *port_list = g_new(PortioList, 1);
 #if 0
     MemoryRegion *xcsr = g_new(MemoryRegion, 1);
 #endif
@@ -494,12 +505,12 @@
     }
 
     /* allocate RAM */
-    memory_region_init_ram(ram, "ppc_prep.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "ppc_prep.ram", ram_size);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(sysmem, 0, ram);
 
     /* allocate and load BIOS */
-    memory_region_init_ram(bios, "ppc_prep.bios", BIOS_SIZE);
+    memory_region_init_ram(bios, NULL, "ppc_prep.bios", BIOS_SIZE);
     memory_region_set_readonly(bios, true);
     memory_region_add_subregion(sysmem, (uint32_t)(-BIOS_SIZE), bios);
     vmstate_register_ram_global(bios);
@@ -610,7 +621,7 @@
     qdev_init_nofail(dev);
 
     /* Register 8 MB of ISA IO space (needed for non-contiguous map) */
-    memory_region_init_io(PPC_io_memory, &PPC_prep_io_ops, sysctrl,
+    memory_region_init_io(PPC_io_memory, NULL, &PPC_prep_io_ops, sysctrl,
                           "ppc-io", 0x00800000);
     memory_region_add_subregion(sysmem, 0x80000000, PPC_io_memory);
 
@@ -628,7 +639,7 @@
             isa_ne2000_init(isa_bus, ne2000_io[i], ne2000_irq[i],
                             &nd_table[i]);
         } else {
-            pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
+            pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL);
         }
     }
 
@@ -641,14 +652,13 @@
     isa_create_simple(isa_bus, "i8042");
 
     sysctrl->reset_irq = first_cpu->irq_inputs[PPC6xx_INPUT_HRESET];
-    /* System control ports */
-    register_ioport_read(0x0092, 0x01, 1, &PREP_io_800_readb, sysctrl);
-    register_ioport_write(0x0092, 0x01, 1, &PREP_io_800_writeb, sysctrl);
-    register_ioport_read(0x0800, 0x52, 1, &PREP_io_800_readb, sysctrl);
-    register_ioport_write(0x0800, 0x52, 1, &PREP_io_800_writeb, sysctrl);
+
+    portio_list_init(port_list, NULL, prep_portio_list, sysctrl, "prep");
+    portio_list_add(port_list, get_system_io(), 0x0);
+
     /* PowerPC control and status register group */
 #if 0
-    memory_region_init_io(xcsr, &PPC_XCSR_ops, NULL, "ppc-xcsr", 0x1000);
+    memory_region_init_io(xcsr, NULL, &PPC_XCSR_ops, NULL, "ppc-xcsr", 0x1000);
     memory_region_add_subregion(sysmem, 0xFEFF0000, xcsr);
 #endif
 
@@ -672,9 +682,6 @@
                          /* XXX: need an option to load a NVRAM image */
                          0,
                          graphic_width, graphic_height, graphic_depth);
-
-    /* Special port to get debug messages from Open-Firmware */
-    register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
 }
 
 static QEMUMachine prep_machine = {
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index fe34291..226ae70 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -676,27 +676,19 @@
 
 static void spapr_create_nvram(sPAPREnvironment *spapr)
 {
-    QemuOpts *machine_opts;
-    DeviceState *dev;
+    DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
+    const char *drivename = qemu_opt_get(qemu_get_machine_opts(), "nvram");
 
-    dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
+    if (drivename) {
+        BlockDriverState *bs;
 
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        const char *drivename;
-
-        drivename = qemu_opt_get(machine_opts, "nvram");
-        if (drivename) {
-            BlockDriverState *bs;
-
-            bs = bdrv_find(drivename);
-            if (!bs) {
-                fprintf(stderr, "No such block device \"%s\" for nvram\n",
-                        drivename);
-                exit(1);
-            }
-            qdev_prop_set_drive_nofail(dev, "drive", bs);
+        bs = bdrv_find(drivename);
+        if (!bs) {
+            fprintf(stderr, "No such block device \"%s\" for nvram\n",
+                    drivename);
+            exit(1);
         }
+        qdev_prop_set_drive_nofail(dev, "drive", bs);
     }
 
     qdev_init_nofail(dev);
@@ -835,7 +827,7 @@
         ram_addr_t nonrma_base = rma_alloc_size;
         ram_addr_t nonrma_size = spapr->ram_limit - rma_alloc_size;
 
-        memory_region_init_ram(ram, "ppc_spapr.ram", nonrma_size);
+        memory_region_init_ram(ram, NULL, "ppc_spapr.ram", nonrma_size);
         vmstate_register_ram_global(ram);
         memory_region_add_subregion(sysmem, nonrma_base, ram);
     }
@@ -887,7 +879,7 @@
         if (strcmp(nd->model, "ibmveth") == 0) {
             spapr_vlan_create(spapr->vio_bus, nd);
         } else {
-            pci_nic_init_nofail(&nd_table[i], nd->model, NULL);
+            pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL);
         }
     }
 
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 91bc8e4..89b33a5 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -116,7 +116,7 @@
     .translate = spapr_tce_translate_iommu,
 };
 
-sPAPRTCETable *spapr_tce_new_table(uint32_t liobn, size_t window_size)
+sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, size_t window_size)
 {
     sPAPRTCETable *tcet;
 
@@ -151,7 +151,7 @@
             "table @ %p, fd=%d\n", tcet, liobn, tcet->table, tcet->fd);
 #endif
 
-    memory_region_init_iommu(&tcet->iommu, &spapr_iommu_ops,
+    memory_region_init_iommu(&tcet->iommu, OBJECT(owner), &spapr_iommu_ops,
                              "iommu-spapr", UINT64_MAX);
 
     QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index c8c12c8..18f2e2f 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -581,10 +581,11 @@
 
     /* Initialize memory regions */
     sprintf(namebuf, "%s.mmio", sphb->dtbusname);
-    memory_region_init(&sphb->memspace, namebuf, INT64_MAX);
+    memory_region_init(&sphb->memspace, OBJECT(sphb), namebuf, INT64_MAX);
 
     sprintf(namebuf, "%s.mmio-alias", sphb->dtbusname);
-    memory_region_init_alias(&sphb->memwindow, namebuf, &sphb->memspace,
+    memory_region_init_alias(&sphb->memwindow, OBJECT(sphb),
+                             namebuf, &sphb->memspace,
                              SPAPR_PCI_MEM_WIN_BUS_OFFSET, sphb->mem_win_size);
     memory_region_add_subregion(get_system_memory(), sphb->mem_win_addr,
                                 &sphb->memwindow);
@@ -598,12 +599,13 @@
      * system_io works around the problem until all the users of
      * old_portion are updated */
     sprintf(namebuf, "%s.io", sphb->dtbusname);
-    memory_region_init(&sphb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE);
+    memory_region_init(&sphb->iospace, OBJECT(sphb),
+                       namebuf, SPAPR_PCI_IO_WIN_SIZE);
     /* FIXME: fix to support multiple PHBs */
     memory_region_add_subregion(get_system_io(), 0, &sphb->iospace);
 
     sprintf(namebuf, "%s.io-alias", sphb->dtbusname);
-    memory_region_init_io(&sphb->iowindow, &spapr_io_ops, sphb,
+    memory_region_init_io(&sphb->iowindow, OBJECT(sphb), &spapr_io_ops, sphb,
                           namebuf, SPAPR_PCI_IO_WIN_SIZE);
     memory_region_add_subregion(get_system_memory(), sphb->io_win_addr,
                                 &sphb->iowindow);
@@ -613,7 +615,7 @@
      * from msi_notify()/msix_notify() */
     if (msi_supported) {
         sprintf(namebuf, "%s.msi", sphb->dtbusname);
-        memory_region_init_io(&sphb->msiwindow, &spapr_msi_ops, sphb,
+        memory_region_init_io(&sphb->msiwindow, OBJECT(sphb), &spapr_msi_ops, sphb,
                               namebuf, SPAPR_MSIX_MAX_DEVS * 0x10000);
         memory_region_add_subregion(get_system_memory(), sphb->msi_win_addr,
                                     &sphb->msiwindow);
@@ -646,7 +648,8 @@
 
     sphb->dma_window_start = 0;
     sphb->dma_window_size = 0x40000000;
-    sphb->tcet = spapr_tce_new_table(sphb->dma_liobn, sphb->dma_window_size);
+    sphb->tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn,
+                                     sphb->dma_window_size);
     if (!sphb->tcet) {
         fprintf(stderr, "Unable to create TCE table for %s\n", sphb->dtbusname);
         return -1;
@@ -696,11 +699,21 @@
     DEFINE_PROP_END_OF_LIST(),
 };
 
+static const char *spapr_phb_root_bus_path(PCIHostState *host_bridge,
+                                           PCIBus *rootbus)
+{
+    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(host_bridge);
+
+    return sphb->dtbusname;
+}
+
 static void spapr_phb_class_init(ObjectClass *klass, void *data)
 {
+    PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
+    hc->root_bus_path = spapr_phb_root_bus_path;
     sdc->init = spapr_phb_init;
     dc->props = spapr_phb_properties;
     dc->reset = spapr_phb_reset;
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 9c18741..7c6f6e4 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -455,7 +455,7 @@
 
     if (pc->rtce_window_size) {
         uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
-        dev->tcet = spapr_tce_new_table(liobn, pc->rtce_window_size);
+        dev->tcet = spapr_tce_new_table(qdev, liobn, pc->rtce_window_size);
         address_space_init(&dev->as, spapr_tce_get_iommu(dev->tcet), qdev->id);
     }
 
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
index 709a707..08e77fb 100644
--- a/hw/ppc/virtex_ml507.c
+++ b/hw/ppc/virtex_ml507.c
@@ -190,7 +190,7 @@
     env = &cpu->env;
     qemu_register_reset(main_cpu_reset, cpu);
 
-    memory_region_init_ram(phys_ram, "ram", ram_size);
+    memory_region_init_ram(phys_ram, NULL, "ram", ram_size);
     vmstate_register_ram_global(phys_ram);
     memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
 
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index eb774d9..aebbbf1 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -89,7 +89,7 @@
     virtio_ccw_register_hcalls();
 
     /* allocate RAM */
-    memory_region_init_ram(ram, "s390.ram", my_ram_size);
+    memory_region_init_ram(ram, NULL, "s390.ram", my_ram_size);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(sysmem, 0, ram);
 
diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c
index 30d1118..edbde00 100644
--- a/hw/s390x/s390-virtio.c
+++ b/hw/s390x/s390-virtio.c
@@ -256,7 +256,7 @@
     s390_virtio_register_hcalls();
 
     /* allocate RAM */
-    memory_region_init_ram(ram, "s390.ram", my_ram_size);
+    memory_region_init_ram(ram, NULL, "s390.ram", my_ram_size);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(sysmem, 0, ram);
 
diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c
index 029789a..8f97c5a 100644
--- a/hw/scsi/esp-pci.c
+++ b/hw/scsi/esp-pci.c
@@ -349,7 +349,8 @@
     s->dma_memory_write = esp_pci_dma_memory_write;
     s->dma_opaque = pci;
     s->chip_id = TCHI_AM53C974;
-    memory_region_init_io(&pci->io, &esp_pci_io_ops, pci, "esp-io", 0x80);
+    memory_region_init_io(&pci->io, OBJECT(pci), &esp_pci_io_ops, pci,
+                          "esp-io", 0x80);
 
     pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->io);
     s->irq = pci->dev.irq[0];
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 0c81a50..c6166c5 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -675,8 +675,8 @@
     assert(sysbus->it_shift != -1);
 
     s->chip_id = TCHI_FAS100A;
-    memory_region_init_io(&sysbus->iomem, &sysbus_esp_mem_ops, sysbus,
-                          "esp", ESP_REGS << sysbus->it_shift);
+    memory_region_init_io(&sysbus->iomem, OBJECT(sysbus), &sysbus_esp_mem_ops,
+                          sysbus, "esp", ESP_REGS << sysbus->it_shift);
     sysbus_init_mmio(dev, &sysbus->iomem);
 
     qdev_init_gpio_in(&dev->qdev, sysbus_esp_gpio_demux, 2);
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index 22b8e98..2c17ae5 100644
--- a/hw/scsi/lsi53c895a.c
+++ b/hw/scsi/lsi53c895a.c
@@ -2090,9 +2090,12 @@
     /* Interrupt pin A */
     pci_conf[PCI_INTERRUPT_PIN] = 0x01;
 
-    memory_region_init_io(&s->mmio_io, &lsi_mmio_ops, s, "lsi-mmio", 0x400);
-    memory_region_init_io(&s->ram_io, &lsi_ram_ops, s, "lsi-ram", 0x2000);
-    memory_region_init_io(&s->io_io, &lsi_io_ops, s, "lsi-io", 256);
+    memory_region_init_io(&s->mmio_io, OBJECT(s), &lsi_mmio_ops, s,
+                          "lsi-mmio", 0x400);
+    memory_region_init_io(&s->ram_io, OBJECT(s), &lsi_ram_ops, s,
+                          "lsi-ram", 0x2000);
+    memory_region_init_io(&s->io_io, OBJECT(s), &lsi_io_ops, s,
+                          "lsi-io", 256);
 
     pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_io);
     pci_register_bar(&s->dev, 1, 0, &s->mmio_io);
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 65ccb09..45d0c77 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -2098,11 +2098,11 @@
     /* Interrupt pin 1 */
     pci_conf[PCI_INTERRUPT_PIN] = 0x01;
 
-    memory_region_init_io(&s->mmio_io, &megasas_mmio_ops, s,
+    memory_region_init_io(&s->mmio_io, OBJECT(s), &megasas_mmio_ops, s,
                           "megasas-mmio", 0x4000);
-    memory_region_init_io(&s->port_io, &megasas_port_ops, s,
+    memory_region_init_io(&s->port_io, OBJECT(s), &megasas_port_ops, s,
                           "megasas-io", 256);
-    memory_region_init_io(&s->queue_io, &megasas_queue_ops, s,
+    memory_region_init_io(&s->queue_io, OBJECT(s), &megasas_queue_ops, s,
                           "megasas-queue", 0x40000);
 
 #ifdef USE_MSIX
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 53ea906..a92b7c1 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -505,10 +505,12 @@
                             uint32_t tag, uint32_t lun, void *hba_private)
 {
     SCSIRequest *req;
+    SCSIBus *bus = scsi_bus_from_device(d);
+    BusState *qbus = BUS(bus);
 
     req = g_malloc0(reqops->size);
     req->refcount = 1;
-    req->bus = scsi_bus_from_device(d);
+    req->bus = bus;
     req->dev = d;
     req->tag = tag;
     req->lun = lun;
@@ -516,6 +518,8 @@
     req->status = -1;
     req->sense_len = 0;
     req->ops = reqops;
+    object_ref(OBJECT(d));
+    object_ref(OBJECT(qbus->parent));
     trace_scsi_req_alloc(req->dev->id, req->lun, req->tag);
     return req;
 }
@@ -1498,13 +1502,17 @@
 {
     assert(req->refcount > 0);
     if (--req->refcount == 0) {
-        SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, req->dev->qdev.parent_bus);
+        BusState *qbus = req->dev->qdev.parent_bus;
+        SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, qbus);
+
         if (bus->info->free_request && req->hba_private) {
             bus->info->free_request(bus, req->hba_private);
         }
         if (req->ops->free_req) {
             req->ops->free_req(req);
         }
+        object_unref(OBJECT(req->dev));
+        object_unref(OBJECT(qbus->parent));
         g_free(req);
     }
 }
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index b8a0abf..712f0ad 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -77,10 +77,12 @@
     exit(1);
 }
 
-static void qemu_sgl_init_external(QEMUSGList *qsgl, struct iovec *sg,
+static void qemu_sgl_init_external(VirtIOSCSIReq *req, struct iovec *sg,
                                    hwaddr *addr, int num)
 {
-    qemu_sglist_init(qsgl, num, &address_space_memory);
+    QEMUSGList *qsgl = &req->qsgl;
+
+    qemu_sglist_init(qsgl, DEVICE(req->dev), num, &address_space_memory);
     while (num--) {
         qemu_sglist_add(qsgl, *(addr++), (sg++)->iov_len);
     }
@@ -99,11 +101,11 @@
     req->resp.buf = req->elem.in_sg[0].iov_base;
 
     if (req->elem.out_num > 1) {
-        qemu_sgl_init_external(&req->qsgl, &req->elem.out_sg[1],
+        qemu_sgl_init_external(req, &req->elem.out_sg[1],
                                &req->elem.out_addr[1],
                                req->elem.out_num - 1);
     } else {
-        qemu_sgl_init_external(&req->qsgl, &req->elem.in_sg[1],
+        qemu_sgl_init_external(req, &req->elem.in_sg[1],
                                &req->elem.in_addr[1],
                                req->elem.in_num - 1);
     }
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index 7cf4044..97d3aa3 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -1075,7 +1075,7 @@
     /* Interrupt pin A */
     pci_config_set_interrupt_pin(pci_dev->config, 1);
 
-    memory_region_init_io(&s->io_space, &pvscsi_ops, s,
+    memory_region_init_io(&s->io_space, OBJECT(s), &pvscsi_ops, s,
                           "pvscsi-io", PVSCSI_MEM_SPACE_SIZE);
     pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io_space);
 
diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
index 61a8aad..f69775c 100644
--- a/hw/sd/milkymist-memcard.c
+++ b/hw/sd/milkymist-memcard.c
@@ -253,7 +253,7 @@
     s->card = sd_init(dinfo ? dinfo->bdrv : NULL, false);
     s->enabled = dinfo ? bdrv_is_inserted(dinfo->bdrv) : 0;
 
-    memory_region_init_io(&s->regs_region, &memcard_mmio_ops, s,
+    memory_region_init_io(&s->regs_region, OBJECT(s), &memcard_mmio_ops, s,
             "milkymist-memcard", R_MAX * 4);
     sysbus_init_mmio(dev, &s->regs_region);
 
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
index ba9f4b3..bf5d1fb 100644
--- a/hw/sd/omap_mmc.c
+++ b/hw/sd/omap_mmc.c
@@ -588,7 +588,7 @@
 
     omap_mmc_reset(s);
 
-    memory_region_init_io(&s->iomem, &omap_mmc_ops, s, "omap.mmc", 0x800);
+    memory_region_init_io(&s->iomem, NULL, &omap_mmc_ops, s, "omap.mmc", 0x800);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
     /* Instantiate the storage */
@@ -612,7 +612,7 @@
 
     omap_mmc_reset(s);
 
-    memory_region_init_io(&s->iomem, &omap_mmc_ops, s, "omap.mmc",
+    memory_region_init_io(&s->iomem, NULL, &omap_mmc_ops, s, "omap.mmc",
                           omap_l4_region_size(ta, 0));
     omap_l4_attach(ta, 0, &s->iomem);
 
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index e08fd04..4b17234 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -479,7 +479,7 @@
     pl181_state *s = FROM_SYSBUS(pl181_state, dev);
     DriveInfo *dinfo;
 
-    memory_region_init_io(&s->iomem, &pl181_ops, s, "pl181", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &pl181_ops, s, "pl181", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq[0]);
     sysbus_init_irq(dev, &s->irq[1]);
diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c
index 0574d6b..90c955f 100644
--- a/hw/sd/pxa2xx_mmci.c
+++ b/hw/sd/pxa2xx_mmci.c
@@ -533,7 +533,7 @@
     s->rx_dma = rx_dma;
     s->tx_dma = tx_dma;
 
-    memory_region_init_io(&s->iomem, &pxa2xx_mmci_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &pxa2xx_mmci_ops, s,
                           "pxa2xx-mmci", 0x00100000);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index b9dd4be..d2dbddc 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1245,7 +1245,7 @@
     s->buf_maxsz = sdhci_get_fifolen(s);
     s->fifo_buffer = g_malloc0(s->buf_maxsz);
     sysbus_init_irq(sbd, &s->irq);
-    memory_region_init_io(&s->iomem, &sdhci_mmio_ops, s, "sdhci",
+    memory_region_init_io(&s->iomem, OBJECT(s), &sdhci_mmio_ops, s, "sdhci",
             SDHC_REGISTERS_MAP_SIZE);
     sysbus_init_mmio(sbd, &s->iomem);
 }
diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
index 3e4818e..98b3408 100644
--- a/hw/sh4/r2d.c
+++ b/hw/sh4/r2d.c
@@ -186,7 +186,7 @@
 
     s->irl = irl;
 
-    memory_region_init_io(&s->iomem, &r2d_fpga_ops, s, "r2d-fpga", 0x40);
+    memory_region_init_io(&s->iomem, NULL, &r2d_fpga_ops, s, "r2d-fpga", 0x40);
     memory_region_add_subregion(sysmem, base, &s->iomem);
     return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS);
 }
@@ -236,6 +236,7 @@
     DeviceState *dev;
     SysBusDevice *busdev;
     MemoryRegion *address_space_mem = get_system_memory();
+    PCIBus *pci_bus;
 
     if (cpu_model == NULL) {
         cpu_model = "SH7751R";
@@ -254,7 +255,7 @@
     qemu_register_reset(main_cpu_reset, reset_info);
 
     /* Allocate memory space */
-    memory_region_init_ram(sdram, "r2d.sdram", SDRAM_SIZE);
+    memory_region_init_ram(sdram, NULL, "r2d.sdram", SDRAM_SIZE);
     vmstate_register_ram_global(sdram);
     memory_region_add_subregion(address_space_mem, SDRAM_BASE, sdram);
     /* Register peripherals */
@@ -264,6 +265,7 @@
     dev = qdev_create(NULL, "sh_pci");
     busdev = SYS_BUS_DEVICE(dev);
     qdev_init_nofail(dev);
+    pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci"));
     sysbus_mmio_map(busdev, 0, P4ADDR(0x1e200000));
     sysbus_mmio_map(busdev, 1, A7ADDR(0x1e200000));
     sysbus_connect_irq(busdev, 0, irq[PCI_INTA]);
@@ -295,7 +297,8 @@
 
     /* NIC: rtl8139 on-board, and 2 slots. */
     for (i = 0; i < nb_nics; i++)
-        pci_nic_init_nofail(&nd_table[i], "rtl8139", i==0 ? "2" : NULL);
+        pci_nic_init_nofail(&nd_table[i], pci_bus,
+                            "rtl8139", i==0 ? "2" : NULL);
 
     /* USB keyboard */
     usbdevice_create("keyboard");
diff --git a/hw/sh4/sh7750.c b/hw/sh4/sh7750.c
index 03e8bd1..1439ba4 100644
--- a/hw/sh4/sh7750.c
+++ b/hw/sh4/sh7750.c
@@ -730,34 +730,34 @@
     s = g_malloc0(sizeof(SH7750State));
     s->cpu = cpu;
     s->periph_freq = 60000000;	/* 60MHz */
-    memory_region_init_io(&s->iomem, &sh7750_mem_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &sh7750_mem_ops, s,
                           "memory", 0x1fc01000);
 
-    memory_region_init_alias(&s->iomem_1f0, "memory-1f0",
+    memory_region_init_alias(&s->iomem_1f0, NULL, "memory-1f0",
                              &s->iomem, 0x1f000000, 0x1000);
     memory_region_add_subregion(sysmem, 0x1f000000, &s->iomem_1f0);
 
-    memory_region_init_alias(&s->iomem_ff0, "memory-ff0",
+    memory_region_init_alias(&s->iomem_ff0, NULL, "memory-ff0",
                              &s->iomem, 0x1f000000, 0x1000);
     memory_region_add_subregion(sysmem, 0xff000000, &s->iomem_ff0);
 
-    memory_region_init_alias(&s->iomem_1f8, "memory-1f8",
+    memory_region_init_alias(&s->iomem_1f8, NULL, "memory-1f8",
                              &s->iomem, 0x1f800000, 0x1000);
     memory_region_add_subregion(sysmem, 0x1f800000, &s->iomem_1f8);
 
-    memory_region_init_alias(&s->iomem_ff8, "memory-ff8",
+    memory_region_init_alias(&s->iomem_ff8, NULL, "memory-ff8",
                              &s->iomem, 0x1f800000, 0x1000);
     memory_region_add_subregion(sysmem, 0xff800000, &s->iomem_ff8);
 
-    memory_region_init_alias(&s->iomem_1fc, "memory-1fc",
+    memory_region_init_alias(&s->iomem_1fc, NULL, "memory-1fc",
                              &s->iomem, 0x1fc00000, 0x1000);
     memory_region_add_subregion(sysmem, 0x1fc00000, &s->iomem_1fc);
 
-    memory_region_init_alias(&s->iomem_ffc, "memory-ffc",
+    memory_region_init_alias(&s->iomem_ffc, NULL, "memory-ffc",
                              &s->iomem, 0x1fc00000, 0x1000);
     memory_region_add_subregion(sysmem, 0xffc00000, &s->iomem_ffc);
 
-    memory_region_init_io(&s->mmct_iomem, &sh7750_mmct_ops, s,
+    memory_region_init_io(&s->mmct_iomem, NULL, &sh7750_mmct_ops, s,
                           "cache-and-tlb", 0x08000000);
     memory_region_add_subregion(sysmem, 0xf0000000, &s->mmct_iomem);
 
diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c
index d213a90..c33a72f 100644
--- a/hw/sh4/sh_pci.c
+++ b/hw/sh4/sh_pci.c
@@ -125,10 +125,10 @@
                               get_system_memory(),
                               get_system_io(),
                               PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
-    memory_region_init_io(&s->memconfig_p4, &sh_pci_reg_ops, s,
+    memory_region_init_io(&s->memconfig_p4, OBJECT(s), &sh_pci_reg_ops, s,
                           "sh_pci", 0x224);
-    memory_region_init_alias(&s->memconfig_a7, "sh_pci.2", &s->memconfig_p4,
-                             0, 0x224);
+    memory_region_init_alias(&s->memconfig_a7, OBJECT(s), "sh_pci.2",
+                             &s->memconfig_p4, 0, 0x224);
     isa_mmio_setup(&s->isa, 0x40000);
     sysbus_init_mmio(dev, &s->memconfig_p4);
     sysbus_init_mmio(dev, &s->memconfig_a7);
diff --git a/hw/sh4/shix.c b/hw/sh4/shix.c
index ffac621..84dd666 100644
--- a/hw/sh4/shix.c
+++ b/hw/sh4/shix.c
@@ -59,16 +59,16 @@
 
     /* Allocate memory space */
     printf("Allocating ROM\n");
-    memory_region_init_ram(rom, "shix.rom", 0x4000);
+    memory_region_init_ram(rom, NULL, "shix.rom", 0x4000);
     vmstate_register_ram_global(rom);
     memory_region_set_readonly(rom, true);
     memory_region_add_subregion(sysmem, 0x00000000, rom);
     printf("Allocating SDRAM 1\n");
-    memory_region_init_ram(&sdram[0], "shix.sdram1", 0x01000000);
+    memory_region_init_ram(&sdram[0], NULL, "shix.sdram1", 0x01000000);
     vmstate_register_ram_global(&sdram[0]);
     memory_region_add_subregion(sysmem, 0x08000000, &sdram[0]);
     printf("Allocating SDRAM 2\n");
-    memory_region_init_ram(&sdram[1], "shix.sdram2", 0x01000000);
+    memory_region_init_ram(&sdram[1], NULL, "shix.sdram2", 0x01000000);
     vmstate_register_ram_global(&sdram[1]);
     memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]);
 
diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
index 78c77ef..5ef282f 100644
--- a/hw/sparc/leon3.c
+++ b/hw/sparc/leon3.c
@@ -147,13 +147,13 @@
         exit(1);
     }
 
-    memory_region_init_ram(ram, "leon3.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "leon3.ram", ram_size);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space_mem, 0x40000000, ram);
 
     /* Allocate BIOS */
     prom_size = 8 * 1024 * 1024; /* 8Mb */
-    memory_region_init_ram(prom, "Leon3.bios", prom_size);
+    memory_region_init_ram(prom, NULL, "Leon3.bios", prom_size);
     vmstate_register_ram_global(prom);
     memory_region_set_readonly(prom, true);
     memory_region_add_subregion(address_space_mem, 0x00000000, prom);
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 0e86ca7..90b7b60 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -582,7 +582,8 @@
 {
     IDRegState *s = FROM_SYSBUS(IDRegState, dev);
 
-    memory_region_init_ram(&s->mem, "sun4m.idreg", sizeof(idreg_data));
+    memory_region_init_ram(&s->mem, OBJECT(s),
+                           "sun4m.idreg", sizeof(idreg_data));
     vmstate_register_ram_global(&s->mem);
     memory_region_set_readonly(&s->mem, true);
     sysbus_init_mmio(dev, &s->mem);
@@ -625,7 +626,7 @@
 {
     AFXState *s = FROM_SYSBUS(AFXState, dev);
 
-    memory_region_init_ram(&s->mem, "sun4m.afx", 4);
+    memory_region_init_ram(&s->mem, OBJECT(s), "sun4m.afx", 4);
     vmstate_register_ram_global(&s->mem);
     sysbus_init_mmio(dev, &s->mem);
     return 0;
@@ -695,7 +696,7 @@
 {
     PROMState *s = FROM_SYSBUS(PROMState, dev);
 
-    memory_region_init_ram(&s->prom, "sun4m.prom", PROM_SIZE_MAX);
+    memory_region_init_ram(&s->prom, OBJECT(s), "sun4m.prom", PROM_SIZE_MAX);
     vmstate_register_ram_global(&s->prom);
     memory_region_set_readonly(&s->prom, true);
     sysbus_init_mmio(dev, &s->prom);
@@ -734,7 +735,7 @@
 {
     RamDevice *d = FROM_SYSBUS(RamDevice, dev);
 
-    memory_region_init_ram(&d->ram, "sun4m.ram", d->size);
+    memory_region_init_ram(&d->ram, OBJECT(d), "sun4m.ram", d->size);
     vmstate_register_ram_global(&d->ram);
     sysbus_init_mmio(dev, &d->ram);
     return 0;
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index a6a3b76..564c195 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -680,7 +680,7 @@
 {
     PROMState *s = FROM_SYSBUS(PROMState, dev);
 
-    memory_region_init_ram(&s->prom, "sun4u.prom", PROM_SIZE_MAX);
+    memory_region_init_ram(&s->prom, OBJECT(s), "sun4u.prom", PROM_SIZE_MAX);
     vmstate_register_ram_global(&s->prom);
     memory_region_set_readonly(&s->prom, true);
     sysbus_init_mmio(dev, &s->prom);
@@ -720,7 +720,7 @@
 {
     RamDevice *d = FROM_SYSBUS(RamDevice, dev);
 
-    memory_region_init_ram(&d->ram, "sun4u.ram", d->size);
+    memory_region_init_ram(&d->ram, OBJECT(d), "sun4u.ram", d->size);
     vmstate_register_ram_global(&d->ram);
     sysbus_init_mmio(dev, &d->ram);
     return 0;
@@ -854,7 +854,7 @@
     }
 
     for(i = 0; i < nb_nics; i++)
-        pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
+        pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL);
 
     ide_drive_get(hd, MAX_IDE_BUS);
 
diff --git a/hw/ssi/omap_spi.c b/hw/ssi/omap_spi.c
index 11403c4..0ed3b11 100644
--- a/hw/ssi/omap_spi.c
+++ b/hw/ssi/omap_spi.c
@@ -354,7 +354,7 @@
     }
     omap_mcspi_reset(s);
 
-    memory_region_init_io(&s->iomem, &omap_mcspi_ops, s, "omap.mcspi",
+    memory_region_init_io(&s->iomem, NULL, &omap_mcspi_ops, s, "omap.mcspi",
                           omap_l4_region_size(ta, 0));
     omap_l4_attach(ta, 0, &s->iomem);
 
diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
index 536c216..711a0c1 100644
--- a/hw/ssi/pl022.c
+++ b/hw/ssi/pl022.c
@@ -277,7 +277,7 @@
 {
     pl022_state *s = FROM_SYSBUS(pl022_state, dev);
 
-    memory_region_init_io(&s->iomem, &pl022_ops, s, "pl022", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &pl022_ops, s, "pl022", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     s->ssi = ssi_create_bus(&dev->qdev, "ssi");
diff --git a/hw/ssi/xilinx_spi.c b/hw/ssi/xilinx_spi.c
index f6bd3ba..7a9fd81 100644
--- a/hw/ssi/xilinx_spi.c
+++ b/hw/ssi/xilinx_spi.c
@@ -330,7 +330,8 @@
         sysbus_init_irq(dev, &s->cs_lines[i]);
     }
 
-    memory_region_init_io(&s->mmio, &spi_ops, s, "xilinx-spi", R_MAX * 4);
+    memory_region_init_io(&s->mmio, OBJECT(s), &spi_ops, s,
+                          "xilinx-spi", R_MAX * 4);
     sysbus_init_mmio(dev, &s->mmio);
 
     s->irqline = -1;
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 05a3ada..6a28746 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -663,7 +663,8 @@
         sysbus_init_irq(sbd, &s->cs_lines[i]);
     }
 
-    memory_region_init_io(&s->iomem, xsc->reg_ops, s, "spi", R_MAX*4);
+    memory_region_init_io(&s->iomem, OBJECT(s), xsc->reg_ops, s,
+                          "spi", R_MAX*4);
     sysbus_init_mmio(sbd, &s->iomem);
 
     s->irqline = -1;
@@ -685,7 +686,7 @@
     s->num_txrx_bytes = 4;
 
     xilinx_spips_realize(dev, errp);
-    memory_region_init_io(&s->mmlqspi, &lqspi_ops, s, "lqspi",
+    memory_region_init_io(&s->mmlqspi, OBJECT(s), &lqspi_ops, s, "lqspi",
                           (1 << LQSPI_ADDRESS_BITS) * 2);
     sysbus_init_mmio(sbd, &s->mmlqspi);
 
diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
index 317f5e4..d23462d 100644
--- a/hw/timer/arm_mptimer.c
+++ b/hw/timer/arm_mptimer.c
@@ -236,14 +236,14 @@
      *  * timer for core 1
      * and so on.
      */
-    memory_region_init_io(&s->iomem, &arm_thistimer_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &arm_thistimer_ops, s,
                           "arm_mptimer_timer", 0x20);
     sysbus_init_mmio(dev, &s->iomem);
     for (i = 0; i < s->num_cpu; i++) {
         TimerBlock *tb = &s->timerblock[i];
         tb->timer = qemu_new_timer_ns(vm_clock, timerblock_tick, tb);
         sysbus_init_irq(dev, &tb->irq);
-        memory_region_init_io(&tb->iomem, &timerblock_ops, tb,
+        memory_region_init_io(&tb->iomem, OBJECT(s), &timerblock_ops, tb,
                               "arm_mptimer_timerblock", 0x20);
         sysbus_init_mmio(dev, &tb->iomem);
     }
diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c
index 6449870..798a8da 100644
--- a/hw/timer/arm_timer.c
+++ b/hw/timer/arm_timer.c
@@ -284,7 +284,8 @@
     s->timer[1] = arm_timer_init(s->freq1);
     s->timer[0]->irq = qi[0];
     s->timer[1]->irq = qi[1];
-    memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &sp804_ops, s,
+                          "sp804", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     vmstate_register(&dev->qdev, -1, &vmstate_sp804, s);
     return 0;
@@ -347,7 +348,8 @@
     sysbus_init_irq(dev, &s->timer[1]->irq);
     sysbus_init_irq(dev, &s->timer[2]->irq);
 
-    memory_region_init_io(&s->iomem, &icp_pit_ops, s, "icp_pit", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &icp_pit_ops, s,
+                          "icp_pit", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
     /* This device has no state to save/restore.  The component timers will
        save themselves.  */
diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c
index ba584f4..a861049 100644
--- a/hw/timer/cadence_ttc.c
+++ b/hw/timer/cadence_ttc.c
@@ -409,7 +409,8 @@
         sysbus_init_irq(dev, &s->timer[i].irq);
     }
 
-    memory_region_init_io(&s->iomem, &cadence_ttc_ops, s, "timer", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &cadence_ttc_ops, s,
+                          "timer", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c
index 3cd9476..6dd1072 100644
--- a/hw/timer/etraxfs_timer.c
+++ b/hw/timer/etraxfs_timer.c
@@ -323,7 +323,8 @@
     sysbus_init_irq(dev, &t->irq);
     sysbus_init_irq(dev, &t->nmi);
 
-    memory_region_init_io(&t->mmio, &timer_ops, t, "etraxfs-timer", 0x5c);
+    memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t,
+                          "etraxfs-timer", 0x5c);
     sysbus_init_mmio(dev, &t->mmio);
     qemu_register_reset(etraxfs_timer_reset, t);
     return 0;
diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index 38dcc1a..28ebe5d 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -1449,8 +1449,8 @@
         sysbus_init_irq(dev, &s->l_timer[i].irq);
     }
 
-    memory_region_init_io(&s->iomem, &exynos4210_mct_ops, s, "exynos4210-mct",
-            MCT_SFR_SIZE);
+    memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_mct_ops, s,
+                          "exynos4210-mct", MCT_SFR_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c
index 185ccb9..8fa0bb2 100644
--- a/hw/timer/exynos4210_pwm.c
+++ b/hw/timer/exynos4210_pwm.c
@@ -390,8 +390,8 @@
         s->timer[i].parent = s;
     }
 
-    memory_region_init_io(&s->iomem, &exynos4210_pwm_ops, s, "exynos4210-pwm",
-            EXYNOS4210_PWM_REG_MEM_SIZE);
+    memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_pwm_ops, s,
+                          "exynos4210-pwm", EXYNOS4210_PWM_REG_MEM_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
diff --git a/hw/timer/exynos4210_rtc.c b/hw/timer/exynos4210_rtc.c
index 3ac77f9..7fca071 100644
--- a/hw/timer/exynos4210_rtc.c
+++ b/hw/timer/exynos4210_rtc.c
@@ -559,8 +559,8 @@
     sysbus_init_irq(dev, &s->alm_irq);
     sysbus_init_irq(dev, &s->tick_irq);
 
-    memory_region_init_io(&s->iomem, &exynos4210_rtc_ops, s, "exynos4210-rtc",
-            EXYNOS4210_RTC_REG_MEM_SIZE);
+    memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_rtc_ops, s,
+                          "exynos4210-rtc", EXYNOS4210_RTC_REG_MEM_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
diff --git a/hw/timer/grlib_gptimer.c b/hw/timer/grlib_gptimer.c
index 7043a34..37ba47d 100644
--- a/hw/timer/grlib_gptimer.c
+++ b/hw/timer/grlib_gptimer.c
@@ -365,7 +365,8 @@
         ptimer_set_freq(timer->ptimer, unit->freq_hz);
     }
 
-    memory_region_init_io(&unit->iomem, &grlib_gptimer_ops, unit, "gptimer",
+    memory_region_init_io(&unit->iomem, OBJECT(unit), &grlib_gptimer_ops,
+                          unit, "gptimer",
                           UNIT_REG_SIZE + GPTIMER_REG_SIZE * unit->nr_timers);
 
     sysbus_init_mmio(dev, &unit->iomem);
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index 95dd01d..90bd584 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -722,7 +722,7 @@
     qdev_init_gpio_out(&dev->qdev, &s->pit_enabled, 1);
 
     /* HPET Area */
-    memory_region_init_io(&s->iomem, &hpet_ram_ops, s, "hpet", 0x400);
+    memory_region_init_io(&s->iomem, OBJECT(s), &hpet_ram_ops, s, "hpet", 0x400);
     sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
diff --git a/hw/timer/i8254.c b/hw/timer/i8254.c
index 16c8dd6..cd52140 100644
--- a/hw/timer/i8254.c
+++ b/hw/timer/i8254.c
@@ -333,7 +333,8 @@
     s->irq_timer = qemu_new_timer_ns(vm_clock, pit_irq_timer, s);
     qdev_init_gpio_out(dev, &s->irq, 1);
 
-    memory_region_init_io(&pit->ioports, &pit_ioport_ops, pit, "pit", 4);
+    memory_region_init_io(&pit->ioports, OBJECT(pit), &pit_ioport_ops,
+                          pit, "pit", 4);
 
     qdev_init_gpio_in(dev, pit_irq_control, 1);
 
diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c
index 7cdb006..e24e0c4 100644
--- a/hw/timer/imx_epit.c
+++ b/hw/timer/imx_epit.c
@@ -396,7 +396,7 @@
     DPRINTF("\n");
 
     sysbus_init_irq(sbd, &s->irq);
-    memory_region_init_io(&s->iomem, &imx_epit_ops, s, TYPE_IMX_EPIT,
+    memory_region_init_io(&s->iomem, OBJECT(s), &imx_epit_ops, s, TYPE_IMX_EPIT,
                           0x00001000);
     sysbus_init_mmio(sbd, &s->iomem);
 
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
index de53b13..97fbebb 100644
--- a/hw/timer/imx_gpt.c
+++ b/hw/timer/imx_gpt.c
@@ -514,7 +514,7 @@
     QEMUBH *bh;
 
     sysbus_init_irq(sbd, &s->irq);
-    memory_region_init_io(&s->iomem, &imx_gpt_ops, s, TYPE_IMX_GPT,
+    memory_region_init_io(&s->iomem, OBJECT(s), &imx_gpt_ops, s, TYPE_IMX_GPT,
                           0x00001000);
     sysbus_init_mmio(sbd, &s->iomem);
 
diff --git a/hw/timer/lm32_timer.c b/hw/timer/lm32_timer.c
index e06fac7..016dade 100644
--- a/hw/timer/lm32_timer.c
+++ b/hw/timer/lm32_timer.c
@@ -180,7 +180,8 @@
     s->ptimer = ptimer_init(s->bh);
     ptimer_set_freq(s->ptimer, s->freq_hz);
 
-    memory_region_init_io(&s->iomem, &timer_ops, s, "timer", R_MAX * 4);
+    memory_region_init_io(&s->iomem, OBJECT(s), &timer_ops, s,
+                          "timer", R_MAX * 4);
     sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c
index bf6c4c8..be3490b 100644
--- a/hw/timer/m48t59.c
+++ b/hw/timer/m48t59.c
@@ -655,7 +655,8 @@
     d = FROM_SYSBUS(M48t59SysBusState, s);
     state = &d->state;
     sysbus_connect_irq(s, 0, IRQ);
-    memory_region_init_io(&d->io, &m48t59_io_ops, state, "m48t59", 4);
+    memory_region_init_io(&d->io, OBJECT(d), &m48t59_io_ops, state,
+                          "m48t59", 4);
     if (io_base != 0) {
         memory_region_add_subregion(get_system_io(), io_base, &d->io);
     }
@@ -683,7 +684,7 @@
     d = ISA_M48T59(isadev);
     s = &d->state;
 
-    memory_region_init_io(&d->io, &m48t59_io_ops, s, "m48t59", 4);
+    memory_region_init_io(&d->io, OBJECT(d), &m48t59_io_ops, s, "m48t59", 4);
     if (io_base != 0) {
         isa_register_ioport(isadev, &d->io, io_base);
     }
@@ -721,7 +722,8 @@
 
     sysbus_init_irq(dev, &s->IRQ);
 
-    memory_region_init_io(&s->iomem, &nvram_ops, s, "m48t59.nvram", s->size);
+    memory_region_init_io(&s->iomem, OBJECT(d), &nvram_ops, s,
+                          "m48t59.nvram", s->size);
     sysbus_init_mmio(dev, &s->iomem);
     m48t59_realize_common(s, &err);
     if (err != NULL) {
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 9c4a7bd..3c3baac 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -863,7 +863,7 @@
     s->suspend_notifier.notify = rtc_notify_suspend;
     qemu_register_suspend_notifier(&s->suspend_notifier);
 
-    memory_region_init_io(&s->io, &cmos_ops, s, "rtc", 2);
+    memory_region_init_io(&s->io, OBJECT(s), &cmos_ops, s, "rtc", 2);
     isa_register_ioport(isadev, &s->io, base);
 
     qdev_set_legacy_instance_id(dev, base, 3);
diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c
index e083a28..5009394 100644
--- a/hw/timer/milkymist-sysctl.c
+++ b/hw/timer/milkymist-sysctl.c
@@ -280,7 +280,7 @@
     ptimer_set_freq(s->ptimer0, s->freq_hz);
     ptimer_set_freq(s->ptimer1, s->freq_hz);
 
-    memory_region_init_io(&s->regs_region, &sysctl_mmio_ops, s,
+    memory_region_init_io(&s->regs_region, OBJECT(s), &sysctl_mmio_ops, s,
             "milkymist-sysctl", R_MAX * 4);
     sysbus_init_mmio(dev, &s->regs_region);
 
diff --git a/hw/timer/omap_gptimer.c b/hw/timer/omap_gptimer.c
index 9b0e9dd..ac389d8 100644
--- a/hw/timer/omap_gptimer.c
+++ b/hw/timer/omap_gptimer.c
@@ -480,7 +480,7 @@
     omap_gp_timer_reset(s);
     omap_gp_timer_clk_setup(s);
 
-    memory_region_init_io(&s->iomem, &omap_gp_timer_ops, s, "omap.gptimer",
+    memory_region_init_io(&s->iomem, NULL, &omap_gp_timer_ops, s, "omap.gptimer",
                           omap_l4_region_size(ta, 0));
     omap_l4_attach(ta, 0, &s->iomem);
 
diff --git a/hw/timer/omap_synctimer.c b/hw/timer/omap_synctimer.c
index a24f35c..a12aca2 100644
--- a/hw/timer/omap_synctimer.c
+++ b/hw/timer/omap_synctimer.c
@@ -94,7 +94,7 @@
     struct omap_synctimer_s *s = g_malloc0(sizeof(*s));
 
     omap_synctimer_reset(s);
-    memory_region_init_io(&s->iomem, &omap_synctimer_ops, s, "omap.synctimer",
+    memory_region_init_io(&s->iomem, NULL, &omap_synctimer_ops, s, "omap.synctimer",
                           omap_l4_region_size(ta, 0));
     omap_l4_attach(ta, 0, &s->iomem);
 
diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c
index 764940b..3ce6ed8 100644
--- a/hw/timer/pl031.c
+++ b/hw/timer/pl031.c
@@ -192,7 +192,7 @@
     pl031_state *s = FROM_SYSBUS(pl031_state, dev);
     struct tm tm;
 
-    memory_region_init_io(&s->iomem, &pl031_ops, s, "pl031", 0x1000);
+    memory_region_init_io(&s->iomem, OBJECT(s), &pl031_ops, s, "pl031", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
 
     sysbus_init_irq(dev, &s->irq);
diff --git a/hw/timer/puv3_ost.c b/hw/timer/puv3_ost.c
index 0c3d827..63f2c9f 100644
--- a/hw/timer/puv3_ost.c
+++ b/hw/timer/puv3_ost.c
@@ -122,7 +122,7 @@
     s->ptimer = ptimer_init(s->bh);
     ptimer_set_freq(s->ptimer, 50 * 1000 * 1000);
 
-    memory_region_init_io(&s->iomem, &puv3_ost_ops, s, "puv3_ost",
+    memory_region_init_io(&s->iomem, OBJECT(s), &puv3_ost_ops, s, "puv3_ost",
             PUV3_REGS_OFFSET);
     sysbus_init_mmio(dev, &s->iomem);
 
diff --git a/hw/timer/pxa2xx_timer.c b/hw/timer/pxa2xx_timer.c
index 8ea2416..4d28719 100644
--- a/hw/timer/pxa2xx_timer.c
+++ b/hw/timer/pxa2xx_timer.c
@@ -461,7 +461,7 @@
         }
     }
 
-    memory_region_init_io(&s->iomem, &pxa2xx_timer_ops, s,
+    memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_timer_ops, s,
                           "pxa2xx-timer", 0x00001000);
     sysbus_init_mmio(dev, &s->iomem);
 
diff --git a/hw/timer/sh_timer.c b/hw/timer/sh_timer.c
index f92ff4f..251a10d 100644
--- a/hw/timer/sh_timer.c
+++ b/hw/timer/sh_timer.c
@@ -319,14 +319,14 @@
         s->timer[2] = sh_timer_init(freq, timer_feat | TIMER_FEAT_CAPT,
 				    ch2_irq0); /* ch2_irq1 not supported */
 
-    memory_region_init_io(&s->iomem, &tmu012_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &tmu012_ops, s,
                           "timer", 0x100000000ULL);
 
-    memory_region_init_alias(&s->iomem_p4, "timer-p4",
+    memory_region_init_alias(&s->iomem_p4, NULL, "timer-p4",
                              &s->iomem, 0, 0x1000);
     memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4);
 
-    memory_region_init_alias(&s->iomem_a7, "timer-a7",
+    memory_region_init_alias(&s->iomem_a7, NULL, "timer-a7",
                              &s->iomem, 0, 0x1000);
     memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
     /* ??? Save/restore.  */
diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
index 1145a87..7f844d7 100644
--- a/hw/timer/slavio_timer.c
+++ b/hw/timer/slavio_timer.c
@@ -394,7 +394,7 @@
 
         size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE;
         snprintf(timer_name, sizeof(timer_name), "timer-%i", i);
-        memory_region_init_io(&tc->iomem, &slavio_timer_mem_ops, tc,
+        memory_region_init_io(&tc->iomem, OBJECT(s), &slavio_timer_mem_ops, tc,
                               timer_name, size);
         sysbus_init_mmio(dev, &tc->iomem);
 
diff --git a/hw/timer/tusb6010.c b/hw/timer/tusb6010.c
index 50edc06..47b6809 100644
--- a/hw/timer/tusb6010.c
+++ b/hw/timer/tusb6010.c
@@ -779,8 +779,8 @@
     TUSBState *s = FROM_SYSBUS(TUSBState, dev);
     s->otg_timer = qemu_new_timer_ns(vm_clock, tusb_otg_tick, s);
     s->pwr_timer = qemu_new_timer_ns(vm_clock, tusb_power_tick, s);
-    memory_region_init_io(&s->iomem[1], &tusb_async_ops, s, "tusb-async",
-                          UINT32_MAX);
+    memory_region_init_io(&s->iomem[1], OBJECT(s), &tusb_async_ops, s,
+                          "tusb-async", UINT32_MAX);
     sysbus_init_mmio(dev, &s->iomem[0]);
     sysbus_init_mmio(dev, &s->iomem[1]);
     sysbus_init_irq(dev, &s->irq);
diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
index 0c39cff..ee53834 100644
--- a/hw/timer/xilinx_timer.c
+++ b/hw/timer/xilinx_timer.c
@@ -218,7 +218,7 @@
         ptimer_set_freq(xt->ptimer, t->freq_hz);
     }
 
-    memory_region_init_io(&t->mmio, &timer_ops, t, "xlnx.xps-timer",
+    memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t, "xlnx.xps-timer",
                           R_MAX * 4 * num_timers(t));
     sysbus_init_mmio(dev, &t->mmio);
     return 0;
diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
index d4d8152..abe384b 100644
--- a/hw/tpm/tpm_tis.c
+++ b/hw/tpm/tpm_tis.c
@@ -888,7 +888,8 @@
     ISADevice *dev = ISA_DEVICE(obj);
     TPMState *s = TPM(obj);
 
-    memory_region_init_io(&s->mmio, &tpm_tis_memory_ops, s, "tpm-tis-mmio",
+    memory_region_init_io(&s->mmio, OBJECT(s), &tpm_tis_memory_ops,
+                          s, "tpm-tis-mmio",
                           TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT);
     memory_region_add_subregion(isa_address_space(dev), TPM_TIS_ADDR_BASE,
                                 &s->mmio);
diff --git a/hw/unicore32/puv3.c b/hw/unicore32/puv3.c
index 56d1afa..5ff0dc9 100644
--- a/hw/unicore32/puv3.c
+++ b/hw/unicore32/puv3.c
@@ -73,7 +73,7 @@
     MemoryRegion *ram_memory = g_new(MemoryRegion, 1);
 
     /* SDRAM at address zero.  */
-    memory_region_init_ram(ram_memory, "puv3.ram", ram_size);
+    memory_region_init_ram(ram_memory, NULL, "puv3.ram", ram_size);
     vmstate_register_ram_global(ram_memory);
     memory_region_add_subregion(get_system_memory(), 0, ram_memory);
 }
diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
index e7d4f74..54147b5 100644
--- a/hw/usb/hcd-ehci-sysbus.c
+++ b/hw/usb/hcd-ehci-sysbus.c
@@ -173,7 +173,7 @@
     FUSBH200EHCIState *f = FUSBH200_EHCI(obj);
     EHCIState *s = &i->ehci;
 
-    memory_region_init_io(&f->mem_vendor, &fusbh200_ehci_mmio_ops, s,
+    memory_region_init_io(&f->mem_vendor, OBJECT(f), &fusbh200_ehci_mmio_ops, s,
                           "fusbh200", 0x4c);
     memory_region_add_subregion(&s->mem,
                                 s->opregbase + s->portscbase + 4 * s->portnr,
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 16d6356..67e4b24 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1241,11 +1241,13 @@
 {
     uint32_t cpage, offset, bytes, plen;
     dma_addr_t page;
+    USBBus *bus = &p->queue->ehci->bus;
+    BusState *qbus = BUS(bus);
 
     cpage  = get_field(p->qtd.token, QTD_TOKEN_CPAGE);
     bytes  = get_field(p->qtd.token, QTD_TOKEN_TBYTES);
     offset = p->qtd.bufptr[0] & ~QTD_BUFPTR_MASK;
-    qemu_sglist_init(&p->sgl, 5, p->queue->ehci->as);
+    qemu_sglist_init(&p->sgl, qbus->parent, 5, p->queue->ehci->as);
 
     while (bytes > 0) {
         if (cpage > 4) {
@@ -1484,7 +1486,7 @@
                 return -1;
             }
 
-            qemu_sglist_init(&ehci->isgl, 2, ehci->as);
+            qemu_sglist_init(&ehci->isgl, DEVICE(ehci), 2, ehci->as);
             if (off + len > 4096) {
                 /* transfer crosses page border */
                 uint32_t len2 = off + len - 4096;
@@ -2551,12 +2553,12 @@
     QTAILQ_INIT(&s->pqueues);
     usb_packet_init(&s->ipacket);
 
-    memory_region_init(&s->mem, "ehci", MMIO_SIZE);
-    memory_region_init_io(&s->mem_caps, &ehci_mmio_caps_ops, s,
+    memory_region_init(&s->mem, OBJECT(dev), "ehci", MMIO_SIZE);
+    memory_region_init_io(&s->mem_caps, OBJECT(dev), &ehci_mmio_caps_ops, s,
                           "capabilities", CAPA_SIZE);
-    memory_region_init_io(&s->mem_opreg, &ehci_mmio_opreg_ops, s,
+    memory_region_init_io(&s->mem_opreg, OBJECT(dev), &ehci_mmio_opreg_ops, s,
                           "operational", s->portscbase);
-    memory_region_init_io(&s->mem_ports, &ehci_mmio_port_ops, s,
+    memory_region_init_io(&s->mem_ports, OBJECT(dev), &ehci_mmio_port_ops, s,
                           "ports", 4 * s->portnr);
 
     memory_region_add_subregion(&s->mem, s->capsbase, &s->mem_caps);
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 5513924..a096ecf 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -1830,7 +1830,8 @@
         }
     }
 
-    memory_region_init_io(&ohci->mem, &ohci_mem_ops, ohci, "ohci", 256);
+    memory_region_init_io(&ohci->mem, OBJECT(dev), &ohci_mem_ops,
+                          ohci, "ohci", 256);
     ohci->localmem_base = localmem_base;
 
     ohci->name = object_get_typename(OBJECT(dev));
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index c85b203..066072e 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -1259,7 +1259,9 @@
 
     qemu_register_reset(uhci_reset, s);
 
-    memory_region_init_io(&s->io_bar, &uhci_ioport_ops, s, "uhci", 0x20);
+    memory_region_init_io(&s->io_bar, OBJECT(s), &uhci_ioport_ops, s,
+                          "uhci", 0x20);
+
     /* Use region 4 for consistency with real hardware.  BSD guests seem
        to rely on this.  */
     pci_register_bar(&s->dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 91633ed..d7a54fd 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -3342,14 +3342,14 @@
 
     xhci->irq = xhci->pci_dev.irq[0];
 
-    memory_region_init(&xhci->mem, "xhci", LEN_REGS);
-    memory_region_init_io(&xhci->mem_cap, &xhci_cap_ops, xhci,
+    memory_region_init(&xhci->mem, OBJECT(xhci), "xhci", LEN_REGS);
+    memory_region_init_io(&xhci->mem_cap, OBJECT(xhci), &xhci_cap_ops, xhci,
                           "capabilities", LEN_CAP);
-    memory_region_init_io(&xhci->mem_oper, &xhci_oper_ops, xhci,
+    memory_region_init_io(&xhci->mem_oper, OBJECT(xhci), &xhci_oper_ops, xhci,
                           "operational", 0x400);
-    memory_region_init_io(&xhci->mem_runtime, &xhci_runtime_ops, xhci,
+    memory_region_init_io(&xhci->mem_runtime, OBJECT(xhci), &xhci_runtime_ops, xhci,
                           "runtime", LEN_RUNTIME);
-    memory_region_init_io(&xhci->mem_doorbell, &xhci_doorbell_ops, xhci,
+    memory_region_init_io(&xhci->mem_doorbell, OBJECT(xhci), &xhci_doorbell_ops, xhci,
                           "doorbell", LEN_DOORBELL);
 
     memory_region_add_subregion(&xhci->mem, 0,            &xhci->mem_cap);
@@ -3361,7 +3361,7 @@
         XHCIPort *port = &xhci->ports[i];
         uint32_t offset = OFF_OPER + 0x400 + 0x10 * i;
         port->xhci = xhci;
-        memory_region_init_io(&port->mem, &xhci_port_ops, port,
+        memory_region_init_io(&port->mem, OBJECT(xhci), &xhci_port_ops, port,
                               port->name, 0x10);
         memory_region_add_subregion(&xhci->mem, offset, &port->mem);
     }
diff --git a/hw/virtio/dataplane/hostmem.c b/hw/virtio/dataplane/hostmem.c
index 7e46723..901d98b 100644
--- a/hw/virtio/dataplane/hostmem.c
+++ b/hw/virtio/dataplane/hostmem.c
@@ -64,8 +64,12 @@
 static void hostmem_listener_commit(MemoryListener *listener)
 {
     HostMem *hostmem = container_of(listener, HostMem, listener);
+    int i;
 
     qemu_mutex_lock(&hostmem->current_regions_lock);
+    for (i = 0; i < hostmem->num_current_regions; i++) {
+        memory_region_unref(hostmem->current_regions[i].mr);
+    }
     g_free(hostmem->current_regions);
     hostmem->current_regions = hostmem->new_regions;
     hostmem->num_current_regions = hostmem->num_new_regions;
@@ -92,8 +96,11 @@
         .guest_addr = section->offset_within_address_space,
         .size = int128_get64(section->size),
         .readonly = section->readonly,
+        .mr = section->mr,
     };
     hostmem->num_new_regions++;
+
+    memory_region_ref(section->mr);
 }
 
 static void hostmem_listener_append_region(MemoryListener *listener,
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index baf84ea..8f6ab13 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -16,6 +16,7 @@
 #include <sys/ioctl.h>
 #include "hw/virtio/vhost.h"
 #include "hw/hw.h"
+#include "qemu/atomic.h"
 #include "qemu/range.h"
 #include <linux/vhost.h>
 #include "exec/address-spaces.h"
@@ -47,11 +48,9 @@
             addr += VHOST_LOG_CHUNK;
             continue;
         }
-        /* Data must be read atomically. We don't really
-         * need the barrier semantics of __sync
-         * builtins, but it's easier to use them than
-         * roll our own. */
-        log = __sync_fetch_and_and(from, 0);
+        /* Data must be read atomically. We don't really need barrier semantics
+         * but it's easier to use atomic_* than roll our own. */
+        log = atomic_xchg(from, 0);
         while ((bit = sizeof(log) > sizeof(int) ?
                 ffsll(log) : ffs(log))) {
             hwaddr page_addr;
@@ -497,6 +496,7 @@
     dev->mem_sections = g_renew(MemoryRegionSection, dev->mem_sections,
                                 dev->n_mem_sections);
     dev->mem_sections[dev->n_mem_sections - 1] = *section;
+    memory_region_ref(section->mr);
     vhost_set_memory(listener, section, true);
 }
 
@@ -512,6 +512,7 @@
     }
 
     vhost_set_memory(listener, section, false);
+    memory_region_unref(section->mr);
     for (i = 0; i < dev->n_mem_sections; ++i) {
         if (dev->mem_sections[i].offset_within_address_space
             == section->offset_within_address_space) {
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index a27051c..3fa72a9 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -205,6 +205,7 @@
             addr = section.offset_within_region;
             balloon_page(memory_region_get_ram_ptr(section.mr) + addr,
                          !!(vq == s->dvq));
+            memory_region_unref(section.mr);
         }
 
         virtqueue_push(vq, &elem, offset);
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index b070b64..c38cfd1 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -966,8 +966,8 @@
         size = 1 << qemu_fls(size);
     }
 
-    memory_region_init_io(&proxy->bar, &virtio_pci_config_ops, proxy,
-                          "virtio-pci", size);
+    memory_region_init_io(&proxy->bar, OBJECT(proxy), &virtio_pci_config_ops,
+                          proxy, "virtio-pci", size);
     pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO,
                      &proxy->bar);
 
diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c
index 05af0b1..85aebc2 100644
--- a/hw/watchdog/wdt_i6300esb.c
+++ b/hw/watchdog/wdt_i6300esb.c
@@ -417,7 +417,8 @@
     d->timer = qemu_new_timer_ns(vm_clock, i6300esb_timer_expired, d);
     d->previous_reboot_flag = 0;
 
-    memory_region_init_io(&d->io_mem, &i6300esb_ops, d, "i6300esb", 0x10);
+    memory_region_init_io(&d->io_mem, OBJECT(d), &i6300esb_ops, d,
+                          "i6300esb", 0x10);
     pci_register_bar(&d->dev, 0, 0, &d->io_mem);
     /* qemu_register_coalesced_mmio (addr, 0x10); ? */
 
diff --git a/hw/watchdog/wdt_ib700.c b/hw/watchdog/wdt_ib700.c
index d85c894..c788554 100644
--- a/hw/watchdog/wdt_ib700.c
+++ b/hw/watchdog/wdt_ib700.c
@@ -97,15 +97,23 @@
     }
 };
 
+static const MemoryRegionPortio wdt_portio_list[] = {
+    { 0x441, 2, 1, .write = ib700_write_disable_reg, },
+    { 0x443, 2, 1, .write = ib700_write_enable_reg, },
+    PORTIO_END_OF_LIST(),
+};
+
 static void wdt_ib700_realize(DeviceState *dev, Error **errp)
 {
     IB700State *s = IB700(dev);
+    PortioList *port_list = g_new(PortioList, 1);
 
     ib700_debug("watchdog init\n");
 
     s->timer = qemu_new_timer_ns(vm_clock, ib700_timer_expired, s);
-    register_ioport_write(0x441, 2, 1, ib700_write_disable_reg, s);
-    register_ioport_write(0x443, 2, 1, ib700_write_enable_reg, s);
+
+    portio_list_init(port_list, OBJECT(s), wdt_portio_list, s, "ib700");
+    portio_list_add(port_list, isa_address_space_io(&s->parent_obj), 0);
 }
 
 static void wdt_ib700_reset(DeviceState *dev)
diff --git a/hw/xen/xen_apic.c b/hw/xen/xen_apic.c
index a958782..9f91e0f 100644
--- a/hw/xen/xen_apic.c
+++ b/hw/xen/xen_apic.c
@@ -38,8 +38,8 @@
 
 static void xen_apic_init(APICCommonState *s)
 {
-    memory_region_init_io(&s->io_memory, &xen_apic_io_ops, s, "xen-apic-msi",
-                          APIC_SPACE_SIZE);
+    memory_region_init_io(&s->io_memory, OBJECT(s), &xen_apic_io_ops, s,
+                          "xen-apic-msi", APIC_SPACE_SIZE);
 
 #if defined(CONFIG_XEN_CTRL_INTERFACE_VERSION) \
     && CONFIG_XEN_CTRL_INTERFACE_VERSION >= 420
diff --git a/hw/xen/xen_platform.c b/hw/xen/xen_platform.c
index b6c6793..15d7cf0 100644
--- a/hw/xen/xen_platform.c
+++ b/hw/xen/xen_platform.c
@@ -262,16 +262,20 @@
 static const MemoryRegionOps platform_fixed_io_ops = {
     .read = platform_fixed_ioport_read,
     .write = platform_fixed_ioport_write,
+    .valid = {
+        .unaligned = true,
+    },
     .impl = {
         .min_access_size = 1,
         .max_access_size = 4,
+        .unaligned = true,
     },
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static void platform_fixed_ioport_init(PCIXenPlatformState* s)
 {
-    memory_region_init_io(&s->fixed_io, &platform_fixed_io_ops, s,
+    memory_region_init_io(&s->fixed_io, OBJECT(s), &platform_fixed_io_ops, s,
                           "xen-fixed", 16);
     memory_region_add_subregion(get_system_io(), XEN_PLATFORM_IOPORT,
                                 &s->fixed_io);
@@ -315,7 +319,8 @@
 
 static void platform_ioport_bar_setup(PCIXenPlatformState *d)
 {
-    memory_region_init_io(&d->bar, &xen_pci_io_ops, d, "xen-pci", 0x100);
+    memory_region_init_io(&d->bar, OBJECT(d), &xen_pci_io_ops, d,
+                          "xen-pci", 0x100);
 }
 
 static uint64_t platform_mmio_read(void *opaque, hwaddr addr,
@@ -343,7 +348,7 @@
 
 static void platform_mmio_setup(PCIXenPlatformState *d)
 {
-    memory_region_init_io(&d->mmio_bar, &platform_mmio_handler, d,
+    memory_region_init_io(&d->mmio_bar, OBJECT(d), &platform_mmio_handler, d,
                           "xen-mmio", 0x1000000);
 }
 
diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
index c31a28a..d7ee774 100644
--- a/hw/xen/xen_pt.c
+++ b/hw/xen/xen_pt.c
@@ -416,7 +416,7 @@
             }
         }
 
-        memory_region_init_io(&s->bar[i], &ops, &s->dev,
+        memory_region_init_io(&s->bar[i], OBJECT(s), &ops, &s->dev,
                               "xen-pci-pt-bar", r->size);
         pci_register_bar(&s->dev, i, type, &s->bar[i]);
 
@@ -440,7 +440,7 @@
 
         s->bases[PCI_ROM_SLOT].access.maddr = d->rom.base_addr;
 
-        memory_region_init_rom_device(&s->rom, NULL, NULL,
+        memory_region_init_rom_device(&s->rom, OBJECT(s), NULL, NULL,
                                       "xen-pci-pt-rom", d->rom.size);
         pci_register_bar(&s->dev, PCI_ROM_SLOT, PCI_BASE_ADDRESS_MEM_PREFETCH,
                          &s->rom);
@@ -606,6 +606,7 @@
     XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState,
                                              memory_listener);
 
+    memory_region_ref(sec->mr);
     xen_pt_region_update(s, sec, true);
 }
 
@@ -615,6 +616,7 @@
                                              memory_listener);
 
     xen_pt_region_update(s, sec, false);
+    memory_region_unref(sec->mr);
 }
 
 static void xen_pt_io_region_add(MemoryListener *l, MemoryRegionSection *sec)
@@ -622,6 +624,7 @@
     XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState,
                                              io_listener);
 
+    memory_region_ref(sec->mr);
     xen_pt_region_update(s, sec, true);
 }
 
@@ -631,6 +634,7 @@
                                              io_listener);
 
     xen_pt_region_update(s, sec, false);
+    memory_region_unref(sec->mr);
 }
 
 static const MemoryListener xen_pt_memory_listener = {
diff --git a/hw/xen/xen_pt_msi.c b/hw/xen/xen_pt_msi.c
index db2c842..6fbe0cc 100644
--- a/hw/xen/xen_pt_msi.c
+++ b/hw/xen/xen_pt_msi.c
@@ -544,7 +544,8 @@
         msix->msix_entry[i].pirq = XEN_PT_UNASSIGNED_PIRQ;
     }
 
-    memory_region_init_io(&msix->mmio, &pci_msix_ops, s, "xen-pci-pt-msix",
+    memory_region_init_io(&msix->mmio, OBJECT(s), &pci_msix_ops,
+                          s, "xen-pci-pt-msix",
                           (total_entries * PCI_MSIX_ENTRY_SIZE
                            + XC_PAGE_SIZE - 1)
                           & XC_PAGE_MASK);
diff --git a/hw/xtensa/xtensa_lx60.c b/hw/xtensa/xtensa_lx60.c
index 650dd31..075daf1 100644
--- a/hw/xtensa/xtensa_lx60.c
+++ b/hw/xtensa/xtensa_lx60.c
@@ -109,7 +109,7 @@
 {
     Lx60FpgaState *s = g_malloc(sizeof(Lx60FpgaState));
 
-    memory_region_init_io(&s->iomem, &lx60_fpga_ops, s,
+    memory_region_init_io(&s->iomem, NULL, &lx60_fpga_ops, s,
             "lx60.fpga", 0x10000);
     memory_region_add_subregion(address_space, base, &s->iomem);
     lx60_fpga_reset(s);
@@ -139,7 +139,7 @@
             sysbus_mmio_get_region(s, 1));
 
     ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, "open_eth.ram", 16384);
+    memory_region_init_ram(ram, OBJECT(s), "open_eth.ram", 16384);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(address_space, buffers, ram);
 }
@@ -195,12 +195,12 @@
     }
 
     ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, "lx60.dram", args->ram_size);
+    memory_region_init_ram(ram, NULL, "lx60.dram", args->ram_size);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(system_memory, 0, ram);
 
     system_io = g_malloc(sizeof(*system_io));
-    memory_region_init(system_io, "lx60.io", 224 * 1024 * 1024);
+    memory_region_init(system_io, NULL, "lx60.io", 224 * 1024 * 1024);
     memory_region_add_subregion(system_memory, 0xf0000000, system_io);
     lx60_fpga_init(system_io, 0x0d020000);
     if (nd_table[0].used) {
@@ -231,7 +231,7 @@
     /* Use presence of kernel file name as 'boot from SRAM' switch. */
     if (kernel_filename) {
         rom = g_malloc(sizeof(*rom));
-        memory_region_init_ram(rom, "lx60.sram", board->sram_size);
+        memory_region_init_ram(rom, NULL, "lx60.sram", board->sram_size);
         vmstate_register_ram_global(rom);
         memory_region_add_subregion(system_memory, 0xfe000000, rom);
 
@@ -262,7 +262,7 @@
             MemoryRegion *flash_mr = pflash_cfi01_get_memory(flash);
             MemoryRegion *flash_io = g_malloc(sizeof(*flash_io));
 
-            memory_region_init_alias(flash_io, "lx60.flash",
+            memory_region_init_alias(flash_io, NULL, "lx60.flash",
                     flash_mr, 0, board->flash_size);
             memory_region_add_subregion(system_memory, 0xfe000000,
                     flash_io);
diff --git a/hw/xtensa/xtensa_sim.c b/hw/xtensa/xtensa_sim.c
index 5241f8d..a88707e 100644
--- a/hw/xtensa/xtensa_sim.c
+++ b/hw/xtensa/xtensa_sim.c
@@ -75,12 +75,12 @@
     }
 
     ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, "xtensa.sram", ram_size);
+    memory_region_init_ram(ram, NULL, "xtensa.sram", ram_size);
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(get_system_memory(), 0, ram);
 
     rom = g_malloc(sizeof(*rom));
-    memory_region_init_ram(rom, "xtensa.rom", 0x1000);
+    memory_region_init_ram(rom, NULL, "xtensa.rom", 0x1000);
     vmstate_register_ram_global(rom);
     memory_region_add_subregion(get_system_memory(), 0xfe000000, rom);
 
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 35bdf85..e791c05 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -447,7 +447,6 @@
 
 /* memory API */
 
-extern int phys_ram_fd;
 extern ram_addr_t ram_size;
 
 /* RAM is pre-allocated and passed into qemu_ram_alloc_from_ptr */
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index 5240ae2..e4996e1 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -52,8 +52,7 @@
 
 void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
 /* This should not be used by devices.  */
-int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr);
-ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);
+MemoryRegion *qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr);
 void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev);
 
 void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
diff --git a/include/exec/ioport.h b/include/exec/ioport.h
index fc28350..bdd4e96 100644
--- a/include/exec/ioport.h
+++ b/include/exec/ioport.h
@@ -25,7 +25,8 @@
 #define IOPORT_H
 
 #include "qemu-common.h"
-#include "exec/iorange.h"
+#include "qom/object.h"
+#include "exec/memory.h"
 
 typedef uint32_t pio_addr_t;
 #define FMT_pioaddr     PRIx32
@@ -33,18 +34,16 @@
 #define MAX_IOPORTS     (64 * 1024)
 #define IOPORTS_MASK    (MAX_IOPORTS - 1)
 
-/* These should really be in isa.h, but are here to make pc.h happy.  */
-typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data);
-typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address);
-typedef void (IOPortDestructor)(void *opaque);
+typedef struct MemoryRegionPortio {
+    uint32_t offset;
+    uint32_t len;
+    unsigned size;
+    uint32_t (*read)(void *opaque, uint32_t address);
+    void (*write)(void *opaque, uint32_t address, uint32_t data);
+    uint32_t base; /* private field */
+} MemoryRegionPortio;
 
-void ioport_register(IORange *iorange);
-int register_ioport_read(pio_addr_t start, int length, int size,
-                         IOPortReadFunc *func, void *opaque);
-int register_ioport_write(pio_addr_t start, int length, int size,
-                          IOPortWriteFunc *func, void *opaque);
-void isa_unassign_ioport(pio_addr_t start, int length);
-bool isa_is_ioport_assigned(pio_addr_t start);
+#define PORTIO_END_OF_LIST() { }
 
 void cpu_outb(pio_addr_t addr, uint8_t val);
 void cpu_outw(pio_addr_t addr, uint16_t val);
@@ -53,20 +52,17 @@
 uint16_t cpu_inw(pio_addr_t addr);
 uint32_t cpu_inl(pio_addr_t addr);
 
-struct MemoryRegion;
-struct MemoryRegionPortio;
-
 typedef struct PortioList {
     const struct MemoryRegionPortio *ports;
+    Object *owner;
     struct MemoryRegion *address_space;
     unsigned nr;
     struct MemoryRegion **regions;
-    struct MemoryRegion **aliases;
     void *opaque;
     const char *name;
 } PortioList;
 
-void portio_list_init(PortioList *piolist,
+void portio_list_init(PortioList *piolist, Object *owner,
                       const struct MemoryRegionPortio *callbacks,
                       void *opaque, const char *name);
 void portio_list_destroy(PortioList *piolist);
diff --git a/include/exec/iorange.h b/include/exec/iorange.h
deleted file mode 100644
index cd980a8..0000000
--- a/include/exec/iorange.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef IORANGE_H
-#define IORANGE_H
-
-#include <stdint.h>
-
-typedef struct IORange IORange;
-typedef struct IORangeOps IORangeOps;
-
-struct IORangeOps {
-    void (*read)(IORange *iorange, uint64_t offset, unsigned width,
-                 uint64_t *data);
-    void (*write)(IORange *iorange, uint64_t offset, unsigned width,
-                  uint64_t data);
-    void (*destructor)(IORange *iorange);
-};
-
-struct IORange {
-    const IORangeOps *ops;
-    uint64_t base;
-    uint64_t len;
-};
-
-static inline void iorange_init(IORange *iorange, const IORangeOps *ops,
-                                uint64_t base, uint64_t len)
-{
-    iorange->ops = ops;
-    iorange->base = base;
-    iorange->len = len;
-}
-
-#endif
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index 26689fe..d0e0633 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -119,8 +119,6 @@
 void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
                                      int dirty_flags);
 
-extern const IORangeOps memory_region_iorange_ops;
-
 #endif
 
 #endif
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 2ddc3c5..ebe0d24 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -24,8 +24,6 @@
 #include "exec/hwaddr.h"
 #endif
 #include "qemu/queue.h"
-#include "exec/iorange.h"
-#include "exec/ioport.h"
 #include "qemu/int128.h"
 #include "qemu/notify.h"
 
@@ -33,7 +31,6 @@
 #define MAX_PHYS_ADDR            (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1)
 
 typedef struct MemoryRegionOps MemoryRegionOps;
-typedef struct MemoryRegionPortio MemoryRegionPortio;
 typedef struct MemoryRegionMmio MemoryRegionMmio;
 
 /* Must match *_DIRTY_FLAGS in cpu-all.h.  To be replaced with dynamic
@@ -48,14 +45,6 @@
     CPUWriteMemoryFunc *write[3];
 };
 
-/* Internal use; thunks between old-style IORange and MemoryRegions. */
-typedef struct MemoryRegionIORange MemoryRegionIORange;
-struct MemoryRegionIORange {
-    IORange iorange;
-    MemoryRegion *mr;
-    hwaddr offset;
-};
-
 typedef struct IOMMUTLBEntry IOMMUTLBEntry;
 
 /* See address_space_translate: bit 0 is read, bit 1 is write.  */
@@ -126,10 +115,6 @@
          bool unaligned;
     } impl;
 
-    /* If .read and .write are not present, old_portio may be used for
-     * backwards compatibility with old portio registration
-     */
-    const MemoryRegionPortio *old_portio;
     /* If .read and .write are not present, old_mmio may be used for
      * backwards compatibility with old mmio registration
      */
@@ -151,6 +136,7 @@
     const MemoryRegionOps *ops;
     const MemoryRegionIOMMUOps *iommu_ops;
     void *opaque;
+    struct Object *owner;
     MemoryRegion *parent;
     Int128 size;
     hwaddr addr;
@@ -179,50 +165,6 @@
     NotifierList iommu_notify;
 };
 
-struct MemoryRegionPortio {
-    uint32_t offset;
-    uint32_t len;
-    unsigned size;
-    IOPortReadFunc *read;
-    IOPortWriteFunc *write;
-};
-
-#define PORTIO_END_OF_LIST() { }
-
-/**
- * AddressSpace: describes a mapping of addresses to #MemoryRegion objects
- */
-struct AddressSpace {
-    /* All fields are private. */
-    char *name;
-    MemoryRegion *root;
-    struct FlatView *current_map;
-    int ioeventfd_nb;
-    struct MemoryRegionIoeventfd *ioeventfds;
-    struct AddressSpaceDispatch *dispatch;
-    QTAILQ_ENTRY(AddressSpace) address_spaces_link;
-};
-
-/**
- * MemoryRegionSection: describes a fragment of a #MemoryRegion
- *
- * @mr: the region, or %NULL if empty
- * @address_space: the address space the region is mapped in
- * @offset_within_region: the beginning of the section, relative to @mr's start
- * @size: the size of the section; will not exceed @mr's boundaries
- * @offset_within_address_space: the address of the first byte of the section
- *     relative to the region's address space
- * @readonly: writes to this section are ignored
- */
-struct MemoryRegionSection {
-    MemoryRegion *mr;
-    AddressSpace *address_space;
-    hwaddr offset_within_region;
-    Int128 size;
-    hwaddr offset_within_address_space;
-    bool readonly;
-};
-
 typedef struct MemoryListener MemoryListener;
 
 /**
@@ -257,18 +199,87 @@
 };
 
 /**
+ * AddressSpace: describes a mapping of addresses to #MemoryRegion objects
+ */
+struct AddressSpace {
+    /* All fields are private. */
+    char *name;
+    MemoryRegion *root;
+    struct FlatView *current_map;
+    int ioeventfd_nb;
+    struct MemoryRegionIoeventfd *ioeventfds;
+    struct AddressSpaceDispatch *dispatch;
+    struct AddressSpaceDispatch *next_dispatch;
+    MemoryListener dispatch_listener;
+
+    QTAILQ_ENTRY(AddressSpace) address_spaces_link;
+};
+
+/**
+ * MemoryRegionSection: describes a fragment of a #MemoryRegion
+ *
+ * @mr: the region, or %NULL if empty
+ * @address_space: the address space the region is mapped in
+ * @offset_within_region: the beginning of the section, relative to @mr's start
+ * @size: the size of the section; will not exceed @mr's boundaries
+ * @offset_within_address_space: the address of the first byte of the section
+ *     relative to the region's address space
+ * @readonly: writes to this section are ignored
+ */
+struct MemoryRegionSection {
+    MemoryRegion *mr;
+    AddressSpace *address_space;
+    hwaddr offset_within_region;
+    Int128 size;
+    hwaddr offset_within_address_space;
+    bool readonly;
+};
+
+/**
  * memory_region_init: Initialize a memory region
  *
  * The region typically acts as a container for other memory regions.  Use
  * memory_region_add_subregion() to add subregions.
  *
  * @mr: the #MemoryRegion to be initialized
+ * @owner: the object that tracks the region's reference count
  * @name: used for debugging; not visible to the user or ABI
  * @size: size of the region; any subregions beyond this size will be clipped
  */
 void memory_region_init(MemoryRegion *mr,
+                        struct Object *owner,
                         const char *name,
                         uint64_t size);
+
+/**
+ * memory_region_ref: Add 1 to a memory region's reference count
+ *
+ * Whenever memory regions are accessed outside the BQL, they need to be
+ * preserved against hot-unplug.  MemoryRegions actually do not have their
+ * own reference count; they piggyback on a QOM object, their "owner".
+ * This function adds a reference to the owner.
+ *
+ * All MemoryRegions must have an owner if they can disappear, even if the
+ * device they belong to operates exclusively under the BQL.  This is because
+ * the region could be returned at any time by memory_region_find, and this
+ * is usually under guest control.
+ *
+ * @mr: the #MemoryRegion
+ */
+void memory_region_ref(MemoryRegion *mr);
+
+/**
+ * memory_region_unref: Remove 1 to a memory region's reference count
+ *
+ * Whenever memory regions are accessed outside the BQL, they need to be
+ * preserved against hot-unplug.  MemoryRegions actually do not have their
+ * own reference count; they piggyback on a QOM object, their "owner".
+ * This function removes a reference to the owner and possibly destroys it.
+ *
+ * @mr: the #MemoryRegion
+ */
+void memory_region_unref(MemoryRegion *mr);
+
 /**
  * memory_region_init_io: Initialize an I/O memory region.
  *
@@ -276,6 +287,7 @@
  * if @size is nonzero, subregions will be clipped to @size.
  *
  * @mr: the #MemoryRegion to be initialized.
+ * @owner: the object that tracks the region's reference count
  * @ops: a structure containing read and write callbacks to be used when
  *       I/O is performed on the region.
  * @opaque: passed to to the read and write callbacks of the @ops structure.
@@ -283,6 +295,7 @@
  * @size: size of the region.
  */
 void memory_region_init_io(MemoryRegion *mr,
+                           struct Object *owner,
                            const MemoryRegionOps *ops,
                            void *opaque,
                            const char *name,
@@ -293,10 +306,12 @@
  *                          region will modify memory directly.
  *
  * @mr: the #MemoryRegion to be initialized.
+ * @owner: the object that tracks the region's reference count
  * @name: the name of the region.
  * @size: size of the region.
  */
 void memory_region_init_ram(MemoryRegion *mr,
+                            struct Object *owner,
                             const char *name,
                             uint64_t size);
 
@@ -306,11 +321,13 @@
  *                              region will modify memory directly.
  *
  * @mr: the #MemoryRegion to be initialized.
+ * @owner: the object that tracks the region's reference count
  * @name: the name of the region.
  * @size: size of the region.
  * @ptr: memory to be mapped; must contain at least @size bytes.
  */
 void memory_region_init_ram_ptr(MemoryRegion *mr,
+                                struct Object *owner,
                                 const char *name,
                                 uint64_t size,
                                 void *ptr);
@@ -320,6 +337,7 @@
  *                           part of another memory region.
  *
  * @mr: the #MemoryRegion to be initialized.
+ * @owner: the object that tracks the region's reference count
  * @name: used for debugging; not visible to the user or ABI
  * @orig: the region to be referenced; @mr will be equivalent to
  *        @orig between @offset and @offset + @size - 1.
@@ -327,6 +345,7 @@
  * @size: size of the region.
  */
 void memory_region_init_alias(MemoryRegion *mr,
+                              struct Object *owner,
                               const char *name,
                               MemoryRegion *orig,
                               hwaddr offset,
@@ -337,11 +356,13 @@
  *                                 handled via callbacks.
  *
  * @mr: the #MemoryRegion to be initialized.
+ * @owner: the object that tracks the region's reference count
  * @ops: callbacks for write access handling.
  * @name: the name of the region.
  * @size: size of the region.
  */
 void memory_region_init_rom_device(MemoryRegion *mr,
+                                   struct Object *owner,
                                    const MemoryRegionOps *ops,
                                    void *opaque,
                                    const char *name,
@@ -356,10 +377,12 @@
  * the memory API will cause an abort().
  *
  * @mr: the #MemoryRegion to be initialized
+ * @owner: the object that tracks the region's reference count
  * @name: used for debugging; not visible to the user or ABI
  * @size: size of the region.
  */
 void memory_region_init_reservation(MemoryRegion *mr,
+                                    struct Object *owner,
                                     const char *name,
                                     uint64_t size);
 
@@ -371,11 +394,13 @@
  * memory region.
  *
  * @mr: the #MemoryRegion to be initialized
+ * @owner: the object that tracks the region's reference count
  * @ops: a function that translates addresses into the @target region
  * @name: used for debugging; not visible to the user or ABI
  * @size: size of the region.
  */
 void memory_region_init_iommu(MemoryRegion *mr,
+                              struct Object *owner,
                               const MemoryRegionIOMMUOps *ops,
                               const char *name,
                               uint64_t size);
@@ -390,6 +415,13 @@
 void memory_region_destroy(MemoryRegion *mr);
 
 /**
+ * memory_region_owner: get a memory region's owner.
+ *
+ * @mr: the memory region being queried.
+ */
+struct Object *memory_region_owner(MemoryRegion *mr);
+
+/**
  * memory_region_size: get a memory region's size.
  *
  * @mr: the memory region being queried.
@@ -808,6 +840,18 @@
                                     hwaddr offset);
 
 /**
+ * memory_region_present: translate an address/size relative to a
+ * MemoryRegion into a #MemoryRegionSection.
+ *
+ * Answer whether a #MemoryRegion within @parent covers the address
+ * @addr.
+ *
+ * @parent: a MemoryRegion within which @addr is a relative address
+ * @addr: the area within @parent to be searched
+ */
+bool memory_region_present(MemoryRegion *parent, hwaddr addr);
+
+/**
  * memory_region_find: translate an address/size relative to a
  * MemoryRegion into a #MemoryRegionSection.
  *
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index a417402..61ff154 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -3,14 +3,26 @@
 
 #include "qemu-common.h"
 #include "exec/memory.h"
-#include "exec/ioport.h"
 #include "hw/isa/isa.h"
 #include "hw/block/fdc.h"
 #include "net/net.h"
 #include "hw/i386/ioapic.h"
 
+#include "qemu/range.h"
+
 /* PC-style peripherals (also used by other machines).  */
 
+typedef struct PcPciInfo {
+    Range w32;
+    Range w64;
+} PcPciInfo;
+
+struct PcGuestInfo {
+    PcPciInfo pci_info;
+    bool has_pci_info;
+    FWCfgState *fw_cfg;
+};
+
 /* parallel.c */
 static inline bool parallel_init(ISABus *bus, int index, CharDriverState *chr)
 {
@@ -56,11 +68,14 @@
 void gsi_handler(void *opaque, int n, int level);
 
 /* vmport.c */
+typedef uint32_t (VMPortReadFunc)(void *opaque, uint32_t address);
+
 static inline void vmport_init(ISABus *bus)
 {
     isa_create_simple(bus, "vmport");
 }
-void vmport_register(unsigned char command, IOPortReadFunc *func, void *opaque);
+
+void vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque);
 void vmmouse_get_data(uint32_t *data);
 void vmmouse_set_data(const uint32_t *data);
 
@@ -82,6 +97,10 @@
 void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge);
 void pc_hot_add_cpu(const int64_t id, Error **errp);
 void pc_acpi_init(const char *default_dsdt);
+
+PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
+                                ram_addr_t above_4g_mem_size);
+
 FWCfgState *pc_memory_init(MemoryRegion *system_memory,
                            const char *kernel_filename,
                            const char *kernel_cmdline,
@@ -89,7 +108,8 @@
                            ram_addr_t below_4g_mem_size,
                            ram_addr_t above_4g_mem_size,
                            MemoryRegion *rom_memory,
-                           MemoryRegion **ram_memory);
+                           MemoryRegion **ram_memory,
+                           PcGuestInfo *guest_info);
 qemu_irq *pc_allocate_cpu_irq(void);
 DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus);
 void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
@@ -175,7 +195,7 @@
 void pc_system_firmware_init(MemoryRegion *rom_memory);
 
 /* pvpanic.c */
-int pvpanic_init(ISABus *bus);
+void pvpanic_init(ISABus *bus);
 
 /* e820 types */
 #define E820_RAM        1
diff --git a/include/hw/pci-host/pam.h b/include/hw/pci-host/pam.h
index 8e9e349..a8b87b8 100644
--- a/include/hw/pci-host/pam.h
+++ b/include/hw/pci-host/pam.h
@@ -90,8 +90,8 @@
                   uint8_t smm_enabled);
 void smram_set_smm(uint8_t *host_smm_enabled, int smm, uint8_t smram,
                    MemoryRegion *smram_region);
-void init_pam(MemoryRegion *ram, MemoryRegion *system, MemoryRegion *pci,
-              PAMMemoryRegion *mem, uint32_t start, uint32_t size);
+void init_pam(DeviceState *dev, MemoryRegion *ram, MemoryRegion *system,
+              MemoryRegion *pci, PAMMemoryRegion *mem, uint32_t start, uint32_t size);
 void pam_update(PAMMemoryRegion *mem, int idx, uint8_t val);
 
 #endif /* QEMU_PAM_H */
diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h
index e182c82..b083831 100644
--- a/include/hw/pci-host/q35.h
+++ b/include/hw/pci-host/q35.h
@@ -55,6 +55,7 @@
     uint8_t smm_enabled;
     ram_addr_t below_4g_mem_size;
     ram_addr_t above_4g_mem_size;
+    PcGuestInfo *guest_info;
 } MCHPCIState;
 
 typedef struct Q35PCIHost {
@@ -81,6 +82,7 @@
 #define MCH_HOST_BRIDGE_PCIEXBAR               0x60    /* 64bit register */
 #define MCH_HOST_BRIDGE_PCIEXBAR_SIZE          8       /* 64bit register */
 #define MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT       0xb0000000
+#define MCH_HOST_BRIDGE_PCIEXBAR_MAX           (0x10000000) /* 256M */
 #define MCH_HOST_BRIDGE_PCIEXBAR_ADMSK         Q35_MASK(64, 35, 28)
 #define MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK      ((uint64_t)(1 << 26))
 #define MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK       ((uint64_t)(1 << 25))
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 6ef1f97..ccec2ba 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -378,9 +378,11 @@
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
-PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
+PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus,
+                        const char *default_model,
                         const char *default_devaddr);
-PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model,
+PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
+                               const char *default_model,
                                const char *default_devaddr);
 
 PCIDevice *pci_vga_init(PCIBus *bus);
@@ -389,14 +391,15 @@
 void pci_for_each_device(PCIBus *bus, int bus_num,
                          void (*fn)(PCIBus *bus, PCIDevice *d, void *opaque),
                          void *opaque);
-PCIBus *pci_find_root_bus(int domain);
-int pci_find_domain(const PCIBus *bus);
+PCIBus *pci_find_primary_bus(void);
+PCIBus *pci_device_root_bus(const PCIDevice *d);
+const char *pci_root_bus_path(PCIDevice *dev);
 PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
 int pci_qdev_find_device(const char *id, PCIDevice **pdev);
-PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
+PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root, const char *devaddr);
 
-int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
-                     unsigned *slotp);
+int pci_parse_devaddr(const char *addr, int *domp, int *busp,
+                      unsigned int *slotp, unsigned int *funcp);
 
 void pci_device_deassert_intx(PCIDevice *dev);
 
@@ -702,7 +705,7 @@
 static inline void pci_dma_sglist_init(QEMUSGList *qsg, PCIDevice *dev,
                                        int alloc_hint)
 {
-    qemu_sglist_init(qsg, alloc_hint, pci_get_address_space(dev));
+    qemu_sglist_init(qsg, DEVICE(dev), alloc_hint, pci_get_address_space(dev));
 }
 
 extern const VMStateDescription vmstate_pci_device;
diff --git a/include/hw/pci/pci_host.h b/include/hw/pci/pci_host.h
index 236cd0f..ba31595 100644
--- a/include/hw/pci/pci_host.h
+++ b/include/hw/pci/pci_host.h
@@ -33,6 +33,10 @@
 #define TYPE_PCI_HOST_BRIDGE "pci-host-bridge"
 #define PCI_HOST_BRIDGE(obj) \
     OBJECT_CHECK(PCIHostState, (obj), TYPE_PCI_HOST_BRIDGE)
+#define PCI_HOST_BRIDGE_CLASS(klass) \
+     OBJECT_CLASS_CHECK(PCIHostBridgeClass, (klass), TYPE_PCI_HOST_BRIDGE)
+#define PCI_HOST_BRIDGE_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(PCIHostBridgeClass, (obj), TYPE_PCI_HOST_BRIDGE)
 
 struct PCIHostState {
     SysBusDevice busdev;
@@ -42,8 +46,16 @@
     MemoryRegion mmcfg;
     uint32_t config_reg;
     PCIBus *bus;
+
+    QLIST_ENTRY(PCIHostState) next;
 };
 
+typedef struct PCIHostBridgeClass {
+    SysBusDeviceClass parent_class;
+
+    const char *(*root_bus_path)(PCIHostState *, PCIBus *);
+} PCIHostBridgeClass;
+
 /* common internal helpers for PCI/PCIe hosts, cut off overflows */
 void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
                                   uint32_t limit, uint32_t val, uint32_t len);
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 09c4570..de95480 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -348,7 +348,8 @@
 void spapr_iommu_init(void);
 void spapr_events_init(sPAPREnvironment *spapr);
 void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq);
-sPAPRTCETable *spapr_tce_new_table(uint32_t liobn, size_t window_size);
+sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
+                                   size_t window_size);
 MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet);
 void spapr_tce_free(sPAPRTCETable *tcet);
 void spapr_tce_reset(sPAPRTCETable *tcet);
diff --git a/include/hw/virtio/dataplane/hostmem.h b/include/hw/virtio/dataplane/hostmem.h
index b2cf093..2810f4b 100644
--- a/include/hw/virtio/dataplane/hostmem.h
+++ b/include/hw/virtio/dataplane/hostmem.h
@@ -18,6 +18,7 @@
 #include "qemu/thread.h"
 
 typedef struct {
+    MemoryRegion *mr;
     void *host_addr;
     hwaddr guest_addr;
     uint64_t size;
diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h
index 10becb6..0aa8913 100644
--- a/include/qemu/atomic.h
+++ b/include/qemu/atomic.h
@@ -1,68 +1,202 @@
-#ifndef __QEMU_BARRIER_H
-#define __QEMU_BARRIER_H 1
+/*
+ * Simple interface for atomic operations.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * Author: 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.
+ *
+ */
+
+#ifndef __QEMU_ATOMIC_H
+#define __QEMU_ATOMIC_H 1
+
+#include "qemu/compiler.h"
+
+/* For C11 atomic ops */
 
 /* Compiler barrier */
-#define barrier()   asm volatile("" ::: "memory")
+#define barrier()   ({ asm volatile("" ::: "memory"); (void)0; })
 
-#if defined(__i386__)
-
-#include "qemu/compiler.h"        /* QEMU_GNUC_PREREQ */
+#ifndef __ATOMIC_RELAXED
 
 /*
- * Because of the strongly ordered x86 storage model, wmb() and rmb() are nops
- * on x86(well, a compiler barrier only).  Well, at least as long as
- * qemu doesn't do accesses to write-combining memory or non-temporal
- * load/stores from C code.
+ * We use GCC builtin if it's available, as that can use mfence on
+ * 32-bit as well, e.g. if built with -march=pentium-m. However, on
+ * i386 the spec is buggy, and the implementation followed it until
+ * 4.3 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36793).
+ */
+#if defined(__i386__) || defined(__x86_64__)
+#if !QEMU_GNUC_PREREQ(4, 4)
+#if defined __x86_64__
+#define smp_mb()    ({ asm volatile("mfence" ::: "memory"); (void)0; })
+#else
+#define smp_mb()    ({ asm volatile("lock; addl $0,0(%%esp) " ::: "memory"); (void)0; })
+#endif
+#endif
+#endif
+
+
+#ifdef __alpha__
+#define smp_read_barrier_depends()   asm volatile("mb":::"memory")
+#endif
+
+#if defined(__i386__) || defined(__x86_64__) || defined(__s390x__)
+
+/*
+ * Because of the strongly ordered storage model, wmb() and rmb() are nops
+ * here (a compiler barrier only).  QEMU doesn't do accesses to write-combining
+ * qemu memory or non-temporal load/stores from C code.
  */
 #define smp_wmb()   barrier()
 #define smp_rmb()   barrier()
 
 /*
- * We use GCC builtin if it's available, as that can use
- * mfence on 32 bit as well, e.g. if built with -march=pentium-m.
- * However, on i386, there seem to be known bugs as recently as 4.3.
- * */
-#if QEMU_GNUC_PREREQ(4, 4)
-#define smp_mb() __sync_synchronize()
-#else
-#define smp_mb() asm volatile("lock; addl $0,0(%%esp) " ::: "memory")
-#endif
+ * __sync_lock_test_and_set() is documented to be an acquire barrier only,
+ * but it is a full barrier at the hardware level.  Add a compiler barrier
+ * to make it a full barrier also at the compiler level.
+ */
+#define atomic_xchg(ptr, i)    (barrier(), __sync_lock_test_and_set(ptr, i))
 
-#elif defined(__x86_64__)
-
-#define smp_wmb()   barrier()
-#define smp_rmb()   barrier()
-#define smp_mb() asm volatile("mfence" ::: "memory")
+/*
+ * Load/store with Java volatile semantics.
+ */
+#define atomic_mb_set(ptr, i)  ((void)atomic_xchg(ptr, i))
 
 #elif defined(_ARCH_PPC)
 
 /*
  * We use an eieio() for wmb() on powerpc.  This assumes we don't
  * need to order cacheable and non-cacheable stores with respect to
- * each other
+ * each other.
+ *
+ * smp_mb has the same problem as on x86 for not-very-new GCC
+ * (http://patchwork.ozlabs.org/patch/126184/, Nov 2011).
  */
-#define smp_wmb()   asm volatile("eieio" ::: "memory")
-
+#define smp_wmb()   ({ asm volatile("eieio" ::: "memory"); (void)0; })
 #if defined(__powerpc64__)
-#define smp_rmb()   asm volatile("lwsync" ::: "memory")
+#define smp_rmb()   ({ asm volatile("lwsync" ::: "memory"); (void)0; })
 #else
-#define smp_rmb()   asm volatile("sync" ::: "memory")
+#define smp_rmb()   ({ asm volatile("sync" ::: "memory"); (void)0; })
 #endif
+#define smp_mb()    ({ asm volatile("sync" ::: "memory"); (void)0; })
 
-#define smp_mb()   asm volatile("sync" ::: "memory")
+#endif /* _ARCH_PPC */
 
-#else
+#endif /* C11 atomics */
 
 /*
  * For (host) platforms we don't have explicit barrier definitions
  * for, we use the gcc __sync_synchronize() primitive to generate a
  * full barrier.  This should be safe on all platforms, though it may
- * be overkill for wmb() and rmb().
+ * be overkill for smp_wmb() and smp_rmb().
  */
-#define smp_wmb()   __sync_synchronize()
-#define smp_mb()   __sync_synchronize()
-#define smp_rmb()   __sync_synchronize()
-
+#ifndef smp_mb
+#define smp_mb()    __sync_synchronize()
 #endif
 
+#ifndef smp_wmb
+#ifdef __ATOMIC_RELEASE
+#define smp_wmb()   __atomic_thread_fence(__ATOMIC_RELEASE)
+#else
+#define smp_wmb()   __sync_synchronize()
+#endif
+#endif
+
+#ifndef smp_rmb
+#ifdef __ATOMIC_ACQUIRE
+#define smp_rmb()   __atomic_thread_fence(__ATOMIC_ACQUIRE)
+#else
+#define smp_rmb()   __sync_synchronize()
+#endif
+#endif
+
+#ifndef smp_read_barrier_depends
+#ifdef __ATOMIC_CONSUME
+#define smp_read_barrier_depends()   __atomic_thread_fence(__ATOMIC_CONSUME)
+#else
+#define smp_read_barrier_depends()   barrier()
+#endif
+#endif
+
+#ifndef atomic_read
+#define atomic_read(ptr)       (*(__typeof__(*ptr) *volatile) (ptr))
+#endif
+
+#ifndef atomic_set
+#define atomic_set(ptr, i)     ((*(__typeof__(*ptr) *volatile) (ptr)) = (i))
+#endif
+
+/* These have the same semantics as Java volatile variables.
+ * See http://gee.cs.oswego.edu/dl/jmm/cookbook.html:
+ * "1. Issue a StoreStore barrier (wmb) before each volatile store."
+ *  2. Issue a StoreLoad barrier after each volatile store.
+ *     Note that you could instead issue one before each volatile load, but
+ *     this would be slower for typical programs using volatiles in which
+ *     reads greatly outnumber writes. Alternatively, if available, you
+ *     can implement volatile store as an atomic instruction (for example
+ *     XCHG on x86) and omit the barrier. This may be more efficient if
+ *     atomic instructions are cheaper than StoreLoad barriers.
+ *  3. Issue LoadLoad and LoadStore barriers after each volatile load."
+ *
+ * If you prefer to think in terms of "pairing" of memory barriers,
+ * an atomic_mb_read pairs with an atomic_mb_set.
+ *
+ * And for the few ia64 lovers that exist, an atomic_mb_read is a ld.acq,
+ * while an atomic_mb_set is a st.rel followed by a memory barrier.
+ *
+ * These are a bit weaker than __atomic_load/store with __ATOMIC_SEQ_CST
+ * (see docs/atomics.txt), and I'm not sure that __ATOMIC_ACQ_REL is enough.
+ * Just always use the barriers manually by the rules above.
+ */
+#ifndef atomic_mb_read
+#define atomic_mb_read(ptr)    ({           \
+    typeof(*ptr) _val = atomic_read(ptr);   \
+    smp_rmb();                              \
+    _val;                                   \
+})
+#endif
+
+#ifndef atomic_mb_set
+#define atomic_mb_set(ptr, i)  do {         \
+    smp_wmb();                              \
+    atomic_set(ptr, i);                     \
+    smp_mb();                               \
+} while (0)
+#endif
+
+#ifndef atomic_xchg
+#ifdef __ATOMIC_SEQ_CST
+#define atomic_xchg(ptr, i)    ({                           \
+    typeof(*ptr) _new = (i), _old;                          \
+    __atomic_exchange(ptr, &_new, &_old, __ATOMIC_SEQ_CST); \
+    _old;                                                   \
+})
+#elif defined __clang__
+#define atomic_xchg(ptr, i)    __sync_exchange(ptr, i)
+#else
+/* __sync_lock_test_and_set() is documented to be an acquire barrier only.  */
+#define atomic_xchg(ptr, i)    (smp_mb(), __sync_lock_test_and_set(ptr, i))
+#endif
+#endif
+
+/* Provide shorter names for GCC atomic builtins.  */
+#define atomic_fetch_inc(ptr)  __sync_fetch_and_add(ptr, 1)
+#define atomic_fetch_dec(ptr)  __sync_fetch_and_add(ptr, -1)
+#define atomic_fetch_add       __sync_fetch_and_add
+#define atomic_fetch_sub       __sync_fetch_and_sub
+#define atomic_fetch_and       __sync_fetch_and_and
+#define atomic_fetch_or        __sync_fetch_and_or
+#define atomic_cmpxchg         __sync_val_compare_and_swap
+
+/* And even shorter names that return void.  */
+#define atomic_inc(ptr)        ((void) __sync_fetch_and_add(ptr, 1))
+#define atomic_dec(ptr)        ((void) __sync_fetch_and_add(ptr, -1))
+#define atomic_add(ptr, n)     ((void) __sync_fetch_and_add(ptr, n))
+#define atomic_sub(ptr, n)     ((void) __sync_fetch_and_sub(ptr, n))
+#define atomic_and(ptr, n)     ((void) __sync_fetch_and_and(ptr, n))
+#define atomic_or(ptr, n)      ((void) __sync_fetch_and_or(ptr, n))
+
 #endif
diff --git a/include/qemu/int128.h b/include/qemu/int128.h
index bfe7678..9ed47aa 100644
--- a/include/qemu/int128.h
+++ b/include/qemu/int128.h
@@ -1,6 +1,10 @@
 #ifndef INT128_H
 #define INT128_H
 
+#include <assert.h>
+#include <stdint.h>
+#include <stdbool.h>
+
 typedef struct Int128 Int128;
 
 struct Int128 {
@@ -55,21 +59,26 @@
 
 static inline Int128 int128_add(Int128 a, Int128 b)
 {
-    Int128 r = { a.lo + b.lo, a.hi + b.hi };
-    r.hi += (r.lo < a.lo) || (r.lo < b.lo);
-    return r;
+    uint64_t lo = a.lo + b.lo;
+
+    /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64).  Hence,
+     * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo.
+     * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k.
+     *
+     * So the carry is lo < a.lo.
+     */
+    return (Int128) { lo, (uint64_t)a.hi + b.hi + (lo < a.lo) };
 }
 
 static inline Int128 int128_neg(Int128 a)
 {
-    a.lo = ~a.lo;
-    a.hi = ~a.hi;
-    return int128_add(a, int128_one());
+    uint64_t lo = -a.lo;
+    return (Int128) { lo, ~(uint64_t)a.hi + !lo };
 }
 
 static inline Int128 int128_sub(Int128 a, Int128 b)
 {
-    return int128_add(a, int128_neg(b));
+    return (Int128){ a.lo - b.lo, a.hi - b.hi - (a.lo < b.lo) };
 }
 
 static inline bool int128_nonneg(Int128 a)
@@ -89,7 +98,7 @@
 
 static inline bool int128_ge(Int128 a, Int128 b)
 {
-    return int128_nonneg(int128_sub(a, b));
+    return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo);
 }
 
 static inline bool int128_lt(Int128 a, Int128 b)
diff --git a/include/qemu/range.h b/include/qemu/range.h
index 3502372..b76cc0d 100644
--- a/include/qemu/range.h
+++ b/include/qemu/range.h
@@ -1,6 +1,22 @@
 #ifndef QEMU_RANGE_H
 #define QEMU_RANGE_H
 
+#include <inttypes.h>
+
+/*
+ * Operations on 64 bit address ranges.
+ * Notes:
+ *   - ranges must not wrap around 0, but can include the last byte ~0x0LL.
+ *   - this can not represent a full 0 to ~0x0LL range.
+ */
+
+/* A structure representing a range of addresses. */
+struct Range {
+    uint64_t begin; /* First byte of the range, or 0 if empty. */
+    uint64_t end;   /* 1 + the last byte. 0 if range empty or ends at ~0x0LL. */
+};
+typedef struct Range Range;
+
 /* Get last byte of a range from offset + length.
  * Undefined for ranges that wrap around 0. */
 static inline uint64_t range_get_last(uint64_t offset, uint64_t len)
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 698fc03..ac9f8d4 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -64,5 +64,6 @@
 typedef struct QEMUSGList QEMUSGList;
 typedef struct SHPCDevice SHPCDevice;
 typedef struct FWCfgState FWCfgState;
+typedef struct PcGuestInfo PcGuestInfo;
 
 #endif /* QEMU_TYPEDEFS_H */
diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
index 031d1f5..00f21f3 100644
--- a/include/sysemu/dma.h
+++ b/include/sysemu/dma.h
@@ -29,6 +29,7 @@
     int nsg;
     int nalloc;
     size_t size;
+    DeviceState *dev;
     AddressSpace *as;
 };
 
@@ -189,7 +190,8 @@
     dma_addr_t len;
 };
 
-void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint, AddressSpace *as);
+void qemu_sglist_init(QEMUSGList *qsg, DeviceState *dev, int alloc_hint,
+                      AddressSpace *as);
 void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len);
 void qemu_sglist_destroy(QEMUSGList *qsg);
 #endif
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 2fb71af..d85bdc0 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -185,6 +185,8 @@
 
 DeviceState *get_boot_device(uint32_t position);
 
+QemuOpts *qemu_get_machine_opts(void);
+
 bool usb_enabled(bool default_usb);
 
 extern QemuOptsList qemu_drive_opts;
diff --git a/ioport.c b/ioport.c
index a0ac2a0..79b7f1a 100644
--- a/ioport.c
+++ b/ioport.c
@@ -28,285 +28,54 @@
 #include "exec/ioport.h"
 #include "trace.h"
 #include "exec/memory.h"
+#include "exec/address-spaces.h"
 
-/***********************************************************/
-/* IO Port */
-
-//#define DEBUG_UNUSED_IOPORT
 //#define DEBUG_IOPORT
 
-#ifdef DEBUG_UNUSED_IOPORT
-#  define LOG_UNUSED_IOPORT(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
-#else
-#  define LOG_UNUSED_IOPORT(fmt, ...) do{ } while (0)
-#endif
-
 #ifdef DEBUG_IOPORT
 #  define LOG_IOPORT(...) qemu_log_mask(CPU_LOG_IOPORT, ## __VA_ARGS__)
 #else
 #  define LOG_IOPORT(...) do { } while (0)
 #endif
 
-/* XXX: use a two level table to limit memory usage */
-
-static void *ioport_opaque[MAX_IOPORTS];
-static IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
-static IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
-static IOPortDestructor *ioport_destructor_table[MAX_IOPORTS];
-
-static IOPortReadFunc default_ioport_readb, default_ioport_readw, default_ioport_readl;
-static IOPortWriteFunc default_ioport_writeb, default_ioport_writew, default_ioport_writel;
-
-static uint32_t ioport_read(int index, uint32_t address)
-{
-    static IOPortReadFunc * const default_func[3] = {
-        default_ioport_readb,
-        default_ioport_readw,
-        default_ioport_readl
-    };
-    IOPortReadFunc *func = ioport_read_table[index][address];
-    if (!func)
-        func = default_func[index];
-    return func(ioport_opaque[address], address);
-}
-
-static void ioport_write(int index, uint32_t address, uint32_t data)
-{
-    static IOPortWriteFunc * const default_func[3] = {
-        default_ioport_writeb,
-        default_ioport_writew,
-        default_ioport_writel
-    };
-    IOPortWriteFunc *func = ioport_write_table[index][address];
-    if (!func)
-        func = default_func[index];
-    func(ioport_opaque[address], address, data);
-}
-
-static uint32_t default_ioport_readb(void *opaque, uint32_t address)
-{
-    LOG_UNUSED_IOPORT("unused inb: port=0x%04"PRIx32"\n", address);
-    return 0xff;
-}
-
-static void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data)
-{
-    LOG_UNUSED_IOPORT("unused outb: port=0x%04"PRIx32" data=0x%02"PRIx32"\n",
-                      address, data);
-}
-
-/* default is to make two byte accesses */
-static uint32_t default_ioport_readw(void *opaque, uint32_t address)
-{
-    uint32_t data;
-    data = ioport_read(0, address);
-    address = (address + 1) & IOPORTS_MASK;
-    data |= ioport_read(0, address) << 8;
-    return data;
-}
-
-static void default_ioport_writew(void *opaque, uint32_t address, uint32_t data)
-{
-    ioport_write(0, address, data & 0xff);
-    address = (address + 1) & IOPORTS_MASK;
-    ioport_write(0, address, (data >> 8) & 0xff);
-}
-
-static uint32_t default_ioport_readl(void *opaque, uint32_t address)
-{
-    LOG_UNUSED_IOPORT("unused inl: port=0x%04"PRIx32"\n", address);
-    return 0xffffffff;
-}
-
-static void default_ioport_writel(void *opaque, uint32_t address, uint32_t data)
-{
-    LOG_UNUSED_IOPORT("unused outl: port=0x%04"PRIx32" data=0x%02"PRIx32"\n",
-                      address, data);
-}
-
-static int ioport_bsize(int size, int *bsize)
-{
-    if (size == 1) {
-        *bsize = 0;
-    } else if (size == 2) {
-        *bsize = 1;
-    } else if (size == 4) {
-        *bsize = 2;
-    } else {
-        return -1;
-    }
-    return 0;
-}
-
-/* size is the word size in byte */
-int register_ioport_read(pio_addr_t start, int length, int size,
-                         IOPortReadFunc *func, void *opaque)
-{
-    int i, bsize;
-
-    if (ioport_bsize(size, &bsize)) {
-        hw_error("register_ioport_read: invalid size");
-        return -1;
-    }
-    for(i = start; i < start + length; ++i) {
-        ioport_read_table[bsize][i] = func;
-        if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
-            hw_error("register_ioport_read: invalid opaque for address 0x%x",
-                     i);
-        ioport_opaque[i] = opaque;
-    }
-    return 0;
-}
-
-/* size is the word size in byte */
-int register_ioport_write(pio_addr_t start, int length, int size,
-                          IOPortWriteFunc *func, void *opaque)
-{
-    int i, bsize;
-
-    if (ioport_bsize(size, &bsize)) {
-        hw_error("register_ioport_write: invalid size");
-        return -1;
-    }
-    for(i = start; i < start + length; ++i) {
-        ioport_write_table[bsize][i] = func;
-        if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
-            hw_error("register_ioport_write: invalid opaque for address 0x%x",
-                     i);
-        ioport_opaque[i] = opaque;
-    }
-    return 0;
-}
-
-static uint32_t ioport_readb_thunk(void *opaque, uint32_t addr)
-{
-    IORange *ioport = opaque;
-    uint64_t data;
-
-    ioport->ops->read(ioport, addr - ioport->base, 1, &data);
-    return data;
-}
-
-static uint32_t ioport_readw_thunk(void *opaque, uint32_t addr)
-{
-    IORange *ioport = opaque;
-    uint64_t data;
-
-    ioport->ops->read(ioport, addr - ioport->base, 2, &data);
-    return data;
-}
-
-static uint32_t ioport_readl_thunk(void *opaque, uint32_t addr)
-{
-    IORange *ioport = opaque;
-    uint64_t data;
-
-    ioport->ops->read(ioport, addr - ioport->base, 4, &data);
-    return data;
-}
-
-static void ioport_writeb_thunk(void *opaque, uint32_t addr, uint32_t data)
-{
-    IORange *ioport = opaque;
-
-    ioport->ops->write(ioport, addr - ioport->base, 1, data);
-}
-
-static void ioport_writew_thunk(void *opaque, uint32_t addr, uint32_t data)
-{
-    IORange *ioport = opaque;
-
-    ioport->ops->write(ioport, addr - ioport->base, 2, data);
-}
-
-static void ioport_writel_thunk(void *opaque, uint32_t addr, uint32_t data)
-{
-    IORange *ioport = opaque;
-
-    ioport->ops->write(ioport, addr - ioport->base, 4, data);
-}
-
-static void iorange_destructor_thunk(void *opaque)
-{
-    IORange *iorange = opaque;
-
-    if (iorange->ops->destructor) {
-        iorange->ops->destructor(iorange);
-    }
-}
-
-void ioport_register(IORange *ioport)
-{
-    register_ioport_read(ioport->base, ioport->len, 1,
-                         ioport_readb_thunk, ioport);
-    register_ioport_read(ioport->base, ioport->len, 2,
-                         ioport_readw_thunk, ioport);
-    register_ioport_read(ioport->base, ioport->len, 4,
-                         ioport_readl_thunk, ioport);
-    register_ioport_write(ioport->base, ioport->len, 1,
-                          ioport_writeb_thunk, ioport);
-    register_ioport_write(ioport->base, ioport->len, 2,
-                          ioport_writew_thunk, ioport);
-    register_ioport_write(ioport->base, ioport->len, 4,
-                          ioport_writel_thunk, ioport);
-    ioport_destructor_table[ioport->base] = iorange_destructor_thunk;
-}
-
-void isa_unassign_ioport(pio_addr_t start, int length)
-{
-    int i;
-
-    if (ioport_destructor_table[start]) {
-        ioport_destructor_table[start](ioport_opaque[start]);
-        ioport_destructor_table[start] = NULL;
-    }
-    for(i = start; i < start + length; i++) {
-        ioport_read_table[0][i] = NULL;
-        ioport_read_table[1][i] = NULL;
-        ioport_read_table[2][i] = NULL;
-
-        ioport_write_table[0][i] = NULL;
-        ioport_write_table[1][i] = NULL;
-        ioport_write_table[2][i] = NULL;
-
-        ioport_opaque[i] = NULL;
-    }
-}
-
-bool isa_is_ioport_assigned(pio_addr_t start)
-{
-    return (ioport_read_table[0][start] || ioport_write_table[0][start] ||
-	    ioport_read_table[1][start] || ioport_write_table[1][start] ||
-	    ioport_read_table[2][start] || ioport_write_table[2][start]);
-}
-
-/***********************************************************/
+typedef struct MemoryRegionPortioList {
+    MemoryRegion mr;
+    void *portio_opaque;
+    MemoryRegionPortio ports[];
+} MemoryRegionPortioList;
 
 void cpu_outb(pio_addr_t addr, uint8_t val)
 {
     LOG_IOPORT("outb: %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
     trace_cpu_out(addr, val);
-    ioport_write(0, addr, val);
+    address_space_write(&address_space_io, addr, &val, 1);
 }
 
 void cpu_outw(pio_addr_t addr, uint16_t val)
 {
+    uint8_t buf[2];
+
     LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
     trace_cpu_out(addr, val);
-    ioport_write(1, addr, val);
+    stw_p(buf, val);
+    address_space_write(&address_space_io, addr, buf, 2);
 }
 
 void cpu_outl(pio_addr_t addr, uint32_t val)
 {
+    uint8_t buf[4];
+
     LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
     trace_cpu_out(addr, val);
-    ioport_write(2, addr, val);
+    stl_p(buf, val);
+    address_space_write(&address_space_io, addr, buf, 4);
 }
 
 uint8_t cpu_inb(pio_addr_t addr)
 {
     uint8_t val;
-    val = ioport_read(0, addr);
+
+    address_space_read(&address_space_io, addr, &val, 1);
     trace_cpu_in(addr, val);
     LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
     return val;
@@ -314,8 +83,11 @@
 
 uint16_t cpu_inw(pio_addr_t addr)
 {
+    uint8_t buf[2];
     uint16_t val;
-    val = ioport_read(1, addr);
+
+    address_space_read(&address_space_io, addr, buf, 2);
+    val = lduw_p(buf);
     trace_cpu_in(addr, val);
     LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
     return val;
@@ -323,14 +95,18 @@
 
 uint32_t cpu_inl(pio_addr_t addr)
 {
+    uint8_t buf[4];
     uint32_t val;
-    val = ioport_read(2, addr);
+
+    address_space_read(&address_space_io, addr, buf, 4);
+    val = ldl_p(buf);
     trace_cpu_in(addr, val);
     LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
     return val;
 }
 
 void portio_list_init(PortioList *piolist,
+                      Object *owner,
                       const MemoryRegionPortio *callbacks,
                       void *opaque, const char *name)
 {
@@ -343,55 +119,105 @@
     piolist->ports = callbacks;
     piolist->nr = 0;
     piolist->regions = g_new0(MemoryRegion *, n);
-    piolist->aliases = g_new0(MemoryRegion *, n);
     piolist->address_space = NULL;
     piolist->opaque = opaque;
+    piolist->owner = owner;
     piolist->name = name;
 }
 
 void portio_list_destroy(PortioList *piolist)
 {
     g_free(piolist->regions);
-    g_free(piolist->aliases);
 }
 
+static const MemoryRegionPortio *find_portio(MemoryRegionPortioList *mrpio,
+                                             uint64_t offset, unsigned size,
+                                             bool write)
+{
+    const MemoryRegionPortio *mrp;
+
+    for (mrp = mrpio->ports; mrp->size; ++mrp) {
+        if (offset >= mrp->offset && offset < mrp->offset + mrp->len &&
+            size == mrp->size &&
+            (write ? (bool)mrp->write : (bool)mrp->read)) {
+            return mrp;
+        }
+    }
+    return NULL;
+}
+
+static uint64_t portio_read(void *opaque, hwaddr addr, unsigned size)
+{
+    MemoryRegionPortioList *mrpio = opaque;
+    const MemoryRegionPortio *mrp = find_portio(mrpio, addr, size, false);
+    uint64_t data;
+
+    data = ((uint64_t)1 << (size * 8)) - 1;
+    if (mrp) {
+        data = mrp->read(mrpio->portio_opaque, mrp->base + addr);
+    } else if (size == 2) {
+        mrp = find_portio(mrpio, addr, 1, false);
+        assert(mrp);
+        data = mrp->read(mrpio->portio_opaque, mrp->base + addr) |
+                (mrp->read(mrpio->portio_opaque, mrp->base + addr + 1) << 8);
+    }
+    return data;
+}
+
+static void portio_write(void *opaque, hwaddr addr, uint64_t data,
+                         unsigned size)
+{
+    MemoryRegionPortioList *mrpio = opaque;
+    const MemoryRegionPortio *mrp = find_portio(mrpio, addr, size, true);
+
+    if (mrp) {
+        mrp->write(mrpio->portio_opaque, mrp->base + addr, data);
+    } else if (size == 2) {
+        mrp = find_portio(mrpio, addr, 1, true);
+        assert(mrp);
+        mrp->write(mrpio->portio_opaque, mrp->base + addr, data & 0xff);
+        mrp->write(mrpio->portio_opaque, mrp->base + addr + 1, data >> 8);
+    }
+}
+
+static const MemoryRegionOps portio_ops = {
+    .read = portio_read,
+    .write = portio_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid.unaligned = true,
+    .impl.unaligned = true,
+};
+
 static void portio_list_add_1(PortioList *piolist,
                               const MemoryRegionPortio *pio_init,
                               unsigned count, unsigned start,
                               unsigned off_low, unsigned off_high)
 {
-    MemoryRegionPortio *pio;
-    MemoryRegionOps *ops;
-    MemoryRegion *region, *alias;
+    MemoryRegionPortioList *mrpio;
     unsigned i;
 
     /* Copy the sub-list and null-terminate it.  */
-    pio = g_new(MemoryRegionPortio, count + 1);
-    memcpy(pio, pio_init, sizeof(MemoryRegionPortio) * count);
-    memset(pio + count, 0, sizeof(MemoryRegionPortio));
+    mrpio = g_malloc0(sizeof(MemoryRegionPortioList) +
+                      sizeof(MemoryRegionPortio) * (count + 1));
+    mrpio->portio_opaque = piolist->opaque;
+    memcpy(mrpio->ports, pio_init, sizeof(MemoryRegionPortio) * count);
+    memset(mrpio->ports + count, 0, sizeof(MemoryRegionPortio));
 
     /* Adjust the offsets to all be zero-based for the region.  */
     for (i = 0; i < count; ++i) {
-        pio[i].offset -= off_low;
+        mrpio->ports[i].offset -= off_low;
+        mrpio->ports[i].base = start + off_low;
     }
 
-    ops = g_new0(MemoryRegionOps, 1);
-    ops->old_portio = pio;
-
-    region = g_new(MemoryRegion, 1);
-    alias = g_new(MemoryRegion, 1);
     /*
      * Use an alias so that the callback is called with an absolute address,
      * rather than an offset relative to to start + off_low.
      */
-    memory_region_init_io(region, ops, piolist->opaque, piolist->name,
-                          INT64_MAX);
-    memory_region_init_alias(alias, piolist->name,
-                             region, start + off_low, off_high - off_low);
+    memory_region_init_io(&mrpio->mr, piolist->owner, &portio_ops, mrpio,
+                          piolist->name, off_high - off_low);
     memory_region_add_subregion(piolist->address_space,
-                                start + off_low, alias);
-    piolist->regions[piolist->nr] = region;
-    piolist->aliases[piolist->nr] = alias;
+                                start + off_low, &mrpio->mr);
+    piolist->regions[piolist->nr] = &mrpio->mr;
     ++piolist->nr;
 }
 
@@ -434,19 +260,14 @@
 
 void portio_list_del(PortioList *piolist)
 {
-    MemoryRegion *mr, *alias;
+    MemoryRegionPortioList *mrpio;
     unsigned i;
 
     for (i = 0; i < piolist->nr; ++i) {
-        mr = piolist->regions[i];
-        alias = piolist->aliases[i];
-        memory_region_del_subregion(piolist->address_space, alias);
-        memory_region_destroy(alias);
-        memory_region_destroy(mr);
-        g_free((MemoryRegionOps *)mr->ops);
-        g_free(mr);
-        g_free(alias);
+        mrpio = container_of(piolist->regions[i], MemoryRegionPortioList, mr);
+        memory_region_del_subregion(piolist->address_space, &mrpio->mr);
+        memory_region_destroy(&mrpio->mr);
+        g_free(mrpio);
         piolist->regions[i] = NULL;
-        piolist->aliases[i] = NULL;
     }
 }
diff --git a/kvm-all.c b/kvm-all.c
index 3ee0ac7..a5cd3d3 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -789,6 +789,7 @@
 static void kvm_region_add(MemoryListener *listener,
                            MemoryRegionSection *section)
 {
+    memory_region_ref(section->mr);
     kvm_set_phys_mem(section, true);
 }
 
@@ -796,6 +797,7 @@
                            MemoryRegionSection *section)
 {
     kvm_set_phys_mem(section, false);
+    memory_region_unref(section->mr);
 }
 
 static void kvm_log_sync(MemoryListener *listener,
@@ -1286,12 +1288,9 @@
 
 static int kvm_irqchip_create(KVMState *s)
 {
-    QemuOptsList *list = qemu_find_opts("machine");
     int ret;
 
-    if (QTAILQ_EMPTY(&list->head) ||
-        !qemu_opt_get_bool(QTAILQ_FIRST(&list->head),
-                           "kernel_irqchip", true) ||
+    if (!qemu_opt_get_bool(qemu_get_machine_opts(), "kernel_irqchip", true) ||
         !kvm_check_extension(s, KVM_CAP_IRQCHIP)) {
         return 0;
     }
diff --git a/memory.c b/memory.c
index 757e9a5..35553b5 100644
--- a/memory.c
+++ b/memory.c
@@ -17,6 +17,7 @@
 #include "exec/address-spaces.h"
 #include "exec/ioport.h"
 #include "qemu/bitops.h"
+#include "qom/object.h"
 #include "sysemu/kvm.h"
 #include <assert.h>
 
@@ -28,12 +29,26 @@
 static bool memory_region_update_pending;
 static bool global_dirty_log = false;
 
+/* flat_view_mutex is taken around reading as->current_map; the critical
+ * section is extremely short, so I'm using a single mutex for every AS.
+ * We could also RCU for the read-side.
+ *
+ * The BQL is taken around transaction commits, hence both locks are taken
+ * while writing to as->current_map (with the BQL taken outside).
+ */
+static QemuMutex flat_view_mutex;
+
 static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners
     = QTAILQ_HEAD_INITIALIZER(memory_listeners);
 
 static QTAILQ_HEAD(, AddressSpace) address_spaces
     = QTAILQ_HEAD_INITIALIZER(address_spaces);
 
+static void memory_init(void)
+{
+    qemu_mutex_init(&flat_view_mutex);
+}
+
 typedef struct AddrRange AddrRange;
 
 /*
@@ -147,6 +162,7 @@
         }                                                               \
     } while (0)
 
+/* No need to ref/unref .mr, the FlatRange keeps it alive.  */
 #define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback)            \
     MEMORY_LISTENER_CALL(callback, dir, (&(MemoryRegionSection) {       \
         .mr = (fr)->mr,                                                 \
@@ -223,6 +239,7 @@
  * order.
  */
 struct FlatView {
+    unsigned ref;
     FlatRange *ranges;
     unsigned nr;
     unsigned nr_allocated;
@@ -244,6 +261,7 @@
 
 static void flatview_init(FlatView *view)
 {
+    view->ref = 1;
     view->ranges = NULL;
     view->nr = 0;
     view->nr_allocated = 0;
@@ -262,12 +280,31 @@
     memmove(view->ranges + pos + 1, view->ranges + pos,
             (view->nr - pos) * sizeof(FlatRange));
     view->ranges[pos] = *range;
+    memory_region_ref(range->mr);
     ++view->nr;
 }
 
 static void flatview_destroy(FlatView *view)
 {
+    int i;
+
+    for (i = 0; i < view->nr; i++) {
+        memory_region_unref(view->ranges[i].mr);
+    }
     g_free(view->ranges);
+    g_free(view);
+}
+
+static void flatview_ref(FlatView *view)
+{
+    atomic_inc(&view->ref);
+}
+
+static void flatview_unref(FlatView *view)
+{
+    if (atomic_fetch_dec(&view->ref) == 1) {
+        flatview_destroy(view);
+    }
 }
 
 static bool can_merge(FlatRange *r1, FlatRange *r2)
@@ -401,94 +438,6 @@
     }
 }
 
-static const MemoryRegionPortio *find_portio(MemoryRegion *mr, uint64_t offset,
-                                             unsigned width, bool write)
-{
-    const MemoryRegionPortio *mrp;
-
-    for (mrp = mr->ops->old_portio; mrp->size; ++mrp) {
-        if (offset >= mrp->offset && offset < mrp->offset + mrp->len
-            && width == mrp->size
-            && (write ? (bool)mrp->write : (bool)mrp->read)) {
-            return mrp;
-        }
-    }
-    return NULL;
-}
-
-static void memory_region_iorange_read(IORange *iorange,
-                                       uint64_t offset,
-                                       unsigned width,
-                                       uint64_t *data)
-{
-    MemoryRegionIORange *mrio
-        = container_of(iorange, MemoryRegionIORange, iorange);
-    MemoryRegion *mr = mrio->mr;
-
-    offset += mrio->offset;
-    if (mr->ops->old_portio) {
-        const MemoryRegionPortio *mrp = find_portio(mr, offset - mrio->offset,
-                                                    width, false);
-
-        *data = ((uint64_t)1 << (width * 8)) - 1;
-        if (mrp) {
-            *data = mrp->read(mr->opaque, offset);
-        } else if (width == 2) {
-            mrp = find_portio(mr, offset - mrio->offset, 1, false);
-            assert(mrp);
-            *data = mrp->read(mr->opaque, offset) |
-                    (mrp->read(mr->opaque, offset + 1) << 8);
-        }
-        return;
-    }
-    *data = 0;
-    access_with_adjusted_size(offset, data, width,
-                              mr->ops->impl.min_access_size,
-                              mr->ops->impl.max_access_size,
-                              memory_region_read_accessor, mr);
-}
-
-static void memory_region_iorange_write(IORange *iorange,
-                                        uint64_t offset,
-                                        unsigned width,
-                                        uint64_t data)
-{
-    MemoryRegionIORange *mrio
-        = container_of(iorange, MemoryRegionIORange, iorange);
-    MemoryRegion *mr = mrio->mr;
-
-    offset += mrio->offset;
-    if (mr->ops->old_portio) {
-        const MemoryRegionPortio *mrp = find_portio(mr, offset - mrio->offset,
-                                                    width, true);
-
-        if (mrp) {
-            mrp->write(mr->opaque, offset, data);
-        } else if (width == 2) {
-            mrp = find_portio(mr, offset - mrio->offset, 1, true);
-            assert(mrp);
-            mrp->write(mr->opaque, offset, data & 0xff);
-            mrp->write(mr->opaque, offset + 1, data >> 8);
-        }
-        return;
-    }
-    access_with_adjusted_size(offset, &data, width,
-                              mr->ops->impl.min_access_size,
-                              mr->ops->impl.max_access_size,
-                              memory_region_write_accessor, mr);
-}
-
-static void memory_region_iorange_destructor(IORange *iorange)
-{
-    g_free(container_of(iorange, MemoryRegionIORange, iorange));
-}
-
-const IORangeOps memory_region_iorange_ops = {
-    .read = memory_region_iorange_read,
-    .write = memory_region_iorange_write,
-    .destructor = memory_region_iorange_destructor,
-};
-
 static AddressSpace *memory_region_to_address_space(MemoryRegion *mr)
 {
     AddressSpace *as;
@@ -592,17 +541,18 @@
 }
 
 /* Render a memory topology into a list of disjoint absolute ranges. */
-static FlatView generate_memory_topology(MemoryRegion *mr)
+static FlatView *generate_memory_topology(MemoryRegion *mr)
 {
-    FlatView view;
+    FlatView *view;
 
-    flatview_init(&view);
+    view = g_new(FlatView, 1);
+    flatview_init(view);
 
     if (mr) {
-        render_memory_region(&view, mr, int128_zero(),
+        render_memory_region(view, mr, int128_zero(),
                              addrrange_make(int128_zero(), int128_2_64()), false);
     }
-    flatview_simplify(&view);
+    flatview_simplify(view);
 
     return view;
 }
@@ -656,15 +606,28 @@
     }
 }
 
+static FlatView *address_space_get_flatview(AddressSpace *as)
+{
+    FlatView *view;
+
+    qemu_mutex_lock(&flat_view_mutex);
+    view = as->current_map;
+    flatview_ref(view);
+    qemu_mutex_unlock(&flat_view_mutex);
+    return view;
+}
+
 static void address_space_update_ioeventfds(AddressSpace *as)
 {
+    FlatView *view;
     FlatRange *fr;
     unsigned ioeventfd_nb = 0;
     MemoryRegionIoeventfd *ioeventfds = NULL;
     AddrRange tmp;
     unsigned i;
 
-    FOR_EACH_FLAT_RANGE(fr, as->current_map) {
+    view = address_space_get_flatview(as);
+    FOR_EACH_FLAT_RANGE(fr, view) {
         for (i = 0; i < fr->mr->ioeventfd_nb; ++i) {
             tmp = addrrange_shift(fr->mr->ioeventfds[i].addr,
                                   int128_sub(fr->addr.start,
@@ -685,11 +648,12 @@
     g_free(as->ioeventfds);
     as->ioeventfds = ioeventfds;
     as->ioeventfd_nb = ioeventfd_nb;
+    flatview_unref(view);
 }
 
 static void address_space_update_topology_pass(AddressSpace *as,
-                                               FlatView old_view,
-                                               FlatView new_view,
+                                               const FlatView *old_view,
+                                               const FlatView *new_view,
                                                bool adding)
 {
     unsigned iold, inew;
@@ -699,14 +663,14 @@
      * Kill ranges in the old map, and instantiate ranges in the new map.
      */
     iold = inew = 0;
-    while (iold < old_view.nr || inew < new_view.nr) {
-        if (iold < old_view.nr) {
-            frold = &old_view.ranges[iold];
+    while (iold < old_view->nr || inew < new_view->nr) {
+        if (iold < old_view->nr) {
+            frold = &old_view->ranges[iold];
         } else {
             frold = NULL;
         }
-        if (inew < new_view.nr) {
-            frnew = &new_view.ranges[inew];
+        if (inew < new_view->nr) {
+            frnew = &new_view->ranges[inew];
         } else {
             frnew = NULL;
         }
@@ -752,14 +716,25 @@
 
 static void address_space_update_topology(AddressSpace *as)
 {
-    FlatView old_view = *as->current_map;
-    FlatView new_view = generate_memory_topology(as->root);
+    FlatView *old_view = address_space_get_flatview(as);
+    FlatView *new_view = generate_memory_topology(as->root);
 
     address_space_update_topology_pass(as, old_view, new_view, false);
     address_space_update_topology_pass(as, old_view, new_view, true);
 
-    *as->current_map = new_view;
-    flatview_destroy(&old_view);
+    qemu_mutex_lock(&flat_view_mutex);
+    flatview_unref(as->current_map);
+    as->current_map = new_view;
+    qemu_mutex_unlock(&flat_view_mutex);
+
+    /* Note that all the old MemoryRegions are still alive up to this
+     * point.  This relieves most MemoryListeners from the need to
+     * ref/unref the MemoryRegions they get---unless they use them
+     * outside the iothread mutex, in which case precise reference
+     * counting is necessary.
+     */
+    flatview_unref(old_view);
+
     address_space_update_ioeventfds(as);
 }
 
@@ -796,6 +771,11 @@
     qemu_ram_free(mr->ram_addr);
 }
 
+static void memory_region_destructor_alias(MemoryRegion *mr)
+{
+    memory_region_unref(mr->alias);
+}
+
 static void memory_region_destructor_ram_from_ptr(MemoryRegion *mr)
 {
     qemu_ram_free_from_ptr(mr->ram_addr);
@@ -816,13 +796,16 @@
 }
 
 void memory_region_init(MemoryRegion *mr,
+                        Object *owner,
                         const char *name,
                         uint64_t size)
 {
     mr->ops = &unassigned_mem_ops;
     mr->opaque = NULL;
+    mr->owner = owner;
     mr->iommu_ops = NULL;
     mr->parent = NULL;
+    mr->owner = NULL;
     mr->size = int128_make64(size);
     if (size == UINT64_MAX) {
         mr->size = int128_2_64();
@@ -1002,12 +985,13 @@
 }
 
 void memory_region_init_io(MemoryRegion *mr,
+                           Object *owner,
                            const MemoryRegionOps *ops,
                            void *opaque,
                            const char *name,
                            uint64_t size)
 {
-    memory_region_init(mr, name, size);
+    memory_region_init(mr, owner, name, size);
     mr->ops = ops;
     mr->opaque = opaque;
     mr->terminates = true;
@@ -1015,10 +999,11 @@
 }
 
 void memory_region_init_ram(MemoryRegion *mr,
+                            Object *owner,
                             const char *name,
                             uint64_t size)
 {
-    memory_region_init(mr, name, size);
+    memory_region_init(mr, owner, name, size);
     mr->ram = true;
     mr->terminates = true;
     mr->destructor = memory_region_destructor_ram;
@@ -1026,11 +1011,12 @@
 }
 
 void memory_region_init_ram_ptr(MemoryRegion *mr,
+                                Object *owner,
                                 const char *name,
                                 uint64_t size,
                                 void *ptr)
 {
-    memory_region_init(mr, name, size);
+    memory_region_init(mr, owner, name, size);
     mr->ram = true;
     mr->terminates = true;
     mr->destructor = memory_region_destructor_ram_from_ptr;
@@ -1038,23 +1024,27 @@
 }
 
 void memory_region_init_alias(MemoryRegion *mr,
+                              Object *owner,
                               const char *name,
                               MemoryRegion *orig,
                               hwaddr offset,
                               uint64_t size)
 {
-    memory_region_init(mr, name, size);
+    memory_region_init(mr, owner, name, size);
+    memory_region_ref(orig);
+    mr->destructor = memory_region_destructor_alias;
     mr->alias = orig;
     mr->alias_offset = offset;
 }
 
 void memory_region_init_rom_device(MemoryRegion *mr,
+                                   Object *owner,
                                    const MemoryRegionOps *ops,
                                    void *opaque,
                                    const char *name,
                                    uint64_t size)
 {
-    memory_region_init(mr, name, size);
+    memory_region_init(mr, owner, name, size);
     mr->ops = ops;
     mr->opaque = opaque;
     mr->terminates = true;
@@ -1064,21 +1054,23 @@
 }
 
 void memory_region_init_iommu(MemoryRegion *mr,
+                              Object *owner,
                               const MemoryRegionIOMMUOps *ops,
                               const char *name,
                               uint64_t size)
 {
-    memory_region_init(mr, name, size);
+    memory_region_init(mr, owner, name, size);
     mr->iommu_ops = ops,
     mr->terminates = true;  /* then re-forwards */
     notifier_list_init(&mr->iommu_notify);
 }
 
 void memory_region_init_reservation(MemoryRegion *mr,
+                                    Object *owner,
                                     const char *name,
                                     uint64_t size)
 {
-    memory_region_init_io(mr, &unassigned_mem_ops, mr, name, size);
+    memory_region_init_io(mr, owner, &unassigned_mem_ops, mr, name, size);
 }
 
 void memory_region_destroy(MemoryRegion *mr)
@@ -1091,6 +1083,25 @@
     g_free(mr->ioeventfds);
 }
 
+Object *memory_region_owner(MemoryRegion *mr)
+{
+    return mr->owner;
+}
+
+void memory_region_ref(MemoryRegion *mr)
+{
+    if (mr && mr->owner) {
+        object_ref(mr->owner);
+    }
+}
+
+void memory_region_unref(MemoryRegion *mr)
+{
+    if (mr && mr->owner) {
+        object_unref(mr->owner);
+    }
+}
+
 uint64_t memory_region_size(MemoryRegion *mr)
 {
     if (int128_eq(mr->size, int128_2_64())) {
@@ -1188,11 +1199,13 @@
     FlatRange *fr;
 
     QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
-        FOR_EACH_FLAT_RANGE(fr, as->current_map) {
+        FlatView *view = address_space_get_flatview(as);
+        FOR_EACH_FLAT_RANGE(fr, view) {
             if (fr->mr == mr) {
                 MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync);
             }
         }
+        flatview_unref(view);
     }
 }
 
@@ -1238,12 +1251,14 @@
 
 static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpace *as)
 {
+    FlatView *view;
     FlatRange *fr;
     CoalescedMemoryRange *cmr;
     AddrRange tmp;
     MemoryRegionSection section;
 
-    FOR_EACH_FLAT_RANGE(fr, as->current_map) {
+    view = address_space_get_flatview(as);
+    FOR_EACH_FLAT_RANGE(fr, view) {
         if (fr->mr == mr) {
             section = (MemoryRegionSection) {
                 .address_space = as,
@@ -1268,6 +1283,7 @@
             }
         }
     }
+    flatview_unref(view);
 }
 
 static void memory_region_update_coalesced_range(MemoryRegion *mr)
@@ -1400,6 +1416,7 @@
     memory_region_transaction_begin();
 
     assert(!subregion->parent);
+    memory_region_ref(subregion);
     subregion->parent = mr;
     subregion->addr = offset;
     QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
@@ -1462,6 +1479,7 @@
     assert(subregion->parent == mr);
     subregion->parent = NULL;
     QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
+    memory_region_unref(subregion);
     memory_region_update_pending |= mr->enabled && subregion->enabled;
     memory_region_transaction_commit();
 }
@@ -1489,12 +1507,14 @@
     }
 
     memory_region_transaction_begin();
+    memory_region_ref(mr);
     memory_region_del_subregion(parent, mr);
     if (may_overlap) {
         memory_region_add_subregion_overlap(parent, addr, mr, priority);
     } else {
         memory_region_add_subregion(parent, addr, mr);
     }
+    memory_region_unref(mr);
     memory_region_transaction_commit();
 }
 
@@ -1530,12 +1550,22 @@
     return 0;
 }
 
-static FlatRange *address_space_lookup(AddressSpace *as, AddrRange addr)
+static FlatRange *flatview_lookup(FlatView *view, AddrRange addr)
 {
-    return bsearch(&addr, as->current_map->ranges, as->current_map->nr,
+    return bsearch(&addr, view->ranges, view->nr,
                    sizeof(FlatRange), cmp_flatrange_addr);
 }
 
+bool memory_region_present(MemoryRegion *parent, hwaddr addr)
+{
+    MemoryRegion *mr = memory_region_find(parent, addr, 1).mr;
+    if (!mr) {
+        return false;
+    }
+    memory_region_unref(mr);
+    return true;
+}
+
 MemoryRegionSection memory_region_find(MemoryRegion *mr,
                                        hwaddr addr, uint64_t size)
 {
@@ -1543,6 +1573,7 @@
     MemoryRegion *root;
     AddressSpace *as;
     AddrRange range;
+    FlatView *view;
     FlatRange *fr;
 
     addr += mr->addr;
@@ -1553,13 +1584,14 @@
 
     as = memory_region_to_address_space(root);
     range = addrrange_make(int128_make64(addr), int128_make64(size));
-    fr = address_space_lookup(as, range);
+
+    view = address_space_get_flatview(as);
+    fr = flatview_lookup(view, range);
     if (!fr) {
         return ret;
     }
 
-    while (fr > as->current_map->ranges
-           && addrrange_intersects(fr[-1].addr, range)) {
+    while (fr > view->ranges && addrrange_intersects(fr[-1].addr, range)) {
         --fr;
     }
 
@@ -1572,16 +1604,22 @@
     ret.size = range.size;
     ret.offset_within_address_space = int128_get64(range.start);
     ret.readonly = fr->readonly;
+    memory_region_ref(ret.mr);
+
+    flatview_unref(view);
     return ret;
 }
 
 void address_space_sync_dirty_bitmap(AddressSpace *as)
 {
+    FlatView *view;
     FlatRange *fr;
 
-    FOR_EACH_FLAT_RANGE(fr, as->current_map) {
+    view = address_space_get_flatview(as);
+    FOR_EACH_FLAT_RANGE(fr, view) {
         MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync);
     }
+    flatview_unref(view);
 }
 
 void memory_global_dirty_log_start(void)
@@ -1599,6 +1637,7 @@
 static void listener_add_address_space(MemoryListener *listener,
                                        AddressSpace *as)
 {
+    FlatView *view;
     FlatRange *fr;
 
     if (listener->address_space_filter
@@ -1612,7 +1651,8 @@
         }
     }
 
-    FOR_EACH_FLAT_RANGE(fr, as->current_map) {
+    view = address_space_get_flatview(as);
+    FOR_EACH_FLAT_RANGE(fr, view) {
         MemoryRegionSection section = {
             .mr = fr->mr,
             .address_space = as,
@@ -1625,6 +1665,7 @@
             listener->region_add(listener, &section);
         }
     }
+    flatview_unref(view);
 }
 
 void memory_listener_register(MemoryListener *listener, AddressSpace *filter)
@@ -1658,6 +1699,10 @@
 
 void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
 {
+    if (QTAILQ_EMPTY(&address_spaces)) {
+        memory_init();
+    }
+
     memory_region_transaction_begin();
     as->root = root;
     as->current_map = g_new(FlatView, 1);
@@ -1679,9 +1724,8 @@
     memory_region_transaction_commit();
     QTAILQ_REMOVE(&address_spaces, as, address_spaces_link);
     address_space_destroy_dispatch(as);
-    flatview_destroy(as->current_map);
+    flatview_unref(as->current_map);
     g_free(as->name);
-    g_free(as->current_map);
     g_free(as->ioeventfds);
 }
 
diff --git a/migration.c b/migration.c
index a704d48..635a7e7 100644
--- a/migration.c
+++ b/migration.c
@@ -293,8 +293,7 @@
 
 static void migrate_finish_set_state(MigrationState *s, int new_state)
 {
-    if (__sync_val_compare_and_swap(&s->state, MIG_STATE_ACTIVE,
-                                    new_state) == new_state) {
+    if (atomic_cmpxchg(&s->state, MIG_STATE_ACTIVE, new_state) == new_state) {
         trace_migrate_set_state(new_state);
     }
 }
diff --git a/qemu-char.c b/qemu-char.c
index 6cec5d7..18c42a3 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -926,7 +926,6 @@
         tty.c_cc[VMIN] = 1;
         tty.c_cc[VTIME] = 0;
     }
-    /* if graphical mode, we allow Ctrl-C handling */
     if (!stdio_allow_signal)
         tty.c_lflag &= ~ISIG;
 
@@ -955,7 +954,6 @@
     chr = qemu_chr_open_fd(0, 1);
     chr->chr_close = qemu_chr_close_stdio;
     chr->chr_set_echo = qemu_chr_set_echo_stdio;
-    stdio_allow_signal = display_type != DT_NOGRAPHIC;
     if (opts->has_signal) {
         stdio_allow_signal = opts->signal;
     }
@@ -2932,6 +2930,14 @@
     if (strstart(filename, "mon:", &p)) {
         filename = p;
         qemu_opt_set(opts, "mux", "on");
+        if (strcmp(filename, "stdio") == 0) {
+            /* Monitor is muxed to stdio: do not exit on Ctrl+C by default
+             * but pass it to the guest.  Handle this only for compat syntax,
+             * for -chardev syntax we have special option for this.
+             * This is what -nographic did, redirecting+muxing serial+monitor
+             * to stdio causing Ctrl+C to be passed to guest. */
+            qemu_opt_set(opts, "signal", "off");
+        }
     }
 
     if (strcmp(filename, "null")    == 0 ||
@@ -3060,8 +3066,7 @@
 {
     backend->stdio = g_new0(ChardevStdio, 1);
     backend->stdio->has_signal = true;
-    backend->stdio->signal =
-        qemu_opt_get_bool(opts, "signal", display_type != DT_NOGRAPHIC);
+    backend->stdio->signal = qemu_opt_get_bool(opts, "signal", true);
 }
 
 static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
diff --git a/qemu-options.hx b/qemu-options.hx
index 137a39b..7cc4d8e 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -842,7 +842,8 @@
 Normally, QEMU uses SDL to display the VGA output. With this option,
 you can totally disable graphical output so that QEMU is a simple
 command line application. The emulated serial port is redirected on
-the console. Therefore, you can still use QEMU to debug a Linux kernel
+the console and muxed with the monitor (unless redirected elsewhere
+explicitly). Therefore, you can still use QEMU to debug a Linux kernel
 with a serial console.
 ETEXI
 
@@ -2485,14 +2486,15 @@
 @item mon:@var{dev_string}
 This is a special option to allow the monitor to be multiplexed onto
 another serial port.  The monitor is accessed with key sequence of
-@key{Control-a} and then pressing @key{c}. See monitor access
-@ref{pcsys_keys} in the -nographic section for more keys.
+@key{Control-a} and then pressing @key{c}.
 @var{dev_string} should be any one of the serial devices specified
 above.  An example to multiplex the monitor onto a telnet server
 listening on port 4444 would be:
 @table @code
 @item -serial mon:telnet::4444,server,nowait
 @end table
+When monitor is multiplexed to stdio this way, Ctrl+C will not terminate
+QEMU anymore but will be passed to the guest instead.
 
 @item braille
 Braille device.  This will use BrlAPI to display the braille output on a real
diff --git a/qom/object.c b/qom/object.c
index 803b94b..b2479d1 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -531,14 +531,14 @@
 #ifdef CONFIG_QOM_CAST_DEBUG
     int i;
 
-    for (i = 0; i < OBJECT_CLASS_CAST_CACHE; i++) {
+    for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) {
         if (class->cast_cache[i] == typename) {
             ret = class;
             goto out;
         }
     }
 #else
-    if (!class->interfaces) {
+    if (!class || !class->interfaces) {
         return class;
     }
 #endif
@@ -551,7 +551,7 @@
     }
 
 #ifdef CONFIG_QOM_CAST_DEBUG
-    if (ret == class) {
+    if (class && ret == class) {
         for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
             class->cast_cache[i - 1] = class->cast_cache[i];
         }
@@ -683,16 +683,15 @@
 
 void object_ref(Object *obj)
 {
-    obj->ref++;
+     atomic_inc(&obj->ref);
 }
 
 void object_unref(Object *obj)
 {
     g_assert(obj->ref > 0);
-    obj->ref--;
 
     /* parent always holds a reference to its children */
-    if (obj->ref == 0) {
+    if (atomic_fetch_dec(&obj->ref) == 1) {
         object_finalize(obj);
     }
 }
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index d3937a2..b92e00d 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -233,6 +233,7 @@
                 abort();
             }
         }
+        memory_region_unref(kd->mr);
         g_free(kd);
     }
 }
@@ -258,6 +259,7 @@
     kd->kda.id = devid;
     kd->kda.addr = -1;
     QSLIST_INSERT_HEAD(&kvm_devices_head, kd, entries);
+    memory_region_ref(kd->mr);
 }
 
 bool write_kvmstate_to_list(ARMCPU *cpu)
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 39f4fbb..15da3d7 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -318,7 +318,7 @@
 
     if ((env->mcg_cap & MCG_SER_P) && addr
         && (code == BUS_MCEERR_AR || code == BUS_MCEERR_AO)) {
-        if (qemu_ram_addr_from_host(addr, &ram_addr) ||
+        if (qemu_ram_addr_from_host(addr, &ram_addr) == NULL ||
             !kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
             fprintf(stderr, "Hardware memory error for memory used by "
                     "QEMU itself instead of guest system!\n");
@@ -350,7 +350,7 @@
         hwaddr paddr;
 
         /* Hope we are lucky for AO MCE */
-        if (qemu_ram_addr_from_host(addr, &ram_addr) ||
+        if (qemu_ram_addr_from_host(addr, &ram_addr) == NULL ||
             !kvm_physical_memory_addr_from_host(CPU(first_cpu)->kvm_state,
                                                 addr, &paddr)) {
             fprintf(stderr, "Hardware memory error for memory used by "
@@ -741,7 +741,6 @@
 
 int kvm_arch_init(KVMState *s)
 {
-    QemuOptsList *list = qemu_find_opts("machine");
     uint64_t identity_base = 0xfffbc000;
     uint64_t shadow_mem;
     int ret;
@@ -790,15 +789,13 @@
     }
     qemu_register_reset(kvm_unpoison_all, NULL);
 
-    if (!QTAILQ_EMPTY(&list->head)) {
-        shadow_mem = qemu_opt_get_size(QTAILQ_FIRST(&list->head),
-                                       "kvm_shadow_mem", -1);
-        if (shadow_mem != -1) {
-            shadow_mem /= 4096;
-            ret = kvm_vm_ioctl(s, KVM_SET_NR_MMU_PAGES, shadow_mem);
-            if (ret < 0) {
-                return ret;
-            }
+    shadow_mem = qemu_opt_get_size(qemu_get_machine_opts(),
+                                   "kvm_shadow_mem", -1);
+    if (shadow_mem != -1) {
+        shadow_mem /= 4096;
+        ret = kvm_vm_ioctl(s, KVM_SET_NR_MMU_PAGES, shadow_mem);
+        if (ret < 0) {
+            return ret;
         }
     }
     return 0;
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index c89dd58..e95ad4a 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1560,7 +1560,7 @@
     };
 
     rma_region = g_new(MemoryRegion, 1);
-    memory_region_init_ram_ptr(rma_region, name, size, rma);
+    memory_region_init_ram_ptr(rma_region, NULL, name, size, rma);
     vmstate_register_ram_global(rma_region);
     memory_region_add_subregion(sysmem, 0, rma_region);
 
diff --git a/target-sparc/mmu_helper.c b/target-sparc/mmu_helper.c
index 3983c96..740cbe8 100644
--- a/target-sparc/mmu_helper.c
+++ b/target-sparc/mmu_helper.c
@@ -845,6 +845,7 @@
         }
     }
     section = memory_region_find(get_system_memory(), phys_addr, 1);
+    memory_region_unref(section.mr);
     if (!int128_nz(section.size)) {
         return -1;
     }
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
index 97e4a5b..51e5092 100644
--- a/tcg/aarch64/tcg-target.h
+++ b/tcg/aarch64/tcg-target.h
@@ -40,6 +40,7 @@
 
 /* optional instructions */
 #define TCG_TARGET_HAS_div_i32          0
+#define TCG_TARGET_HAS_rem_i32          0
 #define TCG_TARGET_HAS_ext8s_i32        1
 #define TCG_TARGET_HAS_ext16s_i32       1
 #define TCG_TARGET_HAS_ext8u_i32        1
@@ -62,6 +63,7 @@
 #define TCG_TARGET_HAS_muls2_i32        0
 
 #define TCG_TARGET_HAS_div_i64          0
+#define TCG_TARGET_HAS_rem_i64          0
 #define TCG_TARGET_HAS_ext8s_i64        1
 #define TCG_TARGET_HAS_ext16s_i64       1
 #define TCG_TARGET_HAS_ext32s_i64       1
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 6be736b..6c4854d 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -22,50 +22,43 @@
  * THE SOFTWARE.
  */
 
-#if defined(__ARM_ARCH_7__) ||  \
-    defined(__ARM_ARCH_7A__) || \
-    defined(__ARM_ARCH_7EM__) || \
-    defined(__ARM_ARCH_7M__) || \
-    defined(__ARM_ARCH_7R__)
-#define USE_ARMV7_INSTRUCTIONS
+/* The __ARM_ARCH define is provided by gcc 4.8.  Construct it otherwise.  */
+#ifndef __ARM_ARCH
+# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
+     || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
+     || defined(__ARM_ARCH_7EM__)
+#  define __ARM_ARCH 7
+# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
+       || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \
+       || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__)
+#  define __ARM_ARCH 6
+# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5E__) \
+       || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \
+       || defined(__ARM_ARCH_5TEJ__)
+#  define __ARM_ARCH 5
+# else
+#  define __ARM_ARCH 4
+# endif
 #endif
 
-#if defined(USE_ARMV7_INSTRUCTIONS) || \
-    defined(__ARM_ARCH_6J__) || \
-    defined(__ARM_ARCH_6K__) || \
-    defined(__ARM_ARCH_6T2__) || \
-    defined(__ARM_ARCH_6Z__) || \
-    defined(__ARM_ARCH_6ZK__)
-#define USE_ARMV6_INSTRUCTIONS
-#endif
+static int arm_arch = __ARM_ARCH;
 
-#if defined(USE_ARMV6_INSTRUCTIONS) || \
-    defined(__ARM_ARCH_5T__) || \
-    defined(__ARM_ARCH_5TE__) || \
-    defined(__ARM_ARCH_5TEJ__)
-#define USE_ARMV5_INSTRUCTIONS
-#endif
-
-#ifdef USE_ARMV5_INSTRUCTIONS
-static const int use_armv5_instructions = 1;
+#if defined(__ARM_ARCH_5T__) \
+    || defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__)
+# define use_armv5t_instructions 1
 #else
-static const int use_armv5_instructions = 0;
+# define use_armv5t_instructions use_armv6_instructions
 #endif
-#undef USE_ARMV5_INSTRUCTIONS
 
-#ifdef USE_ARMV6_INSTRUCTIONS
-static const int use_armv6_instructions = 1;
-#else
-static const int use_armv6_instructions = 0;
-#endif
-#undef USE_ARMV6_INSTRUCTIONS
+#define use_armv6_instructions  (__ARM_ARCH >= 6 || arm_arch >= 6)
+#define use_armv7_instructions  (__ARM_ARCH >= 7 || arm_arch >= 7)
 
-#ifdef USE_ARMV7_INSTRUCTIONS
-static const int use_armv7_instructions = 1;
-#else
-static const int use_armv7_instructions = 0;
+#ifndef use_idiv_instructions
+bool use_idiv_instructions;
 #endif
-#undef USE_ARMV7_INSTRUCTIONS
+#ifdef CONFIG_GETAUXVAL
+# include <sys/auxv.h>
+#endif
 
 #ifndef NDEBUG
 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
@@ -1023,7 +1016,7 @@
     if (val - 8 < 0x02000000 && val - 8 >= -0x02000000) {
         if (addr & 1) {
             /* Use BLX if the target is in Thumb mode */
-            if (!use_armv5_instructions) {
+            if (!use_armv5t_instructions) {
                 tcg_abort();
             }
             tcg_out_blx_imm(s, val);
@@ -1042,7 +1035,7 @@
 
 static inline void tcg_out_callr(TCGContext *s, int cond, int arg)
 {
-    if (use_armv5_instructions) {
+    if (use_armv5t_instructions) {
         tcg_out_blx(s, cond, arg);
     } else {
         tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
@@ -1926,18 +1919,6 @@
     case INDEX_op_divu_i32:
         tcg_out_udiv(s, COND_AL, args[0], args[1], args[2]);
         break;
-    case INDEX_op_rem_i32:
-        tcg_out_sdiv(s, COND_AL, TCG_REG_TMP, args[1], args[2]);
-        tcg_out_mul32(s, COND_AL, TCG_REG_TMP, TCG_REG_TMP, args[2]);
-        tcg_out_dat_reg(s, COND_AL, ARITH_SUB, args[0], args[1], TCG_REG_TMP,
-                        SHIFT_IMM_LSL(0));
-        break;
-    case INDEX_op_remu_i32:
-        tcg_out_udiv(s, COND_AL, TCG_REG_TMP, args[1], args[2]);
-        tcg_out_mul32(s, COND_AL, TCG_REG_TMP, TCG_REG_TMP, args[2]);
-        tcg_out_dat_reg(s, COND_AL, ARITH_SUB, args[0], args[1], TCG_REG_TMP,
-                        SHIFT_IMM_LSL(0));
-        break;
 
     default:
         tcg_abort();
@@ -2041,18 +2022,31 @@
 
     { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
 
-#if TCG_TARGET_HAS_div_i32
     { INDEX_op_div_i32, { "r", "r", "r" } },
-    { INDEX_op_rem_i32, { "r", "r", "r" } },
     { INDEX_op_divu_i32, { "r", "r", "r" } },
-    { INDEX_op_remu_i32, { "r", "r", "r" } },
-#endif
 
     { -1 },
 };
 
 static void tcg_target_init(TCGContext *s)
 {
+#if defined(CONFIG_GETAUXVAL)
+    /* Only probe for the platform and capabilities if we havn't already
+       determined maximum values at compile time.  */
+# if !defined(use_idiv_instructions)
+    {
+        unsigned long hwcap = getauxval(AT_HWCAP);
+        use_idiv_instructions = (hwcap & HWCAP_ARM_IDIVA) != 0;
+    }
+# endif
+    if (__ARM_ARCH < 7) {
+        const char *pl = (const char *)getauxval(AT_PLATFORM);
+        if (pl != NULL && pl[0] == 'v' && pl[1] >= '4' && pl[1] <= '9') {
+            arm_arch = pl[1] - '0';
+        }
+    }
+#endif /* GETAUXVAL */
+
     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
     tcg_regset_set32(tcg_target_call_clobber_regs, 0,
                      (1 << TCG_REG_R0) |
@@ -2094,23 +2088,31 @@
     tcg_out_movi32(s, COND_AL, ret, arg);
 }
 
+/* Compute frame size via macros, to share between tcg_target_qemu_prologue
+   and tcg_register_jit.  */
+
+#define PUSH_SIZE  ((11 - 4 + 1 + 1) * sizeof(tcg_target_long))
+
+#define FRAME_SIZE \
+    ((PUSH_SIZE \
+      + TCG_STATIC_CALL_ARGS_SIZE \
+      + CPU_TEMP_BUF_NLONGS * sizeof(long) \
+      + TCG_TARGET_STACK_ALIGN - 1) \
+     & -TCG_TARGET_STACK_ALIGN)
+
 static void tcg_target_qemu_prologue(TCGContext *s)
 {
-    int frame_size;
+    int stack_addend;
 
     /* Calling convention requires us to save r4-r11 and lr.  */
     /* stmdb sp!, { r4 - r11, lr } */
     tcg_out32(s, (COND_AL << 28) | 0x092d4ff0);
 
-    /* Allocate the local stack frame.  */
-    frame_size = TCG_STATIC_CALL_ARGS_SIZE;
-    frame_size += CPU_TEMP_BUF_NLONGS * sizeof(long);
-    /* We saved an odd number of registers above; keep an 8 aligned stack.  */
-    frame_size = ((frame_size + TCG_TARGET_STACK_ALIGN - 1)
-                  & -TCG_TARGET_STACK_ALIGN) + 4;
+    /* Reserve callee argument and tcg temp space.  */
+    stack_addend = FRAME_SIZE - PUSH_SIZE;
 
     tcg_out_dat_rI(s, COND_AL, ARITH_SUB, TCG_REG_CALL_STACK,
-                   TCG_REG_CALL_STACK, frame_size, 1);
+                   TCG_REG_CALL_STACK, stack_addend, 1);
     tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
                   CPU_TEMP_BUF_NLONGS * sizeof(long));
 
@@ -2121,8 +2123,58 @@
 
     /* Epilogue.  We branch here via tb_ret_addr.  */
     tcg_out_dat_rI(s, COND_AL, ARITH_ADD, TCG_REG_CALL_STACK,
-                   TCG_REG_CALL_STACK, frame_size, 1);
+                   TCG_REG_CALL_STACK, stack_addend, 1);
 
     /* ldmia sp!, { r4 - r11, pc } */
     tcg_out32(s, (COND_AL << 28) | 0x08bd8ff0);
 }
+
+typedef struct {
+    DebugFrameCIE cie;
+    DebugFrameFDEHeader fde;
+    uint8_t fde_def_cfa[4];
+    uint8_t fde_reg_ofs[18];
+} DebugFrame;
+
+#define ELF_HOST_MACHINE EM_ARM
+
+/* We're expecting a 2 byte uleb128 encoded value.  */
+QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
+
+static DebugFrame debug_frame = {
+    .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
+    .cie.id = -1,
+    .cie.version = 1,
+    .cie.code_align = 1,
+    .cie.data_align = 0x7c,             /* sleb128 -4 */
+    .cie.return_column = 14,
+
+    /* Total FDE size does not include the "len" member.  */
+    .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
+
+    .fde_def_cfa = {
+        12, 13,                         /* DW_CFA_def_cfa sp, ... */
+        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
+        (FRAME_SIZE >> 7)
+    },
+    .fde_reg_ofs = {
+        /* The following must match the stmdb in the prologue.  */
+        0x8e, 1,                        /* DW_CFA_offset, lr, -4 */
+        0x8b, 2,                        /* DW_CFA_offset, r11, -8 */
+        0x8a, 3,                        /* DW_CFA_offset, r10, -12 */
+        0x89, 4,                        /* DW_CFA_offset, r9, -16 */
+        0x88, 5,                        /* DW_CFA_offset, r8, -20 */
+        0x87, 6,                        /* DW_CFA_offset, r7, -24 */
+        0x86, 7,                        /* DW_CFA_offset, r6, -28 */
+        0x85, 8,                        /* DW_CFA_offset, r5, -32 */
+        0x84, 9,                        /* DW_CFA_offset, r4, -36 */
+    }
+};
+
+void tcg_register_jit(void *buf, size_t buf_size)
+{
+    debug_frame.fde.func_start = (tcg_target_long) buf;
+    debug_frame.fde.func_len = buf_size;
+
+    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
+}
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 3be41cc..5cd9d6a 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -49,6 +49,13 @@
 
 #define TCG_TARGET_NB_REGS 16
 
+#ifdef __ARM_ARCH_EXT_IDIV__
+#define use_idiv_instructions  1
+#else
+extern bool use_idiv_instructions;
+#endif
+
+
 /* used for function call generation */
 #define TCG_REG_CALL_STACK		TCG_REG_R13
 #define TCG_TARGET_STACK_ALIGN		8
@@ -73,12 +80,8 @@
 #define TCG_TARGET_HAS_deposit_i32      1
 #define TCG_TARGET_HAS_movcond_i32      1
 #define TCG_TARGET_HAS_muls2_i32        1
-
-#ifdef __ARM_ARCH_EXT_IDIV__
-#define TCG_TARGET_HAS_div_i32          1
-#else
-#define TCG_TARGET_HAS_div_i32          0
-#endif
+#define TCG_TARGET_HAS_div_i32          use_idiv_instructions
+#define TCG_TARGET_HAS_rem_i32          0
 
 extern bool tcg_target_deposit_valid(int ofs, int len);
 #define TCG_TARGET_deposit_i32_valid  tcg_target_deposit_valid
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 656e736..68f77ba 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -1766,28 +1766,11 @@
 }
 
 typedef struct {
-    uint32_t len __attribute__((aligned((sizeof(void *)))));
-    uint32_t id;
-    uint8_t version;
-    char augmentation[1];
-    uint8_t code_align;
-    uint8_t data_align;
-    uint8_t return_column;
-} DebugFrameCIE;
-
-typedef struct {
-    uint32_t len __attribute__((aligned((sizeof(void *)))));
-    uint32_t cie_offset;
-    tcg_target_long func_start __attribute__((packed));
-    tcg_target_long func_len __attribute__((packed));
-    uint8_t def_cfa[4];
-    uint8_t ret_ofs[3];
-    uint8_t reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
-} DebugFrameFDE;
-
-typedef struct {
     DebugFrameCIE cie;
-    DebugFrameFDE fde;
+    DebugFrameFDEHeader fde;
+    uint8_t fde_def_cfa[4];
+    uint8_t fde_ret_ofs[3];
+    uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
 } DebugFrame;
 
 #define ELF_HOST_MACHINE  EM_PARISC
@@ -1806,16 +1789,18 @@
     .cie.data_align = 1,
     .cie.return_column = 2,
 
-    .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
-    .fde.def_cfa = {
+    /* Total FDE size does not include the "len" member.  */
+    .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
+
+    .fde_def_cfa = {
         0x12, 30,                       /* DW_CFA_def_cfa_sf sp, ... */
         (-FRAME_SIZE & 0x7f) | 0x80,     /* ... sleb128 -FRAME_SIZE */
         (-FRAME_SIZE >> 7) & 0x7f
     },
-    .fde.ret_ofs = {
+    .fde_ret_ofs = {
         0x11, 2, (-20 / 4) & 0x7f       /* DW_CFA_offset_extended_sf r2, 20 */
     },
-    .fde.reg_ofs = {
+    .fde_reg_ofs = {
         /* This must match the ordering in tcg_target_callee_save_regs.  */
         0x80 + 4, 0,                    /* DW_CFA_offset r4, 0 */
         0x80 + 5, 4,                    /* DW_CFA_offset r5, 4 */
diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h
index ebd53d9..25467bd 100644
--- a/tcg/hppa/tcg-target.h
+++ b/tcg/hppa/tcg-target.h
@@ -85,6 +85,7 @@
 
 /* optional instructions */
 #define TCG_TARGET_HAS_div_i32          0
+#define TCG_TARGET_HAS_rem_i32          0
 #define TCG_TARGET_HAS_rot_i32          1
 #define TCG_TARGET_HAS_ext8s_i32        1
 #define TCG_TARGET_HAS_ext16s_i32       1
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 9e95477..87eeab3 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -2312,29 +2312,15 @@
 }
 
 typedef struct {
-    uint32_t len __attribute__((aligned((sizeof(void *)))));
-    uint32_t id;
-    uint8_t version;
-    char augmentation[1];
-    uint8_t code_align;
-    uint8_t data_align;
-    uint8_t return_column;
-} DebugFrameCIE;
-
-typedef struct {
-    uint32_t len __attribute__((aligned((sizeof(void *)))));
-    uint32_t cie_offset;
-    tcg_target_long func_start __attribute__((packed));
-    tcg_target_long func_len __attribute__((packed));
-    uint8_t def_cfa[4];
-    uint8_t reg_ofs[14];
-} DebugFrameFDE;
-
-typedef struct {
     DebugFrameCIE cie;
-    DebugFrameFDE fde;
+    DebugFrameFDEHeader fde;
+    uint8_t fde_def_cfa[4];
+    uint8_t fde_reg_ofs[14];
 } DebugFrame;
 
+/* We're expecting a 2 byte uleb128 encoded value.  */
+QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
+
 #if !defined(__ELF__)
     /* Host machine without ELF. */
 #elif TCG_TARGET_REG_BITS == 64
@@ -2347,13 +2333,15 @@
     .cie.data_align = 0x78,             /* sleb128 -8 */
     .cie.return_column = 16,
 
-    .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
-    .fde.def_cfa = {
+    /* Total FDE size does not include the "len" member.  */
+    .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
+
+    .fde_def_cfa = {
         12, 7,                          /* DW_CFA_def_cfa %rsp, ... */
         (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
         (FRAME_SIZE >> 7)
     },
-    .fde.reg_ofs = {
+    .fde_reg_ofs = {
         0x90, 1,                        /* DW_CFA_offset, %rip, -8 */
         /* The following ordering must match tcg_target_callee_save_regs.  */
         0x86, 2,                        /* DW_CFA_offset, %rbp, -16 */
@@ -2374,13 +2362,15 @@
     .cie.data_align = 0x7c,             /* sleb128 -4 */
     .cie.return_column = 8,
 
-    .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
-    .fde.def_cfa = {
+    /* Total FDE size does not include the "len" member.  */
+    .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
+
+    .fde_def_cfa = {
         12, 4,                          /* DW_CFA_def_cfa %esp, ... */
         (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
         (FRAME_SIZE >> 7)
     },
-    .fde.reg_ofs = {
+    .fde_reg_ofs = {
         0x88, 1,                        /* DW_CFA_offset, %eip, -4 */
         /* The following ordering must match tcg_target_callee_save_regs.  */
         0x85, 2,                        /* DW_CFA_offset, %ebp, -8 */
@@ -2394,9 +2384,6 @@
 #if defined(ELF_HOST_MACHINE)
 void tcg_register_jit(void *buf, size_t buf_size)
 {
-    /* We're expecting a 2 byte uleb128 encoded value.  */
-    assert(FRAME_SIZE >> 14 == 0);
-
     debug_frame.fde.func_start = (tcg_target_long) buf;
     debug_frame.fde.func_len = buf_size;
 
diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h
index e3d72ea..f32d519 100644
--- a/tcg/ia64/tcg-target.h
+++ b/tcg/ia64/tcg-target.h
@@ -104,7 +104,9 @@
 
 /* optional instructions */
 #define TCG_TARGET_HAS_div_i32          0
+#define TCG_TARGET_HAS_rem_i32          0
 #define TCG_TARGET_HAS_div_i64          0
+#define TCG_TARGET_HAS_rem_i64          0
 #define TCG_TARGET_HAS_andc_i32         1
 #define TCG_TARGET_HAS_andc_i64         1
 #define TCG_TARGET_HAS_bswap16_i32      1
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 6155327..a438950 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -79,6 +79,7 @@
 
 /* optional instructions */
 #define TCG_TARGET_HAS_div_i32          1
+#define TCG_TARGET_HAS_rem_i32          1
 #define TCG_TARGET_HAS_not_i32          1
 #define TCG_TARGET_HAS_nor_i32          1
 #define TCG_TARGET_HAS_ext8s_i32        1
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 29ca934..453ab6b 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -1671,18 +1671,6 @@
         tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
         break;
 
-    case INDEX_op_rem_i32:
-        tcg_out32 (s, DIVW | TAB (0, args[1], args[2]));
-        tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
-        tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
-        break;
-
-    case INDEX_op_remu_i32:
-        tcg_out32 (s, DIVWU | TAB (0, args[1], args[2]));
-        tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
-        tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
-        break;
-
     case INDEX_op_mulu2_i32:
         if (args[0] == args[2] || args[0] == args[3]) {
             tcg_out32 (s, MULLW | TAB (0, args[2], args[3]));
@@ -1992,8 +1980,6 @@
     { INDEX_op_mul_i32, { "r", "r", "ri" } },
     { INDEX_op_div_i32, { "r", "r", "r" } },
     { INDEX_op_divu_i32, { "r", "r", "r" } },
-    { INDEX_op_rem_i32, { "r", "r", "r" } },
-    { INDEX_op_remu_i32, { "r", "r", "r" } },
     { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
     { INDEX_op_sub_i32, { "r", "r", "ri" } },
     { INDEX_op_and_i32, { "r", "r", "ri" } },
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index 17a6bb3..b42d97c 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -78,6 +78,7 @@
 
 /* optional instructions */
 #define TCG_TARGET_HAS_div_i32          1
+#define TCG_TARGET_HAS_rem_i32          0
 #define TCG_TARGET_HAS_rot_i32          1
 #define TCG_TARGET_HAS_ext8s_i32        1
 #define TCG_TARGET_HAS_ext16s_i32       1
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 606b73d..0678de2 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -1617,18 +1617,6 @@
         tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
         break;
 
-    case INDEX_op_rem_i32:
-        tcg_out32 (s, DIVW | TAB (0, args[1], args[2]));
-        tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
-        tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
-        break;
-
-    case INDEX_op_remu_i32:
-        tcg_out32 (s, DIVWU | TAB (0, args[1], args[2]));
-        tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
-        tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
-        break;
-
     case INDEX_op_shl_i32:
         if (const_args[2]) {
             tcg_out_rlw(s, RLWINM, args[0], args[1], args[2], 0, 31 - args[2]);
@@ -1786,16 +1774,6 @@
     case INDEX_op_divu_i64:
         tcg_out32 (s, DIVDU | TAB (args[0], args[1], args[2]));
         break;
-    case INDEX_op_rem_i64:
-        tcg_out32 (s, DIVD | TAB (0, args[1], args[2]));
-        tcg_out32 (s, MULLD | TAB (0, 0, args[2]));
-        tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
-        break;
-    case INDEX_op_remu_i64:
-        tcg_out32 (s, DIVDU | TAB (0, args[1], args[2]));
-        tcg_out32 (s, MULLD | TAB (0, 0, args[2]));
-        tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
-        break;
 
     case INDEX_op_qemu_ld8u:
         tcg_out_qemu_ld (s, args, 0);
@@ -2064,8 +2042,6 @@
     { INDEX_op_mul_i32, { "r", "r", "rI" } },
     { INDEX_op_div_i32, { "r", "r", "r" } },
     { INDEX_op_divu_i32, { "r", "r", "r" } },
-    { INDEX_op_rem_i32, { "r", "r", "r" } },
-    { INDEX_op_remu_i32, { "r", "r", "r" } },
     { INDEX_op_sub_i32, { "r", "rI", "ri" } },
     { INDEX_op_and_i32, { "r", "r", "ri" } },
     { INDEX_op_or_i32, { "r", "r", "ri" } },
@@ -2108,8 +2084,6 @@
     { INDEX_op_mul_i64, { "r", "r", "rI" } },
     { INDEX_op_div_i64, { "r", "r", "r" } },
     { INDEX_op_divu_i64, { "r", "r", "r" } },
-    { INDEX_op_rem_i64, { "r", "r", "r" } },
-    { INDEX_op_remu_i64, { "r", "r", "r" } },
 
     { INDEX_op_neg_i64, { "r", "r" } },
     { INDEX_op_not_i64, { "r", "r" } },
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
index cb77634..48fc6e2 100644
--- a/tcg/ppc64/tcg-target.h
+++ b/tcg/ppc64/tcg-target.h
@@ -76,6 +76,7 @@
 
 /* optional instructions */
 #define TCG_TARGET_HAS_div_i32          1
+#define TCG_TARGET_HAS_rem_i32          0
 #define TCG_TARGET_HAS_rot_i32          1
 #define TCG_TARGET_HAS_ext8s_i32        1
 #define TCG_TARGET_HAS_ext16s_i32       1
@@ -96,6 +97,7 @@
 #define TCG_TARGET_HAS_muls2_i32        0
 
 #define TCG_TARGET_HAS_div_i64          1
+#define TCG_TARGET_HAS_rem_i64          0
 #define TCG_TARGET_HAS_rot_i64          1
 #define TCG_TARGET_HAS_ext8s_i64        1
 #define TCG_TARGET_HAS_ext16s_i64       1
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 025af9b..5bfd29c 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -1647,28 +1647,11 @@
 #endif
 
 typedef struct {
-    uint32_t len __attribute__((aligned((sizeof(void *)))));
-    uint32_t id;
-    uint8_t version;
-    char augmentation[1];
-    uint8_t code_align;
-    uint8_t data_align;
-    uint8_t return_column;
-} DebugFrameCIE;
-
-typedef struct {
-    uint32_t len __attribute__((aligned((sizeof(void *)))));
-    uint32_t cie_offset;
-    tcg_target_long func_start __attribute__((packed));
-    tcg_target_long func_len __attribute__((packed));
-    uint8_t def_cfa[TCG_TARGET_REG_BITS == 64 ? 4 : 2];
-    uint8_t win_save;
-    uint8_t ret_save[3];
-} DebugFrameFDE;
-
-typedef struct {
     DebugFrameCIE cie;
-    DebugFrameFDE fde;
+    DebugFrameFDEHeader fde;
+    uint8_t fde_def_cfa[TCG_TARGET_REG_BITS == 64 ? 4 : 2];
+    uint8_t fde_win_save;
+    uint8_t fde_ret_save[3];
 } DebugFrame;
 
 static DebugFrame debug_frame = {
@@ -1679,8 +1662,10 @@
     .cie.data_align = -sizeof(void *) & 0x7f,
     .cie.return_column = 15,            /* o7 */
 
-    .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
-    .fde.def_cfa = {
+    /* Total FDE size does not include the "len" member.  */
+    .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
+
+    .fde_def_cfa = {
 #if TCG_TARGET_REG_BITS == 64
         12, 30,                         /* DW_CFA_def_cfa i6, 2047 */
         (2047 & 0x7f) | 0x80, (2047 >> 7)
@@ -1688,8 +1673,8 @@
         13, 30                          /* DW_CFA_def_cfa_register i6 */
 #endif
     },
-    .fde.win_save = 0x2d,               /* DW_CFA_GNU_window_save */
-    .fde.ret_save = { 9, 15, 31 },      /* DW_CFA_register o7, i7 */
+    .fde_win_save = 0x2d,               /* DW_CFA_GNU_window_save */
+    .fde_ret_save = { 9, 15, 31 },      /* DW_CFA_register o7, i7 */
 };
 
 void tcg_register_jit(void *buf, size_t buf_size)
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
index b5217be..dab52d7 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -86,6 +86,7 @@
 
 /* optional instructions */
 #define TCG_TARGET_HAS_div_i32		1
+#define TCG_TARGET_HAS_rem_i32		1
 #define TCG_TARGET_HAS_rot_i32          0
 #define TCG_TARGET_HAS_ext8s_i32        0
 #define TCG_TARGET_HAS_ext16s_i32       0
@@ -109,6 +110,7 @@
 
 #if TCG_TARGET_REG_BITS == 64
 #define TCG_TARGET_HAS_div_i64          1
+#define TCG_TARGET_HAS_rem_i64          1
 #define TCG_TARGET_HAS_rot_i64          0
 #define TCG_TARGET_HAS_ext8s_i64        0
 #define TCG_TARGET_HAS_ext16s_i64       0
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 94f6043..364964d 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -731,8 +731,14 @@
 
 static inline void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
 {
-    if (TCG_TARGET_HAS_div_i32) {
+    if (TCG_TARGET_HAS_rem_i32) {
         tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2);
+    } else if (TCG_TARGET_HAS_div_i32) {
+        TCGv_i32 t0 = tcg_temp_new_i32();
+        tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2);
+        tcg_gen_mul_i32(t0, t0, arg2);
+        tcg_gen_sub_i32(ret, arg1, t0);
+        tcg_temp_free_i32(t0);
     } else if (TCG_TARGET_HAS_div2_i32) {
         TCGv_i32 t0 = tcg_temp_new_i32();
         tcg_gen_sari_i32(t0, arg1, 31);
@@ -769,8 +775,14 @@
 
 static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
 {
-    if (TCG_TARGET_HAS_div_i32) {
+    if (TCG_TARGET_HAS_rem_i32) {
         tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2);
+    } else if (TCG_TARGET_HAS_div_i32) {
+        TCGv_i32 t0 = tcg_temp_new_i32();
+        tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2);
+        tcg_gen_mul_i32(t0, t0, arg2);
+        tcg_gen_sub_i32(ret, arg1, t0);
+        tcg_temp_free_i32(t0);
     } else if (TCG_TARGET_HAS_div2_i32) {
         TCGv_i32 t0 = tcg_temp_new_i32();
         tcg_gen_movi_i32(t0, 0);
@@ -1361,8 +1373,14 @@
 
 static inline void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
 {
-    if (TCG_TARGET_HAS_div_i64) {
+    if (TCG_TARGET_HAS_rem_i64) {
         tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2);
+    } else if (TCG_TARGET_HAS_div_i64) {
+        TCGv_i64 t0 = tcg_temp_new_i64();
+        tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2);
+        tcg_gen_mul_i64(t0, t0, arg2);
+        tcg_gen_sub_i64(ret, arg1, t0);
+        tcg_temp_free_i64(t0);
     } else if (TCG_TARGET_HAS_div2_i64) {
         TCGv_i64 t0 = tcg_temp_new_i64();
         tcg_gen_sari_i64(t0, arg1, 63);
@@ -1399,8 +1417,14 @@
 
 static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
 {
-    if (TCG_TARGET_HAS_div_i64) {
+    if (TCG_TARGET_HAS_rem_i64) {
         tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2);
+    } else if (TCG_TARGET_HAS_div_i64) {
+        TCGv_i64 t0 = tcg_temp_new_i64();
+        tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2);
+        tcg_gen_mul_i64(t0, t0, arg2);
+        tcg_gen_sub_i64(ret, arg1, t0);
+        tcg_temp_free_i64(t0);
     } else if (TCG_TARGET_HAS_div2_i64) {
         TCGv_i64 t0 = tcg_temp_new_i64();
         tcg_gen_movi_i64(t0, 0);
diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index 4246e9c..a8af5b9 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -27,20 +27,24 @@
  */
 
 /* predefined ops */
-DEF(end, 0, 0, 0, 0) /* must be kept first */
-DEF(nop, 0, 0, 0, 0)
-DEF(nop1, 0, 0, 1, 0)
-DEF(nop2, 0, 0, 2, 0)
-DEF(nop3, 0, 0, 3, 0)
-DEF(nopn, 0, 0, 1, 0) /* variable number of parameters */
+DEF(end, 0, 0, 0, TCG_OPF_NOT_PRESENT) /* must be kept first */
+DEF(nop, 0, 0, 0, TCG_OPF_NOT_PRESENT)
+DEF(nop1, 0, 0, 1, TCG_OPF_NOT_PRESENT)
+DEF(nop2, 0, 0, 2, TCG_OPF_NOT_PRESENT)
+DEF(nop3, 0, 0, 3, TCG_OPF_NOT_PRESENT)
 
-DEF(discard, 1, 0, 0, 0)
+/* variable number of parameters */
+DEF(nopn, 0, 0, 1, TCG_OPF_NOT_PRESENT)
 
-DEF(set_label, 0, 0, 1, TCG_OPF_BB_END)
-DEF(call, 0, 1, 2, TCG_OPF_CALL_CLOBBER) /* variable number of parameters */
+DEF(discard, 1, 0, 0, TCG_OPF_NOT_PRESENT)
+DEF(set_label, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT)
+
+/* variable number of parameters */
+DEF(call, 0, 1, 2, TCG_OPF_CALL_CLOBBER)
+
 DEF(br, 0, 0, 1, TCG_OPF_BB_END)
 
-#define IMPL(X) (X ? 0 : TCG_OPF_NOT_PRESENT)
+#define IMPL(X) (__builtin_constant_p(X) && !(X) ? TCG_OPF_NOT_PRESENT : 0)
 #if TCG_TARGET_REG_BITS == 32
 # define IMPL64  TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT
 #else
@@ -66,8 +70,8 @@
 DEF(mul_i32, 1, 2, 0, 0)
 DEF(div_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32))
 DEF(divu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32))
-DEF(rem_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32))
-DEF(remu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32))
+DEF(rem_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rem_i32))
+DEF(remu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rem_i32))
 DEF(div2_i32, 2, 3, 0, IMPL(TCG_TARGET_HAS_div2_i32))
 DEF(divu2_i32, 2, 3, 0, IMPL(TCG_TARGET_HAS_div2_i32))
 DEF(and_i32, 1, 2, 0, 0)
@@ -126,8 +130,8 @@
 DEF(mul_i64, 1, 2, 0, IMPL64)
 DEF(div_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64))
 DEF(divu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64))
-DEF(rem_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64))
-DEF(remu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64))
+DEF(rem_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rem_i64))
+DEF(remu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rem_i64))
 DEF(div2_i64, 2, 3, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div2_i64))
 DEF(divu2_i64, 2, 3, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div2_i64))
 DEF(and_i64, 1, 2, 0, IMPL64)
@@ -166,9 +170,9 @@
 
 /* QEMU specific */
 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
-DEF(debug_insn_start, 0, 0, 2, 0)
+DEF(debug_insn_start, 0, 0, 2, TCG_OPF_NOT_PRESENT)
 #else
-DEF(debug_insn_start, 0, 0, 1, 0)
+DEF(debug_insn_start, 0, 0, 1, TCG_OPF_NOT_PRESENT)
 #endif
 DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_END)
 DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_END)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 1d8099c..dac8224 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -68,6 +68,24 @@
 static void patch_reloc(uint8_t *code_ptr, int type, 
                         tcg_target_long value, tcg_target_long addend);
 
+/* The CIE and FDE header definitions will be common to all hosts.  */
+typedef struct {
+    uint32_t len __attribute__((aligned((sizeof(void *)))));
+    uint32_t id;
+    uint8_t version;
+    char augmentation[1];
+    uint8_t code_align;
+    uint8_t data_align;
+    uint8_t return_column;
+} DebugFrameCIE;
+
+typedef struct QEMU_PACKED {
+    uint32_t len __attribute__((aligned((sizeof(void *)))));
+    uint32_t cie_offset;
+    tcg_target_long func_start;
+    tcg_target_long func_len;
+} DebugFrameFDEHeader;
+
 static void tcg_register_jit_int(void *buf, size_t size,
                                  void *debug_frame, size_t debug_frame_size)
     __attribute__((unused));
@@ -1160,9 +1178,7 @@
     i = 0;
     for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
         const TCGOpDef *def = &tcg_op_defs[op];
-        if (op < INDEX_op_call
-            || op == INDEX_op_debug_insn_start
-            || (def->flags & TCG_OPF_NOT_PRESENT)) {
+        if (def->flags & TCG_OPF_NOT_PRESENT) {
             /* Wrong entry in op definitions? */
             if (def->used) {
                 fprintf(stderr, "Invalid op definition for %s\n", def->name);
@@ -2659,9 +2675,9 @@
     img->sym[1].st_size = buf_size;
 
     img->di.cu_low_pc = buf;
-    img->di.cu_high_pc = buf_size;
+    img->di.cu_high_pc = buf + buf_size;
     img->di.fn_low_pc = buf;
-    img->di.fn_high_pc = buf_size;
+    img->di.fn_high_pc = buf + buf_size;
 
 #ifdef DEBUG_JIT
     /* Enable this block to be able to debug the ELF image file creation.
diff --git a/tcg/tcg.h b/tcg/tcg.h
index df375cf..f3f9889 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -60,6 +60,7 @@
 #if TCG_TARGET_REG_BITS == 32
 /* Turn some undef macros into false macros.  */
 #define TCG_TARGET_HAS_div_i64          0
+#define TCG_TARGET_HAS_rem_i64          0
 #define TCG_TARGET_HAS_div2_i64         0
 #define TCG_TARGET_HAS_rot_i64          0
 #define TCG_TARGET_HAS_ext8s_i64        0
@@ -102,11 +103,13 @@
 #define TCG_TARGET_HAS_div2_i32         0
 #elif defined(TCG_TARGET_HAS_div2_i32)
 #define TCG_TARGET_HAS_div_i32          0
+#define TCG_TARGET_HAS_rem_i32          0
 #endif
 #if defined(TCG_TARGET_HAS_div_i64)
 #define TCG_TARGET_HAS_div2_i64         0
 #elif defined(TCG_TARGET_HAS_div2_i64)
 #define TCG_TARGET_HAS_div_i64          0
+#define TCG_TARGET_HAS_rem_i64          0
 #endif
 
 typedef enum TCGOpcode {
@@ -593,7 +596,8 @@
     TCG_OPF_SIDE_EFFECTS = 0x04,
     /* Instruction operands are 64-bits (otherwise 32-bits).  */
     TCG_OPF_64BIT        = 0x08,
-    /* Instruction is optional and not implemented by the host.  */
+    /* Instruction is optional and not implemented by the host, or insn
+       is generic and should not be implemened by the host.  */
     TCG_OPF_NOT_PRESENT  = 0x10,
 };
 
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
index 0395bbb..d7fc14e 100644
--- a/tcg/tci/tcg-target.h
+++ b/tcg/tci/tcg-target.h
@@ -59,9 +59,8 @@
 
 #define TCG_TARGET_HAS_bswap16_i32      1
 #define TCG_TARGET_HAS_bswap32_i32      1
-/* Not more than one of the next two defines must be 1. */
 #define TCG_TARGET_HAS_div_i32          1
-#define TCG_TARGET_HAS_div2_i32         0
+#define TCG_TARGET_HAS_rem_i32          1
 #define TCG_TARGET_HAS_ext8s_i32        1
 #define TCG_TARGET_HAS_ext16s_i32       1
 #define TCG_TARGET_HAS_ext8u_i32        1
@@ -83,9 +82,8 @@
 #define TCG_TARGET_HAS_bswap32_i64      1
 #define TCG_TARGET_HAS_bswap64_i64      1
 #define TCG_TARGET_HAS_deposit_i64      1
-/* Not more than one of the next two defines must be 1. */
 #define TCG_TARGET_HAS_div_i64          0
-#define TCG_TARGET_HAS_div2_i64         0
+#define TCG_TARGET_HAS_rem_i64          0
 #define TCG_TARGET_HAS_ext8s_i64        1
 #define TCG_TARGET_HAS_ext16s_i64       1
 #define TCG_TARGET_HAS_ext32s_i64       1
diff --git a/tests/Makefile b/tests/Makefile
index c107489..279d5f8 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -44,6 +44,9 @@
 gcov-files-test-cutils-y += util/cutils.c
 check-unit-y += tests/test-mul64$(EXESUF)
 gcov-files-test-mul64-y = util/host-utils.c
+check-unit-y += tests/test-int128$(EXESUF)
+# all code tested by test-int128 is inside int128.h
+gcov-files-test-int128-y =
 
 check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 
@@ -75,7 +78,7 @@
 	tests/test-string-input-visitor.o tests/test-qmp-output-visitor.o \
 	tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \
 	tests/test-qmp-commands.o tests/test-visitor-serialization.o \
-	tests/test-x86-cpuid.o tests/test-mul64.o
+	tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o
 
 test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o
 
@@ -98,6 +101,7 @@
 tests/test-x86-cpuid$(EXESUF): tests/test-x86-cpuid.o
 tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o xbzrle.o page_cache.o libqemuutil.a
 tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o
+tests/test-int128$(EXESUF): tests/test-int128.o
 
 tests/test-qapi-types.c tests/test-qapi-types.h :\
 $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
diff --git a/tests/test-int128.c b/tests/test-int128.c
new file mode 100644
index 0000000..5aca032
--- /dev/null
+++ b/tests/test-int128.c
@@ -0,0 +1,212 @@
+/*
+ * Test Int128 arithmetic
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include <glib.h>
+#include <stdio.h>
+#include "qemu/int128.h"
+#include "qemu/osdep.h"
+
+static uint32_t tests[8] = {
+    0x00000000, 0x00000001, 0x7FFFFFFE, 0x7FFFFFFF,
+    0x80000000, 0x80000001, 0xFFFFFFFE, 0xFFFFFFFF,
+};
+
+#define LOW    3ULL
+#define HIGH   (1ULL << 63)
+#define MIDDLE (-1ULL & ~LOW & ~HIGH)
+
+static uint64_t expand16(unsigned x)
+{
+    return (x & LOW) | ((x & 4) ? MIDDLE : 0) | (x & 0x8000 ? HIGH : 0);
+}
+
+static Int128 expand(uint32_t x)
+{
+    uint64_t l, h;
+    l = expand16(x & 65535);
+    h = expand16(x >> 16);
+    return (Int128) {l, h};
+};
+
+static void test_and(void)
+{
+    int i, j;
+
+    for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+        for (j = 0; j < ARRAY_SIZE(tests); ++j) {
+            Int128 a = expand(tests[i]);
+            Int128 b = expand(tests[j]);
+            Int128 r = expand(tests[i] & tests[j]);
+            Int128 s = int128_and(a, b);
+            g_assert_cmpuint(r.lo, ==, s.lo);
+            g_assert_cmpuint(r.hi, ==, s.hi);
+        }
+    }
+}
+
+static void test_add(void)
+{
+    int i, j;
+
+    for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+        for (j = 0; j < ARRAY_SIZE(tests); ++j) {
+            Int128 a = expand(tests[i]);
+            Int128 b = expand(tests[j]);
+            Int128 r = expand(tests[i] + tests[j]);
+            Int128 s = int128_add(a, b);
+            g_assert_cmpuint(r.lo, ==, s.lo);
+            g_assert_cmpuint(r.hi, ==, s.hi);
+        }
+    }
+}
+
+static void test_sub(void)
+{
+    int i, j;
+
+    for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+        for (j = 0; j < ARRAY_SIZE(tests); ++j) {
+            Int128 a = expand(tests[i]);
+            Int128 b = expand(tests[j]);
+            Int128 r = expand(tests[i] - tests[j]);
+            Int128 s = int128_sub(a, b);
+            g_assert_cmpuint(r.lo, ==, s.lo);
+            g_assert_cmpuint(r.hi, ==, s.hi);
+        }
+    }
+}
+
+static void test_neg(void)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+        Int128 a = expand(tests[i]);
+        Int128 r = expand(-tests[i]);
+        Int128 s = int128_neg(a);
+        g_assert_cmpuint(r.lo, ==, s.lo);
+        g_assert_cmpuint(r.hi, ==, s.hi);
+    }
+}
+
+static void test_nz(void)
+{
+    int i, j;
+
+    for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+        for (j = 0; j < ARRAY_SIZE(tests); ++j) {
+            Int128 a = expand(tests[i]);
+            g_assert_cmpuint(int128_nz(a), ==, tests[i] != 0);
+        }
+    }
+}
+
+static void test_le(void)
+{
+    int i, j;
+
+    for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+        for (j = 0; j < ARRAY_SIZE(tests); ++j) {
+            /* Signed comparison */
+            int32_t a = (int32_t) tests[i];
+            int32_t b = (int32_t) tests[j];
+            g_assert_cmpuint(int128_le(expand(a), expand(b)), ==, a <= b);
+        }
+    }
+}
+
+static void test_lt(void)
+{
+    int i, j;
+
+    for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+        for (j = 0; j < ARRAY_SIZE(tests); ++j) {
+            /* Signed comparison */
+            int32_t a = (int32_t) tests[i];
+            int32_t b = (int32_t) tests[j];
+            g_assert_cmpuint(int128_lt(expand(a), expand(b)), ==, a < b);
+        }
+    }
+}
+
+static void test_ge(void)
+{
+    int i, j;
+
+    for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+        for (j = 0; j < ARRAY_SIZE(tests); ++j) {
+            /* Signed comparison */
+            int32_t a = (int32_t) tests[i];
+            int32_t b = (int32_t) tests[j];
+            g_assert_cmpuint(int128_ge(expand(a), expand(b)), ==, a >= b);
+        }
+    }
+}
+
+static void test_gt(void)
+{
+    int i, j;
+
+    for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+        for (j = 0; j < ARRAY_SIZE(tests); ++j) {
+            /* Signed comparison */
+            int32_t a = (int32_t) tests[i];
+            int32_t b = (int32_t) tests[j];
+            g_assert_cmpuint(int128_gt(expand(a), expand(b)), ==, a > b);
+        }
+    }
+}
+
+/* Make sure to test undefined behavior at runtime! */
+
+static void __attribute__((__noinline__, __noclone__))
+test_rshift_one(uint32_t x, int n, uint64_t h, uint64_t l)
+{
+    Int128 a = expand(x);
+    Int128 r = int128_rshift(a, n);
+    g_assert_cmpuint(r.lo, ==, l);
+    g_assert_cmpuint(r.hi, ==, h);
+}
+
+static void test_rshift(void)
+{
+    test_rshift_one(0x00010000U, 64, 0x0000000000000000ULL, 0x0000000000000001ULL);
+    test_rshift_one(0x80010000U, 64, 0xFFFFFFFFFFFFFFFFULL, 0x8000000000000001ULL);
+    test_rshift_one(0x7FFE0000U, 64, 0x0000000000000000ULL, 0x7FFFFFFFFFFFFFFEULL);
+    test_rshift_one(0xFFFE0000U, 64, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFEULL);
+    test_rshift_one(0x00010000U, 60, 0x0000000000000000ULL, 0x0000000000000010ULL);
+    test_rshift_one(0x80010000U, 60, 0xFFFFFFFFFFFFFFF8ULL, 0x0000000000000010ULL);
+    test_rshift_one(0x00018000U, 60, 0x0000000000000000ULL, 0x0000000000000018ULL);
+    test_rshift_one(0x80018000U, 60, 0xFFFFFFFFFFFFFFF8ULL, 0x0000000000000018ULL);
+    test_rshift_one(0x7FFE0000U, 60, 0x0000000000000007ULL, 0xFFFFFFFFFFFFFFE0ULL);
+    test_rshift_one(0xFFFE0000U, 60, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFE0ULL);
+    test_rshift_one(0x7FFE8000U, 60, 0x0000000000000007ULL, 0xFFFFFFFFFFFFFFE8ULL);
+    test_rshift_one(0xFFFE8000U, 60, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFE8ULL);
+    test_rshift_one(0x00018000U,  0, 0x0000000000000001ULL, 0x8000000000000000ULL);
+    test_rshift_one(0x80018000U,  0, 0x8000000000000001ULL, 0x8000000000000000ULL);
+    test_rshift_one(0x7FFE0000U,  0, 0x7FFFFFFFFFFFFFFEULL, 0x0000000000000000ULL);
+    test_rshift_one(0xFFFE0000U,  0, 0xFFFFFFFFFFFFFFFEULL, 0x0000000000000000ULL);
+    test_rshift_one(0x7FFE8000U,  0, 0x7FFFFFFFFFFFFFFEULL, 0x8000000000000000ULL);
+    test_rshift_one(0xFFFE8000U,  0, 0xFFFFFFFFFFFFFFFEULL, 0x8000000000000000ULL);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_add_func("/int128/int128_and", test_and);
+    g_test_add_func("/int128/int128_add", test_add);
+    g_test_add_func("/int128/int128_sub", test_sub);
+    g_test_add_func("/int128/int128_neg", test_neg);
+    g_test_add_func("/int128/int128_nz", test_nz);
+    g_test_add_func("/int128/int128_le", test_le);
+    g_test_add_func("/int128/int128_lt", test_lt);
+    g_test_add_func("/int128/int128_ge", test_ge);
+    g_test_add_func("/int128/int128_gt", test_gt);
+    g_test_add_func("/int128/int128_rshift", test_rshift);
+    return g_test_run();
+}
diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c
index 22915aa..b62338f 100644
--- a/tests/test-thread-pool.c
+++ b/tests/test-thread-pool.c
@@ -17,15 +17,15 @@
 static int worker_cb(void *opaque)
 {
     WorkerTestData *data = opaque;
-    return __sync_fetch_and_add(&data->n, 1);
+    return atomic_fetch_inc(&data->n);
 }
 
 static int long_cb(void *opaque)
 {
     WorkerTestData *data = opaque;
-    __sync_fetch_and_add(&data->n, 1);
+    atomic_inc(&data->n);
     g_usleep(2000000);
-    __sync_fetch_and_add(&data->n, 1);
+    atomic_inc(&data->n);
     return 0;
 }
 
@@ -169,7 +169,7 @@
     /* Cancel the jobs that haven't been started yet.  */
     num_canceled = 0;
     for (i = 0; i < 100; i++) {
-        if (__sync_val_compare_and_swap(&data[i].n, 0, 3) == 0) {
+        if (atomic_cmpxchg(&data[i].n, 0, 3) == 0) {
             data[i].ret = -ECANCELED;
             bdrv_aio_cancel(data[i].aiocb);
             active--;
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 412c425..e0ef426 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -706,16 +706,12 @@
     QemuOpts *opts;
 
     QTAILQ_FOREACH(opts, &list->head, next) {
-        if (!opts->id) {
-            if (!id) {
-                return opts;
-            }
-            continue;
+        if (!opts->id && !id) {
+            return opts;
         }
-        if (strcmp(opts->id, id) != 0) {
-            continue;
+        if (opts->id && id && !strcmp(opts->id, id)) {
+            return opts;
         }
-        return opts;
     }
     return NULL;
 }
@@ -918,15 +914,7 @@
         get_opt_value(value, sizeof(value), p+4);
         id = value;
     }
-    if (defaults) {
-        if (!id && !QTAILQ_EMPTY(&list->head)) {
-            opts = qemu_opts_find(list, NULL);
-        } else {
-            opts = qemu_opts_create(list, id, 0, &local_err);
-        }
-    } else {
-        opts = qemu_opts_create(list, id, 1, &local_err);
-    }
+    opts = qemu_opts_create(list, id, !defaults, &local_err);
     if (opts == NULL) {
         if (error_is_set(&local_err)) {
             qerror_report_err(local_err);
diff --git a/vl.c b/vl.c
index 6d9fd7d..bea1a10 100644
--- a/vl.c
+++ b/vl.c
@@ -409,7 +409,7 @@
             .help = "Dump current dtb to a file and quit",
         }, {
             .name = "phandle_start",
-            .type = QEMU_OPT_STRING,
+            .type = QEMU_OPT_NUMBER,
             .help = "The first phandle ID we may generate dynamically",
         }, {
             .name = "dt_compatible",
@@ -516,6 +516,25 @@
     },
 };
 
+/**
+ * Get machine options
+ *
+ * Returns: machine options (never null).
+ */
+QemuOpts *qemu_get_machine_opts(void)
+{
+    QemuOptsList *list;
+    QemuOpts *opts;
+
+    list = qemu_find_opts("machine");
+    assert(list);
+    opts = qemu_opts_find(list, NULL);
+    if (!opts) {
+        opts = qemu_opts_create_nofail(list);
+    }
+    return opts;
+}
+
 const char *qemu_get_vm_name(void)
 {
     return qemu_name;
@@ -1017,15 +1036,9 @@
     return 0;
 }
 
-/*********QEMU USB setting******/
 bool usb_enabled(bool default_usb)
 {
-    QemuOpts *mach_opts;
-    mach_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (mach_opts) {
-        return qemu_opt_get_bool(mach_opts, "usb", default_usb);
-    }
-    return default_usb;
+    return qemu_opt_get_bool(qemu_get_machine_opts(), "usb", default_usb);
 }
 
 #ifndef _WIN32
@@ -2672,17 +2685,13 @@
 
 static int configure_accelerator(void)
 {
-    const char *p = NULL;
+    const char *p;
     char buf[10];
     int i, ret;
     bool accel_initialised = false;
     bool init_failed = false;
 
-    QemuOptsList *list = qemu_find_opts("machine");
-    if (!QTAILQ_EMPTY(&list->head)) {
-        p = qemu_opt_get(QTAILQ_FIRST(&list->head), "accel");
-    }
-
+    p = qemu_opt_get(qemu_get_machine_opts(), "accel");
     if (p == NULL) {
         /* Use the default "accelerator", tcg */
         p = "tcg";
@@ -4080,14 +4089,10 @@
         qtest_init();
     }
 
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        kernel_filename = qemu_opt_get(machine_opts, "kernel");
-        initrd_filename = qemu_opt_get(machine_opts, "initrd");
-        kernel_cmdline = qemu_opt_get(machine_opts, "append");
-    } else {
-        kernel_filename = initrd_filename = kernel_cmdline = NULL;
-    }
+    machine_opts = qemu_get_machine_opts();
+    kernel_filename = qemu_opt_get(machine_opts, "kernel");
+    initrd_filename = qemu_opt_get(machine_opts, "initrd");
+    kernel_cmdline = qemu_opt_get(machine_opts, "append");
 
     if (!boot_order) {
         boot_order = machine->boot_order;
@@ -4130,7 +4135,7 @@
         exit(1);
     }
 
-    if (!linux_boot && machine_opts && qemu_opt_get(machine_opts, "dtb")) {
+    if (!linux_boot && qemu_opt_get(machine_opts, "dtb")) {
         fprintf(stderr, "-dtb only allowed with -kernel option\n");
         exit(1);
     }
diff --git a/xen-all.c b/xen-all.c
index dcb57a0..21246e0 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -167,7 +167,7 @@
          */
         block_len += HVM_BELOW_4G_MMIO_LENGTH;
     }
-    memory_region_init_ram(&ram_memory, "xen.ram", block_len);
+    memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len);
     vmstate_register_ram_global(&ram_memory);
 
     if (ram_size >= HVM_BELOW_4G_RAM_END) {
@@ -177,7 +177,7 @@
         below_4g_mem_size = ram_size;
     }
 
-    memory_region_init_alias(&ram_640k, "xen.ram.640k",
+    memory_region_init_alias(&ram_640k, NULL, "xen.ram.640k",
                              &ram_memory, 0, 0xa0000);
     memory_region_add_subregion(sysmem, 0, &ram_640k);
     /* Skip of the VGA IO memory space, it will be registered later by the VGA
@@ -186,11 +186,11 @@
      * The area between 0xc0000 and 0x100000 will be used by SeaBIOS to load
      * the Options ROM, so it is registered here as RAM.
      */
-    memory_region_init_alias(&ram_lo, "xen.ram.lo",
+    memory_region_init_alias(&ram_lo, NULL, "xen.ram.lo",
                              &ram_memory, 0xc0000, below_4g_mem_size - 0xc0000);
     memory_region_add_subregion(sysmem, 0xc0000, &ram_lo);
     if (above_4g_mem_size > 0) {
-        memory_region_init_alias(&ram_hi, "xen.ram.hi",
+        memory_region_init_alias(&ram_hi, NULL, "xen.ram.hi",
                                  &ram_memory, 0x100000000ULL,
                                  above_4g_mem_size);
         memory_region_add_subregion(sysmem, 0x100000000ULL, &ram_hi);
@@ -459,6 +459,7 @@
 static void xen_region_add(MemoryListener *listener,
                            MemoryRegionSection *section)
 {
+    memory_region_ref(section->mr);
     xen_set_memory(listener, section, true);
 }
 
@@ -466,6 +467,7 @@
                            MemoryRegionSection *section)
 {
     xen_set_memory(listener, section, false);
+    memory_region_unref(section->mr);
 }
 
 static void xen_sync_dirty_bitmap(XenIOState *state,