diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 0e934ec..de24ad3 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -104,7 +104,7 @@ typedef struct gic_state
     int num_cpu;
 #endif
 
-    int iomemtype;
+    MemoryRegion iomem;
 } gic_state;
 
 /* TODO: Many places that call this routine could be optimized.  */
@@ -567,16 +567,12 @@ static void gic_dist_writel(void *opaque, target_phys_addr_t offset,
     gic_dist_writew(opaque, offset + 2, value >> 16);
 }
 
-static CPUReadMemoryFunc * const gic_dist_readfn[] = {
-   gic_dist_readb,
-   gic_dist_readw,
-   gic_dist_readl
-};
-
-static CPUWriteMemoryFunc * const gic_dist_writefn[] = {
-   gic_dist_writeb,
-   gic_dist_writew,
-   gic_dist_writel
+static const MemoryRegionOps gic_dist_ops = {
+    .old_mmio = {
+        .read = { gic_dist_readb, gic_dist_readw, gic_dist_readl, },
+        .write = { gic_dist_writeb, gic_dist_writew, gic_dist_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 #ifndef NVIC
@@ -741,9 +737,7 @@ static void gic_init(gic_state *s)
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }
-    s->iomemtype = cpu_register_io_memory(gic_dist_readfn,
-                                          gic_dist_writefn, s,
-                                          DEVICE_NATIVE_ENDIAN);
+    memory_region_init_io(&s->iomem, &gic_dist_ops, s, "gic_dist", 0x1000);
     gic_reset(s);
     register_savevm(NULL, "arm_gic", -1, 1, gic_save, gic_load, s);
 }
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index d06eec9..ee67978 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -379,12 +379,14 @@ static const VMStateDescription vmstate_nvic = {
     }
 };
 
+#include "exec-memory.h"
+
 static int armv7m_nvic_init(SysBusDevice *dev)
 {
     nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
 
     gic_init(&s->gic);
-    cpu_register_physical_memory(0xe000e000, 0x1000, s->gic.iomemtype);
+    memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->gic.iomem);
     s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
     vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);
     return 0;
diff --git a/hw/mpcore.c b/hw/mpcore.c
index 379065a..7834fe0 100644
--- a/hw/mpcore.c
+++ b/hw/mpcore.c
@@ -40,6 +40,8 @@ typedef struct mpcore_priv_state {
     int iomemtype;
     mpcore_timer_state timer[8];
     uint32_t num_cpu;
+    MemoryRegion iomem;
+    MemoryRegion container;
 } mpcore_priv_state;
 
 /* Per-CPU Timers.  */
@@ -151,7 +153,8 @@ static void mpcore_timer_init(mpcore_priv_state *mpcore,
 
 /* Per-CPU private memory mapped IO.  */
 
-static uint32_t mpcore_priv_read(void *opaque, target_phys_addr_t offset)
+static uint64_t mpcore_priv_read(void *opaque, target_phys_addr_t offset,
+                                 unsigned size)
 {
     mpcore_priv_state *s = (mpcore_priv_state *)opaque;
     int id;
@@ -203,7 +206,7 @@ bad_reg:
 }
 
 static void mpcore_priv_write(void *opaque, target_phys_addr_t offset,
-                          uint32_t value)
+                              uint64_t value, unsigned size)
 {
     mpcore_priv_state *s = (mpcore_priv_state *)opaque;
     int id;
@@ -250,23 +253,19 @@ bad_reg:
     hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
 }
 
