summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--hw/an5206.c2
-rw-r--r--hw/apb_pci.c6
-rw-r--r--hw/apic.c2
-rw-r--r--hw/arm11mpcore.c2
-rw-r--r--hw/arm_sysctl.c2
-rw-r--r--hw/arm_timer.c4
-rw-r--r--hw/armv7m.c2
-rw-r--r--hw/axis_dev88.c63
-rw-r--r--hw/bitbang_i2c.c4
-rw-r--r--hw/bonito.c201
-rw-r--r--hw/cs4231.c27
-rw-r--r--hw/dec_pci.c4
-rw-r--r--hw/dp8393x.c30
-rw-r--r--hw/ds1225y.c62
-rw-r--r--hw/eccmemctl.c63
-rw-r--r--hw/empty_slot.c32
-rw-r--r--hw/escc.c2
-rw-r--r--hw/esp.c37
-rw-r--r--hw/etraxfs_eth.c2
-rw-r--r--hw/etraxfs_pic.c2
-rw-r--r--hw/etraxfs_ser.c2
-rw-r--r--hw/etraxfs_timer.c2
-rw-r--r--hw/fdc.c58
-rw-r--r--hw/fw_cfg.c110
-rw-r--r--hw/g364fb.c4
-rw-r--r--hw/grackle_pci.c4
-rw-r--r--hw/grlib_apbuart.c30
-rw-r--r--hw/grlib_gptimer.c34
-rw-r--r--hw/grlib_irqmp.c34
-rw-r--r--hw/hpet.c62
-rw-r--r--hw/ide.h2
-rw-r--r--hw/ide/mmio.c57
-rw-r--r--hw/integratorcp.c87
-rw-r--r--hw/ioapic.c34
-rw-r--r--hw/jazz_led.c25
-rw-r--r--hw/lan9118.c2
-rw-r--r--hw/lance.c2
-rw-r--r--hw/lm32_sys.c28
-rw-r--r--hw/lm32_timer.c30
-rw-r--r--hw/lm32_uart.c31
-rw-r--r--hw/m48t59.c23
-rw-r--r--hw/marvell_88w8618_audio.c28
-rw-r--r--hw/mcf.h23
-rw-r--r--hw/mcf5206.c62
-rw-r--r--hw/mcf5208.c11
-rw-r--r--hw/mcf_fec.c38
-rw-r--r--hw/mcf_intc.c33
-rw-r--r--hw/mcf_uart.c34
-rw-r--r--hw/milkymist-ac97.c2
-rw-r--r--hw/milkymist-hpdmc.c2
-rw-r--r--hw/milkymist-memcard.c2
-rw-r--r--hw/milkymist-minimac2.c2
-rw-r--r--hw/milkymist-pfpu.c2
-rw-r--r--hw/milkymist-softusb.c2
-rw-r--r--hw/milkymist-sysctl.c2
-rw-r--r--hw/milkymist-tmu2.c2
-rw-r--r--hw/milkymist-uart.c2
-rw-r--r--hw/milkymist-vgafb.c2
-rw-r--r--hw/mips.h8
-rw-r--r--hw/mips_jazz.c10
-rw-r--r--hw/mipsnet.c2
-rw-r--r--hw/mpc8544_guts.c35
-rw-r--r--hw/mpcore.c2
-rw-r--r--hw/mst_fpga.c29
-rw-r--r--hw/musicpal.c18
-rw-r--r--hw/nseries.c4
-rw-r--r--hw/omap.h45
-rw-r--r--hw/omap1.c8
-rw-r--r--hw/omap2.c207
-rw-r--r--hw/omap_dma.c71
-rw-r--r--hw/omap_dss.c169
-rw-r--r--hw/omap_gpio.c95
-rw-r--r--hw/omap_gptimer.c32
-rw-r--r--hw/omap_i2c.c45
-rw-r--r--hw/omap_intc.c4
-rw-r--r--hw/omap_l4.c182
-rw-r--r--hw/omap_lcdc.c33
-rw-r--r--hw/omap_mmc.c44
-rw-r--r--hw/omap_sdrc.c39
-rw-r--r--hw/omap_spi.c37
-rw-r--r--hw/omap_sx1.c99
-rw-r--r--hw/omap_synctimer.c30
-rw-r--r--hw/omap_tap.c32
-rw-r--r--hw/omap_uart.c41
-rw-r--r--hw/onenand.c2
-rw-r--r--hw/opencores_eth.c4
-rw-r--r--hw/parallel.c27
-rw-r--r--hw/pc.h3
-rw-r--r--hw/pci_host.h1
-rw-r--r--hw/pl011.c27
-rw-r--r--hw/pl022.c29
-rw-r--r--hw/pl031.c30
-rw-r--r--hw/pl041.c2
-rw-r--r--hw/pl050.c27
-rw-r--r--hw/pl061.c27
-rw-r--r--hw/pl080.c27
-rw-r--r--hw/pl110.c27
-rw-r--r--hw/pl181.c26
-rw-r--r--hw/pl190.c28
-rw-r--r--hw/ppc4xx_pci.c68
-rw-r--r--hw/ppce500_pci.c34
-rw-r--r--hw/ppce500_spin.c2
-rw-r--r--hw/prep_pci.c23
-rw-r--r--hw/pxa.h15
-rw-r--r--hw/pxa2xx.c24
-rw-r--r--hw/pxa2xx_dma.c54
-rw-r--r--hw/pxa2xx_gpio.c29
-rw-r--r--hw/pxa2xx_keypad.c34
-rw-r--r--hw/pxa2xx_lcd.c32
-rw-r--r--hw/pxa2xx_mmci.c31
-rw-r--r--hw/pxa2xx_pcmcia.c95
-rw-r--r--hw/pxa2xx_pic.c31
-rw-r--r--hw/pxa2xx_timer.c27
-rw-r--r--hw/r2d.c4
-rw-r--r--hw/rc4030.c51
-rw-r--r--hw/realview.c2
-rw-r--r--hw/realview_gic.c2
-rw-r--r--hw/sbi.c33
-rw-r--r--hw/sh.h9
-rw-r--r--hw/sh7750.c155
-rw-r--r--hw/sh_intc.c85
-rw-r--r--hw/sh_intc.h7
-rw-r--r--hw/sh_pci.c4
-rw-r--r--hw/sh_serial.c55
-rw-r--r--hw/sh_timer.c43
-rw-r--r--hw/shix.c16
-rw-r--r--hw/slavio_intctl.c67
-rw-r--r--hw/slavio_misc.c250
-rw-r--r--hw/slavio_timer.c41
-rw-r--r--hw/smc91c111.c2
-rw-r--r--hw/sparc32_dma.c31
-rw-r--r--hw/spitz.c2
-rw-r--r--hw/stellaris.c115
-rw-r--r--hw/stellaris_enet.c2
-rw-r--r--hw/strongarm.c12
-rw-r--r--hw/sun4c_intctl.c36
-rw-r--r--hw/sun4m.c8
-rw-r--r--hw/sun4m_iommu.c33
-rw-r--r--hw/sun4u.c4
-rw-r--r--hw/syborg_fb.c28
-rw-r--r--hw/syborg_interrupt.c29
-rw-r--r--hw/syborg_keyboard.c28
-rw-r--r--hw/syborg_pointer.c28
-rw-r--r--hw/syborg_rtc.c28
-rw-r--r--hw/syborg_serial.c28
-rw-r--r--hw/syborg_timer.c27
-rw-r--r--hw/syborg_virtio.c26
-rw-r--r--hw/sysbus.c29
-rw-r--r--hw/sysbus.h6
-rw-r--r--hw/tcx.c14
-rw-r--r--hw/tosa.c6
-rw-r--r--hw/tusb6010.c4
-rw-r--r--hw/unin_pci.c16
-rw-r--r--hw/usb-ohci.c2
-rw-r--r--hw/versatile_pci.c6
-rw-r--r--hw/versatilepb.c35
-rw-r--r--hw/vexpress.c31
-rw-r--r--hw/virtex_ml507.c6
-rw-r--r--hw/xilinx_axidma.c29
-rw-r--r--hw/xilinx_axienet.c29
-rw-r--r--hw/xilinx_ethlite.c2
-rw-r--r--hw/xilinx_intc.c2
-rw-r--r--hw/xilinx_timer.c2
-rw-r--r--hw/xilinx_uartlite.c2
-rw-r--r--hw/zaurus.c26
-rw-r--r--memory.c12
-rw-r--r--memory.h7
-rw-r--r--target-sh4/helper.c3
168 files changed, 2396 insertions, 2730 deletions
diff --git a/hw/an5206.c b/hw/an5206.c
index 3fe1f00d9b..319a40e1d2 100644
--- a/hw/an5206.c
+++ b/hw/an5206.c
@@ -53,7 +53,7 @@ static void an5206_init(ram_addr_t ram_size,
     memory_region_init_ram(sram, NULL, "an5206.sram", 512);
     memory_region_add_subregion(address_space_mem, AN5206_RAMBAR_ADDR, sram);
 
-    mcf5206_init(AN5206_MBAR_ADDR, env);
+    mcf5206_init(address_space_mem, AN5206_MBAR_ADDR, env);
 
     /* Load kernel.  */
     if (!kernel_filename) {
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index c232946280..3a1b111455 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -410,18 +410,18 @@ static int pci_pbm_init_device(SysBusDevice *dev)
     memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config",
                           0x10000);
     /* at region 0 */
-    sysbus_init_mmio_region(dev, &s->apb_config);
+    sysbus_init_mmio(dev, &s->apb_config);
 
     memory_region_init_io(&s->pci_config, &pci_config_ops, s, "apb-pci-config",
                           0x1000000);
     /* at region 1 */
-    sysbus_init_mmio_region(dev, &s->pci_config);
+    sysbus_init_mmio(dev, &s->pci_config);
 
     /* pci_ioport */
     memory_region_init_io(&s->pci_ioport, &pci_ioport_ops, s,
                           "apb-pci-ioport", 0x10000);
     /* at region 2 */
-    sysbus_init_mmio_region(dev, &s->pci_ioport);
+    sysbus_init_mmio(dev, &s->pci_ioport);
 
     return 0;
 }
diff --git a/hw/apic.c b/hw/apic.c
index 8289eef5b8..9d0f460b58 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -998,7 +998,7 @@ static int apic_init1(SysBusDevice *dev)
     }
     memory_region_init_io(&s->io_memory, &apic_io_ops, s, "apic",
                           MSI_ADDR_SIZE);
-    sysbus_init_mmio_region(dev, &s->io_memory);
+    sysbus_init_mmio(dev, &s->io_memory);
 
     s->timer = qemu_new_timer_ns(vm_clock, apic_timer, s);
     s->idx = last_apic_idx++;
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index 974a0d8262..32ecf98309 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -73,7 +73,7 @@ static int realview_mpcore_init(SysBusDevice *dev)
         }
     }
     qdev_init_gpio_in(&dev->qdev, mpcore_rirq_set_irq, 64);
-    sysbus_init_mmio_region(dev, sysbus_mmio_get_region(s->priv, 0));
+    sysbus_init_mmio(dev, sysbus_mmio_get_region(s->priv, 0));
     return 0;
 }
 
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index 477fc6fd47..4b88648780 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -383,7 +383,7 @@ static int arm_sysctl_init1(SysBusDevice *dev)
     arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev);
 
     memory_region_init_io(&s->iomem, &arm_sysctl_ops, s, "arm-sysctl", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     qdev_init_gpio_in(&s->busdev.qdev, arm_sysctl_gpio_set, 2);
     qdev_init_gpio_out(&s->busdev.qdev, &s->pl110_mux_ctrl, 1);
     return 0;
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 66db81d5b7..8f442d7878 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -247,7 +247,7 @@ static int sp804_init(SysBusDevice *dev)
     s->timer[0]->irq = qi[0];
     s->timer[1]->irq = qi[1];
     memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     vmstate_register(&dev->qdev, -1, &vmstate_sp804, s);
     return 0;
 }
@@ -311,7 +311,7 @@ static int icp_pit_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->timer[2]->irq);
 
     memory_region_init_io(&s->iomem, &icp_pit_ops, s, "icp_pit", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     /* This device has no state to save/restore.  The component timers will
        save themselves.  */
     return 0;
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 28d41b82a6..eb8c0d68d6 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -126,7 +126,7 @@ static int bitband_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &bitband_ops, &s->base, "bitband",
                           0x02000000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 73eb39d43b..c5405ceb3d 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -39,6 +39,7 @@
 struct nand_state_t
 {
     DeviceState *nand;
+    MemoryRegion iomem;
     unsigned int rdy:1;
     unsigned int ale:1;
     unsigned int cle:1;
@@ -46,7 +47,7 @@ struct nand_state_t
 };
 
 static struct nand_state_t nand_state;
-static uint32_t nand_readl (void *opaque, target_phys_addr_t addr)
+static uint64_t nand_read(void *opaque, target_phys_addr_t addr, unsigned size)
 {
     struct nand_state_t *s = opaque;
     uint32_t r;
@@ -61,31 +62,25 @@ static uint32_t nand_readl (void *opaque, target_phys_addr_t addr)
 }
 
 static void
-nand_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+nand_write(void *opaque, target_phys_addr_t addr, uint64_t value,
+           unsigned size)
 {
     struct nand_state_t *s = opaque;
     int rdy;
 
-    DNAND(printf("%s addr=%x v=%x\n", __func__, addr, value));
+    DNAND(printf("%s addr=%x v=%x\n", __func__, addr, (unsigned)value));
     nand_setpins(s->nand, s->cle, s->ale, s->ce, 1, 0);
     nand_setio(s->nand, value);
     nand_getpins(s->nand, &rdy);
     s->rdy = rdy;
 }
 
-static CPUReadMemoryFunc * const nand_read[] = {
-    &nand_readl,
-    &nand_readl,
-    &nand_readl,
+static const MemoryRegionOps nand_ops = {
+    .read = nand_read,
+    .write = nand_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const nand_write[] = {
-    &nand_writel,
-    &nand_writel,
-    &nand_writel,
-};
-
-
 struct tempsensor_t
 {
     unsigned int shiftreg;
@@ -165,12 +160,13 @@ static void tempsensor_clkedge(struct tempsensor_t *s,
 
 static struct gpio_state_t
 {
+    MemoryRegion iomem;
     struct nand_state_t *nand;
     struct tempsensor_t tempsensor;
     uint32_t regs[0x5c / 4];
 } gpio_state;
 
-static uint32_t gpio_readl (void *opaque, target_phys_addr_t addr)
+static uint64_t gpio_read(void *opaque, target_phys_addr_t addr, unsigned size)
 {
     struct gpio_state_t *s = opaque;
     uint32_t r = 0;
@@ -199,10 +195,11 @@ static uint32_t gpio_readl (void *opaque, target_phys_addr_t addr)
     D(printf("%s %x=%x\n", __func__, addr, r));
 }
 
-static void gpio_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+static void gpio_write(void *opaque, target_phys_addr_t addr, uint64_t value,
+                       unsigned size)
 {
     struct gpio_state_t *s = opaque;
-    D(printf("%s %x=%x\n", __func__, addr, value));
+    D(printf("%s %x=%x\n", __func__, addr, (unsigned)value));
 
     addr >>= 2;
     switch (addr)
@@ -230,14 +227,14 @@ static void gpio_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
     }
 }
 
-static CPUReadMemoryFunc * const gpio_read[] = {
-    NULL, NULL,
-    &gpio_readl,
-};
-
-static CPUWriteMemoryFunc * const gpio_write[] = {
-    NULL, NULL,
-    &gpio_writel,
+static const MemoryRegionOps gpio_ops = {
+    .read = gpio_read,
+    .write = gpio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 #define INTMEM_SIZE (128 * 1024)
@@ -258,8 +255,6 @@ void axisdev88_init (ram_addr_t ram_size,
     void *etraxfs_dmac;
     struct etraxfs_dma_client *dma_eth;
     int i;
-    int nand_regs;
-    int gpio_regs;
     MemoryRegion *address_space_mem = get_system_memory();
     MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
     MemoryRegion *phys_intmem = g_new(MemoryRegion, 1);
@@ -283,14 +278,16 @@ void axisdev88_init (ram_addr_t ram_size,
     nand = drive_get(IF_MTD, 0, 0);
     nand_state.nand = nand_init(nand ? nand->bdrv : NULL,
                                 NAND_MFR_STMICRO, 0x39);
-    nand_regs = cpu_register_io_memory(nand_read, nand_write, &nand_state,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(0x10000000, 0x05000000, nand_regs);
+    memory_region_init_io(&nand_state.iomem, &nand_ops, &nand_state,
+                          "nand", 0x05000000);
+    memory_region_add_subregion(address_space_mem, 0x10000000,
+                                &nand_state.iomem);
 
     gpio_state.nand = &nand_state;
-    gpio_regs = cpu_register_io_memory(gpio_read, gpio_write, &gpio_state,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(0x3001a000, 0x5c, gpio_regs);
+    memory_region_init_io(&gpio_state.iomem, &gpio_ops, &gpio_state,
+                          "gpio", 0x5c);
+    memory_region_add_subregion(address_space_mem, 0x3001a000,
+                                &gpio_state.iomem);
 
 
     cpu_irq = cris_pic_init_cpu(env);
diff --git a/hw/bitbang_i2c.c b/hw/bitbang_i2c.c
index 431359d615..18df411ebc 100644
--- a/hw/bitbang_i2c.c
+++ b/hw/bitbang_i2c.c
@@ -184,6 +184,7 @@ bitbang_i2c_interface *bitbang_i2c_init(i2c_bus *bus)
 /* GPIO interface.  */
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion dummy_iomem;
     bitbang_i2c_interface *bitbang;
     int last_level;
     qemu_irq out;
@@ -205,7 +206,8 @@ static int gpio_i2c_init(SysBusDevice *dev)
     GPIOI2CState *s = FROM_SYSBUS(GPIOI2CState, dev);
     i2c_bus *bus;
 
-    sysbus_init_mmio(dev, 0x0, 0);
+    memory_region_init(&s->dummy_iomem, "gpio_i2c", 0);
+    sysbus_init_mmio(dev, &s->dummy_iomem);
 
     bus = i2c_init_bus(&dev->qdev, "i2c");
     s->bitbang = bitbang_i2c_init(bus);
diff --git a/hw/bonito.c b/hw/bonito.c
index fdb8198f62..04d706aba3 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -201,17 +201,9 @@ typedef struct PCIBonitoState
     } boncop;
 
     /* Bonito registers */
-    target_phys_addr_t bonito_reg_start;
-    target_phys_addr_t bonito_reg_length;
-    int bonito_reg_handle;
-
-    target_phys_addr_t bonito_pciconf_start;
-    target_phys_addr_t bonito_pciconf_length;
-    int bonito_pciconf_handle;
-
-    target_phys_addr_t bonito_spciconf_start;
-    target_phys_addr_t bonito_spciconf_length;
-    int bonito_spciconf_handle;
+    MemoryRegion iomem;
+    MemoryRegion iomem_ldma;
+    MemoryRegion iomem_cop;
 
     target_phys_addr_t bonito_pciio_start;
     target_phys_addr_t bonito_pciio_length;
@@ -221,19 +213,12 @@ typedef struct PCIBonitoState
     target_phys_addr_t bonito_localio_length;
     int bonito_localio_handle;
 
-    target_phys_addr_t bonito_ldma_start;
-    target_phys_addr_t bonito_ldma_length;
-    int bonito_ldma_handle;
-
-    target_phys_addr_t bonito_cop_start;
-    target_phys_addr_t bonito_cop_length;
-    int bonito_cop_handle;
-
 } PCIBonitoState;
 
 PCIBonitoState * bonito_state;
 
-static void bonito_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void bonito_writel(void *opaque, target_phys_addr_t addr,
+                          uint64_t val, unsigned size)
 {
     PCIBonitoState *s = opaque;
     uint32_t saddr;
@@ -295,7 +280,8 @@ static void bonito_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
-static uint32_t bonito_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t bonito_readl(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
 {
     PCIBonitoState *s = opaque;
     uint32_t saddr;
@@ -311,20 +297,18 @@ static uint32_t bonito_readl(void *opaque, target_phys_addr_t addr)
     }
 }
 
-static CPUWriteMemoryFunc * const bonito_write[] = {
-    NULL,
-    NULL,
-    bonito_writel,
-};
-
-static CPUReadMemoryFunc * const bonito_read[] = {
-    NULL,
-    NULL,
-    bonito_readl,
+static const MemoryRegionOps bonito_ops = {
+    .read = bonito_readl,
+    .write = bonito_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static void bonito_pciconf_writel(void *opaque, target_phys_addr_t addr,
-                                  uint32_t val)
+                                  uint64_t val, unsigned size)
 {
     PCIBonitoState *s = opaque;
 
@@ -332,7 +316,8 @@ static void bonito_pciconf_writel(void *opaque, target_phys_addr_t addr,
     s->dev.config_write(&s->dev, addr, val, 4);
 }
 
-static uint32_t bonito_pciconf_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t bonito_pciconf_readl(void *opaque, target_phys_addr_t addr,
+                                     unsigned size)
 {
 
     PCIBonitoState *s = opaque;
@@ -342,19 +327,19 @@ static uint32_t bonito_pciconf_readl(void *opaque, target_phys_addr_t addr)
 }
 
 /* north bridge PCI configure space. 0x1fe0 0000 - 0x1fe0 00ff */
-static CPUWriteMemoryFunc * const bonito_pciconf_write[] = {
-    NULL,
-    NULL,
-    bonito_pciconf_writel,
-};
 
-static CPUReadMemoryFunc * const bonito_pciconf_read[] = {
-    NULL,
-    NULL,
-    bonito_pciconf_readl,
+static const MemoryRegionOps bonito_pciconf_ops = {
+    .read = bonito_pciconf_readl,
+    .write = bonito_pciconf_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
-static uint32_t bonito_ldma_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t bonito_ldma_readl(void *opaque, target_phys_addr_t addr,
+                                  unsigned size)
 {
     uint32_t val;
     PCIBonitoState *s = opaque;
@@ -365,26 +350,25 @@ static uint32_t bonito_ldma_readl(void *opaque, target_phys_addr_t addr)
 }
 
 static void bonito_ldma_writel(void *opaque, target_phys_addr_t addr,
-                               uint32_t val)
+                               uint64_t val, unsigned size)
 {
     PCIBonitoState *s = opaque;
 
     ((uint32_t *)(&s->bonldma))[addr/sizeof(uint32_t)] = val & 0xffffffff;
 }
 
-static CPUWriteMemoryFunc * const bonito_ldma_write[] = {
-    NULL,
-    NULL,
-    bonito_ldma_writel,
+static const MemoryRegionOps bonito_ldma_ops = {
+    .read = bonito_ldma_readl,
+    .write = bonito_ldma_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
-static CPUReadMemoryFunc * const bonito_ldma_read[] = {
-    NULL,
-    NULL,
-    bonito_ldma_readl,
-};
-
-static uint32_t bonito_cop_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t bonito_cop_readl(void *opaque, target_phys_addr_t addr,
+                                 unsigned size)
 {
     uint32_t val;
     PCIBonitoState *s = opaque;
@@ -395,23 +379,21 @@ static uint32_t bonito_cop_readl(void *opaque, target_phys_addr_t addr)
 }
 
 static void bonito_cop_writel(void *opaque, target_phys_addr_t addr,
-                              uint32_t val)
+                              uint64_t val, unsigned size)
 {
     PCIBonitoState *s = opaque;
 
     ((uint32_t *)(&s->boncop))[addr/sizeof(uint32_t)] = val & 0xffffffff;
 }
 
-static CPUWriteMemoryFunc * const bonito_cop_write[] = {
-    NULL,
-    NULL,
-    bonito_cop_writel,
-};
-
-static CPUReadMemoryFunc * const bonito_cop_read[] = {
-    NULL,
-    NULL,
-    bonito_cop_readl,
+static const MemoryRegionOps bonito_cop_ops = {
+    .read = bonito_cop_readl,
+    .write = bonito_cop_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static uint32_t bonito_sbridge_pciaddr(void *opaque, target_phys_addr_t addr)
@@ -602,16 +584,20 @@ static uint32_t bonito_spciconf_readl(void *opaque, target_phys_addr_t addr)
 }
 
 /* south bridge PCI configure space. 0x1fe8 0000 - 0x1fef ffff */
-static CPUWriteMemoryFunc * const bonito_spciconf_write[] = {
-    bonito_spciconf_writeb,
-    bonito_spciconf_writew,
-    bonito_spciconf_writel,
-};
-
-static CPUReadMemoryFunc * const bonito_spciconf_read[] = {
-    bonito_spciconf_readb,
-    bonito_spciconf_readw,
-    bonito_spciconf_readl,
+static const MemoryRegionOps bonito_spciconf_ops = {
+    .old_mmio = {
+        .read = {
+            bonito_spciconf_readb,
+            bonito_spciconf_readw,
+            bonito_spciconf_readl,
+        },
+        .write = {
+            bonito_spciconf_writeb,
+            bonito_spciconf_writew,
+            bonito_spciconf_writel,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 #define BONITO_IRQ_BASE 32
@@ -690,51 +676,38 @@ static int bonito_pcihost_initfn(SysBusDevice *dev)
 static int bonito_initfn(PCIDevice *dev)
 {
     PCIBonitoState *s = DO_UPCAST(PCIBonitoState, dev, dev);
+    SysBusDevice *sysbus = &s->pcihost->busdev;
 
     /* Bonito North Bridge, built on FPGA, VENDOR_ID/DEVICE_ID are "undefined" */
     pci_config_set_prog_interface(dev->config, 0x00);
 
     /* set the north bridge register mapping */
-    s->bonito_reg_handle = cpu_register_io_memory(bonito_read, bonito_write, s,
-                                                  DEVICE_NATIVE_ENDIAN);
-    s->bonito_reg_start = BONITO_INTERNAL_REG_BASE;
-    s->bonito_reg_length = BONITO_INTERNAL_REG_SIZE;
-    cpu_register_physical_memory(s->bonito_reg_start, s->bonito_reg_length,
-                                 s->bonito_reg_handle);
+    memory_region_init_io(&s->iomem, &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 */
-    s->bonito_pciconf_handle = cpu_register_io_memory(bonito_pciconf_read,
-                                                      bonito_pciconf_write, s,
-                                                      DEVICE_NATIVE_ENDIAN);
-    s->bonito_pciconf_start = BONITO_PCICONFIG_BASE;
-    s->bonito_pciconf_length = BONITO_PCICONFIG_SIZE;
-    cpu_register_physical_memory(s->bonito_pciconf_start, s->bonito_pciconf_length,
-                                 s->bonito_pciconf_handle);
+    memory_region_init_io(&s->pcihost->conf_mem, &bonito_pciconf_ops, s,
+                          "north-bridge-pci-config", BONITO_PCICONFIG_SIZE);
+    sysbus_init_mmio(sysbus, &s->pcihost->conf_mem);
+    sysbus_mmio_map(sysbus, 1, BONITO_PCICONFIG_BASE);
 
     /* set the south bridge pci configure  mapping */
-    s->bonito_spciconf_handle = cpu_register_io_memory(bonito_spciconf_read,
-                                                       bonito_spciconf_write, s,
-                                                       DEVICE_NATIVE_ENDIAN);
-    s->bonito_spciconf_start = BONITO_SPCICONFIG_BASE;
-    s->bonito_spciconf_length = BONITO_SPCICONFIG_SIZE;
-    cpu_register_physical_memory(s->bonito_spciconf_start, s->bonito_spciconf_length,
-                                 s->bonito_spciconf_handle);
-
-    s->bonito_ldma_handle = cpu_register_io_memory(bonito_ldma_read,
-                                                   bonito_ldma_write, s,
-                                                   DEVICE_NATIVE_ENDIAN);
-    s->bonito_ldma_start = 0xbfe00200;
-    s->bonito_ldma_length = 0x100;
-    cpu_register_physical_memory(s->bonito_ldma_start, s->bonito_ldma_length,
-                                 s->bonito_ldma_handle);
-
-    s->bonito_cop_handle = cpu_register_io_memory(bonito_cop_read,
-                                                  bonito_cop_write, s,
-                                                  DEVICE_NATIVE_ENDIAN);
-    s->bonito_cop_start = 0xbfe00300;
-    s->bonito_cop_length = 0x100;
-    cpu_register_physical_memory(s->bonito_cop_start, s->bonito_cop_length,
-                                 s->bonito_cop_handle);
+    memory_region_init_io(&s->pcihost->data_mem, &bonito_spciconf_ops, s,
+                          "south-bridge-pci-config", BONITO_SPCICONFIG_SIZE);
+    sysbus_init_mmio(sysbus, &s->pcihost->data_mem);
+    sysbus_mmio_map(sysbus, 2, BONITO_SPCICONFIG_BASE);
+
+    memory_region_init_io(&s->iomem_ldma, &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,
+                          "cop", 0x100);
+    sysbus_init_mmio(sysbus, &s->iomem_cop);
+    sysbus_mmio_map(sysbus, 4, 0xbfe00300);
 
     /* Map PCI IO Space  0x1fd0 0000 - 0x1fd1 0000 */
     s->bonito_pciio_start = BONITO_PCIIO_BASE;
@@ -780,10 +753,12 @@ PCIBus *bonito_init(qemu_irq *pic)
     pcihost->bus = b;
     qdev_init_nofail(dev);
 
-    d = pci_create_simple(b, PCI_DEVFN(0, 0), "Bonito");
+    /* set the pcihost pointer before bonito_initfn is called */
+    d = pci_create(b, PCI_DEVFN(0, 0), "Bonito");
     s = DO_UPCAST(PCIBonitoState, dev, d);
     s->pcihost = pcihost;
     bonito_state = s;
+    qdev_init_nofail(&d->qdev);
 
     return b;
 }
diff --git a/hw/cs4231.c b/hw/cs4231.c
index a65b697a19..2dfb708fe7 100644
--- a/hw/cs4231.c
+++ b/hw/cs4231.c
@@ -35,6 +35,7 @@
 
 typedef struct CSState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     qemu_irq irq;
     uint32_t regs[CS_REGS];
     uint8_t dregs[CS_DREGS];
@@ -54,7 +55,8 @@ static void cs_reset(DeviceState *d)
     s->dregs[25] = CS_VER;
 }
 
-static uint32_t cs_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t cs_mem_read(void *opaque, target_phys_addr_t addr,
+                            unsigned size)
 {
     CSState *s = opaque;
     uint32_t saddr, ret;
@@ -80,7 +82,8 @@ static uint32_t cs_mem_readl(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static void cs_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void cs_mem_write(void *opaque, target_phys_addr_t addr,
+                         uint64_t val, unsigned size)
 {
     CSState *s = opaque;
     uint32_t saddr;
@@ -119,16 +122,10 @@ static void cs_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
-static CPUReadMemoryFunc * const cs_mem_read[3] = {
-    cs_mem_readl,
-    cs_mem_readl,
-    cs_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const cs_mem_write[3] = {
-    cs_mem_writel,
-    cs_mem_writel,
-    cs_mem_writel,
+static const MemoryRegionOps cs_mem_ops = {
+    .read = cs_mem_read,
+    .write = cs_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_cs4231 = {
@@ -145,12 +142,10 @@ static const VMStateDescription vmstate_cs4231 = {
 
 static int cs4231_init1(SysBusDevice *dev)
 {
-    int io;
     CSState *s = FROM_SYSBUS(CSState, dev);
 
-    io = cpu_register_io_memory(cs_mem_read, cs_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, CS_SIZE, io);
+    memory_region_init_io(&s->iomem, &cs_mem_ops, s, "cs4321", CS_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
     return 0;
diff --git a/hw/dec_pci.c b/hw/dec_pci.c
index 1aec06611c..08d4e06697 100644
--- a/hw/dec_pci.c
+++ b/hw/dec_pci.c
@@ -87,8 +87,8 @@ static int pci_dec_21154_init_device(SysBusDevice *dev)
                           &s->host_state, "pci-conf-idx", 0x1000);
     memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
                           &s->host_state, "pci-data-idx", 0x1000);
-    sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio_region(dev, &s->host_state.data_mem);
+    sysbus_init_mmio(dev, &s->host_state.conf_mem);
+    sysbus_init_mmio(dev, &s->host_state.data_mem);
     return 0;
 }
 
diff --git a/hw/dp8393x.c b/hw/dp8393x.c
index f66844b108..54f5864b43 100644
--- a/hw/dp8393x.c
+++ b/hw/dp8393x.c
@@ -156,7 +156,8 @@ typedef struct dp8393xState {
     int64_t wt_last_update;
     NICConf conf;
     NICState *nic;
-    int mmio_index;
+    MemoryRegion *address_space;
+    MemoryRegion mmio;
 
     /* Registers */
     uint8_t cam[16][6];
@@ -664,16 +665,12 @@ static void dp8393x_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     dp8393x_writew(opaque, addr + 2, (val >> 16) & 0xffff);
 }
 
-static CPUReadMemoryFunc * const dp8393x_read[3] = {
-    dp8393x_readb,
-    dp8393x_readw,
-    dp8393x_readl,
-};
-
-static CPUWriteMemoryFunc * const dp8393x_write[3] = {
-    dp8393x_writeb,
-    dp8393x_writew,
-    dp8393x_writel,
+static const MemoryRegionOps dp8393x_ops = {
+    .old_mmio = {
+        .read = { dp8393x_readb, dp8393x_readw, dp8393x_readl, },
+        .write = { dp8393x_writeb, dp8393x_writew, dp8393x_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int nic_can_receive(VLANClientState *nc)
@@ -865,7 +862,8 @@ static void nic_cleanup(VLANClientState *nc)
 {
     dp8393xState *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
-    cpu_unregister_io_memory(s->mmio_index);
+    memory_region_del_subregion(s->address_space, &s->mmio);
+    memory_region_destroy(&s->mmio);
 
     qemu_del_timer(s->watchdog);
     qemu_free_timer(s->watchdog);
@@ -882,6 +880,7 @@ static NetClientInfo net_dp83932_info = {
 };
 
 void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift,
+                  MemoryRegion *address_space,
                   qemu_irq irq, void* mem_opaque,
                   void (*memory_rw)(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write))
 {
@@ -891,6 +890,7 @@ void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift,
 
     s = g_malloc0(sizeof(dp8393xState));
 
+    s->address_space = address_space;
     s->mem_opaque = mem_opaque;
     s->memory_rw = memory_rw;
     s->it_shift = it_shift;
@@ -908,7 +908,7 @@ void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift,
     qemu_register_reset(nic_reset, s);
     nic_reset(s);
 
-    s->mmio_index = cpu_register_io_memory(dp8393x_read, dp8393x_write, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x40 << it_shift, s->mmio_index);
+    memory_region_init_io(&s->mmio, &dp8393x_ops, s,
+                          "dp8393x", 0x40 << it_shift);
+    memory_region_add_subregion(address_space, base, &s->mmio);
 }
diff --git a/hw/ds1225y.c b/hw/ds1225y.c
index 6852a61d08..59d224edfe 100644
--- a/hw/ds1225y.c
+++ b/hw/ds1225y.c
@@ -27,13 +27,14 @@
 
 typedef struct {
     DeviceState qdev;
+    MemoryRegion iomem;
     uint32_t chip_size;
     char *filename;
     FILE *file;
     uint8_t *contents;
 } NvRamState;
 
-static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
+static uint64_t nvram_read(void *opaque, target_phys_addr_t addr, unsigned size)
 {
     NvRamState *s = opaque;
     uint32_t val;
@@ -43,25 +44,8 @@ static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
     return val;
 }
 
-static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-    v = nvram_readb(opaque, addr);
-    v |= nvram_readb(opaque, addr + 1) << 8;
-    return v;
-}
-
-static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-    v = nvram_readb(opaque, addr);
-    v |= nvram_readb(opaque, addr + 1) << 8;
-    v |= nvram_readb(opaque, addr + 2) << 16;
-    v |= nvram_readb(opaque, addr + 3) << 24;
-    return v;
-}
-
-static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t val)
+static void nvram_write(void *opaque, target_phys_addr_t addr, uint64_t val,
+                        unsigned size)
 {
     NvRamState *s = opaque;
 
@@ -76,30 +60,14 @@ static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
-static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    nvram_writeb(opaque, addr, val & 0xff);
-    nvram_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    nvram_writeb(opaque, addr, val & 0xff);
-    nvram_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    nvram_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    nvram_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
-static CPUReadMemoryFunc * const nvram_read[] = {
-    &nvram_readb,
-    &nvram_readw,
-    &nvram_readl,
-};
-
-static CPUWriteMemoryFunc * const nvram_write[] = {
-    &nvram_writeb,
-    &nvram_writew,
-    &nvram_writel,
+static const MemoryRegionOps nvram_ops = {
+    .read = nvram_read,
+    .write = nvram_write,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static int nvram_post_load(void *opaque, int version_id)
@@ -146,13 +114,11 @@ static int nvram_sysbus_initfn(SysBusDevice *dev)
 {
     NvRamState *s = &FROM_SYSBUS(SysBusNvRamState, dev)->nvram;
     FILE *file;
-    int s_io;
 
     s->contents = g_malloc0(s->chip_size);
 
-    s_io = cpu_register_io_memory(nvram_read, nvram_write, s,
-                                  DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, s->chip_size, s_io);
+    memory_region_init_io(&s->iomem, &nvram_ops, s, "nvram", s->chip_size);
+    sysbus_init_mmio(dev, &s->iomem);
 
     /* Read current file */
     file = fopen(s->filename, "rb");
diff --git a/hw/eccmemctl.c b/hw/eccmemctl.c
index 2bda87b6c9..774346543a 100644
--- a/hw/eccmemctl.c
+++ b/hw/eccmemctl.c
@@ -122,13 +122,15 @@
 
 typedef struct ECCState {
     SysBusDevice busdev;
+    MemoryRegion iomem, iomem_diag;
     qemu_irq irq;
     uint32_t regs[ECC_NREGS];
     uint8_t diag[ECC_DIAG_SIZE];
     uint32_t version;
 } ECCState;
 
-static void ecc_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void ecc_mem_write(void *opaque, target_phys_addr_t addr, uint64_t val,
+                          unsigned size)
 {
     ECCState *s = opaque;
 
@@ -170,7 +172,8 @@ static void ecc_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
-static uint32_t ecc_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t ecc_mem_read(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
 {
     ECCState *s = opaque;
     uint32_t ret = 0;
@@ -216,20 +219,18 @@ static uint32_t ecc_mem_readl(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static CPUReadMemoryFunc * const ecc_mem_read[3] = {
-    NULL,
-    NULL,
-    ecc_mem_readl,
+static const MemoryRegionOps ecc_mem_ops = {
+    .read = ecc_mem_read,
+    .write = ecc_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
-static CPUWriteMemoryFunc * const ecc_mem_write[3] = {
-    NULL,
-    NULL,
-    ecc_mem_writel,
-};
-
-static void ecc_diag_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                uint32_t val)
+static void ecc_diag_mem_write(void *opaque, target_phys_addr_t addr,
+                               uint64_t val, unsigned size)
 {
     ECCState *s = opaque;
 
@@ -237,7 +238,8 @@ static void ecc_diag_mem_writeb(void *opaque, target_phys_addr_t addr,
     s->diag[addr & ECC_DIAG_MASK] = val;
 }
 
-static uint32_t ecc_diag_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t ecc_diag_mem_read(void *opaque, target_phys_addr_t addr,
+                                  unsigned size)
 {
     ECCState *s = opaque;
     uint32_t ret = s->diag[(int)addr];
@@ -246,16 +248,14 @@ static uint32_t ecc_diag_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static CPUReadMemoryFunc * const ecc_diag_mem_read[3] = {
-    ecc_diag_mem_readb,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const ecc_diag_mem_write[3] = {
-    ecc_diag_mem_writeb,
-    NULL,
-    NULL,
+static const MemoryRegionOps ecc_diag_mem_ops = {
+    .read = ecc_diag_mem_read,
+    .write = ecc_diag_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static const VMStateDescription vmstate_ecc = {
@@ -292,20 +292,17 @@ static void ecc_reset(DeviceState *d)
 
 static int ecc_init1(SysBusDevice *dev)
 {
-    int ecc_io_memory;
     ECCState *s = FROM_SYSBUS(ECCState, dev);
 
     sysbus_init_irq(dev, &s->irq);
     s->regs[0] = s->version;
-    ecc_io_memory = cpu_register_io_memory(ecc_mem_read, ecc_mem_write, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, ECC_SIZE, ecc_io_memory);
+    memory_region_init_io(&s->iomem, &ecc_mem_ops, s, "ecc", ECC_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
 
     if (s->version == ECC_MCC) { // SS-600MP only
-        ecc_io_memory = cpu_register_io_memory(ecc_diag_mem_read,
-                                               ecc_diag_mem_write, s,
-                                               DEVICE_NATIVE_ENDIAN);
-        sysbus_init_mmio(dev, ECC_DIAG_SIZE, ecc_io_memory);
+        memory_region_init_io(&s->iomem_diag, &ecc_diag_mem_ops, s,
+                              "ecc.diag", ECC_DIAG_SIZE);
+        sysbus_init_mmio(dev, &s->iomem_diag);
     }
 
     return 0;
diff --git a/hw/empty_slot.c b/hw/empty_slot.c
index da8adc4d03..8b734f2c9f 100644
--- a/hw/empty_slot.c
+++ b/hw/empty_slot.c
@@ -24,31 +24,27 @@
 
 typedef struct EmptySlot {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint64_t size;
 } EmptySlot;
 
-static uint32_t empty_slot_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t empty_slot_read(void *opaque, target_phys_addr_t addr,
+                                unsigned size)
 {
     DPRINTF("read from " TARGET_FMT_plx "\n", addr);
     return 0;
 }
 
-static void empty_slot_writel(void *opaque, target_phys_addr_t addr,
-                              uint32_t val)
+static void empty_slot_write(void *opaque, target_phys_addr_t addr,
+                             uint64_t val, unsigned size)
 {
-    DPRINTF("write 0x%x to " TARGET_FMT_plx "\n", val, addr);
+    DPRINTF("write 0x%x to " TARGET_FMT_plx "\n", (unsigned)val, addr);
 }
 
-CPUReadMemoryFunc * const empty_slot_read[3] = {
-    empty_slot_readl,
-    empty_slot_readl,
-    empty_slot_readl,
-};
-
-static CPUWriteMemoryFunc * const empty_slot_write[3] = {
-    empty_slot_writel,
-    empty_slot_writel,
-    empty_slot_writel,
+static const MemoryRegionOps empty_slot_ops = {
+    .read = empty_slot_read,
+    .write = empty_slot_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 void empty_slot_init(target_phys_addr_t addr, uint64_t slot_size)
@@ -73,12 +69,10 @@ void empty_slot_init(target_phys_addr_t addr, uint64_t slot_size)
 static int empty_slot_init1(SysBusDevice *dev)
 {
     EmptySlot *s = FROM_SYSBUS(EmptySlot, dev);
-    ram_addr_t empty_slot_offset;
 
-    empty_slot_offset = cpu_register_io_memory(empty_slot_read,
-                                               empty_slot_write, s,
-                                               DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, s->size, empty_slot_offset | IO_MEM_RAM);
+    memory_region_init_io(&s->iomem, &empty_slot_ops, s,
+                          "empty-slot", s->size);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
diff --git a/hw/escc.c b/hw/escc.c
index 13c7e66b36..81204a633d 100644
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -888,7 +888,7 @@ static int escc_init1(SysBusDevice *dev)
 
     memory_region_init_io(&s->mmio, &escc_mem_ops, s, "escc",
                           ESCC_SIZE << s->it_shift);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
 
     if (s->chn[0].type == mouse) {
         qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0,
diff --git a/hw/esp.c b/hw/esp.c
index b698a43fe6..9551c7846b 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -45,6 +45,7 @@ typedef struct ESPState ESPState;
 
 struct ESPState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint8_t rregs[ESP_REGS];
     uint8_t wregs[ESP_REGS];
     qemu_irq irq;
@@ -504,7 +505,8 @@ static void esp_gpio_demux(void *opaque, int irq, int level)
     }
 }
 
-static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t esp_mem_read(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
 {
     ESPState *s = opaque;
     uint32_t saddr, old_val;
@@ -545,7 +547,8 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
     return s->rregs[saddr];
 }
 
-static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void esp_mem_write(void *opaque, target_phys_addr_t addr,
+                          uint64_t val, unsigned size)
 {
     ESPState *s = opaque;
     uint32_t saddr;
@@ -641,7 +644,7 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
             s->rregs[ESP_RINTR] = 0;
             break;
         default:
-            ESP_ERROR("Unhandled ESP command (%2.2x)\n", val);
+            ESP_ERROR("Unhandled ESP command (%2.2x)\n", (unsigned)val);
             break;
         }
         break;
@@ -656,22 +659,23 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
         s->rregs[saddr] = val;
         break;
     default:
-        ESP_ERROR("invalid write of 0x%02x at [0x%x]\n", val, saddr);
+        ESP_ERROR("invalid write of 0x%02x at [0x%x]\n", (unsigned)val, saddr);
         return;
     }
     s->wregs[saddr] = val;
 }
 
-static CPUReadMemoryFunc * const esp_mem_read[3] = {
-    esp_mem_readb,
-    NULL,
-    NULL,
-};
+static bool esp_mem_accepts(void *opaque, target_phys_addr_t addr,
+                            unsigned size, bool is_write)
+{
+    return (size == 1) || (is_write && size == 4);
+}
 
-static CPUWriteMemoryFunc * const esp_mem_write[3] = {
-    esp_mem_writeb,
-    NULL,
-    esp_mem_writeb,
+static const MemoryRegionOps esp_mem_ops = {
+    .read = esp_mem_read,
+    .write = esp_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid.accepts = esp_mem_accepts,
 };
 
 static const VMStateDescription vmstate_esp = {
@@ -735,14 +739,13 @@ static const struct SCSIBusInfo esp_scsi_info = {
 static int esp_init1(SysBusDevice *dev)
 {
     ESPState *s = FROM_SYSBUS(ESPState, dev);
-    int esp_io_memory;
 
     sysbus_init_irq(dev, &s->irq);
     assert(s->it_shift != -1);
 
-    esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, ESP_REGS << s->it_shift, esp_io_memory);
+    memory_region_init_io(&s->iomem, &esp_mem_ops, s,
+                          "esp", ESP_REGS << s->it_shift);
+    sysbus_init_mmio(dev, &s->iomem);
 
     qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2);
 
diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c
index 246a279b20..5ac2d15fa1 100644
--- a/hw/etraxfs_eth.c
+++ b/hw/etraxfs_eth.c
@@ -604,7 +604,7 @@ static int fs_eth_init(SysBusDevice *dev)
 	s->dma_in->client.pull = NULL;
 
 	memory_region_init_io(&s->mmio, &eth_ops, s, "etraxfs-eth", 0x5c);
-	sysbus_init_mmio_region(dev, &s->mmio);
+	sysbus_init_mmio(dev, &s->mmio);
 
 	qemu_macaddr_default_if_unset(&s->conf.macaddr);
 	s->nic = qemu_new_nic(&net_etraxfs_info, &s->conf,
diff --git a/hw/etraxfs_pic.c b/hw/etraxfs_pic.c
index 47a56d753c..72cbdb8c89 100644
--- a/hw/etraxfs_pic.c
+++ b/hw/etraxfs_pic.c
@@ -147,7 +147,7 @@ static int etraxfs_pic_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->parent_nmi);
 
     memory_region_init_io(&s->mmio, &pic_ops, s, "etraxfs-pic", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
     return 0;
 }
 
diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
index 298b9857ca..2623dab9d4 100644
--- a/hw/etraxfs_ser.c
+++ b/hw/etraxfs_ser.c
@@ -214,7 +214,7 @@ static int etraxfs_ser_init(SysBusDevice *dev)
 
     sysbus_init_irq(dev, &s->irq);
     memory_region_init_io(&s->mmio, &ser_ops, s, "etraxfs-serial", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
 
     s->chr = qdev_init_chardev(&dev->qdev);
     if (s->chr)
diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c
index 57dc739710..319cee130b 100644
--- a/hw/etraxfs_timer.c
+++ b/hw/etraxfs_timer.c
@@ -323,7 +323,7 @@ static int etraxfs_timer_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &t->nmi);
 
     memory_region_init_io(&t->mmio, &timer_ops, t, "etraxfs-timer", 0x5c);
-    sysbus_init_mmio_region(dev, &t->mmio);
+    sysbus_init_mmio(dev, &t->mmio);
     qemu_register_reset(etraxfs_timer_reset, t);
     return 0;
 }
diff --git a/hw/fdc.c b/hw/fdc.c
index ecaad0965c..2adfb44b3b 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -373,6 +373,7 @@ enum {
 #define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT)
 
 struct FDCtrl {
+    MemoryRegion iomem;
     qemu_irq irq;
     /* Controller state */
     QEMUTimer *result_timer;
@@ -491,39 +492,32 @@ static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
     }
 }
 
-static uint32_t fdctrl_read_mem (void *opaque, target_phys_addr_t reg)
+static uint64_t fdctrl_read_mem (void *opaque, target_phys_addr_t reg,
+                                 unsigned ize)
 {
     return fdctrl_read(opaque, (uint32_t)reg);
 }
 
-static void fdctrl_write_mem (void *opaque,
-                              target_phys_addr_t reg, uint32_t value)
+static void fdctrl_write_mem (void *opaque, target_phys_addr_t reg,
+                              uint64_t value, unsigned size)
 {
     fdctrl_write(opaque, (uint32_t)reg, value);
 }
 
-static CPUReadMemoryFunc * const fdctrl_mem_read[3] = {
-    fdctrl_read_mem,
-    fdctrl_read_mem,
-    fdctrl_read_mem,
+static const MemoryRegionOps fdctrl_mem_ops = {
+    .read = fdctrl_read_mem,
+    .write = fdctrl_write_mem,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const fdctrl_mem_write[3] = {
-    fdctrl_write_mem,
-    fdctrl_write_mem,
-    fdctrl_write_mem,
-};
-
-static CPUReadMemoryFunc * const fdctrl_mem_read_strict[3] = {
-    fdctrl_read_mem,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const fdctrl_mem_write_strict[3] = {
-    fdctrl_write_mem,
-    NULL,
-    NULL,
+static const MemoryRegionOps fdctrl_mem_strict_ops = {
+    .read = fdctrl_read_mem,
+    .write = fdctrl_write_mem,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static bool fdrive_media_changed_needed(void *opaque)
@@ -1914,17 +1908,15 @@ static int sysbus_fdc_init1(SysBusDevice *dev)
 {
     FDCtrlSysBus *sys = DO_UPCAST(FDCtrlSysBus, busdev, dev);
     FDCtrl *fdctrl = &sys->state;
-    int io;
     int ret;
 
-    io = cpu_register_io_memory(fdctrl_mem_read, fdctrl_mem_write, fdctrl,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x08, io);
+    memory_region_init_io(&fdctrl->iomem, &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);
     fdctrl->dma_chann = -1;
 
-    qdev_set_legacy_instance_id(&dev->qdev, io, 2);
+    qdev_set_legacy_instance_id(&dev->qdev, 0 /* io */, 2); /* FIXME */
     ret = fdctrl_init_common(fdctrl);
 
     return ret;
@@ -1933,17 +1925,15 @@ static int sysbus_fdc_init1(SysBusDevice *dev)
 static int sun4m_fdc_init1(SysBusDevice *dev)
 {
     FDCtrl *fdctrl = &(FROM_SYSBUS(FDCtrlSysBus, dev)->state);
-    int io;
 
-    io = cpu_register_io_memory(fdctrl_mem_read_strict,
-                                fdctrl_mem_write_strict, fdctrl,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x08, io);
+    memory_region_init_io(&fdctrl->iomem, &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);
 
     fdctrl->sun4m = 1;
-    qdev_set_legacy_instance_id(&dev->qdev, io, 2);
+    qdev_set_legacy_instance_id(&dev->qdev, 0 /* io */, 2); /* FIXME */
     return fdctrl_init_common(fdctrl);
 }
 
diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
index dbcb888bbd..f9535328f0 100644
--- a/hw/fw_cfg.c
+++ b/hw/fw_cfg.c
@@ -39,6 +39,7 @@
 #endif
 
 #define FW_CFG_SIZE 2
+#define FW_CFG_DATA_SIZE 1
 
 typedef struct FWCfgEntry {
     uint32_t len;
@@ -49,6 +50,7 @@ typedef struct FWCfgEntry {
 
 struct FWCfgState {
     SysBusDevice busdev;
+    MemoryRegion ctl_iomem, data_iomem, comb_iomem;
     uint32_t ctl_iobase, data_iobase;
     FWCfgEntry entries[2][FW_CFG_MAX_ENTRY];
     FWCfgFiles *files;
@@ -232,60 +234,76 @@ static uint8_t fw_cfg_read(FWCfgState *s)
     return ret;
 }
 
-static uint32_t fw_cfg_io_readb(void *opaque, uint32_t addr)
+static uint64_t fw_cfg_data_mem_read(void *opaque, target_phys_addr_t addr,
+                                     unsigned size)
 {
     return fw_cfg_read(opaque);
 }
 
-static void fw_cfg_io_writeb(void *opaque, uint32_t addr, uint32_t value)
+static void fw_cfg_data_mem_write(void *opaque, target_phys_addr_t addr,
+                                  uint64_t value, unsigned size)
 {
     fw_cfg_write(opaque, (uint8_t)value);
 }
 
-static void fw_cfg_io_writew(void *opaque, uint32_t addr, uint32_t value)
+static void fw_cfg_ctl_mem_write(void *opaque, target_phys_addr_t addr,
+                                 uint64_t value, unsigned size)
 {
     fw_cfg_select(opaque, (uint16_t)value);
 }
 
-static uint32_t fw_cfg_mem_readb(void *opaque, target_phys_addr_t addr)
+static bool fw_cfg_ctl_mem_valid(void *opaque, target_phys_addr_t addr,
+                                 unsigned size, bool is_write)
 {
-    return fw_cfg_read(opaque);
+    return is_write && size == 2;
 }
 
-static void fw_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
-                              uint32_t value)
+static uint64_t fw_cfg_comb_read(void *opaque, target_phys_addr_t addr,
+                                 unsigned size)
 {
-    fw_cfg_write(opaque, (uint8_t)value);
+    return fw_cfg_read(opaque);
 }
 
-static void fw_cfg_mem_writew(void *opaque, target_phys_addr_t addr,
-                              uint32_t value)
+static void fw_cfg_comb_write(void *opaque, target_phys_addr_t addr,
+                              uint64_t value, unsigned size)
 {
-    fw_cfg_select(opaque, (uint16_t)value);
+    switch (size) {
+    case 1:
+        fw_cfg_write(opaque, (uint8_t)value);
+        break;
+    case 2:
+        fw_cfg_select(opaque, (uint16_t)value);
+        break;
+    }
 }
 
-static CPUReadMemoryFunc * const fw_cfg_ctl_mem_read[3] = {
-    NULL,
-    NULL,
-    NULL,
-};
+static bool fw_cfg_comb_valid(void *opaque, target_phys_addr_t addr,
+                                  unsigned size, bool is_write)
+{
+    return (size == 1) || (is_write && size == 2);
+}
 
-static CPUWriteMemoryFunc * const fw_cfg_ctl_mem_write[3] = {
-    NULL,
-    fw_cfg_mem_writew,
-    NULL,
+static const MemoryRegionOps fw_cfg_ctl_mem_ops = {
+    .write = fw_cfg_ctl_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid.accepts = fw_cfg_ctl_mem_valid,
 };
 
-static CPUReadMemoryFunc * const fw_cfg_data_mem_read[3] = {
-    fw_cfg_mem_readb,
-    NULL,
-    NULL,
+static const MemoryRegionOps fw_cfg_data_mem_ops = {
+    .read = fw_cfg_data_mem_read,
+    .write = fw_cfg_data_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
-static CPUWriteMemoryFunc * const fw_cfg_data_mem_write[3] = {
-    fw_cfg_mem_writeb,
-    NULL,
-    NULL,
+static const MemoryRegionOps fw_cfg_comb_mem_ops = {
+    .read = fw_cfg_comb_read,
+    .write = fw_cfg_comb_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid.accepts = fw_cfg_comb_valid,
 };
 
 static void fw_cfg_reset(DeviceState *d)
@@ -489,24 +507,26 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
 static int fw_cfg_init1(SysBusDevice *dev)
 {
     FWCfgState *s = FROM_SYSBUS(FWCfgState, dev);
-    int io_ctl_memory, io_data_memory;
-
-    io_ctl_memory = cpu_register_io_memory(fw_cfg_ctl_mem_read,
-                                           fw_cfg_ctl_mem_write, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, FW_CFG_SIZE, io_ctl_memory);
 
-    io_data_memory = cpu_register_io_memory(fw_cfg_data_mem_read,
-                                            fw_cfg_data_mem_write, s,
-                                            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, FW_CFG_SIZE, io_data_memory);
-
-    if (s->ctl_iobase) {
-        register_ioport_write(s->ctl_iobase, 2, 2, fw_cfg_io_writew, s);
-    }
-    if (s->data_iobase) {
-        register_ioport_read(s->data_iobase, 1, 1, fw_cfg_io_readb, s);
-        register_ioport_write(s->data_iobase, 1, 1, fw_cfg_io_writeb, s);
+    memory_region_init_io(&s->ctl_iomem, &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,
+                          "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,
+                          "fwcfg", FW_CFG_SIZE);
+
+    if (s->ctl_iobase + 1 == s->data_iobase) {
+        sysbus_add_io(dev, s->ctl_iobase, &s->comb_iomem);
+    } else {
+        if (s->ctl_iobase) {
+            sysbus_add_io(dev, s->ctl_iobase, &s->ctl_iomem);
+        }
+        if (s->data_iobase) {
+            sysbus_add_io(dev, s->data_iobase, &s->data_iomem);
+        }
     }
     return 0;
 }
diff --git a/hw/g364fb.c b/hw/g364fb.c
index f00ee27b17..34fb08c097 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -540,8 +540,8 @@ static int g364fb_sysbus_init(SysBusDevice *dev)
 
     g364fb_init(&dev->qdev, s);
     sysbus_init_irq(dev, &s->irq);
-    sysbus_init_mmio_region(dev, &s->mem_ctrl);
-    sysbus_init_mmio_region(dev, &s->mem_vram);
+    sysbus_init_mmio(dev, &s->mem_ctrl);
+    sysbus_init_mmio(dev, &s->mem_vram);
 
     return 0;
 }
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index 94a608ef6d..1e529fb5d0 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -108,8 +108,8 @@ static int pci_grackle_init_device(SysBusDevice *dev)
                           &s->host_state, "pci-conf-idx", 0x1000);
     memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
                           &s->host_state, "pci-data-idx", 0x1000);
-    sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio_region(dev, &s->host_state.data_mem);
+    sysbus_init_mmio(dev, &s->host_state.conf_mem);
+    sysbus_init_mmio(dev, &s->host_state.data_mem);
 
     qemu_register_reset(pci_grackle_reset, &s->host_state);
     return 0;
diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
index c90b810413..62bdb03a9c 100644
--- a/hw/grlib_apbuart.c
+++ b/hw/grlib_apbuart.c
@@ -67,7 +67,7 @@
 
 typedef struct UART {
     SysBusDevice busdev;
-
+    MemoryRegion iomem;
     qemu_irq irq;
 
     CharDriverState *chr;
@@ -103,7 +103,8 @@ static void grlib_apbuart_event(void *opaque, int event)
 }
 
 static void
-grlib_apbuart_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
+grlib_apbuart_write(void *opaque, target_phys_addr_t addr,
+                    uint64_t value, unsigned size)
 {
     UART          *uart = opaque;
     unsigned char  c    = 0;
@@ -136,18 +137,21 @@ grlib_apbuart_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
     trace_grlib_apbuart_writel_unknown(addr, value);
 }
 
-static CPUReadMemoryFunc * const grlib_apbuart_read[] = {
-    NULL, NULL, NULL,
-};
+static bool grlib_apbuart_accepts(void *opaque, target_phys_addr_t addr,
+                                  unsigned size, bool is_write)
+{
+    return is_write && size == 4;
+}
 
-static CPUWriteMemoryFunc * const grlib_apbuart_write[] = {
-    NULL, NULL, grlib_apbuart_writel,
+static const MemoryRegionOps grlib_apbuart_ops = {
+    .write = grlib_apbuart_write,
+    .valid.accepts = grlib_apbuart_accepts,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int grlib_apbuart_init(SysBusDevice *dev)
 {
     UART *uart      = FROM_SYSBUS(typeof(*uart), dev);
-    int   uart_regs = 0;
 
     qemu_chr_add_handlers(uart->chr,
                           grlib_apbuart_can_receive,
@@ -157,14 +161,10 @@ static int grlib_apbuart_init(SysBusDevice *dev)
 
     sysbus_init_irq(dev, &uart->irq);
 
-    uart_regs = cpu_register_io_memory(grlib_apbuart_read,
-                                       grlib_apbuart_write,
-                                       uart, DEVICE_NATIVE_ENDIAN);
-    if (uart_regs < 0) {
-        return -1;
-    }
+    memory_region_init_io(&uart->iomem, &grlib_apbuart_ops, uart,
+                          "uart", UART_REG_SIZE);
 
-    sysbus_init_mmio(dev, UART_REG_SIZE, uart_regs);
+    sysbus_init_mmio(dev, &uart->iomem);
 
     return 0;
 }
diff --git a/hw/grlib_gptimer.c b/hw/grlib_gptimer.c
index 85869b95eb..5645054c3c 100644
--- a/hw/grlib_gptimer.c
+++ b/hw/grlib_gptimer.c
@@ -68,6 +68,7 @@ struct GPTimer {
 
 struct GPTimerUnit {
     SysBusDevice  busdev;
+    MemoryRegion iomem;
 
     uint32_t nr_timers;         /* Number of timers available */
     uint32_t freq_hz;           /* System frequency */
@@ -153,7 +154,8 @@ static void grlib_gptimer_hit(void *opaque)
     }
 }
 
-static uint32_t grlib_gptimer_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t grlib_gptimer_read(void *opaque, target_phys_addr_t addr,
+                                   unsigned size)
 {
     GPTimerUnit        *unit  = opaque;
     target_phys_addr_t  timer_addr;
@@ -211,8 +213,8 @@ static uint32_t grlib_gptimer_readl(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
-static void
-grlib_gptimer_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void grlib_gptimer_write(void *opaque, target_phys_addr_t addr,
+                                uint64_t value, unsigned size)
 {
     GPTimerUnit        *unit = opaque;
     target_phys_addr_t  timer_addr;
@@ -299,12 +301,14 @@ grlib_gptimer_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
     trace_grlib_gptimer_writel(-1, addr, value);
 }
 
-static CPUReadMemoryFunc * const grlib_gptimer_read[] = {
-    NULL, NULL, grlib_gptimer_readl,
-};
-
-static CPUWriteMemoryFunc * const grlib_gptimer_write[] = {
-    NULL, NULL, grlib_gptimer_writel,
+static const MemoryRegionOps grlib_gptimer_ops = {
+    .read = grlib_gptimer_read,
+    .write = grlib_gptimer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static void grlib_gptimer_reset(DeviceState *d)
@@ -340,7 +344,6 @@ static int grlib_gptimer_init(SysBusDevice *dev)
 {
     GPTimerUnit  *unit = FROM_SYSBUS(typeof(*unit), dev);
     unsigned int  i;
-    int           timer_regs;
 
     assert(unit->nr_timers > 0);
     assert(unit->nr_timers <= GPTIMER_MAX_TIMERS);
@@ -361,15 +364,10 @@ static int grlib_gptimer_init(SysBusDevice *dev)
         ptimer_set_freq(timer->ptimer, unit->freq_hz);
     }
 
-    timer_regs = cpu_register_io_memory(grlib_gptimer_read,
-                                        grlib_gptimer_write,
-                                        unit, DEVICE_NATIVE_ENDIAN);
-    if (timer_regs < 0) {
-        return -1;
-    }
+    memory_region_init_io(&unit->iomem, &grlib_gptimer_ops, unit, "gptimer",
+                          UNIT_REG_SIZE + GPTIMER_REG_SIZE * unit->nr_timers);
 
-    sysbus_init_mmio(dev, UNIT_REG_SIZE + GPTIMER_REG_SIZE * unit->nr_timers,
-                     timer_regs);
+    sysbus_init_mmio(dev, &unit->iomem);
     return 0;
 }
 
diff --git a/hw/grlib_irqmp.c b/hw/grlib_irqmp.c
index 9490a7830d..28725563c0 100644
--- a/hw/grlib_irqmp.c
+++ b/hw/grlib_irqmp.c
@@ -49,6 +49,7 @@ typedef struct IRQMPState IRQMPState;
 
 typedef struct IRQMP {
     SysBusDevice busdev;
+    MemoryRegion iomem;
 
     void *set_pil_in;
     void *set_pil_in_opaque;
@@ -161,7 +162,8 @@ void grlib_irqmp_set_irq(void *opaque, int irq, int level)
     }
 }
 
-static uint32_t grlib_irqmp_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t grlib_irqmp_read(void *opaque, target_phys_addr_t addr,
+                                 unsigned size)
 {
     IRQMP      *irqmp = opaque;
     IRQMPState *state;
@@ -224,8 +226,8 @@ static uint32_t grlib_irqmp_readl(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
-static void
-grlib_irqmp_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void grlib_irqmp_write(void *opaque, target_phys_addr_t addr,
+                              uint64_t value, unsigned size)
 {
     IRQMP      *irqmp = opaque;
     IRQMPState *state;
@@ -311,12 +313,14 @@ grlib_irqmp_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
     trace_grlib_irqmp_writel_unknown(addr, value);
 }
 
-static CPUReadMemoryFunc * const grlib_irqmp_read[] = {
-    NULL, NULL, &grlib_irqmp_readl,
-};
-
-static CPUWriteMemoryFunc * const grlib_irqmp_write[] = {
-    NULL, NULL, &grlib_irqmp_writel,
+static const MemoryRegionOps grlib_irqmp_ops = {
+    .read = grlib_irqmp_read,
+    .write = grlib_irqmp_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static void grlib_irqmp_reset(DeviceState *d)
@@ -332,7 +336,6 @@ static void grlib_irqmp_reset(DeviceState *d)
 static int grlib_irqmp_init(SysBusDevice *dev)
 {
     IRQMP *irqmp = FROM_SYSBUS(typeof(*irqmp), dev);
-    int    irqmp_regs;
 
     assert(irqmp != NULL);
 
@@ -341,17 +344,12 @@ static int grlib_irqmp_init(SysBusDevice *dev)
         return -1;
     }
 
-    irqmp_regs = cpu_register_io_memory(grlib_irqmp_read,
-                                        grlib_irqmp_write,
-                                        irqmp, DEVICE_NATIVE_ENDIAN);
+    memory_region_init_io(&irqmp->iomem, &grlib_irqmp_ops, irqmp,
+                          "irqmp", IRQMP_REG_SIZE);
 
     irqmp->state = g_malloc0(sizeof *irqmp->state);
 
-    if (irqmp_regs < 0) {
-        return -1;
-    }
-
-    sysbus_init_mmio(dev, IRQMP_REG_SIZE, irqmp_regs);
+    sysbus_init_mmio(dev, &irqmp->iomem);
 
     return 0;
 }
diff --git a/hw/hpet.c b/hw/hpet.c
index 6e6ea520bc..5312df7c3a 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -59,6 +59,7 @@ typedef struct HPETTimer {  /* timers */
 
 typedef struct HPETState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint64_t hpet_offset;
     qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
     uint32_t flags;
@@ -354,7 +355,8 @@ static uint32_t hpet_ram_readw(void *opaque, target_phys_addr_t addr)
 }
 #endif
 
-static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t hpet_ram_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     HPETState *s = opaque;
     uint64_t cur_tick, index;
@@ -425,24 +427,8 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
-#ifdef HPET_DEBUG
-static void hpet_ram_writeb(void *opaque, target_phys_addr_t addr,
-                            uint32_t value)
-{
-    printf("qemu: invalid hpet_write b at %" PRIx64 " = %#x\n",
-           addr, value);
-}
-
-static void hpet_ram_writew(void *opaque, target_phys_addr_t addr,
-                            uint32_t value)
-{
-    printf("qemu: invalid hpet_write w at %" PRIx64 " = %#x\n",
-           addr, value);
-}
-#endif
-
-static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
-                            uint32_t value)
+static void hpet_ram_write(void *opaque, target_phys_addr_t addr,
+                           uint64_t value, unsigned size)
 {
     int i;
     HPETState *s = opaque;
@@ -450,7 +436,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
 
     DPRINTF("qemu: Enter hpet_ram_writel at %" PRIx64 " = %#x\n", addr, value);
     index = addr;
-    old_val = hpet_ram_readl(opaque, addr);
+    old_val = hpet_ram_read(opaque, addr, 4);
     new_val = value;
 
     /*address range of all TN regs*/
@@ -605,26 +591,14 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const hpet_ram_read[] = {
-#ifdef HPET_DEBUG
-    hpet_ram_readb,
-    hpet_ram_readw,
-#else
-    NULL,
-    NULL,
-#endif
-    hpet_ram_readl,
-};
-
-static CPUWriteMemoryFunc * const hpet_ram_write[] = {
-#ifdef HPET_DEBUG
-    hpet_ram_writeb,
-    hpet_ram_writew,
-#else
-    NULL,
-    NULL,
-#endif
-    hpet_ram_writel,
+static const MemoryRegionOps hpet_ram_ops = {
+    .read = hpet_ram_read,
+    .write = hpet_ram_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void hpet_reset(DeviceState *d)
@@ -677,7 +651,7 @@ static void hpet_handle_rtc_irq(void *opaque, int n, int level)
 static int hpet_init(SysBusDevice *dev)
 {
     HPETState *s = FROM_SYSBUS(HPETState, dev);
-    int i, iomemtype;
+    int i;
     HPETTimer *timer;
 
     if (hpet_cfg.count == UINT8_MAX) {
@@ -716,10 +690,8 @@ static int hpet_init(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, hpet_handle_rtc_irq, 1);
 
     /* HPET Area */
-    iomemtype = cpu_register_io_memory(hpet_ram_read,
-                                       hpet_ram_write, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x400, iomemtype);
+    memory_region_init_io(&s->iomem, &hpet_ram_ops, s, "hpet", 0x400);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
diff --git a/hw/ide.h b/hw/ide.h
index 9059aae289..f9f6bd8254 100644
--- a/hw/ide.h
+++ b/hw/ide.h
@@ -3,6 +3,7 @@
 
 #include "isa.h"
 #include "pci.h"
+#include "memory.h"
 
 #define MAX_IDE_DEVS	2
 
@@ -24,6 +25,7 @@ MemoryRegion *pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
 
 /* ide-mmio.c */
 void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
+                    MemoryRegion *address_space,
                     qemu_irq irq, int shift,
                     DriveInfo *hd0, DriveInfo *hd1);
 
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
index 2ec21b0163..fcfb09eeab 100644
--- a/hw/ide/mmio.c
+++ b/hw/ide/mmio.c
@@ -37,6 +37,7 @@
 typedef struct {
     IDEBus bus;
     int shift;
+    MemoryRegion iomem1, iomem2;
 } MMIOState;
 
 static void mmio_ide_reset(void *opaque)
@@ -46,7 +47,8 @@ static void mmio_ide_reset(void *opaque)
     ide_bus_reset(&s->bus);
 }
 
-static uint32_t mmio_ide_read (void *opaque, target_phys_addr_t addr)
+static uint64_t mmio_ide_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     MMIOState *s = opaque;
     addr >>= s->shift;
@@ -56,8 +58,8 @@ static uint32_t mmio_ide_read (void *opaque, target_phys_addr_t addr)
         return ide_data_readw(&s->bus, 0);
 }
 
-static void mmio_ide_write (void *opaque, target_phys_addr_t addr,
-	uint32_t val)
+static void mmio_ide_write(void *opaque, target_phys_addr_t addr,
+                           uint64_t val, unsigned size)
 {
     MMIOState *s = opaque;
     addr >>= s->shift;
@@ -67,41 +69,30 @@ static void mmio_ide_write (void *opaque, target_phys_addr_t addr,
         ide_data_writew(&s->bus, 0, val);
 }
 
-static CPUReadMemoryFunc * const mmio_ide_reads[] = {
-    mmio_ide_read,
-    mmio_ide_read,
-    mmio_ide_read,
+static const MemoryRegionOps mmio_ide_ops = {
+    .read = mmio_ide_read,
+    .write = mmio_ide_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const mmio_ide_writes[] = {
-    mmio_ide_write,
-    mmio_ide_write,
-    mmio_ide_write,
-};
-
-static uint32_t mmio_ide_status_read (void *opaque, target_phys_addr_t addr)
+static uint64_t mmio_ide_status_read(void *opaque, target_phys_addr_t addr,
+                                     unsigned size)
 {
     MMIOState *s= opaque;
     return ide_status_read(&s->bus, 0);
 }
 
-static void mmio_ide_cmd_write (void *opaque, target_phys_addr_t addr,
-	uint32_t val)
+static void mmio_ide_cmd_write(void *opaque, target_phys_addr_t addr,
+                               uint64_t val, unsigned size)
 {
     MMIOState *s = opaque;
     ide_cmd_write(&s->bus, 0, val);
 }
 
-static CPUReadMemoryFunc * const mmio_ide_status[] = {
-    mmio_ide_status_read,
-    mmio_ide_status_read,
-    mmio_ide_status_read,
-};
-
-static CPUWriteMemoryFunc * const mmio_ide_cmd[] = {
-    mmio_ide_cmd_write,
-    mmio_ide_cmd_write,
-    mmio_ide_cmd_write,
+static const MemoryRegionOps mmio_ide_cs_ops = {
+    .read = mmio_ide_status_read,
+    .write = mmio_ide_cmd_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_ide_mmio = {
@@ -117,22 +108,22 @@ static const VMStateDescription vmstate_ide_mmio = {
 };
 
 void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
+                    MemoryRegion *address_space,
                     qemu_irq irq, int shift,
                     DriveInfo *hd0, DriveInfo *hd1)
 {
     MMIOState *s = g_malloc0(sizeof(MMIOState));
-    int mem1, mem2;
 
     ide_init2_with_non_qdev_drives(&s->bus, hd0, hd1, irq);
 
     s->shift = shift;
 
-    mem1 = cpu_register_io_memory(mmio_ide_reads, mmio_ide_writes, s,
-                                  DEVICE_NATIVE_ENDIAN);
-    mem2 = cpu_register_io_memory(mmio_ide_status, mmio_ide_cmd, s,
-                                  DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(membase, 16 << shift, mem1);
-    cpu_register_physical_memory(membase2, 2 << shift, mem2);
+    memory_region_init_io(&s->iomem1, &mmio_ide_ops, s,
+                          "ide-mmio.1", 16 << shift);
+    memory_region_init_io(&s->iomem2, &mmio_ide_cs_ops, s,
+                          "ide-mmio.2", 2 << shift);
+    memory_region_add_subregion(address_space, membase, &s->iomem1);
+    memory_region_add_subregion(address_space, membase2, &s->iomem2);
     vmstate_register(NULL, 0, &vmstate_ide_mmio, s);
     qemu_register_reset(mmio_ide_reset, s);
 }
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index 9a289b4776..2551236d5c 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -18,6 +18,7 @@
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t memsz;
     MemoryRegion flash;
     bool flash_mapped;
@@ -39,7 +40,8 @@ static uint8_t integrator_spd[128] = {
    0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
 };
 
-static uint32_t integratorcm_read(void *opaque, target_phys_addr_t offset)
+static uint64_t integratorcm_read(void *opaque, target_phys_addr_t offset,
+                                  unsigned size)
 {
     integratorcm_state *s = (integratorcm_state *)opaque;
     if (offset >= 0x100 && offset < 0x200) {
@@ -152,7 +154,7 @@ static void integratorcm_update(integratorcm_state *s)
 }
 
 static void integratorcm_write(void *opaque, target_phys_addr_t offset,
-                               uint32_t value)
+                               uint64_t value, unsigned size)
 {
     integratorcm_state *s = (integratorcm_state *)opaque;
     switch (offset >> 2) {
@@ -228,21 +230,14 @@ static void integratorcm_write(void *opaque, target_phys_addr_t offset,
 
 /* Integrator/CM control registers.  */
 
-static CPUReadMemoryFunc * const integratorcm_readfn[] = {
-   integratorcm_read,
-   integratorcm_read,
-   integratorcm_read
-};
-
-static CPUWriteMemoryFunc * const integratorcm_writefn[] = {
-   integratorcm_write,
-   integratorcm_write,
-   integratorcm_write
+static const MemoryRegionOps integratorcm_ops = {
+    .read = integratorcm_read,
+    .write = integratorcm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int integratorcm_init(SysBusDevice *dev)
 {
-    int iomemtype;
     integratorcm_state *s = FROM_SYSBUS(integratorcm_state, dev);
 
     s->cm_osc = 0x01000048;
@@ -269,10 +264,10 @@ static int integratorcm_init(SysBusDevice *dev)
     memory_region_init_ram(&s->flash, NULL, "integrator.flash", 0x100000);
     s->flash_mapped = false;
 
-    iomemtype = cpu_register_io_memory(integratorcm_readfn,
-                                       integratorcm_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x00800000, iomemtype);
+    memory_region_init_io(&s->iomem, &integratorcm_ops, s,
+                          "integratorcm", 0x00800000);
+    sysbus_init_mmio(dev, &s->iomem);
+
     integratorcm_do_remap(s, 1);
     /* ??? Save/restore.  */
     return 0;
@@ -284,6 +279,7 @@ static int integratorcm_init(SysBusDevice *dev)
 typedef struct icp_pic_state
 {
   SysBusDevice busdev;
+  MemoryRegion iomem;
   uint32_t level;
   uint32_t irq_enabled;
   uint32_t fiq_enabled;
@@ -311,7 +307,8 @@ static void icp_pic_set_irq(void *opaque, int irq, int level)
     icp_pic_update(s);
 }
 
-static uint32_t icp_pic_read(void *opaque, target_phys_addr_t offset)
+static uint64_t icp_pic_read(void *opaque, target_phys_addr_t offset,
+                             unsigned size)
 {
     icp_pic_state *s = (icp_pic_state *)opaque;
 
@@ -340,7 +337,7 @@ static uint32_t icp_pic_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void icp_pic_write(void *opaque, target_phys_addr_t offset,
-                          uint32_t value)
+                          uint64_t value, unsigned size)
 {
     icp_pic_state *s = (icp_pic_state *)opaque;
 
@@ -376,35 +373,28 @@ static void icp_pic_write(void *opaque, target_phys_addr_t offset,
     icp_pic_update(s);
 }
 
-static CPUReadMemoryFunc * const icp_pic_readfn[] = {
-   icp_pic_read,
-   icp_pic_read,
-   icp_pic_read
-};
-
-static CPUWriteMemoryFunc * const icp_pic_writefn[] = {
-   icp_pic_write,
-   icp_pic_write,
-   icp_pic_write
+static const MemoryRegionOps icp_pic_ops = {
+    .read = icp_pic_read,
+    .write = icp_pic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int icp_pic_init(SysBusDevice *dev)
 {
     icp_pic_state *s = FROM_SYSBUS(icp_pic_state, dev);
-    int iomemtype;
 
     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);
-    iomemtype = cpu_register_io_memory(icp_pic_readfn,
-                                       icp_pic_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x00800000, iomemtype);
+    memory_region_init_io(&s->iomem, &icp_pic_ops, s, "icp-pic", 0x00800000);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
 /* CP control registers.  */
-static uint32_t icp_control_read(void *opaque, target_phys_addr_t offset)
+
+static uint64_t icp_control_read(void *opaque, target_phys_addr_t offset,
+                                 unsigned size)
 {
     switch (offset >> 2) {
     case 0: /* CP_IDFIELD */
@@ -422,7 +412,7 @@ static uint32_t icp_control_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void icp_control_write(void *opaque, target_phys_addr_t offset,
-                          uint32_t value)
+                          uint64_t value, unsigned size)
 {
     switch (offset >> 2) {
     case 1: /* CP_FLASHPROG */
@@ -434,26 +424,21 @@ static void icp_control_write(void *opaque, target_phys_addr_t offset,
         hw_error("icp_control_write: Bad offset %x\n", (int)offset);
     }
 }
-static CPUReadMemoryFunc * const icp_control_readfn[] = {
-   icp_control_read,
-   icp_control_read,
-   icp_control_read
-};
 
-static CPUWriteMemoryFunc * const icp_control_writefn[] = {
-   icp_control_write,
-   icp_control_write,
-   icp_control_write
+static const MemoryRegionOps icp_control_ops = {
+    .read = icp_control_read,
+    .write = icp_control_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void icp_control_init(uint32_t base)
+static void icp_control_init(target_phys_addr_t base)
 {
-    int iomemtype;
+    MemoryRegion *io;
 
-    iomemtype = cpu_register_io_memory(icp_control_readfn,
-                                       icp_control_writefn, NULL,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x00800000, iomemtype);
+    io = (MemoryRegion *)g_malloc0(sizeof(MemoryRegion));
+    memory_region_init_io(io, &icp_control_ops, NULL,
+                          "control", 0x00800000);
+    memory_region_add_subregion(get_system_memory(), base, io);
     /* ??? Save/restore.  */
 }
 
diff --git a/hw/ioapic.c b/hw/ioapic.c
index 61991d7679..27b07c6317 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -86,6 +86,7 @@ typedef struct IOAPICState IOAPICState;
 
 struct IOAPICState {
     SysBusDevice busdev;
+    MemoryRegion io_memory;
     uint8_t id;
     uint8_t ioregsel;
     uint32_t irr;
@@ -195,7 +196,8 @@ void ioapic_eoi_broadcast(int vector)
     }
 }
 
-static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t
+ioapic_mem_read(void *opaque, target_phys_addr_t addr, unsigned int size)
 {
     IOAPICState *s = opaque;
     int index;
@@ -206,6 +208,9 @@ static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
         val = s->ioregsel;
         break;
     case IOAPIC_IOWIN:
+        if (size != 4) {
+            break;
+        }
         switch (s->ioregsel) {
         case IOAPIC_REG_ID:
             val = s->id << IOAPIC_ID_SHIFT;
@@ -234,7 +239,8 @@ static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
 }
 
 static void
-ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+ioapic_mem_write(void *opaque, target_phys_addr_t addr, uint64_t val,
+                 unsigned int size)
 {
     IOAPICState *s = opaque;
     int index;
@@ -244,6 +250,9 @@ ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
         s->ioregsel = val;
         break;
     case IOAPIC_IOWIN:
+        if (size != 4) {
+            break;
+        }
         DPRINTF("write: %08x = %08x\n", s->ioregsel, val);
         switch (s->ioregsel) {
         case IOAPIC_REG_ID:
@@ -309,32 +318,23 @@ static void ioapic_reset(DeviceState *d)
     }
 }
 
-static CPUReadMemoryFunc * const ioapic_mem_read[3] = {
-    ioapic_mem_readl,
-    ioapic_mem_readl,
-    ioapic_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const ioapic_mem_write[3] = {
-    ioapic_mem_writel,
-    ioapic_mem_writel,
-    ioapic_mem_writel,
+static const MemoryRegionOps ioapic_io_ops = {
+    .read = ioapic_mem_read,
+    .write = ioapic_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int ioapic_init1(SysBusDevice *dev)
 {
     IOAPICState *s = FROM_SYSBUS(IOAPICState, dev);
-    int io_memory;
     static int ioapic_no;
 
     if (ioapic_no >= MAX_IOAPICS) {
         return -1;
     }
 
-    io_memory = cpu_register_io_memory(ioapic_mem_read,
-                                       ioapic_mem_write, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, io_memory);
+    memory_region_init_io(&s->io_memory, &ioapic_io_ops, s, "ioapic", 0x1000);
+    sysbus_init_mmio(dev, &s->io_memory);
 
     qdev_init_gpio_in(&dev->qdev, ioapic_set_irq, IOAPIC_NUM_PINS);
 
diff --git a/hw/jazz_led.c b/hw/jazz_led.c
index eb472a04c3..6fab334253 100644
--- a/hw/jazz_led.c
+++ b/hw/jazz_led.c
@@ -43,6 +43,7 @@ typedef enum {
 } screen_state_t;
 
 typedef struct LedState {
+    MemoryRegion iomem;
     uint8_t segments;
     DisplayState *ds;
     screen_state_t state;
@@ -140,16 +141,12 @@ static void led_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
 #endif
 }
 
-static CPUReadMemoryFunc * const led_read[3] = {
-    led_readb,
-    led_readw,
-    led_readl,
-};
-
-static CPUWriteMemoryFunc * const led_write[3] = {
-    led_writeb,
-    led_writew,
-    led_writel,
+static const MemoryRegionOps led_ops = {
+    .old_mmio = {
+        .read = { led_readb, led_readw, led_readl, },
+        .write = { led_writeb, led_writew, led_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 /***********************************************************/
@@ -307,18 +304,16 @@ static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
     dpy_update(s->ds, 0, 0, 2, 1);
 }
 
-void jazz_led_init(target_phys_addr_t base)
+void jazz_led_init(MemoryRegion *address_space, target_phys_addr_t base)
 {
     LedState *s;
-    int io;
 
     s = g_malloc0(sizeof(LedState));
 
     s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND;
 
-    io = cpu_register_io_memory(led_read, led_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 1, io);
+    memory_region_init_io(&s->iomem, &led_ops, s, "led", 1);
+    memory_region_add_subregion(address_space, base, &s->iomem);
 
     s->ds = graphic_console_init(jazz_led_update_display,
                                  jazz_led_invalidate_display,
diff --git a/hw/lan9118.c b/hw/lan9118.c
index f8149e6983..ee8b2eab06 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -1132,7 +1132,7 @@ static int lan9118_init1(SysBusDevice *dev)
     int i;
 
     memory_region_init_io(&s->mmio, &lan9118_mem_ops, s, "lan9118-mmio", 0x100);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
     sysbus_init_irq(dev, &s->irq);
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
 
diff --git a/hw/lance.c b/hw/lance.c
index 93d5fda35b..716470061c 100644
--- a/hw/lance.c
+++ b/hw/lance.c
@@ -121,7 +121,7 @@ static int lance_init(SysBusDevice *dev)
 
     qdev_init_gpio_in(&dev->qdev, parent_lance_reset, 1);
 
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
 
     sysbus_init_irq(dev, &s->irq);
 
diff --git a/hw/lm32_sys.c b/hw/lm32_sys.c
index e5ff962f43..83974ee4fb 100644
--- a/hw/lm32_sys.c
+++ b/hw/lm32_sys.c
@@ -47,6 +47,7 @@ enum {
 
 struct LM32SysState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t base;
     uint32_t regs[R_MAX];
     uint8_t testname[MAX_TESTNAME_LEN];
@@ -60,7 +61,8 @@ static void copy_testname(LM32SysState *s)
     s->testname[MAX_TESTNAME_LEN - 1] = '\0';
 }
 
-static void sys_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void sys_write(void *opaque, target_phys_addr_t addr,
+                      uint64_t value, unsigned size)
 {
     LM32SysState *s = opaque;
     char *testname;
@@ -89,16 +91,16 @@ static void sys_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     }
 }
 
-static CPUReadMemoryFunc * const sys_read_fn[] = {
-    NULL,
-    NULL,
-    NULL,
-};
+static bool sys_ops_accepts(void *opaque, target_phys_addr_t addr,
+                            unsigned size, bool is_write)
+{
+    return is_write && size == 4;
+}
 
-static CPUWriteMemoryFunc * const sys_write_fn[] = {
-    NULL,
-    NULL,
-    &sys_write,
+static const MemoryRegionOps sys_ops = {
+    .write = sys_write,
+    .valid.accepts = sys_ops_accepts,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void sys_reset(DeviceState *d)
@@ -115,11 +117,9 @@ static void sys_reset(DeviceState *d)
 static int lm32_sys_init(SysBusDevice *dev)
 {
     LM32SysState *s = FROM_SYSBUS(typeof(*s), dev);
-    int sys_regs;
 
-    sys_regs = cpu_register_io_memory(sys_read_fn, sys_write_fn, s,
-            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, sys_regs);
+    memory_region_init_io(&s->iomem, &sys_ops , s, "sys", R_MAX * 4);
+    sysbus_init_mmio(dev, &s->iomem);
 
     /* Note: This device is not created in the board initialization,
      * instead it has to be added with the -device parameter. Therefore,
diff --git a/hw/lm32_timer.c b/hw/lm32_timer.c
index 49cbb22993..445847f1ce 100644
--- a/hw/lm32_timer.c
+++ b/hw/lm32_timer.c
@@ -51,6 +51,7 @@ enum {
 
 struct LM32TimerState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
 
     QEMUBH *bh;
     ptimer_state *ptimer;
@@ -70,7 +71,7 @@ static void timer_update_irq(LM32TimerState *s)
     qemu_set_irq(s->irq, state);
 }
 
-static uint32_t timer_read(void *opaque, target_phys_addr_t addr)
+static uint64_t timer_read(void *opaque, target_phys_addr_t addr, unsigned size)
 {
     LM32TimerState *s = opaque;
     uint32_t r = 0;
@@ -95,7 +96,8 @@ static uint32_t timer_read(void *opaque, target_phys_addr_t addr)
     return r;
 }
 
-static void timer_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void timer_write(void *opaque, target_phys_addr_t addr,
+                        uint64_t value, unsigned size)
 {
     LM32TimerState *s = opaque;
 
@@ -131,16 +133,14 @@ static void timer_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     timer_update_irq(s);
 }
 
-static CPUReadMemoryFunc * const timer_read_fn[] = {
-    NULL,
-    NULL,
-    &timer_read,
-};
-
-static CPUWriteMemoryFunc * const timer_write_fn[] = {
-    NULL,
-    NULL,
-    &timer_write,
+static const MemoryRegionOps timer_ops = {
+    .read = timer_read,
+    .write = timer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static void timer_hit(void *opaque)
@@ -172,7 +172,6 @@ static void timer_reset(DeviceState *d)
 static int lm32_timer_init(SysBusDevice *dev)
 {
     LM32TimerState *s = FROM_SYSBUS(typeof(*s), dev);
-    int timer_regs;
 
     sysbus_init_irq(dev, &s->irq);
 
@@ -180,9 +179,8 @@ static int lm32_timer_init(SysBusDevice *dev)
     s->ptimer = ptimer_init(s->bh);
     ptimer_set_freq(s->ptimer, s->freq_hz);
 
-    timer_regs = cpu_register_io_memory(timer_read_fn, timer_write_fn, s,
-            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, timer_regs);
+    memory_region_init_io(&s->iomem, &timer_ops, s, "timer", R_MAX * 4);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c
index 367854550c..d013abd1c6 100644
--- a/hw/lm32_uart.c
+++ b/hw/lm32_uart.c
@@ -91,6 +91,7 @@ enum {
 
 struct LM32UartState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     CharDriverState *chr;
     qemu_irq irq;
 
@@ -124,7 +125,8 @@ static void uart_update_irq(LM32UartState *s)
     qemu_set_irq(s->irq, irq);
 }
 
-static uint32_t uart_read(void *opaque, target_phys_addr_t addr)
+static uint64_t uart_read(void *opaque, target_phys_addr_t addr,
+                          unsigned size)
 {
     LM32UartState *s = opaque;
     uint32_t r = 0;
@@ -158,7 +160,8 @@ static uint32_t uart_read(void *opaque, target_phys_addr_t addr)
     return r;
 }
 
-static void uart_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void uart_write(void *opaque, target_phys_addr_t addr,
+                       uint64_t value, unsigned size)
 {
     LM32UartState *s = opaque;
     unsigned char ch = value;
@@ -192,16 +195,14 @@ static void uart_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     uart_update_irq(s);
 }
 
-static CPUReadMemoryFunc * const uart_read_fn[] = {
-    NULL,
-    NULL,
-    &uart_read,
-};
-
-static CPUWriteMemoryFunc * const uart_write_fn[] = {
-    NULL,
-    NULL,
-    &uart_write,
+static const MemoryRegionOps uart_ops = {
+    .read = uart_read,
+    .write = uart_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static void uart_rx(void *opaque, const uint8_t *buf, int size)
@@ -245,13 +246,11 @@ static void uart_reset(DeviceState *d)
 static int lm32_uart_init(SysBusDevice *dev)
 {
     LM32UartState *s = FROM_SYSBUS(typeof(*s), dev);
-    int uart_regs;
 
     sysbus_init_irq(dev, &s->irq);
 
-    uart_regs = cpu_register_io_memory(uart_read_fn, uart_write_fn, s,
-            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, uart_regs);
+    memory_region_init_io(&s->iomem, &uart_ops, s, "uart", R_MAX * 4);
+    sysbus_init_mmio(dev, &s->iomem);
 
     s->chr = qdev_init_chardev(&dev->qdev);
     if (s->chr) {
diff --git a/hw/m48t59.c b/hw/m48t59.c
index a77937ef68..8d8d495d7a 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -52,6 +52,7 @@
 struct M48t59State {
     /* Hardware parameters */
     qemu_irq IRQ;
+    MemoryRegion iomem;
     uint32_t io_base;
     uint32_t size;
     /* RTC management */
@@ -573,16 +574,12 @@ static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
     return retval;
 }
 
-static CPUWriteMemoryFunc * const nvram_write[] = {
-    &nvram_writeb,
-    &nvram_writew,
-    &nvram_writel,
-};
-
-static CPUReadMemoryFunc * const nvram_read[] = {
-    &nvram_readb,
-    &nvram_readw,
-    &nvram_readl,
+static const MemoryRegionOps nvram_ops = {
+    .old_mmio = {
+        .read = { nvram_readb, nvram_readw, nvram_readl, },
+        .write = { nvram_writeb, nvram_writew, nvram_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_m48t59 = {
@@ -712,13 +709,11 @@ static int m48t59_init1(SysBusDevice *dev)
 {
     M48t59SysBusState *d = FROM_SYSBUS(M48t59SysBusState, dev);
     M48t59State *s = &d->state;
-    int mem_index;
 
     sysbus_init_irq(dev, &s->IRQ);
 
-    mem_index = cpu_register_io_memory(nvram_read, nvram_write, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, s->size, mem_index);
+    memory_region_init_io(&s->iomem, &nvram_ops, s, "m48t59.nvram", s->size);
+    sysbus_init_mmio(dev, &s->iomem);
     m48t59_init_common(s);
 
     return 0;
diff --git a/hw/marvell_88w8618_audio.c b/hw/marvell_88w8618_audio.c
index f8c5242867..855b792b9d 100644
--- a/hw/marvell_88w8618_audio.c
+++ b/hw/marvell_88w8618_audio.c
@@ -36,6 +36,7 @@
 
 typedef struct mv88w8618_audio_state {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     qemu_irq irq;
     uint32_t playback_mode;
     uint32_t status;
@@ -134,7 +135,8 @@ static void mv88w8618_audio_clock_update(mv88w8618_audio_state *s)
     wm8750_set_bclk_in(s->wm, rate);
 }
 
-static uint32_t mv88w8618_audio_read(void *opaque, target_phys_addr_t offset)
+static uint64_t mv88w8618_audio_read(void *opaque, target_phys_addr_t offset,
+                                    unsigned size)
 {
     mv88w8618_audio_state *s = opaque;
 
@@ -160,7 +162,7 @@ static uint32_t mv88w8618_audio_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void mv88w8618_audio_write(void *opaque, target_phys_addr_t offset,
-                                 uint32_t value)
+                                  uint64_t value, unsigned size)
 {
     mv88w8618_audio_state *s = opaque;
 
@@ -227,31 +229,23 @@ static void mv88w8618_audio_reset(DeviceState *d)
     s->phys_buf = 0;
 }
 
-static CPUReadMemoryFunc * const mv88w8618_audio_readfn[] = {
-    mv88w8618_audio_read,
-    mv88w8618_audio_read,
-    mv88w8618_audio_read
-};
-
-static CPUWriteMemoryFunc * const mv88w8618_audio_writefn[] = {
-    mv88w8618_audio_write,
-    mv88w8618_audio_write,
-    mv88w8618_audio_write
+static const MemoryRegionOps mv88w8618_audio_ops = {
+    .read = mv88w8618_audio_read,
+    .write = mv88w8618_audio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int mv88w8618_audio_init(SysBusDevice *dev)
 {
     mv88w8618_audio_state *s = FROM_SYSBUS(mv88w8618_audio_state, dev);
-    int iomemtype;
 
     sysbus_init_irq(dev, &s->irq);
 
     wm8750_data_req_set(s->wm, mv88w8618_audio_callback, s);
 
-    iomemtype = cpu_register_io_memory(mv88w8618_audio_readfn,
-                                       mv88w8618_audio_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, MP_AUDIO_SIZE, iomemtype);
+    memory_region_init_io(&s->iomem, &mv88w8618_audio_ops, s,
+                          "audio", MP_AUDIO_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
diff --git a/hw/mcf.h b/hw/mcf.h
index 91f2821f1f..baa790b0c5 100644
--- a/hw/mcf.h
+++ b/hw/mcf.h
@@ -2,20 +2,29 @@
 #define HW_MCF_H
 /* Motorola ColdFire device prototypes.  */
 
+struct MemoryRegion;
+
 /* mcf_uart.c */
-uint32_t mcf_uart_read(void *opaque, target_phys_addr_t addr);
-void mcf_uart_write(void *opaque, target_phys_addr_t addr, uint32_t val);
+uint64_t mcf_uart_read(void *opaque, target_phys_addr_t addr,
+                       unsigned size);
+void mcf_uart_write(void *opaque, target_phys_addr_t addr,
+                    uint64_t val, unsigned size);
 void *mcf_uart_init(qemu_irq irq, CharDriverState *chr);
-void mcf_uart_mm_init(target_phys_addr_t base, qemu_irq irq,
-                      CharDriverState *chr);
+void mcf_uart_mm_init(struct MemoryRegion *sysmem,
+                      target_phys_addr_t base,
+                      qemu_irq irq, CharDriverState *chr);
 
 /* mcf_intc.c */
-qemu_irq *mcf_intc_init(target_phys_addr_t base, CPUState *env);
+qemu_irq *mcf_intc_init(struct MemoryRegion *sysmem,
+                        target_phys_addr_t base,
+                        CPUState *env);
 
 /* mcf_fec.c */
-void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq);
+void mcf_fec_init(struct MemoryRegion *sysmem, NICInfo *nd,
+                  target_phys_addr_t base, qemu_irq *irq);
 
 /* mcf5206.c */
-qemu_irq *mcf5206_init(uint32_t base, CPUState *env);
+qemu_irq *mcf5206_init(struct MemoryRegion *sysmem,
+                       uint32_t base, CPUState *env);
 
 #endif
diff --git a/hw/mcf5206.c b/hw/mcf5206.c
index 15d6f22f13..7b6d501447 100644
--- a/hw/mcf5206.c
+++ b/hw/mcf5206.c
@@ -9,6 +9,7 @@
 #include "mcf.h"
 #include "qemu-timer.h"
 #include "sysemu.h"
+#include "exec-memory.h"
 
 /* General purpose timer module.  */
 typedef struct {
@@ -144,6 +145,7 @@ static m5206_timer_state *m5206_timer_init(qemu_irq irq)
 
 typedef struct {
     CPUState *env;
+    MemoryRegion iomem;
     m5206_timer_state *timer[2];
     void *uart[2];
     uint8_t scr;
@@ -261,16 +263,17 @@ static void m5206_mbar_reset(m5206_mbar_state *s)
     s->par = 0;
 }
 
-static uint32_t m5206_mbar_read(m5206_mbar_state *s, uint32_t offset)
+static uint64_t m5206_mbar_read(m5206_mbar_state *s,
+                                uint64_t offset, unsigned size)
 {
     if (offset >= 0x100 && offset < 0x120) {
         return m5206_timer_read(s->timer[0], offset - 0x100);
     } else if (offset >= 0x120 && offset < 0x140) {
         return m5206_timer_read(s->timer[1], offset - 0x120);
     } else if (offset >= 0x140 && offset < 0x160) {
-        return mcf_uart_read(s->uart[0], offset - 0x140);
+        return mcf_uart_read(s->uart[0], offset - 0x140, size);
     } else if (offset >= 0x180 && offset < 0x1a0) {
-        return mcf_uart_read(s->uart[1], offset - 0x180);
+        return mcf_uart_read(s->uart[1], offset - 0x180, size);
     }
     switch (offset) {
     case 0x03: return s->scr;
@@ -299,7 +302,7 @@ static uint32_t m5206_mbar_read(m5206_mbar_state *s, uint32_t offset)
 }
 
 static void m5206_mbar_write(m5206_mbar_state *s, uint32_t offset,
-                             uint32_t value)
+                             uint64_t value, unsigned size)
 {
     if (offset >= 0x100 && offset < 0x120) {
         m5206_timer_write(s->timer[0], offset - 0x100, value);
@@ -308,10 +311,10 @@ static void m5206_mbar_write(m5206_mbar_state *s, uint32_t offset,
         m5206_timer_write(s->timer[1], offset - 0x120, value);
         return;
     } else if (offset >= 0x140 && offset < 0x160) {
-        mcf_uart_write(s->uart[0], offset - 0x140, value);
+        mcf_uart_write(s->uart[0], offset - 0x140, value, size);
         return;
     } else if (offset >= 0x180 && offset < 0x1a0) {
-        mcf_uart_write(s->uart[1], offset - 0x180, value);
+        mcf_uart_write(s->uart[1], offset - 0x180, value, size);
         return;
     }
     switch (offset) {
@@ -385,7 +388,7 @@ static uint32_t m5206_mbar_readb(void *opaque, target_phys_addr_t offset)
         }
         return val & 0xff;
     }
-    return m5206_mbar_read(s, offset);
+    return m5206_mbar_read(s, offset, 1);
 }
 
 static uint32_t m5206_mbar_readw(void *opaque, target_phys_addr_t offset)
@@ -409,7 +412,7 @@ static uint32_t m5206_mbar_readw(void *opaque, target_phys_addr_t offset)
         val |= m5206_mbar_readb(opaque, offset + 1);
         return val;
     }
-    return m5206_mbar_read(s, offset);
+    return m5206_mbar_read(s, offset, 2);
 }
 
 static uint32_t m5206_mbar_readl(void *opaque, target_phys_addr_t offset)
@@ -427,7 +430,7 @@ static uint32_t m5206_mbar_readl(void *opaque, target_phys_addr_t offset)
         val |= m5206_mbar_readw(opaque, offset + 2);
         return val;
     }
-    return m5206_mbar_read(s, offset);
+    return m5206_mbar_read(s, offset, 4);
 }
 
 static void m5206_mbar_writew(void *opaque, target_phys_addr_t offset,
@@ -456,7 +459,7 @@ static void m5206_mbar_writeb(void *opaque, target_phys_addr_t offset,
         m5206_mbar_writew(opaque, offset & ~1, tmp);
         return;
     }
-    m5206_mbar_write(s, offset, value);
+    m5206_mbar_write(s, offset, value, 1);
 }
 
 static void m5206_mbar_writew(void *opaque, target_phys_addr_t offset,
@@ -484,7 +487,7 @@ static void m5206_mbar_writew(void *opaque, target_phys_addr_t offset,
         m5206_mbar_writeb(opaque, offset + 1, value & 0xff);
         return;
     }
-    m5206_mbar_write(s, offset, value);
+    m5206_mbar_write(s, offset, value, 2);
 }
 
 static void m5206_mbar_writel(void *opaque, target_phys_addr_t offset,
@@ -502,32 +505,35 @@ static void m5206_mbar_writel(void *opaque, target_phys_addr_t offset,
         m5206_mbar_writew(opaque, offset + 2, value & 0xffff);
         return;
     }
-    m5206_mbar_write(s, offset, value);
+    m5206_mbar_write(s, offset, value, 4);
 }
 
-static CPUReadMemoryFunc * const m5206_mbar_readfn[] = {
-   m5206_mbar_readb,
-   m5206_mbar_readw,
-   m5206_mbar_readl
+static const MemoryRegionOps m5206_mbar_ops = {
+    .old_mmio = {
+        .read = {
+            m5206_mbar_readb,
+            m5206_mbar_readw,
+            m5206_mbar_readl,
+        },
+        .write = {
+            m5206_mbar_writeb,
+            m5206_mbar_writew,
+            m5206_mbar_writel,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const m5206_mbar_writefn[] = {
-   m5206_mbar_writeb,
-   m5206_mbar_writew,
-   m5206_mbar_writel
-};
-
-qemu_irq *mcf5206_init(uint32_t base, CPUState *env)
+qemu_irq *mcf5206_init(MemoryRegion *sysmem, uint32_t base, CPUState *env)
 {
     m5206_mbar_state *s;
     qemu_irq *pic;
-    int iomemtype;
 
     s = (m5206_mbar_state *)g_malloc0(sizeof(m5206_mbar_state));
-    iomemtype = cpu_register_io_memory(m5206_mbar_readfn,
-                                       m5206_mbar_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x00001000, iomemtype);
+
+    memory_region_init_io(&s->iomem, &m5206_mbar_ops, s,
+                          "mbar", 0x00001000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     pic = qemu_allocate_irqs(m5206_mbar_set_irq, s, 14);
     s->timer[0] = m5206_timer_init(pic[9]);
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index 1c2c0c48aa..ec608a1a38 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -221,11 +221,11 @@ static void mcf5208evb_init(ram_addr_t ram_size,
     memory_region_add_subregion(address_space_mem, 0x80000000, sram);
 
     /* Internal peripherals.  */
-    pic = mcf_intc_init(0xfc048000, env);
+    pic = mcf_intc_init(address_space_mem, 0xfc048000, env);
 
-    mcf_uart_mm_init(0xfc060000, pic[26], serial_hds[0]);
-    mcf_uart_mm_init(0xfc064000, pic[27], serial_hds[1]);
-    mcf_uart_mm_init(0xfc068000, pic[28], serial_hds[2]);
+    mcf_uart_mm_init(address_space_mem, 0xfc060000, pic[26], serial_hds[0]);
+    mcf_uart_mm_init(address_space_mem, 0xfc064000, pic[27], serial_hds[1]);
+    mcf_uart_mm_init(address_space_mem, 0xfc068000, pic[28], serial_hds[2]);
 
     mcf5208_sys_init(address_space_mem, pic);
 
@@ -234,7 +234,8 @@ static void mcf5208evb_init(ram_addr_t ram_size,
         exit(1);
     }
     if (nd_table[0].vlan)
-        mcf_fec_init(&nd_table[0], 0xfc030000, pic + 36);
+        mcf_fec_init(address_space_mem, &nd_table[0],
+                     0xfc030000, pic + 36);
 
     /*  0xfc000000 SCM.  */
     /*  0xfc004000 XBS.  */
diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c
index 42a5d77952..ae37bef0f0 100644
--- a/hw/mcf_fec.c
+++ b/hw/mcf_fec.c
@@ -10,6 +10,7 @@
 #include "mcf.h"
 /* For crc32 */
 #include <zlib.h>
+#include "exec-memory.h"
 
 //#define DEBUG_FEC 1
 
@@ -23,8 +24,9 @@ do { printf("mcf_fec: " fmt , ## __VA_ARGS__); } while (0)
 #define FEC_MAX_FRAME_SIZE 2032
 
 typedef struct {
+    MemoryRegion *sysmem;
+    MemoryRegion iomem;
     qemu_irq *irq;
-    int mmio_index;
     NICState *nic;
     NICConf conf;
     uint32_t irq_state;
@@ -214,7 +216,8 @@ static void mcf_fec_reset(mcf_fec_state *s)
     s->rfsr = 0x500;
 }
 
-static uint32_t mcf_fec_read(void *opaque, target_phys_addr_t addr)
+static uint64_t mcf_fec_read(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
 {
     mcf_fec_state *s = (mcf_fec_state *)opaque;
     switch (addr & 0x3ff) {
@@ -251,7 +254,8 @@ static uint32_t mcf_fec_read(void *opaque, target_phys_addr_t addr)
     }
 }
 
-static void mcf_fec_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void mcf_fec_write(void *opaque, target_phys_addr_t addr,
+                          uint64_t value, unsigned size)
 {
     mcf_fec_state *s = (mcf_fec_state *)opaque;
     switch (addr & 0x3ff) {
@@ -429,23 +433,18 @@ static ssize_t mcf_fec_receive(VLANClientState *nc, const uint8_t *buf, size_t s
     return size;
 }
 
-static CPUReadMemoryFunc * const mcf_fec_readfn[] = {
-   mcf_fec_read,
-   mcf_fec_read,
-   mcf_fec_read
-};
-
-static CPUWriteMemoryFunc * const mcf_fec_writefn[] = {
-   mcf_fec_write,
-   mcf_fec_write,
-   mcf_fec_write
+static const MemoryRegionOps mcf_fec_ops = {
+    .read = mcf_fec_read,
+    .write = mcf_fec_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void mcf_fec_cleanup(VLANClientState *nc)
 {
     mcf_fec_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
-    cpu_unregister_io_memory(s->mmio_index);
+    memory_region_del_subregion(s->sysmem, &s->iomem);
+    memory_region_destroy(&s->iomem);
 
     g_free(s);
 }
@@ -458,18 +457,19 @@ static NetClientInfo net_mcf_fec_info = {
     .cleanup = mcf_fec_cleanup,
 };
 
-void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq)
+void mcf_fec_init(MemoryRegion *sysmem, NICInfo *nd,
+                  target_phys_addr_t base, qemu_irq *irq)
 {
     mcf_fec_state *s;
 
     qemu_check_nic_model(nd, "mcf_fec");
 
     s = (mcf_fec_state *)g_malloc0(sizeof(mcf_fec_state));
+    s->sysmem = sysmem;
     s->irq = irq;
-    s->mmio_index = cpu_register_io_memory(mcf_fec_readfn,
-                                           mcf_fec_writefn, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x400, s->mmio_index);
+
+    memory_region_init_io(&s->iomem, &mcf_fec_ops, s, "fec", 0x400);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     s->conf.macaddr = nd->macaddr;
     s->conf.vlan = nd->vlan;
diff --git a/hw/mcf_intc.c b/hw/mcf_intc.c
index 99092e72d1..0b498dd3ac 100644
--- a/hw/mcf_intc.c
+++ b/hw/mcf_intc.c
@@ -7,8 +7,10 @@
  */
 #include "hw.h"
 #include "mcf.h"
+#include "exec-memory.h"
 
 typedef struct {
+    MemoryRegion iomem;
     uint64_t ipr;
     uint64_t imr;
     uint64_t ifr;
@@ -41,7 +43,8 @@ static void mcf_intc_update(mcf_intc_state *s)
     m68k_set_irq_level(s->env, best_level, s->active_vector);
 }
 
-static uint32_t mcf_intc_read(void *opaque, target_phys_addr_t addr)
+static uint64_t mcf_intc_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     int offset;
     mcf_intc_state *s = (mcf_intc_state *)opaque;
@@ -73,7 +76,8 @@ static uint32_t mcf_intc_read(void *opaque, target_phys_addr_t addr)
     }
 }
 
-static void mcf_intc_write(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void mcf_intc_write(void *opaque, target_phys_addr_t addr,
+                           uint64_t val, unsigned size)
 {
     int offset;
     mcf_intc_state *s = (mcf_intc_state *)opaque;
@@ -127,31 +131,24 @@ static void mcf_intc_reset(mcf_intc_state *s)
     s->active_vector = 24;
 }
 
-static CPUReadMemoryFunc * const mcf_intc_readfn[] = {
-   mcf_intc_read,
-   mcf_intc_read,
-   mcf_intc_read
+static const MemoryRegionOps mcf_intc_ops = {
+    .read = mcf_intc_read,
+    .write = mcf_intc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const mcf_intc_writefn[] = {
-   mcf_intc_write,
-   mcf_intc_write,
-   mcf_intc_write
-};
-
-qemu_irq *mcf_intc_init(target_phys_addr_t base, CPUState *env)
+qemu_irq *mcf_intc_init(MemoryRegion *sysmem,
+                        target_phys_addr_t base,
+                        CPUState *env)
 {
     mcf_intc_state *s;
-    int iomemtype;
 
     s = g_malloc0(sizeof(mcf_intc_state));
     s->env = env;
     mcf_intc_reset(s);
 
-    iomemtype = cpu_register_io_memory(mcf_intc_readfn,
-                                       mcf_intc_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x100, iomemtype);
+    memory_region_init_io(&s->iomem, &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/mcf_uart.c b/hw/mcf_uart.c
index e6b2ab067a..ec6a87f238 100644
--- a/hw/mcf_uart.c
+++ b/hw/mcf_uart.c
@@ -8,8 +8,10 @@
 #include "hw.h"
 #include "mcf.h"
 #include "qemu-char.h"
+#include "exec-memory.h"
 
 typedef struct {
+    MemoryRegion iomem;
     uint8_t mr[2];
     uint8_t sr;
     uint8_t isr;
@@ -64,7 +66,8 @@ static void mcf_uart_update(mcf_uart_state *s)
     qemu_set_irq(s->irq, (s->isr & s->imr) != 0);
 }
 
-uint32_t mcf_uart_read(void *opaque, target_phys_addr_t addr)
+uint64_t mcf_uart_read(void *opaque, target_phys_addr_t addr,
+                       unsigned size)
 {
     mcf_uart_state *s = (mcf_uart_state *)opaque;
     switch (addr & 0x3f) {
@@ -182,7 +185,8 @@ static void mcf_do_command(mcf_uart_state *s, uint8_t cmd)
     }
 }
 
-void mcf_uart_write(void *opaque, target_phys_addr_t addr, uint32_t val)
+void mcf_uart_write(void *opaque, target_phys_addr_t addr,
+                    uint64_t val, unsigned size)
 {
     mcf_uart_state *s = (mcf_uart_state *)opaque;
     switch (addr & 0x3f) {
@@ -283,28 +287,20 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
     return s;
 }
 
-
-static CPUReadMemoryFunc * const mcf_uart_readfn[] = {
-   mcf_uart_read,
-   mcf_uart_read,
-   mcf_uart_read
-};
-
-static CPUWriteMemoryFunc * const mcf_uart_writefn[] = {
-   mcf_uart_write,
-   mcf_uart_write,
-   mcf_uart_write
+static const MemoryRegionOps mcf_uart_ops = {
+    .read = mcf_uart_read,
+    .write = mcf_uart_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-void mcf_uart_mm_init(target_phys_addr_t base, qemu_irq irq,
+void mcf_uart_mm_init(MemoryRegion *sysmem,
+                      target_phys_addr_t base,
+                      qemu_irq irq,
                       CharDriverState *chr)
 {
     mcf_uart_state *s;
-    int iomemtype;
 
     s = mcf_uart_init(irq, chr);
-    iomemtype = cpu_register_io_memory(mcf_uart_readfn,
-                                       mcf_uart_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x40, iomemtype);
+    memory_region_init_io(&s->iomem, &mcf_uart_ops, s, "uart", 0x40);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 }
diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c
index 5c5ed275b3..e824a49e9a 100644
--- a/hw/milkymist-ac97.c
+++ b/hw/milkymist-ac97.c
@@ -302,7 +302,7 @@ static int milkymist_ac97_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &ac97_mmio_ops, s,
             "milkymist-ac97", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     return 0;
 }
diff --git a/hw/milkymist-hpdmc.c b/hw/milkymist-hpdmc.c
index 17c840ff08..be575c98a0 100644
--- a/hw/milkymist-hpdmc.c
+++ b/hw/milkymist-hpdmc.c
@@ -129,7 +129,7 @@ static int milkymist_hpdmc_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &hpdmc_mmio_ops, s,
             "milkymist-hpdmc", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     return 0;
 }
diff --git a/hw/milkymist-memcard.c b/hw/milkymist-memcard.c
index fb6e558755..865a46c127 100644
--- a/hw/milkymist-memcard.c
+++ b/hw/milkymist-memcard.c
@@ -255,7 +255,7 @@ static int milkymist_memcard_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &memcard_mmio_ops, s,
             "milkymist-memcard", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     return 0;
 }
diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c
index 85d9400c67..b5e0dac116 100644
--- a/hw/milkymist-minimac2.c
+++ b/hw/milkymist-minimac2.c
@@ -465,7 +465,7 @@ static int milkymist_minimac2_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &minimac2_ops, s,
                           "milkymist-minimac2", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     /* register buffers memory */
     memory_region_init_ram(&s->buffers, NULL, "milkymist-minimac2.buffers",
diff --git a/hw/milkymist-pfpu.c b/hw/milkymist-pfpu.c
index 672f6e43eb..dc92eb68e3 100644
--- a/hw/milkymist-pfpu.c
+++ b/hw/milkymist-pfpu.c
@@ -499,7 +499,7 @@ static int milkymist_pfpu_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &pfpu_mmio_ops, s,
             "milkymist-pfpu", MICROCODE_END * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     return 0;
 }
diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c
index ec5f3343d4..6dd953ce9f 100644
--- a/hw/milkymist-softusb.c
+++ b/hw/milkymist-softusb.c
@@ -264,7 +264,7 @@ static int milkymist_softusb_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &softusb_mmio_ops, s,
                           "milkymist-softusb", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     /* register pmem and dmem */
     memory_region_init_ram(&s->pmem, NULL, "milkymist-softusb.pmem",
diff --git a/hw/milkymist-sysctl.c b/hw/milkymist-sysctl.c
index 5783f083b1..6326b70abb 100644
--- a/hw/milkymist-sysctl.c
+++ b/hw/milkymist-sysctl.c
@@ -273,7 +273,7 @@ static int milkymist_sysctl_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &sysctl_mmio_ops, s,
             "milkymist-sysctl", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     return 0;
 }
diff --git a/hw/milkymist-tmu2.c b/hw/milkymist-tmu2.c
index aad0ed06d4..20110e5a83 100644
--- a/hw/milkymist-tmu2.c
+++ b/hw/milkymist-tmu2.c
@@ -449,7 +449,7 @@ static int milkymist_tmu2_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &tmu2_mmio_ops, s,
             "milkymist-tmu2", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     return 0;
 }
diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c
index 5404ca998c..eaf1c0dce1 100644
--- a/hw/milkymist-uart.c
+++ b/hw/milkymist-uart.c
@@ -197,7 +197,7 @@ static int milkymist_uart_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &uart_mmio_ops, s,
             "milkymist-uart", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     s->chr = qdev_init_chardev(&dev->qdev);
     if (s->chr) {
diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c
index be81abdb08..01cd309ca3 100644
--- a/hw/milkymist-vgafb.c
+++ b/hw/milkymist-vgafb.c
@@ -272,7 +272,7 @@ static int milkymist_vgafb_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->regs_region, &vgafb_mmio_ops, s,
             "milkymist-vgafb", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->regs_region);
+    sysbus_init_mmio(dev, &s->regs_region);
 
     s->ds = graphic_console_init(vgafb_update_display,
                                  vgafb_invalidate_display,
diff --git a/hw/mips.h b/hw/mips.h
index 6fa9a3ae75..22156fce53 100644
--- a/hw/mips.h
+++ b/hw/mips.h
@@ -2,6 +2,8 @@
 #define HW_MIPS_H
 /* Definitions for mips board emulation.  */
 
+#include "memory.h"
+
 /* gt64xxx.c */
 PCIBus *gt64120_register(qemu_irq *pic);
 
@@ -9,7 +11,7 @@ PCIBus *gt64120_register(qemu_irq *pic);
 PCIBus *bonito_init(qemu_irq *pic);
 
 /* jazz_led.c */
-void jazz_led_init(target_phys_addr_t base);
+void jazz_led_init(MemoryRegion *address_space, target_phys_addr_t base);
 
 /* rc4030.c */
 typedef struct rc4030DMAState *rc4030_dma;
@@ -18,10 +20,12 @@ void rc4030_dma_read(void *dma, uint8_t *buf, int len);
 void rc4030_dma_write(void *dma, uint8_t *buf, int len);
 
 void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
-                  qemu_irq **irqs, rc4030_dma **dmas);
+                  qemu_irq **irqs, rc4030_dma **dmas,
+                  MemoryRegion *sysmem);
 
 /* dp8393x.c */
 void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift,
+                  MemoryRegion *address_space,
                   qemu_irq irq, void* mem_opaque,
                   void (*memory_rw)(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write));
 
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 14beea2d64..358de599b0 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -177,7 +177,8 @@ static void mips_jazz_init(MemoryRegion *address_space,
     cpu_mips_clock_init(env);
 
     /* Chipset */
-    rc4030_opaque = rc4030_init(env->irq[6], env->irq[3], &rc4030, &dmas);
+    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_add_subregion(address_space, 0x8000d000, dma_dummy);
 
@@ -226,7 +227,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
         if (!nd->model)
             nd->model = g_strdup("dp83932");
         if (strcmp(nd->model, "dp83932") == 0) {
-            dp83932_init(nd, 0x80001000, 2, rc4030[4],
+            dp83932_init(nd, 0x80001000, 2, get_system_memory(), rc4030[4],
                          rc4030_opaque, rc4030_dma_memory_rw);
             break;
         } else if (strcmp(nd->model, "?") == 0) {
@@ -274,7 +275,8 @@ static void mips_jazz_init(MemoryRegion *address_space,
 
     /* Parallel port */
     if (parallel_hds[0])
-        parallel_mm_init(0x80008000, 0, rc4030[0], parallel_hds[0]);
+        parallel_mm_init(address_space, 0x80008000, 0, rc4030[0],
+                         parallel_hds[0]);
 
     /* Sound card */
     /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */
@@ -287,7 +289,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
     sysbus_mmio_map(sysbus, 0, 0x80009000);
 
     /* LED indicator */
-    jazz_led_init(0x8000f000);
+    jazz_led_init(address_space, 0x8000f000);
 }
 
 static
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index 605367bc5f..b1234b8282 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -236,7 +236,7 @@ static int mipsnet_sysbus_init(SysBusDevice *dev)
     MIPSnetState *s = DO_UPCAST(MIPSnetState, busdev, dev);
 
     memory_region_init_io(&s->io, &mipsnet_ioport_ops, s, "mipsnet-io", 36);
-    sysbus_init_mmio_region(dev, &s->io);
+    sysbus_init_mmio(dev, &s->io);
     sysbus_init_irq(dev, &s->irq);
 
     s->nic = qemu_new_nic(&net_mipsnet_info, &s->conf,
diff --git a/hw/mpc8544_guts.c b/hw/mpc8544_guts.c
index c685f3e08c..f01b38cfc2 100644
--- a/hw/mpc8544_guts.c
+++ b/hw/mpc8544_guts.c
@@ -53,11 +53,13 @@
 
 struct GutsState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
 };
 
 typedef struct GutsState GutsState;
 
-static uint32_t mpc8544_guts_read32(void *opaque, target_phys_addr_t addr)
+static uint64_t mpc8544_guts_read(void *opaque, target_phys_addr_t addr,
+                                  unsigned size)
 {
     uint32_t value = 0;
     CPUState *env = cpu_single_env;
@@ -78,14 +80,8 @@ static uint32_t mpc8544_guts_read32(void *opaque, target_phys_addr_t addr)
     return value;
 }
 
-static CPUReadMemoryFunc * const mpc8544_guts_read[] = {
-    NULL,
-    NULL,
-    &mpc8544_guts_read32,
-};
-
-static void mpc8544_guts_write32(void *opaque, target_phys_addr_t addr,
-                              uint32_t value)
+static void mpc8544_guts_write(void *opaque, target_phys_addr_t addr,
+                               uint64_t value, unsigned size)
 {
     addr &= MPC8544_GUTS_MMIO_SIZE - 1;
 
@@ -97,27 +93,30 @@ static void mpc8544_guts_write32(void *opaque, target_phys_addr_t addr,
         break;
     default:
         fprintf(stderr, "guts: Unknown register write: %x = %x\n",
-                (int)addr, value);
+                (int)addr, (unsigned)value);
         break;
     }
 }
 
-static CPUWriteMemoryFunc * const mpc8544_guts_write[] = {
-    NULL,
-    NULL,
-    &mpc8544_guts_write32,
+static const MemoryRegionOps mpc8544_guts_ops = {
+    .read = mpc8544_guts_read,
+    .write = mpc8544_guts_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static int mpc8544_guts_initfn(SysBusDevice *dev)
 {
     GutsState *s;
-    int iomem;
 
     s = FROM_SYSBUS(GutsState, sysbus_from_qdev(dev));
 
-    iomem = cpu_register_io_memory(mpc8544_guts_read, mpc8544_guts_write, s,
-                                   DEVICE_BIG_ENDIAN);
-    sysbus_init_mmio(dev, MPC8544_GUTS_MMIO_SIZE, iomem);
+    memory_region_init_io(&s->iomem, &mpc8544_guts_ops, s,
+                          "mpc6544.guts", MPC8544_GUTS_MMIO_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
diff --git a/hw/mpcore.c b/hw/mpcore.c
index d6175cfc2d..4357d12217 100644
--- a/hw/mpcore.c
+++ b/hw/mpcore.c
@@ -275,7 +275,7 @@ static int mpcore_priv_init(SysBusDevice *dev)
 
     gic_init(&s->gic, s->num_cpu);
     mpcore_priv_map_setup(s);
-    sysbus_init_mmio_region(dev, &s->container);
+    sysbus_init_mmio(dev, &s->container);
     for (i = 0; i < s->num_cpu * 2; i++) {
         mpcore_timer_init(s, &s->timer[i], i);
     }
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index 7bcd5d75e8..93247022b9 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -34,6 +34,7 @@
 
 typedef struct mst_irq_state{
 	SysBusDevice busdev;
+	MemoryRegion iomem;
 
 	qemu_irq parent;
 
@@ -86,8 +87,8 @@ mst_fpga_set_irq(void *opaque, int irq, int level)
 }
 
 
-static uint32_t
-mst_fpga_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t
+mst_fpga_readb(void *opaque, target_phys_addr_t addr, unsigned size)
 {
 	mst_irq_state *s = (mst_irq_state *) opaque;
 
@@ -124,7 +125,8 @@ mst_fpga_readb(void *opaque, target_phys_addr_t addr)
 }
 
 static void
-mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
+mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint64_t value,
+		unsigned size)
 {
 	mst_irq_state *s = (mst_irq_state *) opaque;
 	value &= 0xffffffff;
@@ -175,17 +177,11 @@ mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
 	}
 }
 
-static CPUReadMemoryFunc * const mst_fpga_readfn[] = {
-	mst_fpga_readb,
-	mst_fpga_readb,
-	mst_fpga_readb,
+static const MemoryRegionOps mst_fpga_ops = {
+	.read = mst_fpga_readb,
+	.write = mst_fpga_writeb,
+	.endianness = DEVICE_NATIVE_ENDIAN,
 };
-static CPUWriteMemoryFunc * const mst_fpga_writefn[] = {
-	mst_fpga_writeb,
-	mst_fpga_writeb,
-	mst_fpga_writeb,
-};
-
 
 static int mst_fpga_post_load(void *opaque, int version_id)
 {
@@ -198,7 +194,6 @@ static int mst_fpga_post_load(void *opaque, int version_id)
 static int mst_fpga_init(SysBusDevice *dev)
 {
 	mst_irq_state *s;
-	int iomemtype;
 
 	s = FROM_SYSBUS(mst_irq_state, dev);
 
@@ -210,9 +205,9 @@ static int mst_fpga_init(SysBusDevice *dev)
 	/* alloc the external 16 irqs */
 	qdev_init_gpio_in(&dev->qdev, mst_fpga_set_irq, MST_NUM_IRQS);
 
-	iomemtype = cpu_register_io_memory(mst_fpga_readfn,
-		mst_fpga_writefn, s, DEVICE_NATIVE_ENDIAN);
-	sysbus_init_mmio(dev, 0x00100000, iomemtype);
+	memory_region_init_io(&s->iomem, &mst_fpga_ops, s,
+			    "fpga", 0x00100000);
+	sysbus_init_mmio(dev, &s->iomem);
 	return 0;
 }
 
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 20553b525b..3c6cefe908 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -386,7 +386,7 @@ static int mv88w8618_eth_init(SysBusDevice *dev)
                           dev->qdev.info->name, dev->qdev.id, s);
     memory_region_init_io(&s->iomem, &mv88w8618_eth_ops, s, "mv88w8618-eth",
                           MP_ETH_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
@@ -593,7 +593,7 @@ static int musicpal_lcd_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &musicpal_lcd_ops, s,
                           "musicpal-lcd", MP_LCD_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     s->ds = graphic_console_init(lcd_refresh, lcd_invalidate,
                                  NULL, NULL, s);
@@ -713,7 +713,7 @@ static int mv88w8618_pic_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->parent_irq);
     memory_region_init_io(&s->iomem, &mv88w8618_pic_ops, s,
                           "musicpal-pic", MP_PIC_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
@@ -869,7 +869,7 @@ static int mv88w8618_pit_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &mv88w8618_pit_ops, s,
                           "musicpal-pit", MP_PIT_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
@@ -954,7 +954,7 @@ static int mv88w8618_flashcfg_init(SysBusDevice *dev)
     s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
     memory_region_init_io(&s->iomem, &mv88w8618_flashcfg_ops, s,
                           "musicpal-flashcfg", MP_FLASHCFG_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
@@ -1050,7 +1050,7 @@ static int mv88w8618_wlan_init(SysBusDevice *dev)
 
     memory_region_init_io(iomem, &mv88w8618_wlan_ops, NULL,
                           "musicpal-wlan", MP_WLAN_SIZE);
-    sysbus_init_mmio_region(dev, iomem);
+    sysbus_init_mmio(dev, iomem);
     return 0;
 }
 
@@ -1256,7 +1256,7 @@ static int musicpal_gpio_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &musicpal_gpio_ops, s,
                           "musicpal-gpio", MP_GPIO_SIZE);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
 
@@ -1315,6 +1315,7 @@ static SysBusDeviceInfo musicpal_gpio_info = {
 
 typedef struct musicpal_key_state {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t kbd_extended;
     uint32_t pressed_keys;
     qemu_irq out[8];
@@ -1401,7 +1402,8 @@ static int musicpal_key_init(SysBusDevice *dev)
 {
     musicpal_key_state *s = FROM_SYSBUS(musicpal_key_state, dev);
 
-    sysbus_init_mmio(dev, 0x0, 0);
+    memory_region_init(&s->iomem, "dummy", 0);
+    sysbus_init_mmio(dev, &s->iomem);
 
     s->kbd_extended = 0;
     s->pressed_keys = 0;
diff --git a/hw/nseries.c b/hw/nseries.c
index eb991431a4..d429dbdebf 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -33,6 +33,7 @@
 #include "loader.h"
 #include "blockdev.h"
 #include "sysbus.h"
+#include "exec-memory.h"
 
 /* Nokia N8x0 support */
 struct n800_s {
@@ -1275,11 +1276,12 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
                 const char *kernel_cmdline, const char *initrd_filename,
                 const char *cpu_model, struct arm_boot_info *binfo, int model)
 {
+    MemoryRegion *sysmem = get_system_memory();
     struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s));
     int sdram_size = binfo->ram_size;
     DisplayState *ds;
 
-    s->cpu = omap2420_mpu_init(sdram_size, cpu_model);
+    s->cpu = omap2420_mpu_init(sysmem, sdram_size, cpu_model);
 
     /* Setup peripherals
      *
diff --git a/hw/omap.h b/hw/omap.h
index cc09a3c0ee..42eb361b21 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -76,6 +76,7 @@ struct omap_l4_agent_info_s {
     int ta_region;
 };
 struct omap_target_agent_s {
+    MemoryRegion iomem;
     struct omap_l4_s *bus;
     int regions;
     const struct omap_l4_region_s *start;
@@ -84,7 +85,8 @@ struct omap_target_agent_s {
     uint32_t control;
     uint32_t status;
 };
-struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num);
+struct omap_l4_s *omap_l4_init(MemoryRegion *address_space,
+                               target_phys_addr_t base, int ta_num);
 
 struct omap_target_agent_s;
 struct omap_target_agent_s *omap_l4ta_get(
@@ -92,16 +94,17 @@ struct omap_target_agent_s *omap_l4ta_get(
     const struct omap_l4_region_s *regions,
     const struct omap_l4_agent_info_s *agents,
     int cs);
-target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
-                int iotype);
+target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
+                                         int region, MemoryRegion *mr);
 target_phys_addr_t omap_l4_region_base(struct omap_target_agent_s *ta,
                                        int region);
-int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
-                CPUWriteMemoryFunc * const *mem_write, void *opaque);
+target_phys_addr_t omap_l4_region_size(struct omap_target_agent_s *ta,
+                                       int region);
 
 /* OMAP2 SDRAM controller */
 struct omap_sdrc_s;
-struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base);
+struct omap_sdrc_s *omap_sdrc_init(MemoryRegion *sysmem,
+                                   target_phys_addr_t base);
 void omap_sdrc_reset(struct omap_sdrc_s *s);
 
 /* OMAP2 general purpose memory controller */
@@ -431,9 +434,11 @@ enum omap_dma_model {
 
 struct soc_dma_s;
 struct soc_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
+                MemoryRegion *sysmem,
                 qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk,
                 enum omap_dma_model model);
 struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
+                MemoryRegion *sysmem,
                 struct omap_mpu_state_s *mpu, int fifo,
                 int chans, omap_clk iclk, omap_clk fclk);
 void omap_dma_reset(struct soc_dma_s *s);
@@ -658,7 +663,8 @@ struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
                 qemu_irq irq, omap_clk fclk, omap_clk iclk,
                 qemu_irq txdma, qemu_irq rxdma,
                 const char *label, CharDriverState *chr);
-struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta,
+struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem,
+                struct omap_target_agent_s *ta,
                 qemu_irq irq, omap_clk fclk, omap_clk iclk,
                 qemu_irq txdma, qemu_irq rxdma,
                 const char *label, CharDriverState *chr);
@@ -725,8 +731,11 @@ void omap_tap_init(struct omap_target_agent_s *ta,
 /* omap_lcdc.c */
 struct omap_lcd_panel_s;
 void omap_lcdc_reset(struct omap_lcd_panel_s *s);
-struct omap_lcd_panel_s *omap_lcdc_init(target_phys_addr_t base, qemu_irq irq,
-                struct omap_dma_lcd_channel_s *dma, omap_clk clk);
+struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem,
+                                        target_phys_addr_t base,
+                                        qemu_irq irq,
+                                        struct omap_dma_lcd_channel_s *dma,
+                                        omap_clk clk);
 
 /* omap_dss.c */
 struct rfbi_chip_s {
@@ -738,6 +747,7 @@ struct rfbi_chip_s {
 struct omap_dss_s;
 void omap_dss_reset(struct omap_dss_s *s);
 struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
+                MemoryRegion *sysmem,
                 target_phys_addr_t l3_base,
                 qemu_irq irq, qemu_irq drq,
                 omap_clk fck1, omap_clk fck2, omap_clk ck54m,
@@ -747,6 +757,7 @@ void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip);
 /* omap_mmc.c */
 struct omap_mmc_s;
 struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
+                MemoryRegion *sysmem,
                 BlockDriverState *bd,
                 qemu_irq irq, qemu_irq dma[], omap_clk clk);
 struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
@@ -758,8 +769,11 @@ void omap_mmc_enable(struct omap_mmc_s *s, int enable);
 
 /* omap_i2c.c */
 struct omap_i2c_s;
-struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
-                qemu_irq irq, qemu_irq *dma, omap_clk clk);
+struct omap_i2c_s *omap_i2c_init(MemoryRegion *sysmem,
+                                 target_phys_addr_t base,
+                                 qemu_irq irq,
+                                 qemu_irq *dma,
+                                 omap_clk clk);
 struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
                 qemu_irq irq, qemu_irq *dma, omap_clk fclk, omap_clk iclk);
 void omap_i2c_reset(struct omap_i2c_s *s);
@@ -822,8 +836,11 @@ struct omap_mpu_state_s {
     MemoryRegion pwl_iomem;
     MemoryRegion pwt_iomem;
     MemoryRegion mpui_io_iomem;
+    MemoryRegion tap_iomem;
     MemoryRegion imif_ram;
     MemoryRegion emiff_ram;
+    MemoryRegion sdram;
+    MemoryRegion sram;
 
     struct omap_dma_port_if_s {
         uint32_t (*read[3])(struct omap_mpu_state_s *s,
@@ -952,7 +969,8 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
                 const char *core);
 
 /* omap2.c */
-struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
+struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
+                unsigned long sdram_size,
                 const char *core);
 
 # if TARGET_PHYS_ADDR_BITS == 32
@@ -1125,7 +1143,4 @@ inline static int debug_register_io_memory(CPUReadMemoryFunc * const *mem_read,
 #  define cpu_register_io_memory	debug_register_io_memory
 # endif
 
-/* Define when we want to reduce the number of IO regions registered.  */
-/*# define L4_MUX_HACK*/
-
 #endif /* hw_omap_h */
diff --git a/hw/omap1.c b/hw/omap1.c
index 619812c176..53cde76116 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -3849,7 +3849,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
         dma_irqs[i] = qdev_get_gpio_in(s->ih[omap1_dma_irq_map[i].ih],
                                        omap1_dma_irq_map[i].intr);
     }
-    s->dma = omap_dma_init(0xfffed800, dma_irqs,
+    s->dma = omap_dma_init(0xfffed800, dma_irqs, system_memory,
                            qdev_get_gpio_in(s->ih[0], OMAP_INT_DMA_LCD),
                            s, omap_findclk(s, "dma_ck"), omap_dma_3_1);
 
@@ -3884,7 +3884,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
                     qdev_get_gpio_in(s->ih[1], OMAP_INT_OS_TIMER),
                     omap_findclk(s, "clk32-kHz"));
 
-    s->lcd = omap_lcdc_init(0xfffec000,
+    s->lcd = omap_lcdc_init(system_memory, 0xfffec000,
                             qdev_get_gpio_in(s->ih[0], OMAP_INT_LCD_CTRL),
                             omap_dma_get_lcdch(s->dma),
                             omap_findclk(s, "lcd_ck"));
@@ -3938,7 +3938,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
         fprintf(stderr, "qemu: missing SecureDigital device\n");
         exit(1);
     }
-    s->mmc = omap_mmc_init(0xfffb7800, dinfo->bdrv,
+    s->mmc = omap_mmc_init(0xfffb7800, system_memory, dinfo->bdrv,
                            qdev_get_gpio_in(s->ih[1], OMAP_INT_OQN),
                            &s->drq[OMAP_DMA_MMC_TX],
                     omap_findclk(s, "mmc_ck"));
@@ -3964,7 +3964,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
     omap_pwl_init(system_memory, 0xfffb5800, s, omap_findclk(s, "armxor_ck"));
     omap_pwt_init(system_memory, 0xfffb6000, s, omap_findclk(s, "armxor_ck"));
 
-    s->i2c[0] = omap_i2c_init(0xfffb3800,
+    s->i2c[0] = omap_i2c_init(system_memory, 0xfffb3800,
                               qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C),
                     &s->drq[OMAP_DMA_I2C_RX], omap_findclk(s, "mpuper_ck"));
 
diff --git a/hw/omap2.c b/hw/omap2.c
index 5197fef2d8..91577ae128 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -33,6 +33,7 @@
 /* Enhanced Audio Controller (CODEC only) */
 struct omap_eac_s {
     qemu_irq irq;
+    MemoryRegion iomem;
 
     uint16_t sysconfig;
     uint8_t config[4];
@@ -323,11 +324,16 @@ static void omap_eac_reset(struct omap_eac_s *s)
     omap_eac_interrupt_update(s);
 }
 
-static uint32_t omap_eac_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_eac_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     struct omap_eac_s *s = (struct omap_eac_s *) opaque;
     uint32_t ret;
 
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
     switch (addr) {
     case 0x000:	/* CPCFR1 */
         return s->config[0];
@@ -435,10 +441,14 @@ static uint32_t omap_eac_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_eac_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                           uint64_t value, unsigned size)
 {
     struct omap_eac_s *s = (struct omap_eac_s *) opaque;
 
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x098:	/* APD1LCR */
     case 0x09c:	/* APD1RCR */
@@ -574,22 +584,15 @@ static void omap_eac_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_eac_readfn[] = {
-    omap_badwidth_read16,
-    omap_eac_read,
-    omap_badwidth_read16,
-};
-
-static CPUWriteMemoryFunc * const omap_eac_writefn[] = {
-    omap_badwidth_write16,
-    omap_eac_write,
-    omap_badwidth_write16,
+static const MemoryRegionOps omap_eac_ops = {
+    .read = omap_eac_read,
+    .write = omap_eac_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
                 qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
 {
-    int iomemtype;
     struct omap_eac_s *s = (struct omap_eac_s *)
             g_malloc0(sizeof(struct omap_eac_s));
 
@@ -600,9 +603,9 @@ static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
 
     AUD_register_card("OMAP EAC", &s->codec.card);
 
-    iomemtype = cpu_register_io_memory(omap_eac_readfn,
-                    omap_eac_writefn, s, DEVICE_NATIVE_ENDIAN);
-    omap_l4_attach(ta, 0, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_eac_ops, s, "omap.eac",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &s->iomem);
 
     return s;
 }
@@ -610,6 +613,8 @@ static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
 /* STI/XTI (emulation interface) console - reverse engineered only */
 struct omap_sti_s {
     qemu_irq irq;
+    MemoryRegion iomem;
+    MemoryRegion iomem_fifo;
     CharDriverState *chr;
 
     uint32_t sysconfig;
@@ -639,10 +644,15 @@ static void omap_sti_reset(struct omap_sti_s *s)
     omap_sti_interrupt_update(s);
 }
 
-static uint32_t omap_sti_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_sti_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     struct omap_sti_s *s = (struct omap_sti_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x00:	/* STI_REVISION */
         return 0x10;
@@ -676,10 +686,14 @@ static uint32_t omap_sti_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_sti_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                           uint64_t value, unsigned size)
 {
     struct omap_sti_s *s = (struct omap_sti_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x00:	/* STI_REVISION */
     case 0x14:	/* STI_SYSSTATUS / STI_RX_STATUS / XTI_SYSSTATUS */
@@ -721,31 +735,30 @@ static void omap_sti_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_sti_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_sti_read,
-};
-
-static CPUWriteMemoryFunc * const omap_sti_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_sti_write,
+static const MemoryRegionOps omap_sti_ops = {
+    .read = omap_sti_read,
+    .write = omap_sti_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static uint32_t omap_sti_fifo_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_sti_fifo_read(void *opaque, target_phys_addr_t addr,
+                                   unsigned size)
 {
     OMAP_BAD_REG(addr);
     return 0;
 }
 
 static void omap_sti_fifo_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                                uint64_t value, unsigned size)
 {
     struct omap_sti_s *s = (struct omap_sti_s *) opaque;
     int ch = addr >> 6;
     uint8_t byte = value;
 
+    if (size != 1) {
+        return omap_badwidth_write8(opaque, addr, size);
+    }
+
     if (ch == STI_TRACE_CONTROL_CHANNEL) {
         /* Flush channel <i>value</i>.  */
         qemu_chr_fe_write(s->chr, (const uint8_t *) "\r", 1);
@@ -759,23 +772,17 @@ static void omap_sti_fifo_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_sti_fifo_readfn[] = {
-    omap_sti_fifo_read,
-    omap_badwidth_read8,
-    omap_badwidth_read8,
-};
-
-static CPUWriteMemoryFunc * const omap_sti_fifo_writefn[] = {
-    omap_sti_fifo_write,
-    omap_badwidth_write8,
-    omap_badwidth_write8,
+static const MemoryRegionOps omap_sti_fifo_ops = {
+    .read = omap_sti_fifo_read,
+    .write = omap_sti_fifo_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
+                MemoryRegion *sysmem,
                 target_phys_addr_t channel_base, qemu_irq irq, omap_clk clk,
                 CharDriverState *chr)
 {
-    int iomemtype;
     struct omap_sti_s *s = (struct omap_sti_s *)
             g_malloc0(sizeof(struct omap_sti_s));
 
@@ -784,13 +791,13 @@ static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
 
     s->chr = chr ?: qemu_chr_new("null", "null", NULL);
 
-    iomemtype = l4_register_io_memory(omap_sti_readfn,
-                    omap_sti_writefn, s);
-    omap_l4_attach(ta, 0, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_sti_ops, s, "omap.sti",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &s->iomem);
 
-    iomemtype = cpu_register_io_memory(omap_sti_fifo_readfn,
-                    omap_sti_fifo_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(channel_base, 0x10000, iomemtype);
+    memory_region_init_io(&s->iomem_fifo, &omap_sti_fifo_ops, s,
+                          "omap.sti.fifo", 0x10000);
+    memory_region_add_subregion(sysmem, channel_base, &s->iomem_fifo);
 
     return s;
 }
@@ -993,6 +1000,8 @@ static const struct omap_l4_agent_info_s omap_l4_agent_info[54] = {
 struct omap_prcm_s {
     qemu_irq irq[3];
     struct omap_mpu_state_s *mpu;
+    MemoryRegion iomem0;
+    MemoryRegion iomem1;
 
     uint32_t irqst[3];
     uint32_t irqen[3];
@@ -1031,11 +1040,16 @@ static void omap_prcm_int_update(struct omap_prcm_s *s, int dom)
     /* XXX or is the mask applied before PRCM_IRQSTATUS_* ? */
 }
 
-static uint32_t omap_prcm_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_prcm_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
     uint32_t ret;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x000:	/* PRCM_REVISION */
         return 0x10;
@@ -1339,10 +1353,14 @@ static void omap_prcm_dpll_update(struct omap_prcm_s *s)
 }
 
 static void omap_prcm_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x000:	/* PRCM_REVISION */
     case 0x054:	/* PRCM_VOLTST */
@@ -1692,16 +1710,10 @@ static void omap_prcm_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_prcm_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_prcm_read,
-};
-
-static CPUWriteMemoryFunc * const omap_prcm_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_prcm_write,
+static const MemoryRegionOps omap_prcm_ops = {
+    .read = omap_prcm_read,
+    .write = omap_prcm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void omap_prcm_reset(struct omap_prcm_s *s)
@@ -1788,7 +1800,6 @@ static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
                 qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
                 struct omap_mpu_state_s *mpu)
 {
-    int iomemtype;
     struct omap_prcm_s *s = (struct omap_prcm_s *)
             g_malloc0(sizeof(struct omap_prcm_s));
 
@@ -1798,10 +1809,12 @@ static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
     s->mpu = mpu;
     omap_prcm_coldreset(s);
 
-    iomemtype = l4_register_io_memory(omap_prcm_readfn,
-                    omap_prcm_writefn, s);
-    omap_l4_attach(ta, 0, iomemtype);
-    omap_l4_attach(ta, 1, iomemtype);
+    memory_region_init_io(&s->iomem0, &omap_prcm_ops, s, "omap.pcrm0",
+                          omap_l4_region_size(ta, 0));
+    memory_region_init_io(&s->iomem1, &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);
 
     return s;
 }
@@ -1809,6 +1822,7 @@ static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
 /* System and Pinout control */
 struct omap_sysctl_s {
     struct omap_mpu_state_s *mpu;
+    MemoryRegion iomem;
 
     uint32_t sysconfig;
     uint32_t devconfig;
@@ -2062,16 +2076,20 @@ static void omap_sysctl_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_sysctl_readfn[] = {
-    omap_sysctl_read8,
-    omap_badwidth_read32,	/* TODO */
-    omap_sysctl_read,
-};
-
-static CPUWriteMemoryFunc * const omap_sysctl_writefn[] = {
-    omap_sysctl_write8,
-    omap_badwidth_write32,	/* TODO */
-    omap_sysctl_write,
+static const MemoryRegionOps omap_sysctl_ops = {
+    .old_mmio = {
+        .read = {
+            omap_sysctl_read8,
+            omap_badwidth_read32,	/* TODO */
+            omap_sysctl_read,
+        },
+        .write = {
+            omap_sysctl_write8,
+            omap_badwidth_write32,	/* TODO */
+            omap_sysctl_write,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void omap_sysctl_reset(struct omap_sysctl_s *s)
@@ -2161,16 +2179,15 @@ static void omap_sysctl_reset(struct omap_sysctl_s *s)
 static struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
                 omap_clk iclk, struct omap_mpu_state_s *mpu)
 {
-    int iomemtype;
     struct omap_sysctl_s *s = (struct omap_sysctl_s *)
             g_malloc0(sizeof(struct omap_sysctl_s));
 
     s->mpu = mpu;
     omap_sysctl_reset(s);
 
-    iomemtype = l4_register_io_memory(omap_sysctl_readfn,
-                    omap_sysctl_writefn, s);
-    omap_l4_attach(ta, 0, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_sysctl_ops, s, "omap.sysctl",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &s->iomem);
 
     return s;
 }
@@ -2223,12 +2240,12 @@ static const struct dma_irq_map omap2_dma_irq_map[] = {
     { 0, OMAP_INT_24XX_SDMA_IRQ3 },
 };
 
-struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
+struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
+                unsigned long sdram_size,
                 const char *core)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
             g_malloc0(sizeof(struct omap_mpu_state_s));
-    ram_addr_t sram_base, q2_base;
     qemu_irq *cpu_irq;
     qemu_irq dma_irqs[4];
     DriveInfo *dinfo;
@@ -2252,14 +2269,12 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
     omap_clk_init(s);
 
     /* Memory-mapped stuff */
-    cpu_register_physical_memory(OMAP2_Q2_BASE, s->sdram_size,
-                    (q2_base = qemu_ram_alloc(NULL, "omap2.dram",
-                                              s->sdram_size)) | IO_MEM_RAM);
-    cpu_register_physical_memory(OMAP2_SRAM_BASE, s->sram_size,
-                    (sram_base = qemu_ram_alloc(NULL, "omap2.sram",
-                                                s->sram_size)) | IO_MEM_RAM);
+    memory_region_init_ram(&s->sdram, NULL, "omap2.dram", s->sdram_size);
+    memory_region_add_subregion(sysmem, OMAP2_Q2_BASE, &s->sdram);
+    memory_region_init_ram(&s->sram, NULL, "omap2.sram", s->sram_size);
+    memory_region_add_subregion(sysmem, OMAP2_SRAM_BASE, &s->sram);
 
-    s->l4 = omap_l4_init(OMAP2_L4_BASE, 54);
+    s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54);
 
     /* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */
     cpu_irq = arm_pic_init_cpu(s->env);
@@ -2284,18 +2299,18 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
         dma_irqs[i] = qdev_get_gpio_in(s->ih[omap2_dma_irq_map[i].ih],
                                        omap2_dma_irq_map[i].intr);
     }
-    s->dma = omap_dma4_init(0x48056000, dma_irqs, s, 256, 32,
+    s->dma = omap_dma4_init(0x48056000, dma_irqs, sysmem, s, 256, 32,
                     omap_findclk(s, "sdma_iclk"),
                     omap_findclk(s, "sdma_fclk"));
     s->port->addr_valid = omap2_validate_addr;
 
     /* Register SDRAM and SRAM ports for fast DMA transfers.  */
-    soc_dma_port_add_mem(s->dma, qemu_get_ram_ptr(q2_base),
+    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sdram),
                          OMAP2_Q2_BASE, s->sdram_size);
-    soc_dma_port_add_mem(s->dma, qemu_get_ram_ptr(sram_base),
+    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sram),
                          OMAP2_SRAM_BASE, s->sram_size);
 
-    s->uart[0] = omap2_uart_init(omap_l4ta(s->l4, 19),
+    s->uart[0] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 19),
                                  qdev_get_gpio_in(s->ih[0],
                                                   OMAP_INT_24XX_UART1_IRQ),
                     omap_findclk(s, "uart1_fclk"),
@@ -2304,7 +2319,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
                     s->drq[OMAP24XX_DMA_UART1_RX],
                     "uart1",
                     serial_hds[0]);
-    s->uart[1] = omap2_uart_init(omap_l4ta(s->l4, 20),
+    s->uart[1] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 20),
                                  qdev_get_gpio_in(s->ih[0],
                                                   OMAP_INT_24XX_UART2_IRQ),
                     omap_findclk(s, "uart2_fclk"),
@@ -2313,7 +2328,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
                     s->drq[OMAP24XX_DMA_UART2_RX],
                     "uart2",
                     serial_hds[0] ? serial_hds[1] : NULL);
-    s->uart[2] = omap2_uart_init(omap_l4ta(s->l4, 21),
+    s->uart[2] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 21),
                                  qdev_get_gpio_in(s->ih[0],
                                                   OMAP_INT_24XX_UART3_IRQ),
                     omap_findclk(s, "uart3_fclk"),
@@ -2421,7 +2436,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
     sysbus_mmio_map(busdev, 3, omap_l4_region_base(ta, 4));
     sysbus_mmio_map(busdev, 4, omap_l4_region_base(ta, 5));
 
-    s->sdrc = omap_sdrc_init(0x68009000);
+    s->sdrc = omap_sdrc_init(sysmem, 0x68009000);
     s->gpmc = omap_gpmc_init(s, 0x6800a000,
                              qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPMC_IRQ),
                              s->drq[OMAP24XX_DMA_GPMC]);
@@ -2447,7 +2462,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
                     omap_findclk(s, "spi2_fclk"),
                     omap_findclk(s, "spi2_iclk"));
 
-    s->dss = omap_dss_init(omap_l4ta(s->l4, 10), 0x68000800,
+    s->dss = omap_dss_init(omap_l4ta(s->l4, 10), sysmem, 0x68000800,
                     /* XXX wire M_IRQ_25, D_L2_IRQ_30 and I_IRQ_13 together */
                     qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_DSS_IRQ),
                            s->drq[OMAP24XX_DMA_DSS],
@@ -2456,7 +2471,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
                     omap_findclk(s, "dss_l3_iclk"),
                     omap_findclk(s, "dss_l4_iclk"));
 
-    omap_sti_init(omap_l4ta(s->l4, 18), 0x54000000,
+    omap_sti_init(omap_l4ta(s->l4, 18), sysmem, 0x54000000,
                   qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_STI),
                   omap_findclk(s, "emul_ck"),
                     serial_hds[0] && serial_hds[1] && serial_hds[2] ?
diff --git a/hw/omap_dma.c b/hw/omap_dma.c
index f943d4e147..389cb78dee 100644
--- a/hw/omap_dma.c
+++ b/hw/omap_dma.c
@@ -102,6 +102,7 @@ struct omap_dma_channel_s {
 
 struct omap_dma_s {
     struct soc_dma_s *dma;
+    MemoryRegion iomem;
 
     struct omap_mpu_state_s *mpu;
     omap_clk clk;
@@ -1445,12 +1446,17 @@ static int omap_dma_sys_read(struct omap_dma_s *s, int offset,
     return 0;
 }
 
-static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_dma_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     struct omap_dma_s *s = (struct omap_dma_s *) opaque;
     int reg, ch;
     uint16_t ret;
 
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
     switch (addr) {
     case 0x300 ... 0x3fe:
         if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
@@ -1489,11 +1495,15 @@ static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_dma_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                           uint64_t value, unsigned size)
 {
     struct omap_dma_s *s = (struct omap_dma_s *) opaque;
     int reg, ch;
 
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x300 ... 0x3fe:
         if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
@@ -1530,16 +1540,10 @@ static void omap_dma_write(void *opaque, target_phys_addr_t addr,
     OMAP_BAD_REG(addr);
 }
 
-static CPUReadMemoryFunc * const omap_dma_readfn[] = {
-    omap_badwidth_read16,
-    omap_dma_read,
-    omap_badwidth_read16,
-};
-
-static CPUWriteMemoryFunc * const omap_dma_writefn[] = {
-    omap_badwidth_write16,
-    omap_dma_write,
-    omap_badwidth_write16,
+static const MemoryRegionOps omap_dma_ops = {
+    .read = omap_dma_read,
+    .write = omap_dma_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void omap_dma_request(void *opaque, int drq, int req)
@@ -1615,10 +1619,11 @@ static void omap_dma_setcaps(struct omap_dma_s *s)
 }
 
 struct soc_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
+                MemoryRegion *sysmem,
                 qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk,
                 enum omap_dma_model model)
 {
-    int iomemtype, num_irqs, memsize, i;
+    int num_irqs, memsize, i;
     struct omap_dma_s *s = (struct omap_dma_s *)
             g_malloc0(sizeof(struct omap_dma_s));
 
@@ -1658,9 +1663,8 @@ struct soc_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
     omap_dma_reset(s->dma);
     omap_dma_clk_update(s, 0, 1);
 
-    iomemtype = cpu_register_io_memory(omap_dma_readfn,
-                    omap_dma_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, memsize, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_dma_ops, s, "omap.dma", memsize);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     mpu->drq = s->dma->drq;
 
@@ -1688,12 +1692,17 @@ static void omap_dma_interrupts_4_update(struct omap_dma_s *s)
         qemu_irq_raise(s->irq[3]);
 }
 
-static uint32_t omap_dma4_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_dma4_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_dma_s *s = (struct omap_dma_s *) opaque;
     int irqn = 0, chnum;
     struct omap_dma_channel_s *ch;
 
+    if (size == 1) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
     switch (addr) {
     case 0x00:	/* DMA4_REVISION */
         return 0x40;
@@ -1834,12 +1843,16 @@ static uint32_t omap_dma4_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_dma4_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_dma_s *s = (struct omap_dma_s *) opaque;
     int chnum, irqn = 0;
     struct omap_dma_channel_s *ch;
 
+    if (size == 1) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x14:	/* DMA4_IRQSTATUS_L3 */
         irqn ++;
@@ -2021,23 +2034,18 @@ static void omap_dma4_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_dma4_readfn[] = {
-    omap_badwidth_read16,
-    omap_dma4_read,
-    omap_dma4_read,
-};
-
-static CPUWriteMemoryFunc * const omap_dma4_writefn[] = {
-    omap_badwidth_write16,
-    omap_dma4_write,
-    omap_dma4_write,
+static const MemoryRegionOps omap_dma4_ops = {
+    .read = omap_dma4_read,
+    .write = omap_dma4_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
+                MemoryRegion *sysmem,
                 struct omap_mpu_state_s *mpu, int fifo,
                 int chans, omap_clk iclk, omap_clk fclk)
 {
-    int iomemtype, i;
+    int i;
     struct omap_dma_s *s = (struct omap_dma_s *)
             g_malloc0(sizeof(struct omap_dma_s));
 
@@ -2065,9 +2073,8 @@ struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
     omap_dma_reset(s->dma);
     omap_dma_clk_update(s, 0, !!s->dma->freq);
 
-    iomemtype = cpu_register_io_memory(omap_dma4_readfn,
-                    omap_dma4_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_dma4_ops, s, "omap.dma4", 0x1000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     mpu->drq = s->dma->drq;
 
diff --git a/hw/omap_dss.c b/hw/omap_dss.c
index b4a8b4c45d..ede640b92e 100644
--- a/hw/omap_dss.c
+++ b/hw/omap_dss.c
@@ -25,6 +25,7 @@ struct omap_dss_s {
     qemu_irq irq;
     qemu_irq drq;
     DisplayState *state;
+    MemoryRegion iomem_diss1, iomem_disc1, iomem_rfbi1, iomem_venc1, iomem_im3;
 
     int autoidle;
     int control;
@@ -167,10 +168,15 @@ void omap_dss_reset(struct omap_dss_s *s)
     omap_dispc_interrupt_update(s);
 }
 
-static uint32_t omap_diss_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_diss_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x00:	/* DSS_REVISIONNUMBER */
         return 0x20;
@@ -201,10 +207,14 @@ static uint32_t omap_diss_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_diss_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x00:	/* DSS_REVISIONNUMBER */
     case 0x14:	/* DSS_SYSSTATUS */
@@ -230,22 +240,21 @@ static void omap_diss_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_diss1_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_diss_read,
+static const MemoryRegionOps omap_diss_ops = {
+    .read = omap_diss_read,
+    .write = omap_diss_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const omap_diss1_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_diss_write,
-};
-
-static uint32_t omap_disc_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_disc_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x000:	/* DISPC_REVISION */
         return 0x20;
@@ -363,10 +372,14 @@ static uint32_t omap_disc_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_disc_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x010:	/* DISPC_SYSCONFIG */
         if (value & 2)						/* SOFTRESET */
@@ -570,16 +583,10 @@ static void omap_disc_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_disc1_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_disc_read,
-};
-
-static CPUWriteMemoryFunc * const omap_disc1_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_disc_write,
+static const MemoryRegionOps omap_disc_ops = {
+    .read = omap_disc_read,
+    .write = omap_disc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void omap_rfbi_transfer_stop(struct omap_dss_s *s)
@@ -656,10 +663,15 @@ static void omap_rfbi_transfer_start(struct omap_dss_s *s)
     omap_dispc_interrupt_update(s);
 }
 
-static uint32_t omap_rfbi_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_rfbi_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x00:	/* RFBI_REVISION */
         return 0x10;
@@ -719,10 +731,14 @@ static uint32_t omap_rfbi_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_rfbi_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x10:	/* RFBI_SYSCONFIG */
         if (value & 2)						/* SOFTRESET */
@@ -842,20 +858,19 @@ static void omap_rfbi_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_rfbi1_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_rfbi_read,
-};
-
-static CPUWriteMemoryFunc * const omap_rfbi1_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_rfbi_write,
+static const MemoryRegionOps omap_rfbi_ops = {
+    .read = omap_rfbi_read,
+    .write = omap_rfbi_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static uint32_t omap_venc_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_venc_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x00:	/* REV_ID */
     case 0x04:	/* STATUS */
@@ -910,8 +925,12 @@ static uint32_t omap_venc_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_venc_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, size);
+    }
+
     switch (addr) {
     case 0x08:	/* F_CONTROL */
     case 0x10:	/* VIDOUT_CTRL */
@@ -961,20 +980,19 @@ static void omap_venc_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_venc1_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_venc_read,
+static const MemoryRegionOps omap_venc_ops = {
+    .read = omap_venc_read,
+    .write = omap_venc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const omap_venc1_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_venc_write,
-};
-
-static uint32_t omap_im3_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_im3_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x0a8:	/* SBIMERRLOGA */
     case 0x0b0:	/* SBIMERRLOG */
@@ -995,8 +1013,12 @@ static uint32_t omap_im3_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_im3_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                           uint64_t value, unsigned size)
 {
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x0b0:	/* SBIMERRLOG */
     case 0x190:	/* SBIMSTATE */
@@ -1011,25 +1033,19 @@ static void omap_im3_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_im3_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_im3_read,
-};
-
-static CPUWriteMemoryFunc * const omap_im3_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_im3_write,
+static const MemoryRegionOps omap_im3_ops = {
+    .read = omap_im3_read,
+    .write = omap_im3_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
+                MemoryRegion *sysmem,
                 target_phys_addr_t l3_base,
                 qemu_irq irq, qemu_irq drq,
                 omap_clk fck1, omap_clk fck2, omap_clk ck54m,
                 omap_clk ick1, omap_clk ick2)
 {
-    int iomemtype[5];
     struct omap_dss_s *s = (struct omap_dss_s *)
             g_malloc0(sizeof(struct omap_dss_s));
 
@@ -1037,21 +1053,22 @@ struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
     s->drq = drq;
     omap_dss_reset(s);
 
-    iomemtype[0] = l4_register_io_memory(omap_diss1_readfn,
-                    omap_diss1_writefn, s);
-    iomemtype[1] = l4_register_io_memory(omap_disc1_readfn,
-                    omap_disc1_writefn, s);
-    iomemtype[2] = l4_register_io_memory(omap_rfbi1_readfn,
-                    omap_rfbi1_writefn, s);
-    iomemtype[3] = l4_register_io_memory(omap_venc1_readfn,
-                    omap_venc1_writefn, s);
-    iomemtype[4] = cpu_register_io_memory(omap_im3_readfn,
-                    omap_im3_writefn, s, DEVICE_NATIVE_ENDIAN);
-    omap_l4_attach(ta, 0, iomemtype[0]);
-    omap_l4_attach(ta, 1, iomemtype[1]);
-    omap_l4_attach(ta, 2, iomemtype[2]);
-    omap_l4_attach(ta, 3, iomemtype[3]);
-    cpu_register_physical_memory(l3_base, 0x1000, iomemtype[4]);
+    memory_region_init_io(&s->iomem_diss1, &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",
+                          omap_l4_region_size(ta, 1));
+    memory_region_init_io(&s->iomem_rfbi1, &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",
+                          omap_l4_region_size(ta, 3));
+    memory_region_init_io(&s->iomem_im3, &omap_im3_ops, s,
+                          "omap.im3", 0x1000);
+
+    omap_l4_attach(ta, 0, &s->iomem_diss1);
+    omap_l4_attach(ta, 1, &s->iomem_disc1);
+    omap_l4_attach(ta, 2, &s->iomem_rfbi1);
+    omap_l4_attach(ta, 3, &s->iomem_venc1);
+    memory_region_add_subregion(sysmem, l3_base, &s->iomem_im3);
 
 #if 0
     s->state = graphic_console_init(omap_update_display,
diff --git a/hw/omap_gpio.c b/hw/omap_gpio.c
index 30630a8aa9..29147be8b8 100644
--- a/hw/omap_gpio.c
+++ b/hw/omap_gpio.c
@@ -37,6 +37,7 @@ struct omap_gpio_s {
 
 struct omap_gpif_s {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     int mpu_model;
     void *clk;
     struct omap_gpio_s omap1;
@@ -60,11 +61,16 @@ static void omap_gpio_set(void *opaque, int line, int level)
     }
 }
 
-static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_gpio_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
     int offset = addr & OMAP_MPUI_REG_MASK;
 
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
     switch (offset) {
     case 0x00:	/* DATA_INPUT */
         return s->inputs & s->pins;
@@ -94,13 +100,17 @@ static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
     int offset = addr & OMAP_MPUI_REG_MASK;
     uint16_t diff;
     int ln;
 
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
     switch (offset) {
     case 0x00:	/* DATA_INPUT */
         OMAP_RO_REG(addr);
@@ -156,16 +166,10 @@ static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
 }
 
 /* *Some* sources say the memory region is 32-bit.  */
-static CPUReadMemoryFunc * const omap_gpio_readfn[] = {
-    omap_badwidth_read16,
-    omap_gpio_read,
-    omap_badwidth_read16,
-};
-
-static CPUWriteMemoryFunc * const omap_gpio_writefn[] = {
-    omap_badwidth_write16,
-    omap_gpio_write,
-    omap_badwidth_write16,
+static const MemoryRegionOps omap_gpio_ops = {
+    .read = omap_gpio_read,
+    .write = omap_gpio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void omap_gpio_reset(struct omap_gpio_s *s)
@@ -183,6 +187,7 @@ struct omap2_gpio_s {
     qemu_irq irq[2];
     qemu_irq wkup;
     qemu_irq *handler;
+    MemoryRegion iomem;
 
     uint8_t revision;
     uint8_t config[2];
@@ -200,6 +205,7 @@ struct omap2_gpio_s {
 
 struct omap2_gpif_s {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     int mpu_model;
     void *iclk;
     void *fclk[6];
@@ -563,16 +569,20 @@ static void omap2_gpio_module_writep(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap2_gpio_module_readfn[] = {
-    omap2_gpio_module_readp,
-    omap2_gpio_module_readp,
-    omap2_gpio_module_read,
-};
-
-static CPUWriteMemoryFunc * const omap2_gpio_module_writefn[] = {
-    omap2_gpio_module_writep,
-    omap2_gpio_module_writep,
-    omap2_gpio_module_write,
+static const MemoryRegionOps omap2_gpio_module_ops = {
+    .old_mmio = {
+        .read = {
+            omap2_gpio_module_readp,
+            omap2_gpio_module_readp,
+            omap2_gpio_module_read,
+        },
+        .write = {
+            omap2_gpio_module_writep,
+            omap2_gpio_module_writep,
+            omap2_gpio_module_write,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void omap_gpif_reset(DeviceState *dev)
@@ -594,7 +604,8 @@ static void omap2_gpif_reset(DeviceState *dev)
     s->gpo = 0;
 }
 
-static uint32_t omap2_gpif_top_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap2_gpif_top_read(void *opaque, target_phys_addr_t addr,
+                                    unsigned size)
 {
     struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
 
@@ -623,7 +634,7 @@ static uint32_t omap2_gpif_top_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap2_gpif_top_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                                 uint64_t value, unsigned size)
 {
     struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
 
@@ -651,16 +662,10 @@ static void omap2_gpif_top_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap2_gpif_top_readfn[] = {
-    omap2_gpif_top_read,
-    omap2_gpif_top_read,
-    omap2_gpif_top_read,
-};
-
-static CPUWriteMemoryFunc * const omap2_gpif_top_writefn[] = {
-    omap2_gpif_top_write,
-    omap2_gpif_top_write,
-    omap2_gpif_top_write,
+static const MemoryRegionOps omap2_gpif_top_ops = {
+    .read = omap2_gpif_top_read,
+    .write = omap2_gpif_top_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int omap_gpio_init(SysBusDevice *dev)
@@ -672,11 +677,9 @@ static int omap_gpio_init(SysBusDevice *dev)
     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);
-    sysbus_init_mmio(dev, 0x1000,
-                    cpu_register_io_memory(omap_gpio_readfn,
-                                    omap_gpio_writefn,
-                                    &s->omap1,
-                                    DEVICE_NATIVE_ENDIAN));
+    memory_region_init_io(&s->iomem, &omap_gpio_ops, &s->omap1,
+                          "omap.gpio", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
@@ -689,10 +692,9 @@ static int omap2_gpio_init(SysBusDevice *dev)
     }
     if (s->mpu_model < omap3430) {
         s->modulecount = (s->mpu_model < omap2430) ? 4 : 5;
-        sysbus_init_mmio(dev, 0x1000,
-                        cpu_register_io_memory(omap2_gpif_top_readfn,
-                                        omap2_gpif_top_writefn, s,
-                                        DEVICE_NATIVE_ENDIAN));
+        memory_region_init_io(&s->iomem, &omap2_gpif_top_ops, s,
+                              "omap2.gpio", 0x1000);
+        sysbus_init_mmio(dev, &s->iomem);
     } else {
         s->modulecount = 6;
     }
@@ -710,10 +712,9 @@ static int omap2_gpio_init(SysBusDevice *dev)
         sysbus_init_irq(dev, &m->irq[0]); /* mpu irq */
         sysbus_init_irq(dev, &m->irq[1]); /* dsp irq */
         sysbus_init_irq(dev, &m->wkup);
-        sysbus_init_mmio(dev, 0x1000,
-                        cpu_register_io_memory(omap2_gpio_module_readfn,
-                                        omap2_gpio_module_writefn,
-                                        m, DEVICE_NATIVE_ENDIAN));
+        memory_region_init_io(&m->iomem, &omap2_gpio_module_ops, m,
+                              "omap.gpio-module", 0x1000);
+        sysbus_init_mmio(dev, &m->iomem);
     }
     return 0;
 }
diff --git a/hw/omap_gptimer.c b/hw/omap_gptimer.c
index 704b000636..7a145198a4 100644
--- a/hw/omap_gptimer.c
+++ b/hw/omap_gptimer.c
@@ -23,6 +23,7 @@
 
 /* GP timers */
 struct omap_gp_timer_s {
+    MemoryRegion iomem;
     qemu_irq irq;
     qemu_irq wkup;
     qemu_irq in;
@@ -337,12 +338,6 @@ static uint32_t omap_gp_timer_readh(void *opaque, target_phys_addr_t addr)
     }
 }
 
-static CPUReadMemoryFunc * const omap_gp_timer_readfn[] = {
-    omap_badwidth_read32,
-    omap_gp_timer_readh,
-    omap_gp_timer_readw,
-};
-
 static void omap_gp_timer_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
@@ -454,16 +449,25 @@ static void omap_gp_timer_writeh(void *opaque, target_phys_addr_t addr,
         s->writeh = (uint16_t) value;
 }
 
-static CPUWriteMemoryFunc * const omap_gp_timer_writefn[] = {
-    omap_badwidth_write32,
-    omap_gp_timer_writeh,
-    omap_gp_timer_write,
+static const MemoryRegionOps omap_gp_timer_ops = {
+    .old_mmio = {
+        .read = {
+            omap_badwidth_read32,
+            omap_gp_timer_readh,
+            omap_gp_timer_readw,
+        },
+        .write = {
+            omap_badwidth_write32,
+            omap_gp_timer_writeh,
+            omap_gp_timer_write,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
                 qemu_irq irq, omap_clk fclk, omap_clk iclk)
 {
-    int iomemtype;
     struct omap_gp_timer_s *s = (struct omap_gp_timer_s *)
             g_malloc0(sizeof(struct omap_gp_timer_s));
 
@@ -476,9 +480,9 @@ struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
     omap_gp_timer_reset(s);
     omap_gp_timer_clk_setup(s);
 
-    iomemtype = l4_register_io_memory(omap_gp_timer_readfn,
-                    omap_gp_timer_writefn, s);
-    omap_l4_attach(ta, 0, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_gp_timer_ops, s, "omap.gptimer",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &s->iomem);
 
     return s;
 }
diff --git a/hw/omap_i2c.c b/hw/omap_i2c.c
index 11577b1eec..5ec422c566 100644
--- a/hw/omap_i2c.c
+++ b/hw/omap_i2c.c
@@ -21,6 +21,7 @@
 #include "omap.h"
 
 struct omap_i2c_s {
+    MemoryRegion iomem;
     qemu_irq irq;
     qemu_irq drq[2];
     i2c_bus *bus;
@@ -409,22 +410,28 @@ static void omap_i2c_writeb(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_i2c_readfn[] = {
-    omap_badwidth_read16,
-    omap_i2c_read,
-    omap_badwidth_read16,
+static const MemoryRegionOps omap_i2c_ops = {
+    .old_mmio = {
+        .read = {
+            omap_badwidth_read16,
+            omap_i2c_read,
+            omap_badwidth_read16,
+        },
+        .write = {
+            omap_i2c_writeb, /* Only the last fifo write can be 8 bit.  */
+            omap_i2c_write,
+            omap_badwidth_write16,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const omap_i2c_writefn[] = {
-    omap_i2c_writeb,	/* Only the last fifo write can be 8 bit.  */
-    omap_i2c_write,
-    omap_badwidth_write16,
-};
-
-struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
-                qemu_irq irq, qemu_irq *dma, omap_clk clk)
+struct omap_i2c_s *omap_i2c_init(MemoryRegion *sysmem,
+                                 target_phys_addr_t base,
+                                 qemu_irq irq,
+                                 qemu_irq *dma,
+                                 omap_clk clk)
 {
-    int iomemtype;
     struct omap_i2c_s *s = (struct omap_i2c_s *)
             g_malloc0(sizeof(struct omap_i2c_s));
 
@@ -436,9 +443,8 @@ struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
     s->bus = i2c_init_bus(NULL, "i2c");
     omap_i2c_reset(s);
 
-    iomemtype = cpu_register_io_memory(omap_i2c_readfn,
-                    omap_i2c_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x800, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap.i2c", 0x800);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     return s;
 }
@@ -446,7 +452,6 @@ struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
 struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
                 qemu_irq irq, qemu_irq *dma, omap_clk fclk, omap_clk iclk)
 {
-    int iomemtype;
     struct omap_i2c_s *s = (struct omap_i2c_s *)
             g_malloc0(sizeof(struct omap_i2c_s));
 
@@ -457,9 +462,9 @@ struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
     s->bus = i2c_init_bus(NULL, "i2c");
     omap_i2c_reset(s);
 
-    iomemtype = l4_register_io_memory(omap_i2c_readfn,
-                    omap_i2c_writefn, s);
-    omap_l4_attach(ta, 0, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap2.i2c",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &s->iomem);
 
     return s;
 }
diff --git a/hw/omap_intc.c b/hw/omap_intc.c
index 45efa25109..fc53ec71fb 100644
--- a/hw/omap_intc.c
+++ b/hw/omap_intc.c
@@ -369,7 +369,7 @@ static int omap_intc_init(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, omap_set_intr, s->nbanks * 32);
     memory_region_init_io(&s->mmio, &omap_inth_mem_ops, s,
                           "omap-intc", s->size);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
     return 0;
 }
 
@@ -600,7 +600,7 @@ static int omap2_intc_init(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, omap_set_intr_noedge, s->nbanks * 32);
     memory_region_init_io(&s->mmio, &omap2_inth_mem_ops, s,
                           "omap2-intc", 0x1000);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
     return 0;
 }
 
diff --git a/hw/omap_l4.c b/hw/omap_l4.c
index a4a8883d2a..dbad7f67a8 100644
--- a/hw/omap_l4.c
+++ b/hw/omap_l4.c
@@ -20,129 +20,23 @@
 #include "hw.h"
 #include "omap.h"
 
-#ifdef L4_MUX_HACK
-static int omap_l4_io_entries;
-static int omap_cpu_io_entry;
-static struct omap_l4_entry {
-        CPUReadMemoryFunc * const *mem_read;
-        CPUWriteMemoryFunc * const *mem_write;
-        void *opaque;
-} *omap_l4_io_entry;
-static CPUReadMemoryFunc * const *omap_l4_io_readb_fn;
-static CPUReadMemoryFunc * const *omap_l4_io_readh_fn;
-static CPUReadMemoryFunc * const *omap_l4_io_readw_fn;
-static CPUWriteMemoryFunc * const *omap_l4_io_writeb_fn;
-static CPUWriteMemoryFunc * const *omap_l4_io_writeh_fn;
-static CPUWriteMemoryFunc * const *omap_l4_io_writew_fn;
-static void **omap_l4_io_opaque;
-
-int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
-                CPUWriteMemoryFunc * const *mem_write, void *opaque)
-{
-    omap_l4_io_entry[omap_l4_io_entries].mem_read = mem_read;
-    omap_l4_io_entry[omap_l4_io_entries].mem_write = mem_write;
-    omap_l4_io_entry[omap_l4_io_entries].opaque = opaque;
-
-    return omap_l4_io_entries ++;
-}
-
-static uint32_t omap_l4_io_readb(void *opaque, target_phys_addr_t addr)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_readb_fn[i](omap_l4_io_opaque[i], addr);
-}
-
-static uint32_t omap_l4_io_readh(void *opaque, target_phys_addr_t addr)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_readh_fn[i](omap_l4_io_opaque[i], addr);
-}
-
-static uint32_t omap_l4_io_readw(void *opaque, target_phys_addr_t addr)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_readw_fn[i](omap_l4_io_opaque[i], addr);
-}
-
-static void omap_l4_io_writeb(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_writeb_fn[i](omap_l4_io_opaque[i], addr, value);
-}
-
-static void omap_l4_io_writeh(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_writeh_fn[i](omap_l4_io_opaque[i], addr, value);
-}
-
-static void omap_l4_io_writew(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_writew_fn[i](omap_l4_io_opaque[i], addr, value);
-}
-
-static CPUReadMemoryFunc * const omap_l4_io_readfn[] = {
-    omap_l4_io_readb,
-    omap_l4_io_readh,
-    omap_l4_io_readw,
-};
-
-static CPUWriteMemoryFunc * const omap_l4_io_writefn[] = {
-    omap_l4_io_writeb,
-    omap_l4_io_writeh,
-    omap_l4_io_writew,
-};
-#else
-int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
-                          CPUWriteMemoryFunc * const *mem_write,
-                          void *opaque)
-{
-    return cpu_register_io_memory(mem_read, mem_write, opaque,
-                                  DEVICE_NATIVE_ENDIAN);
-}
-#endif
-
 struct omap_l4_s {
+    MemoryRegion *address_space;
     target_phys_addr_t base;
     int ta_num;
     struct omap_target_agent_s ta[0];
 };
 
-struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num)
+struct omap_l4_s *omap_l4_init(MemoryRegion *address_space,
+                               target_phys_addr_t base, int ta_num)
 {
     struct omap_l4_s *bus = g_malloc0(
                     sizeof(*bus) + ta_num * sizeof(*bus->ta));
 
+    bus->address_space = address_space;
     bus->ta_num = ta_num;
     bus->base = base;
 
-#ifdef L4_MUX_HACK
-    omap_l4_io_entries = 1;
-    omap_l4_io_entry = g_malloc0(125 * sizeof(*omap_l4_io_entry));
-
-    omap_cpu_io_entry =
-            cpu_register_io_memory(omap_l4_io_readfn,
-                            omap_l4_io_writefn, bus, DEVICE_NATIVE_ENDIAN);
-# define L4_PAGES	(0xb4000 / TARGET_PAGE_SIZE)
-    omap_l4_io_readb_fn = g_malloc0(sizeof(void *) * L4_PAGES);
-    omap_l4_io_readh_fn = g_malloc0(sizeof(void *) * L4_PAGES);
-    omap_l4_io_readw_fn = g_malloc0(sizeof(void *) * L4_PAGES);
-    omap_l4_io_writeb_fn = g_malloc0(sizeof(void *) * L4_PAGES);
-    omap_l4_io_writeh_fn = g_malloc0(sizeof(void *) * L4_PAGES);
-    omap_l4_io_writew_fn = g_malloc0(sizeof(void *) * L4_PAGES);
-    omap_l4_io_opaque = g_malloc0(sizeof(void *) * L4_PAGES);
-#endif
-
     return bus;
 }
 
@@ -152,10 +46,21 @@ target_phys_addr_t omap_l4_region_base(struct omap_target_agent_s *ta,
     return ta->bus->base + ta->start[region].offset;
 }
 
-static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr)
+target_phys_addr_t omap_l4_region_size(struct omap_target_agent_s *ta,
+                                       int region)
+{
+    return ta->start[region].size;
+}
+
+static uint64_t omap_l4ta_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
 
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
     switch (addr) {
     case 0x00:	/* COMPONENT */
         return s->component;
@@ -172,10 +77,14 @@ static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_l4ta_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x00:	/* COMPONENT */
     case 0x28:	/* AGENT_STATUS */
@@ -193,16 +102,10 @@ static void omap_l4ta_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_l4ta_readfn[] = {
-    omap_badwidth_read16,
-    omap_l4ta_read,
-    omap_badwidth_read16,
-};
-
-static CPUWriteMemoryFunc * const omap_l4ta_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_l4ta_write,
+static const MemoryRegionOps omap_l4ta_ops = {
+    .read = omap_l4ta_read,
+    .write = omap_l4ta_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus,
@@ -210,7 +113,7 @@ struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus,
 	const struct omap_l4_agent_info_s *agents,
 	int cs)
 {
-    int i, iomemtype;
+    int i;
     struct omap_target_agent_s *ta = NULL;
     const struct omap_l4_agent_info_s *info = NULL;
 
@@ -233,21 +136,17 @@ struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus,
     ta->status = 0x00000000;
     ta->control = 0x00000200;	/* XXX 01000200 for L4TAO */
 
-    iomemtype = l4_register_io_memory(omap_l4ta_readfn,
-                    omap_l4ta_writefn, ta);
-    ta->base = omap_l4_attach(ta, info->ta_region, iomemtype);
+    memory_region_init_io(&ta->iomem, &omap_l4ta_ops, ta, "omap.l4ta",
+                          omap_l4_region_size(ta, info->ta_region));
+    omap_l4_attach(ta, info->ta_region, &ta->iomem);
 
     return ta;
 }
 
-target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
-                int iotype)
+target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
+                                         int region, MemoryRegion *mr)
 {
     target_phys_addr_t base;
-    ssize_t size;
-#ifdef L4_MUX_HACK
-    int i;
-#endif
 
     if (region < 0 || region >= ta->regions) {
         fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region);
@@ -255,23 +154,8 @@ target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
     }
 
     base = ta->bus->base + ta->start[region].offset;
-    size = ta->start[region].size;
-    if (iotype) {
-#ifndef L4_MUX_HACK
-        cpu_register_physical_memory(base, size, iotype);
-#else
-        cpu_register_physical_memory(base, size, omap_cpu_io_entry);
-        i = (base - ta->bus->base) / TARGET_PAGE_SIZE;
-        for (; size > 0; size -= TARGET_PAGE_SIZE, i ++) {
-            omap_l4_io_readb_fn[i] = omap_l4_io_entry[iotype].mem_read[0];
-            omap_l4_io_readh_fn[i] = omap_l4_io_entry[iotype].mem_read[1];
-            omap_l4_io_readw_fn[i] = omap_l4_io_entry[iotype].mem_read[2];
-            omap_l4_io_writeb_fn[i] = omap_l4_io_entry[iotype].mem_write[0];
-            omap_l4_io_writeh_fn[i] = omap_l4_io_entry[iotype].mem_write[1];
-            omap_l4_io_writew_fn[i] = omap_l4_io_entry[iotype].mem_write[2];
-            omap_l4_io_opaque[i] = omap_l4_io_entry[iotype].opaque;
-        }
-#endif
+    if (mr) {
+        memory_region_add_subregion(ta->bus->address_space, base, mr);
     }
 
     return base;
diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c
index 29e604863d..8484f7058d 100644
--- a/hw/omap_lcdc.c
+++ b/hw/omap_lcdc.c
@@ -22,6 +22,7 @@
 #include "framebuffer.h"
 
 struct omap_lcd_panel_s {
+    MemoryRegion iomem;
     qemu_irq irq;
     DisplayState *state;
 
@@ -323,7 +324,8 @@ static void omap_lcd_update(struct omap_lcd_panel_s *s) {
     }
 }
 
-static uint32_t omap_lcdc_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_lcdc_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *) opaque;
 
@@ -356,7 +358,7 @@ static uint32_t omap_lcdc_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_lcdc_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *) opaque;
 
@@ -399,16 +401,10 @@ static void omap_lcdc_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_lcdc_readfn[] = {
-    omap_lcdc_read,
-    omap_lcdc_read,
-    omap_lcdc_read,
-};
-
-static CPUWriteMemoryFunc * const omap_lcdc_writefn[] = {
-    omap_lcdc_write,
-    omap_lcdc_write,
-    omap_lcdc_write,
+static const MemoryRegionOps omap_lcdc_ops = {
+    .read = omap_lcdc_read,
+    .write = omap_lcdc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 void omap_lcdc_reset(struct omap_lcd_panel_s *s)
@@ -433,10 +429,12 @@ void omap_lcdc_reset(struct omap_lcd_panel_s *s)
     s->ctrl = 0;
 }
 
-struct omap_lcd_panel_s *omap_lcdc_init(target_phys_addr_t base, qemu_irq irq,
-                struct omap_dma_lcd_channel_s *dma, omap_clk clk)
+struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem,
+                                        target_phys_addr_t base,
+                                        qemu_irq irq,
+                                        struct omap_dma_lcd_channel_s *dma,
+                                        omap_clk clk)
 {
-    int iomemtype;
     struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *)
             g_malloc0(sizeof(struct omap_lcd_panel_s));
 
@@ -444,9 +442,8 @@ struct omap_lcd_panel_s *omap_lcdc_init(target_phys_addr_t base, qemu_irq irq,
     s->dma = dma;
     omap_lcdc_reset(s);
 
-    iomemtype = cpu_register_io_memory(omap_lcdc_readfn,
-                    omap_lcdc_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x100, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_lcdc_ops, s, "omap.lcdc", 0x100);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     s->state = graphic_console_init(omap_update_display,
                                     omap_invalidate_display,
diff --git a/hw/omap_mmc.c b/hw/omap_mmc.c
index a1afeb5c91..aec0285675 100644
--- a/hw/omap_mmc.c
+++ b/hw/omap_mmc.c
@@ -24,6 +24,7 @@ struct omap_mmc_s {
     qemu_irq irq;
     qemu_irq *dma;
     qemu_irq coverswitch;
+    MemoryRegion iomem;
     omap_clk clk;
     SDState *card;
     uint16_t last_cmd;
@@ -305,11 +306,15 @@ void omap_mmc_reset(struct omap_mmc_s *host)
     host->clkdiv = 0;
 }
 
-static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset)
+static uint64_t omap_mmc_read(void *opaque, target_phys_addr_t offset,
+                              unsigned size)
 {
     uint16_t i;
     struct omap_mmc_s *s = (struct omap_mmc_s *) opaque;
-    offset &= OMAP_MPUI_REG_MASK;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, offset);
+    }
 
     switch (offset) {
     case 0x00:	/* MMC_CMD */
@@ -395,11 +400,14 @@ static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void omap_mmc_write(void *opaque, target_phys_addr_t offset,
-                uint32_t value)
+                           uint64_t value, unsigned size)
 {
     int i;
     struct omap_mmc_s *s = (struct omap_mmc_s *) opaque;
-    offset &= OMAP_MPUI_REG_MASK;
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, offset, value);
+    }
 
     switch (offset) {
     case 0x00:	/* MMC_CMD */
@@ -540,16 +548,10 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static CPUReadMemoryFunc * const omap_mmc_readfn[] = {
-    omap_badwidth_read16,
-    omap_mmc_read,
-    omap_badwidth_read16,
-};
-
-static CPUWriteMemoryFunc * const omap_mmc_writefn[] = {
-    omap_badwidth_write16,
-    omap_mmc_write,
-    omap_badwidth_write16,
+static const MemoryRegionOps omap_mmc_ops = {
+    .read = omap_mmc_read,
+    .write = omap_mmc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void omap_mmc_cover_cb(void *opaque, int line, int level)
@@ -571,10 +573,10 @@ static void omap_mmc_cover_cb(void *opaque, int line, int level)
 }
 
 struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
+                MemoryRegion *sysmem,
                 BlockDriverState *bd,
                 qemu_irq irq, qemu_irq dma[], omap_clk clk)
 {
-    int iomemtype;
     struct omap_mmc_s *s = (struct omap_mmc_s *)
             g_malloc0(sizeof(struct omap_mmc_s));
 
@@ -586,9 +588,8 @@ struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
 
     omap_mmc_reset(s);
 
-    iomemtype = cpu_register_io_memory(omap_mmc_readfn,
-                    omap_mmc_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x800, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_mmc_ops, s, "omap.mmc", 0x800);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     /* Instantiate the storage */
     s->card = sd_init(bd, 0);
@@ -600,7 +601,6 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
                 BlockDriverState *bd, qemu_irq irq, qemu_irq dma[],
                 omap_clk fclk, omap_clk iclk)
 {
-    int iomemtype;
     struct omap_mmc_s *s = (struct omap_mmc_s *)
             g_malloc0(sizeof(struct omap_mmc_s));
 
@@ -612,9 +612,9 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
 
     omap_mmc_reset(s);
 
-    iomemtype = l4_register_io_memory(omap_mmc_readfn,
-                    omap_mmc_writefn, s);
-    omap_l4_attach(ta, 0, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_mmc_ops, s, "omap.mmc",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &s->iomem);
 
     /* Instantiate the storage */
     s->card = sd_init(bd, 0);
diff --git a/hw/omap_sdrc.c b/hw/omap_sdrc.c
index 1df2fd82bd..784e326105 100644
--- a/hw/omap_sdrc.c
+++ b/hw/omap_sdrc.c
@@ -22,6 +22,7 @@
 
 /* SDRAM Controller Subsystem */
 struct omap_sdrc_s {
+    MemoryRegion iomem;
     uint8_t config;
 };
 
@@ -30,10 +31,15 @@ void omap_sdrc_reset(struct omap_sdrc_s *s)
     s->config = 0x10;
 }
 
-static uint32_t omap_sdrc_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_sdrc_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x00:	/* SDRC_REVISION */
         return 0x20;
@@ -81,10 +87,14 @@ static uint32_t omap_sdrc_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_sdrc_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x00:	/* SDRC_REVISION */
     case 0x14:	/* SDRC_SYSSTATUS */
@@ -97,7 +107,7 @@ static void omap_sdrc_write(void *opaque, target_phys_addr_t addr,
     case 0x10:	/* SDRC_SYSCONFIG */
         if ((value >> 3) != 0x2)
             fprintf(stderr, "%s: bad SDRAM idle mode %i\n",
-                            __FUNCTION__, value >> 3);
+                    __FUNCTION__, (unsigned)value >> 3);
         if (value & 2)
             omap_sdrc_reset(s);
         s->config = value & 0x18;
@@ -137,29 +147,22 @@ static void omap_sdrc_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_sdrc_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_sdrc_read,
-};
-
-static CPUWriteMemoryFunc * const omap_sdrc_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_sdrc_write,
+static const MemoryRegionOps omap_sdrc_ops = {
+    .read = omap_sdrc_read,
+    .write = omap_sdrc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base)
+struct omap_sdrc_s *omap_sdrc_init(MemoryRegion *sysmem,
+                                   target_phys_addr_t base)
 {
-    int iomemtype;
     struct omap_sdrc_s *s = (struct omap_sdrc_s *)
             g_malloc0(sizeof(struct omap_sdrc_s));
 
     omap_sdrc_reset(s);
 
-    iomemtype = cpu_register_io_memory(omap_sdrc_readfn,
-                    omap_sdrc_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_sdrc_ops, s, "omap.sdrc", 0x1000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     return s;
 }
diff --git a/hw/omap_spi.c b/hw/omap_spi.c
index 6030ad9551..8f2b697d2d 100644
--- a/hw/omap_spi.c
+++ b/hw/omap_spi.c
@@ -24,6 +24,7 @@
 
 /* Multichannel SPI */
 struct omap_mcspi_s {
+    MemoryRegion iomem;
     qemu_irq irq;
     int chnum;
 
@@ -129,12 +130,17 @@ void omap_mcspi_reset(struct omap_mcspi_s *s)
     omap_mcspi_interrupt_update(s);
 }
 
-static uint32_t omap_mcspi_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_mcspi_read(void *opaque, target_phys_addr_t addr,
+                                unsigned size)
 {
     struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
     int ch = 0;
     uint32_t ret;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x00:	/* MCSPI_REVISION */
         return 0x91;
@@ -199,11 +205,15 @@ static uint32_t omap_mcspi_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_mcspi_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                             uint64_t value, unsigned size)
 {
     struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
     int ch = 0;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x00:	/* MCSPI_REVISION */
     case 0x14:	/* MCSPI_SYSSTATUS */
@@ -267,7 +277,7 @@ static void omap_mcspi_write(void *opaque, target_phys_addr_t addr,
         if (((value >> 12) & 3) == 3)			/* TRM */
             fprintf(stderr, "%s: invalid TRM value (3)\n", __FUNCTION__);
         if (((value >> 7) & 0x1f) < 3)			/* WL */
-            fprintf(stderr, "%s: invalid WL value (%i)\n",
+            fprintf(stderr, "%s: invalid WL value (%" PRIx64 ")\n",
                             __FUNCTION__, (value >> 7) & 0x1f);
         s->ch[ch].config = value & 0x7fffff;
         break;
@@ -298,22 +308,15 @@ static void omap_mcspi_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_mcspi_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_mcspi_read,
-};
-
-static CPUWriteMemoryFunc * const omap_mcspi_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_mcspi_write,
+static const MemoryRegionOps omap_mcspi_ops = {
+    .read = omap_mcspi_read,
+    .write = omap_mcspi_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
                 qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
 {
-    int iomemtype;
     struct omap_mcspi_s *s = (struct omap_mcspi_s *)
             g_malloc0(sizeof(struct omap_mcspi_s));
     struct omap_mcspi_ch_s *ch = s->ch;
@@ -327,9 +330,9 @@ struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
     }
     omap_mcspi_reset(s);
 
-    iomemtype = l4_register_io_memory(omap_mcspi_readfn,
-                    omap_mcspi_writefn, s);
-    omap_l4_attach(ta, 0, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_mcspi_ops, s, "omap.mcspi",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &s->iomem);
 
     return s;
 }
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index fe535459df..8e58645dc0 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -59,46 +59,28 @@
  * - 1 RTC
  */
 
-static uint32_t static_readb(void *opaque, target_phys_addr_t offset)
+static uint64_t static_read(void *opaque, target_phys_addr_t offset,
+                            unsigned size)
 {
     uint32_t *val = (uint32_t *) opaque;
+    uint32_t mask = (4 / size) - 1;
 
-    return *val >> ((offset & 3) << 3);
-}
-
-static uint32_t static_readh(void *opaque, target_phys_addr_t offset)
-{
-    uint32_t *val = (uint32_t *) opaque;
-
-    return *val >> ((offset & 1) << 3);
-}
-
-static uint32_t static_readw(void *opaque, target_phys_addr_t offset)
-{
-    uint32_t *val = (uint32_t *) opaque;
-
-    return *val >> ((offset & 0) << 3);
+    return *val >> ((offset & mask) << 3);
 }
 
 static void static_write(void *opaque, target_phys_addr_t offset,
-                uint32_t value)
+                         uint64_t value, unsigned size)
 {
 #ifdef SPY
-    printf("%s: value %08lx written at " PA_FMT "\n",
-                    __FUNCTION__, value, offset);
+    printf("%s: value %" PRIx64 " %u bytes written at 0x%x\n",
+                    __func__, value, size, (int)offset);
 #endif
 }
 
-static CPUReadMemoryFunc * const static_readfn[] = {
-    static_readb,
-    static_readh,
-    static_readw,
-};
-
-static CPUWriteMemoryFunc * const static_writefn[] = {
-    static_write,
-    static_write,
-    static_write,
+static const MemoryRegionOps static_ops = {
+    .read = static_read,
+    .write = static_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 #define sdram_size	0x02000000
@@ -123,7 +105,9 @@ static void sx1_init(ram_addr_t ram_size,
 {
     struct omap_mpu_state_s *cpu;
     MemoryRegion *address_space = get_system_memory();
-    int io;
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
+    MemoryRegion *flash_1 = g_new(MemoryRegion, 1);
+    MemoryRegion *cs = g_new(MemoryRegion, 4);
     static uint32_t cs0val = 0x00213090;
     static uint32_t cs1val = 0x00215070;
     static uint32_t cs2val = 0x00001139;
@@ -140,20 +124,25 @@ static void sx1_init(ram_addr_t ram_size,
     cpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, cpu_model);
 
     /* External Flash (EMIFS) */
-    cpu_register_physical_memory(OMAP_CS0_BASE, flash_size,
-                                 qemu_ram_alloc(NULL, "omap_sx1.flash0-0",
-                                                flash_size) | IO_MEM_ROM);
-
-    io = cpu_register_io_memory(static_readfn, static_writefn, &cs0val,
-                                DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(OMAP_CS0_BASE + flash_size,
-                    OMAP_CS0_SIZE - flash_size, io);
-    io = cpu_register_io_memory(static_readfn, static_writefn, &cs2val,
-                                DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(OMAP_CS2_BASE, OMAP_CS2_SIZE, io);
-    io = cpu_register_io_memory(static_readfn, static_writefn, &cs3val,
-                                DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(OMAP_CS3_BASE, OMAP_CS3_SIZE, io);
+    memory_region_init_ram(flash, NULL, "omap_sx1.flash0-0", flash_size);
+    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,
+                          "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,
+                          "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,
+                          "sx1.cs3", OMAP_CS3_SIZE);
+    memory_region_add_subregion(address_space,
+                                OMAP_CS2_BASE, &cs[3]);
 
     fl_idx = 0;
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -176,13 +165,14 @@ static void sx1_init(ram_addr_t ram_size,
 
     if ((version == 1) &&
             (dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
-        cpu_register_physical_memory(OMAP_CS1_BASE, flash1_size,
-                                     qemu_ram_alloc(NULL, "omap_sx1.flash1-0",
-                                                    flash1_size) | IO_MEM_ROM);
-        io = cpu_register_io_memory(static_readfn, static_writefn, &cs1val,
-                                    DEVICE_NATIVE_ENDIAN);
-        cpu_register_physical_memory(OMAP_CS1_BASE + flash1_size,
-                        OMAP_CS1_SIZE - flash1_size, io);
+        memory_region_init_ram(flash_1, NULL, "omap_sx1.flash1-0", flash1_size);
+        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,
+                              "sx1.cs1", OMAP_CS1_SIZE - flash1_size);
+        memory_region_add_subregion(address_space,
+                                OMAP_CS1_BASE + flash1_size, &cs[1]);
 
         if (!pflash_cfi01_register(OMAP_CS1_BASE, NULL,
                                    "omap_sx1.flash1-1", flash1_size,
@@ -194,9 +184,10 @@ static void sx1_init(ram_addr_t ram_size,
         }
         fl_idx++;
     } else {
-        io = cpu_register_io_memory(static_readfn, static_writefn, &cs1val,
-                                    DEVICE_NATIVE_ENDIAN);
-        cpu_register_physical_memory(OMAP_CS1_BASE, OMAP_CS1_SIZE, io);
+        memory_region_init_io(&cs[1], &static_ops, &cs1val,
+                              "sx1.cs1", OMAP_CS1_SIZE);
+        memory_region_add_subregion(address_space,
+                                OMAP_CS1_BASE, &cs[1]);
     }
 
     if (!kernel_filename && !fl_idx) {
diff --git a/hw/omap_synctimer.c b/hw/omap_synctimer.c
index b47ca88195..367f26e3a1 100644
--- a/hw/omap_synctimer.c
+++ b/hw/omap_synctimer.c
@@ -21,6 +21,7 @@
 #include "qemu-timer.h"
 #include "omap.h"
 struct omap_synctimer_s {
+    MemoryRegion iomem;
     uint32_t val;
     uint16_t readh;
 };
@@ -65,22 +66,26 @@ static uint32_t omap_synctimer_readh(void *opaque, target_phys_addr_t addr)
     }
 }
 
-static CPUReadMemoryFunc * const omap_synctimer_readfn[] = {
-    omap_badwidth_read32,
-    omap_synctimer_readh,
-    omap_synctimer_readw,
-};
-
 static void omap_synctimer_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
     OMAP_BAD_REG(addr);
 }
 
-static CPUWriteMemoryFunc * const omap_synctimer_writefn[] = {
-    omap_badwidth_write32,
-    omap_synctimer_write,
-    omap_synctimer_write,
+static const MemoryRegionOps omap_synctimer_ops = {
+    .old_mmio = {
+        .read = {
+            omap_badwidth_read32,
+            omap_synctimer_readh,
+            omap_synctimer_readw,
+        },
+        .write = {
+            omap_badwidth_write32,
+            omap_synctimer_write,
+            omap_synctimer_write,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta,
@@ -89,8 +94,9 @@ struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta,
     struct omap_synctimer_s *s = g_malloc0(sizeof(*s));
 
     omap_synctimer_reset(s);
-    omap_l4_attach(ta, 0, l4_register_io_memory(
-                      omap_synctimer_readfn, omap_synctimer_writefn, s));
+    memory_region_init_io(&s->iomem, &omap_synctimer_ops, s, "omap.synctimer",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &s->iomem);
 
     return s;
 }
diff --git a/hw/omap_tap.c b/hw/omap_tap.c
index 1f18dddb22..0277c73652 100644
--- a/hw/omap_tap.c
+++ b/hw/omap_tap.c
@@ -22,10 +22,15 @@
 #include "omap.h"
 
 /* TEST-Chip-level TAP */
-static uint32_t omap_tap_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_tap_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x204:	/* IDCODE_reg */
         switch (s->mpu_model) {
@@ -87,26 +92,25 @@ static uint32_t omap_tap_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_tap_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                           uint64_t value, unsigned size)
 {
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     OMAP_BAD_REG(addr);
 }
 
-static CPUReadMemoryFunc * const omap_tap_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_tap_read,
-};
-
-static CPUWriteMemoryFunc * const omap_tap_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_tap_write,
+static const MemoryRegionOps omap_tap_ops = {
+    .read = omap_tap_read,
+    .write = omap_tap_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 void omap_tap_init(struct omap_target_agent_s *ta,
                 struct omap_mpu_state_s *mpu)
 {
-    omap_l4_attach(ta, 0, l4_register_io_memory(
-                            omap_tap_readfn, omap_tap_writefn, mpu));
+    memory_region_init_io(&mpu->tap_iomem, &omap_tap_ops, mpu, "omap.tap",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &mpu->tap_iomem);
 }
diff --git a/hw/omap_uart.c b/hw/omap_uart.c
index 19f8e6eec9..167d5c4e50 100644
--- a/hw/omap_uart.c
+++ b/hw/omap_uart.c
@@ -26,6 +26,7 @@
 
 /* UARTs */
 struct omap_uart_s {
+    MemoryRegion iomem;
     target_phys_addr_t base;
     SerialState *serial; /* TODO */
     struct omap_target_agent_s *ta;
@@ -68,11 +69,15 @@ struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
     return s;
 }
 
-static uint32_t omap_uart_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_uart_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_uart_s *s = (struct omap_uart_s *) opaque;
 
-    addr &= 0xff;
+    if (size == 4) {
+        return omap_badwidth_read8(opaque, addr);
+    }
+
     switch (addr) {
     case 0x20:	/* MDR1 */
         return s->mdr[0];
@@ -103,11 +108,14 @@ static uint32_t omap_uart_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_uart_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_uart_s *s = (struct omap_uart_s *) opaque;
 
-    addr &= 0xff;
+    if (size == 4) {
+        return omap_badwidth_write8(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x20:	/* MDR1 */
         s->mdr[0] = value & 0x7f;
@@ -145,32 +153,27 @@ static void omap_uart_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_uart_readfn[] = {
-    omap_uart_read,
-    omap_uart_read,
-    omap_badwidth_read8,
+static const MemoryRegionOps omap_uart_ops = {
+    .read = omap_uart_read,
+    .write = omap_uart_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const omap_uart_writefn[] = {
-    omap_uart_write,
-    omap_uart_write,
-    omap_badwidth_write8,
-};
-
-struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta,
+struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem,
+                struct omap_target_agent_s *ta,
                 qemu_irq irq, omap_clk fclk, omap_clk iclk,
                 qemu_irq txdma, qemu_irq rxdma,
                 const char *label, CharDriverState *chr)
 {
-    target_phys_addr_t base = omap_l4_attach(ta, 0, 0);
+    target_phys_addr_t base = omap_l4_attach(ta, 0, NULL);
     struct omap_uart_s *s = omap_uart_init(base, irq,
                     fclk, iclk, txdma, rxdma, label, chr);
-    int iomemtype = cpu_register_io_memory(omap_uart_readfn,
-                    omap_uart_writefn, s, DEVICE_NATIVE_ENDIAN);
+
+    memory_region_init_io(&s->iomem, &omap_uart_ops, s, "omap.uart", 0x100);
 
     s->ta = ta;
 
-    cpu_register_physical_memory(base + 0x20, 0x100, iomemtype);
+    memory_region_add_subregion(sysmem, base + 0x20, &s->iomem);
 
     return s;
 }
diff --git a/hw/onenand.c b/hw/onenand.c
index 7898da9321..a9d8d677ee 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -791,7 +791,7 @@ static int onenand_initfn(SysBusDevice *dev)
     s->data[1][1] = ram + ((0x8010 + (1 << (PAGE_SHIFT - 6))) << s->shift);
     onenand_mem_setup(s);
     sysbus_init_irq(dev, &s->intr);
-    sysbus_init_mmio_region(dev, &s->container);
+    sysbus_init_mmio(dev, &s->container);
     vmstate_register(&dev->qdev,
                      ((s->shift & 0x7f) << 24)
                      | ((s->id.man & 0xff) << 16)
diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c
index 2c1e475395..f7cc1b403b 100644
--- a/hw/opencores_eth.c
+++ b/hw/opencores_eth.c
@@ -708,11 +708,11 @@ static int sysbus_open_eth_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->reg_io, &open_eth_reg_ops, s,
             "open_eth.regs", 0x54);
-    sysbus_init_mmio_region(dev, &s->reg_io);
+    sysbus_init_mmio(dev, &s->reg_io);
 
     memory_region_init_io(&s->desc_io, &open_eth_desc_ops, s,
             "open_eth.desc", 0x400);
-    sysbus_init_mmio_region(dev, &s->desc_io);
+    sysbus_init_mmio(dev, &s->desc_io);
 
     sysbus_init_irq(dev, &s->irq);
 
diff --git a/hw/parallel.c b/hw/parallel.c
index 8494d94f69..c4c5dbee5b 100644
--- a/hw/parallel.c
+++ b/hw/parallel.c
@@ -65,6 +65,7 @@
 #define PARA_CTR_SIGNAL (PARA_CTR_SELECT|PARA_CTR_INIT|PARA_CTR_AUTOLF|PARA_CTR_STROBE)
 
 typedef struct ParallelState {
+    MemoryRegion iomem;
     uint8_t dataw;
     uint8_t datar;
     uint8_t status;
@@ -555,24 +556,20 @@ static void parallel_mm_writel (void *opaque,
     parallel_ioport_write_sw(s, addr >> s->it_shift, value);
 }
 
-static CPUReadMemoryFunc * const parallel_mm_read_sw[] = {
-    &parallel_mm_readb,
-    &parallel_mm_readw,
-    &parallel_mm_readl,
-};
-
-static CPUWriteMemoryFunc * const parallel_mm_write_sw[] = {
-    &parallel_mm_writeb,
-    &parallel_mm_writew,
-    &parallel_mm_writel,
+static const MemoryRegionOps parallel_mm_ops = {
+    .old_mmio = {
+        .read = { parallel_mm_readb, parallel_mm_readw, parallel_mm_readl },
+        .write = { parallel_mm_writeb, parallel_mm_writew, parallel_mm_writel },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 /* If fd is zero, it means that the parallel device uses the console */
-bool parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
+bool parallel_mm_init(MemoryRegion *address_space,
+                      target_phys_addr_t base, int it_shift, qemu_irq irq,
                       CharDriverState *chr)
 {
     ParallelState *s;
-    int io_sw;
 
     s = g_malloc0(sizeof(ParallelState));
     s->irq = irq;
@@ -580,9 +577,9 @@ bool parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
     s->it_shift = it_shift;
     qemu_register_reset(parallel_reset, s);
 
-    io_sw = cpu_register_io_memory(parallel_mm_read_sw, parallel_mm_write_sw,
-                                   s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 8 << it_shift, io_sw);
+    memory_region_init_io(&s->iomem, &parallel_mm_ops, s,
+                          "parallel", 8 << it_shift);
+    memory_region_add_subregion(address_space, base, &s->iomem);
     return true;
 }
 
diff --git a/hw/pc.h b/hw/pc.h
index 4515006381..b7b7e40ce7 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -55,7 +55,8 @@ static inline bool parallel_init(int index, CharDriverState *chr)
     return true;
 }
 
-bool parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
+bool parallel_mm_init(MemoryRegion *address_space,
+                      target_phys_addr_t base, int it_shift, qemu_irq irq,
                       CharDriverState *chr);
 
 /* i8259.c */
diff --git a/hw/pci_host.h b/hw/pci_host.h
index 0211086d70..359e38f63b 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -34,6 +34,7 @@ struct PCIHostState {
     SysBusDevice busdev;
     MemoryRegion conf_mem;
     MemoryRegion data_mem;
+    MemoryRegion mmcfg;
     MemoryRegion *address_space;
     uint32_t config_reg;
     PCIBus *bus;
diff --git a/hw/pl011.c b/hw/pl011.c
index 707a161046..1b05d76a78 100644
--- a/hw/pl011.c
+++ b/hw/pl011.c
@@ -12,6 +12,7 @@
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t readbuff;
     uint32_t flags;
     uint32_t lcr;
@@ -53,7 +54,8 @@ static void pl011_update(pl011_state *s)
     qemu_set_irq(s->irq, flags != 0);
 }
 
-static uint32_t pl011_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl011_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl011_state *s = (pl011_state *)opaque;
     uint32_t c;
@@ -123,7 +125,7 @@ static void pl011_set_read_trigger(pl011_state *s)
 }
 
 static void pl011_write(void *opaque, target_phys_addr_t offset,
-                          uint32_t value)
+                        uint64_t value, unsigned size)
 {
     pl011_state *s = (pl011_state *)opaque;
     unsigned char ch;
@@ -223,16 +225,10 @@ static void pl011_event(void *opaque, int event)
         pl011_put_fifo(opaque, 0x400);
 }
 
-static CPUReadMemoryFunc * const pl011_readfn[] = {
-   pl011_read,
-   pl011_read,
-   pl011_read
-};
-
-static CPUWriteMemoryFunc * const pl011_writefn[] = {
-   pl011_write,
-   pl011_write,
-   pl011_write
+static const MemoryRegionOps pl011_ops = {
+    .read = pl011_read,
+    .write = pl011_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_pl011 = {
@@ -262,13 +258,10 @@ static const VMStateDescription vmstate_pl011 = {
 
 static int pl011_init(SysBusDevice *dev, const unsigned char *id)
 {
-    int iomemtype;
     pl011_state *s = FROM_SYSBUS(pl011_state, dev);
 
-    iomemtype = cpu_register_io_memory(pl011_readfn,
-                                       pl011_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000,iomemtype);
+    memory_region_init_io(&s->iomem, &pl011_ops, s, "pl011", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     s->id = id;
     s->chr = qdev_init_chardev(&dev->qdev);
diff --git a/hw/pl022.c b/hw/pl022.c
index 9a1cb710f3..d43e4a29da 100644
--- a/hw/pl022.c
+++ b/hw/pl022.c
@@ -42,6 +42,7 @@ do { fprintf(stderr, "pl022: error: " fmt , ## __VA_ARGS__);} while (0)
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t cr0;
     uint32_t cr1;
     uint32_t bitmask;
@@ -130,7 +131,8 @@ static void pl022_xfer(pl022_state *s)
     pl022_update(s);
 }
 
-static uint32_t pl022_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl022_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl022_state *s = (pl022_state *)opaque;
     int val;
@@ -173,7 +175,7 @@ static uint32_t pl022_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pl022_write(void *opaque, target_phys_addr_t offset,
-                        uint32_t value)
+                        uint64_t value, unsigned size)
 {
     pl022_state *s = (pl022_state *)opaque;
 
@@ -193,7 +195,7 @@ static void pl022_write(void *opaque, target_phys_addr_t offset,
         break;
     case 0x08: /* DR */
         if (s->tx_fifo_len < 8) {
-            DPRINTF("TX %02x\n", value);
+            DPRINTF("TX %02x\n", (unsigned)value);
             s->tx_fifo[s->tx_fifo_head] = value & s->bitmask;
             s->tx_fifo_head = (s->tx_fifo_head + 1) & 7;
             s->tx_fifo_len++;
@@ -227,16 +229,10 @@ static void pl022_reset(pl022_state *s)
     s->sr = PL022_SR_TFE | PL022_SR_TNF;
 }
 
-static CPUReadMemoryFunc * const pl022_readfn[] = {
-   pl022_read,
-   pl022_read,
-   pl022_read
-};
-
-static CPUWriteMemoryFunc * const pl022_writefn[] = {
-   pl022_write,
-   pl022_write,
-   pl022_write
+static const MemoryRegionOps pl022_ops = {
+    .read = pl022_read,
+    .write = pl022_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_pl022 = {
@@ -279,12 +275,9 @@ static const VMStateDescription vmstate_pl022 = {
 static int pl022_init(SysBusDevice *dev)
 {
     pl022_state *s = FROM_SYSBUS(pl022_state, dev);
-    int iomemtype;
 
-    iomemtype = cpu_register_io_memory(pl022_readfn,
-                                       pl022_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &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");
     pl022_reset(s);
diff --git a/hw/pl031.c b/hw/pl031.c
index 017a313fda..a007ff0ff2 100644
--- a/hw/pl031.c
+++ b/hw/pl031.c
@@ -32,6 +32,7 @@ do { printf("pl031: " fmt , ## __VA_ARGS__); } while (0)
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     QEMUTimer *timer;
     qemu_irq irq;
 
@@ -105,7 +106,8 @@ static void pl031_set_alarm(pl031_state *s)
     }
 }
 
-static uint32_t pl031_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl031_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl031_state *s = (pl031_state *)opaque;
 
@@ -141,7 +143,7 @@ static uint32_t pl031_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pl031_write(void * opaque, target_phys_addr_t offset,
-                        uint32_t value)
+                        uint64_t value, unsigned size)
 {
     pl031_state *s = (pl031_state *)opaque;
 
@@ -186,31 +188,19 @@ static void pl031_write(void * opaque, target_phys_addr_t offset,
     }
 }
 
-static CPUWriteMemoryFunc * const  pl031_writefn[] = {
-    pl031_write,
-    pl031_write,
-    pl031_write
-};
-
-static CPUReadMemoryFunc * const  pl031_readfn[] = {
-    pl031_read,
-    pl031_read,
-    pl031_read
+static const MemoryRegionOps pl031_ops = {
+    .read = pl031_read,
+    .write = pl031_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int pl031_init(SysBusDevice *dev)
 {
-    int iomemtype;
     pl031_state *s = FROM_SYSBUS(pl031_state, dev);
     struct tm tm;
 
-    iomemtype = cpu_register_io_memory(pl031_readfn, pl031_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    if (iomemtype == -1) {
-        hw_error("pl031_init: Can't register I/O memory\n");
-    }
-
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &pl031_ops, s, "pl031", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
 
     sysbus_init_irq(dev, &s->irq);
     /* ??? We assume vm_clock is zero at this point.  */
diff --git a/hw/pl041.c b/hw/pl041.c
index efd52ac42f..d8e55d1ef2 100644
--- a/hw/pl041.c
+++ b/hw/pl041.c
@@ -543,7 +543,7 @@ static int pl041_init(SysBusDevice *dev)
 
     /* Connect the device to the sysbus */
     memory_region_init_io(&s->iomem, &pl041_ops, s, "pl041", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
     /* Init the codec */
diff --git a/hw/pl050.c b/hw/pl050.c
index f7fa2e253c..8182a1c82d 100644
--- a/hw/pl050.c
+++ b/hw/pl050.c
@@ -12,6 +12,7 @@
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     void *dev;
     uint32_t cr;
     uint32_t clk;
@@ -57,7 +58,8 @@ static void pl050_update(void *opaque, int level)
     qemu_set_irq(s->irq, raise);
 }
 
-static uint32_t pl050_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl050_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl050_state *s = (pl050_state *)opaque;
     if (offset >= 0xfe0 && offset < 0x1000)
@@ -99,7 +101,7 @@ static uint32_t pl050_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pl050_write(void *opaque, target_phys_addr_t offset,
-                          uint32_t value)
+                        uint64_t value, unsigned size)
 {
     pl050_state *s = (pl050_state *)opaque;
     switch (offset >> 2) {
@@ -124,27 +126,18 @@ static void pl050_write(void *opaque, target_phys_addr_t offset,
         hw_error("pl050_write: Bad offset %x\n", (int)offset);
     }
 }
-static CPUReadMemoryFunc * const pl050_readfn[] = {
-   pl050_read,
-   pl050_read,
-   pl050_read
-};
-
-static CPUWriteMemoryFunc * const pl050_writefn[] = {
-   pl050_write,
-   pl050_write,
-   pl050_write
+static const MemoryRegionOps pl050_ops = {
+    .read = pl050_read,
+    .write = pl050_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int pl050_init(SysBusDevice *dev, int is_mouse)
 {
     pl050_state *s = FROM_SYSBUS(pl050_state, dev);
-    int iomemtype;
 
-    iomemtype = cpu_register_io_memory(pl050_readfn,
-                                       pl050_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &pl050_ops, s, "pl050", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     s->is_mouse = is_mouse;
     if (s->is_mouse)
diff --git a/hw/pl061.c b/hw/pl061.c
index cf5adbe1fb..f33ae84408 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -30,6 +30,7 @@ static const uint8_t pl061_id_luminary[12] =
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t locked;
     uint32_t data;
     uint32_t old_data;
@@ -112,7 +113,8 @@ static void pl061_update(pl061_state *s)
     /* FIXME: Implement input interrupts.  */
 }
 
-static uint32_t pl061_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl061_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl061_state *s = (pl061_state *)opaque;
 
@@ -168,7 +170,7 @@ static uint32_t pl061_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pl061_write(void *opaque, target_phys_addr_t offset,
-                        uint32_t value)
+                        uint64_t value, unsigned size)
 {
     pl061_state *s = (pl061_state *)opaque;
     uint8_t mask;
@@ -262,27 +264,18 @@ static void pl061_set_irq(void * opaque, int irq, int level)
     }
 }
 
-static CPUReadMemoryFunc * const pl061_readfn[] = {
-   pl061_read,
-   pl061_read,
-   pl061_read
-};
-
-static CPUWriteMemoryFunc * const pl061_writefn[] = {
-   pl061_write,
-   pl061_write,
-   pl061_write
+static const MemoryRegionOps pl061_ops = {
+    .read = pl061_read,
+    .write = pl061_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int pl061_init(SysBusDevice *dev, const unsigned char *id)
 {
-    int iomemtype;
     pl061_state *s = FROM_SYSBUS(pl061_state, dev);
     s->id = id;
-    iomemtype = cpu_register_io_memory(pl061_readfn,
-                                       pl061_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &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);
     qdev_init_gpio_out(&dev->qdev, s->out, 8);
diff --git a/hw/pl080.c b/hw/pl080.c
index 5ba3b0859b..e001df92e0 100644
--- a/hw/pl080.c
+++ b/hw/pl080.c
@@ -37,6 +37,7 @@ typedef struct {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint8_t tc_int;
     uint8_t tc_mask;
     uint8_t err_int;
@@ -217,7 +218,8 @@ again:
     }
 }
 
-static uint32_t pl080_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl080_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl080_state *s = (pl080_state *)opaque;
     uint32_t i;
@@ -285,7 +287,7 @@ static uint32_t pl080_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pl080_write(void *opaque, target_phys_addr_t offset,
-                          uint32_t value)
+                        uint64_t value, unsigned size)
 {
     pl080_state *s = (pl080_state *)opaque;
     int i;
@@ -344,27 +346,18 @@ static void pl080_write(void *opaque, target_phys_addr_t offset,
     pl080_update(s);
 }
 
-static CPUReadMemoryFunc * const pl080_readfn[] = {
-   pl080_read,
-   pl080_read,
-   pl080_read
-};
-
-static CPUWriteMemoryFunc * const pl080_writefn[] = {
-   pl080_write,
-   pl080_write,
-   pl080_write
+static const MemoryRegionOps pl080_ops = {
+    .read = pl080_read,
+    .write = pl080_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int pl08x_init(SysBusDevice *dev, int nchannels)
 {
-    int iomemtype;
     pl080_state *s = FROM_SYSBUS(pl080_state, dev);
 
-    iomemtype = cpu_register_io_memory(pl080_readfn,
-                                       pl080_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &pl080_ops, s, "pl080", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     s->nchannels = nchannels;
     return 0;
diff --git a/hw/pl110.c b/hw/pl110.c
index 4ac710a6ec..7aef8a4e25 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -40,6 +40,7 @@ enum pl110_version
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     DisplayState *ds;
 
     int version;
@@ -301,7 +302,8 @@ static void pl110_update(pl110_state *s)
   /* TODO: Implement interrupts.  */
 }
 
-static uint32_t pl110_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl110_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl110_state *s = (pl110_state *)opaque;
 
@@ -350,7 +352,7 @@ static uint32_t pl110_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pl110_write(void *opaque, target_phys_addr_t offset,
-                        uint32_t val)
+                        uint64_t val, unsigned size)
 {
     pl110_state *s = (pl110_state *)opaque;
     int n;
@@ -416,16 +418,10 @@ static void pl110_write(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static CPUReadMemoryFunc * const pl110_readfn[] = {
-   pl110_read,
-   pl110_read,
-   pl110_read
-};
-
-static CPUWriteMemoryFunc * const pl110_writefn[] = {
-   pl110_write,
-   pl110_write,
-   pl110_write
+static const MemoryRegionOps pl110_ops = {
+    .read = pl110_read,
+    .write = pl110_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void pl110_mux_ctrl_set(void *opaque, int line, int level)
@@ -437,12 +433,9 @@ static void pl110_mux_ctrl_set(void *opaque, int line, int level)
 static int pl110_init(SysBusDevice *dev)
 {
     pl110_state *s = FROM_SYSBUS(pl110_state, dev);
-    int iomemtype;
 
-    iomemtype = cpu_register_io_memory(pl110_readfn,
-                                       pl110_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &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);
     s->ds = graphic_console_init(pl110_update_display,
diff --git a/hw/pl181.c b/hw/pl181.c
index 0943c09eca..46855f69de 100644
--- a/hw/pl181.c
+++ b/hw/pl181.c
@@ -24,6 +24,7 @@ do { printf("pl181: " fmt , ## __VA_ARGS__); } while (0)
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     SDState *card;
     uint32_t clock;
     uint32_t power;
@@ -259,7 +260,8 @@ static void pl181_fifo_run(pl181_state *s)
     }
 }
 
-static uint32_t pl181_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl181_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl181_state *s = (pl181_state *)opaque;
     uint32_t tmp;
@@ -342,7 +344,7 @@ static uint32_t pl181_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pl181_write(void *opaque, target_phys_addr_t offset,
-                          uint32_t value)
+                        uint64_t value, unsigned size)
 {
     pl181_state *s = (pl181_state *)opaque;
 
@@ -412,16 +414,10 @@ static void pl181_write(void *opaque, target_phys_addr_t offset,
     pl181_update(s);
 }
 
-static CPUReadMemoryFunc * const pl181_readfn[] = {
-   pl181_read,
-   pl181_read,
-   pl181_read
-};
-
-static CPUWriteMemoryFunc * const pl181_writefn[] = {
-   pl181_write,
-   pl181_write,
-   pl181_write
+static const MemoryRegionOps pl181_ops = {
+    .read = pl181_read,
+    .write = pl181_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void pl181_reset(void *opaque)
@@ -453,13 +449,11 @@ static void pl181_reset(void *opaque)
 
 static int pl181_init(SysBusDevice *dev)
 {
-    int iomemtype;
     pl181_state *s = FROM_SYSBUS(pl181_state, dev);
     DriveInfo *dinfo;
 
-    iomemtype = cpu_register_io_memory(pl181_readfn, pl181_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &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]);
     qdev_init_gpio_out(&s->busdev.qdev, s->cardstatus, 2);
diff --git a/hw/pl190.c b/hw/pl190.c
index 8dc7e42861..6fc2656f69 100644
--- a/hw/pl190.c
+++ b/hw/pl190.c
@@ -17,6 +17,7 @@
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t level;
     uint32_t soft_level;
     uint32_t irq_enable;
@@ -84,7 +85,8 @@ static void pl190_update_vectors(pl190_state *s)
     pl190_update(s);
 }
 
-static uint32_t pl190_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl190_read(void *opaque, target_phys_addr_t offset,
+                           unsigned size)
 {
     pl190_state *s = (pl190_state *)opaque;
     int i;
@@ -140,7 +142,8 @@ static uint32_t pl190_read(void *opaque, target_phys_addr_t offset)
     }
 }
 
-static void pl190_write(void *opaque, target_phys_addr_t offset, uint32_t val)
+static void pl190_write(void *opaque, target_phys_addr_t offset,
+                        uint64_t val, unsigned size)
 {
     pl190_state *s = (pl190_state *)opaque;
 
@@ -199,16 +202,10 @@ static void pl190_write(void *opaque, target_phys_addr_t offset, uint32_t val)
     pl190_update(s);
 }
 
-static CPUReadMemoryFunc * const pl190_readfn[] = {
-   pl190_read,
-   pl190_read,
-   pl190_read
-};
-
-static CPUWriteMemoryFunc * const pl190_writefn[] = {
-   pl190_write,
-   pl190_write,
-   pl190_write
+static const MemoryRegionOps pl190_ops = {
+    .read = pl190_read,
+    .write = pl190_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void pl190_reset(DeviceState *d)
@@ -230,12 +227,9 @@ static void pl190_reset(DeviceState *d)
 static int pl190_init(SysBusDevice *dev)
 {
     pl190_state *s = FROM_SYSBUS(pl190_state, dev);
-    int iomemtype;
 
-    iomemtype = cpu_register_io_memory(pl190_readfn,
-                                       pl190_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &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);
     sysbus_init_irq(dev, &s->fiq);
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index 339b38ec7a..2c69210225 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -54,6 +54,8 @@ struct PPC4xxPCIState {
 
     PCIHostState pci_state;
     PCIDevice *pci_dev;
+    MemoryRegion iomem_addr;
+    MemoryRegion iomem_regs;
 };
 typedef struct PPC4xxPCIState PPC4xxPCIState;
 
@@ -84,35 +86,30 @@ typedef struct PPC4xxPCIState PPC4xxPCIState;
 #define PCI_REG_SIZE        0x40
 
 
-static uint32_t pci4xx_cfgaddr_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t pci4xx_cfgaddr_read(void *opaque, target_phys_addr_t addr,
+                                    unsigned size)
 {
     PPC4xxPCIState *ppc4xx_pci = opaque;
 
     return ppc4xx_pci->pci_state.config_reg;
 }
 
-static CPUReadMemoryFunc * const pci4xx_cfgaddr_read[] = {
-    &pci4xx_cfgaddr_readl,
-    &pci4xx_cfgaddr_readl,
-    &pci4xx_cfgaddr_readl,
-};
-
-static void pci4xx_cfgaddr_writel(void *opaque, target_phys_addr_t addr,
-                                  uint32_t value)
+static void pci4xx_cfgaddr_write(void *opaque, target_phys_addr_t addr,
+                                  uint64_t value, unsigned size)
 {
     PPC4xxPCIState *ppc4xx_pci = opaque;
 
     ppc4xx_pci->pci_state.config_reg = value & ~0x3;
 }
 
-static CPUWriteMemoryFunc * const pci4xx_cfgaddr_write[] = {
-    &pci4xx_cfgaddr_writel,
-    &pci4xx_cfgaddr_writel,
-    &pci4xx_cfgaddr_writel,
+static const MemoryRegionOps pci4xx_cfgaddr_ops = {
+    .read = pci4xx_cfgaddr_read,
+    .write = pci4xx_cfgaddr_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static void ppc4xx_pci_reg_write4(void *opaque, target_phys_addr_t offset,
-                                  uint32_t value)
+                                  uint64_t value, unsigned size)
 {
     struct PPC4xxPCIState *pci = opaque;
 
@@ -179,7 +176,8 @@ static void ppc4xx_pci_reg_write4(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static uint32_t ppc4xx_pci_reg_read4(void *opaque, target_phys_addr_t offset)
+static uint64_t ppc4xx_pci_reg_read4(void *opaque, target_phys_addr_t offset,
+                                     unsigned size)
 {
     struct PPC4xxPCIState *pci = opaque;
     uint32_t value;
@@ -246,16 +244,10 @@ static uint32_t ppc4xx_pci_reg_read4(void *opaque, target_phys_addr_t offset)
     return value;
 }
 
-static CPUReadMemoryFunc * const pci_reg_read[] = {
-    &ppc4xx_pci_reg_read4,
-    &ppc4xx_pci_reg_read4,
-    &ppc4xx_pci_reg_read4,
-};
-
-static CPUWriteMemoryFunc * const pci_reg_write[] = {
-    &ppc4xx_pci_reg_write4,
-    &ppc4xx_pci_reg_write4,
-    &ppc4xx_pci_reg_write4,
+static const MemoryRegionOps pci_reg_ops = {
+    .read = ppc4xx_pci_reg_read4,
+    .write = ppc4xx_pci_reg_write4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static void ppc4xx_pci_reset(void *opaque)
@@ -337,7 +329,6 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
                         target_phys_addr_t registers)
 {
     PPC4xxPCIState *controller;
-    int index;
     static int ppc4xx_pci_id;
     uint8_t *pci_conf;
 
@@ -360,12 +351,11 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
     pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_OTHER);
 
     /* CFGADDR */
-    index = cpu_register_io_memory(pci4xx_cfgaddr_read,
-                                   pci4xx_cfgaddr_write, controller,
-                                   DEVICE_LITTLE_ENDIAN);
-    if (index < 0)
-        goto free;
-    cpu_register_physical_memory(config_space + PCIC0_CFGADDR, 4, index);
+    memory_region_init_io(&controller->iomem_addr, &pci4xx_cfgaddr_ops,
+                          controller, "pci.cfgaddr", 4);
+    memory_region_add_subregion(get_system_memory(),
+                                config_space + PCIC0_CFGADDR,
+                                &controller->iomem_addr);
 
     /* CFGDATA */
     memory_region_init_io(&controller->pci_state.data_mem,
@@ -376,11 +366,10 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
                                 &controller->pci_state.data_mem);
 
     /* Internal registers */
-    index = cpu_register_io_memory(pci_reg_read, pci_reg_write, controller,
-                                   DEVICE_LITTLE_ENDIAN);
-    if (index < 0)
-        goto free;
-    cpu_register_physical_memory(registers, PCI_REG_SIZE, index);
+    memory_region_init_io(&controller->iomem_regs, &pci_reg_ops, controller,
+                          "pci.regs", PCI_REG_SIZE);
+    memory_region_add_subregion(get_system_memory(), registers,
+                                &controller->iomem_regs);
 
     qemu_register_reset(ppc4xx_pci_reset, controller);
 
@@ -389,9 +378,4 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
                      &vmstate_ppc4xx_pci, controller);
 
     return controller->pci_state.bus;
-
-free:
-    printf("%s error\n", __func__);
-    g_free(controller);
-    return NULL;
 }
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 960a5d0c60..6232af19fa 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -79,12 +79,13 @@ struct PPCE500PCIState {
     uint32_t gasket_time;
     qemu_irq irq[4];
     /* mmio maps */
-    int reg;
+    MemoryRegion iomem;
 };
 
 typedef struct PPCE500PCIState PPCE500PCIState;
 
-static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
+static uint64_t pci_reg_read4(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     PPCE500PCIState *pci = opaque;
     unsigned long win;
@@ -152,14 +153,8 @@ static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
     return value;
 }
 
-static CPUReadMemoryFunc * const e500_pci_reg_read[] = {
-    &pci_reg_read4,
-    &pci_reg_read4,
-    &pci_reg_read4,
-};
-
 static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
-                               uint32_t value)
+                           uint64_t value, unsigned size)
 {
     PPCE500PCIState *pci = opaque;
     unsigned long win;
@@ -168,7 +163,7 @@ static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
     win = addr & 0xfe0;
 
     pci_debug("%s: value:%x -> win:%lx(addr:" TARGET_FMT_plx ")\n",
-              __func__, value, win, addr);
+              __func__, (unsigned)value, win, addr);
 
     switch (win) {
     case PPCE500_PCI_OW1:
@@ -225,10 +220,10 @@ static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
     };
 }
 
-static CPUWriteMemoryFunc * const e500_pci_reg_write[] = {
-    &pci_reg_write4,
-    &pci_reg_write4,
-    &pci_reg_write4,
+static const MemoryRegionOps e500_pci_reg_ops = {
+    .read = pci_reg_read4,
+    .write = pci_reg_write4,
+    .endianness = DEVICE_BIG_ENDIAN,
 };
 
 static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
@@ -310,18 +305,17 @@ static void e500_pci_map(SysBusDevice *dev, target_phys_addr_t base)
 
     sysbus_add_memory(dev, base + PCIE500_CFGADDR, &h->conf_mem);
     sysbus_add_memory(dev, base + PCIE500_CFGDATA, &h->data_mem);
-    cpu_register_physical_memory(base + PCIE500_REG_BASE, PCIE500_REG_SIZE,
-                                 s->reg);
+    sysbus_add_memory(dev, base + PCIE500_REG_BASE, &s->iomem);
 }
 
 static void e500_pci_unmap(SysBusDevice *dev, target_phys_addr_t base)
 {
     PCIHostState *h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
+    PPCE500PCIState *s = DO_UPCAST(PPCE500PCIState, pci_state, h);
 
     sysbus_del_memory(dev, &h->conf_mem);
     sysbus_del_memory(dev, &h->data_mem);
-    cpu_register_physical_memory(base + PCIE500_REG_BASE, PCIE500_REG_SIZE,
-                                 IO_MEM_UNASSIGNED);
+    sysbus_del_memory(dev, &s->iomem);
 }
 
 #include "exec-memory.h"
@@ -353,8 +347,8 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
                           "pci-conf-idx", 4);
     memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, h,
                           "pci-conf-data", 4);
-    s->reg = cpu_register_io_memory(e500_pci_reg_read, e500_pci_reg_write, s,
-                                    DEVICE_BIG_ENDIAN);
+    memory_region_init_io(&s->iomem, &e500_pci_reg_ops, s,
+                          "pci.reg", PCIE500_REG_SIZE);
     sysbus_init_mmio_cb2(dev, e500_pci_map, e500_pci_unmap);
 
     return 0;
diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c
index cccd94073a..df74953874 100644
--- a/hw/ppce500_spin.c
+++ b/hw/ppce500_spin.c
@@ -195,7 +195,7 @@ static int ppce500_spin_initfn(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &spin_rw_ops, s, "e500 spin pv device",
                           sizeof(SpinInfo) * MAX_CPUS);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     qemu_register_reset(spin_reset, s);
 
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index 149807a7d5..ea9fb6902c 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -86,16 +86,12 @@ static uint32_t PPC_PCIIO_readl (void *opaque, target_phys_addr_t addr)
     return val;
 }
 
-static CPUWriteMemoryFunc * const PPC_PCIIO_write[] = {
-    &PPC_PCIIO_writeb,
-    &PPC_PCIIO_writew,
-    &PPC_PCIIO_writel,
-};
-
-static CPUReadMemoryFunc * const PPC_PCIIO_read[] = {
-    &PPC_PCIIO_readb,
-    &PPC_PCIIO_readw,
-    &PPC_PCIIO_readl,
+static const MemoryRegionOps PPC_PCIIO_ops = {
+    .old_mmio = {
+        .read = { PPC_PCIIO_readb, PPC_PCIIO_readw, PPC_PCIIO_readl, },
+        .write = { PPC_PCIIO_writeb, PPC_PCIIO_writew, PPC_PCIIO_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int prep_map_irq(PCIDevice *pci_dev, int irq_num)
@@ -116,7 +112,6 @@ PCIBus *pci_prep_init(qemu_irq *pic,
 {
     PREPPCIState *s;
     PCIDevice *d;
-    int PPC_io_memory;
 
     s = g_malloc0(sizeof(PREPPCIState));
     s->bus = pci_register_bus(NULL, "pci",
@@ -135,10 +130,8 @@ PCIBus *pci_prep_init(qemu_irq *pic,
     memory_region_add_subregion(address_space_io, 0xcfc, &s->data_mem);
     sysbus_init_ioports(&s->busdev, 0xcfc, 1);
 
-    PPC_io_memory = cpu_register_io_memory(PPC_PCIIO_read,
-                                           PPC_PCIIO_write, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(0x80800000, 0x00400000, PPC_io_memory);
+    memory_region_init_io(&s->mmcfg, &PPC_PCIIO_ops, s, "pciio", 0x00400000);
+    memory_region_add_subregion(address_space_mem, 0x80800000, &s->mmcfg);
 
     /* PCI host bridge */
     d = pci_register_device(s->bus, "PREP Host Bridge - Motorola Raven",
diff --git a/hw/pxa.h b/hw/pxa.h
index 7e9838408b..e7787393c7 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -78,14 +78,15 @@ DeviceState *pxa27x_dma_init(target_phys_addr_t base, qemu_irq irq);
 
 /* pxa2xx_lcd.c */
 typedef struct PXA2xxLCDState PXA2xxLCDState;
-PXA2xxLCDState *pxa2xx_lcdc_init(target_phys_addr_t base,
-                qemu_irq irq);
+PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
+                target_phys_addr_t base, qemu_irq irq);
 void pxa2xx_lcd_vsync_notifier(PXA2xxLCDState *s, qemu_irq handler);
 void pxa2xx_lcdc_oritentation(void *opaque, int angle);
 
 /* pxa2xx_mmci.c */
 typedef struct PXA2xxMMCIState PXA2xxMMCIState;
-PXA2xxMMCIState *pxa2xx_mmci_init(target_phys_addr_t base,
+PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
+                target_phys_addr_t base,
                 BlockDriverState *bd, qemu_irq irq,
                 qemu_irq rx_dma, qemu_irq tx_dma);
 void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly,
@@ -93,7 +94,8 @@ void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly,
 
 /* pxa2xx_pcmcia.c */
 typedef struct PXA2xxPCMCIAState PXA2xxPCMCIAState;
-PXA2xxPCMCIAState *pxa2xx_pcmcia_init(target_phys_addr_t base);
+PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
+                                      target_phys_addr_t base);
 int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card);
 int pxa2xx_pcmcia_dettach(void *opaque);
 void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq);
@@ -104,8 +106,9 @@ struct  keymap {
     int row;
 };
 typedef struct PXA2xxKeyPadState PXA2xxKeyPadState;
-PXA2xxKeyPadState *pxa27x_keypad_init(target_phys_addr_t base,
-                qemu_irq irq);
+PXA2xxKeyPadState *pxa27x_keypad_init(MemoryRegion *sysmem,
+                                      target_phys_addr_t base,
+                                      qemu_irq irq);
 void pxa27x_register_keypad(PXA2xxKeyPadState *kp, struct keymap *map,
                 int size);
 
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index e9a507ece5..bd177b76d4 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -813,7 +813,7 @@ static int pxa2xx_ssp_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
 
     memory_region_init_io(&s->iomem, &pxa2xx_ssp_ops, s, "pxa2xx-ssp", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     register_savevm(&dev->qdev, "pxa2xx_ssp", -1, 0,
                     pxa2xx_ssp_save, pxa2xx_ssp_load, s);
 
@@ -1180,7 +1180,7 @@ static int pxa2xx_rtc_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->rtc_irq);
 
     memory_region_init_io(&s->iomem, &pxa2xx_rtc_ops, s, "pxa2xx-rtc", 0x10000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
@@ -1515,7 +1515,7 @@ static int pxa2xx_i2c_initfn(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &pxa2xx_i2c_ops, s,
                           "pxa2xx-i2x", s->region_size);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
     return 0;
@@ -2072,7 +2072,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
         fprintf(stderr, "qemu: missing SecureDigital device\n");
         exit(1);
     }
-    s->mmc = pxa2xx_mmci_init(0x41100000, dinfo->bdrv,
+    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
                     qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
                     qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
@@ -2094,7 +2094,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
                         qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_ICP),
                         serial_hds[i]);
 
-    s->lcd = pxa2xx_lcdc_init(0x44000000,
+    s->lcd = pxa2xx_lcdc_init(address_space, 0x44000000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_LCD));
 
     s->cm_base = 0x41300000;
@@ -2133,8 +2133,8 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
                         qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
     }
 
-    s->pcmcia[0] = pxa2xx_pcmcia_init(0x20000000);
-    s->pcmcia[1] = pxa2xx_pcmcia_init(0x30000000);
+    s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
+    s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
 
     sysbus_create_simple("pxa2xx_rtc", 0x40900000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_RTCALARM));
@@ -2149,7 +2149,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
                     qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_I2S),
                     qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_I2S));
 
-    s->kp = pxa27x_keypad_init(0x41500000,
+    s->kp = pxa27x_keypad_init(address_space, 0x41500000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_KEYPAD));
 
     /* GPIO1 resets the processor */
@@ -2201,7 +2201,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
         fprintf(stderr, "qemu: missing SecureDigital device\n");
         exit(1);
     }
-    s->mmc = pxa2xx_mmci_init(0x41100000, dinfo->bdrv,
+    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
                     qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
                     qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
@@ -2223,7 +2223,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
                         qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_ICP),
                         serial_hds[i]);
 
-    s->lcd = pxa2xx_lcdc_init(0x44000000,
+    s->lcd = pxa2xx_lcdc_init(address_space, 0x44000000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_LCD));
 
     s->cm_base = 0x41300000;
@@ -2262,8 +2262,8 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
                         qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
     }
 
-    s->pcmcia[0] = pxa2xx_pcmcia_init(0x20000000);
-    s->pcmcia[1] = pxa2xx_pcmcia_init(0x30000000);
+    s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
+    s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
 
     sysbus_create_simple("pxa2xx_rtc", 0x40900000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_RTCALARM));
diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c
index 07ec2dbb66..cb281071f0 100644
--- a/hw/pxa2xx_dma.c
+++ b/hw/pxa2xx_dma.c
@@ -28,6 +28,7 @@ typedef struct {
 
 typedef struct PXA2xxDMAState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     qemu_irq irq;
 
     uint32_t stopintr;
@@ -250,11 +251,17 @@ static void pxa2xx_dma_run(PXA2xxDMAState *s)
     }
 }
 
-static uint32_t pxa2xx_dma_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pxa2xx_dma_read(void *opaque, target_phys_addr_t offset,
+                                unsigned size)
 {
     PXA2xxDMAState *s = (PXA2xxDMAState *) opaque;
     unsigned int channel;
 
+    if (size != 4) {
+        hw_error("%s: Bad access width\n", __FUNCTION__);
+        return 5;
+    }
+
     switch (offset) {
     case DRCMR64 ... DRCMR74:
         offset -= DRCMR64 - DRCMR0 - (64 << 2);
@@ -303,12 +310,17 @@ static uint32_t pxa2xx_dma_read(void *opaque, target_phys_addr_t offset)
     return 7;
 }
 
-static void pxa2xx_dma_write(void *opaque,
-                 target_phys_addr_t offset, uint32_t value)
+static void pxa2xx_dma_write(void *opaque, target_phys_addr_t offset,
+                             uint64_t value, unsigned size)
 {
     PXA2xxDMAState *s = (PXA2xxDMAState *) opaque;
     unsigned int channel;
 
+    if (size != 4) {
+        hw_error("%s: Bad access width\n", __FUNCTION__);
+        return;
+    }
+
     switch (offset) {
     case DRCMR64 ... DRCMR74:
         offset -= DRCMR64 - DRCMR0 - (64 << 2);
@@ -319,7 +331,7 @@ static void pxa2xx_dma_write(void *opaque,
         if (value & DRCMR_MAPVLD)
             if ((value & DRCMR_CHLNUM) > s->channels)
                 hw_error("%s: Bad DMA channel %i\n",
-                         __FUNCTION__, value & DRCMR_CHLNUM);
+                         __FUNCTION__, (unsigned)value & DRCMR_CHLNUM);
 
         s->req[channel] = value;
         break;
@@ -402,28 +414,10 @@ static void pxa2xx_dma_write(void *opaque,
     }
 }
 
-static uint32_t pxa2xx_dma_readbad(void *opaque, target_phys_addr_t offset)
-{
-    hw_error("%s: Bad access width\n", __FUNCTION__);
-    return 5;
-}
-
-static void pxa2xx_dma_writebad(void *opaque,
-                 target_phys_addr_t offset, uint32_t value)
-{
-    hw_error("%s: Bad access width\n", __FUNCTION__);
-}
-
-static CPUReadMemoryFunc * const pxa2xx_dma_readfn[] = {
-    pxa2xx_dma_readbad,
-    pxa2xx_dma_readbad,
-    pxa2xx_dma_read
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_dma_writefn[] = {
-    pxa2xx_dma_writebad,
-    pxa2xx_dma_writebad,
-    pxa2xx_dma_write
+static const MemoryRegionOps pxa2xx_dma_ops = {
+    .read = pxa2xx_dma_read,
+    .write = pxa2xx_dma_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void pxa2xx_dma_request(void *opaque, int req_num, int on)
@@ -453,7 +447,7 @@ static void pxa2xx_dma_request(void *opaque, int req_num, int on)
 
 static int pxa2xx_dma_init(SysBusDevice *dev)
 {
-    int i, iomemtype;
+    int i;
     PXA2xxDMAState *s;
     s = FROM_SYSBUS(PXA2xxDMAState, dev);
 
@@ -471,9 +465,9 @@ static int pxa2xx_dma_init(SysBusDevice *dev)
 
     qdev_init_gpio_in(&dev->qdev, pxa2xx_dma_request, PXA2XX_DMA_NUM_REQUESTS);
 
-    iomemtype = cpu_register_io_memory(pxa2xx_dma_readfn,
-                    pxa2xx_dma_writefn, s, DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x00010000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_dma_ops, s,
+                          "pxa2xx.dma", 0x00010000);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
     return 0;
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index 200b0cfe3a..cc58c40914 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -16,6 +16,7 @@
 typedef struct PXA2xxGPIOInfo PXA2xxGPIOInfo;
 struct PXA2xxGPIOInfo {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     qemu_irq irq0, irq1, irqX;
     int lines;
     int ncpu;
@@ -137,7 +138,8 @@ static void pxa2xx_gpio_handler_update(PXA2xxGPIOInfo *s) {
     }
 }
 
-static uint32_t pxa2xx_gpio_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pxa2xx_gpio_read(void *opaque, target_phys_addr_t offset,
+                                 unsigned size)
 {
     PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
     uint32_t ret;
@@ -188,8 +190,8 @@ static uint32_t pxa2xx_gpio_read(void *opaque, target_phys_addr_t offset)
     return 0;
 }
 
-static void pxa2xx_gpio_write(void *opaque,
-                target_phys_addr_t offset, uint32_t value)
+static void pxa2xx_gpio_write(void *opaque, target_phys_addr_t offset,
+                              uint64_t value, unsigned size)
 {
     PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
     int bank;
@@ -240,16 +242,10 @@ static void pxa2xx_gpio_write(void *opaque,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_gpio_readfn[] = {
-    pxa2xx_gpio_read,
-    pxa2xx_gpio_read,
-    pxa2xx_gpio_read
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_gpio_writefn[] = {
-    pxa2xx_gpio_write,
-    pxa2xx_gpio_write,
-    pxa2xx_gpio_write
+static const MemoryRegionOps pxa_gpio_ops = {
+    .read = pxa2xx_gpio_read,
+    .write = pxa2xx_gpio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
@@ -275,7 +271,6 @@ DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
 
 static int pxa2xx_gpio_initfn(SysBusDevice *dev)
 {
-    int iomemtype;
     PXA2xxGPIOInfo *s;
 
     s = FROM_SYSBUS(PXA2xxGPIOInfo, dev);
@@ -285,10 +280,8 @@ static int pxa2xx_gpio_initfn(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, pxa2xx_gpio_set, s->lines);
     qdev_init_gpio_out(&dev->qdev, s->handler, s->lines);
 
-    iomemtype = cpu_register_io_memory(pxa2xx_gpio_readfn,
-                    pxa2xx_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
-
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &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);
     sysbus_init_irq(dev, &s->irqX);
diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c
index e33959d25c..f86323fecf 100644
--- a/hw/pxa2xx_keypad.c
+++ b/hw/pxa2xx_keypad.c
@@ -80,6 +80,7 @@
 #define PXAKBD_MAXCOL   8
 
 struct PXA2xxKeyPadState {
+    MemoryRegion iomem;
     qemu_irq    irq;
     struct  keymap *map;
     int         pressed_cnt;
@@ -174,7 +175,8 @@ out:
     return;
 }
 
-static uint32_t pxa2xx_keypad_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pxa2xx_keypad_read(void *opaque, target_phys_addr_t offset,
+                                   unsigned size)
 {
     PXA2xxKeyPadState *s = (PXA2xxKeyPadState *) opaque;
     uint32_t tmp;
@@ -235,8 +237,8 @@ static uint32_t pxa2xx_keypad_read(void *opaque, target_phys_addr_t offset)
     return 0;
 }
 
-static void pxa2xx_keypad_write(void *opaque,
-                target_phys_addr_t offset, uint32_t value)
+static void pxa2xx_keypad_write(void *opaque, target_phys_addr_t offset,
+                                uint64_t value, unsigned size)
 {
     PXA2xxKeyPadState *s = (PXA2xxKeyPadState *) opaque;
 
@@ -277,16 +279,10 @@ static void pxa2xx_keypad_write(void *opaque,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_keypad_readfn[] = {
-    pxa2xx_keypad_read,
-    pxa2xx_keypad_read,
-    pxa2xx_keypad_read
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_keypad_writefn[] = {
-    pxa2xx_keypad_write,
-    pxa2xx_keypad_write,
-    pxa2xx_keypad_write
+static const MemoryRegionOps pxa2xx_keypad_ops = {
+    .read = pxa2xx_keypad_read,
+    .write = pxa2xx_keypad_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_pxa2xx_keypad = {
@@ -306,18 +302,18 @@ static const VMStateDescription vmstate_pxa2xx_keypad = {
     }
 };
 
-PXA2xxKeyPadState *pxa27x_keypad_init(target_phys_addr_t base,
-        qemu_irq irq)
+PXA2xxKeyPadState *pxa27x_keypad_init(MemoryRegion *sysmem,
+                                      target_phys_addr_t base,
+                                      qemu_irq irq)
 {
-    int iomemtype;
     PXA2xxKeyPadState *s;
 
     s = (PXA2xxKeyPadState *) g_malloc0(sizeof(PXA2xxKeyPadState));
     s->irq = irq;
 
-    iomemtype = cpu_register_io_memory(pxa2xx_keypad_readfn,
-                    pxa2xx_keypad_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x00100000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_keypad_ops, s,
+                          "pxa2xx-keypad", 0x00100000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     vmstate_register(NULL, 0, &vmstate_pxa2xx_keypad, s);
 
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index b73290cb3f..fd23d63a64 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -30,6 +30,7 @@ struct DMAChannel {
 };
 
 struct PXA2xxLCDState {
+    MemoryRegion iomem;
     qemu_irq irq;
     int irqlevel;
 
@@ -315,7 +316,8 @@ static void pxa2xx_descriptor_load(PXA2xxLCDState *s)
     }
 }
 
-static uint32_t pxa2xx_lcdc_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pxa2xx_lcdc_read(void *opaque, target_phys_addr_t offset,
+                                 unsigned size)
 {
     PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
     int ch;
@@ -408,8 +410,8 @@ static uint32_t pxa2xx_lcdc_read(void *opaque, target_phys_addr_t offset)
     return 0;
 }
 
-static void pxa2xx_lcdc_write(void *opaque,
-                target_phys_addr_t offset, uint32_t value)
+static void pxa2xx_lcdc_write(void *opaque, target_phys_addr_t offset,
+                              uint64_t value, unsigned size)
 {
     PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
     int ch;
@@ -561,16 +563,10 @@ static void pxa2xx_lcdc_write(void *opaque,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_lcdc_readfn[] = {
-    pxa2xx_lcdc_read,
-    pxa2xx_lcdc_read,
-    pxa2xx_lcdc_read
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_lcdc_writefn[] = {
-    pxa2xx_lcdc_write,
-    pxa2xx_lcdc_write,
-    pxa2xx_lcdc_write
+static const MemoryRegionOps pxa2xx_lcdc_ops = {
+    .read = pxa2xx_lcdc_read,
+    .write = pxa2xx_lcdc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 /* Load new palette for a given DMA channel, convert to internal format */
@@ -981,9 +977,9 @@ static const VMStateDescription vmstate_pxa2xx_lcdc = {
 #define BITS 32
 #include "pxa2xx_template.h"
 
-PXA2xxLCDState *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq)
+PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
+                                 target_phys_addr_t base, qemu_irq irq)
 {
-    int iomemtype;
     PXA2xxLCDState *s;
 
     s = (PXA2xxLCDState *) g_malloc0(sizeof(PXA2xxLCDState));
@@ -992,9 +988,9 @@ PXA2xxLCDState *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq)
 
     pxa2xx_lcdc_orientation(s, graphic_rotate);
 
-    iomemtype = cpu_register_io_memory(pxa2xx_lcdc_readfn,
-                    pxa2xx_lcdc_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x00100000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_lcdc_ops, s,
+                          "pxa2xx-lcd-controller", 0x00100000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     s->ds = graphic_console_init(pxa2xx_update_display,
                                  pxa2xx_invalidate_display,
diff --git a/hw/pxa2xx_mmci.c b/hw/pxa2xx_mmci.c
index 1de497929b..f47c79ca4a 100644
--- a/hw/pxa2xx_mmci.c
+++ b/hw/pxa2xx_mmci.c
@@ -13,6 +13,7 @@
 #include "qdev.h"
 
 struct PXA2xxMMCIState {
+    MemoryRegion iomem;
     qemu_irq irq;
     qemu_irq rx_dma;
     qemu_irq tx_dma;
@@ -403,12 +404,6 @@ static uint32_t pxa2xx_mmci_readw(void *opaque, target_phys_addr_t offset)
     return pxa2xx_mmci_read(opaque, offset);
 }
 
-static CPUReadMemoryFunc * const pxa2xx_mmci_readfn[] = {
-    pxa2xx_mmci_readb,
-    pxa2xx_mmci_readh,
-    pxa2xx_mmci_readw
-};
-
 static void pxa2xx_mmci_writeb(void *opaque,
                 target_phys_addr_t offset, uint32_t value)
 {
@@ -433,10 +428,16 @@ static void pxa2xx_mmci_writew(void *opaque,
     pxa2xx_mmci_write(opaque, offset, value);
 }
 
-static CPUWriteMemoryFunc * const pxa2xx_mmci_writefn[] = {
-    pxa2xx_mmci_writeb,
-    pxa2xx_mmci_writeh,
-    pxa2xx_mmci_writew
+static const MemoryRegionOps pxa2xx_mmci_ops = {
+    .old_mmio = {
+        .read = { pxa2xx_mmci_readb,
+                  pxa2xx_mmci_readh,
+                  pxa2xx_mmci_readw, },
+        .write = { pxa2xx_mmci_writeb,
+                   pxa2xx_mmci_writeh,
+                   pxa2xx_mmci_writew, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void pxa2xx_mmci_save(QEMUFile *f, void *opaque)
@@ -517,11 +518,11 @@ static int pxa2xx_mmci_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-PXA2xxMMCIState *pxa2xx_mmci_init(target_phys_addr_t base,
+PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
+                target_phys_addr_t base,
                 BlockDriverState *bd, qemu_irq irq,
                 qemu_irq rx_dma, qemu_irq tx_dma)
 {
-    int iomemtype;
     PXA2xxMMCIState *s;
 
     s = (PXA2xxMMCIState *) g_malloc0(sizeof(PXA2xxMMCIState));
@@ -529,9 +530,9 @@ PXA2xxMMCIState *pxa2xx_mmci_init(target_phys_addr_t base,
     s->rx_dma = rx_dma;
     s->tx_dma = tx_dma;
 
-    iomemtype = cpu_register_io_memory(pxa2xx_mmci_readfn,
-                    pxa2xx_mmci_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x00100000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_mmci_ops, s,
+                          "pxa2xx-mmci", 0x00100000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     /* Instantiate the actual storage */
     s->card = sd_init(bd, 0);
diff --git a/hw/pxa2xx_pcmcia.c b/hw/pxa2xx_pcmcia.c
index 74c6817baf..dc522dcf43 100644
--- a/hw/pxa2xx_pcmcia.c
+++ b/hw/pxa2xx_pcmcia.c
@@ -11,16 +11,20 @@
 #include "pcmcia.h"
 #include "pxa.h"
 
+
 struct PXA2xxPCMCIAState {
     PCMCIASocket slot;
     PCMCIACardState *card;
+    MemoryRegion common_iomem;
+    MemoryRegion attr_iomem;
+    MemoryRegion iomem;
 
     qemu_irq irq;
     qemu_irq cd_irq;
 };
 
-static uint32_t pxa2xx_pcmcia_common_read(void *opaque,
-                target_phys_addr_t offset)
+static uint64_t pxa2xx_pcmcia_common_read(void *opaque,
+                target_phys_addr_t offset, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
 
@@ -31,8 +35,8 @@ static uint32_t pxa2xx_pcmcia_common_read(void *opaque,
     return 0;
 }
 
-static void pxa2xx_pcmcia_common_write(void *opaque,
-                target_phys_addr_t offset, uint32_t value)
+static void pxa2xx_pcmcia_common_write(void *opaque, target_phys_addr_t offset,
+                                       uint64_t value, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
 
@@ -41,8 +45,8 @@ static void pxa2xx_pcmcia_common_write(void *opaque,
     }
 }
 
-static uint32_t pxa2xx_pcmcia_attr_read(void *opaque,
-                target_phys_addr_t offset)
+static uint64_t pxa2xx_pcmcia_attr_read(void *opaque,
+                target_phys_addr_t offset, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
 
@@ -53,8 +57,8 @@ static uint32_t pxa2xx_pcmcia_attr_read(void *opaque,
     return 0;
 }
 
-static void pxa2xx_pcmcia_attr_write(void *opaque,
-                target_phys_addr_t offset, uint32_t value)
+static void pxa2xx_pcmcia_attr_write(void *opaque, target_phys_addr_t offset,
+                                     uint64_t value, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
 
@@ -63,8 +67,8 @@ static void pxa2xx_pcmcia_attr_write(void *opaque,
     }
 }
 
-static uint32_t pxa2xx_pcmcia_io_read(void *opaque,
-                target_phys_addr_t offset)
+static uint64_t pxa2xx_pcmcia_io_read(void *opaque,
+                target_phys_addr_t offset, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
 
@@ -75,8 +79,8 @@ static uint32_t pxa2xx_pcmcia_io_read(void *opaque,
     return 0;
 }
 
-static void pxa2xx_pcmcia_io_write(void *opaque,
-                target_phys_addr_t offset, uint32_t value)
+static void pxa2xx_pcmcia_io_write(void *opaque, target_phys_addr_t offset,
+                                   uint64_t value, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
 
@@ -85,40 +89,22 @@ static void pxa2xx_pcmcia_io_write(void *opaque,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_pcmcia_common_readfn[] = {
-    pxa2xx_pcmcia_common_read,
-    pxa2xx_pcmcia_common_read,
-    pxa2xx_pcmcia_common_read,
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_pcmcia_common_writefn[] = {
-    pxa2xx_pcmcia_common_write,
-    pxa2xx_pcmcia_common_write,
-    pxa2xx_pcmcia_common_write,
-};
-
-static CPUReadMemoryFunc * const pxa2xx_pcmcia_attr_readfn[] = {
-    pxa2xx_pcmcia_attr_read,
-    pxa2xx_pcmcia_attr_read,
-    pxa2xx_pcmcia_attr_read,
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_pcmcia_attr_writefn[] = {
-    pxa2xx_pcmcia_attr_write,
-    pxa2xx_pcmcia_attr_write,
-    pxa2xx_pcmcia_attr_write,
+static const MemoryRegionOps pxa2xx_pcmcia_common_ops = {
+    .read = pxa2xx_pcmcia_common_read,
+    .write = pxa2xx_pcmcia_common_write,
+    .endianness = DEVICE_NATIVE_ENDIAN
 };
 
-static CPUReadMemoryFunc * const pxa2xx_pcmcia_io_readfn[] = {
-    pxa2xx_pcmcia_io_read,
-    pxa2xx_pcmcia_io_read,
-    pxa2xx_pcmcia_io_read,
+static const MemoryRegionOps pxa2xx_pcmcia_attr_ops = {
+    .read = pxa2xx_pcmcia_attr_read,
+    .write = pxa2xx_pcmcia_attr_write,
+    .endianness = DEVICE_NATIVE_ENDIAN
 };
 
-static CPUWriteMemoryFunc * const pxa2xx_pcmcia_io_writefn[] = {
-    pxa2xx_pcmcia_io_write,
-    pxa2xx_pcmcia_io_write,
-    pxa2xx_pcmcia_io_write,
+static const MemoryRegionOps pxa2xx_pcmcia_io_ops = {
+    .read = pxa2xx_pcmcia_io_read,
+    .write = pxa2xx_pcmcia_io_write,
+    .endianness = DEVICE_NATIVE_ENDIAN
 };
 
 static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
@@ -130,30 +116,33 @@ static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
     qemu_set_irq(s->irq, level);
 }
 
-PXA2xxPCMCIAState *pxa2xx_pcmcia_init(target_phys_addr_t base)
+PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
+                                      target_phys_addr_t base)
 {
-    int iomemtype;
     PXA2xxPCMCIAState *s;
 
     s = (PXA2xxPCMCIAState *)
             g_malloc0(sizeof(PXA2xxPCMCIAState));
 
     /* Socket I/O Memory Space */
-    iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_io_readfn,
-                    pxa2xx_pcmcia_io_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base | 0x00000000, 0x04000000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_pcmcia_io_ops, s,
+                          "pxa2xx-pcmcia-io", 0x04000000);
+    memory_region_add_subregion(sysmem, base | 0x00000000,
+                                &s->iomem);
 
     /* Then next 64 MB is reserved */
 
     /* Socket Attribute Memory Space */
-    iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_attr_readfn,
-                    pxa2xx_pcmcia_attr_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base | 0x08000000, 0x04000000, iomemtype);
+    memory_region_init_io(&s->attr_iomem, &pxa2xx_pcmcia_attr_ops, s,
+                          "pxa2xx-pcmcia-attribute", 0x04000000);
+    memory_region_add_subregion(sysmem, base | 0x08000000,
+                                &s->attr_iomem);
 
     /* Socket Common Memory Space */
-    iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_common_readfn,
-                    pxa2xx_pcmcia_common_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base | 0x0c000000, 0x04000000, iomemtype);
+    memory_region_init_io(&s->common_iomem, &pxa2xx_pcmcia_common_ops, s,
+                          "pxa2xx-pcmcia-common", 0x04000000);
+    memory_region_add_subregion(sysmem, base | 0x0c000000,
+                                &s->common_iomem);
 
     if (base == 0x30000000)
         s->slot.slot_string = "PXA PC Card Socket 1";
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index bdd82e6bf2..92effbc806 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -33,6 +33,7 @@
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     CPUState *cpu_env;
     uint32_t int_enabled[2];
     uint32_t int_pending[2];
@@ -115,7 +116,8 @@ static inline uint32_t pxa2xx_pic_highest(PXA2xxPICState *s) {
     return ichp;
 }
 
-static uint32_t pxa2xx_pic_mem_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pxa2xx_pic_mem_read(void *opaque, target_phys_addr_t offset,
+                                    unsigned size)
 {
     PXA2xxPICState *s = (PXA2xxPICState *) opaque;
 
@@ -155,7 +157,7 @@ static uint32_t pxa2xx_pic_mem_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pxa2xx_pic_mem_write(void *opaque, target_phys_addr_t offset,
-                uint32_t value)
+                                 uint64_t value, unsigned size)
 {
     PXA2xxPICState *s = (PXA2xxPICState *) opaque;
 
@@ -214,7 +216,7 @@ static uint32_t pxa2xx_pic_cp_read(void *opaque, int op2, int reg, int crm)
     }
 
     offset = pxa2xx_cp_reg_map[reg];
-    return pxa2xx_pic_mem_read(opaque, offset);
+    return pxa2xx_pic_mem_read(opaque, offset, 4);
 }
 
 static void pxa2xx_pic_cp_write(void *opaque, int op2, int reg, int crm,
@@ -228,19 +230,13 @@ static void pxa2xx_pic_cp_write(void *opaque, int op2, int reg, int crm,
     }
 
     offset = pxa2xx_cp_reg_map[reg];
-    pxa2xx_pic_mem_write(opaque, offset, value);
+    pxa2xx_pic_mem_write(opaque, offset, value, 4);
 }
 
-static CPUReadMemoryFunc * const pxa2xx_pic_readfn[] = {
-    pxa2xx_pic_mem_read,
-    pxa2xx_pic_mem_read,
-    pxa2xx_pic_mem_read,
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_pic_writefn[] = {
-    pxa2xx_pic_mem_write,
-    pxa2xx_pic_mem_write,
-    pxa2xx_pic_mem_write,
+static const MemoryRegionOps pxa2xx_pic_ops = {
+    .read = pxa2xx_pic_mem_read,
+    .write = pxa2xx_pic_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int pxa2xx_pic_post_load(void *opaque, int version_id)
@@ -252,7 +248,6 @@ static int pxa2xx_pic_post_load(void *opaque, int version_id)
 DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env)
 {
     DeviceState *dev = qdev_create(NULL, "pxa2xx_pic");
-    int iomemtype;
     PXA2xxPICState *s = FROM_SYSBUS(PXA2xxPICState, sysbus_from_qdev(dev));
 
     s->cpu_env = env;
@@ -269,9 +264,9 @@ DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env)
     qdev_init_gpio_in(dev, pxa2xx_pic_set_irq, PXA2XX_PIC_SRCS);
 
     /* Enable IC memory-mapped registers access.  */
-    iomemtype = cpu_register_io_memory(pxa2xx_pic_readfn,
-                    pxa2xx_pic_writefn, s, DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(sysbus_from_qdev(dev), 0x00100000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_pic_ops, s,
+                          "pxa2xx-pic", 0x00100000);
+    sysbus_init_mmio(sysbus_from_qdev(dev), &s->iomem);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
 
     /* Enable IC coprocessor access.  */
diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index 4235e42639..50e26789d2 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -81,6 +81,7 @@ typedef struct {
 
 struct PXA2xxTimerInfo {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t flags;
 
     int32_t clock;
@@ -148,7 +149,8 @@ static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
     qemu_mod_timer(s->tm4[n].tm.qtimer, new_qemu);
 }
 
-static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset,
+                                  unsigned size)
 {
     PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
     int tm = 0;
@@ -226,7 +228,7 @@ static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
-                uint32_t value)
+                               uint64_t value, unsigned size)
 {
     int i, tm = 0;
     PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
@@ -325,16 +327,10 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_timer_readfn[] = {
-    pxa2xx_timer_read,
-    pxa2xx_timer_read,
-    pxa2xx_timer_read,
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_timer_writefn[] = {
-    pxa2xx_timer_write,
-    pxa2xx_timer_write,
-    pxa2xx_timer_write,
+static const MemoryRegionOps pxa2xx_timer_ops = {
+    .read = pxa2xx_timer_read,
+    .write = pxa2xx_timer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void pxa2xx_timer_tick(void *opaque)
@@ -387,7 +383,6 @@ static int pxa25x_timer_post_load(void *opaque, int version_id)
 static int pxa2xx_timer_init(SysBusDevice *dev)
 {
     int i;
-    int iomemtype;
     PXA2xxTimerInfo *s;
 
     s = FROM_SYSBUS(PXA2xxTimerInfo, dev);
@@ -419,9 +414,9 @@ static int pxa2xx_timer_init(SysBusDevice *dev)
         }
     }
 
-    iomemtype = cpu_register_io_memory(pxa2xx_timer_readfn,
-                    pxa2xx_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x00001000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_timer_ops, s,
+                          "pxa2xx-timer", 0x00001000);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
diff --git a/hw/r2d.c b/hw/r2d.c
index b65fd427b7..9b6fcba19b 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -250,7 +250,7 @@ static void r2d_init(ram_addr_t ram_size,
     memory_region_init_ram(sdram, NULL, "r2d.sdram", SDRAM_SIZE);
     memory_region_add_subregion(address_space_mem, SDRAM_BASE, sdram);
     /* Register peripherals */
-    s = sh7750_init(env);
+    s = sh7750_init(env, address_space_mem);
     irq = r2d_fpga_init(address_space_mem, 0x04000000, sh7750_irl(s));
     sysbus_create_varargs("sh_pci", 0x1e200000, irq[PCI_INTA], irq[PCI_INTB],
                           irq[PCI_INTC], irq[PCI_INTD], NULL);
@@ -260,7 +260,7 @@ static void r2d_init(ram_addr_t ram_size,
 
     /* onboard CF (True IDE mode, Master only). */
     dinfo = drive_get(IF_IDE, 0, 0);
-    mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1,
+    mmio_ide_init(0x14001000, 0x1400080c, address_space_mem, irq[CF_IDE], 1,
                   dinfo, NULL);
 
     /* onboard flash memory */
diff --git a/hw/rc4030.c b/hw/rc4030.c
index 33e10709c6..9f39b30505 100644
--- a/hw/rc4030.c
+++ b/hw/rc4030.c
@@ -95,6 +95,9 @@ typedef struct rc4030State
 
     qemu_irq timer_irq;
     qemu_irq jazz_bus_irq;
+
+    MemoryRegion iomem_chipset;
+    MemoryRegion iomem_jazzio;
 } rc4030State;
 
 static void set_next_tick(rc4030State *s)
@@ -419,16 +422,12 @@ static void rc4030_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
     rc4030_writel(opaque, addr & ~0x3, val);
 }
 
-static CPUReadMemoryFunc * const rc4030_read[3] = {
-    rc4030_readb,
-    rc4030_readw,
-    rc4030_readl,
-};
-
-static CPUWriteMemoryFunc * const rc4030_write[3] = {
-    rc4030_writeb,
-    rc4030_writew,
-    rc4030_writel,
+static const MemoryRegionOps rc4030_ops = {
+    .old_mmio = {
+        .read = { rc4030_readb, rc4030_readw, rc4030_readl, },
+        .write = { rc4030_writeb, rc4030_writew, rc4030_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void update_jazz_irq(rc4030State *s)
@@ -573,16 +572,12 @@ static void jazzio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     jazzio_writew(opaque, addr + 2, (val >> 16) & 0xffff);
 }
 
-static CPUReadMemoryFunc * const jazzio_read[3] = {
-    jazzio_readb,
-    jazzio_readw,
-    jazzio_readl,
-};
-
-static CPUWriteMemoryFunc * const jazzio_write[3] = {
-    jazzio_writeb,
-    jazzio_writew,
-    jazzio_writel,
+static const MemoryRegionOps jazzio_ops = {
+    .old_mmio = {
+        .read = { jazzio_readb, jazzio_readw, jazzio_readl, },
+        .write = { jazzio_writeb, jazzio_writew, jazzio_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void rc4030_reset(void *opaque)
@@ -801,10 +796,10 @@ static rc4030_dma *rc4030_allocate_dmas(void *opaque, int n)
 }
 
 void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
-                  qemu_irq **irqs, rc4030_dma **dmas)
+                  qemu_irq **irqs, rc4030_dma **dmas,
+                  MemoryRegion *sysmem)
 {
     rc4030State *s;
-    int s_chipset, s_jazzio;
 
     s = g_malloc0(sizeof(rc4030State));
 
@@ -819,12 +814,12 @@ void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
     register_savevm(NULL, "rc4030", 0, 2, rc4030_save, rc4030_load, s);
     rc4030_reset(s);
 
-    s_chipset = cpu_register_io_memory(rc4030_read, rc4030_write, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(0x80000000, 0x300, s_chipset);
-    s_jazzio = cpu_register_io_memory(jazzio_read, jazzio_write, s,
-                                      DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(0xf0000000, 0x00001000, s_jazzio);
+    memory_region_init_io(&s->iomem_chipset, &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,
+                          "rc4030.jazzio", 0x00001000);
+    memory_region_add_subregion(sysmem, 0xf0000000, &s->iomem_jazzio);
 
     return s;
 }
diff --git a/hw/realview.c b/hw/realview.c
index 9a8e63c8f5..750a279b76 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -77,7 +77,7 @@ static int realview_i2c_init(SysBusDevice *dev)
     s->bitbang = bitbang_i2c_init(bus);
     memory_region_init_io(&s->iomem, &realview_i2c_ops, s,
                           "realview-i2c", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index cd6a44d9d0..479f939553 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -62,7 +62,7 @@ static int realview_gic_init(SysBusDevice *dev)
 
     gic_init(&s->gic);
     realview_gic_map_setup(s);
-    sysbus_init_mmio_region(dev, &s->container);
+    sysbus_init_mmio(dev, &s->container);
     return 0;
 }
 
diff --git a/hw/sbi.c b/hw/sbi.c
index 53f66f2c5e..8965a71771 100644
--- a/hw/sbi.c
+++ b/hw/sbi.c
@@ -39,6 +39,7 @@
 
 typedef struct SBIState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t regs[SBI_NREGS];
     uint32_t intreg_pending[MAX_CPUS];
     qemu_irq cpu_irqs[MAX_CPUS];
@@ -51,7 +52,8 @@ static void sbi_set_irq(void *opaque, int irq, int level)
 {
 }
 
-static uint32_t sbi_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t sbi_mem_read(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
 {
     SBIState *s = opaque;
     uint32_t saddr, ret;
@@ -67,13 +69,14 @@ static uint32_t sbi_mem_readl(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static void sbi_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void sbi_mem_write(void *opaque, target_phys_addr_t addr,
+                          uint64_t val, unsigned dize)
 {
     SBIState *s = opaque;
     uint32_t saddr;
 
     saddr = addr >> 2;
-    DPRINTF("write system reg 0x" TARGET_FMT_plx " = %x\n", addr, val);
+    DPRINTF("write system reg 0x" TARGET_FMT_plx " = %x\n", addr, (int)val);
     switch (saddr) {
     default:
         s->regs[saddr] = val;
@@ -81,16 +84,14 @@ static void sbi_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
-static CPUReadMemoryFunc * const sbi_mem_read[3] = {
-    NULL,
-    NULL,
-    sbi_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const sbi_mem_write[3] = {
-    NULL,
-    NULL,
-    sbi_mem_writel,
+static const MemoryRegionOps sbi_mem_ops = {
+    .read = sbi_mem_read,
+    .write = sbi_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static const VMStateDescription vmstate_sbi = {
@@ -117,7 +118,6 @@ static void sbi_reset(DeviceState *d)
 static int sbi_init1(SysBusDevice *dev)
 {
     SBIState *s = FROM_SYSBUS(SBIState, dev);
-    int sbi_io_memory;
     unsigned int i;
 
     qdev_init_gpio_in(&dev->qdev, sbi_set_irq, 32 + MAX_CPUS);
@@ -125,9 +125,8 @@ static int sbi_init1(SysBusDevice *dev)
         sysbus_init_irq(dev, &s->cpu_irqs[i]);
     }
 
-    sbi_io_memory = cpu_register_io_memory(sbi_mem_read, sbi_mem_write, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, SBI_SIZE, sbi_io_memory);
+    memory_region_init_io(&s->iomem, &sbi_mem_ops, s, "sbi", SBI_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
diff --git a/hw/sh.h b/hw/sh.h
index d30e9f5b6c..6488db25c4 100644
--- a/hw/sh.h
+++ b/hw/sh.h
@@ -9,8 +9,9 @@
 
 /* sh7750.c */
 struct SH7750State;
+struct MemoryRegion;
 
-struct SH7750State *sh7750_init(CPUState * cpu);
+struct SH7750State *sh7750_init(CPUState * cpu, struct MemoryRegion *sysmem);
 
 typedef struct {
     /* The callback will be triggered if any of the designated lines change */
@@ -30,14 +31,16 @@ int sh7750_register_io_device(struct SH7750State *s,
 #define TMU012_FEAT_TOCR   (1 << 0)
 #define TMU012_FEAT_3CHAN  (1 << 1)
 #define TMU012_FEAT_EXTCLK (1 << 2)
-void tmu012_init(target_phys_addr_t base, int feat, uint32_t freq,
+void tmu012_init(struct MemoryRegion *sysmem, target_phys_addr_t base,
+                 int feat, uint32_t freq,
 		 qemu_irq ch0_irq, qemu_irq ch1_irq,
 		 qemu_irq ch2_irq0, qemu_irq ch2_irq1);
 
 
 /* sh_serial.c */
 #define SH_SERIAL_FEAT_SCIF (1 << 0)
-void sh_serial_init (target_phys_addr_t base, int feat,
+void sh_serial_init(MemoryRegion *sysmem,
+                    target_phys_addr_t base, int feat,
 		     uint32_t freq, CharDriverState *chr,
 		     qemu_irq eri_source,
 		     qemu_irq rxi_source,
diff --git a/hw/sh7750.c b/hw/sh7750.c
index 9f3ea9285f..4f4d8e7d05 100644
--- a/hw/sh7750.c
+++ b/hw/sh7750.c
@@ -30,10 +30,19 @@
 #include "sh7750_regnames.h"
 #include "sh_intc.h"
 #include "cpu.h"
+#include "exec-memory.h"
 
 #define NB_DEVICES 4
 
 typedef struct SH7750State {
+    MemoryRegion iomem;
+    MemoryRegion iomem_1f0;
+    MemoryRegion iomem_ff0;
+    MemoryRegion iomem_1f8;
+    MemoryRegion iomem_ff8;
+    MemoryRegion iomem_1fc;
+    MemoryRegion iomem_ffc;
+    MemoryRegion mmct_iomem;
     /* CPU */
     CPUSH4State *cpu;
     /* Peripheral frequency in Hz */
@@ -436,16 +445,16 @@ static void sh7750_mem_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const sh7750_mem_read[] = {
-    sh7750_mem_readb,
-    sh7750_mem_readw,
-    sh7750_mem_readl
-};
-
-static CPUWriteMemoryFunc * const sh7750_mem_write[] = {
-    sh7750_mem_writeb,
-    sh7750_mem_writew,
-    sh7750_mem_writel
+static const MemoryRegionOps sh7750_mem_ops = {
+    .old_mmio = {
+        .read = {sh7750_mem_readb,
+                 sh7750_mem_readw,
+                 sh7750_mem_readl },
+        .write = {sh7750_mem_writeb,
+                  sh7750_mem_writew,
+                  sh7750_mem_writel },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 /* sh775x interrupt controller tables for sh_intc.c
@@ -615,18 +624,23 @@ static struct intc_group groups_irl[] = {
 #define MM_UTLB_DATA     (7)
 #define MM_REGION_TYPE(addr)  ((addr & MM_REGION_MASK) >> 24)
 
-static uint32_t invalid_read(void *opaque, target_phys_addr_t addr)
+static uint64_t invalid_read(void *opaque, target_phys_addr_t addr)
 {
     abort();
 
     return 0;
 }
 
-static uint32_t sh7750_mmct_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t sh7750_mmct_read(void *opaque, target_phys_addr_t addr,
+                                 unsigned size)
 {
     SH7750State *s = opaque;
     uint32_t ret = 0;
 
+    if (size != 4) {
+        return invalid_read(opaque, addr);
+    }
+
     switch (MM_REGION_TYPE(addr)) {
     case MM_ICACHE_ADDR:
     case MM_ICACHE_DATA:
@@ -656,16 +670,20 @@ static uint32_t sh7750_mmct_readl(void *opaque, target_phys_addr_t addr)
 }
 
 static void invalid_write(void *opaque, target_phys_addr_t addr,
-			  uint32_t mem_value)
+                          uint64_t mem_value)
 {
     abort();
 }
 
-static void sh7750_mmct_writel(void *opaque, target_phys_addr_t addr,
-				uint32_t mem_value)
+static void sh7750_mmct_write(void *opaque, target_phys_addr_t addr,
+                              uint64_t mem_value, unsigned size)
 {
     SH7750State *s = opaque;
 
+    if (size != 4) {
+        invalid_write(opaque, addr, mem_value);
+    }
+
     switch (MM_REGION_TYPE(addr)) {
     case MM_ICACHE_ADDR:
     case MM_ICACHE_DATA:
@@ -694,50 +712,51 @@ static void sh7750_mmct_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const sh7750_mmct_read[] = {
-    invalid_read,
-    invalid_read,
-    sh7750_mmct_readl
-};
-
-static CPUWriteMemoryFunc * const sh7750_mmct_write[] = {
-    invalid_write,
-    invalid_write,
-    sh7750_mmct_writel
+static const struct MemoryRegionOps sh7750_mmct_ops = {
+    .read = sh7750_mmct_read,
+    .write = sh7750_mmct_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-SH7750State *sh7750_init(CPUSH4State * cpu)
+SH7750State *sh7750_init(CPUSH4State * cpu, MemoryRegion *sysmem)
 {
     SH7750State *s;
-    int sh7750_io_memory;
-    int sh7750_mm_cache_and_tlb; /* memory mapped cache and tlb */
 
     s = g_malloc0(sizeof(SH7750State));
     s->cpu = cpu;
     s->periph_freq = 60000000;	/* 60MHz */
-    sh7750_io_memory = cpu_register_io_memory(sh7750_mem_read,
-					      sh7750_mem_write, s,
-                                              DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory_offset(0x1f000000, 0x1000,
-                                        sh7750_io_memory, 0x1f000000);
-    cpu_register_physical_memory_offset(0xff000000, 0x1000,
-                                        sh7750_io_memory, 0x1f000000);
-    cpu_register_physical_memory_offset(0x1f800000, 0x1000,
-                                        sh7750_io_memory, 0x1f800000);
-    cpu_register_physical_memory_offset(0xff800000, 0x1000,
-                                        sh7750_io_memory, 0x1f800000);
-    cpu_register_physical_memory_offset(0x1fc00000, 0x1000,
-                                        sh7750_io_memory, 0x1fc00000);
-    cpu_register_physical_memory_offset(0xffc00000, 0x1000,
-                                        sh7750_io_memory, 0x1fc00000);
-
-    sh7750_mm_cache_and_tlb = cpu_register_io_memory(sh7750_mmct_read,
-						     sh7750_mmct_write, s,
-                                                     DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(0xf0000000, 0x08000000,
-				 sh7750_mm_cache_and_tlb);
-
-    sh_intc_init(&s->intc, NR_SOURCES,
+    memory_region_init_io(&s->iomem, &sh7750_mem_ops, s,
+                          "memory", 0x1fc01000);
+
+    memory_region_init_alias(&s->iomem_1f0, "memory-1f0",
+                             &s->iomem, 0x1f000000, 0x1000);
+    memory_region_add_subregion(sysmem, 0x1f000000, &s->iomem_1f0);
+
+    memory_region_init_alias(&s->iomem_ff0, "memory-ff0",
+                             &s->iomem, 0x1f000000, 0x1000);
+    memory_region_add_subregion(sysmem, 0xff000000, &s->iomem_ff0);
+
+    memory_region_init_alias(&s->iomem_1f8, "memory-1f8",
+                             &s->iomem, 0x1f800000, 0x1000);
+    memory_region_add_subregion(sysmem, 0x1f800000, &s->iomem_1f8);
+
+    memory_region_init_alias(&s->iomem_ff8, "memory-ff8",
+                             &s->iomem, 0x1f800000, 0x1000);
+    memory_region_add_subregion(sysmem, 0xff800000, &s->iomem_ff8);
+
+    memory_region_init_alias(&s->iomem_1fc, "memory-1fc",
+                             &s->iomem, 0x1fc00000, 0x1000);
+    memory_region_add_subregion(sysmem, 0x1fc00000, &s->iomem_1fc);
+
+    memory_region_init_alias(&s->iomem_ffc, "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,
+                          "cache-and-tlb", 0x08000000);
+    memory_region_add_subregion(sysmem, 0xf0000000, &s->mmct_iomem);
+
+    sh_intc_init(sysmem, &s->intc, NR_SOURCES,
 		 _INTC_ARRAY(mask_registers),
 		 _INTC_ARRAY(prio_registers));
 
@@ -747,21 +766,23 @@ SH7750State *sh7750_init(CPUSH4State * cpu)
 
     cpu->intc_handle = &s->intc;
 
-    sh_serial_init(0x1fe00000, 0, s->periph_freq, serial_hds[0],
-		   s->intc.irqs[SCI1_ERI],
-		   s->intc.irqs[SCI1_RXI],
-		   s->intc.irqs[SCI1_TXI],
-		   s->intc.irqs[SCI1_TEI],
-		   NULL);
-    sh_serial_init(0x1fe80000, SH_SERIAL_FEAT_SCIF,
-		   s->periph_freq, serial_hds[1],
-		   s->intc.irqs[SCIF_ERI],
-		   s->intc.irqs[SCIF_RXI],
-		   s->intc.irqs[SCIF_TXI],
-		   NULL,
-		   s->intc.irqs[SCIF_BRI]);
-
-    tmu012_init(0x1fd80000,
+    sh_serial_init(sysmem, 0x1fe00000,
+                   0, s->periph_freq, serial_hds[0],
+                   s->intc.irqs[SCI1_ERI],
+                   s->intc.irqs[SCI1_RXI],
+                   s->intc.irqs[SCI1_TXI],
+                   s->intc.irqs[SCI1_TEI],
+                   NULL);
+    sh_serial_init(sysmem, 0x1fe80000,
+                   SH_SERIAL_FEAT_SCIF,
+                   s->periph_freq, serial_hds[1],
+                   s->intc.irqs[SCIF_ERI],
+                   s->intc.irqs[SCIF_RXI],
+                   s->intc.irqs[SCIF_TXI],
+                   NULL,
+                   s->intc.irqs[SCIF_BRI]);
+
+    tmu012_init(sysmem, 0x1fd80000,
 		TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
 		s->periph_freq,
 		s->intc.irqs[TMU0],
@@ -785,7 +806,7 @@ SH7750State *sh7750_init(CPUSH4State * cpu)
         sh_intc_register_sources(&s->intc,
 				 _INTC_ARRAY(vectors_tmu34),
 				 NULL, 0);
-        tmu012_init(0x1e100000, 0, s->periph_freq,
+        tmu012_init(sysmem, 0x1e100000, 0, s->periph_freq,
 		    s->intc.irqs[TMU3],
 		    s->intc.irqs[TMU4],
 		    NULL, NULL);
diff --git a/hw/sh_intc.c b/hw/sh_intc.c
index e07424f2a1..b24ec77582 100644
--- a/hw/sh_intc.c
+++ b/hw/sh_intc.c
@@ -219,7 +219,8 @@ static void sh_intc_toggle_mask(struct intc_desc *desc, intc_enum id,
 #endif
 }
 
-static uint32_t sh_intc_read(void *opaque, target_phys_addr_t offset)
+static uint64_t sh_intc_read(void *opaque, target_phys_addr_t offset,
+                             unsigned size)
 {
     struct intc_desc *desc = opaque;
     intc_enum *enum_ids = NULL;
@@ -238,7 +239,7 @@ static uint32_t sh_intc_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void sh_intc_write(void *opaque, target_phys_addr_t offset,
-			  uint32_t value)
+                          uint64_t value, unsigned size)
 {
     struct intc_desc *desc = opaque;
     intc_enum *enum_ids = NULL;
@@ -282,16 +283,10 @@ static void sh_intc_write(void *opaque, target_phys_addr_t offset,
 #endif
 }
 
-static CPUReadMemoryFunc * const sh_intc_readfn[] = {
-    sh_intc_read,
-    sh_intc_read,
-    sh_intc_read
-};
-
-static CPUWriteMemoryFunc * const sh_intc_writefn[] = {
-    sh_intc_write,
-    sh_intc_write,
-    sh_intc_write
+static const struct MemoryRegionOps sh_intc_ops = {
+    .read = sh_intc_read,
+    .write = sh_intc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id)
@@ -302,15 +297,36 @@ struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id)
     return NULL;
 }
 
-static void sh_intc_register(struct intc_desc *desc, 
-			     unsigned long address)
+static unsigned int sh_intc_register(MemoryRegion *sysmem,
+                             struct intc_desc *desc,
+                             const unsigned long address,
+                             const char *type,
+                             const char *action,
+                             const unsigned int index)
 {
-    if (address) {
-        cpu_register_physical_memory_offset(P4ADDR(address), 4,
-                                            desc->iomemtype, INTC_A7(address));
-        cpu_register_physical_memory_offset(A7ADDR(address), 4,
-                                            desc->iomemtype, INTC_A7(address));
+    char name[60];
+    MemoryRegion *iomem, *iomem_p4, *iomem_a7;
+
+    if (!address) {
+        return 0;
     }
+
+    iomem = &desc->iomem;
+    iomem_p4 = desc->iomem_aliases + index;
+    iomem_a7 = iomem_p4 + 1;
+
+#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_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_add_subregion(sysmem, A7ADDR(address), iomem_a7);
+#undef SH_INTC_IOMEM_FORMAT
+
+    /* used to increment aliases index */
+    return 2;
 }
 
 static void sh_intc_register_source(struct intc_desc *desc,
@@ -415,14 +431,15 @@ void sh_intc_register_sources(struct intc_desc *desc,
     }
 }
 
-int sh_intc_init(struct intc_desc *desc,
+int sh_intc_init(MemoryRegion *sysmem,
+         struct intc_desc *desc,
 		 int nr_sources,
 		 struct intc_mask_reg *mask_regs,
 		 int nr_mask_regs,
 		 struct intc_prio_reg *prio_regs,
 		 int nr_prio_regs)
 {
-    unsigned int i;
+    unsigned int i, j;
 
     desc->pending = 0;
     desc->nr_sources = nr_sources;
@@ -430,7 +447,12 @@ int sh_intc_init(struct intc_desc *desc,
     desc->nr_mask_regs = nr_mask_regs;
     desc->prio_regs = prio_regs;
     desc->nr_prio_regs = nr_prio_regs;
+    /* Allocate 4 MemoryRegions per register (2 actions * 2 aliases).
+     **/
+    desc->iomem_aliases = g_new0(MemoryRegion,
+                                 (nr_mask_regs + nr_prio_regs) * 4);
 
+    j = 0;
     i = sizeof(struct intc_source) * nr_sources;
     desc->sources = g_malloc0(i);
 
@@ -442,15 +464,19 @@ int sh_intc_init(struct intc_desc *desc,
 
     desc->irqs = qemu_allocate_irqs(sh_intc_set_irq, desc, nr_sources);
  
-    desc->iomemtype = cpu_register_io_memory(sh_intc_readfn,
-					     sh_intc_writefn, desc,
-                                             DEVICE_NATIVE_ENDIAN);
+    memory_region_init_io(&desc->iomem, &sh_intc_ops, desc,
+                          "interrupt-controller", 0x100000000ULL);
+
+#define INT_REG_PARAMS(reg_struct, type, action, j) \
+        reg_struct->action##_reg, #type, #action, j
     if (desc->mask_regs) {
         for (i = 0; i < desc->nr_mask_regs; i++) {
 	    struct intc_mask_reg *mr = desc->mask_regs + i;
 
-	    sh_intc_register(desc, mr->set_reg);
-	    sh_intc_register(desc, mr->clr_reg);
+            j += sh_intc_register(sysmem, desc,
+                                  INT_REG_PARAMS(mr, mask, set, j));
+            j += sh_intc_register(sysmem, desc,
+                                  INT_REG_PARAMS(mr, mask, clr, j));
 	}
     }
 
@@ -458,10 +484,13 @@ int sh_intc_init(struct intc_desc *desc,
         for (i = 0; i < desc->nr_prio_regs; i++) {
 	    struct intc_prio_reg *pr = desc->prio_regs + i;
 
-	    sh_intc_register(desc, pr->set_reg);
-	    sh_intc_register(desc, pr->clr_reg);
+            j += sh_intc_register(sysmem, desc,
+                                  INT_REG_PARAMS(pr, prio, set, j));
+            j += sh_intc_register(sysmem, desc,
+                                  INT_REG_PARAMS(pr, prio, clr, j));
 	}
     }
+#undef INT_REG_PARAMS
 
     return 0;
 }
diff --git a/hw/sh_intc.h b/hw/sh_intc.h
index c117d6fb8c..80c9430577 100644
--- a/hw/sh_intc.h
+++ b/hw/sh_intc.h
@@ -3,6 +3,7 @@
 
 #include "qemu-common.h"
 #include "irq.h"
+#include "exec-memory.h"
 
 typedef unsigned char intc_enum;
 
@@ -46,6 +47,8 @@ struct intc_source {
 };
 
 struct intc_desc {
+    MemoryRegion iomem;
+    MemoryRegion *iomem_aliases;
     qemu_irq *irqs;
     struct intc_source *sources;
     int nr_sources;
@@ -53,7 +56,6 @@ struct intc_desc {
     int nr_mask_regs;
     struct intc_prio_reg *prio_regs;
     int nr_prio_regs;
-    int iomemtype;
     int pending; /* number of interrupt sources that has pending set */
 };
 
@@ -68,7 +70,8 @@ void sh_intc_register_sources(struct intc_desc *desc,
 			      struct intc_group *groups,
 			      int nr_groups);
 
-int sh_intc_init(struct intc_desc *desc,
+int sh_intc_init(MemoryRegion *sysmem,
+                 struct intc_desc *desc,
 		 int nr_sources,
 		 struct intc_mask_reg *mask_regs,
 		 int nr_mask_regs,
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index 36f39300d5..86f468e500 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -154,8 +154,8 @@ static int sh_pci_init_device(SysBusDevice *dev)
                              0, 0x224);
     isa_mmio_setup(&s->isa, 0x40000);
     sysbus_init_mmio_cb2(dev, sh_pci_map, sh_pci_unmap);
-    sysbus_init_mmio_region(dev, &s->memconfig_a7);
-    sysbus_init_mmio_region(dev, &s->isa);
+    sysbus_init_mmio(dev, &s->memconfig_a7);
+    sysbus_init_mmio(dev, &s->isa);
     s->dev = pci_create_simple(s->bus, PCI_DEVFN(0, 0), "sh_pci_host");
     return 0;
 }
diff --git a/hw/sh_serial.c b/hw/sh_serial.c
index a20c59ef77..43b0eb1c1d 100644
--- a/hw/sh_serial.c
+++ b/hw/sh_serial.c
@@ -27,6 +27,7 @@
 #include "hw.h"
 #include "sh.h"
 #include "qemu-char.h"
+#include "exec-memory.h"
 
 //#define DEBUG_SERIAL
 
@@ -39,6 +40,9 @@
 #define SH_RX_FIFO_LENGTH (16)
 
 typedef struct {
+    MemoryRegion iomem;
+    MemoryRegion iomem_p4;
+    MemoryRegion iomem_a7;
     uint8_t smr;
     uint8_t brr;
     uint8_t scr;
@@ -74,7 +78,8 @@ static void sh_serial_clear_fifo(sh_serial_state * s)
     s->rx_tail = 0;
 }
 
-static void sh_serial_write(void *opaque, uint32_t offs, uint32_t val)
+static void sh_serial_write(void *opaque, target_phys_addr_t offs,
+                            uint64_t val, unsigned size)
 {
     sh_serial_state *s = opaque;
     unsigned char ch;
@@ -185,7 +190,8 @@ static void sh_serial_write(void *opaque, uint32_t offs, uint32_t val)
     abort();
 }
 
-static uint32_t sh_serial_read(void *opaque, uint32_t offs)
+static uint64_t sh_serial_read(void *opaque, target_phys_addr_t offs,
+                               unsigned size)
 {
     sh_serial_state *s = opaque;
     uint32_t ret = ~0;
@@ -338,28 +344,22 @@ static void sh_serial_event(void *opaque, int event)
         sh_serial_receive_break(s);
 }
 
-static CPUReadMemoryFunc * const sh_serial_readfn[] = {
-    &sh_serial_read,
-    &sh_serial_read,
-    &sh_serial_read,
+static const MemoryRegionOps sh_serial_ops = {
+    .read = sh_serial_read,
+    .write = sh_serial_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const sh_serial_writefn[] = {
-    &sh_serial_write,
-    &sh_serial_write,
-    &sh_serial_write,
-};
-
-void sh_serial_init (target_phys_addr_t base, int feat,
-		     uint32_t freq, CharDriverState *chr,
-		     qemu_irq eri_source,
-		     qemu_irq rxi_source,
-		     qemu_irq txi_source,
-		     qemu_irq tei_source,
-		     qemu_irq bri_source)
+void sh_serial_init(MemoryRegion *sysmem,
+                    target_phys_addr_t base, int feat,
+                    uint32_t freq, CharDriverState *chr,
+                    qemu_irq eri_source,
+                    qemu_irq rxi_source,
+                    qemu_irq txi_source,
+                    qemu_irq tei_source,
+                    qemu_irq bri_source)
 {
     sh_serial_state *s;
-    int s_io_memory;
 
     s = g_malloc0(sizeof(sh_serial_state));
 
@@ -381,11 +381,16 @@ void sh_serial_init (target_phys_addr_t base, int feat,
 
     sh_serial_clear_fifo(s);
 
-    s_io_memory = cpu_register_io_memory(sh_serial_readfn,
-					 sh_serial_writefn, s,
-                                         DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(P4ADDR(base), 0x28, s_io_memory);
-    cpu_register_physical_memory(A7ADDR(base), 0x28, s_io_memory);
+    memory_region_init_io(&s->iomem, &sh_serial_ops, s,
+                          "serial", 0x100000000ULL);
+
+    memory_region_init_alias(&s->iomem_p4, "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,
+                             0, 0x28);
+    memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
 
     s->chr = chr;
 
diff --git a/hw/sh_timer.c b/hw/sh_timer.c
index dca3c94210..d2c0cec835 100644
--- a/hw/sh_timer.c
+++ b/hw/sh_timer.c
@@ -11,6 +11,7 @@
 #include "hw.h"
 #include "sh.h"
 #include "qemu-timer.h"
+#include "exec-memory.h"
 
 //#define DEBUG_TIMER
 
@@ -210,6 +211,9 @@ static void *sh_timer_init(uint32_t freq, int feat, qemu_irq irq)
 }
 
 typedef struct {
+    MemoryRegion iomem;
+    MemoryRegion iomem_p4;
+    MemoryRegion iomem_a7;
     void *timer[3];
     int level[3];
     uint32_t tocr;
@@ -217,7 +221,8 @@ typedef struct {
     int feat;
 } tmu012_state;
 
-static uint32_t tmu012_read(void *opaque, target_phys_addr_t offset)
+static uint64_t tmu012_read(void *opaque, target_phys_addr_t offset,
+                            unsigned size)
 {
     tmu012_state *s = (tmu012_state *)opaque;
 
@@ -248,7 +253,7 @@ static uint32_t tmu012_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void tmu012_write(void *opaque, target_phys_addr_t offset,
-                        uint32_t value)
+                        uint64_t value, unsigned size)
 {
     tmu012_state *s = (tmu012_state *)opaque;
 
@@ -291,23 +296,17 @@ static void tmu012_write(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static CPUReadMemoryFunc * const tmu012_readfn[] = {
-    tmu012_read,
-    tmu012_read,
-    tmu012_read
+static const MemoryRegionOps tmu012_ops = {
+    .read = tmu012_read,
+    .write = tmu012_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const tmu012_writefn[] = {
-    tmu012_write,
-    tmu012_write,
-    tmu012_write
-};
-
-void tmu012_init(target_phys_addr_t base, int feat, uint32_t freq,
+void tmu012_init(MemoryRegion *sysmem, target_phys_addr_t base,
+                 int feat, uint32_t freq,
 		 qemu_irq ch0_irq, qemu_irq ch1_irq,
 		 qemu_irq ch2_irq0, qemu_irq ch2_irq1)
 {
-    int iomemtype;
     tmu012_state *s;
     int timer_feat = (feat & TMU012_FEAT_EXTCLK) ? TIMER_FEAT_EXTCLK : 0;
 
@@ -318,10 +317,16 @@ void tmu012_init(target_phys_addr_t base, int feat, uint32_t freq,
     if (feat & TMU012_FEAT_3CHAN)
         s->timer[2] = sh_timer_init(freq, timer_feat | TIMER_FEAT_CAPT,
 				    ch2_irq0); /* ch2_irq1 not supported */
-    iomemtype = cpu_register_io_memory(tmu012_readfn,
-                                       tmu012_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(P4ADDR(base), 0x00001000, iomemtype);
-    cpu_register_physical_memory(A7ADDR(base), 0x00001000, iomemtype);
+
+    memory_region_init_io(&s->iomem, &tmu012_ops, s,
+                          "timer", 0x100000000ULL);
+
+    memory_region_init_alias(&s->iomem_p4, "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",
+                             &s->iomem, 0, 0x1000);
+    memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
     /* ??? Save/restore.  */
 }
diff --git a/hw/shix.c b/hw/shix.c
index dbf47642df..e0c2200777 100644
--- a/hw/shix.c
+++ b/hw/shix.c
@@ -32,6 +32,7 @@
 #include "sysemu.h"
 #include "boards.h"
 #include "loader.h"
+#include "exec-memory.h"
 
 #define BIOS_FILENAME "shix_bios.bin"
 #define BIOS_ADDRESS 0xA0000000
@@ -44,6 +45,9 @@ static void shix_init(ram_addr_t ram_size,
     int ret;
     CPUState *env;
     struct SH7750State *s;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *rom = g_new(MemoryRegion, 1);
+    MemoryRegion *sdram = g_new(MemoryRegion, 2);
     
     if (!cpu_model)
         cpu_model = "any";
@@ -53,11 +57,15 @@ static void shix_init(ram_addr_t ram_size,
 
     /* Allocate memory space */
     printf("Allocating ROM\n");
-    cpu_register_physical_memory(0x00000000, 0x00004000, IO_MEM_ROM);
+    memory_region_init_ram(rom, NULL, "shix.rom", 0x4000);
+    memory_region_set_readonly(rom, true);
+    memory_region_add_subregion(sysmem, 0x00000000, rom);
     printf("Allocating SDRAM 1\n");
-    cpu_register_physical_memory(0x08000000, 0x01000000, 0x00004000);
+    memory_region_init_ram(&sdram[0], NULL, "shix.sdram1", 0x01000000);
+    memory_region_add_subregion(sysmem, 0x08000000, &sdram[0]);
     printf("Allocating SDRAM 2\n");
-    cpu_register_physical_memory(0x0c000000, 0x01000000, 0x01004000);
+    memory_region_init_ram(&sdram[1], NULL, "shix.sdram2", 0x01000000);
+    memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]);
 
     /* Load BIOS in 0 (and access it through P2, 0xA0000000) */
     if (bios_name == NULL)
@@ -72,7 +80,7 @@ static void shix_init(ram_addr_t ram_size,
     }
 
     /* Register peripherals */
-    s = sh7750_init(env);
+    s = sh7750_init(env, sysmem);
     /* XXXXX Check success */
     tc58128_init(s, "shix_linux_nand.bin", NULL);
     fprintf(stderr, "initialization terminated\n");
diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index 329c251845..9925e6460b 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -46,6 +46,7 @@
 struct SLAVIO_INTCTLState;
 
 typedef struct SLAVIO_CPUINTCTLState {
+    MemoryRegion iomem;
     struct SLAVIO_INTCTLState *master;
     uint32_t intreg_pending;
     uint32_t cpu;
@@ -54,6 +55,7 @@ typedef struct SLAVIO_CPUINTCTLState {
 
 typedef struct SLAVIO_INTCTLState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
 #ifdef DEBUG_IRQ_COUNT
     uint64_t irq_count[32];
 #endif
@@ -76,7 +78,8 @@ typedef struct SLAVIO_INTCTLState {
 static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs);
 
 // per-cpu interrupt controller
-static uint32_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr,
+                                        unsigned size)
 {
     SLAVIO_CPUINTCTLState *s = opaque;
     uint32_t saddr, ret;
@@ -96,7 +99,7 @@ static uint32_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr)
 }
 
 static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr,
-                                     uint32_t val)
+                                     uint64_t val, unsigned size)
 {
     SLAVIO_CPUINTCTLState *s = opaque;
     uint32_t saddr;
@@ -121,20 +124,19 @@ static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const slavio_intctl_mem_read[3] = {
-    NULL,
-    NULL,
-    slavio_intctl_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const slavio_intctl_mem_write[3] = {
-    NULL,
-    NULL,
-    slavio_intctl_mem_writel,
+static const MemoryRegionOps slavio_intctl_mem_ops = {
+    .read = slavio_intctl_mem_readl,
+    .write = slavio_intctl_mem_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 // master system interrupt controller
-static uint32_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr,
+                                         unsigned size)
 {
     SLAVIO_INTCTLState *s = opaque;
     uint32_t saddr, ret;
@@ -160,7 +162,7 @@ static uint32_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr)
 }
 
 static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr,
-                                      uint32_t val)
+                                      uint64_t val, unsigned size)
 {
     SLAVIO_INTCTLState *s = opaque;
     uint32_t saddr;
@@ -192,16 +194,14 @@ static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const slavio_intctlm_mem_read[3] = {
-    NULL,
-    NULL,
-    slavio_intctlm_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const slavio_intctlm_mem_write[3] = {
-    NULL,
-    NULL,
-    slavio_intctlm_mem_writel,
+static const MemoryRegionOps slavio_intctlm_mem_ops = {
+    .read = slavio_intctlm_mem_readl,
+    .write = slavio_intctlm_mem_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 void slavio_pic_info(Monitor *mon, DeviceState *dev)
@@ -422,24 +422,23 @@ static void slavio_intctl_reset(DeviceState *d)
 static int slavio_intctl_init1(SysBusDevice *dev)
 {
     SLAVIO_INTCTLState *s = FROM_SYSBUS(SLAVIO_INTCTLState, dev);
-    int io_memory;
     unsigned int i, j;
+    char slave_name[45];
 
     qdev_init_gpio_in(&dev->qdev, slavio_set_irq_all, 32 + MAX_CPUS);
-    io_memory = cpu_register_io_memory(slavio_intctlm_mem_read,
-                                       slavio_intctlm_mem_write, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, INTCTLM_SIZE, io_memory);
+    memory_region_init_io(&s->iomem, &slavio_intctlm_mem_ops, s,
+                          "master-interrupt-controller", INTCTLM_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
 
     for (i = 0; i < MAX_CPUS; i++) {
+        snprintf(slave_name, sizeof(slave_name),
+                 "slave-interrupt-controller-%i", i);
         for (j = 0; j < MAX_PILS; j++) {
             sysbus_init_irq(dev, &s->cpu_irqs[i][j]);
         }
-        io_memory = cpu_register_io_memory(slavio_intctl_mem_read,
-                                           slavio_intctl_mem_write,
-                                           &s->slaves[i],
-                                           DEVICE_NATIVE_ENDIAN);
-        sysbus_init_mmio(dev, INTCTL_SIZE, io_memory);
+        memory_region_init_io(&s->slaves[i].iomem, &slavio_intctl_mem_ops,
+                              &s->slaves[i], slave_name, INTCTL_SIZE);
+        sysbus_init_mmio(dev, &s->slaves[i].iomem);
         s->slaves[i].cpu = i;
         s->slaves[i].master = s;
     }
diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index 1f5a2d7330..484301c48a 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -36,6 +36,13 @@
 
 typedef struct MiscState {
     SysBusDevice busdev;
+    MemoryRegion cfg_iomem;
+    MemoryRegion diag_iomem;
+    MemoryRegion mdm_iomem;
+    MemoryRegion led_iomem;
+    MemoryRegion sysctrl_iomem;
+    MemoryRegion aux1_iomem;
+    MemoryRegion aux2_iomem;
     qemu_irq irq;
     qemu_irq fdc_tc;
     uint32_t dummy;
@@ -48,6 +55,7 @@ typedef struct MiscState {
 
 typedef struct APCState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     qemu_irq cpu_halt;
 } APCState;
 
@@ -100,7 +108,7 @@ static void slavio_set_power_fail(void *opaque, int irq, int power_failing)
 }
 
 static void slavio_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                  uint32_t val)
+                                  uint64_t val, unsigned size)
 {
     MiscState *s = opaque;
 
@@ -109,7 +117,8 @@ static void slavio_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
     slavio_misc_update_irq(s);
 }
 
-static uint32_t slavio_cfg_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_cfg_mem_readb(void *opaque, target_phys_addr_t addr,
+                                     unsigned size)
 {
     MiscState *s = opaque;
     uint32_t ret = 0;
@@ -119,20 +128,18 @@ static uint32_t slavio_cfg_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static CPUReadMemoryFunc * const slavio_cfg_mem_read[3] = {
-    slavio_cfg_mem_readb,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const slavio_cfg_mem_write[3] = {
-    slavio_cfg_mem_writeb,
-    NULL,
-    NULL,
+static const MemoryRegionOps slavio_cfg_mem_ops = {
+    .read = slavio_cfg_mem_readb,
+    .write = slavio_cfg_mem_writeb,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static void slavio_diag_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                   uint32_t val)
+                                   uint64_t val, unsigned size)
 {
     MiscState *s = opaque;
 
@@ -140,7 +147,8 @@ static void slavio_diag_mem_writeb(void *opaque, target_phys_addr_t addr,
     s->diag = val & 0xff;
 }
 
-static uint32_t slavio_diag_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_diag_mem_readb(void *opaque, target_phys_addr_t addr,
+                                      unsigned size)
 {
     MiscState *s = opaque;
     uint32_t ret = 0;
@@ -150,20 +158,18 @@ static uint32_t slavio_diag_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static CPUReadMemoryFunc * const slavio_diag_mem_read[3] = {
-    slavio_diag_mem_readb,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const slavio_diag_mem_write[3] = {
-    slavio_diag_mem_writeb,
-    NULL,
-    NULL,
+static const MemoryRegionOps slavio_diag_mem_ops = {
+    .read = slavio_diag_mem_readb,
+    .write = slavio_diag_mem_writeb,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static void slavio_mdm_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                  uint32_t val)
+                                  uint64_t val, unsigned size)
 {
     MiscState *s = opaque;
 
@@ -171,7 +177,8 @@ static void slavio_mdm_mem_writeb(void *opaque, target_phys_addr_t addr,
     s->mctrl = val & 0xff;
 }
 
-static uint32_t slavio_mdm_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_mdm_mem_readb(void *opaque, target_phys_addr_t addr,
+                                     unsigned size)
 {
     MiscState *s = opaque;
     uint32_t ret = 0;
@@ -181,20 +188,18 @@ static uint32_t slavio_mdm_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static CPUReadMemoryFunc * const slavio_mdm_mem_read[3] = {
-    slavio_mdm_mem_readb,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const slavio_mdm_mem_write[3] = {
-    slavio_mdm_mem_writeb,
-    NULL,
-    NULL,
+static const MemoryRegionOps slavio_mdm_mem_ops = {
+    .read = slavio_mdm_mem_readb,
+    .write = slavio_mdm_mem_writeb,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static void slavio_aux1_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                   uint32_t val)
+                                   uint64_t val, unsigned size)
 {
     MiscState *s = opaque;
 
@@ -210,7 +215,8 @@ static void slavio_aux1_mem_writeb(void *opaque, target_phys_addr_t addr,
     s->aux1 = val & 0xff;
 }
 
-static uint32_t slavio_aux1_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_aux1_mem_readb(void *opaque, target_phys_addr_t addr,
+                                      unsigned size)
 {
     MiscState *s = opaque;
     uint32_t ret = 0;
@@ -220,20 +226,18 @@ static uint32_t slavio_aux1_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static CPUReadMemoryFunc * const slavio_aux1_mem_read[3] = {
-    slavio_aux1_mem_readb,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const slavio_aux1_mem_write[3] = {
-    slavio_aux1_mem_writeb,
-    NULL,
-    NULL,
+static const MemoryRegionOps slavio_aux1_mem_ops = {
+    .read = slavio_aux1_mem_readb,
+    .write = slavio_aux1_mem_writeb,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static void slavio_aux2_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                   uint32_t val)
+                                   uint64_t val, unsigned size)
 {
     MiscState *s = opaque;
 
@@ -248,7 +252,8 @@ static void slavio_aux2_mem_writeb(void *opaque, target_phys_addr_t addr,
     slavio_misc_update_irq(s);
 }
 
-static uint32_t slavio_aux2_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_aux2_mem_readb(void *opaque, target_phys_addr_t addr,
+                                      unsigned size)
 {
     MiscState *s = opaque;
     uint32_t ret = 0;
@@ -258,19 +263,18 @@ static uint32_t slavio_aux2_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static CPUReadMemoryFunc * const slavio_aux2_mem_read[3] = {
-    slavio_aux2_mem_readb,
-    NULL,
-    NULL,
+static const MemoryRegionOps slavio_aux2_mem_ops = {
+    .read = slavio_aux2_mem_readb,
+    .write = slavio_aux2_mem_writeb,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
-static CPUWriteMemoryFunc * const slavio_aux2_mem_write[3] = {
-    slavio_aux2_mem_writeb,
-    NULL,
-    NULL,
-};
-
-static void apc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void apc_mem_writeb(void *opaque, target_phys_addr_t addr,
+                           uint64_t val, unsigned size)
 {
     APCState *s = opaque;
 
@@ -278,7 +282,8 @@ static void apc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
     qemu_irq_raise(s->cpu_halt);
 }
 
-static uint32_t apc_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t apc_mem_readb(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     uint32_t ret = 0;
 
@@ -286,19 +291,18 @@ static uint32_t apc_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static CPUReadMemoryFunc * const apc_mem_read[3] = {
-    apc_mem_readb,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const apc_mem_write[3] = {
-    apc_mem_writeb,
-    NULL,
-    NULL,
+static const MemoryRegionOps apc_mem_ops = {
+    .read = apc_mem_readb,
+    .write = apc_mem_writeb,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    }
 };
 
-static uint32_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr,
+                                         unsigned size)
 {
     MiscState *s = opaque;
     uint32_t ret = 0;
@@ -315,7 +319,7 @@ static uint32_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr)
 }
 
 static void slavio_sysctrl_mem_writel(void *opaque, target_phys_addr_t addr,
-                                      uint32_t val)
+                                      uint64_t val, unsigned size)
 {
     MiscState *s = opaque;
 
@@ -332,19 +336,18 @@ static void slavio_sysctrl_mem_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const slavio_sysctrl_mem_read[3] = {
-    NULL,
-    NULL,
-    slavio_sysctrl_mem_readl,
+static const MemoryRegionOps slavio_sysctrl_mem_ops = {
+    .read = slavio_sysctrl_mem_readl,
+    .write = slavio_sysctrl_mem_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
-static CPUWriteMemoryFunc * const slavio_sysctrl_mem_write[3] = {
-    NULL,
-    NULL,
-    slavio_sysctrl_mem_writel,
-};
-
-static uint32_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr,
+                                     unsigned size)
 {
     MiscState *s = opaque;
     uint32_t ret = 0;
@@ -361,7 +364,7 @@ static uint32_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr)
 }
 
 static void slavio_led_mem_writew(void *opaque, target_phys_addr_t addr,
-                                  uint32_t val)
+                                  uint64_t val, unsigned size)
 {
     MiscState *s = opaque;
 
@@ -375,16 +378,14 @@ static void slavio_led_mem_writew(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const slavio_led_mem_read[3] = {
-    NULL,
-    slavio_led_mem_readw,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const slavio_led_mem_write[3] = {
-    NULL,
-    slavio_led_mem_writew,
-    NULL,
+static const MemoryRegionOps slavio_led_mem_ops = {
+    .read = slavio_led_mem_readw,
+    .write = slavio_led_mem_writew,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 2,
+        .max_access_size = 2,
+    },
 };
 
 static const VMStateDescription vmstate_misc = {
@@ -407,69 +408,60 @@ static const VMStateDescription vmstate_misc = {
 static int apc_init1(SysBusDevice *dev)
 {
     APCState *s = FROM_SYSBUS(APCState, dev);
-    int io;
 
     sysbus_init_irq(dev, &s->cpu_halt);
 
     /* Power management (APC) XXX: not a Slavio device */
-    io = cpu_register_io_memory(apc_mem_read, apc_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, MISC_SIZE, io);
+    memory_region_init_io(&s->iomem, &apc_mem_ops, s,
+                          "apc", MISC_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
 static int slavio_misc_init1(SysBusDevice *dev)
 {
     MiscState *s = FROM_SYSBUS(MiscState, dev);
-    int io;
 
     sysbus_init_irq(dev, &s->irq);
     sysbus_init_irq(dev, &s->fdc_tc);
 
     /* 8 bit registers */
     /* Slavio control */
-    io = cpu_register_io_memory(slavio_cfg_mem_read,
-                                slavio_cfg_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, MISC_SIZE, io);
+    memory_region_init_io(&s->cfg_iomem, &slavio_cfg_mem_ops, s,
+                          "configuration", MISC_SIZE);
+    sysbus_init_mmio(dev, &s->cfg_iomem);
 
     /* Diagnostics */
-    io = cpu_register_io_memory(slavio_diag_mem_read,
-                                slavio_diag_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, MISC_SIZE, io);
+    memory_region_init_io(&s->diag_iomem, &slavio_diag_mem_ops, s,
+                          "diagnostic", MISC_SIZE);
+    sysbus_init_mmio(dev, &s->diag_iomem);
 
     /* Modem control */
-    io = cpu_register_io_memory(slavio_mdm_mem_read,
-                                slavio_mdm_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, MISC_SIZE, io);
+    memory_region_init_io(&s->mdm_iomem, &slavio_mdm_mem_ops, s,
+                          "modem", MISC_SIZE);
+    sysbus_init_mmio(dev, &s->mdm_iomem);
 
     /* 16 bit registers */
     /* ss600mp diag LEDs */
-    io = cpu_register_io_memory(slavio_led_mem_read,
-                                slavio_led_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, MISC_SIZE, io);
+    memory_region_init_io(&s->led_iomem, &slavio_led_mem_ops, s,
+                          "leds", MISC_SIZE);
+    sysbus_init_mmio(dev, &s->led_iomem);
 
     /* 32 bit registers */
     /* System control */
-    io = cpu_register_io_memory(slavio_sysctrl_mem_read,
-                                slavio_sysctrl_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, SYSCTRL_SIZE, io);
+    memory_region_init_io(&s->sysctrl_iomem, &slavio_sysctrl_mem_ops, s,
+                          "system-control", MISC_SIZE);
+    sysbus_init_mmio(dev, &s->sysctrl_iomem);
 
     /* AUX 1 (Misc System Functions) */
-    io = cpu_register_io_memory(slavio_aux1_mem_read,
-                                slavio_aux1_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, MISC_SIZE, io);
+    memory_region_init_io(&s->aux1_iomem, &slavio_aux1_mem_ops, s,
+                          "misc-system-functions", MISC_SIZE);
+    sysbus_init_mmio(dev, &s->aux1_iomem);
 
     /* AUX 2 (Software Powerdown Control) */
-    io = cpu_register_io_memory(slavio_aux2_mem_read,
-                                slavio_aux2_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, MISC_SIZE, io);
+    memory_region_init_io(&s->aux2_iomem, &slavio_aux2_mem_ops, s,
+                          "software-powerdown-control", MISC_SIZE);
+    sysbus_init_mmio(dev, &s->aux2_iomem);
 
     qdev_init_gpio_in(&dev->qdev, slavio_set_power_fail, 1);
 
diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c
index 84449baa71..2353c43bda 100644
--- a/hw/slavio_timer.c
+++ b/hw/slavio_timer.c
@@ -61,6 +61,7 @@ typedef struct SLAVIO_TIMERState {
 } SLAVIO_TIMERState;
 
 typedef struct TimerContext {
+    MemoryRegion iomem;
     SLAVIO_TIMERState *s;
     unsigned int timer_index; /* 0 for system, 1 ... MAX_CPUS for CPU timers */
 } TimerContext;
@@ -128,7 +129,8 @@ static void slavio_timer_irq(void *opaque)
     }
 }
 
-static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr,
+                                       unsigned size)
 {
     TimerContext *tc = opaque;
     SLAVIO_TIMERState *s = tc->s;
@@ -188,7 +190,7 @@ static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
 }
 
 static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr,
-                                    uint32_t val)
+                                    uint64_t val, unsigned size)
 {
     TimerContext *tc = opaque;
     SLAVIO_TIMERState *s = tc->s;
@@ -311,16 +313,14 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const slavio_timer_mem_read[3] = {
-    NULL,
-    NULL,
-    slavio_timer_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const slavio_timer_mem_write[3] = {
-    NULL,
-    NULL,
-    slavio_timer_mem_writel,
+static const MemoryRegionOps slavio_timer_mem_ops = {
+    .read = slavio_timer_mem_readl,
+    .write = slavio_timer_mem_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static const VMStateDescription vmstate_timer = {
@@ -374,13 +374,15 @@ static void slavio_timer_reset(DeviceState *d)
 
 static int slavio_timer_init1(SysBusDevice *dev)
 {
-    int io;
     SLAVIO_TIMERState *s = FROM_SYSBUS(SLAVIO_TIMERState, dev);
     QEMUBH *bh;
     unsigned int i;
     TimerContext *tc;
 
     for (i = 0; i <= MAX_CPUS; i++) {
+        uint64_t size;
+        char timer_name[20];
+
         tc = g_malloc0(sizeof(TimerContext));
         tc->s = s;
         tc->timer_index = i;
@@ -389,14 +391,11 @@ static int slavio_timer_init1(SysBusDevice *dev)
         s->cputimer[i].timer = ptimer_init(bh);
         ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
 
-        io = cpu_register_io_memory(slavio_timer_mem_read,
-                                    slavio_timer_mem_write, tc,
-                                    DEVICE_NATIVE_ENDIAN);
-        if (i == 0) {
-            sysbus_init_mmio(dev, SYS_TIMER_SIZE, io);
-        } else {
-            sysbus_init_mmio(dev, CPU_TIMER_SIZE, io);
-        }
+        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,
+                              timer_name, size);
+        sysbus_init_mmio(dev, &tc->iomem);
 
         sysbus_init_irq(dev, &s->cputimer[i].irq);
     }
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index fc8c4984a7..9a3eddf25d 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -748,7 +748,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,
                           "smc91c111-mmio", 16);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
     sysbus_init_irq(dev, &s->irq);
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     s->nic = qemu_new_nic(&net_smc91c111_info, &s->conf,
diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c
index e75694bec2..035d2e205b 100644
--- a/hw/sparc32_dma.c
+++ b/hw/sparc32_dma.c
@@ -64,6 +64,7 @@ typedef struct DMAState DMAState;
 
 struct DMAState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t dmaregs[DMA_REGS];
     qemu_irq irq;
     void *iommu;
@@ -164,7 +165,8 @@ void espdma_memory_write(void *opaque, uint8_t *buf, int len)
     s->dmaregs[1] += len;
 }
 
-static uint32_t dma_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t dma_mem_read(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
 {
     DMAState *s = opaque;
     uint32_t saddr;
@@ -180,7 +182,8 @@ static uint32_t dma_mem_readl(void *opaque, target_phys_addr_t addr)
     return s->dmaregs[saddr];
 }
 
-static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void dma_mem_write(void *opaque, target_phys_addr_t addr,
+                          uint64_t val, unsigned size)
 {
     DMAState *s = opaque;
     uint32_t saddr;
@@ -234,16 +237,14 @@ static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
-static CPUReadMemoryFunc * const dma_mem_read[3] = {
-    NULL,
-    NULL,
-    dma_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const dma_mem_write[3] = {
-    NULL,
-    NULL,
-    dma_mem_writel,
+static const MemoryRegionOps dma_mem_ops = {
+    .read = dma_mem_read,
+    .write = dma_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static void dma_reset(DeviceState *d)
@@ -268,15 +269,13 @@ static const VMStateDescription vmstate_dma = {
 static int sparc32_dma_init1(SysBusDevice *dev)
 {
     DMAState *s = FROM_SYSBUS(DMAState, dev);
-    int dma_io_memory;
     int reg_size;
 
     sysbus_init_irq(dev, &s->irq);
 
-    dma_io_memory = cpu_register_io_memory(dma_mem_read, dma_mem_write, s,
-                                           DEVICE_NATIVE_ENDIAN);
     reg_size = s->is_ledma ? DMA_ETH_SIZE : DMA_SIZE;
-    sysbus_init_mmio(dev, reg_size, dma_io_memory);
+    memory_region_init_io(&s->iomem, &dma_mem_ops, s, "dma", reg_size);
+    sysbus_init_mmio(dev, &s->iomem);
 
     qdev_init_gpio_in(&dev->qdev, dma_set_irq, 1);
     qdev_init_gpio_out(&dev->qdev, s->gpio, 2);
diff --git a/hw/spitz.c b/hw/spitz.c
index 23f9d41ff7..df0e1466a2 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -167,7 +167,7 @@ static int sl_nand_init(SysBusDevice *dev) {
     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);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 2bf1c235dc..ce62a98158 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -45,6 +45,7 @@ typedef const struct {
 
 typedef struct gptm_state {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t config;
     uint32_t mode[2];
     uint32_t control;
@@ -140,7 +141,8 @@ static void gptm_tick(void *opaque)
     gptm_update_irq(s);
 }
 
-static uint32_t gptm_read(void *opaque, target_phys_addr_t offset)
+static uint64_t gptm_read(void *opaque, target_phys_addr_t offset,
+                          unsigned size)
 {
     gptm_state *s = (gptm_state *)opaque;
 
@@ -188,7 +190,8 @@ static uint32_t gptm_read(void *opaque, target_phys_addr_t offset)
     }
 }
 
-static void gptm_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+static void gptm_write(void *opaque, target_phys_addr_t offset,
+                       uint64_t value, unsigned size)
 {
     gptm_state *s = (gptm_state *)opaque;
     uint32_t oldval;
@@ -268,16 +271,10 @@ static void gptm_write(void *opaque, target_phys_addr_t offset, uint32_t value)
     gptm_update_irq(s);
 }
 
-static CPUReadMemoryFunc * const gptm_readfn[] = {
-   gptm_read,
-   gptm_read,
-   gptm_read
-};
-
-static CPUWriteMemoryFunc * const gptm_writefn[] = {
-   gptm_write,
-   gptm_write,
-   gptm_write
+static const MemoryRegionOps gptm_ops = {
+    .read = gptm_read,
+    .write = gptm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_stellaris_gptm = {
@@ -305,16 +302,14 @@ static const VMStateDescription vmstate_stellaris_gptm = {
 
 static int stellaris_gptm_init(SysBusDevice *dev)
 {
-    int iomemtype;
     gptm_state *s = FROM_SYSBUS(gptm_state, dev);
 
     sysbus_init_irq(dev, &s->irq);
     qdev_init_gpio_out(&dev->qdev, &s->trigger, 1);
 
-    iomemtype = cpu_register_io_memory(gptm_readfn,
-                                       gptm_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &gptm_ops, s,
+                          "gptm", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
 
     s->opaque[0] = s->opaque[1] = s;
     s->timer[0] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[0]);
@@ -327,6 +322,7 @@ static int stellaris_gptm_init(SysBusDevice *dev)
 /* System controller.  */
 
 typedef struct {
+    MemoryRegion iomem;
     uint32_t pborctl;
     uint32_t ldopctl;
     uint32_t int_status;
@@ -414,7 +410,8 @@ static int ssys_board_class(const ssys_state *s)
     }
 }
 
-static uint32_t ssys_read(void *opaque, target_phys_addr_t offset)
+static uint64_t ssys_read(void *opaque, target_phys_addr_t offset,
+                          unsigned size)
 {
     ssys_state *s = (ssys_state *)opaque;
 
@@ -518,7 +515,8 @@ static void ssys_calculate_system_clock(ssys_state *s)
     }
 }
 
-static void ssys_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+static void ssys_write(void *opaque, target_phys_addr_t offset,
+                       uint64_t value, unsigned size)
 {
     ssys_state *s = (ssys_state *)opaque;
 
@@ -602,16 +600,10 @@ static void ssys_write(void *opaque, target_phys_addr_t offset, uint32_t value)
     ssys_update(s);
 }
 
-static CPUReadMemoryFunc * const ssys_readfn[] = {
-   ssys_read,
-   ssys_read,
-   ssys_read
-};
-
-static CPUWriteMemoryFunc * const ssys_writefn[] = {
-   ssys_write,
-   ssys_write,
-   ssys_write
+static const MemoryRegionOps ssys_ops = {
+    .read = ssys_read,
+    .write = ssys_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void ssys_reset(void *opaque)
@@ -667,7 +659,6 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq,
                               stellaris_board_info * board,
                               uint8_t *macaddr)
 {
-    int iomemtype;
     ssys_state *s;
 
     s = (ssys_state *)g_malloc0(sizeof(ssys_state));
@@ -677,10 +668,8 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq,
     s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16);
     s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16);
 
-    iomemtype = cpu_register_io_memory(ssys_readfn,
-                                       ssys_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x00001000, iomemtype);
+    memory_region_init_io(&s->iomem, &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);
     return 0;
@@ -693,6 +682,7 @@ typedef struct {
     SysBusDevice busdev;
     i2c_bus *bus;
     qemu_irq irq;
+    MemoryRegion iomem;
     uint32_t msa;
     uint32_t mcs;
     uint32_t mdr;
@@ -710,7 +700,8 @@ typedef struct {
 #define STELLARIS_I2C_MCS_IDLE    0x20
 #define STELLARIS_I2C_MCS_BUSBSY  0x40
 
-static uint32_t stellaris_i2c_read(void *opaque, target_phys_addr_t offset)
+static uint64_t stellaris_i2c_read(void *opaque, target_phys_addr_t offset,
+                                   unsigned size)
 {
     stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
 
@@ -747,7 +738,7 @@ static void stellaris_i2c_update(stellaris_i2c_state *s)
 }
 
 static void stellaris_i2c_write(void *opaque, target_phys_addr_t offset,
-                                uint32_t value)
+                                uint64_t value, unsigned size)
 {
     stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
 
@@ -838,16 +829,10 @@ static void stellaris_i2c_reset(stellaris_i2c_state *s)
     stellaris_i2c_update(s);
 }
 
-static CPUReadMemoryFunc * const stellaris_i2c_readfn[] = {
-   stellaris_i2c_read,
-   stellaris_i2c_read,
-   stellaris_i2c_read
-};
-
-static CPUWriteMemoryFunc * const stellaris_i2c_writefn[] = {
-   stellaris_i2c_write,
-   stellaris_i2c_write,
-   stellaris_i2c_write
+static const MemoryRegionOps stellaris_i2c_ops = {
+    .read = stellaris_i2c_read,
+    .write = stellaris_i2c_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_stellaris_i2c = {
@@ -871,16 +856,14 @@ static int stellaris_i2c_init(SysBusDevice * dev)
 {
     stellaris_i2c_state *s = FROM_SYSBUS(stellaris_i2c_state, dev);
     i2c_bus *bus;
-    int iomemtype;
 
     sysbus_init_irq(dev, &s->irq);
     bus = i2c_init_bus(&dev->qdev, "i2c");
     s->bus = bus;
 
-    iomemtype = cpu_register_io_memory(stellaris_i2c_readfn,
-                                       stellaris_i2c_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &stellaris_i2c_ops, s,
+                          "i2c", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
     /* ??? For now we only implement the master interface.  */
     stellaris_i2c_reset(s);
     vmstate_register(&dev->qdev, -1, &vmstate_stellaris_i2c, s);
@@ -904,6 +887,7 @@ static int stellaris_i2c_init(SysBusDevice * dev)
 typedef struct
 {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t actss;
     uint32_t ris;
     uint32_t im;
@@ -1004,7 +988,8 @@ static void stellaris_adc_reset(stellaris_adc_state *s)
     }
 }
 
-static uint32_t stellaris_adc_read(void *opaque, target_phys_addr_t offset)
+static uint64_t stellaris_adc_read(void *opaque, target_phys_addr_t offset,
+                                   unsigned size)
 {
     stellaris_adc_state *s = (stellaris_adc_state *)opaque;
 
@@ -1052,7 +1037,7 @@ static uint32_t stellaris_adc_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void stellaris_adc_write(void *opaque, target_phys_addr_t offset,
-                                uint32_t value)
+                                uint64_t value, unsigned size)
 {
     stellaris_adc_state *s = (stellaris_adc_state *)opaque;
 
@@ -1066,7 +1051,7 @@ static void stellaris_adc_write(void *opaque, target_phys_addr_t offset,
             return;
         case 0x04: /* SSCTL */
             if (value != 6) {
-                hw_error("ADC: Unimplemented sequence %x\n",
+                hw_error("ADC: Unimplemented sequence %" PRIx64 "\n",
                           value);
             }
             s->ssctl[n] = value;
@@ -1109,16 +1094,10 @@ static void stellaris_adc_write(void *opaque, target_phys_addr_t offset,
     stellaris_adc_update(s);
 }
 
-static CPUReadMemoryFunc * const stellaris_adc_readfn[] = {
-   stellaris_adc_read,
-   stellaris_adc_read,
-   stellaris_adc_read
-};
-
-static CPUWriteMemoryFunc * const stellaris_adc_writefn[] = {
-   stellaris_adc_write,
-   stellaris_adc_write,
-   stellaris_adc_write
+static const MemoryRegionOps stellaris_adc_ops = {
+    .read = stellaris_adc_read,
+    .write = stellaris_adc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_stellaris_adc = {
@@ -1159,17 +1138,15 @@ static const VMStateDescription vmstate_stellaris_adc = {
 static int stellaris_adc_init(SysBusDevice *dev)
 {
     stellaris_adc_state *s = FROM_SYSBUS(stellaris_adc_state, dev);
-    int iomemtype;
     int n;
 
     for (n = 0; n < 4; n++) {
         sysbus_init_irq(dev, &s->irq[n]);
     }
 
-    iomemtype = cpu_register_io_memory(stellaris_adc_readfn,
-                                       stellaris_adc_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &stellaris_adc_ops, s,
+                          "adc", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
     stellaris_adc_reset(s);
     qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1);
     vmstate_register(&dev->qdev, -1, &vmstate_stellaris_adc, s);
diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c
index d5613ffffd..866c9a2381 100644
--- a/hw/stellaris_enet.c
+++ b/hw/stellaris_enet.c
@@ -406,7 +406,7 @@ static int stellaris_enet_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->mmio, &stellaris_enet_ops, s, "stellaris_enet",
                           0x1000);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
     sysbus_init_irq(dev, &s->irq);
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
 
diff --git a/hw/strongarm.c b/hw/strongarm.c
index a3d908051f..7c75bb912d 100644
--- a/hw/strongarm.c
+++ b/hw/strongarm.c
@@ -170,7 +170,7 @@ static int strongarm_pic_initfn(SysBusDevice *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);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     sysbus_init_irq(dev, &s->fiq);
 
@@ -371,7 +371,7 @@ static int strongarm_rtc_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->rtc_hz_irq);
 
     memory_region_init_io(&s->iomem, &strongarm_rtc_ops, s, "rtc", 0x10000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
@@ -617,7 +617,7 @@ static int strongarm_gpio_initfn(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &strongarm_gpio_ops, s, "gpio", 0x1000);
 
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     for (i = 0; i < 11; i++) {
         sysbus_init_irq(dev, &s->irqs[i]);
     }
@@ -779,7 +779,7 @@ static int strongarm_ppc_init(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &strongarm_ppc_ops, s, "ppc", 0x1000);
 
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
@@ -1165,7 +1165,7 @@ static int strongarm_uart_init(SysBusDevice *dev)
     StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev);
 
     memory_region_init_io(&s->iomem, &strongarm_uart_ops, s, "uart", 0x10000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
     s->rx_timeout_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_rx_to, s);
@@ -1446,7 +1446,7 @@ static int strongarm_ssp_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
 
     memory_region_init_io(&s->iomem, &strongarm_ssp_ops, s, "ssp", 0x1000);
-    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_mmio(dev, &s->iomem);
 
     s->bus = ssi_create_bus(&dev->qdev, "ssi");
     return 0;
diff --git a/hw/sun4c_intctl.c b/hw/sun4c_intctl.c
index 5c7fdeffb4..e15b1674ce 100644
--- a/hw/sun4c_intctl.c
+++ b/hw/sun4c_intctl.c
@@ -46,6 +46,7 @@
 
 typedef struct Sun4c_INTCTLState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
 #ifdef DEBUG_IRQ_COUNT
     uint64_t irq_count;
 #endif
@@ -60,7 +61,8 @@ typedef struct Sun4c_INTCTLState {
 
 static void sun4c_check_interrupts(void *opaque);
 
-static uint32_t sun4c_intctl_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t sun4c_intctl_mem_read(void *opaque, target_phys_addr_t addr,
+                                      unsigned size)
 {
     Sun4c_INTCTLState *s = opaque;
     uint32_t ret;
@@ -71,27 +73,25 @@ static uint32_t sun4c_intctl_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static void sun4c_intctl_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                    uint32_t val)
+static void sun4c_intctl_mem_write(void *opaque, target_phys_addr_t addr,
+                                   uint64_t val, unsigned size)
 {
     Sun4c_INTCTLState *s = opaque;
 
-    DPRINTF("write reg 0x" TARGET_FMT_plx " = %x\n", addr, val);
+    DPRINTF("write reg 0x" TARGET_FMT_plx " = %x\n", addr, (unsigned)val);
     val &= 0xbf;
     s->reg = val;
     sun4c_check_interrupts(s);
 }
 
-static CPUReadMemoryFunc * const sun4c_intctl_mem_read[3] = {
-    sun4c_intctl_mem_readb,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const sun4c_intctl_mem_write[3] = {
-    sun4c_intctl_mem_writeb,
-    NULL,
-    NULL,
+static const MemoryRegionOps sun4c_intctl_mem_ops = {
+    .read = sun4c_intctl_mem_read,
+    .write = sun4c_intctl_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 void sun4c_pic_info(Monitor *mon, void *opaque)
@@ -192,13 +192,11 @@ static void sun4c_intctl_reset(DeviceState *d)
 static int sun4c_intctl_init1(SysBusDevice *dev)
 {
     Sun4c_INTCTLState *s = FROM_SYSBUS(Sun4c_INTCTLState, dev);
-    int io_memory;
     unsigned int i;
 
-    io_memory = cpu_register_io_memory(sun4c_intctl_mem_read,
-                                       sun4c_intctl_mem_write, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, INTCTL_SIZE, io_memory);
+    memory_region_init_io(&s->iomem, &sun4c_intctl_mem_ops, s,
+                          "intctl", INTCTL_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
     qdev_init_gpio_in(&dev->qdev, sun4c_set_irq, 8);
 
     for (i = 0; i < MAX_PILS; i++) {
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 314edc4d87..3f172ad062 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -604,7 +604,7 @@ static int idreg_init1(SysBusDevice *dev)
 
     memory_region_init_ram(&s->mem, NULL, "sun4m.idreg", sizeof(idreg_data));
     memory_region_set_readonly(&s->mem, true);
-    sysbus_init_mmio_region(dev, &s->mem);
+    sysbus_init_mmio(dev, &s->mem);
     return 0;
 }
 
@@ -644,7 +644,7 @@ static int afx_init1(SysBusDevice *dev)
     AFXState *s = FROM_SYSBUS(AFXState, dev);
 
     memory_region_init_ram(&s->mem, NULL, "sun4m.afx", 4);
-    sysbus_init_mmio_region(dev, &s->mem);
+    sysbus_init_mmio(dev, &s->mem);
     return 0;
 }
 
@@ -713,7 +713,7 @@ static int prom_init1(SysBusDevice *dev)
 
     memory_region_init_ram(&s->prom, NULL, "sun4m.prom", PROM_SIZE_MAX);
     memory_region_set_readonly(&s->prom, true);
-    sysbus_init_mmio_region(dev, &s->prom);
+    sysbus_init_mmio(dev, &s->prom);
     return 0;
 }
 
@@ -746,7 +746,7 @@ static int ram_init1(SysBusDevice *dev)
     RamDevice *d = FROM_SYSBUS(RamDevice, dev);
 
     memory_region_init_ram(&d->ram, NULL, "sun4m.ram", d->size);
-    sysbus_init_mmio_region(dev, &d->ram);
+    sysbus_init_mmio(dev, &d->ram);
     return 0;
 }
 
diff --git a/hw/sun4m_iommu.c b/hw/sun4m_iommu.c
index 6eeadfa184..ef7627c467 100644
--- a/hw/sun4m_iommu.c
+++ b/hw/sun4m_iommu.c
@@ -128,13 +128,15 @@
 
 typedef struct IOMMUState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t regs[IOMMU_NREGS];
     target_phys_addr_t iostart;
     qemu_irq irq;
     uint32_t version;
 } IOMMUState;
 
-static uint32_t iommu_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t iommu_mem_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     IOMMUState *s = opaque;
     target_phys_addr_t saddr;
@@ -155,8 +157,8 @@ static uint32_t iommu_mem_readl(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static void iommu_mem_writel(void *opaque, target_phys_addr_t addr,
-                             uint32_t val)
+static void iommu_mem_write(void *opaque, target_phys_addr_t addr,
+                            uint64_t val, unsigned size)
 {
     IOMMUState *s = opaque;
     target_phys_addr_t saddr;
@@ -237,16 +239,14 @@ static void iommu_mem_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const iommu_mem_read[3] = {
-    NULL,
-    NULL,
-    iommu_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const iommu_mem_write[3] = {
-    NULL,
-    NULL,
-    iommu_mem_writel,
+static const MemoryRegionOps iommu_mem_ops = {
+    .read = iommu_mem_read,
+    .write = iommu_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static uint32_t iommu_page_get_flags(IOMMUState *s, target_phys_addr_t addr)
@@ -347,13 +347,12 @@ static void iommu_reset(DeviceState *d)
 static int iommu_init1(SysBusDevice *dev)
 {
     IOMMUState *s = FROM_SYSBUS(IOMMUState, dev);
-    int io;
 
     sysbus_init_irq(dev, &s->irq);
 
-    io = cpu_register_io_memory(iommu_mem_read, iommu_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, IOMMU_NREGS * sizeof(uint32_t), io);
+    memory_region_init_io(&s->iomem, &iommu_mem_ops, s, "iommu",
+                          IOMMU_NREGS * sizeof(uint32_t));
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
diff --git a/hw/sun4u.c b/hw/sun4u.c
index eaaefe3c94..97600a942d 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -626,7 +626,7 @@ static int prom_init1(SysBusDevice *dev)
 
     memory_region_init_ram(&s->prom, NULL, "sun4u.prom", PROM_SIZE_MAX);
     memory_region_set_readonly(&s->prom, true);
-    sysbus_init_mmio_region(dev, &s->prom);
+    sysbus_init_mmio(dev, &s->prom);
     return 0;
 }
 
@@ -660,7 +660,7 @@ static int ram_init1(SysBusDevice *dev)
     RamDevice *d = FROM_SYSBUS(RamDevice, dev);
 
     memory_region_init_ram(&d->ram, NULL, "sun4u.ram", d->size);
-    sysbus_init_mmio_region(dev, &d->ram);
+    sysbus_init_mmio(dev, &d->ram);
     return 0;
 }
 
diff --git a/hw/syborg_fb.c b/hw/syborg_fb.c
index ae3e0ebc64..b87d7e6d10 100644
--- a/hw/syborg_fb.c
+++ b/hw/syborg_fb.c
@@ -65,6 +65,7 @@ enum {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     DisplayState *ds;
     /*QEMUConsole *console;*/
     uint32_t need_update : 1;
@@ -294,7 +295,8 @@ static void syborg_fb_invalidate_display(void * opaque)
     s->need_update = 1;
 }
 
-static uint32_t syborg_fb_read(void *opaque, target_phys_addr_t offset)
+static uint64_t syborg_fb_read(void *opaque, target_phys_addr_t offset,
+                               unsigned size)
 {
     SyborgFBState *s = opaque;
 
@@ -366,7 +368,7 @@ static uint32_t syborg_fb_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void syborg_fb_write(void *opaque, target_phys_addr_t offset,
-                            uint32_t val)
+                            uint64_t val, unsigned size)
 {
     SyborgFBState *s = opaque;
 
@@ -454,16 +456,10 @@ static void syborg_fb_write(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static CPUReadMemoryFunc * const syborg_fb_readfn[] = {
-    syborg_fb_read,
-    syborg_fb_read,
-    syborg_fb_read
-};
-
-static CPUWriteMemoryFunc * const syborg_fb_writefn[] = {
-    syborg_fb_write,
-    syborg_fb_write,
-    syborg_fb_write
+static const MemoryRegionOps syborg_fb_ops = {
+    .read = syborg_fb_read,
+    .write = syborg_fb_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void syborg_fb_save(QEMUFile *f, void *opaque)
@@ -515,13 +511,11 @@ static int syborg_fb_load(QEMUFile *f, void *opaque, int version_id)
 static int syborg_fb_init(SysBusDevice *dev)
 {
     SyborgFBState *s = FROM_SYSBUS(SyborgFBState, dev);
-    int iomemtype;
 
     sysbus_init_irq(dev, &s->irq);
-    iomemtype = cpu_register_io_memory(syborg_fb_readfn,
-                                       syborg_fb_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &syborg_fb_ops, s,
+                          "framebuffer", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
 
     s->ds = graphic_console_init(syborg_fb_update_display,
                                  syborg_fb_invalidate_display,
diff --git a/hw/syborg_interrupt.c b/hw/syborg_interrupt.c
index 1b0f3bb9b5..93e81c8660 100644
--- a/hw/syborg_interrupt.c
+++ b/hw/syborg_interrupt.c
@@ -55,6 +55,7 @@ typedef struct {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     int pending_count;
     uint32_t num_irqs;
     syborg_int_flags *flags;
@@ -84,7 +85,8 @@ static void syborg_int_set_irq(void *opaque, int irq, int level)
     }
 }
 
-static uint32_t syborg_int_read(void *opaque, target_phys_addr_t offset)
+static uint64_t syborg_int_read(void *opaque, target_phys_addr_t offset,
+                                unsigned size)
 {
     SyborgIntState *s = (SyborgIntState *)opaque;
     int i;
@@ -114,7 +116,8 @@ static uint32_t syborg_int_read(void *opaque, target_phys_addr_t offset)
     }
 }
 
-static void syborg_int_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+static void syborg_int_write(void *opaque, target_phys_addr_t offset,
+                             uint64_t value, unsigned size)
 {
     SyborgIntState *s = (SyborgIntState *)opaque;
     int i;
@@ -156,16 +159,10 @@ static void syborg_int_write(void *opaque, target_phys_addr_t offset, uint32_t v
     syborg_int_update(s);
 }
 
-static CPUReadMemoryFunc * const syborg_int_readfn[] = {
-    syborg_int_read,
-    syborg_int_read,
-    syborg_int_read
-};
-
-static CPUWriteMemoryFunc * const syborg_int_writefn[] = {
-    syborg_int_write,
-    syborg_int_write,
-    syborg_int_write
+static const MemoryRegionOps syborg_int_ops = {
+    .read = syborg_int_read,
+    .write = syborg_int_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void syborg_int_save(QEMUFile *f, void *opaque)
@@ -205,14 +202,12 @@ static int syborg_int_load(QEMUFile *f, void *opaque, int version_id)
 static int syborg_int_init(SysBusDevice *dev)
 {
     SyborgIntState *s = FROM_SYSBUS(SyborgIntState, dev);
-    int iomemtype;
 
     sysbus_init_irq(dev, &s->parent_irq);
     qdev_init_gpio_in(&dev->qdev, syborg_int_set_irq, s->num_irqs);
-    iomemtype = cpu_register_io_memory(syborg_int_readfn,
-                                       syborg_int_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &syborg_int_ops, s,
+                          "interrupt", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
     s->flags = g_malloc0(s->num_irqs * sizeof(syborg_int_flags));
 
     register_savevm(&dev->qdev, "syborg_int", -1, 1, syborg_int_save,
diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c
index 82b9dc088e..942a7dc800 100644
--- a/hw/syborg_keyboard.c
+++ b/hw/syborg_keyboard.c
@@ -51,6 +51,7 @@ enum {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t int_enabled;
     int extension_bit;
     uint32_t fifo_size;
@@ -66,7 +67,8 @@ static void syborg_keyboard_update(SyborgKeyboardState *s)
     qemu_set_irq(s->irq, level);
 }
 
-static uint32_t syborg_keyboard_read(void *opaque, target_phys_addr_t offset)
+static uint64_t syborg_keyboard_read(void *opaque, target_phys_addr_t offset,
+                                    unsigned size)
 {
     SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
     int c;
@@ -104,7 +106,7 @@ static uint32_t syborg_keyboard_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void syborg_keyboard_write(void *opaque, target_phys_addr_t offset,
-                                  uint32_t value)
+                                  uint64_t value, unsigned size)
 {
     SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
 
@@ -121,16 +123,10 @@ static void syborg_keyboard_write(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static CPUReadMemoryFunc * const syborg_keyboard_readfn[] = {
-     syborg_keyboard_read,
-     syborg_keyboard_read,
-     syborg_keyboard_read
-};
-
-static CPUWriteMemoryFunc * const syborg_keyboard_writefn[] = {
-     syborg_keyboard_write,
-     syborg_keyboard_write,
-     syborg_keyboard_write
+static const MemoryRegionOps syborg_keyboard_ops = {
+    .read = syborg_keyboard_read,
+    .write = syborg_keyboard_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void syborg_keyboard_event(void *opaque, int keycode)
@@ -184,13 +180,11 @@ static const VMStateDescription vmstate_syborg_keyboard = {
 static int syborg_keyboard_init(SysBusDevice *dev)
 {
     SyborgKeyboardState *s = FROM_SYSBUS(SyborgKeyboardState, dev);
-    int iomemtype;
 
     sysbus_init_irq(dev, &s->irq);
-    iomemtype = cpu_register_io_memory(syborg_keyboard_readfn,
-                                       syborg_keyboard_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &syborg_keyboard_ops, s,
+                              "keyboard", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
     if (s->fifo_size <= 0) {
         fprintf(stderr, "syborg_keyboard: fifo too small\n");
         s->fifo_size = 16;
diff --git a/hw/syborg_pointer.c b/hw/syborg_pointer.c
index b91214daea..bb75fa42c8 100644
--- a/hw/syborg_pointer.c
+++ b/hw/syborg_pointer.c
@@ -44,6 +44,7 @@ typedef struct {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     int int_enabled;
     uint32_t fifo_size;
     event_data *event_fifo;
@@ -57,7 +58,8 @@ static void syborg_pointer_update(SyborgPointerState *s)
     qemu_set_irq(s->irq, s->read_count && s->int_enabled);
 }
 
-static uint32_t syborg_pointer_read(void *opaque, target_phys_addr_t offset)
+static uint64_t syborg_pointer_read(void *opaque, target_phys_addr_t offset,
+                                    unsigned size)
 {
     SyborgPointerState *s = (SyborgPointerState *)opaque;
 
@@ -87,7 +89,7 @@ static uint32_t syborg_pointer_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void syborg_pointer_write(void *opaque, target_phys_addr_t offset,
-                                 uint32_t value)
+                                 uint64_t value, unsigned size)
 {
     SyborgPointerState *s = (SyborgPointerState *)opaque;
 
@@ -110,16 +112,10 @@ static void syborg_pointer_write(void *opaque, target_phys_addr_t offset,
     syborg_pointer_update(s);
 }
 
-static CPUReadMemoryFunc * const syborg_pointer_readfn[] = {
-   syborg_pointer_read,
-   syborg_pointer_read,
-   syborg_pointer_read
-};
-
-static CPUWriteMemoryFunc * const syborg_pointer_writefn[] = {
-   syborg_pointer_write,
-   syborg_pointer_write,
-   syborg_pointer_write
+static const MemoryRegionOps syborg_pointer_ops = {
+    .read = syborg_pointer_read,
+    .write = syborg_pointer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void syborg_pointer_event(void *opaque, int dx, int dy, int dz,
@@ -186,13 +182,11 @@ static const VMStateDescription vmstate_syborg_pointer = {
 static int syborg_pointer_init(SysBusDevice *dev)
 {
     SyborgPointerState *s = FROM_SYSBUS(SyborgPointerState, dev);
-    int iomemtype;
 
     sysbus_init_irq(dev, &s->irq);
-    iomemtype = cpu_register_io_memory(syborg_pointer_readfn,
-				       syborg_pointer_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &syborg_pointer_ops, s,
+                          "pointer", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
 
     if (s->fifo_size <= 0) {
         fprintf(stderr, "syborg_pointer: fifo too small\n");
diff --git a/hw/syborg_rtc.c b/hw/syborg_rtc.c
index 69f6ccf29c..b5f34798b6 100644
--- a/hw/syborg_rtc.c
+++ b/hw/syborg_rtc.c
@@ -35,12 +35,14 @@ enum {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     int64_t offset;
     int64_t data;
     qemu_irq irq;
 } SyborgRTCState;
 
-static uint32_t syborg_rtc_read(void *opaque, target_phys_addr_t offset)
+static uint64_t syborg_rtc_read(void *opaque, target_phys_addr_t offset,
+                                unsigned size)
 {
     SyborgRTCState *s = (SyborgRTCState *)opaque;
     offset &= 0xfff;
@@ -58,7 +60,8 @@ static uint32_t syborg_rtc_read(void *opaque, target_phys_addr_t offset)
     }
 }
 
-static void syborg_rtc_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+static void syborg_rtc_write(void *opaque, target_phys_addr_t offset,
+                             uint64_t value, unsigned size)
 {
     SyborgRTCState *s = (SyborgRTCState *)opaque;
     uint64_t now;
@@ -90,16 +93,10 @@ static void syborg_rtc_write(void *opaque, target_phys_addr_t offset, uint32_t v
     }
 }
 
-static CPUReadMemoryFunc * const syborg_rtc_readfn[] = {
-    syborg_rtc_read,
-    syborg_rtc_read,
-    syborg_rtc_read
-};
-
-static CPUWriteMemoryFunc * const syborg_rtc_writefn[] = {
-    syborg_rtc_write,
-    syborg_rtc_write,
-    syborg_rtc_write
+static const MemoryRegionOps syborg_rtc_ops = {
+    .read = syborg_rtc_read,
+    .write = syborg_rtc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_syborg_rtc = {
@@ -118,12 +115,9 @@ static int syborg_rtc_init(SysBusDevice *dev)
 {
     SyborgRTCState *s = FROM_SYSBUS(SyborgRTCState, dev);
     struct tm tm;
-    int iomemtype;
 
-    iomemtype = cpu_register_io_memory(syborg_rtc_readfn,
-                                       syborg_rtc_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &syborg_rtc_ops, s, "rtc", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
 
     qemu_get_timedate(&tm, 0);
     s->offset = (uint64_t)mktime(&tm) * 1000000000;
diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
index c83f82c36e..6f339fa7a6 100644
--- a/hw/syborg_serial.c
+++ b/hw/syborg_serial.c
@@ -58,6 +58,7 @@ enum {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t int_enable;
     uint32_t fifo_size;
     uint32_t *read_fifo;
@@ -152,7 +153,8 @@ static void dma_rx_start(SyborgSerialState *s, uint32_t len)
     syborg_serial_update(s);
 }
 
-static uint32_t syborg_serial_read(void *opaque, target_phys_addr_t offset)
+static uint64_t syborg_serial_read(void *opaque, target_phys_addr_t offset,
+                                   unsigned size)
 {
     SyborgSerialState *s = (SyborgSerialState *)opaque;
     uint32_t c;
@@ -192,7 +194,7 @@ static uint32_t syborg_serial_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void syborg_serial_write(void *opaque, target_phys_addr_t offset,
-                                uint32_t value)
+                                uint64_t value, unsigned size)
 {
     SyborgSerialState *s = (SyborgSerialState *)opaque;
     unsigned char ch;
@@ -261,16 +263,10 @@ static void syborg_serial_event(void *opaque, int event)
     /* TODO: Report BREAK events?  */
 }
 
-static CPUReadMemoryFunc * const syborg_serial_readfn[] = {
-     syborg_serial_read,
-     syborg_serial_read,
-     syborg_serial_read
-};
-
-static CPUWriteMemoryFunc * const syborg_serial_writefn[] = {
-     syborg_serial_write,
-     syborg_serial_write,
-     syborg_serial_write
+static const MemoryRegionOps syborg_serial_ops = {
+    .read = syborg_serial_read,
+    .write = syborg_serial_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_syborg_serial = {
@@ -295,13 +291,11 @@ static const VMStateDescription vmstate_syborg_serial = {
 static int syborg_serial_init(SysBusDevice *dev)
 {
     SyborgSerialState *s = FROM_SYSBUS(SyborgSerialState, dev);
-    int iomemtype;
 
     sysbus_init_irq(dev, &s->irq);
-    iomemtype = cpu_register_io_memory(syborg_serial_readfn,
-                                       syborg_serial_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &syborg_serial_ops, s,
+                          "serial", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
     s->chr = qdev_init_chardev(&dev->qdev);
     if (s->chr) {
         qemu_chr_add_handlers(s->chr, syborg_serial_can_receive,
diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c
index 50c813e969..1498f01a62 100644
--- a/hw/syborg_timer.c
+++ b/hw/syborg_timer.c
@@ -53,6 +53,7 @@ enum {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     ptimer_state *timer;
     int running;
     int oneshot;
@@ -83,7 +84,8 @@ static void syborg_timer_tick(void *opaque)
     syborg_timer_update(s);
 }
 
-static uint32_t syborg_timer_read(void *opaque, target_phys_addr_t offset)
+static uint64_t syborg_timer_read(void *opaque, target_phys_addr_t offset,
+                                  unsigned size)
 {
     SyborgTimerState *s = (SyborgTimerState *)opaque;
 
@@ -114,7 +116,7 @@ static uint32_t syborg_timer_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void syborg_timer_write(void *opaque, target_phys_addr_t offset,
-                               uint32_t value)
+                               uint64_t value, unsigned size)
 {
     SyborgTimerState *s = (SyborgTimerState *)opaque;
 
@@ -162,16 +164,10 @@ static void syborg_timer_write(void *opaque, target_phys_addr_t offset,
     }
 }
 
-static CPUReadMemoryFunc * const syborg_timer_readfn[] = {
-    syborg_timer_read,
-    syborg_timer_read,
-    syborg_timer_read
-};
-
-static CPUWriteMemoryFunc * const syborg_timer_writefn[] = {
-    syborg_timer_write,
-    syborg_timer_write,
-    syborg_timer_write
+static const MemoryRegionOps syborg_timer_ops = {
+    .read = syborg_timer_read,
+    .write = syborg_timer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_syborg_timer = {
@@ -194,17 +190,14 @@ static int syborg_timer_init(SysBusDevice *dev)
 {
     SyborgTimerState *s = FROM_SYSBUS(SyborgTimerState, dev);
     QEMUBH *bh;
-    int iomemtype;
 
     if (s->freq == 0) {
         fprintf(stderr, "syborg_timer: Zero/unset frequency\n");
         exit(1);
     }
     sysbus_init_irq(dev, &s->irq);
-    iomemtype = cpu_register_io_memory(syborg_timer_readfn,
-                                       syborg_timer_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &syborg_timer_ops, s, "timer", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
 
     bh = qemu_bh_new(syborg_timer_tick, s);
     s->timer = ptimer_init(bh);
diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
index 6de952c938..96a0ee651f 100644
--- a/hw/syborg_virtio.c
+++ b/hw/syborg_virtio.c
@@ -62,6 +62,7 @@ enum {
 typedef struct {
     SysBusDevice busdev;
     VirtIODevice *vdev;
+    MemoryRegion iomem;
     qemu_irq irq;
     uint32_t int_enable;
     uint32_t id;
@@ -221,16 +222,12 @@ static void syborg_virtio_writeb(void *opaque, target_phys_addr_t offset,
     BADF("Bad byte write offset 0x%x\n", (int)offset);
 }
 
-static CPUReadMemoryFunc * const syborg_virtio_readfn[] = {
-     syborg_virtio_readb,
-     syborg_virtio_readw,
-     syborg_virtio_readl
-};
-
-static CPUWriteMemoryFunc * const syborg_virtio_writefn[] = {
-     syborg_virtio_writeb,
-     syborg_virtio_writew,
-     syborg_virtio_writel
+static const MemoryRegionOps syborg_virtio_ops = {
+    .old_mmio = {
+        .read = { syborg_virtio_readb, syborg_virtio_readw, syborg_virtio_readl },
+        .write = { syborg_virtio_writeb, syborg_virtio_writew, syborg_virtio_writel },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void syborg_virtio_update_irq(void *opaque, uint16_t vector)
@@ -256,17 +253,14 @@ static VirtIOBindings syborg_virtio_bindings = {
 
 static int syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)
 {
-    int iomemtype;
-
     proxy->vdev = vdev;
 
     /* Don't support multiple vectors */
     proxy->vdev->nvectors = 0;
     sysbus_init_irq(&proxy->busdev, &proxy->irq);
-    iomemtype = cpu_register_io_memory(syborg_virtio_readfn,
-                                       syborg_virtio_writefn, proxy,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(&proxy->busdev, 0x1000, iomemtype);
+    memory_region_init_io(&proxy->iomem, &syborg_virtio_ops, proxy,
+                          "virtio", 0x1000);
+    sysbus_init_mmio(&proxy->busdev, &proxy->iomem);
 
     proxy->id = ((uint32_t)0x1af4 << 16) | vdev->device_id;
 
diff --git a/hw/sysbus.c b/hw/sysbus.c
index fd2fc6a51d..b315a8cf5d 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -55,9 +55,6 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)
                                         dev->mmio[n].memory);
         } else if (dev->mmio[n].unmap) {
             dev->mmio[n].unmap(dev, dev->mmio[n].addr);
-        } else {
-            cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size,
-                                         IO_MEM_UNASSIGNED);
         }
     }
     dev->mmio[n].addr = addr;
@@ -67,9 +64,6 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)
                                     dev->mmio[n].memory);
     } else if (dev->mmio[n].cb) {
         dev->mmio[n].cb(dev, addr);
-    } else {
-        cpu_register_physical_memory(addr, dev->mmio[n].size,
-                                     dev->mmio[n].iofunc);
     }
 }
 
@@ -95,18 +89,6 @@ void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target)
     }
 }
 
-void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size,
-                      ram_addr_t iofunc)
-{
-    int n;
-
-    assert(dev->num_mmio < QDEV_MAX_MMIO);
-    n = dev->num_mmio++;
-    dev->mmio[n].addr = -1;
-    dev->mmio[n].size = size;
-    dev->mmio[n].iofunc = iofunc;
-}
-
 void sysbus_init_mmio_cb2(SysBusDevice *dev,
                           mmio_mapfunc cb, mmio_mapfunc unmap)
 {
@@ -115,19 +97,17 @@ void sysbus_init_mmio_cb2(SysBusDevice *dev,
     assert(dev->num_mmio < QDEV_MAX_MMIO);
     n = dev->num_mmio++;
     dev->mmio[n].addr = -1;
-    dev->mmio[n].size = 0;
     dev->mmio[n].cb = cb;
     dev->mmio[n].unmap = unmap;
 }
 
-void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory)
+void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory)
 {
     int n;
 
     assert(dev->num_mmio < QDEV_MAX_MMIO);
     n = dev->num_mmio++;
     dev->mmio[n].addr = -1;
-    dev->mmio[n].size = memory_region_size(memory);
     dev->mmio[n].memory = memory;
 }
 
@@ -237,12 +217,17 @@ DeviceState *sysbus_try_create_varargs(const char *name,
 static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
 {
     SysBusDevice *s = sysbus_from_qdev(dev);
+    target_phys_addr_t size;
     int i;
 
     monitor_printf(mon, "%*sirq %d\n", indent, "", s->num_irq);
     for (i = 0; i < s->num_mmio; i++) {
+        size = 0;
+        if (s->mmio[i].memory) {
+            size = memory_region_size(s->mmio[i].memory);
+        }
         monitor_printf(mon, "%*smmio " TARGET_FMT_plx "/" TARGET_FMT_plx "\n",
-                       indent, "", s->mmio[i].addr, s->mmio[i].size);
+                       indent, "", s->mmio[i].addr, size);
     }
 }
 
diff --git a/hw/sysbus.h b/hw/sysbus.h
index 6c36537c24..9bac582ea4 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -21,10 +21,8 @@ struct SysBusDevice {
     int num_mmio;
     struct {
         target_phys_addr_t addr;
-        target_phys_addr_t size;
         mmio_mapfunc cb;
         mmio_mapfunc unmap;
-        ram_addr_t iofunc;
         MemoryRegion *memory;
     } mmio[QDEV_MAX_MMIO];
     int num_pio;
@@ -45,11 +43,9 @@ typedef struct {
 void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init);
 void sysbus_register_withprop(SysBusDeviceInfo *info);
 void *sysbus_new(void);
-void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size,
-                      ram_addr_t iofunc);
 void sysbus_init_mmio_cb2(SysBusDevice *dev,
                           mmio_mapfunc cb, mmio_mapfunc unmap);
-void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory);
+void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory);
 MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n);
 void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p);
 void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target);
diff --git a/hw/tcx.c b/hw/tcx.c
index cd24100e14..a9873571d3 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -529,21 +529,21 @@ static int tcx_init1(SysBusDevice *dev)
     size = s->vram_size;
     memory_region_init_alias(&s->vram_8bit, "tcx.vram.8bit",
                              &s->vram_mem, vram_offset, size);
-    sysbus_init_mmio_region(dev, &s->vram_8bit);
+    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);
-    sysbus_init_mmio_region(dev, &s->dac);
+    sysbus_init_mmio(dev, &s->dac);
 
     /* TEC (dummy) */
     memory_region_init_io(&s->tec, &dummy_ops, s, "tcx.tec", TCX_TEC_NREGS);
-    sysbus_init_mmio_region(dev, &s->tec);
+    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",
                           TCX_THC_NREGS_24);
-    sysbus_init_mmio_region(dev, &s->thc24);
+    sysbus_init_mmio(dev, &s->thc24);
 
     if (s->depth == 24) {
         /* 24-bit plane */
@@ -552,7 +552,7 @@ static int tcx_init1(SysBusDevice *dev)
         s->vram24_offset = vram_offset;
         memory_region_init_alias(&s->vram_24bit, "tcx.vram.24bit",
                                  &s->vram_mem, vram_offset, size);
-        sysbus_init_mmio_region(dev, &s->vram_24bit);
+        sysbus_init_mmio(dev, &s->vram_24bit);
         vram_offset += size;
         vram_base += size;
 
@@ -562,7 +562,7 @@ static int tcx_init1(SysBusDevice *dev)
         s->cplane_offset = vram_offset;
         memory_region_init_alias(&s->vram_cplane, "tcx.vram.cplane",
                                  &s->vram_mem, vram_offset, size);
-        sysbus_init_mmio_region(dev, &s->vram_cplane);
+        sysbus_init_mmio(dev, &s->vram_cplane);
 
         s->ds = graphic_console_init(tcx24_update_display,
                                      tcx24_invalidate_display,
@@ -571,7 +571,7 @@ static int tcx_init1(SysBusDevice *dev)
         /* THC 8 bit (dummy) */
         memory_region_init_io(&s->thc8, &dummy_ops, s, "tcx.thc8",
                               TCX_THC_NREGS_8);
-        sysbus_init_mmio_region(dev, &s->thc8);
+        sysbus_init_mmio(dev, &s->thc8);
 
         s->ds = graphic_console_init(tcx_update_display,
                                      tcx_invalidate_display,
diff --git a/hw/tosa.c b/hw/tosa.c
index b992b994c7..67a71fee6c 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -208,6 +208,7 @@ static void tosa_init(ram_addr_t ram_size,
                 const char *initrd_filename, const char *cpu_model)
 {
     MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *rom = g_new(MemoryRegion, 1);
     PXA2xxState *cpu;
     TC6393xbState *tmio;
     DeviceState *scp0, *scp1;
@@ -217,8 +218,9 @@ static void tosa_init(ram_addr_t ram_size,
 
     cpu = pxa255_init(address_space_mem, tosa_binfo.ram_size);
 
-    cpu_register_physical_memory(0, TOSA_ROM,
-                    qemu_ram_alloc(NULL, "tosa.rom", TOSA_ROM) | IO_MEM_ROM);
+    memory_region_init_ram(rom, NULL, "tosa.rom", TOSA_ROM);
+    memory_region_set_readonly(rom, true);
+    memory_region_add_subregion(address_space_mem, 0, rom);
 
     tmio = tc6393xb_init(address_space_mem, 0x10000000,
             qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_TC6393XB_INT));
diff --git a/hw/tusb6010.c b/hw/tusb6010.c
index ce7c81f8f2..276300a302 100644
--- a/hw/tusb6010.c
+++ b/hw/tusb6010.c
@@ -781,8 +781,8 @@ static int tusb6010_init(SysBusDevice *dev)
     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);
-    sysbus_init_mmio_region(dev, &s->iomem[0]);
-    sysbus_init_mmio_region(dev, &s->iomem[1]);
+    sysbus_init_mmio(dev, &s->iomem[0]);
+    sysbus_init_mmio(dev, &s->iomem[1]);
     sysbus_init_irq(dev, &s->irq);
     qdev_init_gpio_in(&dev->qdev, tusb6010_irq, musb_irq_max + 1);
     s->musb = musb_init(&dev->qdev, 1);
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index 4299052c5e..14d99147f3 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -144,8 +144,8 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
                           &s->host_state, "pci-conf-idx", 0x1000);
     memory_region_init_io(&s->host_state.data_mem, &unin_data_ops, s,
                           "pci-conf-data", 0x1000);
-    sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio_region(dev, &s->host_state.data_mem);
+    sysbus_init_mmio(dev, &s->host_state.conf_mem);
+    sysbus_init_mmio(dev, &s->host_state.data_mem);
 
     qemu_register_reset(pci_unin_reset, &s->host_state);
     return 0;
@@ -163,8 +163,8 @@ static int pci_u3_agp_init_device(SysBusDevice *dev)
                           &s->host_state, "pci-conf-idx", 0x1000);
     memory_region_init_io(&s->host_state.data_mem, &unin_data_ops, s,
                           "pci-conf-data", 0x1000);
-    sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio_region(dev, &s->host_state.data_mem);
+    sysbus_init_mmio(dev, &s->host_state.conf_mem);
+    sysbus_init_mmio(dev, &s->host_state.data_mem);
 
     qemu_register_reset(pci_unin_reset, &s->host_state);
 
@@ -182,8 +182,8 @@ static int pci_unin_agp_init_device(SysBusDevice *dev)
                           &s->host_state, "pci-conf-idx", 0x1000);
     memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
                           &s->host_state, "pci-conf-data", 0x1000);
-    sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio_region(dev, &s->host_state.data_mem);
+    sysbus_init_mmio(dev, &s->host_state.conf_mem);
+    sysbus_init_mmio(dev, &s->host_state.data_mem);
     return 0;
 }
 
@@ -198,8 +198,8 @@ static int pci_unin_internal_init_device(SysBusDevice *dev)
                           &s->host_state, "pci-conf-idx", 0x1000);
     memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
                           &s->host_state, "pci-conf-data", 0x1000);
-    sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio_region(dev, &s->host_state.data_mem);
+    sysbus_init_mmio(dev, &s->host_state.conf_mem);
+    sysbus_init_mmio(dev, &s->host_state.data_mem);
     return 0;
 }
 
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index c2981c59a4..e68be70b15 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1829,7 +1829,7 @@ static int ohci_init_pxa(SysBusDevice *dev)
     /* Cannot fail as we pass NULL for masterbus */
     usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0);
     sysbus_init_irq(dev, &s->ohci.irq);
-    sysbus_init_mmio_region(dev, &s->ohci.mem);
+    sysbus_init_mmio(dev, &s->ohci.mem);
 
     return 0;
 }
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index 8a88696f2c..a285f7f383 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -81,13 +81,13 @@ static int pci_vpb_init(SysBusDevice *dev)
      */
     memory_region_init_io(&s->mem_config, &pci_vpb_config_ops, bus,
                           "pci-vpb-selfconfig", 0x1000000);
-    sysbus_init_mmio_region(dev, &s->mem_config);
+    sysbus_init_mmio(dev, &s->mem_config);
     memory_region_init_io(&s->mem_config2, &pci_vpb_config_ops, bus,
                           "pci-vpb-config", 0x1000000);
-    sysbus_init_mmio_region(dev, &s->mem_config2);
+    sysbus_init_mmio(dev, &s->mem_config2);
     if (s->realview) {
         isa_mmio_setup(&s->isa, 0x0100000);
-        sysbus_init_mmio_region(dev, &s->isa);
+        sysbus_init_mmio(dev, &s->isa);
     }
 
     pci_create_simple(bus, -1, "versatile_pci_host");
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 6370600bb3..a6315fce5d 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -17,12 +17,14 @@
 #include "usb-ohci.h"
 #include "boards.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 /* Primary interrupt controller.  */
 
 typedef struct vpb_sic_state
 {
   SysBusDevice busdev;
+  MemoryRegion iomem;
   uint32_t level;
   uint32_t mask;
   uint32_t pic_enable;
@@ -75,7 +77,8 @@ static void vpb_sic_set_irq(void *opaque, int irq, int level)
     vpb_sic_update(s);
 }
 
-static uint32_t vpb_sic_read(void *opaque, target_phys_addr_t offset)
+static uint64_t vpb_sic_read(void *opaque, target_phys_addr_t offset,
+                             unsigned size)
 {
     vpb_sic_state *s = (vpb_sic_state *)opaque;
 
@@ -97,7 +100,7 @@ static uint32_t vpb_sic_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void vpb_sic_write(void *opaque, target_phys_addr_t offset,
-                          uint32_t value)
+                          uint64_t value, unsigned size)
 {
     vpb_sic_state *s = (vpb_sic_state *)opaque;
 
@@ -131,22 +134,15 @@ static void vpb_sic_write(void *opaque, target_phys_addr_t offset,
     vpb_sic_update(s);
 }
 
-static CPUReadMemoryFunc * const vpb_sic_readfn[] = {
-   vpb_sic_read,
-   vpb_sic_read,
-   vpb_sic_read
-};
-
-static CPUWriteMemoryFunc * const vpb_sic_writefn[] = {
-   vpb_sic_write,
-   vpb_sic_write,
-   vpb_sic_write
+static const MemoryRegionOps vpb_sic_ops = {
+    .read = vpb_sic_read,
+    .write = vpb_sic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int vpb_sic_init(SysBusDevice *dev)
 {
     vpb_sic_state *s = FROM_SYSBUS(vpb_sic_state, dev);
-    int iomemtype;
     int i;
 
     qdev_init_gpio_in(&dev->qdev, vpb_sic_set_irq, 32);
@@ -154,10 +150,8 @@ static int vpb_sic_init(SysBusDevice *dev)
         sysbus_init_irq(dev, &s->parent[i]);
     }
     s->irq = 31;
-    iomemtype = cpu_register_io_memory(vpb_sic_readfn,
-                                       vpb_sic_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &vpb_sic_ops, s, "vpb-sic", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
     return 0;
 }
 
@@ -176,7 +170,8 @@ static void versatile_init(ram_addr_t ram_size,
                      int board_id)
 {
     CPUState *env;
-    ram_addr_t ram_offset;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
     qemu_irq *cpu_pic;
     qemu_irq pic[32];
     qemu_irq sic[32];
@@ -195,10 +190,10 @@ static void versatile_init(ram_addr_t ram_size,
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    ram_offset = qemu_ram_alloc(NULL, "versatile.ram", ram_size);
+    memory_region_init_ram(ram, NULL, "versatile.ram", ram_size);
     /* ??? RAM should repeat to fill physical memory space.  */
     /* SDRAM at address zero.  */
-    cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
+    memory_region_add_subregion(sysmem, 0, ram);
 
     sysctl = qdev_create(NULL, "realview_sysctl");
     qdev_prop_set_uint32(sysctl, "sys_id", 0x41007004);
diff --git a/hw/vexpress.c b/hw/vexpress.c
index 0940a26d73..08c93d5544 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -25,6 +25,7 @@
 #include "net.h"
 #include "sysemu.h"
 #include "boards.h"
+#include "exec-memory.h"
 
 #define SMP_BOOT_ADDR 0xe0000000
 
@@ -40,7 +41,12 @@ static void vexpress_a9_init(ram_addr_t ram_size,
                      const char *initrd_filename, const char *cpu_model)
 {
     CPUState *env = NULL;
-    ram_addr_t ram_offset, vram_offset, sram_offset;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *lowram = g_new(MemoryRegion, 1);
+    MemoryRegion *vram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    MemoryRegion *hackram = g_new(MemoryRegion, 1);
     DeviceState *dev, *sysctl, *pl041;
     SysBusDevice *busdev;
     qemu_irq *irqp;
@@ -71,7 +77,7 @@ static void vexpress_a9_init(ram_addr_t ram_size,
         exit(1);
     }
 
-    ram_offset = qemu_ram_alloc(NULL, "vexpress.highmem", ram_size);
+    memory_region_init_ram(ram, NULL, "vexpress.highmem", ram_size);
     low_ram_size = ram_size;
     if (low_ram_size > 0x4000000) {
         low_ram_size = 0x4000000;
@@ -80,9 +86,9 @@ static void vexpress_a9_init(ram_addr_t ram_size,
      * address space should in theory be remappable to various
      * things including ROM or RAM; we always map the RAM there.
      */
-    cpu_register_physical_memory(0x0, low_ram_size, ram_offset | IO_MEM_RAM);
-    cpu_register_physical_memory(0x60000000, ram_size,
-                                 ram_offset | IO_MEM_RAM);
+    memory_region_init_alias(lowram, "vexpress.lowmem", ram, 0, low_ram_size);
+    memory_region_add_subregion(sysmem, 0x0, lowram);
+    memory_region_add_subregion(sysmem, 0x60000000, ram);
 
     /* 0x1e000000 A9MPCore (SCU) private memory region */
     dev = qdev_create(NULL, "a9mpcore_priv");
@@ -175,17 +181,15 @@ static void vexpress_a9_init(ram_addr_t ram_size,
     /* CS4: NOR1 flash          : 0x44000000 .. 0x48000000 */
     /* CS2: SRAM                : 0x48000000 .. 0x4a000000 */
     sram_size = 0x2000000;
-    sram_offset = qemu_ram_alloc(NULL, "vexpress.sram", sram_size);
-    cpu_register_physical_memory(0x48000000, sram_size,
-                                 sram_offset | IO_MEM_RAM);
+    memory_region_init_ram(sram, NULL, "vexpress.sram", sram_size);
+    memory_region_add_subregion(sysmem, 0x48000000, sram);
 
     /* CS3: USB, ethernet, VRAM : 0x4c000000 .. 0x50000000 */
 
     /* 0x4c000000 Video RAM */
     vram_size = 0x800000;
-    vram_offset = qemu_ram_alloc(NULL, "vexpress.vram", vram_size);
-    cpu_register_physical_memory(0x4c000000, vram_size,
-                                 vram_offset | IO_MEM_RAM);
+    memory_region_init_ram(vram, NULL, "vexpress.vram", vram_size);
+    memory_region_add_subregion(sysmem, 0x4c000000, vram);
 
     /* 0x4e000000 LAN9118 Ethernet */
     if (nd_table[0].vlan) {
@@ -198,9 +202,8 @@ static void vexpress_a9_init(ram_addr_t ram_size,
        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.  */
-    ram_offset = qemu_ram_alloc(NULL, "vexpress.hack", 0x1000);
-    cpu_register_physical_memory(SMP_BOOT_ADDR, 0x1000,
-                                 ram_offset | IO_MEM_RAM);
+    memory_region_init_ram(hackram, NULL, "vexpress.hack", 0x1000);
+    memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, hackram);
 
     vexpress_binfo.ram_size = ram_size;
     vexpress_binfo.kernel_filename = kernel_filename;
diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
index 5ea0e60e41..6ffb896b7b 100644
--- a/hw/virtex_ml507.c
+++ b/hw/virtex_ml507.c
@@ -192,7 +192,7 @@ static void virtex_init(ram_addr_t ram_size,
     CPUState *env;
     target_phys_addr_t ram_base = 0;
     DriveInfo *dinfo;
-    ram_addr_t phys_ram;
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
     qemu_irq irq[32], *cpu_irq;
     int kernel_size;
     int i;
@@ -205,8 +205,8 @@ static void virtex_init(ram_addr_t ram_size,
     env = ppc440_init_xilinx(&ram_size, 1, cpu_model, 400000000);
     qemu_register_reset(main_cpu_reset, env);
 
-    phys_ram = qemu_ram_alloc(NULL, "ram", ram_size);
-    cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM);
+    memory_region_init_ram(phys_ram, NULL, "ram", ram_size);
+    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi01_register(0xfc000000, NULL, "virtex.flash", FLASH_SIZE,
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index 571a5b0661..596ec0ed68 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -91,6 +91,7 @@ struct AXIStream {
 
 struct XilinxAXIDMA {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t freqhz;
     void *dmach;
 
@@ -362,7 +363,8 @@ void axidma_push(void *opaque, unsigned char *buf, size_t len, uint32_t *app)
     stream_update_irq(s);
 }
 
-static uint32_t axidma_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t axidma_read(void *opaque, target_phys_addr_t addr,
+                            unsigned size)
 {
     struct XilinxAXIDMA *d = opaque;
     struct AXIStream *s;
@@ -396,8 +398,8 @@ static uint32_t axidma_readl(void *opaque, target_phys_addr_t addr)
 
 }
 
-static void
-axidma_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void axidma_write(void *opaque, target_phys_addr_t addr,
+                         uint64_t value, unsigned size)
 {
     struct XilinxAXIDMA *d = opaque;
     struct AXIStream *s;
@@ -449,22 +451,15 @@ axidma_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
     stream_update_irq(s);
 }
 
-static CPUReadMemoryFunc * const axidma_read[] = {
-    &axidma_readl,
-    &axidma_readl,
-    &axidma_readl,
-};
-
-static CPUWriteMemoryFunc * const axidma_write[] = {
-    &axidma_writel,
-    &axidma_writel,
-    &axidma_writel,
+static const MemoryRegionOps axidma_ops = {
+    .read = axidma_read,
+    .write = axidma_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int xilinx_axidma_init(SysBusDevice *dev)
 {
     struct XilinxAXIDMA *s = FROM_SYSBUS(typeof(*s), dev);
-    int axidma_regs;
     int i;
 
     sysbus_init_irq(dev, &s->streams[1].irq);
@@ -476,9 +471,9 @@ static int xilinx_axidma_init(SysBusDevice *dev)
 
     xlx_dma_connect_dma(s->dmach, s, axidma_push);
 
-    axidma_regs = cpu_register_io_memory(axidma_read, axidma_write, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4 * 2, axidma_regs);
+    memory_region_init_io(&s->iomem, &axidma_ops, s,
+                          "axidma", R_MAX * 4 * 2);
+    sysbus_init_mmio(dev, &s->iomem);
 
     for (i = 0; i < 2; i++) {
         stream_reset(&s->streams[i]);
diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index b875aad019..a2eb3e6d5b 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -308,6 +308,7 @@ struct TEMAC  {
 
 struct XilinxAXIEnet {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     qemu_irq irq;
     void *dmach;
     NICState *nic;
@@ -411,7 +412,7 @@ static void enet_update_irq(struct XilinxAXIEnet *s)
     qemu_set_irq(s->irq, !!s->regs[R_IP]);
 }
 
-static uint32_t enet_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t enet_read(void *opaque, target_phys_addr_t addr, unsigned size)
 {
     struct XilinxAXIEnet *s = opaque;
     uint32_t r = 0;
@@ -502,8 +503,8 @@ static uint32_t enet_readl(void *opaque, target_phys_addr_t addr)
     return r;
 }
 
-static void
-enet_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void enet_write(void *opaque, target_phys_addr_t addr,
+                       uint64_t value, unsigned size)
 {
     struct XilinxAXIEnet *s = opaque;
     struct TEMAC *t = &s->TEMAC;
@@ -596,7 +597,7 @@ enet_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
 
         default:
             DENET(qemu_log("%s addr=" TARGET_FMT_plx " v=%x\n",
-                           __func__, addr * 4, value));
+                           __func__, addr * 4, (unsigned)value));
             if (addr < ARRAY_SIZE(s->regs)) {
                 s->regs[addr] = value;
             }
@@ -605,16 +606,10 @@ enet_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
     enet_update_irq(s);
 }
 
-static CPUReadMemoryFunc * const enet_read[] = {
-    &enet_readl,
-    &enet_readl,
-    &enet_readl,
-};
-
-static CPUWriteMemoryFunc * const enet_write[] = {
-    &enet_writel,
-    &enet_writel,
-    &enet_writel,
+static const MemoryRegionOps enet_ops = {
+    .read = enet_read,
+    .write = enet_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static int eth_can_rx(VLANClientState *nc)
@@ -847,7 +842,6 @@ static NetClientInfo net_xilinx_enet_info = {
 static int xilinx_enet_init(SysBusDevice *dev)
 {
     struct XilinxAXIEnet *s = FROM_SYSBUS(typeof(*s), dev);
-    int enet_regs;
 
     sysbus_init_irq(dev, &s->irq);
 
@@ -857,9 +851,8 @@ static int xilinx_enet_init(SysBusDevice *dev)
 
     xlx_dma_connect_client(s->dmach, s, axienet_stream_push);
 
-    enet_regs = cpu_register_io_memory(enet_read, enet_write, s,
-                                       DEVICE_LITTLE_ENDIAN);
-    sysbus_init_mmio(dev, 0x40000, enet_regs);
+    memory_region_init_io(&s->iomem, &enet_ops, s, "enet", 0x40000);
+    sysbus_init_mmio(dev, &s->iomem);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     s->nic = qemu_new_nic(&net_xilinx_enet_info, &s->conf,
diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c
index 6f44c8466e..6777254f35 100644
--- a/hw/xilinx_ethlite.c
+++ b/hw/xilinx_ethlite.c
@@ -217,7 +217,7 @@ static int xilinx_ethlite_init(SysBusDevice *dev)
     s->rxbuf = 0;
 
     memory_region_init_io(&s->mmio, &eth_ops, s, "xilinx-ethlite", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf,
diff --git a/hw/xilinx_intc.c b/hw/xilinx_intc.c
index 58b73d95cc..c567885bcf 100644
--- a/hw/xilinx_intc.c
+++ b/hw/xilinx_intc.c
@@ -157,7 +157,7 @@ static int xilinx_intc_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &p->parent_irq);
 
     memory_region_init_io(&p->mmio, &pic_ops, p, "xilinx-pic", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &p->mmio);
+    sysbus_init_mmio(dev, &p->mmio);
     return 0;
 }
 
diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c
index 8779c56f0b..0b2f32a3af 100644
--- a/hw/xilinx_timer.c
+++ b/hw/xilinx_timer.c
@@ -214,7 +214,7 @@ static int xilinx_timer_init(SysBusDevice *dev)
 
     memory_region_init_io(&t->mmio, &timer_ops, t, "xilinx-timer",
                           R_MAX * 4 * t->nr_timers);
-    sysbus_init_mmio_region(dev, &t->mmio);
+    sysbus_init_mmio(dev, &t->mmio);
     return 0;
 }
 
diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
index ceb7b4d9ed..6533df934f 100644
--- a/hw/xilinx_uartlite.c
+++ b/hw/xilinx_uartlite.c
@@ -203,7 +203,7 @@ static int xilinx_uartlite_init(SysBusDevice *dev)
 
     uart_update_status(s);
     memory_region_init_io(&s->mmio, &uart_ops, s, "xilinx-uartlite", R_MAX * 4);
-    sysbus_init_mmio_region(dev, &s->mmio);
+    sysbus_init_mmio(dev, &s->mmio);
 
     s->chr = qdev_init_chardev(&dev->qdev);
     if (s->chr)
diff --git a/hw/zaurus.c b/hw/zaurus.c
index 0eeacf7cb3..c4bcd29825 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -28,6 +28,7 @@ typedef struct ScoopInfo ScoopInfo;
 struct ScoopInfo {
     SysBusDevice busdev;
     qemu_irq handler[16];
+    MemoryRegion iomem;
     uint16_t status;
     uint16_t power;
     uint32_t gpio_level;
@@ -67,7 +68,8 @@ static inline void scoop_gpio_handler_update(ScoopInfo *s) {
     s->prev_level = level;
 }
 
-static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t scoop_read(void *opaque, target_phys_addr_t addr,
+                           unsigned size)
 {
     ScoopInfo *s = (ScoopInfo *) opaque;
 
@@ -100,7 +102,8 @@ static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
-static void scoop_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void scoop_write(void *opaque, target_phys_addr_t addr,
+                        uint64_t value, unsigned size)
 {
     ScoopInfo *s = (ScoopInfo *) opaque;
     value &= 0xffff;
@@ -143,15 +146,10 @@ static void scoop_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
     }
 }
 
-static CPUReadMemoryFunc * const scoop_readfn[] = {
-    scoop_readb,
-    scoop_readb,
-    scoop_readb,
-};
-static CPUWriteMemoryFunc * const scoop_writefn[] = {
-    scoop_writeb,
-    scoop_writeb,
-    scoop_writeb,
+static const MemoryRegionOps scoop_ops = {
+    .read = scoop_read,
+    .write = scoop_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void scoop_gpio_set(void *opaque, int line, int level)
@@ -167,15 +165,13 @@ static void scoop_gpio_set(void *opaque, int line, int level)
 static int scoop_init(SysBusDevice *dev)
 {
     ScoopInfo *s = FROM_SYSBUS(ScoopInfo, dev);
-    int iomemtype;
 
     s->status = 0x02;
     qdev_init_gpio_out(&s->busdev.qdev, s->handler, 16);
     qdev_init_gpio_in(&s->busdev.qdev, scoop_gpio_set, 16);
-    iomemtype = cpu_register_io_memory(scoop_readfn,
-                    scoop_writefn, s, DEVICE_NATIVE_ENDIAN);
+    memory_region_init_io(&s->iomem, &scoop_ops, s, "scoop", 0x1000);
 
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    sysbus_init_mmio(dev, &s->iomem);
 
     return 0;
 }
diff --git a/memory.c b/memory.c
index 7c20a0703f..adfdf1470c 100644
--- a/memory.c
+++ b/memory.c
@@ -831,8 +831,14 @@ void memory_region_init(MemoryRegion *mr,
 
 static bool memory_region_access_valid(MemoryRegion *mr,
                                        target_phys_addr_t addr,
-                                       unsigned size)
+                                       unsigned size,
+                                       bool is_write)
 {
+    if (mr->ops->valid.accepts
+        && !mr->ops->valid.accepts(mr->opaque, addr, size, is_write)) {
+        return false;
+    }
+
     if (!mr->ops->valid.unaligned && (addr & (size - 1))) {
         return false;
     }
@@ -856,7 +862,7 @@ static uint32_t memory_region_read_thunk_n(void *_mr,
     MemoryRegion *mr = _mr;
     uint64_t data = 0;
 
-    if (!memory_region_access_valid(mr, addr, size)) {
+    if (!memory_region_access_valid(mr, addr, size, false)) {
         return -1U; /* FIXME: better signalling */
     }
 
@@ -880,7 +886,7 @@ static void memory_region_write_thunk_n(void *_mr,
 {
     MemoryRegion *mr = _mr;
 
-    if (!memory_region_access_valid(mr, addr, size)) {
+    if (!memory_region_access_valid(mr, addr, size, true)) {
         return; /* FIXME: better signalling */
     }
 
diff --git a/memory.h b/memory.h
index 7fb36d16ec..53bf261792 100644
--- a/memory.h
+++ b/memory.h
@@ -71,6 +71,13 @@ struct MemoryRegionOps {
          * accesses throw machine checks.
          */
          bool unaligned;
+        /*
+         * If present, and returns #false, the transaction is not accepted
+         * by the device (and results in machine dependent behaviour such
+         * as a machine check exception).
+         */
+        bool (*accepts)(void *opaque, target_phys_addr_t addr,
+                        unsigned size, bool is_write);
     } valid;
     /* Internal implementation constraints: */
     struct {
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index 5a1e15e63d..f4dda48dd1 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -24,7 +24,10 @@
 #include <signal.h>
 
 #include "cpu.h"
+
+#if !defined(CONFIG_USER_ONLY)
 #include "hw/sh_intc.h"
+#endif
 
 #if defined(CONFIG_USER_ONLY)