-static CPUReadMemoryFunc * const mpcore_priv_readfn[] = {
-   mpcore_priv_read,
-   mpcore_priv_read,
-   mpcore_priv_read
+static const MemoryRegionOps mpcore_priv_ops = {
+    .read = mpcore_priv_read,
+    .write = mpcore_priv_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const mpcore_priv_writefn[] = {
-   mpcore_priv_write,
-   mpcore_priv_write,
-   mpcore_priv_write
-};
-
-static void mpcore_priv_map(SysBusDevice *dev, target_phys_addr_t base)
+static void mpcore_priv_map_setup(mpcore_priv_state *s)
 {
-    mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
-    cpu_register_physical_memory(base, 0x1000, s->iomemtype);
-    cpu_register_physical_memory(base + 0x1000, 0x1000, s->gic.iomemtype);
+    memory_region_init(&s->container, "mpcode-priv-container", 0x2000);
+    memory_region_init_io(&s->iomem, &mpcore_priv_ops, s, "mpcode-priv",
+                          0x1000);
+    memory_region_add_subregion(&s->container, 0, &s->iomem);
+    memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
 }
 
 static int mpcore_priv_init(SysBusDevice *dev)
@@ -275,10 +274,8 @@ static int mpcore_priv_init(SysBusDevice *dev)
     int i;
 
     gic_init(&s->gic, s->num_cpu);
-    s->iomemtype = cpu_register_io_memory(mpcore_priv_readfn,
-                                          mpcore_priv_writefn, s,
-                                          DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio_cb(dev, 0x2000, mpcore_priv_map);
+    mpcore_priv_map_setup(s);
+    sysbus_init_mmio_region(dev, &s->container);
     for (i = 0; i < s->num_cpu * 2; i++) {
         mpcore_timer_init(s, &s->timer[i], i);
     }
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index db908b6..9ac40a9 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -23,39 +23,37 @@ gic_get_current_cpu(void)
 
 typedef struct {
     gic_state gic;
-    int iomemtype;
+    MemoryRegion iomem;
+    MemoryRegion container;
 } RealViewGICState;
 
-static uint32_t realview_gic_cpu_read(void *opaque, target_phys_addr_t offset)
+static uint64_t realview_gic_cpu_read(void *opaque, target_phys_addr_t offset,
+                                      unsigned size)
 {
     gic_state *s = (gic_state *)opaque;
     return gic_cpu_read(s, gic_get_current_cpu(), offset);
 }
 
 static void realview_gic_cpu_write(void *opaque, target_phys_addr_t offset,
-                          uint32_t value)
+                                   uint64_t value, unsigned size)
 {
     gic_state *s = (gic_state *)opaque;
     gic_cpu_write(s, gic_get_current_cpu(), offset, value);
 }
 
-static CPUReadMemoryFunc * const realview_gic_cpu_readfn[] = {
-   realview_gic_cpu_read,
-   realview_gic_cpu_read,
-   realview_gic_cpu_read
+static const MemoryRegionOps realview_gic_cpu_ops = {
+    .read = realview_gic_cpu_read,
+    .write = realview_gic_cpu_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const realview_gic_cpu_writefn[] = {
-   realview_gic_cpu_write,
-   realview_gic_cpu_write,
-   realview_gic_cpu_write
-};
-
-static void realview_gic_map(SysBusDevice *dev, target_phys_addr_t base)
+static void realview_gic_map_setup(RealViewGICState *s)
 {
-    RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
-    cpu_register_physical_memory(base, 0x1000, s->iomemtype);
-    cpu_register_physical_memory(base + 0x1000, 0x1000, s->gic.iomemtype);
+    memory_region_init(&s->container, "realview-gic-container", 0x2000);
+    memory_region_init_io(&s->iomem, &realview_gic_cpu_ops, &s->gic,
+                          "realview-gic", 0x1000);
+    memory_region_add_subregion(&s->container, 0, &s->iomem);
+    memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
 }
 
 static int realview_gic_init(SysBusDevice *dev)
@@ -63,10 +61,8 @@ static int realview_gic_init(SysBusDevice *dev)
     RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
 
     gic_init(&s->gic);
-    s->iomemtype = cpu_register_io_memory(realview_gic_cpu_readfn,
-                                          realview_gic_cpu_writefn, s,
-                                          DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio_cb(dev, 0x2000, realview_gic_map);
+    realview_gic_map_setup(s);
+    sysbus_init_mmio_region(dev, &s->container);
     return 0;
 }
 
